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