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++;
}
|