doscmd(1): Raise WARNS to 6 and silence all warnings.
[dragonfly.git] / usr.bin / doscmd / tty.c
blob09860d85b17d0977d809dc6343e74c5e50e718c5
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 tty.c,v 2.4 1996/04/08 22:03:27 prb Exp
32 * $FreeBSD: src/usr.bin/doscmd/tty.c,v 1.8.2.2 2002/04/25 11:04:51 tg Exp $
33 * $DragonFly: src/usr.bin/doscmd/tty.c,v 1.6 2004/01/26 18:16:18 drhodus Exp $
36 #include <sys/ioctl.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/mman.h>
40 #include <ctype.h>
41 #include <err.h>
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <paths.h>
45 #include <signal.h>
46 #include <stdio.h>
47 #include <termios.h>
48 #include <unistd.h>
49 #ifdef __DragonFly__
50 # include <osreldate.h>
51 # include <machine/console.h>
52 #endif
54 #ifndef NO_X
55 #include <X11/Xlib.h>
56 #include <X11/Xutil.h>
57 #include <X11/keysym.h>
58 #endif
60 #include "doscmd.h"
61 #include "AsyncIO.h"
62 #include "font8x8.h"
63 #include "font8x14.h"
64 #include "font8x16.h"
65 #include "mouse.h"
66 #include "trap.h"
67 #include "tty.h"
68 #include "video.h"
70 #ifndef NO_X
71 static int show = 1;
72 #endif
73 static int blink = 1;
74 int flipdelete = 0; /* Flip meaning of delete and backspace */
75 static u_short break_code = 0x00;
76 static u_short scan_code = 0x00;
77 int height;
78 int width;
79 int vattr;
80 const char *xfont = 0;
82 #ifndef NO_X
83 Display *dpy;
84 Window win;
85 XFontStruct *font;
86 XImage *xi = 0;
87 Visual *visual;
88 unsigned int depth;
89 unsigned long black;
90 unsigned long white;
91 int FW, FH, FD;
92 GC gc;
93 GC cgc;
94 int xfd;
96 /* LUT for the vram -> XImage conversion */
97 u_int8_t lut[4][256][8];
99 /* X pixel values for the RGB triples */
100 unsigned long pixels[16];
101 #endif
103 typedef struct TextLine {
104 u_short *data;
105 u_char max_length; /* Not used, but here for future use */
106 u_char changed:1;
107 } TextLine;
108 TextLine *lines = NULL;
110 int kbd_fd = -1;
111 int kbd_read = 0;
113 static struct termios tty_cook, tty_raw;
115 #define row (CursRow0)
116 #define col (CursCol0)
118 /* Local functions */
119 static void _kbd_event(int, int, void *, regcontext_t *);
120 static void Failure(void *);
121 static void SetVREGCur(void);
122 static void debug_event(int, int, void *, regcontext_t *);
123 static unsigned char inb_port60(int);
124 static int inrange(int, int, int);
125 static void kbd_event(int, int, void *, regcontext_t *);
126 static u_short read_raw_kbd(int, u_short *);
127 static void setgc(u_short);
128 static void video_async_event(int, int, void *, regcontext_t *);
130 #ifndef NO_X
131 static void dac2rgb(XColor *, int);
132 static void prepare_lut(void);
133 static void putchar_graphics(int, int, int);
134 static void tty_rwrite_graphics(int, int, int);
135 static int video_event(XEvent *ev);
136 static void video_update_graphics(void);
137 static void video_update_text(void);
138 static void vram2ximage(void);
139 #endif
141 #define PEEKSZ 16
143 #define K_NEXT *(u_short *)0x41a
144 #define K_FREE *(u_short *)0x41c
145 #define K_BUFSTARTP *(u_short *)0x480
146 #define K_BUFENDP *(u_short *)0x482
147 #define K_BUFSTART ((u_short *)(0x400 + *(u_short *)0x480))
148 #define K_BUFEND ((u_short *)(0x400 + *(u_short *)0x482))
149 #define K_BUF(i) *((u_short *)((u_char *)0x400 + (i)))
151 #define K1_STATUS BIOSDATA[0x17]
152 #define K1_RSHIFT 0x01
153 #define K1_LSHIFT 0x02
154 #define K1_SHIFT 0x03
155 #define K1_CTRL 0x04
156 #define K1_ALT 0x08
157 #define K1_SLOCK 0x10 /* Active */
158 #define K1_NLOCK 0x20 /* Active */
159 #define K1_CLOCK 0x40 /* Active */
160 #define K1_INSERT 0x80 /* Active */
162 #define K2_STATUS BIOSDATA[0x18]
163 #define K2_LCTRL 0x01
164 #define K2_LALT 0x02
165 #define K2_SYSREQ 0x04
166 #define K2_PAUSE 0x08
167 #define K2_SLOCK 0x10 /* Actually held down */
168 #define K2_NLOCK 0x20 /* Actually held down */
169 #define K2_CLOCK 0x40 /* Actually held down */
170 #define K2_INSERT 0x80 /* Actually held down */
172 #define K3_STATUS BIOSDATA[0x96]
173 #define K3_E1 0x01 /* Last code read was e1 */
174 #define K3_E2 0x02 /* Last code read was e2 */
175 #define K3_RCTRL 0x04
176 #define K3_RALT 0x08
177 #define K3_ENHANCED 0x10
178 #define K3_FORCENLOCK 0x20
179 #define K3_TWOBYTE 0x40 /* last code was first of 2 */
180 #define K3_READID 0x80 /* read ID in progress */
182 #define K4_STATUS BIOSDATA[0x97]
183 #define K4_SLOCK_LED 0x01
184 #define K4_NLOCK_LED 0x02
185 #define K4_CLOCK_LED 0x04
186 #define K4_ACK 0x10 /* ACK recieved from keyboard */
187 #define K4_RESEND 0x20 /* RESEND recieved from keyboard */
188 #define K4_LED 0x40 /* LED update in progress */
189 #define K4_ERROR 0x80
191 static void
192 Failure(void *arg __unused)
194 fprintf(stderr, "X Connection shutdown\n");
195 quit(1);
198 static void
199 SetVREGCur(void)
201 int cp = row * width + col;
202 VGA_CRTC[CRTC_CurLocHi] = cp >> 8;
203 VGA_CRTC[CRTC_CurLocLo] = cp & 0xff;
206 static void
207 console_denit(void *arg)
209 int fd = *(int *)arg;
211 #if defined (__DragonFly__)
212 if (ioctl(fd, KDSKBMODE, K_XLATE))
213 perror("KDSKBMODE/K_XLATE");
214 #else
215 # ifdef __NetBSD__
216 if (ioctl(fd, CONSOLE_X_MODE_OFF, 0))
217 perror("CONSOLE_X_MODE_OFF");
218 # else /* BSD/OS */
219 if (ioctl(fd, PCCONIOCCOOK, 0))
220 perror("PCCONIOCCOOK");
221 # endif
222 #endif
223 if (tcsetattr(fd, TCSANOW, &tty_cook))
224 perror("tcsetattr");
227 void
228 _kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
230 if (!(cond & AS_RD))
231 return;
232 printf("_kbd_event: fd=%d\n", fd);
233 kbd_read = 1;
236 void
237 console_init(void)
239 int fd;
240 caddr_t addr;
242 if ((fd = open(_PATH_DEV "vga", 2)) < 0) {
243 perror(_PATH_DEV "vga");
244 quit(1);
246 addr = mmap((caddr_t)0xA0000, 5 * 64 * 1024,
247 PROT_EXEC | PROT_READ | PROT_WRITE,
248 MAP_FILE | MAP_FIXED | MAP_SHARED,
249 fd, 0);
250 if (addr != (caddr_t)0xA0000) {
251 perror("mmap");
252 quit(1);
255 #if 0
256 addr = mmap((caddr_t)0x100000 - 0x1000, 0x1000,
257 PROT_EXEC | PROT_READ | PROT_WRITE,
258 MAP_FILE | MAP_FIXED | MAP_SHARED,
259 fd, 0);
260 if (addr != (caddr_t)(0x100000 - 0x1000)) {
261 perror("mmap");
262 quit(1);
264 #endif
266 if ((fd = open(_PATH_CONSOLE, 2)) < 0) {
267 perror(_PATH_CONSOLE);
268 quit(1);
271 fd = squirrel_fd(fd);
272 kbd_fd = fd;
274 #if defined (__DragonFly__)
275 if (ioctl(fd, KDSKBMODE, K_RAW)) {
276 perror("KDSKBMODE/K_RAW");
277 quit(1);
279 #else
280 # ifdef __NetBSD__
281 if (ioctl(fd, CONSOLE_X_MODE_ON, 0)) {
282 perror("CONSOLE_X_MODE_ON");
283 quit(1);
285 # else /* BSD/OS */
286 if (ioctl(fd, PCCONIOCRAW, 0)) {
287 perror("PCCONIOCRAW");
288 quit(1);
290 # endif
291 #endif
293 call_on_quit(console_denit, &kbd_fd);
295 if (fcntl(fd, F_SETFL, O_NDELAY|O_ASYNC) < 0) {
296 perror("fcntl");
297 quit(1);
299 if (tcgetattr(fd, &tty_cook)) {
300 perror("tcgetattr");
301 quit(1);
303 tty_raw = tty_cook;
304 cfmakeraw(&tty_raw);
305 if (tcsetattr(fd, TCSANOW, &tty_raw)) {
306 perror("tcsetattr");
307 quit(1);
310 #if 0
311 _RegisterIO(STDIN_FILENO, debug_event, 0, Failure);
312 _RegisterIO(fd, kbd_event, 0, Failure);
313 #endif
314 _RegisterIO(fd, _kbd_event, 0, Failure);
317 void
318 video_setborder(int color)
320 #ifndef NO_X
321 XSetWindowBackground(dpy, win, pixels[color & 0xf]);
322 #endif
324 void
325 video_blink(int mode)
327 blink = mode;
330 static void
331 setgc(u_short attr)
333 #ifndef NO_X
334 XGCValues v;
335 if (blink && !show && (attr & 0x8000))
336 v.foreground = pixels[(attr >> 12) & 0x07];
337 else
338 v.foreground = pixels[(attr >> 8) & 0x0f];
340 v.background = pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
341 XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
342 #endif
345 void
346 video_update(regcontext_t *REGS __unused)
348 #ifndef NO_X
349 static int icnt = 3;
351 if (kbd_read)
352 kbd_event(kbd_fd, AS_RD, 0, REGS);
354 if (--icnt == 0) {
355 icnt = 3;
357 lpt_poll(); /* Handle timeout on lpt code */
359 /* quick and dirty */
360 if (VGA_ATC[ATC_ModeCtrl] & 1)
361 video_update_graphics();
362 else
363 video_update_text();
365 #endif
368 #ifndef NO_X
369 static void
370 video_update_graphics(void)
372 vram2ximage();
374 XPutImage(dpy, win, DefaultGC(dpy, DefaultScreen(dpy)),
375 xi, 0, 0, 0, 0, width, height);
376 XFlush(dpy);
378 return;
381 static void
382 video_update_text(void)
384 static int or = -1;
385 static int oc = -1;
388 static char buf[256];
389 int r, c;
390 int attr = vmem[0] & 0xff00;
391 XGCValues v;
393 if (xmode) {
394 wakeup_poll(); /* Wake up anyone waiting on kbd poll */
396 show ^= 1;
398 setgc(attr);
400 for (r = 0; r < height; ++r) {
401 int cc = 0;
403 if (!lines[r].changed) {
404 if ((r == or || r == row) && (or != row || oc != col))
405 lines[r].changed = 1;
406 else {
407 for (c = 0; c < width; ++c) {
408 if (lines[r].data[c] != vmem[r * width + c]) {
409 lines[r].changed = 1;
410 break;
412 if (blink && lines[r].data[c] & 0x8000) {
413 lines[r].changed = 1;
414 break;
420 if (!lines[r].changed)
421 continue;
423 reset_poll();
424 lines[r].changed = 0;
425 memcpy(lines[r].data,
426 &vmem[r * width], sizeof(u_short) * width);
428 for (c = 0; c < width; ++c) {
429 int cv = vmem[r * width + c];
430 if ((cv & 0xff00) != attr) {
431 if (cc < c)
432 XDrawImageString(dpy, win, gc,
433 2 + cc * FW,
434 2 + (r + 1) * FH,
435 buf + cc, c - cc);
436 cc = c;
437 attr = cv & 0xff00;
438 setgc(attr);
440 buf[c] = (cv & 0xff) ? cv & 0xff : ' ';
442 if (cc < c) {
443 XDrawImageString(dpy, win, gc,
444 2 + cc * FW,
445 2 + (r + 1) * FH,
446 buf + cc, c - cc);
449 or = row;
450 oc = col;
452 if (CursStart <= CursEnd && CursEnd <= FH &&
453 show && row < height && col < width) {
455 attr = vmem[row * width + col] & 0xff00;
456 v.foreground = pixels[(attr >> 8) & 0x0f] ^
457 pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
458 if (v.foreground) {
459 v.function = GXxor;
460 } else {
461 v.foreground = pixels[7];
462 v.function = GXcopy;
464 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
465 XFillRectangle(dpy, win, cgc,
466 2 + col * FW,
467 2 + row * FH + CursStart + FD,
468 FW, CursEnd + 1 - CursStart);
471 if (mouse_status.installed && mouse_status.show) {
472 c = mouse_status.x / mouse_status.hmickey;
473 r = mouse_status.y / mouse_status.vmickey;
475 lines[r].changed = 1;
476 attr = vmem[r * width + c] & 0xff00;
477 v.foreground = pixels[(attr >> 8) & 0x0f] ^
478 pixels[(attr >> 12) & 0x0f];
479 if (v.foreground) {
480 v.function = GXxor;
481 } else {
482 v.foreground = pixels[7];
483 v.function = GXcopy;
485 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
486 XFillRectangle(dpy, win, cgc,
487 2 + c * FW,
488 2 + r * FH + 2,
489 FW, FH);
492 XFlush(dpy);
496 /* Convert the contents of the video RAM into an XImage.
498 Bugs: - The function is way too slow.
499 - It only works for the 16 color modes.
500 - It only works on 15/16-bit TrueColor visuals. */
501 static void
502 vram2ximage(void)
504 int i, x, y, yoffset;
505 u_int16_t *image = (u_int16_t *)xi->data;
507 yoffset = 0;
508 for (y = 0; y < height; y++) {
509 yoffset += width / 8;
510 for (x = 0; x < width; x += 8) {
511 int offset = yoffset + x / 8;
512 for (i = 0; i < 8; i++) {
513 int color = lut[0][vplane0[offset]][i] |
514 lut[1][vplane1[offset]][i] |
515 lut[2][vplane2[offset]][i] |
516 lut[3][vplane3[offset]][i];
517 *image++ = (u_int16_t)pixels[color];
522 return;
524 #endif
526 static u_short Ascii2Scan[] = {
527 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
528 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
529 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
530 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
531 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
532 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
533 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
534 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
535 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
536 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
537 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
538 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
539 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
540 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
541 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
542 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
545 struct {
546 u_short base;
547 u_short shift;
548 u_short ctrl;
549 u_short alt;
550 } ScanCodes[] = {
551 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */
552 { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */
553 { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */
554 { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */
555 { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */
556 { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */
557 { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */
558 { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */
559 { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */
560 { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */
561 { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
562 { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
563 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
564 { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
565 { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
566 { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
567 { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
568 { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
569 { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
570 { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
571 { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
572 { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
573 { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
574 { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
575 { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
576 { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
577 { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
578 { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
579 { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
580 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
581 { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
582 { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
583 { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
584 { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
585 { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
586 { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
587 { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
588 { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
589 { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
590 { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
591 { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
592 { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
593 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
594 { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
595 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
596 { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
597 { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
598 { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
599 { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
600 { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
601 { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
602 { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
603 { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
604 { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
605 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
606 { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
607 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
608 { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
609 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */
610 { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
611 { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
612 { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
613 { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
614 { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
615 { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
616 { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
617 { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
618 { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
619 { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
620 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
621 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */
622 { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
623 { 0x4800, 0x4838, 0xffff, 0xffff }, /* key 72 - cursor up */
624 { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
625 { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
626 { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
627 { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
628 { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
629 { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
630 { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
631 { 0x5000, 0x5032, 0xffff, 0xffff }, /* key 80 - cursor down */
632 { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
633 { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
634 { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
635 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
636 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
637 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
638 { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
639 { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
642 void
643 debug_event(int fd __unused, int cond, void *arg __unused, regcontext_t *REGS)
645 static char ibuf[1024];
646 static int icnt = 0;
647 static u_short ds = 0;
648 static u_short di = 0;
649 static u_short cnt = 16 * 8;
650 char *ep;
651 int r;
653 if (!(cond & AS_RD))
654 return;
656 r = read(STDIN_FILENO, ibuf + icnt, sizeof(ibuf) - icnt);
657 if (r <= 0)
658 return;
660 icnt += r;
662 ibuf[icnt] = 0;
663 while ((ep = strchr(ibuf, '\n')) != 0) {
664 int ac;
665 char *_av[16];
666 char **av;
668 *ep++ = 0;
669 ac = ParseBuffer(ibuf, av = _av, 16);
671 if (ac > 0) {
672 if (!strcasecmp(av[0], "dump")) {
673 if (ac > 1) {
674 char *c;
675 if ((c = strchr(av[1], ':')) != 0) {
676 ds = strtol(av[1], 0, 16);
677 di = strtol(c+1, 0, 16);
678 } else
679 di = strtol(av[1], 0, 16);
681 if (ac > 2)
682 cnt = strtol(av[2], 0, 0);
683 cnt = (cnt + 0xf) & ~0xf;
684 if (cnt == 0)
685 cnt = 0x10;
686 di &= ~0xf;
688 for (r = 0; r < cnt; r += 0x10, di = (di + 0x10) & 0xffff) {
689 int i;
690 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
692 printf("%04x:%04x:", ds, di);
693 for (i = 0; i < 8; ++i)
694 printf(" %02x", ap[i]);
695 printf(" ");
696 for (i = 8; i < 16; ++i)
697 printf(" %02x", ap[i]);
698 printf(": ");
699 for (i = 0; i < 8; ++i)
700 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
701 printf(" ");
702 for (i = 8; i < 16; ++i)
703 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
704 printf("\n");
706 } else if (!strcasecmp(av[0], "dis")) {
707 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
709 if (ac > 1) {
710 char *c;
711 if ((c = strchr(av[1], ':')) != 0) {
712 ds = strtol(av[1], 0, 16);
713 di = strtol(c+1, 0, 16);
714 } else
715 di = strtol(av[1], 0, 16);
717 if (ac > 2)
718 cnt = strtol(av[2], 0, 0);
720 for (r = 0; r < cnt; ++r) {
721 char buf[16];
722 int c = i386dis(ds, di, ap, buf, 0);
723 printf("%04x:%04x %s\n", ds, di, buf);
724 di += c;
725 ap += c;
727 } else if (!strcasecmp(av[0], "regs")) {
728 dump_regs(REGS);
729 } else if (!strcasecmp(av[0], "force")) {
730 char *p = av[1];
732 while ((p = *++av) != 0) {
733 while (*p) {
734 if (*p >= ' ' && *p <= '~')
735 KbdWrite(ScanCodes[Ascii2Scan[(int)*p] & 0xff].base);
736 ++p;
739 KbdWrite(ScanCodes[28].base);
740 } else if (!strcasecmp(av[0], "bell")) {
741 #ifndef NO_X
742 XBell(dpy, 0);
743 XFlush(dpy);
744 #endif
745 } else {
746 fprintf(stderr, "%s: unknown command\n", av[0]);
750 if (ep < ibuf + icnt) {
751 char *f = ep;
752 char *t = ibuf;
753 icnt -= ep - ibuf;
754 while (icnt--)
755 *t++ = *f++;
756 } else
757 icnt = 0;
758 ibuf[icnt] = 0;
762 unsigned char
763 inb_port60(int port __unused)
765 int r = break_code;
766 break_code = 0;
767 scan_code = 0xffff;
768 return(r);
771 void
772 kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
774 if (!(cond & AS_RD))
775 return;
777 kbd_read = 0;
779 printf("kbd_event: fd=%d\n", fd);
780 if ((break_code = read_raw_kbd(fd, &scan_code)) != 0xffff)
781 hardint(0x01);
784 void
785 int09(REGISTERS __unused)
787 if (raw_kbd) {
788 if (scan_code != 0xffff) {
789 KbdWrite(scan_code);
790 break_code = 0;
791 scan_code = 0xffff;
792 #if 0
793 kbd_event(kbd_fd, 0, sc, REGS);
794 #endif
797 send_eoi();
800 u_short
801 read_raw_kbd(int fd, u_short *code)
803 unsigned char c;
805 *code = 0xffff;
807 if (read(fd, &c, 1) == 1) {
808 if (c == 0xe0) {
809 K3_STATUS |= K3_TWOBYTE;
810 return(c);
812 switch (c) {
813 case 29: /* Control */
814 K1_STATUS |= K1_CTRL;
815 if (K3_STATUS & K3_TWOBYTE)
816 K3_STATUS |= K3_RCTRL;
817 else
818 K2_STATUS |= K2_LCTRL;
819 break;
820 case 29 | 0x80: /* Control */
821 K1_STATUS &= ~K1_CTRL;
822 if (K3_STATUS & K3_TWOBYTE)
823 K3_STATUS &= ~K3_RCTRL;
824 else
825 K2_STATUS &= ~K2_LCTRL;
826 break;
828 case 42: /* left shift */
829 K1_STATUS |= K1_LSHIFT;
830 break;
831 case 42 | 0x80: /* left shift */
832 K1_STATUS &= ~K1_LSHIFT;
833 break;
835 case 54: /* right shift */
836 K1_STATUS |= K1_RSHIFT;
837 break;
838 case 54 | 0x80: /* right shift */
839 K1_STATUS &= ~K1_RSHIFT;
840 break;
842 case 56: /* Alt */
843 K1_STATUS |= K1_ALT;
844 if (K3_STATUS & K3_TWOBYTE)
845 K3_STATUS |= K3_RALT;
846 else
847 K2_STATUS |= K2_LALT;
848 break;
849 case 56 | 0x80: /* Alt */
850 K1_STATUS &= ~K1_ALT;
851 if (K3_STATUS & K3_TWOBYTE)
852 K3_STATUS &= ~K3_RALT;
853 else
854 K2_STATUS &= ~K2_LALT;
855 break;
857 case 58: /* caps-lock */
858 K1_STATUS ^= K1_CLOCK;
859 if (K1_STATUS & K1_CLOCK)
860 K4_STATUS |= K4_CLOCK_LED;
861 else
862 K4_STATUS &= ~K4_CLOCK_LED;
863 K2_STATUS |= K2_CLOCK;
864 break;
865 case 58 | 0x80: /* caps-lock */
866 K2_STATUS &= ~K2_CLOCK;
867 break;
869 case 69: /* num-lock */
870 K1_STATUS ^= K1_NLOCK;
871 if (K1_STATUS & K1_NLOCK)
872 K4_STATUS |= K4_NLOCK_LED;
873 else
874 K4_STATUS &= ~K4_NLOCK_LED;
875 K2_STATUS |= K2_NLOCK;
876 break;
877 case 69 | 0x80: /* num-lock */
878 K2_STATUS &= ~K2_NLOCK;
879 break;
881 case 70: /* scroll-lock */
882 K1_STATUS ^= K1_SLOCK;
883 if (K1_STATUS & K1_SLOCK)
884 K4_STATUS |= K4_SLOCK_LED;
885 else
886 K4_STATUS &= ~K4_SLOCK_LED;
887 K2_STATUS |= K2_SLOCK;
888 break;
889 case 70 | 0x80: /* scroll-lock */
890 K2_STATUS &= ~K2_SLOCK;
891 break;
893 case 82: /* insert */
894 K1_STATUS ^= K1_INSERT;
895 K2_STATUS |= K2_INSERT;
896 break;
897 case 82 | 0x80: /* insert */
898 K2_STATUS &= ~K2_INSERT;
899 break;
903 #if 0 /*XXXXX*/
904 if ((K4_STATUS & 0x07) != oldled) {
905 oldled = K4_STATUS & 0x07;
906 ioctl (fd, PCCONIOCSETLED, &oldled);
908 #endif
910 if (c == 83 && (K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL))
911 quit(0);
913 if (c < 89) {
914 u_short scode;
916 if (K1_STATUS & K1_ALT) {
917 scode = ScanCodes[c].alt;
918 } else if (K1_STATUS & K1_CTRL) {
919 scode = ScanCodes[c].ctrl;
920 } else if (K1_STATUS & K1_SHIFT) {
921 scode = ScanCodes[c].shift;
922 } else {
923 scode = ScanCodes[c].base;
924 if (K1_STATUS & K1_CLOCK) {
925 if (islower(scode & 0xff)) {
926 scode = (scode & 0xff00) | toupper(scode & 0xff);
929 if ((K1_STATUS & K1_NLOCK) && (K3_STATUS & K3_TWOBYTE) == 0) {
930 switch (c) {
931 case 71: /* home */
932 case 72: /* cursor up */
933 case 73: /* page up */
934 case 75: /* cursor left */
935 case 76: /* center key */
936 case 77: /* cursor right */
937 case 79: /* end */
938 case 80: /* cursor down */
939 case 81: /* page down */
940 case 82: /* insert */
941 case 83: /* delete */
942 scode = ScanCodes[c].shift;
943 break;
947 *code = scode;
949 K3_STATUS &= ~K3_TWOBYTE;
950 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
951 switch (c) {
952 case 0x13: /* R */
953 kill(getpid(), SIGALRM); /* force redraw */
954 printf("FORCED REDRAW\n");
955 return(0xffff);
956 case 0x14: /* T */
957 tmode ^= 1;
958 if (!tmode)
959 resettrace((regcontext_t *)&saved_sigframe->
960 sf_uc.uc_mcontext);
961 return(0xffff);
962 case 0x53: /* DEL */
963 quit(0);
966 return(c);
967 } else {
968 return(0xffff);
972 void
973 video_async_event(int fd, int cond, void *arg __unused,
974 regcontext_t *REGS __unused)
976 #ifndef NO_X
977 int int9 = 0;
979 if (!(cond & AS_RD))
980 return;
982 for (;;) {
983 int x;
984 fd_set fdset;
985 XEvent ev;
986 static struct timeval tv;
989 * Handle any events just sitting around...
991 XFlush(dpy);
992 while (QLength(dpy) > 0) {
993 XNextEvent(dpy, &ev);
994 int9 |= video_event(&ev);
997 FD_ZERO(&fdset);
998 FD_SET(fd, &fdset);
1000 x = select(FD_SETSIZE, &fdset, 0, 0, &tv);
1002 switch (x) {
1003 case -1:
1005 * Errno might be wrong, so we just select again.
1006 * This could cause a problem is something really
1007 * was wrong with select....
1009 perror("select");
1010 return;
1011 case 0:
1012 XFlush(dpy);
1013 if (int9)
1014 hardint(0x01);
1015 return;
1016 default:
1017 if (FD_ISSET(fd, &fdset)) {
1018 do {
1019 XNextEvent(dpy, &ev);
1020 int9 |= video_event(&ev);
1021 } while (QLength(dpy));
1023 break;
1026 #endif
1029 #ifndef NO_X
1030 static int
1031 video_event(XEvent *ev)
1033 switch (ev->type) {
1034 case MotionNotify: {
1035 XMotionEvent *me = (XMotionEvent *)ev;
1036 me->x -= 2;
1037 me->y -= 2;
1039 mouse_status.x = (me->x < mouse_status.range.x)
1040 ? mouse_status.range.x
1041 : (me->x > mouse_status.range.w)
1042 ? mouse_status.range.w : me->x;
1043 mouse_status.y = (me->y < mouse_status.range.y)
1044 ? mouse_status.range.y
1045 : (me->y > mouse_status.range.h)
1046 ? mouse_status.range.h : me->y;
1047 break;
1049 case ButtonRelease: {
1050 XButtonEvent *be = (XButtonEvent *)ev;
1051 be->x -= 2;
1052 be->y -= 2;
1054 if (be->button < 3)
1055 mouse_status.ups[be->button]++;
1057 mouse_status.x = (be->x < mouse_status.range.x)
1058 ? mouse_status.range.x
1059 : (be->x > mouse_status.range.w)
1060 ? mouse_status.range.w : be->x;
1061 mouse_status.y = (be->y < mouse_status.range.y)
1062 ? mouse_status.range.y
1063 : (be->y > mouse_status.range.h)
1064 ? mouse_status.range.h : be->y;
1065 break;
1067 case ButtonPress: {
1068 XButtonEvent *be = (XButtonEvent *)ev;
1069 be->x -= 2;
1070 be->y -= 2;
1072 if (be->button < 3)
1073 mouse_status.downs[be->button]++;
1075 mouse_status.x = (be->x < mouse_status.range.x)
1076 ? mouse_status.range.x
1077 : (be->x > mouse_status.range.w)
1078 ? mouse_status.range.w : be->x;
1079 mouse_status.y = (be->y < mouse_status.range.y)
1080 ? mouse_status.range.y
1081 : (be->y > mouse_status.range.h)
1082 ? mouse_status.range.h : be->y;
1084 if ((K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1085 quit(0);
1087 break;
1089 case NoExpose:
1090 break;
1091 case GraphicsExpose:
1092 case Expose: {
1093 int r;
1094 for (r = 0; r < height; ++r)
1095 lines[r].changed = 1;
1096 break;
1098 case KeyRelease: {
1099 static char buf[128];
1100 KeySym ks;
1102 break_code |= 0x80;
1104 if (!(ev->xkey.state & ShiftMask)) {
1105 K1_STATUS &= ~K1_LSHIFT;
1106 K1_STATUS &= ~K1_RSHIFT;
1108 if (!(ev->xkey.state & ControlMask)) {
1109 K1_STATUS &= ~K1_CTRL;
1110 K2_STATUS &= ~K2_LCTRL;
1111 K3_STATUS &= ~K3_RCTRL;
1113 if (!(ev->xkey.state & Mod1Mask)) {
1114 K1_STATUS &= ~K1_ALT;
1115 K2_STATUS &= ~K2_LALT;
1116 K3_STATUS &= ~K3_RALT;
1118 if (!(ev->xkey.state & LockMask)) {
1119 K2_STATUS &= ~K2_CLOCK;
1122 XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1123 switch (ks) {
1124 case XK_Shift_L:
1125 K1_STATUS &= ~K1_LSHIFT;
1126 break;
1127 case XK_Shift_R:
1128 K1_STATUS &= ~K1_RSHIFT;
1129 break;
1130 case XK_Control_L:
1131 K1_STATUS &= ~K1_CTRL;
1132 K2_STATUS &= ~K2_LCTRL;
1133 break;
1134 case XK_Control_R:
1135 K1_STATUS &= ~K1_CTRL;
1136 K3_STATUS &= ~K3_RCTRL;
1137 break;
1138 case XK_Alt_L:
1139 K1_STATUS &= ~K1_ALT;
1140 K2_STATUS &= ~K2_LALT;
1141 break;
1142 case XK_Alt_R:
1143 K1_STATUS &= ~K1_ALT;
1144 K3_STATUS &= ~K3_RALT;
1145 break;
1146 case XK_Scroll_Lock:
1147 K2_STATUS &= ~K2_SLOCK;
1148 break;
1149 case XK_Num_Lock:
1150 K2_STATUS &= ~K2_NLOCK;
1151 break;
1152 case XK_Caps_Lock:
1153 K2_STATUS &= ~K2_CLOCK;
1154 break;
1155 case XK_Insert:
1156 K2_STATUS &= ~K2_INSERT;
1157 break;
1159 return(1);
1161 case KeyPress: {
1162 static char buf[128];
1163 KeySym ks;
1164 int n;
1165 int nlock = 0;
1166 u_short scan = 0xffff;
1168 if (!(ev->xkey.state & ShiftMask)) {
1169 K1_STATUS &= ~K1_LSHIFT;
1170 K1_STATUS &= ~K1_RSHIFT;
1172 if (!(ev->xkey.state & ControlMask)) {
1173 K1_STATUS &= ~K1_CTRL;
1174 K2_STATUS &= ~K2_LCTRL;
1175 K3_STATUS &= ~K3_RCTRL;
1177 if (!(ev->xkey.state & Mod1Mask)) {
1178 K1_STATUS &= ~K1_ALT;
1179 K2_STATUS &= ~K2_LALT;
1180 K3_STATUS &= ~K3_RALT;
1182 if (!(ev->xkey.state & LockMask)) {
1183 K2_STATUS &= ~K2_CLOCK;
1186 n = XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1188 switch (ks) {
1189 case XK_Shift_L:
1190 K1_STATUS |= K1_LSHIFT;
1191 break;
1192 case XK_Shift_R:
1193 K1_STATUS |= K1_RSHIFT;
1194 break;
1195 case XK_Control_L:
1196 K1_STATUS |= K1_CTRL;
1197 K2_STATUS |= K2_LCTRL;
1198 break;
1199 case XK_Control_R:
1200 K1_STATUS |= K1_CTRL;
1201 K3_STATUS |= K3_RCTRL;
1202 break;
1203 case XK_Alt_L:
1204 K1_STATUS |= K1_ALT;
1205 K2_STATUS |= K2_LALT;
1206 break;
1207 case XK_Alt_R:
1208 K1_STATUS |= K1_ALT;
1209 K3_STATUS |= K3_RALT;
1210 break;
1211 case XK_Scroll_Lock:
1212 K1_STATUS ^= K1_SLOCK;
1213 K2_STATUS |= K2_SLOCK;
1214 break;
1215 case XK_Num_Lock:
1216 K1_STATUS ^= K1_NLOCK;
1217 K2_STATUS |= K2_NLOCK;
1218 break;
1219 case XK_Caps_Lock:
1220 K1_STATUS ^= K1_CLOCK;
1221 K2_STATUS |= K2_CLOCK;
1222 break;
1223 case XK_Insert:
1224 case XK_KP_Insert:
1225 K1_STATUS ^= K1_INSERT;
1226 K2_STATUS |= K2_INSERT;
1227 scan = 82;
1228 goto docode;
1230 case XK_Escape:
1231 scan = 1;
1232 goto docode;
1234 case XK_Tab:
1235 case XK_ISO_Left_Tab:
1236 scan = 15;
1237 goto docode;
1239 case XK_Return:
1240 case XK_KP_Enter:
1241 scan = 28;
1242 goto docode;
1244 case XK_Print:
1245 scan = 55;
1246 goto docode;
1248 case XK_F1:
1249 case XK_F2:
1250 case XK_F3:
1251 case XK_F4:
1252 case XK_F5:
1253 case XK_F6:
1254 case XK_F7:
1255 case XK_F8:
1256 case XK_F9:
1257 case XK_F10:
1258 scan = ks - XK_F1 + 59;
1259 goto docode;
1261 case XK_KP_7:
1262 nlock = 1;
1263 case XK_Home:
1264 case XK_KP_Home:
1265 scan = 71;
1266 goto docode;
1267 case XK_KP_8:
1268 nlock = 1;
1269 case XK_Up:
1270 case XK_KP_Up:
1271 scan = 72;
1272 goto docode;
1273 case XK_KP_9:
1274 nlock = 1;
1275 case XK_Prior:
1276 case XK_KP_Prior:
1277 scan = 73;
1278 goto docode;
1279 case XK_KP_Subtract:
1280 scan = 74;
1281 goto docode;
1282 case XK_KP_4:
1283 nlock = 1;
1284 case XK_Left:
1285 case XK_KP_Left:
1286 scan = 75;
1287 goto docode;
1288 case XK_KP_5:
1289 nlock = 1;
1290 case XK_Begin:
1291 case XK_KP_Begin:
1292 scan = 76;
1293 goto docode;
1294 case XK_KP_6:
1295 nlock = 1;
1296 case XK_Right:
1297 case XK_KP_Right:
1298 scan = 77;
1299 goto docode;
1300 case XK_KP_Add:
1301 scan = 78;
1302 goto docode;
1303 case XK_KP_1:
1304 nlock = 1;
1305 case XK_End:
1306 case XK_KP_End:
1307 scan = 79;
1308 goto docode;
1309 case XK_KP_2:
1310 nlock = 1;
1311 case XK_Down:
1312 case XK_KP_Down:
1313 scan = 80;
1314 goto docode;
1315 case XK_KP_3:
1316 nlock = 1;
1317 case XK_Next:
1318 case XK_KP_Next:
1319 scan = 81;
1320 goto docode;
1321 case XK_KP_0:
1322 nlock = 1;
1323 /* case XK_Insert: This is above */
1324 scan = 82;
1325 goto docode;
1327 case XK_KP_Decimal:
1328 nlock = 1;
1329 scan = 83;
1330 goto docode;
1332 case XK_Delete:
1333 case XK_KP_Delete:
1334 scan = flipdelete ? 14 : 83;
1335 goto docode;
1337 case XK_BackSpace:
1338 scan = flipdelete ? 83 : 14;
1339 goto docode;
1341 case XK_F11:
1342 scan = 87;
1343 goto docode;
1344 case XK_F12:
1345 scan = 88;
1346 goto docode;
1349 case XK_KP_Divide:
1350 scan = Ascii2Scan['/'];
1351 goto docode;
1353 case XK_KP_Multiply:
1354 scan = Ascii2Scan['*'];
1355 goto docode;
1357 default:
1358 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1359 if (ks == 'T' || ks == 't') {
1360 tmode ^= 1;
1361 if (!tmode)
1362 resettrace((regcontext_t *)&saved_sigframe->
1363 sf_uc.uc_mcontext);
1364 break;
1366 if (ks == 'R' || ks == 'r') {
1367 kill(getpid(), SIGALRM); /* redraw */
1368 break;
1371 if (ks < ' ' || ks > '~')
1372 break;
1373 scan = Ascii2Scan[ks];
1374 docode:
1375 if (nlock)
1376 scan |= 0x100;
1378 if ((scan & ~0x100) > 88) {
1379 scan = 0xffff;
1380 break;
1383 if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
1384 scan = ScanCodes[scan & 0xff].shift;
1385 } else if (K1_STATUS & K1_CTRL) {
1386 scan = ScanCodes[scan & 0xff].ctrl;
1387 } else if (K1_STATUS & K1_ALT) {
1388 scan = ScanCodes[scan & 0xff].alt;
1389 } else
1390 scan = ScanCodes[scan & 0xff].base;
1392 break;
1394 if (scan != 0xffff) {
1395 break_code = scan >> 8;
1396 KbdWrite(scan);
1398 return(1);
1400 default:
1401 break;
1403 return(0);
1405 #endif
1407 void
1408 tty_move(int r, int c)
1410 row = r;
1411 col = c;
1412 SetVREGCur();
1415 void
1416 tty_report(int *r, int *c)
1418 *r = row;
1419 *c = col;
1422 void
1423 tty_flush(void)
1425 K_NEXT = K_FREE = K_BUFSTARTP;
1428 void
1429 tty_index(int scroll)
1431 int i;
1433 if (row > (height - 1))
1434 row = 0;
1435 else if (++row >= height) {
1436 row = height - 1;
1437 if (scroll) {
1438 memcpy(vmem, &vmem[width], 2 * width * (height - 1));
1439 for (i = 0; i < width; ++i)
1440 vmem[(height - 1) * width + i] = vattr | ' ';
1443 SetVREGCur();
1446 void
1447 tty_write(int c, int attr)
1449 if (attr == TTYF_REDIRECT) {
1450 if (redirect1) {
1451 write(1, &c, 1);
1452 return;
1454 attr = -1;
1456 if (capture_fd >= 0) {
1457 char cc = c;
1458 write(capture_fd, &cc, 1);
1460 c &= 0xff;
1461 switch (c) {
1462 case 0x07:
1463 if (xmode) {
1464 #ifndef NO_X
1465 XBell(dpy, 0);
1466 #endif
1467 } else
1468 write(1, "\007", 1);
1469 break;
1470 case 0x08:
1471 if (row > (height - 1) || col > width)
1472 break;
1473 if (col > 0)
1474 --col;
1475 vmem[row * width + col] &= 0xff00;
1476 break;
1477 case '\t':
1478 if (row > (height - 1))
1479 row = 0;
1480 col = (col + 8) & ~0x07;
1481 if (col > width) {
1482 col = 0;
1483 tty_index(1);
1485 break;
1486 case '\r':
1487 col = 0;
1488 break;
1489 case '\n':
1490 tty_index(1);
1491 break;
1492 default:
1493 if (col >= width) {
1494 col = 0;
1495 tty_index(1);
1497 if (row > (height - 1))
1498 row = 0;
1499 if (attr >= 0)
1500 vmem[row * width + col] = attr & 0xff00;
1501 else
1502 vmem[row * width + col] &= 0xff00;
1503 vmem[row * width + col++] |= c;
1504 break;
1506 SetVREGCur();
1509 void
1510 tty_rwrite(int n, int c, int attr)
1512 u_char srow, scol;
1513 c &= 0xff;
1515 #ifndef NO_X
1516 if (VGA_ATC[ATC_ModeCtrl] & 1) {
1517 tty_rwrite_graphics(n, c, attr);
1518 return;
1520 #endif
1522 srow = row;
1523 scol = col;
1524 while (n--) {
1525 if (col >= width) {
1526 col = 0;
1527 tty_index(0);
1529 if (row > (height - 1))
1530 row = 0;
1531 if (attr >= 0)
1532 vmem[row * width + col] = attr & 0xff00;
1533 else
1534 vmem[row * width + col] &= 0xff00;
1535 vmem[row * width + col++] |= c;
1537 row = srow;
1538 col = scol;
1539 SetVREGCur();
1542 #ifndef NO_X
1543 /* Write a character in graphics mode. Note that the text is put at *text*
1544 coordinates. */
1545 static void
1546 tty_rwrite_graphics(int n, int c, int attr)
1548 u_int8_t srow, scol;
1549 int ht = height / CharHeight;
1550 int wd = width / 8;
1552 srow = row;
1553 scol = col;
1555 while (n--) {
1556 if (col >= wd) {
1557 col = 0;
1558 /* tty_index(0); *//* scroll up if last line is filled */
1560 if (row > (ht - 1))
1561 row = 0;
1562 putchar_graphics(row * wd * CharHeight + col, c, attr);
1563 col++;
1565 row = srow;
1566 col = scol;
1567 SetVREGCur();
1569 return;
1572 /* Put the character together from its pixel representation in 'font8xXX[]'
1573 and write it to 'vram'. The attribute byte gives the desired color; if bit
1574 7 is set, the pixels are XOR'd with the underlying color(s).
1576 XXX This must be updated for the 256 color modes. */
1577 static void
1578 putchar_graphics(int xy, int c, int attr)
1580 int i, j;
1581 u_int8_t cline;
1582 u_int8_t *cpos;
1584 /* get char position in the pixel representation */
1585 cpos = (u_int8_t *)(0xC3000 + c * CharHeight);
1587 for (i = 0; i < CharHeight; i++) {
1588 cline = cpos[i];
1589 for (j = 0; j < 4; j++) {
1590 if (attr & 0x8000) {
1591 /* XOR */
1592 if (attr & (0x0100 << j))
1593 vram[xy + i * width / 8 + j * 0x10000] ^= cline;
1594 } else {
1595 /* replace */
1596 if (attr & (0x0100 << j))
1597 vram[xy + i * width / 8 + j * 0x10000] &= ~cline;
1598 else
1599 vram[xy + i * width / 8 + j * 0x10000] |= cline;
1604 return;
1606 #endif
1608 void tty_pause(void)
1610 sigset_t set;
1612 sigprocmask(0, 0, &set);
1613 sigdelset(&set, SIGIO);
1614 sigdelset(&set, SIGALRM);
1615 sigsuspend(&set);
1618 static int nextchar = 0;
1621 tty_read(REGISTERS, int flag)
1623 int r;
1625 if ((r = nextchar) != 0) {
1626 nextchar = 0;
1627 return(r & 0xff);
1630 if ((flag & TTYF_REDIRECT) && redirect0) {
1631 char c;
1632 if (read(STDIN_FILENO, &c, 1) != 1)
1633 return(-1);
1634 if (c == '\n')
1635 c = '\r';
1636 return(c);
1639 if (KbdEmpty()) {
1640 if (flag & TTYF_BLOCK) {
1641 while (KbdEmpty())
1642 tty_pause();
1643 } else {
1644 return(-1);
1648 r = KbdRead();
1649 if ((r & 0xff) == 0)
1650 nextchar = r >> 8;
1651 r &= 0xff;
1652 if (flag & TTYF_CTRL) {
1653 if (r == 3) {
1655 * XXX - Not quite sure where we should return, maybe not
1656 * all the way to the user, but...
1658 if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1659 fake_int(REGS, 0x23);
1660 R_EIP = R_EIP - 2;
1661 return(-2);
1665 if (flag & TTYF_ECHO) {
1666 if ((flag & TTYF_ECHONL) && (r == '\n' || r == '\r')) {
1667 tty_write('\r', -1);
1668 tty_write('\n', -1);
1669 } else
1670 tty_write(r, -1);
1672 return(r & 0xff);
1676 tty_peek(REGISTERS, int flag)
1678 int c = 0;
1680 if (c == nextchar)
1681 return(nextchar & 0xff);
1683 if (KbdEmpty()) {
1684 if (flag & TTYF_POLL) {
1685 sleep_poll();
1686 if (KbdEmpty())
1687 return(0);
1688 } else if (flag & TTYF_BLOCK) {
1689 while (KbdEmpty())
1690 tty_pause();
1691 } else
1692 return(0);
1694 c = KbdPeek();
1695 if ((c & 0xff) == 3) {
1697 * XXX - Not quite sure where we should return, maybe not
1698 * all the way to the user, but...
1700 if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1701 fake_int(REGS, 0x23);
1702 R_EIP = R_EIP - 2;
1703 return(-2);
1706 return(0xff);
1710 tty_state(void)
1712 return(K1_STATUS);
1716 tty_estate(void)
1718 int state = 0;
1719 if (K2_STATUS & K2_SYSREQ)
1720 state |= 0x80;
1721 if (K2_STATUS & K2_CLOCK)
1722 state |= 0x40;
1723 if (K2_STATUS & K2_NLOCK)
1724 state |= 0x20;
1725 if (K2_STATUS & K2_SLOCK)
1726 state |= 0x10;
1727 if (K3_STATUS & K3_RALT)
1728 state |= 0x08;
1729 if (K3_STATUS & K3_RCTRL)
1730 state |= 0x04;
1731 if (K2_STATUS & K2_LALT)
1732 state |= 0x02;
1733 if (K2_STATUS & K2_LCTRL)
1734 state |= 0x01;
1735 return(state);
1738 static int
1739 inrange(int a, int n, int x)
1741 return(a < n ? n : a > x ? x : a);
1744 void
1745 tty_scroll(int sr, int sc, int er, int ec, int n, int attr)
1747 int i, j;
1749 sr = inrange(sr, 0, height);
1750 er = inrange(er, 0, height);
1751 sc = inrange(sc, 0, width);
1752 ec = inrange(ec, 0, width);
1753 if (sr > er || sc > ec)
1754 return;
1755 ++er;
1756 ++ec;
1758 attr &= 0xff00;
1759 attr |= ' ';
1761 if (n > 0 && n < er - sr) {
1762 for (j = sr; j < er - n; ) {
1763 memcpy(&vmem[j * width + sc],
1764 &vmem[(j + n) * width + sc],
1765 sizeof(vmem[0]) * (ec - sc));
1766 ++j;
1768 } else
1769 n = er - sr;
1770 for (j = er - n; j < er; ) {
1771 for (i = sc; i < ec; ++i)
1772 vmem[j * width + i] = attr;
1773 ++j;
1777 void
1778 tty_rscroll(int sr, int sc, int er, int ec, int n, int attr)
1780 int i, j;
1782 sr = inrange(sr, 0, height);
1783 er = inrange(er, 0, height);
1784 sc = inrange(sc, 0, width);
1785 ec = inrange(ec, 0, width);
1786 if (sr > er || sc > ec)
1787 return;
1788 ++er;
1789 ++ec;
1791 attr &= 0xff00;
1792 attr |= ' ';
1794 if (n > 0 && n < er - sr) {
1795 for (j = er; j > sr + n; ) {
1796 --j;
1797 memcpy(&vmem[j * width + sc],
1798 &vmem[(j - n) * width + sc],
1799 sizeof(vmem[0]) * (ec - sc));
1801 } else
1802 n = er - sr;
1803 for (j = sr + n; j > sr; ) {
1804 --j;
1805 for (i = sc; i < ec; ++i)
1806 vmem[j * width + i] = attr;
1811 tty_char(int r, int c)
1813 if (r == -1)
1814 r = row;
1815 if (c == -1)
1816 c = col;
1817 r = inrange(r, 0, height);
1818 c = inrange(c, 0, width);
1819 return(vmem[r * width + c]);
1823 KbdEmpty(void)
1825 return(K_NEXT == K_FREE);
1828 void
1829 KbdWrite(u_short code)
1831 int kf;
1833 kf = K_FREE + 2;
1834 if (kf == K_BUFENDP)
1835 kf = K_BUFSTARTP;
1837 if (kf == K_NEXT) {
1838 #ifndef NO_X
1839 XBell(dpy, 0);
1840 #endif
1841 return;
1843 K_BUF(K_FREE) = code;
1844 K_FREE = kf;
1847 u_short
1848 KbdRead(void)
1850 int kf = K_NEXT;
1852 K_NEXT = K_NEXT + 2;
1853 if (K_NEXT == K_BUFENDP)
1854 K_NEXT = K_BUFSTARTP;
1856 return(K_BUF(kf));
1859 u_short
1860 KbdPeek(void)
1862 return(K_BUF(K_NEXT));
1865 void
1866 kbd_init(void)
1868 u_long vec;
1870 define_input_port_handler(0x60, inb_port60);
1872 K_BUFSTARTP = 0x1e; /* Start of keyboard buffer */
1873 K_BUFENDP = 0x3e; /* End of keyboard buffer */
1874 K_NEXT = K_FREE = K_BUFSTARTP;
1876 vec = insert_hardint_trampoline();
1877 ivec[0x09] = vec;
1878 register_callback(vec, int09, "int 09");
1880 return;
1883 void
1884 kbd_bios_init(void)
1886 BIOSDATA[0x96] = 0x10; /* MF II kbd, 101 keys */
1887 K1_STATUS = 0;
1888 K2_STATUS = 0;
1889 K3_STATUS = 0;
1890 K4_STATUS = 0;
1893 #ifndef NO_X
1894 /* Calculate 16 bit RGB values for X from the 6 bit DAC values and the
1895 palette. This works for 16 and 256 color modes, although we don't really
1896 support the latter yet. */
1897 static void
1898 dac2rgb(XColor *color, int i)
1900 int n, m;
1902 /* 256 colors are easy; just take the RGB values from the DAC and
1903 shift left. For the pedants: multiplication with 65535./63. and
1904 rounding makes a difference of less than two percent. */
1905 if (VGA_ATC[ATC_ModeCtrl] & 0x40) {
1906 color->red = dac_rgb[i].red << 10;
1907 color->green = dac_rgb[i].green << 10;
1908 color->blue = dac_rgb[i].blue << 10;
1910 return;
1913 /* For the 16 color modes, check bit 7 of the Mode Control register in
1914 the ATC. If set, we take bits 0-3 of the Color Select register and
1915 bits 0-3 of the palette register 'i' to build the index into the
1916 DAC table; otherwise, bits 2 and 3 of the CS reg and bits 0-5 of
1917 the palette register are used. Note that the entries in 'palette[]'
1918 are supposed to be already masked to 6 bits. */
1919 if (VGA_ATC[ATC_ModeCtrl] & 0x80) {
1920 n = VGA_ATC[ATC_ColorSelect] & 0x0f;
1921 m = palette[i] & 0x0f;
1922 } else {
1923 n = VGA_ATC[ATC_ColorSelect] & 0x0c;
1924 m = palette[i];
1926 color->red = dac_rgb[16*n + m].red << 10;
1927 color->green = dac_rgb[16*n + m].green << 10;
1928 color->blue = dac_rgb[16*n + m].blue << 10;
1930 #endif
1932 /* Get a connection to the X server and create the window. */
1933 void
1934 init_window(void)
1936 #ifndef NO_X
1937 XGCValues gcv;
1938 int i;
1942 * Arg... I can no longer change X's fd out from under it.
1943 * Open up all the available fd's, leave 3 behind for X
1944 * to play with, open X and then release all the other fds
1946 int nfds = sysconf(_SC_OPEN_MAX);
1947 int *fds = malloc(sizeof(int) * nfds);
1948 i = 0;
1949 if (fds)
1950 for (i = 0; i < nfds && (i == 0 || fds[i-1] < 63); ++i)
1951 if ((fds[i] = open(_PATH_DEVNULL, 0)) < 0)
1952 break;
1954 * Leave 3 fds behind for X to play with
1956 if (i > 0) close(fds[--i]);
1957 if (i > 0) close(fds[--i]);
1958 if (i > 0) close(fds[--i]);
1960 dpy = XOpenDisplay(NULL);
1962 while (i > 0)
1963 close(fds[--i]);
1965 if (dpy == NULL)
1966 err(1, "Could not open display ``%s''\n", XDisplayName(NULL));
1967 xfd = ConnectionNumber(dpy);
1969 _RegisterIO(xfd, video_async_event, 0, Failure);
1970 if (debug_flags & D_DEBUGIN)
1971 _RegisterIO(0, debug_event, 0, Failure);
1973 /* Create window, but defer setting a size and GC. */
1974 win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
1975 1, 1, 2, black, black);
1977 gcv.foreground = white;
1978 gcv.background = black;
1979 gc = XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
1981 gcv.foreground = 1;
1982 gcv.background = 0;
1983 gcv.function = GXxor;
1984 cgc = XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1986 if (raw_kbd) {
1987 XSelectInput(dpy, win, ExposureMask | ButtonPressMask
1988 | ButtonReleaseMask | PointerMotionMask );
1989 } else {
1990 XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
1991 ExposureMask | ButtonPressMask
1992 | ButtonReleaseMask | PointerMotionMask );
1995 XStoreName(dpy, win, "DOS");
1997 /* Get the default visual and depth for later use. */
1998 depth = DefaultDepth(dpy, DefaultScreen(dpy));
1999 visual = DefaultVisual(dpy, DefaultScreen(dpy));
2001 prepare_lut();
2003 #if 0
2004 /* While we are developing the graphics code ... */
2005 call_on_quit(write_vram, NULL);
2006 #endif
2007 #endif
2010 void
2011 load_font(void)
2013 #ifndef NO_X
2014 XGCValues gcv;
2016 if (!xfont)
2017 xfont = FONTVGA;
2019 font = XLoadQueryFont(dpy, xfont);
2021 if (font == NULL)
2022 font = XLoadQueryFont(dpy, FONTVGA);
2024 if (font == NULL)
2025 err(1, "Could not open font ``%s''\n", xfont);
2027 gcv.font = font->fid;
2028 XChangeGC(dpy, gc, GCFont, &gcv);
2030 FW = font->max_bounds.width;
2031 FH = font->max_bounds.ascent + font->max_bounds.descent;
2032 FD = font->max_bounds.descent;
2034 /* Put the pixel representation at c000:3000. */
2035 switch (CharHeight) {
2036 case 8:
2037 memcpy((void *)0xc3000, font8x8, sizeof(font8x8));
2038 break;
2039 case 14:
2040 memcpy((void *)0xc3000, font8x14, sizeof(font8x14));
2041 break;
2042 case 16:
2043 memcpy((void *)0xc3000, font8x16, sizeof(font8x16));
2044 break;
2045 default:
2046 err(1, "load_font: CharHeight = %d?", CharHeight);
2049 return;
2050 #endif
2053 /* Get a new, or resize an old XImage as canvas for the graphics display. */
2054 void
2055 get_ximage(void)
2057 #ifndef NO_X
2058 if (xi != NULL)
2059 XFree(xi);
2061 xi = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL,
2062 width, height, 32, 0);
2063 if (xi == NULL)
2064 err(1, "Could not get ximage");
2066 xi->data = malloc(width * height * depth / 8);
2067 if (xi->data == NULL) {
2068 XDestroyImage(xi);
2069 err(1, "Could not get memory for ximage data");
2072 return;
2073 #endif
2076 /* Get memory for the text line buffer. */
2077 void
2078 get_lines(void)
2080 int i;
2082 if (lines == NULL) {
2083 lines = (TextLine *)malloc(sizeof(TextLine) * height);
2084 if (lines == NULL)
2085 err(1, "Could not allocate data structure for text lines\n");
2087 for (i = 0; i < height; ++i) {
2088 lines[i].max_length = width;
2089 lines[i].data = (u_short *)malloc(width * sizeof(u_short));
2090 if (lines[i].data == NULL)
2091 err(1, "Could not allocate data structure for text lines\n");
2092 lines[i].changed = 1;
2094 } else {
2095 lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
2096 if (lines == NULL)
2097 err(1, "Could not allocate data structure for text lines\n");
2099 for (i = 0; i < height; ++i) {
2100 lines[i].max_length = width;
2101 lines[i].data = (u_short *)realloc(lines[i].data,
2102 width * sizeof(u_short));
2103 if (lines[i].data == NULL)
2104 err(1, "Could not allocate data structure for text lines\n");
2105 lines[i].changed = 1;
2110 #ifndef NO_X
2111 /* Prepare the LUT for the VRAM -> XImage conversion. */
2112 static void
2113 prepare_lut(void)
2115 int i, j, k;
2117 for (i = 0; i < 4; i++) {
2118 for (j = 0; j < 256; j++) {
2119 for (k = 0; k < 8; k++) {
2120 lut[i][j][7 - k] = ((j & (1 << k)) ? (1 << i) : 0);
2125 return;
2127 #endif
2129 /* Resize the window, using information from 'vga_status[]'. This function is
2130 called after a mode change. */
2131 void
2132 resize_window(void)
2134 #ifndef NO_X
2135 XSizeHints *sh;
2136 vmode_t vmode;
2138 sh = XAllocSizeHints();
2139 if (sh == NULL)
2140 err(1, "Could not get XSizeHints structure");
2141 #endif
2143 width = DpyCols;
2144 height = DpyRows + 1;
2146 #ifndef NO_X
2147 vmode = vmodelist[find_vmode(VideoMode)];
2148 if (vmode.type == TEXT) {
2149 sh->base_width = FW * width + 4;
2150 sh->base_height = FH * height + 4;
2151 sh->base_width += 4;
2152 sh->base_height += 4;
2153 } else {
2154 width *= 8;
2155 height *= CharHeight;
2156 sh->base_width = width;
2157 sh->base_height = height;
2160 sh->min_width = sh->max_width = sh->base_width;
2161 sh->min_height = sh->max_height = sh->base_height;
2162 sh->flags = USSize | PMinSize | PMaxSize | PSize;
2164 debug(D_VIDEO, "VGA: Set window size %dx%d\n",
2165 sh->base_width, sh->base_height);
2167 XSetWMNormalHints(dpy, win, sh);
2168 XResizeWindow(dpy, win, sh->base_width, sh->base_height);
2169 XMapWindow(dpy, win);
2170 XFlush(dpy);
2172 XFree(sh);
2174 return;
2175 #endif
2178 /* Calculate 'pixels[]' from the current DAC table and palette.
2180 To do: do not use 'pixels[]', use an array of 'XColor's which we can
2181 allocate and free on demand. Install a private colormap if necessary. */
2182 void
2183 update_pixels(void)
2185 #ifndef NO_X
2186 int i;
2188 /* We support only 16 colors for now. */
2189 for (i = 0; i < 16; i++) {
2190 XColor color;
2192 dac2rgb(&color, i);
2193 if (XAllocColor(dpy,
2194 DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
2195 pixels[i] = color.pixel;
2196 } else if (i < 7)
2197 pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
2198 else
2199 pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
2201 #endif
2204 void
2205 write_vram(void *arg __unused)
2207 int fd;
2209 if ((fd = open("vram", O_WRONLY | O_CREAT, 0644)) == -1)
2210 err(1, "Can't open vram file");
2211 (void)write(fd, (void *)vram, 256 * 1024);
2213 return;