Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.bin / doscmd / port.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1992, 1993, 1996
3 * Berkeley Software Design, Inc. All rights reserved.
4 *
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.
17 *
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.
29 *
30 * BSDI port.c,v 2.2 1996/04/08 19:33:03 bostic Exp
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: src/usr.bin/doscmd/port.c,v 1.5.2.1 2002/04/25 11:04:51 tg Exp $");
35
36#include <sys/ioctl.h>
37#include <machine/sysarch.h>
38
39#include "doscmd.h"
40#include "tty.h"
41
42#define MINPORT 0x000
43#define MAXPORT_MASK (MAXPORT - 1)
44
45#define in(port) \
46({ \
47 register int _inb_result; \
48\
49 asm volatile ("xorl %%eax,%%eax; inb %%dx,%%al" : \
50 "=a" (_inb_result) : "d" (port)); \
51 _inb_result; \
52})
53
54#define out(port, data) \
55 asm volatile ("outb %%al,%%dx" : : "a" (data), "d" (port))
56
57FILE *iolog = 0;
58u_long ioports[MAXPORT/32];
59#ifdef __FreeBSD__
60static void
61iomap(int port, int cnt)
62{
63 if (port + cnt >= MAXPORT) {
64 errno = ERANGE;
65 goto bad;
66 }
67 if (i386_set_ioperm(port, cnt, 1) < 0) {
68 bad:
69 perror("iomap");
70 quit(1);
71 }
72}
73
74static void
75iounmap(int port, int cnt)
76{
77 if (port + cnt >= MAXPORT) {
78 errno = ERANGE;
79 goto bad;
80 }
81 if (i386_set_ioperm(port, cnt, 0) < 0) {
82 bad:
83 perror("iounmap");
84 quit(1);
85 }
86}
87#else
88static void
89iomap(int port, int cnt)
90{
91
92 if (port + cnt >= MAXPORT) {
93 errno = ERANGE;
94 goto bad;
95 }
96 while (cnt--) {
97 ioports[port/32] |= (1 << (port%32));
98 port++;
99 }
100 if (i386_set_ioperm(ioports) < 0) {
101 bad:
102 perror("iomap");
103 quit(1);
104 }
105}
106
107static void
108iounmap(int port, int cnt)
109{
110
111 if (port + cnt >= MAXPORT) {
112 errno = ERANGE;
113 goto bad;
114 }
115 while (cnt--) {
116 ioports[port/32] &= ~(1 << (port%32));
117 port++;
118 }
119 if (i386_set_ioperm(ioports) < 0) {
120 bad:
121 perror("iounmap");
122 quit(1);
123 }
124}
125#endif
126void
127outb_traceport(int port, unsigned char byte)
128{
129/*
130 if (!iolog && !(iolog = fopen("/tmp/iolog", "a")))
131 iolog = stderr;
132
133 fprintf(iolog, "0x%03X -> %02X\n", port, byte);
134 */
135
136 iomap(port, 1);
137 out(port, byte);
138 iounmap(port, 1);
139}
140
141unsigned char
142inb_traceport(int port)
143{
144 unsigned char byte;
145
146/*
147 if (!iolog && !(iolog = fopen("/tmp/iolog", "a")))
148 iolog = stderr;
149 */
150
151 iomap(port, 1);
152 byte = in(port);
153 iounmap(port, 1);
154
155/*
156 fprintf(iolog, "0x%03X <- %02X\n", port, byte);
157 fflush(iolog);
158 */
159 return(byte);
160}
161
162/*
163 * Real input/output to (hopefully) iomapped port
164 */
165void
166outb_port(int port, unsigned char byte)
167{
168 out(port, byte);
169}
170
171unsigned char
172inb_port(int port)
173{
174 return in(port);
175}
176
177/*
178 * Fake input/output ports
179 */
180
181static void
182outb_nullport(int port __unused, unsigned char byte __unused)
183{
184/*
185 debug(D_PORT, "outb_nullport called for port 0x%03X = 0x%02X.\n",
186 port, byte);
187 */
188}
189
190static unsigned char
191inb_nullport(int port __unused)
192{
193/*
194 debug(D_PORT, "inb_nullport called for port 0x%03X.\n", port);
195 */
196 return(0xff);
197}
198
199/*
200 * configuration table for ports' emulators
201 */
202
203struct portsw {
204 unsigned char (*p_inb)(int port);
205 void (*p_outb)(int port, unsigned char byte);
206} portsw[MAXPORT];
207
208void
209init_io_port_handlers(void)
210{
211 int i;
212
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;
218 }
219
220}
221
222void
223define_input_port_handler(int port, unsigned char (*p_inb)(int port))
224{
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);
229}
230
231void
232define_output_port_handler(int port, void (*p_outb)(int port, unsigned char byte))
233{
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);
238}
239
240
241void
242inb(regcontext_t *REGS, int port)
243{
244 unsigned char (*in_handler)(int);
245
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);
252}
253
254void
255insb(regcontext_t *REGS, int port)
256{
257 unsigned char (*in_handler)(int);
258 unsigned char data;
259
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);
267
268 if (R_FLAGS & PSL_D)
269 R_DI--;
270 else
271 R_DI++;
272}
273
274void
275inx(regcontext_t *REGS, int port)
276{
277 unsigned char (*in_handler)(int);
278
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);
290}
291
292void
293insx(regcontext_t *REGS, int port)
294{
295 unsigned char (*in_handler)(int);
296 unsigned char data;
297
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);
305
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);
313
314 if (R_FLAGS & PSL_D)
315 R_DI -= 2;
316 else
317 R_DI += 2;
318}
319
320void
321outb(regcontext_t *REGS, int port)
322{
323 void (*out_handler)(int, unsigned char);
324
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);
331/*
332 if (port == 0x3bc && R_AL == 0x55)
333 tmode = 1;
334*/
335}
336
337void
338outx(regcontext_t *REGS, int port)
339{
340 void (*out_handler)(int, unsigned char);
341
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);
354}
355
356void
357outsb(regcontext_t *REGS, int port)
358{
359 void (*out_handler)(int, unsigned char);
360 unsigned char value;
361
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);
369
370 if (R_FLAGS & PSL_D)
371 R_DI--;
372 else
373 R_DI++;
374}
375
376void
377outsx(regcontext_t *REGS, int port)
378{
379 void (*out_handler)(int, unsigned char);
380 unsigned char value;
381
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);
389
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);
397
398 if (R_FLAGS & PSL_D)
399 R_DI -= 2;
400 else
401 R_DI += 2;
402}
403
404unsigned char port_61 = 0x10;
405int sound_on = 1;
406int sound_freq = 1000;
407
408void
409outb_speaker(int port __unused, unsigned char byte)
410{
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);
418 }
419#endif
420 port_61 = byte;
421}
422
423unsigned char
424inb_speaker(int port __unused)
425{
426/* port_61 = (port_61 + 1) & 0xff; */
427 return(port_61);
428}
429
430void
431speaker_init()
432{
433 define_input_port_handler(0x61, inb_speaker);
434 define_output_port_handler(0x61, outb_speaker);
435
436}