2 * Copyright (c) 2008 Joshua Phillips. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 struct serial com1
, com2
, com3
, com4
;
35 #define com1Base 0x3F8
36 #define com2Base 0x2F8
37 #define com3Base 0x3E8
38 #define com4Base 0x2E8
40 static int detect_uart(struct serial
*self
);
41 static char sanitise_output(struct serial
*self
, char ch
);
42 static void send_char(struct serial
*self
, char ch
);
44 // Probe to see if the device is there
47 // 2 - 16450 or 8250 with scratch reg
50 static int detect_uart(struct serial
*self
)
54 // Check if UART is present
55 tmp
= inb(self
->port
+ 4);
56 outb(self
->port
+ 4, 0x10);
57 if ((inb(self
->port
+ 6) & 0xF0))
59 outb(self
->port
+ 4, 0x1F);
60 if ((inb(self
->port
+ 6) & 0xF0) != 0xF0)
62 outb(self
->port
+ 4, tmp
);
64 // Look for scratch register
65 tmp
= inb(self
->port
+ 7);
66 outb(self
->port
+ 7, 0x55);
67 if (inb(self
->port
+ 7) != 0x55)
69 outb(self
->port
+ 7, 0xAA);
70 if (inb(self
->port
+ 7) != 0xAA)
72 outb(self
->port
+ 7, tmp
);
75 outb(self
->port
+ 2, 1);
76 x
= inb(self
->port
+ 2);
77 outb(self
->port
+ 2, 0x00);
85 static char sanitise_output(struct serial
*self
, char ch
)
88 // We have to send the age-old CRLF combo
90 send_char(self
, '\r');
92 } else if (ch
== '\b'){
99 // send a single character
100 static void send_char(struct serial
*self
, char ch
)
102 // remove characters we don't want (control characters, etc.)
103 if (!(ch
= sanitise_output(self
, ch
)))
105 // wait for UART to be ready
106 while (!(inb(self
->port
+ 5) & 0x20)){
110 outb(self
->port
, ch
);
113 bool serial_init(struct serial
*self
, int com_number
, unsigned long baud
)
115 unsigned int divisor
;
119 self
->port
= com1Base
;
123 self
->port
= com2Base
;
127 self
->port
= com3Base
;
131 self
->port
= com4Base
;
138 if (detect_uart(self
) == 0){
139 // couldn't actually find the device
143 divisor
= 115200 / baud
;
144 outb(self
->port
+ 1, 0x00); // disable all interrupts
145 outb(self
->port
+ 3, 0x80); // enable 'DLAB' - baud rate divisor
146 outb(self
->port
+ 0, divisor
); // divisor (lower)
147 outb(self
->port
+ 1, divisor
>> 8); // divisor (upper)
148 outb(self
->port
+ 3, 0x03); // 8-bits, no parity, one stop bit
149 outb(self
->port
+ 2, 0xC7); // enable FIFO, clear them, with 14-byte threshold
150 outb(self
->port
+ 4, 0x0B); // enable (something)
151 outb(self
->port
+ 4, inb(self
->port
+ 4) | 8); // set OUT2 bit to enable interrupts
152 outb(self
->port
+ 1, 0x01); // enable ERBFI (receiver buffer full) interrupt
154 self
->initialized
= true;
158 void serial_send(struct serial
*self
, const char *str
)
161 send_char(self
, *str
);