summaryrefslogtreecommitdiff
path: root/src/kernel/klog.c
blob: 52444b19de9827836b153b45ac464314a8e25cf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <stdint.h>
#include <serial.h>
#include <io.h>
#include <printf.h>
#include <kernel.h>
#include <stdbool.h>
#include <libc.h>

//README 
//this file has some temporary workarounds until I get further into development
//this isn't going to be the serial driver I end up keeping

#define VIDEO_BUFFER PHYS_TO_VIRT(0xb8000)
#define MAX_LOOPBACK_ATTEMPTS 20

//later we'll set it up for interrupting instead of polling
bool init_serial(uint16_t port) {
  outb_wait(port + 1, 0x00); 
  outb_wait(port + 2, 0x00); 
  outb_wait(port + 3, 0x80); 
  outb_wait(port + 0, 0x01); //here
  outb_wait(port + 1, 0x00);
  outb_wait(port + 3, 0x03); 
  outb_wait(port + 2, 0xc7); 
  outb_wait(port + 4, 0x0b); 
  outb_wait(port + 4, 0x1e); 


  //we shouldn't accept this as a loopback success.
  //I'm making an exception because my dell desktop has a faulty serial port
  //that requires some extra effort.

  uint8_t loopback_byte;
  for(int attempts = 0; attempts < MAX_LOOPBACK_ATTEMPTS; attempts++) {
    outb_wait(port + 0, 0xae); // test char
    loopback_byte = inb(port);
    if(loopback_byte == 0xae) break;
  }

  if(loopback_byte != 0xae) {
    //I'm sorry if these next few lines give you a stroke. They gave me one.
    
    //My old Dell test desktop has disfunctional serial hardware that only works after a reboot.
    //Seeing we don't have ACPI set up yet, we can't reboot without crashing.
    //IM GOING TO REMOVE THIS ONCE I DEVELOP THE "REAL" SERIAL DRIVER!!!! 
    asm("mov rax, 0\n"
        "div rax\n");
    return false;
  }
  
  outb_wait(port + 4, 0x0f); 
  return true;
}

void _putchar_serial(uint16_t port, char msg) {
  while(!(inb(port + 5) & 0x20)); //wait for transmit to be done
  outb_wait(port, msg);
}

static unsigned int on_char = 0;
static unsigned int on_line = 0;


void clear_screen() {
  char *screen_buffer = (void *)VIDEO_BUFFER;
  for(unsigned int i = 0; i <= (80 * 25); i++) screen_buffer[i * 2] = ' ';
  on_char = 0;
  on_line = 0;
} 

void next_line() {
  if(on_line >= 25) {
    on_line = 0;
    clear_screen();
  }
  else {
    on_line++;
  }
  on_char = 0;
}

void move_cursor(unsigned int x, unsigned int y) {
  //yeah yeah yeah, it doens't test for overflows... I'm gonna delete this once i get serial working
  //on my second desktop
  on_char = x;
  on_line = y;
}

//until we get serial working on hp
void _putchar_screen(char msg) {
  if(on_char >= 80) {
    next_line();
  } else if(msg == '\n') {
    next_line();
    return;
  }
  char *screen_buffer = (void *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2)));
  *screen_buffer = msg;
  on_char++;
}