Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / doscmd / port.c
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  * $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.2 2003/06/17 04:29:26 dillon Exp $
34  */
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
57 FILE *iolog = 0;
58 u_long ioports[MAXPORT/32];
59 #ifdef __FreeBSD__
60 static void
61 iomap(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
74 static void
75 iounmap(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
88 static void
89 iomap(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
107 static void
108 iounmap(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
126 void
127 outb_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
141 unsigned char
142 inb_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  */
165 void
166 outb_port(int port, unsigned char byte)
167 {
168     out(port, byte);
169 }
170
171 unsigned char
172 inb_port(int port)
173 {
174     return in(port);
175 }
176
177 /* 
178  * Fake input/output ports
179  */
180
181 static void
182 outb_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
190 static unsigned char
191 inb_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
203 struct portsw {
204         unsigned char   (*p_inb)(int port);
205         void            (*p_outb)(int port, unsigned char byte);
206 } portsw[MAXPORT];
207
208 void
209 init_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
222 void
223 define_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
231 void
232 define_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
241 void
242 inb(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
254 void
255 insb(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
274 void
275 inx(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
292 void
293 insx(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
320 void
321 outb(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
337 void
338 outx(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
356 void
357 outsb(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
376 void
377 outsx(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
404 unsigned char port_61 = 0x10;
405 int sound_on = 1;
406 int sound_freq = 1000;
407
408 void
409 outb_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
423 unsigned char
424 inb_speaker(int port __unused)
425 {
426 /*    port_61 = (port_61 + 1) & 0xff; */
427     return(port_61);
428 }
429
430 void
431 speaker_init()
432 {
433     define_input_port_handler(0x61, inb_speaker);
434     define_output_port_handler(0x61, outb_speaker);
435
436 }