1 | // Intel 8250 serial port (UART). |
2 | |
3 | #include "types.h" |
4 | #include "defs.h" |
5 | #include "param.h" |
6 | #include "traps.h" |
7 | #include "spinlock.h" |
8 | #include "sleeplock.h" |
9 | #include "fs.h" |
10 | #include "file.h" |
11 | #include "mmu.h" |
12 | #include "proc.h" |
13 | #include "x86.h" |
14 | |
15 | #define COM1 0x3f8 |
16 | |
17 | static int uart; // is there a uart? |
18 | |
19 | void |
20 | uartinit(void) |
21 | { |
22 | char *p; |
23 | |
24 | // Turn off the FIFO |
25 | outb(COM1+2, 0); |
26 | |
27 | // 9600 baud, 8 data bits, 1 stop bit, parity off. |
28 | outb(COM1+3, 0x80); // Unlock divisor |
29 | outb(COM1+0, 115200/9600); |
30 | outb(COM1+1, 0); |
31 | outb(COM1+3, 0x03); // Lock divisor, 8 data bits. |
32 | outb(COM1+4, 0); |
33 | outb(COM1+1, 0x01); // Enable receive interrupts. |
34 | |
35 | // If status is 0xFF, no serial port. |
36 | if(inb(COM1+5) == 0xFF) |
37 | return; |
38 | uart = 1; |
39 | |
40 | // Acknowledge pre-existing interrupt conditions; |
41 | // enable interrupts. |
42 | inb(COM1+2); |
43 | inb(COM1+0); |
44 | ioapicenable(IRQ_COM1, 0); |
45 | |
46 | // Announce that we're here. |
47 | for(p="xv6...\n" ; *p; p++) |
48 | uartputc(*p); |
49 | } |
50 | |
51 | void |
52 | uartputc(int c) |
53 | { |
54 | int i; |
55 | |
56 | if(!uart) |
57 | return; |
58 | for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) |
59 | microdelay(10); |
60 | outb(COM1+0, c); |
61 | } |
62 | |
63 | static int |
64 | uartgetc(void) |
65 | { |
66 | if(!uart) |
67 | return -1; |
68 | if(!(inb(COM1+5) & 0x01)) |
69 | return -1; |
70 | return inb(COM1+0); |
71 | } |
72 | |
73 | void |
74 | uartintr(void) |
75 | { |
76 | consoleintr(uartgetc); |
77 | } |
78 | |