pcio.c revision 1.5 1 /* $NetBSD: pcio.c,v 1.5 1997/09/17 17:48:00 drochner 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 #ifdef COMCONS_KEYPRESS
112 && awaitkey(1, 0)
113 #endif
114 )
115 goto ok;
116 #else
117 /*
118 * serial console must have hardware handshake!
119 * check:
120 * 1. character output without error
121 * 2. status bits for modem ready set
122 * (status seems only useful after character output)
123 * 3. optionally, keypress within 1s
124 */
125 if (!(computc(' ', SERIAL_ARG) & 0x80)
126 && (comstatus(SERIAL_ARG) & 0x00b0)
127 #ifdef COMCONS_KEYPRESS
128 && awaitkey(1, 0)
129 #endif
130 )
131 goto ok;
132 #endif
133 }
134 iodev = CONSDEV_PC;
135 ok:
136 break;
137 case CONSDEV_COM0:
138 case CONSDEV_COM1:
139 case CONSDEV_COM2:
140 case CONSDEV_COM3:
141 iodev = dev;
142 btinfo_console.addr = getcomaddr(iodev - CONSDEV_COM0);
143 if(!btinfo_console.addr) goto nocom;
144 cominit(SERIAL_ARG);
145 break;
146 default:
147 nocom:
148 iodev = CONSDEV_PC;
149 break;
150 }
151 strncpy(btinfo_console.devname, iodev == CONSDEV_PC ? "pc" : "com", 16);
152 #if defined(DIRECT_SERIAL) && defined(CONSPEED)
153 btinfo_console.speed = CONSPEED;
154 #else
155 btinfo_console.speed = 9600;
156 #endif
157 #else /* !SUPPORT_SERIAL */
158 strncpy(btinfo_console.devname, "pc", 16);
159 #endif /* SUPPORT_SERIAL */
160 }
161
162 static inline void
163 internal_putchar(c)
164 int c;
165 {
166 #ifdef SUPPORT_SERIAL
167 switch (iodev) {
168 case CONSDEV_PC:
169 #endif
170 conputc(c);
171 #ifdef SUPPORT_SERIAL
172 break;
173 case CONSDEV_COM0:
174 case CONSDEV_COM1:
175 case CONSDEV_COM2:
176 case CONSDEV_COM3:
177 computc(c, SERIAL_ARG);
178 break;
179 }
180 #endif
181 }
182
183 void
184 putchar(c)
185 int c;
186 {
187 if (c == '\n')
188 internal_putchar('\r');
189 internal_putchar(c);
190 }
191
192 int
193 getchar()
194 {
195 #ifdef SUPPORT_SERIAL
196 switch (iodev) {
197 default: /* to make gcc -Wall happy... */
198 case CONSDEV_PC:
199 #endif
200 return (congetc());
201 #ifdef SUPPORT_SERIAL
202 case CONSDEV_COM0:
203 case CONSDEV_COM1:
204 case CONSDEV_COM2:
205 case CONSDEV_COM3:
206 return (comgetc(SERIAL_ARG));
207 }
208 #endif
209 }
210
211 int
212 iskey()
213 {
214 #ifdef SUPPORT_SERIAL
215 switch (iodev) {
216 default: /* to make gcc -Wall happy... */
217 case CONSDEV_PC:
218 #endif
219 return (coniskey());
220 #ifdef SUPPORT_SERIAL
221 case CONSDEV_COM0:
222 case CONSDEV_COM1:
223 case CONSDEV_COM2:
224 case CONSDEV_COM3:
225 #ifdef DIRECT_SERIAL
226 return(!!comstatus_d(SERIAL_ARG));
227 #else
228 return (!!(comstatus(SERIAL_ARG) & 0x0100));
229 #endif
230 }
231 #endif /* SUPPORT_SERIAL */
232 }
233
234 char
235 awaitkey(timeout, tell)
236 int timeout, tell;
237 {
238 int i;
239 char c = 0;
240
241 i = timeout * POLL_FREQ;
242
243 while (i) {
244 if (tell && (i % POLL_FREQ) == 0)
245 printf("%d\b", i/POLL_FREQ);
246 if (iskey()) {
247 /* flush input buffer */
248 while (iskey())
249 c = getchar();
250 goto out; /* XXX what happens if c == 0? */
251 }
252 delay(1000000 / POLL_FREQ);
253 i--;
254 }
255
256 out:
257 if (tell)
258 printf("0\n");
259
260 return(c);
261 }
262