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