pcio.c revision 1.11.2.2 1 1.11.2.2 thorpej /* $NetBSD: pcio.c,v 1.11.2.2 2002/02/19 20:18:37 thorpej Exp $ */
2 1.11.2.2 thorpej
3 1.11.2.2 thorpej /*
4 1.11.2.2 thorpej * Copyright (c) 1996, 1997
5 1.11.2.2 thorpej * Matthias Drochner. All rights reserved.
6 1.11.2.2 thorpej *
7 1.11.2.2 thorpej * Redistribution and use in source and binary forms, with or without
8 1.11.2.2 thorpej * modification, are permitted provided that the following conditions
9 1.11.2.2 thorpej * are met:
10 1.11.2.2 thorpej * 1. Redistributions of source code must retain the above copyright
11 1.11.2.2 thorpej * notice, this list of conditions and the following disclaimer.
12 1.11.2.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright
13 1.11.2.2 thorpej * notice, this list of conditions and the following disclaimer in the
14 1.11.2.2 thorpej * documentation and/or other materials provided with the distribution.
15 1.11.2.2 thorpej * 3. All advertising materials mentioning features or use of this software
16 1.11.2.2 thorpej * must display the following acknowledgement:
17 1.11.2.2 thorpej * This product includes software developed for the NetBSD Project
18 1.11.2.2 thorpej * by Matthias Drochner.
19 1.11.2.2 thorpej * 4. The name of the author may not be used to endorse or promote products
20 1.11.2.2 thorpej * derived from this software without specific prior written permission.
21 1.11.2.2 thorpej *
22 1.11.2.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.11.2.2 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.11.2.2 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.11.2.2 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.11.2.2 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.11.2.2 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.11.2.2 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.11.2.2 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.11.2.2 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.11.2.2 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.11.2.2 thorpej *
33 1.11.2.2 thorpej */
34 1.11.2.2 thorpej
35 1.11.2.2 thorpej /*
36 1.11.2.2 thorpej * console I/O
37 1.11.2.2 thorpej * needs lowlevel routines from conio.S and comio.S
38 1.11.2.2 thorpej */
39 1.11.2.2 thorpej
40 1.11.2.2 thorpej #include <lib/libsa/stand.h>
41 1.11.2.2 thorpej #include <lib/libkern/libkern.h>
42 1.11.2.2 thorpej
43 1.11.2.2 thorpej #include "libi386.h"
44 1.11.2.2 thorpej #include "bootinfo.h"
45 1.11.2.2 thorpej
46 1.11.2.2 thorpej extern void conputc __P((int));
47 1.11.2.2 thorpej extern int congetc __P((void));
48 1.11.2.2 thorpej extern int coniskey __P((void));
49 1.11.2.2 thorpej
50 1.11.2.2 thorpej struct btinfo_console btinfo_console;
51 1.11.2.2 thorpej
52 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
53 1.11.2.2 thorpej static int iodev;
54 1.11.2.2 thorpej
55 1.11.2.2 thorpej #ifdef DIRECT_SERIAL
56 1.11.2.2 thorpej #include "comio_direct.h"
57 1.11.2.2 thorpej
58 1.11.2.2 thorpej #define cominit cominit_d
59 1.11.2.2 thorpej #define computc computc_d
60 1.11.2.2 thorpej #define comgetc comgetc_d
61 1.11.2.2 thorpej /* comstatus() is different */
62 1.11.2.2 thorpej
63 1.11.2.2 thorpej #define SERIAL_ARG btinfo_console.addr
64 1.11.2.2 thorpej #else
65 1.11.2.2 thorpej extern void cominit __P((int));
66 1.11.2.2 thorpej extern int computc __P((int, int));
67 1.11.2.2 thorpej extern int comgetc __P((int));
68 1.11.2.2 thorpej extern int comstatus __P((int));
69 1.11.2.2 thorpej
70 1.11.2.2 thorpej #define SERIAL_ARG (iodev - CONSDEV_COM0)
71 1.11.2.2 thorpej #endif /* DIRECT_SERIAL */
72 1.11.2.2 thorpej
73 1.11.2.2 thorpej static int getcomaddr __P((int));
74 1.11.2.2 thorpej #endif /* SUPPORT_SERIAL */
75 1.11.2.2 thorpej
76 1.11.2.2 thorpej #define POLL_FREQ 10
77 1.11.2.2 thorpej
78 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
79 1.11.2.2 thorpej static int
80 1.11.2.2 thorpej getcomaddr(idx)
81 1.11.2.2 thorpej int idx;
82 1.11.2.2 thorpej {
83 1.11.2.2 thorpej short addr;
84 1.11.2.2 thorpej /* read in BIOS data area */
85 1.11.2.2 thorpej pvbcopy((void *)(0x400 + 2 * idx), &addr, 2);
86 1.11.2.2 thorpej return(addr);
87 1.11.2.2 thorpej }
88 1.11.2.2 thorpej #endif
89 1.11.2.2 thorpej
90 1.11.2.2 thorpej void
91 1.11.2.2 thorpej initio(dev)
92 1.11.2.2 thorpej int dev;
93 1.11.2.2 thorpej {
94 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
95 1.11.2.2 thorpej int i;
96 1.11.2.2 thorpej
97 1.11.2.2 thorpej switch (dev) {
98 1.11.2.2 thorpej case CONSDEV_AUTO:
99 1.11.2.2 thorpej for(i = 0; i < 3; i++) {
100 1.11.2.2 thorpej iodev = CONSDEV_COM0 + i;
101 1.11.2.2 thorpej btinfo_console.addr = getcomaddr(i);
102 1.11.2.2 thorpej if(!btinfo_console.addr) break;
103 1.11.2.2 thorpej conputc('0' + i); /* to tell user what happens */
104 1.11.2.2 thorpej cominit(SERIAL_ARG);
105 1.11.2.2 thorpej #ifdef DIRECT_SERIAL
106 1.11.2.2 thorpej /* check for:
107 1.11.2.2 thorpej * 1. successful output
108 1.11.2.2 thorpej * 2. optionally, keypress within 1s
109 1.11.2.2 thorpej */
110 1.11.2.2 thorpej if ( computc(':', SERIAL_ARG) &&
111 1.11.2.2 thorpej computc('-', SERIAL_ARG) &&
112 1.11.2.2 thorpej computc('(', SERIAL_ARG)
113 1.11.2.2 thorpej #ifdef COMCONS_KEYPRESS
114 1.11.2.2 thorpej && awaitkey(7, 0)
115 1.11.2.2 thorpej #endif
116 1.11.2.2 thorpej )
117 1.11.2.2 thorpej goto ok;
118 1.11.2.2 thorpej #else /* ! DIRECT_SERIAL */
119 1.11.2.2 thorpej /*
120 1.11.2.2 thorpej * serial console must have hardware handshake!
121 1.11.2.2 thorpej * check:
122 1.11.2.2 thorpej * 1. character output without error
123 1.11.2.2 thorpej * 2. status bits for modem ready set
124 1.11.2.2 thorpej * (status seems only useful after character output)
125 1.11.2.2 thorpej * 3. optionally, keypress within 1s
126 1.11.2.2 thorpej */
127 1.11.2.2 thorpej if (!(computc('@', SERIAL_ARG) & 0x80)
128 1.11.2.2 thorpej && (comstatus(SERIAL_ARG) & 0x00b0)
129 1.11.2.2 thorpej #ifdef COMCONS_KEYPRESS
130 1.11.2.2 thorpej && awaitkey(7, 0)
131 1.11.2.2 thorpej #endif
132 1.11.2.2 thorpej )
133 1.11.2.2 thorpej goto ok;
134 1.11.2.2 thorpej #endif /* DIRECT_SERIAL */
135 1.11.2.2 thorpej }
136 1.11.2.2 thorpej iodev = CONSDEV_PC;
137 1.11.2.2 thorpej ok:
138 1.11.2.2 thorpej break;
139 1.11.2.2 thorpej case CONSDEV_COM0:
140 1.11.2.2 thorpej case CONSDEV_COM1:
141 1.11.2.2 thorpej case CONSDEV_COM2:
142 1.11.2.2 thorpej case CONSDEV_COM3:
143 1.11.2.2 thorpej iodev = dev;
144 1.11.2.2 thorpej btinfo_console.addr = getcomaddr(iodev - CONSDEV_COM0);
145 1.11.2.2 thorpej if(!btinfo_console.addr) goto nocom;
146 1.11.2.2 thorpej cominit(SERIAL_ARG);
147 1.11.2.2 thorpej break;
148 1.11.2.2 thorpej case CONSDEV_COM0KBD:
149 1.11.2.2 thorpej case CONSDEV_COM1KBD:
150 1.11.2.2 thorpej case CONSDEV_COM2KBD:
151 1.11.2.2 thorpej case CONSDEV_COM3KBD:
152 1.11.2.2 thorpej iodev = dev - 4;
153 1.11.2.2 thorpej i = iodev - CONSDEV_COM0;
154 1.11.2.2 thorpej btinfo_console.addr = getcomaddr(i);
155 1.11.2.2 thorpej if(!btinfo_console.addr) goto nocom;
156 1.11.2.2 thorpej conputc('0' + i); /* to tell user what happens */
157 1.11.2.2 thorpej cominit(SERIAL_ARG);
158 1.11.2.2 thorpej #ifdef DIRECT_SERIAL
159 1.11.2.2 thorpej /* check for:
160 1.11.2.2 thorpej * 1. successful output
161 1.11.2.2 thorpej * 2. optionally, keypress within 1s
162 1.11.2.2 thorpej */
163 1.11.2.2 thorpej if ( computc(':', SERIAL_ARG) &&
164 1.11.2.2 thorpej computc('-', SERIAL_ARG) &&
165 1.11.2.2 thorpej computc('(', SERIAL_ARG)
166 1.11.2.2 thorpej #ifdef COMCONS_KEYPRESS
167 1.11.2.2 thorpej && awaitkey(7, 0)
168 1.11.2.2 thorpej #endif
169 1.11.2.2 thorpej )
170 1.11.2.2 thorpej break;
171 1.11.2.2 thorpej #else /* ! DIRECT_SERIAL */
172 1.11.2.2 thorpej /*
173 1.11.2.2 thorpej * serial console must have hardware handshake!
174 1.11.2.2 thorpej * check:
175 1.11.2.2 thorpej * 1. character output without error
176 1.11.2.2 thorpej * 2. status bits for modem ready set
177 1.11.2.2 thorpej * (status seems only useful after character output)
178 1.11.2.2 thorpej * 3. optionally, keypress within 1s
179 1.11.2.2 thorpej */
180 1.11.2.2 thorpej if (!(computc('@', SERIAL_ARG) & 0x80)
181 1.11.2.2 thorpej && (comstatus(SERIAL_ARG) & 0x00b0)
182 1.11.2.2 thorpej #ifdef COMCONS_KEYPRESS
183 1.11.2.2 thorpej && awaitkey(7, 0)
184 1.11.2.2 thorpej #endif
185 1.11.2.2 thorpej )
186 1.11.2.2 thorpej break;
187 1.11.2.2 thorpej #endif /* DIRECT_SERIAL */
188 1.11.2.2 thorpej default:
189 1.11.2.2 thorpej nocom:
190 1.11.2.2 thorpej iodev = CONSDEV_PC;
191 1.11.2.2 thorpej break;
192 1.11.2.2 thorpej }
193 1.11.2.2 thorpej conputc('\015');
194 1.11.2.2 thorpej conputc('\n');
195 1.11.2.2 thorpej strncpy(btinfo_console.devname, iodev == CONSDEV_PC ? "pc" : "com", 16);
196 1.11.2.2 thorpej #if defined(DIRECT_SERIAL) && defined(CONSPEED)
197 1.11.2.2 thorpej btinfo_console.speed = CONSPEED;
198 1.11.2.2 thorpej #else
199 1.11.2.2 thorpej btinfo_console.speed = 9600;
200 1.11.2.2 thorpej #endif
201 1.11.2.2 thorpej #else /* !SUPPORT_SERIAL */
202 1.11.2.2 thorpej strncpy(btinfo_console.devname, "pc", 16);
203 1.11.2.2 thorpej #endif /* SUPPORT_SERIAL */
204 1.11.2.2 thorpej }
205 1.11.2.2 thorpej
206 1.11.2.2 thorpej static inline void internal_putchar __P((int));
207 1.11.2.2 thorpej
208 1.11.2.2 thorpej static inline void
209 1.11.2.2 thorpej internal_putchar(c)
210 1.11.2.2 thorpej int c;
211 1.11.2.2 thorpej {
212 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
213 1.11.2.2 thorpej switch (iodev) {
214 1.11.2.2 thorpej case CONSDEV_PC:
215 1.11.2.2 thorpej #endif
216 1.11.2.2 thorpej conputc(c);
217 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
218 1.11.2.2 thorpej break;
219 1.11.2.2 thorpej case CONSDEV_COM0:
220 1.11.2.2 thorpej case CONSDEV_COM1:
221 1.11.2.2 thorpej case CONSDEV_COM2:
222 1.11.2.2 thorpej case CONSDEV_COM3:
223 1.11.2.2 thorpej computc(c, SERIAL_ARG);
224 1.11.2.2 thorpej break;
225 1.11.2.2 thorpej }
226 1.11.2.2 thorpej #endif
227 1.11.2.2 thorpej }
228 1.11.2.2 thorpej
229 1.11.2.2 thorpej void
230 1.11.2.2 thorpej putchar(c)
231 1.11.2.2 thorpej int c;
232 1.11.2.2 thorpej {
233 1.11.2.2 thorpej if (c == '\n')
234 1.11.2.2 thorpej internal_putchar('\r');
235 1.11.2.2 thorpej internal_putchar(c);
236 1.11.2.2 thorpej }
237 1.11.2.2 thorpej
238 1.11.2.2 thorpej int
239 1.11.2.2 thorpej getchar()
240 1.11.2.2 thorpej {
241 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
242 1.11.2.2 thorpej int c;
243 1.11.2.2 thorpej switch (iodev) {
244 1.11.2.2 thorpej default: /* to make gcc -Wall happy... */
245 1.11.2.2 thorpej case CONSDEV_PC:
246 1.11.2.2 thorpej #endif
247 1.11.2.2 thorpej return (congetc());
248 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
249 1.11.2.2 thorpej case CONSDEV_COM0:
250 1.11.2.2 thorpej case CONSDEV_COM1:
251 1.11.2.2 thorpej case CONSDEV_COM2:
252 1.11.2.2 thorpej case CONSDEV_COM3:
253 1.11.2.2 thorpej #ifdef DIRECT_SERIAL
254 1.11.2.2 thorpej c = comgetc(SERIAL_ARG);
255 1.11.2.2 thorpej #else
256 1.11.2.2 thorpej do {
257 1.11.2.2 thorpej c = comgetc(SERIAL_ARG);
258 1.11.2.2 thorpej } while ((c >> 8) == 0xe0); /* catch timeout */
259 1.11.2.2 thorpej #ifdef COMDEBUG
260 1.11.2.2 thorpej if (c & 0x8000) {
261 1.11.2.2 thorpej printf("com input %x, status %x\n",
262 1.11.2.2 thorpej c, comstatus(SERIAL_ARG));
263 1.11.2.2 thorpej }
264 1.11.2.2 thorpej #endif
265 1.11.2.2 thorpej c &= 0xff;
266 1.11.2.2 thorpej #endif /* DIRECT_SERIAL */
267 1.11.2.2 thorpej return (c);
268 1.11.2.2 thorpej }
269 1.11.2.2 thorpej #endif /* SUPPORT_SERIAL */
270 1.11.2.2 thorpej }
271 1.11.2.2 thorpej
272 1.11.2.2 thorpej int
273 1.11.2.2 thorpej iskey()
274 1.11.2.2 thorpej {
275 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
276 1.11.2.2 thorpej switch (iodev) {
277 1.11.2.2 thorpej default: /* to make gcc -Wall happy... */
278 1.11.2.2 thorpej case CONSDEV_PC:
279 1.11.2.2 thorpej #endif
280 1.11.2.2 thorpej return (coniskey());
281 1.11.2.2 thorpej #ifdef SUPPORT_SERIAL
282 1.11.2.2 thorpej case CONSDEV_COM0:
283 1.11.2.2 thorpej case CONSDEV_COM1:
284 1.11.2.2 thorpej case CONSDEV_COM2:
285 1.11.2.2 thorpej case CONSDEV_COM3:
286 1.11.2.2 thorpej #ifdef DIRECT_SERIAL
287 1.11.2.2 thorpej return(!!comstatus_d(SERIAL_ARG));
288 1.11.2.2 thorpej #else
289 1.11.2.2 thorpej return (!!(comstatus(SERIAL_ARG) & 0x0100));
290 1.11.2.2 thorpej #endif
291 1.11.2.2 thorpej }
292 1.11.2.2 thorpej #endif /* SUPPORT_SERIAL */
293 1.11.2.2 thorpej }
294 1.11.2.2 thorpej
295 1.11.2.2 thorpej char
296 1.11.2.2 thorpej awaitkey(timeout, tell)
297 1.11.2.2 thorpej int timeout, tell;
298 1.11.2.2 thorpej {
299 1.11.2.2 thorpej int i;
300 1.11.2.2 thorpej char c = 0;
301 1.11.2.2 thorpej
302 1.11.2.2 thorpej i = timeout * POLL_FREQ;
303 1.11.2.2 thorpej
304 1.11.2.2 thorpej while (i) {
305 1.11.2.2 thorpej if (tell && (i % POLL_FREQ) == 0) {
306 1.11.2.2 thorpej char numbuf[20];
307 1.11.2.2 thorpej int len, j;
308 1.11.2.2 thorpej
309 1.11.2.2 thorpej sprintf(numbuf, "%d ", i/POLL_FREQ);
310 1.11.2.2 thorpej len = strlen(numbuf);
311 1.11.2.2 thorpej for (j = 0; j < len; j++)
312 1.11.2.2 thorpej numbuf[len + j] = '\b';
313 1.11.2.2 thorpej numbuf[len + j] = '\0';
314 1.11.2.2 thorpej printf(numbuf);
315 1.11.2.2 thorpej }
316 1.11.2.2 thorpej if (iskey()) {
317 1.11.2.2 thorpej /* flush input buffer */
318 1.11.2.2 thorpej while (iskey())
319 1.11.2.2 thorpej c = getchar();
320 1.11.2.2 thorpej goto out; /* XXX what happens if c == 0? */
321 1.11.2.2 thorpej }
322 1.11.2.2 thorpej delay(1000000 / POLL_FREQ);
323 1.11.2.2 thorpej i--;
324 1.11.2.2 thorpej }
325 1.11.2.2 thorpej
326 1.11.2.2 thorpej out:
327 1.11.2.2 thorpej if (tell)
328 1.11.2.2 thorpej printf("0\n");
329 1.11.2.2 thorpej
330 1.11.2.2 thorpej return(c);
331 1.11.2.2 thorpej }
332