wbsio: support W83627UHG (0xa2); supported by lm(4) as W83627DHG (0xc1)
[dragonfly.git] / usr.bin / doscmd / port.c
blob579de4a6840946307153245e63904378f06de2db
1 /*
2 * Copyright (c) 1992, 1993, 1996
3 * Berkeley Software Design, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Berkeley Software
16 * Design, Inc.
18 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
30 * BSDI port.c,v 2.2 1996/04/08 19:33:03 bostic Exp
32 * $FreeBSD: src/usr.bin/doscmd/port.c,v 1.5.2.1 2002/04/25 11:04:51 tg Exp $
33 * $DragonFly: src/usr.bin/doscmd/port.c,v 1.6 2005/04/10 20:55:38 drhodus Exp $
36 #include <sys/ioctl.h>
37 #include <machine/sysarch.h>
39 #include "doscmd.h"
40 #include "tty.h"
42 #define MINPORT 0x000
43 #define MAXPORT_MASK (MAXPORT - 1)
45 #define in(port) \
46 ({ \
47 int _inb_result; \
49 asm volatile ("xorl %%eax,%%eax; inb %%dx,%%al" : \
50 "=a" (_inb_result) : "d" (port)); \
51 _inb_result; \
54 #define out(port, data) \
55 asm volatile ("outb %%al,%%dx" : : "a" (data), "d" (port))
57 FILE *iolog = 0;
58 u_long ioports[MAXPORT/32];
59 #ifdef __DragonFly__
60 static void
61 iomap(int port, int cnt)
63 if (port + cnt >= MAXPORT) {
64 errno = ERANGE;
65 goto bad;
67 if (i386_set_ioperm(port, cnt, 1) < 0) {
68 bad:
69 perror("iomap");
70 quit(1);
74 static void
75 iounmap(int port, int cnt)
77 if (port + cnt >= MAXPORT) {
78 errno = ERANGE;
79 goto bad;
81 if (i386_set_ioperm(port, cnt, 0) < 0) {
82 bad:
83 perror("iounmap");
84 quit(1);
87 #else
88 static void
89 iomap(int port, int cnt)
92 if (port + cnt >= MAXPORT) {
93 errno = ERANGE;
94 goto bad;
96 while (cnt--) {
97 ioports[port/32] |= (1 << (port%32));
98 port++;
100 if (i386_set_ioperm(ioports) < 0) {
101 bad:
102 perror("iomap");
103 quit(1);
107 static void
108 iounmap(int port, int cnt)
111 if (port + cnt >= MAXPORT) {
112 errno = ERANGE;
113 goto bad;
115 while (cnt--) {
116 ioports[port/32] &= ~(1 << (port%32));
117 port++;
119 if (i386_set_ioperm(ioports) < 0) {
120 bad:
121 perror("iounmap");
122 quit(1);
125 #endif
126 void
127 outb_traceport(int port, unsigned char byte)
130 if (!iolog && !(iolog = fopen("/tmp/iolog", "a")))
131 iolog = stderr;
133 fprintf(iolog, "0x%03X -> %02X\n", port, byte);
136 iomap(port, 1);
137 out(port, byte);
138 iounmap(port, 1);
141 unsigned char
142 inb_traceport(int port)
144 unsigned char byte;
147 if (!iolog && !(iolog = fopen("/tmp/iolog", "a")))
148 iolog = stderr;
151 iomap(port, 1);
152 byte = in(port);
153 iounmap(port, 1);
156 fprintf(iolog, "0x%03X <- %02X\n", port, byte);
157 fflush(iolog);
159 return(byte);
163 * Real input/output to (hopefully) iomapped port
165 void
166 outb_port(int port, unsigned char byte)
168 out(port, byte);
171 unsigned char
172 inb_port(int port)
174 return in(port);
178 * Fake input/output ports
181 static void
182 outb_nullport(int port __unused, unsigned char byte __unused)
185 debug(D_PORT, "outb_nullport called for port 0x%03X = 0x%02X.\n",
186 port, byte);
190 static unsigned char
191 inb_nullport(int port __unused)
194 debug(D_PORT, "inb_nullport called for port 0x%03X.\n", port);
196 return(0xff);
200 * configuration table for ports' emulators
203 struct portsw {
204 unsigned char (*p_inb)(int port);
205 void (*p_outb)(int port, unsigned char byte);
206 } portsw[MAXPORT];
208 void
209 init_io_port_handlers(void)
211 int i;
213 for (i = 0; i < MAXPORT; i++) {
214 if (portsw[i].p_inb == 0)
215 portsw[i].p_inb = inb_nullport;
216 if (portsw[i].p_outb == 0)
217 portsw[i].p_outb = outb_nullport;
222 void
223 define_input_port_handler(int port, unsigned char (*p_inb)(int port))
225 if ((port >= MINPORT) && (port < MAXPORT)) {
226 portsw[port].p_inb = p_inb;
227 } else
228 fprintf (stderr, "attempt to handle invalid port 0x%04x", port);
231 void
232 define_output_port_handler(int port, void (*p_outb)(int port, unsigned char byte))
234 if ((port >= MINPORT) && (port < MAXPORT)) {
235 portsw[port].p_outb = p_outb;
236 } else
237 fprintf (stderr, "attempt to handle invalid port 0x%04x", port);
241 void
242 inb(regcontext_t *REGS, int port)
244 unsigned char (*in_handler)(int);
246 if ((port >= MINPORT) && (port < MAXPORT))
247 in_handler = portsw[port].p_inb;
248 else
249 in_handler = inb_nullport;
250 R_AL = (*in_handler)(port);
251 debug(D_PORT, "IN on port %02x -> %02x\n", port, R_AL);
254 void
255 insb(regcontext_t *REGS, int port)
257 unsigned char (*in_handler)(int);
258 unsigned char data;
260 if ((port >= MINPORT) && (port < MAXPORT))
261 in_handler = portsw[port].p_inb;
262 else
263 in_handler = inb_nullport;
264 data = (*in_handler)(port);
265 *(u_char *)MAKEPTR(R_ES, R_DI) = data;
266 debug(D_PORT, "INS on port %02x -> %02x\n", port, data);
268 if (R_FLAGS & PSL_D)
269 R_DI--;
270 else
271 R_DI++;
274 void
275 inx(regcontext_t *REGS, int port)
277 unsigned char (*in_handler)(int);
279 if ((port >= MINPORT) && (port < MAXPORT))
280 in_handler = portsw[port].p_inb;
281 else
282 in_handler = inb_nullport;
283 R_AL = (*in_handler)(port);
284 if ((port >= MINPORT) && (port < MAXPORT))
285 in_handler = portsw[port + 1].p_inb;
286 else
287 in_handler = inb_nullport;
288 R_AH = (*in_handler)(port + 1);
289 debug(D_PORT, "IN on port %02x -> %04x\n", port, R_AX);
292 void
293 insx(regcontext_t *REGS, int port)
295 unsigned char (*in_handler)(int);
296 unsigned char data;
298 if ((port >= MINPORT) && (port < MAXPORT))
299 in_handler = portsw[port].p_inb;
300 else
301 in_handler = inb_nullport;
302 data = (*in_handler)(port);
303 *(u_char *)MAKEPTR(R_ES, R_DI) = data;
304 debug(D_PORT, "INS on port %02x -> %02x\n", port, data);
306 if ((port >= MINPORT) && (port < MAXPORT))
307 in_handler = portsw[port + 1].p_inb;
308 else
309 in_handler = inb_nullport;
310 data = (*in_handler)(port + 1);
311 ((u_char *)MAKEPTR(R_ES, R_DI))[1] = data;
312 debug(D_PORT, "INS on port %02x -> %02x\n", port, data);
314 if (R_FLAGS & PSL_D)
315 R_DI -= 2;
316 else
317 R_DI += 2;
320 void
321 outb(regcontext_t *REGS, int port)
323 void (*out_handler)(int, unsigned char);
325 if ((port >= MINPORT) && (port < MAXPORT))
326 out_handler = portsw[port].p_outb;
327 else
328 out_handler = outb_nullport;
329 (*out_handler)(port, R_AL);
330 debug(D_PORT, "OUT on port %02x <- %02x\n", port, R_AL);
332 if (port == 0x3bc && R_AL == 0x55)
333 tmode = 1;
337 void
338 outx(regcontext_t *REGS, int port)
340 void (*out_handler)(int, unsigned char);
342 if ((port >= MINPORT) && (port < MAXPORT))
343 out_handler = portsw[port].p_outb;
344 else
345 out_handler = outb_nullport;
346 (*out_handler)(port, R_AL);
347 debug(D_PORT, "OUT on port %02x <- %02x\n", port, R_AL);
348 if ((port >= MINPORT) && (port < MAXPORT))
349 out_handler = portsw[port + 1].p_outb;
350 else
351 out_handler = outb_nullport;
352 (*out_handler)(port + 1, R_AH);
353 debug(D_PORT, "OUT on port %02x <- %02x\n", port + 1, R_AH);
356 void
357 outsb(regcontext_t *REGS, int port)
359 void (*out_handler)(int, unsigned char);
360 unsigned char value;
362 if ((port >= MINPORT) && (port < MAXPORT))
363 out_handler = portsw[port].p_outb;
364 else
365 out_handler = outb_nullport;
366 value = *(u_char *)MAKEPTR(R_ES, R_DI);
367 debug(D_PORT, "OUT on port %02x <- %02x\n", port, value);
368 (*out_handler)(port, value);
370 if (R_FLAGS & PSL_D)
371 R_DI--;
372 else
373 R_DI++;
376 void
377 outsx(regcontext_t *REGS, int port)
379 void (*out_handler)(int, unsigned char);
380 unsigned char value;
382 if ((port >= MINPORT) && (port < MAXPORT))
383 out_handler = portsw[port].p_outb;
384 else
385 out_handler = outb_nullport;
386 value = *(u_char *)MAKEPTR(R_ES, R_DI);
387 debug(D_PORT, "OUT on port %02x <- %02x\n", port, value);
388 (*out_handler)(port, value);
390 if ((port >= MINPORT) && (port < MAXPORT))
391 out_handler = portsw[port + 1].p_outb;
392 else
393 out_handler = outb_nullport;
394 value = ((u_char *)MAKEPTR(R_ES, R_DI))[1];
395 debug(D_PORT, "OUT on port %02x <- %02x\n", port+1, value);
396 (*out_handler)(port + 1, value);
398 if (R_FLAGS & PSL_D)
399 R_DI -= 2;
400 else
401 R_DI += 2;
404 unsigned char port_61 = 0x10;
405 int sound_on = 1;
406 int sound_freq = 1000;
408 void
409 outb_speaker(int port __unused, unsigned char byte)
411 #if 0 /*XXXXX*/
412 if (raw_kbd) {
413 if ((port_61 & 3) != 3) {
414 if ((byte & 3) == 3 && /* prtim[2].gate && */ sound_on)
415 ioctl(kbd_fd, PCCONIOCSTARTBEEP, &sound_freq);
416 } else if ((byte & 3) != 3)
417 ioctl(kbd_fd, PCCONIOCSTOPBEEP);
419 #endif
420 port_61 = byte;
423 unsigned char
424 inb_speaker(int port __unused)
426 /* port_61 = (port_61 + 1) & 0xff; */
427 return(port_61);
430 void
431 speaker_init(void)
433 define_input_port_handler(0x61, inb_speaker);
434 define_output_port_handler(0x61, outb_speaker);