|
|
1.1 root 1: // 16bit code to handle serial and printer services.
2: //
3: // Copyright (C) 2008,2009 Kevin O'Connor <[email protected]>
4: // Copyright (C) 2002 MandrakeSoft S.A.
5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
8: #include "biosvar.h" // SET_BDA
9: #include "util.h" // debug_enter
10: #include "bregs.h" // struct bregs
11:
12:
13: /****************************************************************
14: * COM ports
15: ****************************************************************/
16:
17: static u16
18: detect_serial(u16 port, u8 timeout, u8 count)
19: {
20: outb(0x02, port+SEROFF_IER);
21: u8 ier = inb(port+SEROFF_IER);
22: if (ier != 0x02)
23: return 0;
24: u8 iir = inb(port+SEROFF_IIR);
25: if ((iir & 0x3f) != 0x02)
26: return 0;
27:
28: outb(0x00, port+SEROFF_IER);
29: SET_BDA(port_com[count], port);
30: SET_BDA(com_timeout[count], timeout);
31: return 1;
32: }
33:
34: void
1.1.1.2 root 35: serial_setup(void)
1.1 root 36: {
37: if (! CONFIG_SERIAL)
38: return;
39: dprintf(3, "init serial\n");
40:
41: u16 count = 0;
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);
47:
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));
51: }
52:
53: static u16
54: getComAddr(struct bregs *regs)
55: {
56: if (regs->dx >= 4) {
57: set_invalid(regs);
58: return 0;
59: }
60: u16 addr = GET_BDA(port_com[regs->dx]);
61: if (! addr)
62: set_invalid(regs);
63: return addr;
64: }
65:
66: // SERIAL - INITIALIZE PORT
67: static void
68: handle_1400(struct bregs *regs)
69: {
70: u16 addr = getComAddr(regs);
71: if (!addr)
72: return;
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);
77: } else {
78: u16 val16 = 0x600 >> ((regs->al & 0xE0) >> 5);
79: outb(val16 & 0xFF, addr+SEROFF_DLL);
80: outb(val16 >> 8, addr+SEROFF_DLH);
81: }
82: outb(regs->al & 0x1F, addr+SEROFF_LCR);
83: regs->ah = inb(addr+SEROFF_LSR);
84: regs->al = inb(addr+SEROFF_MSR);
85: set_success(regs);
86: }
87:
88: // SERIAL - WRITE CHARACTER TO PORT
89: static void
90: handle_1401(struct bregs *regs)
91: {
92: u16 addr = getComAddr(regs);
93: if (!addr)
94: return;
1.1.1.3 ! root 95: u32 end = calc_future_timer_ticks(GET_BDA(com_timeout[regs->dx]));
1.1 root 96: for (;;) {
97: u8 lsr = inb(addr+SEROFF_LSR);
98: if ((lsr & 0x60) == 0x60) {
99: // Success - can write data
100: outb(regs->al, addr+SEROFF_DATA);
101: // XXX - reread lsr?
102: regs->ah = lsr;
103: break;
104: }
1.1.1.3 ! root 105: if (check_timer(end)) {
1.1 root 106: // Timed out - can't write data.
107: regs->ah = lsr | 0x80;
108: break;
109: }
110: yield();
111: }
112: set_success(regs);
113: }
114:
115: // SERIAL - READ CHARACTER FROM PORT
116: static void
117: handle_1402(struct bregs *regs)
118: {
119: u16 addr = getComAddr(regs);
120: if (!addr)
121: return;
1.1.1.3 ! root 122: u32 end = calc_future_timer_ticks(GET_BDA(com_timeout[regs->dx]));
1.1 root 123: for (;;) {
124: u8 lsr = inb(addr+SEROFF_LSR);
125: if (lsr & 0x01) {
126: // Success - can read data
127: regs->al = inb(addr+SEROFF_DATA);
128: regs->ah = lsr;
129: break;
130: }
1.1.1.3 ! root 131: if (check_timer(end)) {
1.1 root 132: // Timed out - can't read data.
133: regs->ah = lsr | 0x80;
134: break;
135: }
136: yield();
137: }
138: set_success(regs);
139: }
140:
141: // SERIAL - GET PORT STATUS
142: static void
143: handle_1403(struct bregs *regs)
144: {
145: u16 addr = getComAddr(regs);
146: if (!addr)
147: return;
148: regs->ah = inb(addr+SEROFF_LSR);
149: regs->al = inb(addr+SEROFF_MSR);
150: set_success(regs);
151: }
152:
153: static void
154: handle_14XX(struct bregs *regs)
155: {
156: set_unimplemented(regs);
157: }
158:
159: // INT 14h Serial Communications Service Entry Point
160: void VISIBLE16
161: handle_14(struct bregs *regs)
162: {
163: debug_enter(regs, DEBUG_HDL_14);
164: if (! CONFIG_SERIAL) {
165: handle_14XX(regs);
166: return;
167: }
168:
169: switch (regs->ah) {
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;
175: }
176: }
177:
178: // XXX - Baud Rate Generator Table
179: u8 BaudTable[16] VAR16FIXED(0xe729);
180:
181:
182: /****************************************************************
183: * LPT ports
184: ****************************************************************/
185:
186: static u16
187: detect_parport(u16 port, u8 timeout, u8 count)
188: {
189: // clear input mode
190: outb(inb(port+2) & 0xdf, port+2);
191:
192: outb(0xaa, port);
193: if (inb(port) != 0xaa)
194: // Not present
195: return 0;
196: SET_BDA(port_lpt[count], port);
197: SET_BDA(lpt_timeout[count], timeout);
198: return 1;
199: }
200:
201: void
1.1.1.2 root 202: lpt_setup(void)
1.1 root 203: {
204: if (! CONFIG_LPT)
205: return;
206: dprintf(3, "init lpt\n");
207:
208: u16 count = 0;
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);
212:
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));
216: }
217:
218: static u16
219: getLptAddr(struct bregs *regs)
220: {
221: if (regs->dx >= 3) {
222: set_invalid(regs);
223: return 0;
224: }
225: u16 addr = GET_BDA(port_lpt[regs->dx]);
226: if (! addr)
227: set_invalid(regs);
228: return addr;
229: }
230:
231: // INT 17 - PRINTER - WRITE CHARACTER
232: static void
233: handle_1700(struct bregs *regs)
234: {
235: u16 addr = getLptAddr(regs);
236: if (!addr)
237: return;
238:
1.1.1.3 ! root 239: u32 end = calc_future_timer_ticks(GET_BDA(lpt_timeout[regs->dx]));
1.1 root 240:
241: outb(regs->al, addr);
242: u8 val8 = inb(addr+2);
243: outb(val8 | 0x01, addr+2); // send strobe
244: udelay(5);
245: outb(val8 & ~0x01, addr+2);
246:
247: for (;;) {
248: u8 v = inb(addr+1);
249: if (!(v & 0x40)) {
250: // Success
251: regs->ah = v ^ 0x48;
252: break;
253: }
1.1.1.3 ! root 254: if (check_timer(end)) {
1.1 root 255: // Timeout
256: regs->ah = (v ^ 0x48) | 0x01;
257: break;
258: }
259: yield();
260: }
261:
262: set_success(regs);
263: }
264:
265: // INT 17 - PRINTER - INITIALIZE PORT
266: static void
267: handle_1701(struct bregs *regs)
268: {
269: u16 addr = getLptAddr(regs);
270: if (!addr)
271: return;
272:
273: u8 val8 = inb(addr+2);
274: outb(val8 & ~0x04, addr+2); // send init
275: udelay(5);
276: outb(val8 | 0x04, addr+2);
277:
278: regs->ah = inb(addr+1) ^ 0x48;
279: set_success(regs);
280: }
281:
282: // INT 17 - PRINTER - GET STATUS
283: static void
284: handle_1702(struct bregs *regs)
285: {
286: u16 addr = getLptAddr(regs);
287: if (!addr)
288: return;
289: regs->ah = inb(addr+1) ^ 0x48;
290: set_success(regs);
291: }
292:
293: static void
294: handle_17XX(struct bregs *regs)
295: {
296: set_unimplemented(regs);
297: }
298:
299: // INT17h : Printer Service Entry Point
300: void VISIBLE16
301: handle_17(struct bregs *regs)
302: {
303: debug_enter(regs, DEBUG_HDL_17);
304: if (! CONFIG_LPT) {
305: handle_17XX(regs);
306: return;
307: }
308:
309: switch (regs->ah) {
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;
314: }
315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.