-
Notifications
You must be signed in to change notification settings - Fork 2
/
serial.c
91 lines (77 loc) · 1.58 KB
/
serial.c
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
#include "string.h"
#include "ports.h"
#include "isr.h"
#include "serial.h"
#include "printk.h"
enum serial_ports {
SERIAL_PORT_A = 0x3F8,
SERIAL_PORT_B = 0x2F8,
SERIAL_PORT_C = 0x3E8,
SERIAL_PORT_D = 0x2E8
};
static int
serial_rcvd(void)
{
return inb(SERIAL_PORT_A + 5) & 1;
}
static char
serial_recv(void)
{
if (serial_rcvd() == 0)
return '\0';
return inb(SERIAL_PORT_A);
}
static int
serial_transmit_empty(void)
{
return inb(SERIAL_PORT_A + 5) & 0x20;
}
static void
serial_send(char out)
{
while (serial_transmit_empty() == 0);
outb(SERIAL_PORT_A, out);
}
void
serial__puts(const char *s)
{
for (; *s != '\0'; s++)
serial_send(*s);
}
static void
serial_handler(struct registers *r)
{
char serial = serial_recv();
/*
* Fix the serial input assuming it is ascii
*/
switch (serial) {
case '\0':
return;
break;
case 127:
serial = 0x08;
break;
case 13:
serial = '\n';
break;
default:
break;
}
printk(INFO, "Serial: %d\n", serial);
}
void
serial__init(void)
{
printk(INFO, "Registering Serial IRQ\n");
register_interrupt_handler(IRQ4, &serial_handler);
/* We will initialize the first serial port */
outb(SERIAL_PORT_A + 1, 0x00);
outb(SERIAL_PORT_A + 3, 0x80); /* Enable divisor mode */
outb(SERIAL_PORT_A + 0, 0x03); /* Div Low: 03 Set the port to 38400 bps */
outb(SERIAL_PORT_A + 1, 0x00); /* Div High: 00 */
outb(SERIAL_PORT_A + 3, 0x03);
outb(SERIAL_PORT_A + 2, 0xC7);
outb(SERIAL_PORT_A + 4, 0x0B);
outb(SERIAL_PORT_A + 1, 0x01); /* Enable interrupts on receive */
}