1 // 16bit code to handle serial and printer services.
3 // Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002 MandrakeSoft S.A.
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
8 #include "biosvar.h" // SET_BDA
9 #include "util.h" // debug_enter
10 #include "bregs.h" // struct bregs
13 /****************************************************************
15 ****************************************************************/
18 detect_serial(u16 port, u8 timeout, u8 count)
20 outb(0x02, port+SEROFF_IER);
21 u8 ier = inb(port+SEROFF_IER);
24 u8 iir = inb(port+SEROFF_IIR);
25 if ((iir & 0x3f) != 0x02)
28 outb(0x00, port+SEROFF_IER);
29 SET_BDA(port_com[count], port);
30 SET_BDA(com_timeout[count], timeout);
39 dprintf(3, "init serial\n");
42 count += detect_serial(PORT_SERIAL1, 0x0a, count);
43 count += detect_serial(PORT_SERIAL2, 0x0a, count);
44 count += detect_serial(PORT_SERIAL3, 0x0a, count);
45 count += detect_serial(PORT_SERIAL4, 0x0a, count);
46 dprintf(1, "Found %d serial ports\n", count);
48 // Equipment word bits 9..11 determing # serial ports
49 u16 eqb = GET_BDA(equipment_list_flags);
50 SET_BDA(equipment_list_flags, (eqb & 0xf1ff) | (count << 9));
54 getComAddr(struct bregs *regs)
60 u16 addr = GET_BDA(port_com[regs->dx]);
66 // SERIAL - INITIALIZE PORT
68 handle_1400(struct bregs *regs)
70 u16 addr = getComAddr(regs);
73 outb(inb(addr+SEROFF_LCR) | 0x80, addr+SEROFF_LCR);
74 if ((regs->al & 0xE0) == 0) {
75 outb(0x17, addr+SEROFF_DLL);
76 outb(0x04, addr+SEROFF_DLH);
78 u16 val16 = 0x600 >> ((regs->al & 0xE0) >> 5);
79 outb(val16 & 0xFF, addr+SEROFF_DLL);
80 outb(val16 >> 8, addr+SEROFF_DLH);
82 outb(regs->al & 0x1F, addr+SEROFF_LCR);
83 regs->ah = inb(addr+SEROFF_LSR);
84 regs->al = inb(addr+SEROFF_MSR);
88 // SERIAL - WRITE CHARACTER TO PORT
90 handle_1401(struct bregs *regs)
92 u16 addr = getComAddr(regs);
95 u32 end = calc_future_timer_ticks(GET_BDA(com_timeout[regs->dx]));
97 u8 lsr = inb(addr+SEROFF_LSR);
98 if ((lsr & 0x60) == 0x60) {
99 // Success - can write data
100 outb(regs->al, addr+SEROFF_DATA);
105 if (check_timer(end)) {
106 // Timed out - can't write data.
107 regs->ah = lsr | 0x80;
115 // SERIAL - READ CHARACTER FROM PORT
117 handle_1402(struct bregs *regs)
119 u16 addr = getComAddr(regs);
122 u32 end = calc_future_timer_ticks(GET_BDA(com_timeout[regs->dx]));
124 u8 lsr = inb(addr+SEROFF_LSR);
126 // Success - can read data
127 regs->al = inb(addr+SEROFF_DATA);
131 if (check_timer(end)) {
132 // Timed out - can't read data.
133 regs->ah = lsr | 0x80;
141 // SERIAL - GET PORT STATUS
143 handle_1403(struct bregs *regs)
145 u16 addr = getComAddr(regs);
148 regs->ah = inb(addr+SEROFF_LSR);
149 regs->al = inb(addr+SEROFF_MSR);
154 handle_14XX(struct bregs *regs)
156 set_unimplemented(regs);
159 // INT 14h Serial Communications Service Entry Point
161 handle_14(struct bregs *regs)
163 debug_enter(regs, DEBUG_HDL_14);
164 if (! CONFIG_SERIAL) {
170 case 0x00: handle_1400(regs); break;
171 case 0x01: handle_1401(regs); break;
172 case 0x02: handle_1402(regs); break;
173 case 0x03: handle_1403(regs); break;
174 default: handle_14XX(regs); break;
178 // XXX - Baud Rate Generator Table
179 u8 BaudTable[16] VAR16FIXED(0xe729);
182 /****************************************************************
184 ****************************************************************/
187 detect_parport(u16 port, u8 timeout, u8 count)
190 outb(inb(port+2) & 0xdf, port+2);
193 if (inb(port) != 0xaa)
196 SET_BDA(port_lpt[count], port);
197 SET_BDA(lpt_timeout[count], timeout);
206 dprintf(3, "init lpt\n");
209 count += detect_parport(PORT_LPT1, 0x14, count);
210 count += detect_parport(PORT_LPT2, 0x14, count);
211 dprintf(1, "Found %d lpt ports\n", count);
213 // Equipment word bits 14..15 determing # parallel ports
214 u16 eqb = GET_BDA(equipment_list_flags);
215 SET_BDA(equipment_list_flags, (eqb & 0x3fff) | (count << 14));
219 getLptAddr(struct bregs *regs)
225 u16 addr = GET_BDA(port_lpt[regs->dx]);
231 // INT 17 - PRINTER - WRITE CHARACTER
233 handle_1700(struct bregs *regs)
235 u16 addr = getLptAddr(regs);
239 u32 end = calc_future_timer_ticks(GET_BDA(lpt_timeout[regs->dx]));
241 outb(regs->al, addr);
242 u8 val8 = inb(addr+2);
243 outb(val8 | 0x01, addr+2); // send strobe
245 outb(val8 & ~0x01, addr+2);
254 if (check_timer(end)) {
256 regs->ah = (v ^ 0x48) | 0x01;
265 // INT 17 - PRINTER - INITIALIZE PORT
267 handle_1701(struct bregs *regs)
269 u16 addr = getLptAddr(regs);
273 u8 val8 = inb(addr+2);
274 outb(val8 & ~0x04, addr+2); // send init
276 outb(val8 | 0x04, addr+2);
278 regs->ah = inb(addr+1) ^ 0x48;
282 // INT 17 - PRINTER - GET STATUS
284 handle_1702(struct bregs *regs)
286 u16 addr = getLptAddr(regs);
289 regs->ah = inb(addr+1) ^ 0x48;
294 handle_17XX(struct bregs *regs)
296 set_unimplemented(regs);
299 // INT17h : Printer Service Entry Point
301 handle_17(struct bregs *regs)
303 debug_enter(regs, DEBUG_HDL_17);
310 case 0x00: handle_1700(regs); break;
311 case 0x01: handle_1701(regs); break;
312 case 0x02: handle_1702(regs); break;
313 default: handle_17XX(regs); break;