Fix usage of .Fa, .Fn, .Vt, .Dv, .Sy...
[dragonfly.git] / usr.bin / doscmd / tty.c
blob6f000118458ac536a30ddd500e849c0394a4a6d2
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, int cond, void *arg, 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, regcontext_t *REGS)
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, regcontext_t *REGS)
975 #ifndef NO_X
976 int int9 = 0;
978 if (!(cond & AS_RD))
979 return;
981 for (;;) {
982 int x;
983 fd_set fdset;
984 XEvent ev;
985 static struct timeval tv;
988 * Handle any events just sitting around...
990 XFlush(dpy);
991 while (QLength(dpy) > 0) {
992 XNextEvent(dpy, &ev);
993 int9 |= video_event(&ev);
996 FD_ZERO(&fdset);
997 FD_SET(fd, &fdset);
999 x = select(FD_SETSIZE, &fdset, 0, 0, &tv);
1001 switch (x) {
1002 case -1:
1004 * Errno might be wrong, so we just select again.
1005 * This could cause a problem is something really
1006 * was wrong with select....
1008 perror("select");
1009 return;
1010 case 0:
1011 XFlush(dpy);
1012 if (int9)
1013 hardint(0x01);
1014 return;
1015 default:
1016 if (FD_ISSET(fd, &fdset)) {
1017 do {
1018 XNextEvent(dpy, &ev);
1019 int9 |= video_event(&ev);
1020 } while (QLength(dpy));
1022 break;
1025 #endif
1028 #ifndef NO_X
1029 static int
1030 video_event(XEvent *ev)
1032 switch (ev->type) {
1033 case MotionNotify: {
1034 XMotionEvent *me = (XMotionEvent *)ev;
1035 me->x -= 2;
1036 me->y -= 2;
1038 mouse_status.x = (me->x < mouse_status.range.x)
1039 ? mouse_status.range.x
1040 : (me->x > mouse_status.range.w)
1041 ? mouse_status.range.w : me->x;
1042 mouse_status.y = (me->y < mouse_status.range.y)
1043 ? mouse_status.range.y
1044 : (me->y > mouse_status.range.h)
1045 ? mouse_status.range.h : me->y;
1046 break;
1048 case ButtonRelease: {
1049 XButtonEvent *be = (XButtonEvent *)ev;
1050 be->x -= 2;
1051 be->y -= 2;
1053 if (be->button < 3)
1054 mouse_status.ups[be->button]++;
1056 mouse_status.x = (be->x < mouse_status.range.x)
1057 ? mouse_status.range.x
1058 : (be->x > mouse_status.range.w)
1059 ? mouse_status.range.w : be->x;
1060 mouse_status.y = (be->y < mouse_status.range.y)
1061 ? mouse_status.range.y
1062 : (be->y > mouse_status.range.h)
1063 ? mouse_status.range.h : be->y;
1064 break;
1066 case ButtonPress: {
1067 XButtonEvent *be = (XButtonEvent *)ev;
1068 be->x -= 2;
1069 be->y -= 2;
1071 if (be->button < 3)
1072 mouse_status.downs[be->button]++;
1074 mouse_status.x = (be->x < mouse_status.range.x)
1075 ? mouse_status.range.x
1076 : (be->x > mouse_status.range.w)
1077 ? mouse_status.range.w : be->x;
1078 mouse_status.y = (be->y < mouse_status.range.y)
1079 ? mouse_status.range.y
1080 : (be->y > mouse_status.range.h)
1081 ? mouse_status.range.h : be->y;
1083 if ((K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1084 quit(0);
1086 break;
1088 case NoExpose:
1089 break;
1090 case GraphicsExpose:
1091 case Expose: {
1092 int r;
1093 for (r = 0; r < height; ++r)
1094 lines[r].changed = 1;
1095 break;
1097 case KeyRelease: {
1098 static char buf[128];
1099 KeySym ks;
1101 break_code |= 0x80;
1103 if (!(ev->xkey.state & ShiftMask)) {
1104 K1_STATUS &= ~K1_LSHIFT;
1105 K1_STATUS &= ~K1_RSHIFT;
1107 if (!(ev->xkey.state & ControlMask)) {
1108 K1_STATUS &= ~K1_CTRL;
1109 K2_STATUS &= ~K2_LCTRL;
1110 K3_STATUS &= ~K3_RCTRL;
1112 if (!(ev->xkey.state & Mod1Mask)) {
1113 K1_STATUS &= ~K1_ALT;
1114 K2_STATUS &= ~K2_LALT;
1115 K3_STATUS &= ~K3_RALT;
1117 if (!(ev->xkey.state & LockMask)) {
1118 K2_STATUS &= ~K2_CLOCK;
1121 XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1122 switch (ks) {
1123 case XK_Shift_L:
1124 K1_STATUS &= ~K1_LSHIFT;
1125 break;
1126 case XK_Shift_R:
1127 K1_STATUS &= ~K1_RSHIFT;
1128 break;
1129 case XK_Control_L:
1130 K1_STATUS &= ~K1_CTRL;
1131 K2_STATUS &= ~K2_LCTRL;
1132 break;
1133 case XK_Control_R:
1134 K1_STATUS &= ~K1_CTRL;
1135 K3_STATUS &= ~K3_RCTRL;
1136 break;
1137 case XK_Alt_L:
1138 K1_STATUS &= ~K1_ALT;
1139 K2_STATUS &= ~K2_LALT;
1140 break;
1141 case XK_Alt_R:
1142 K1_STATUS &= ~K1_ALT;
1143 K3_STATUS &= ~K3_RALT;
1144 break;
1145 case XK_Scroll_Lock:
1146 K2_STATUS &= ~K2_SLOCK;
1147 break;
1148 case XK_Num_Lock:
1149 K2_STATUS &= ~K2_NLOCK;
1150 break;
1151 case XK_Caps_Lock:
1152 K2_STATUS &= ~K2_CLOCK;
1153 break;
1154 case XK_Insert:
1155 K2_STATUS &= ~K2_INSERT;
1156 break;
1158 return(1);
1160 case KeyPress: {
1161 static char buf[128];
1162 KeySym ks;
1163 int n;
1164 int nlock = 0;
1165 u_short scan = 0xffff;
1167 if (!(ev->xkey.state & ShiftMask)) {
1168 K1_STATUS &= ~K1_LSHIFT;
1169 K1_STATUS &= ~K1_RSHIFT;
1171 if (!(ev->xkey.state & ControlMask)) {
1172 K1_STATUS &= ~K1_CTRL;
1173 K2_STATUS &= ~K2_LCTRL;
1174 K3_STATUS &= ~K3_RCTRL;
1176 if (!(ev->xkey.state & Mod1Mask)) {
1177 K1_STATUS &= ~K1_ALT;
1178 K2_STATUS &= ~K2_LALT;
1179 K3_STATUS &= ~K3_RALT;
1181 if (!(ev->xkey.state & LockMask)) {
1182 K2_STATUS &= ~K2_CLOCK;
1185 n = XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1187 switch (ks) {
1188 case XK_Shift_L:
1189 K1_STATUS |= K1_LSHIFT;
1190 break;
1191 case XK_Shift_R:
1192 K1_STATUS |= K1_RSHIFT;
1193 break;
1194 case XK_Control_L:
1195 K1_STATUS |= K1_CTRL;
1196 K2_STATUS |= K2_LCTRL;
1197 break;
1198 case XK_Control_R:
1199 K1_STATUS |= K1_CTRL;
1200 K3_STATUS |= K3_RCTRL;
1201 break;
1202 case XK_Alt_L:
1203 K1_STATUS |= K1_ALT;
1204 K2_STATUS |= K2_LALT;
1205 break;
1206 case XK_Alt_R:
1207 K1_STATUS |= K1_ALT;
1208 K3_STATUS |= K3_RALT;
1209 break;
1210 case XK_Scroll_Lock:
1211 K1_STATUS ^= K1_SLOCK;
1212 K2_STATUS |= K2_SLOCK;
1213 break;
1214 case XK_Num_Lock:
1215 K1_STATUS ^= K1_NLOCK;
1216 K2_STATUS |= K2_NLOCK;
1217 break;
1218 case XK_Caps_Lock:
1219 K1_STATUS ^= K1_CLOCK;
1220 K2_STATUS |= K2_CLOCK;
1221 break;
1222 case XK_Insert:
1223 case XK_KP_Insert:
1224 K1_STATUS ^= K1_INSERT;
1225 K2_STATUS |= K2_INSERT;
1226 scan = 82;
1227 goto docode;
1229 case XK_Escape:
1230 scan = 1;
1231 goto docode;
1233 case XK_Tab:
1234 case XK_ISO_Left_Tab:
1235 scan = 15;
1236 goto docode;
1238 case XK_Return:
1239 case XK_KP_Enter:
1240 scan = 28;
1241 goto docode;
1243 case XK_Print:
1244 scan = 55;
1245 goto docode;
1247 case XK_F1:
1248 case XK_F2:
1249 case XK_F3:
1250 case XK_F4:
1251 case XK_F5:
1252 case XK_F6:
1253 case XK_F7:
1254 case XK_F8:
1255 case XK_F9:
1256 case XK_F10:
1257 scan = ks - XK_F1 + 59;
1258 goto docode;
1260 case XK_KP_7:
1261 nlock = 1;
1262 case XK_Home:
1263 case XK_KP_Home:
1264 scan = 71;
1265 goto docode;
1266 case XK_KP_8:
1267 nlock = 1;
1268 case XK_Up:
1269 case XK_KP_Up:
1270 scan = 72;
1271 goto docode;
1272 case XK_KP_9:
1273 nlock = 1;
1274 case XK_Prior:
1275 case XK_KP_Prior:
1276 scan = 73;
1277 goto docode;
1278 case XK_KP_Subtract:
1279 scan = 74;
1280 goto docode;
1281 case XK_KP_4:
1282 nlock = 1;
1283 case XK_Left:
1284 case XK_KP_Left:
1285 scan = 75;
1286 goto docode;
1287 case XK_KP_5:
1288 nlock = 1;
1289 case XK_Begin:
1290 case XK_KP_Begin:
1291 scan = 76;
1292 goto docode;
1293 case XK_KP_6:
1294 nlock = 1;
1295 case XK_Right:
1296 case XK_KP_Right:
1297 scan = 77;
1298 goto docode;
1299 case XK_KP_Add:
1300 scan = 78;
1301 goto docode;
1302 case XK_KP_1:
1303 nlock = 1;
1304 case XK_End:
1305 case XK_KP_End:
1306 scan = 79;
1307 goto docode;
1308 case XK_KP_2:
1309 nlock = 1;
1310 case XK_Down:
1311 case XK_KP_Down:
1312 scan = 80;
1313 goto docode;
1314 case XK_KP_3:
1315 nlock = 1;
1316 case XK_Next:
1317 case XK_KP_Next:
1318 scan = 81;
1319 goto docode;
1320 case XK_KP_0:
1321 nlock = 1;
1322 /* case XK_Insert: This is above */
1323 scan = 82;
1324 goto docode;
1326 case XK_KP_Decimal:
1327 nlock = 1;
1328 scan = 83;
1329 goto docode;
1331 case XK_Delete:
1332 case XK_KP_Delete:
1333 scan = flipdelete ? 14 : 83;
1334 goto docode;
1336 case XK_BackSpace:
1337 scan = flipdelete ? 83 : 14;
1338 goto docode;
1340 case XK_F11:
1341 scan = 87;
1342 goto docode;
1343 case XK_F12:
1344 scan = 88;
1345 goto docode;
1348 case XK_KP_Divide:
1349 scan = Ascii2Scan['/'];
1350 goto docode;
1352 case XK_KP_Multiply:
1353 scan = Ascii2Scan['*'];
1354 goto docode;
1356 default:
1357 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1358 if (ks == 'T' || ks == 't') {
1359 tmode ^= 1;
1360 if (!tmode)
1361 resettrace((regcontext_t *)&saved_sigframe->
1362 sf_uc.uc_mcontext);
1363 break;
1365 if (ks == 'R' || ks == 'r') {
1366 kill(getpid(), SIGALRM); /* redraw */
1367 break;
1370 if (ks < ' ' || ks > '~')
1371 break;
1372 scan = Ascii2Scan[ks];
1373 docode:
1374 if (nlock)
1375 scan |= 0x100;
1377 if ((scan & ~0x100) > 88) {
1378 scan = 0xffff;
1379 break;
1382 if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
1383 scan = ScanCodes[scan & 0xff].shift;
1384 } else if (K1_STATUS & K1_CTRL) {
1385 scan = ScanCodes[scan & 0xff].ctrl;
1386 } else if (K1_STATUS & K1_ALT) {
1387 scan = ScanCodes[scan & 0xff].alt;
1388 } else
1389 scan = ScanCodes[scan & 0xff].base;
1391 break;
1393 if (scan != 0xffff) {
1394 break_code = scan >> 8;
1395 KbdWrite(scan);
1397 return(1);
1399 default:
1400 break;
1402 return(0);
1404 #endif
1406 void
1407 tty_move(int r, int c)
1409 row = r;
1410 col = c;
1411 SetVREGCur();
1414 void
1415 tty_report(int *r, int *c)
1417 *r = row;
1418 *c = col;
1421 void
1422 tty_flush(void)
1424 K_NEXT = K_FREE = K_BUFSTARTP;
1427 void
1428 tty_index(int scroll)
1430 int i;
1432 if (row > (height - 1))
1433 row = 0;
1434 else if (++row >= height) {
1435 row = height - 1;
1436 if (scroll) {
1437 memcpy(vmem, &vmem[width], 2 * width * (height - 1));
1438 for (i = 0; i < width; ++i)
1439 vmem[(height - 1) * width + i] = vattr | ' ';
1442 SetVREGCur();
1445 void
1446 tty_write(int c, int attr)
1448 if (attr == TTYF_REDIRECT) {
1449 if (redirect1) {
1450 write(1, &c, 1);
1451 return;
1453 attr = -1;
1455 if (capture_fd >= 0) {
1456 char cc = c;
1457 write(capture_fd, &cc, 1);
1459 c &= 0xff;
1460 switch (c) {
1461 case 0x07:
1462 if (xmode) {
1463 #ifndef NO_X
1464 XBell(dpy, 0);
1465 #endif
1466 } else
1467 write(1, "\007", 1);
1468 break;
1469 case 0x08:
1470 if (row > (height - 1) || col > width)
1471 break;
1472 if (col > 0)
1473 --col;
1474 vmem[row * width + col] &= 0xff00;
1475 break;
1476 case '\t':
1477 if (row > (height - 1))
1478 row = 0;
1479 col = (col + 8) & ~0x07;
1480 if (col > width) {
1481 col = 0;
1482 tty_index(1);
1484 break;
1485 case '\r':
1486 col = 0;
1487 break;
1488 case '\n':
1489 tty_index(1);
1490 break;
1491 default:
1492 if (col >= width) {
1493 col = 0;
1494 tty_index(1);
1496 if (row > (height - 1))
1497 row = 0;
1498 if (attr >= 0)
1499 vmem[row * width + col] = attr & 0xff00;
1500 else
1501 vmem[row * width + col] &= 0xff00;
1502 vmem[row * width + col++] |= c;
1503 break;
1505 SetVREGCur();
1508 void
1509 tty_rwrite(int n, int c, int attr)
1511 u_char srow, scol;
1512 c &= 0xff;
1514 #ifndef NO_X
1515 if (VGA_ATC[ATC_ModeCtrl] & 1) {
1516 tty_rwrite_graphics(n, c, attr);
1517 return;
1519 #endif
1521 srow = row;
1522 scol = col;
1523 while (n--) {
1524 if (col >= width) {
1525 col = 0;
1526 tty_index(0);
1528 if (row > (height - 1))
1529 row = 0;
1530 if (attr >= 0)
1531 vmem[row * width + col] = attr & 0xff00;
1532 else
1533 vmem[row * width + col] &= 0xff00;
1534 vmem[row * width + col++] |= c;
1536 row = srow;
1537 col = scol;
1538 SetVREGCur();
1541 #ifndef NO_X
1542 /* Write a character in graphics mode. Note that the text is put at *text*
1543 coordinates. */
1544 static void
1545 tty_rwrite_graphics(int n, int c, int attr)
1547 u_int8_t srow, scol;
1548 int ht = height / CharHeight;
1549 int wd = width / 8;
1551 srow = row;
1552 scol = col;
1554 while (n--) {
1555 if (col >= wd) {
1556 col = 0;
1557 /* tty_index(0); *//* scroll up if last line is filled */
1559 if (row > (ht - 1))
1560 row = 0;
1561 putchar_graphics(row * wd * CharHeight + col, c, attr);
1562 col++;
1564 row = srow;
1565 col = scol;
1566 SetVREGCur();
1568 return;
1571 /* Put the character together from its pixel representation in 'font8xXX[]'
1572 and write it to 'vram'. The attribute byte gives the desired color; if bit
1573 7 is set, the pixels are XOR'd with the underlying color(s).
1575 XXX This must be updated for the 256 color modes. */
1576 static void
1577 putchar_graphics(int xy, int c, int attr)
1579 int i, j;
1580 u_int8_t cline;
1581 u_int8_t *cpos;
1583 /* get char position in the pixel representation */
1584 cpos = (u_int8_t *)(0xC3000 + c * CharHeight);
1586 for (i = 0; i < CharHeight; i++) {
1587 cline = cpos[i];
1588 for (j = 0; j < 4; j++) {
1589 if (attr & 0x8000) {
1590 /* XOR */
1591 if (attr & (0x0100 << j))
1592 vram[xy + i * width / 8 + j * 0x10000] ^= cline;
1593 } else {
1594 /* replace */
1595 if (attr & (0x0100 << j))
1596 vram[xy + i * width / 8 + j * 0x10000] &= ~cline;
1597 else
1598 vram[xy + i * width / 8 + j * 0x10000] |= cline;
1603 return;
1605 #endif
1607 void tty_pause(void)
1609 sigset_t set;
1611 sigprocmask(0, 0, &set);
1612 sigdelset(&set, SIGIO);
1613 sigdelset(&set, SIGALRM);
1614 sigsuspend(&set);
1617 static int nextchar = 0;
1620 tty_read(REGISTERS, int flag)
1622 int r;
1624 if ((r = nextchar) != 0) {
1625 nextchar = 0;
1626 return(r & 0xff);
1629 if ((flag & TTYF_REDIRECT) && redirect0) {
1630 char c;
1631 if (read(STDIN_FILENO, &c, 1) != 1)
1632 return(-1);
1633 if (c == '\n')
1634 c = '\r';
1635 return(c);
1638 if (KbdEmpty()) {
1639 if (flag & TTYF_BLOCK) {
1640 while (KbdEmpty())
1641 tty_pause();
1642 } else {
1643 return(-1);
1647 r = KbdRead();
1648 if ((r & 0xff) == 0)
1649 nextchar = r >> 8;
1650 r &= 0xff;
1651 if (flag & TTYF_CTRL) {
1652 if (r == 3) {
1654 * XXX - Not quite sure where we should return, maybe not
1655 * all the way to the user, but...
1657 if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1658 fake_int(REGS, 0x23);
1659 R_EIP = R_EIP - 2;
1660 return(-2);
1664 if (flag & TTYF_ECHO) {
1665 if ((flag & TTYF_ECHONL) && (r == '\n' || r == '\r')) {
1666 tty_write('\r', -1);
1667 tty_write('\n', -1);
1668 } else
1669 tty_write(r, -1);
1671 return(r & 0xff);
1675 tty_peek(REGISTERS, int flag)
1677 int c;
1679 if (c == nextchar)
1680 return(nextchar & 0xff);
1682 if (KbdEmpty()) {
1683 if (flag & TTYF_POLL) {
1684 sleep_poll();
1685 if (KbdEmpty())
1686 return(0);
1687 } else if (flag & TTYF_BLOCK) {
1688 while (KbdEmpty())
1689 tty_pause();
1690 } else
1691 return(0);
1693 c = KbdPeek();
1694 if ((c & 0xff) == 3) {
1696 * XXX - Not quite sure where we should return, maybe not
1697 * all the way to the user, but...
1699 if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1700 fake_int(REGS, 0x23);
1701 R_EIP = R_EIP - 2;
1702 return(-2);
1705 return(0xff);
1709 tty_state(void)
1711 return(K1_STATUS);
1715 tty_estate(void)
1717 int state = 0;
1718 if (K2_STATUS & K2_SYSREQ)
1719 state |= 0x80;
1720 if (K2_STATUS & K2_CLOCK)
1721 state |= 0x40;
1722 if (K2_STATUS & K2_NLOCK)
1723 state |= 0x20;
1724 if (K2_STATUS & K2_SLOCK)
1725 state |= 0x10;
1726 if (K3_STATUS & K3_RALT)
1727 state |= 0x08;
1728 if (K3_STATUS & K3_RCTRL)
1729 state |= 0x04;
1730 if (K2_STATUS & K2_LALT)
1731 state |= 0x02;
1732 if (K2_STATUS & K2_LCTRL)
1733 state |= 0x01;
1734 return(state);
1737 static int
1738 inrange(int a, int n, int x)
1740 return(a < n ? n : a > x ? x : a);
1743 void
1744 tty_scroll(int sr, int sc, int er, int ec, int n, int attr)
1746 int i, j;
1748 sr = inrange(sr, 0, height);
1749 er = inrange(er, 0, height);
1750 sc = inrange(sc, 0, width);
1751 ec = inrange(ec, 0, width);
1752 if (sr > er || sc > ec)
1753 return;
1754 ++er;
1755 ++ec;
1757 attr &= 0xff00;
1758 attr |= ' ';
1760 if (n > 0 && n < er - sr) {
1761 for (j = sr; j < er - n; ) {
1762 memcpy(&vmem[j * width + sc],
1763 &vmem[(j + n) * width + sc],
1764 sizeof(vmem[0]) * (ec - sc));
1765 ++j;
1767 } else
1768 n = er - sr;
1769 for (j = er - n; j < er; ) {
1770 for (i = sc; i < ec; ++i)
1771 vmem[j * width + i] = attr;
1772 ++j;
1776 void
1777 tty_rscroll(int sr, int sc, int er, int ec, int n, int attr)
1779 int i, j;
1781 sr = inrange(sr, 0, height);
1782 er = inrange(er, 0, height);
1783 sc = inrange(sc, 0, width);
1784 ec = inrange(ec, 0, width);
1785 if (sr > er || sc > ec)
1786 return;
1787 ++er;
1788 ++ec;
1790 attr &= 0xff00;
1791 attr |= ' ';
1793 if (n > 0 && n < er - sr) {
1794 for (j = er; j > sr + n; ) {
1795 --j;
1796 memcpy(&vmem[j * width + sc],
1797 &vmem[(j - n) * width + sc],
1798 sizeof(vmem[0]) * (ec - sc));
1800 } else
1801 n = er - sr;
1802 for (j = sr + n; j > sr; ) {
1803 --j;
1804 for (i = sc; i < ec; ++i)
1805 vmem[j * width + i] = attr;
1810 tty_char(int r, int c)
1812 if (r == -1)
1813 r = row;
1814 if (c == -1)
1815 c = col;
1816 r = inrange(r, 0, height);
1817 c = inrange(c, 0, width);
1818 return(vmem[r * width + c]);
1822 KbdEmpty(void)
1824 return(K_NEXT == K_FREE);
1827 void
1828 KbdWrite(u_short code)
1830 int kf;
1832 kf = K_FREE + 2;
1833 if (kf == K_BUFENDP)
1834 kf = K_BUFSTARTP;
1836 if (kf == K_NEXT) {
1837 #ifndef NO_X
1838 XBell(dpy, 0);
1839 #endif
1840 return;
1842 K_BUF(K_FREE) = code;
1843 K_FREE = kf;
1846 u_short
1847 KbdRead(void)
1849 int kf = K_NEXT;
1851 K_NEXT = K_NEXT + 2;
1852 if (K_NEXT == K_BUFENDP)
1853 K_NEXT = K_BUFSTARTP;
1855 return(K_BUF(kf));
1858 u_short
1859 KbdPeek(void)
1861 return(K_BUF(K_NEXT));
1864 void
1865 kbd_init(void)
1867 u_long vec;
1869 define_input_port_handler(0x60, inb_port60);
1871 K_BUFSTARTP = 0x1e; /* Start of keyboard buffer */
1872 K_BUFENDP = 0x3e; /* End of keyboard buffer */
1873 K_NEXT = K_FREE = K_BUFSTARTP;
1875 vec = insert_hardint_trampoline();
1876 ivec[0x09] = vec;
1877 register_callback(vec, int09, "int 09");
1879 return;
1882 void
1883 kbd_bios_init(void)
1885 BIOSDATA[0x96] = 0x10; /* MF II kbd, 101 keys */
1886 K1_STATUS = 0;
1887 K2_STATUS = 0;
1888 K3_STATUS = 0;
1889 K4_STATUS = 0;
1892 #ifndef NO_X
1893 /* Calculate 16 bit RGB values for X from the 6 bit DAC values and the
1894 palette. This works for 16 and 256 color modes, although we don't really
1895 support the latter yet. */
1896 static void
1897 dac2rgb(XColor *color, int i)
1899 int n, m;
1901 /* 256 colors are easy; just take the RGB values from the DAC and
1902 shift left. For the pedants: multiplication with 65535./63. and
1903 rounding makes a difference of less than two percent. */
1904 if (VGA_ATC[ATC_ModeCtrl] & 0x40) {
1905 color->red = dac_rgb[i].red << 10;
1906 color->green = dac_rgb[i].green << 10;
1907 color->blue = dac_rgb[i].blue << 10;
1909 return;
1912 /* For the 16 color modes, check bit 7 of the Mode Control register in
1913 the ATC. If set, we take bits 0-3 of the Color Select register and
1914 bits 0-3 of the palette register 'i' to build the index into the
1915 DAC table; otherwise, bits 2 and 3 of the CS reg and bits 0-5 of
1916 the palette register are used. Note that the entries in 'palette[]'
1917 are supposed to be already masked to 6 bits. */
1918 if (VGA_ATC[ATC_ModeCtrl] & 0x80) {
1919 n = VGA_ATC[ATC_ColorSelect] & 0x0f;
1920 m = palette[i] & 0x0f;
1921 } else {
1922 n = VGA_ATC[ATC_ColorSelect] & 0x0c;
1923 m = palette[i];
1925 color->red = dac_rgb[16*n + m].red << 10;
1926 color->green = dac_rgb[16*n + m].green << 10;
1927 color->blue = dac_rgb[16*n + m].blue << 10;
1929 #endif
1931 /* Get a connection to the X server and create the window. */
1932 void
1933 init_window(void)
1935 #ifndef NO_X
1936 XGCValues gcv;
1937 int i;
1941 * Arg... I can no longer change X's fd out from under it.
1942 * Open up all the available fd's, leave 3 behind for X
1943 * to play with, open X and then release all the other fds
1945 int nfds = sysconf(_SC_OPEN_MAX);
1946 int *fds = malloc(sizeof(int) * nfds);
1947 i = 0;
1948 if (fds)
1949 for (i = 0; i < nfds && (i == 0 || fds[i-1] < 63); ++i)
1950 if ((fds[i] = open(_PATH_DEVNULL, 0)) < 0)
1951 break;
1953 * Leave 3 fds behind for X to play with
1955 if (i > 0) close(fds[--i]);
1956 if (i > 0) close(fds[--i]);
1957 if (i > 0) close(fds[--i]);
1959 dpy = XOpenDisplay(NULL);
1961 while (i > 0)
1962 close(fds[--i]);
1964 if (dpy == NULL)
1965 err(1, "Could not open display ``%s''\n", XDisplayName(NULL));
1966 xfd = ConnectionNumber(dpy);
1968 _RegisterIO(xfd, video_async_event, 0, Failure);
1969 if (debug_flags & D_DEBUGIN)
1970 _RegisterIO(0, debug_event, 0, Failure);
1972 /* Create window, but defer setting a size and GC. */
1973 win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
1974 1, 1, 2, black, black);
1976 gcv.foreground = white;
1977 gcv.background = black;
1978 gc = XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
1980 gcv.foreground = 1;
1981 gcv.background = 0;
1982 gcv.function = GXxor;
1983 cgc = XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1985 if (raw_kbd) {
1986 XSelectInput(dpy, win, ExposureMask | ButtonPressMask
1987 | ButtonReleaseMask | PointerMotionMask );
1988 } else {
1989 XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
1990 ExposureMask | ButtonPressMask
1991 | ButtonReleaseMask | PointerMotionMask );
1994 XStoreName(dpy, win, "DOS");
1996 /* Get the default visual and depth for later use. */
1997 depth = DefaultDepth(dpy, DefaultScreen(dpy));
1998 visual = DefaultVisual(dpy, DefaultScreen(dpy));
2000 prepare_lut();
2002 #if 0
2003 /* While we are developing the graphics code ... */
2004 call_on_quit(write_vram, NULL);
2005 #endif
2006 #endif
2009 void
2010 load_font(void)
2012 #ifndef NO_X
2013 XGCValues gcv;
2015 if (!xfont)
2016 xfont = FONTVGA;
2018 font = XLoadQueryFont(dpy, xfont);
2020 if (font == NULL)
2021 font = XLoadQueryFont(dpy, FONTVGA);
2023 if (font == NULL)
2024 err(1, "Could not open font ``%s''\n", xfont);
2026 gcv.font = font->fid;
2027 XChangeGC(dpy, gc, GCFont, &gcv);
2029 FW = font->max_bounds.width;
2030 FH = font->max_bounds.ascent + font->max_bounds.descent;
2031 FD = font->max_bounds.descent;
2033 /* Put the pixel representation at c000:3000. */
2034 switch (CharHeight) {
2035 case 8:
2036 memcpy((void *)0xc3000, font8x8, sizeof(font8x8));
2037 break;
2038 case 14:
2039 memcpy((void *)0xc3000, font8x14, sizeof(font8x14));
2040 break;
2041 case 16:
2042 memcpy((void *)0xc3000, font8x16, sizeof(font8x16));
2043 break;
2044 default:
2045 err(1, "load_font: CharHeight = %d?", CharHeight);
2048 return;
2049 #endif
2052 /* Get a new, or resize an old XImage as canvas for the graphics display. */
2053 void
2054 get_ximage(void)
2056 #ifndef NO_X
2057 if (xi != NULL)
2058 XFree(xi);
2060 xi = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL,
2061 width, height, 32, 0);
2062 if (xi == NULL)
2063 err(1, "Could not get ximage");
2065 xi->data = malloc(width * height * depth / 8);
2066 if (xi->data == NULL) {
2067 XDestroyImage(xi);
2068 err(1, "Could not get memory for ximage data");
2071 return;
2072 #endif
2075 /* Get memory for the text line buffer. */
2076 void
2077 get_lines(void)
2079 int i;
2081 if (lines == NULL) {
2082 lines = (TextLine *)malloc(sizeof(TextLine) * height);
2083 if (lines == NULL)
2084 err(1, "Could not allocate data structure for text lines\n");
2086 for (i = 0; i < height; ++i) {
2087 lines[i].max_length = width;
2088 lines[i].data = (u_short *)malloc(width * sizeof(u_short));
2089 if (lines[i].data == NULL)
2090 err(1, "Could not allocate data structure for text lines\n");
2091 lines[i].changed = 1;
2093 } else {
2094 lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
2095 if (lines == NULL)
2096 err(1, "Could not allocate data structure for text lines\n");
2098 for (i = 0; i < height; ++i) {
2099 lines[i].max_length = width;
2100 lines[i].data = (u_short *)realloc(lines[i].data,
2101 width * sizeof(u_short));
2102 if (lines[i].data == NULL)
2103 err(1, "Could not allocate data structure for text lines\n");
2104 lines[i].changed = 1;
2109 #ifndef NO_X
2110 /* Prepare the LUT for the VRAM -> XImage conversion. */
2111 static void
2112 prepare_lut(void)
2114 int i, j, k;
2116 for (i = 0; i < 4; i++) {
2117 for (j = 0; j < 256; j++) {
2118 for (k = 0; k < 8; k++) {
2119 lut[i][j][7 - k] = ((j & (1 << k)) ? (1 << i) : 0);
2124 return;
2126 #endif
2128 /* Resize the window, using information from 'vga_status[]'. This function is
2129 called after a mode change. */
2130 void
2131 resize_window(void)
2133 #ifndef NO_X
2134 XSizeHints *sh;
2135 vmode_t vmode;
2137 sh = XAllocSizeHints();
2138 if (sh == NULL)
2139 err(1, "Could not get XSizeHints structure");
2140 #endif
2142 width = DpyCols;
2143 height = DpyRows + 1;
2145 #ifndef NO_X
2146 vmode = vmodelist[find_vmode(VideoMode)];
2147 if (vmode.type == TEXT) {
2148 sh->base_width = FW * width + 4;
2149 sh->base_height = FH * height + 4;
2150 sh->base_width += 4;
2151 sh->base_height += 4;
2152 } else {
2153 width *= 8;
2154 height *= CharHeight;
2155 sh->base_width = width;
2156 sh->base_height = height;
2159 sh->min_width = sh->max_width = sh->base_width;
2160 sh->min_height = sh->max_height = sh->base_height;
2161 sh->flags = USSize | PMinSize | PMaxSize | PSize;
2163 debug(D_VIDEO, "VGA: Set window size %dx%d\n",
2164 sh->base_width, sh->base_height);
2166 XSetWMNormalHints(dpy, win, sh);
2167 XResizeWindow(dpy, win, sh->base_width, sh->base_height);
2168 XMapWindow(dpy, win);
2169 XFlush(dpy);
2171 XFree(sh);
2173 return;
2174 #endif
2177 /* Calculate 'pixels[]' from the current DAC table and palette.
2179 To do: do not use 'pixels[]', use an array of 'XColor's which we can
2180 allocate and free on demand. Install a private colormap if necessary. */
2181 void
2182 update_pixels(void)
2184 #ifndef NO_X
2185 int i;
2187 /* We support only 16 colors for now. */
2188 for (i = 0; i < 16; i++) {
2189 XColor color;
2191 dac2rgb(&color, i);
2192 if (XAllocColor(dpy,
2193 DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
2194 pixels[i] = color.pixel;
2195 } else if (i < 7)
2196 pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
2197 else
2198 pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
2200 #endif
2203 void
2204 write_vram(void *arg __unused)
2206 int fd;
2208 if ((fd = open("vram", O_WRONLY | O_CREAT, 0644)) == -1)
2209 err(1, "Can't open vram file");
2210 (void)write(fd, (void *)vram, 256 * 1024);
2212 return;