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
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
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
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>
38 #include <sys/types.h>
50 # include <osreldate.h>
51 # include <machine/console.h>
56 #include <X11/Xutil.h>
57 #include <X11/keysym.h>
74 int flipdelete = 0; /* Flip meaning of delete and backspace */
75 static u_short break_code = 0x00;
76 static u_short scan_code = 0x00;
80 const char *xfont = 0;
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];
103 typedef struct TextLine {
105 u_char max_length; /* Not used, but here for future use */
108 TextLine *lines = NULL;
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 *);
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);
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
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
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
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
192 Failure(void *arg __unused)
194 fprintf(stderr, "X Connection shutdown\n");
201 int cp = row * width + col;
202 VGA_CRTC[CRTC_CurLocHi] = cp >> 8;
203 VGA_CRTC[CRTC_CurLocLo] = cp & 0xff;
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");
216 if (ioctl(fd, CONSOLE_X_MODE_OFF, 0))
217 perror("CONSOLE_X_MODE_OFF");
219 if (ioctl(fd, PCCONIOCCOOK, 0))
220 perror("PCCONIOCCOOK");
223 if (tcsetattr(fd, TCSANOW, &tty_cook))
228 _kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
232 printf("_kbd_event: fd=%d\n", fd);
242 if ((fd = open(_PATH_DEV "vga", 2)) < 0) {
243 perror(_PATH_DEV "vga");
246 addr = mmap((caddr_t)0xA0000, 5 * 64 * 1024,
247 PROT_EXEC | PROT_READ | PROT_WRITE,
248 MAP_FILE | MAP_FIXED | MAP_SHARED,
250 if (addr != (caddr_t)0xA0000) {
256 addr = mmap((caddr_t)0x100000 - 0x1000, 0x1000,
257 PROT_EXEC | PROT_READ | PROT_WRITE,
258 MAP_FILE | MAP_FIXED | MAP_SHARED,
260 if (addr != (caddr_t)(0x100000 - 0x1000)) {
266 if ((fd = open(_PATH_CONSOLE, 2)) < 0) {
267 perror(_PATH_CONSOLE);
271 fd = squirrel_fd(fd);
274 #if defined (__DragonFly__)
275 if (ioctl(fd, KDSKBMODE, K_RAW)) {
276 perror("KDSKBMODE/K_RAW");
281 if (ioctl(fd, CONSOLE_X_MODE_ON, 0)) {
282 perror("CONSOLE_X_MODE_ON");
286 if (ioctl(fd, PCCONIOCRAW, 0)) {
287 perror("PCCONIOCRAW");
293 call_on_quit(console_denit, &kbd_fd);
295 if (fcntl(fd, F_SETFL, O_NDELAY|O_ASYNC) < 0) {
299 if (tcgetattr(fd, &tty_cook)) {
305 if (tcsetattr(fd, TCSANOW, &tty_raw)) {
311 _RegisterIO(STDIN_FILENO, debug_event, 0, Failure);
312 _RegisterIO(fd, kbd_event, 0, Failure);
314 _RegisterIO(fd, _kbd_event, 0, Failure);
318 video_setborder(int color)
321 XSetWindowBackground(dpy, win, pixels[color & 0xf]);
325 video_blink(int mode)
335 if (blink && !show && (attr & 0x8000))
336 v.foreground = pixels[(attr >> 12) & 0x07];
338 v.foreground = pixels[(attr >> 8) & 0x0f];
340 v.background = pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
341 XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
346 video_update(regcontext_t *REGS __unused)
352 kbd_event(kbd_fd, AS_RD, 0, REGS);
357 lpt_poll(); /* Handle timeout on lpt code */
359 /* quick and dirty */
360 if (VGA_ATC[ATC_ModeCtrl] & 1)
361 video_update_graphics();
370 video_update_graphics(void)
374 XPutImage(dpy, win, DefaultGC(dpy, DefaultScreen(dpy)),
375 xi, 0, 0, 0, 0, width, height);
382 video_update_text(void)
388 static char buf[256];
390 int attr = vmem[0] & 0xff00;
394 wakeup_poll(); /* Wake up anyone waiting on kbd poll */
400 for (r = 0; r < height; ++r) {
403 if (!lines[r].changed) {
404 if ((r == or || r == row) && (or != row || oc != col))
405 lines[r].changed = 1;
407 for (c = 0; c < width; ++c) {
408 if (lines[r].data[c] != vmem[r * width + c]) {
409 lines[r].changed = 1;
412 if (blink && lines[r].data[c] & 0x8000) {
413 lines[r].changed = 1;
420 if (!lines[r].changed)
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) {
432 XDrawImageString(dpy, win, gc,
440 buf[c] = (cv & 0xff) ? cv & 0xff : ' ';
443 XDrawImageString(dpy, win, gc,
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)];
461 v.foreground = pixels[7];
464 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
465 XFillRectangle(dpy, win, cgc,
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];
482 v.foreground = pixels[7];
485 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
486 XFillRectangle(dpy, win, cgc,
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. */
504 int i, x, y, yoffset;
505 u_int16_t *image = (u_int16_t *)xi->data;
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];
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,
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 */
643 debug_event(int fd __unused, int cond, void *arg __unused, regcontext_t *REGS)
645 static char ibuf[1024];
647 static u_short ds = 0;
648 static u_short di = 0;
649 static u_short cnt = 16 * 8;
656 r = read(STDIN_FILENO, ibuf + icnt, sizeof(ibuf) - icnt);
663 while ((ep = strchr(ibuf, '\n')) != 0) {
669 ac = ParseBuffer(ibuf, av = _av, 16);
672 if (!strcasecmp(av[0], "dump")) {
675 if ((c = strchr(av[1], ':')) != 0) {
676 ds = strtol(av[1], 0, 16);
677 di = strtol(c+1, 0, 16);
679 di = strtol(av[1], 0, 16);
682 cnt = strtol(av[2], 0, 0);
683 cnt = (cnt + 0xf) & ~0xf;
688 for (r = 0; r < cnt; r += 0x10, di = (di + 0x10) & 0xffff) {
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]);
696 for (i = 8; i < 16; ++i)
697 printf(" %02x", ap[i]);
699 for (i = 0; i < 8; ++i)
700 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
702 for (i = 8; i < 16; ++i)
703 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
706 } else if (!strcasecmp(av[0], "dis")) {
707 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
711 if ((c = strchr(av[1], ':')) != 0) {
712 ds = strtol(av[1], 0, 16);
713 di = strtol(c+1, 0, 16);
715 di = strtol(av[1], 0, 16);
718 cnt = strtol(av[2], 0, 0);
720 for (r = 0; r < cnt; ++r) {
722 int c = i386dis(ds, di, ap, buf, 0);
723 printf("%04x:%04x %s\n", ds, di, buf);
727 } else if (!strcasecmp(av[0], "regs")) {
729 } else if (!strcasecmp(av[0], "force")) {
732 while ((p = *++av) != 0) {
734 if (*p >= ' ' && *p <= '~')
735 KbdWrite(ScanCodes[Ascii2Scan[(int)*p] & 0xff].base);
739 KbdWrite(ScanCodes[28].base);
740 } else if (!strcasecmp(av[0], "bell")) {
746 fprintf(stderr, "%s: unknown command\n", av[0]);
750 if (ep < ibuf + icnt) {
763 inb_port60(int port __unused)
772 kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
779 printf("kbd_event: fd=%d\n", fd);
780 if ((break_code = read_raw_kbd(fd, &scan_code)) != 0xffff)
785 int09(REGISTERS __unused)
788 if (scan_code != 0xffff) {
793 kbd_event(kbd_fd, 0, sc, REGS);
801 read_raw_kbd(int fd, u_short *code)
807 if (read(fd, &c, 1) == 1) {
809 K3_STATUS |= K3_TWOBYTE;
813 case 29: /* Control */
814 K1_STATUS |= K1_CTRL;
815 if (K3_STATUS & K3_TWOBYTE)
816 K3_STATUS |= K3_RCTRL;
818 K2_STATUS |= K2_LCTRL;
820 case 29 | 0x80: /* Control */
821 K1_STATUS &= ~K1_CTRL;
822 if (K3_STATUS & K3_TWOBYTE)
823 K3_STATUS &= ~K3_RCTRL;
825 K2_STATUS &= ~K2_LCTRL;
828 case 42: /* left shift */
829 K1_STATUS |= K1_LSHIFT;
831 case 42 | 0x80: /* left shift */
832 K1_STATUS &= ~K1_LSHIFT;
835 case 54: /* right shift */
836 K1_STATUS |= K1_RSHIFT;
838 case 54 | 0x80: /* right shift */
839 K1_STATUS &= ~K1_RSHIFT;
844 if (K3_STATUS & K3_TWOBYTE)
845 K3_STATUS |= K3_RALT;
847 K2_STATUS |= K2_LALT;
849 case 56 | 0x80: /* Alt */
850 K1_STATUS &= ~K1_ALT;
851 if (K3_STATUS & K3_TWOBYTE)
852 K3_STATUS &= ~K3_RALT;
854 K2_STATUS &= ~K2_LALT;
857 case 58: /* caps-lock */
858 K1_STATUS ^= K1_CLOCK;
859 if (K1_STATUS & K1_CLOCK)
860 K4_STATUS |= K4_CLOCK_LED;
862 K4_STATUS &= ~K4_CLOCK_LED;
863 K2_STATUS |= K2_CLOCK;
865 case 58 | 0x80: /* caps-lock */
866 K2_STATUS &= ~K2_CLOCK;
869 case 69: /* num-lock */
870 K1_STATUS ^= K1_NLOCK;
871 if (K1_STATUS & K1_NLOCK)
872 K4_STATUS |= K4_NLOCK_LED;
874 K4_STATUS &= ~K4_NLOCK_LED;
875 K2_STATUS |= K2_NLOCK;
877 case 69 | 0x80: /* num-lock */
878 K2_STATUS &= ~K2_NLOCK;
881 case 70: /* scroll-lock */
882 K1_STATUS ^= K1_SLOCK;
883 if (K1_STATUS & K1_SLOCK)
884 K4_STATUS |= K4_SLOCK_LED;
886 K4_STATUS &= ~K4_SLOCK_LED;
887 K2_STATUS |= K2_SLOCK;
889 case 70 | 0x80: /* scroll-lock */
890 K2_STATUS &= ~K2_SLOCK;
893 case 82: /* insert */
894 K1_STATUS ^= K1_INSERT;
895 K2_STATUS |= K2_INSERT;
897 case 82 | 0x80: /* insert */
898 K2_STATUS &= ~K2_INSERT;
904 if ((K4_STATUS & 0x07) != oldled) {
905 oldled = K4_STATUS & 0x07;
906 ioctl (fd, PCCONIOCSETLED, &oldled);
910 if (c == 83 && (K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL))
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;
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) {
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 */
938 case 80: /* cursor down */
939 case 81: /* page down */
940 case 82: /* insert */
941 case 83: /* delete */
942 scode = ScanCodes[c].shift;
949 K3_STATUS &= ~K3_TWOBYTE;
950 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
953 kill(getpid(), SIGALRM); /* force redraw */
954 printf("FORCED REDRAW\n");
959 resettrace((regcontext_t *)&saved_sigframe->
973 video_async_event(int fd, int cond, void *arg __unused,
974 regcontext_t *REGS __unused)
986 static struct timeval tv;
989 * Handle any events just sitting around...
992 while (QLength(dpy) > 0) {
993 XNextEvent(dpy, &ev);
994 int9 |= video_event(&ev);
1000 x = select(FD_SETSIZE, &fdset, 0, 0, &tv);
1005 * Errno might be wrong, so we just select again.
1006 * This could cause a problem is something really
1007 * was wrong with select....
1017 if (FD_ISSET(fd, &fdset)) {
1019 XNextEvent(dpy, &ev);
1020 int9 |= video_event(&ev);
1021 } while (QLength(dpy));
1031 video_event(XEvent *ev)
1034 case MotionNotify: {
1035 XMotionEvent *me = (XMotionEvent *)ev;
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;
1049 case ButtonRelease: {
1050 XButtonEvent *be = (XButtonEvent *)ev;
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;
1068 XButtonEvent *be = (XButtonEvent *)ev;
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)) {
1091 case GraphicsExpose:
1094 for (r = 0; r < height; ++r)
1095 lines[r].changed = 1;
1099 static char buf[128];
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);
1125 K1_STATUS &= ~K1_LSHIFT;
1128 K1_STATUS &= ~K1_RSHIFT;
1131 K1_STATUS &= ~K1_CTRL;
1132 K2_STATUS &= ~K2_LCTRL;
1135 K1_STATUS &= ~K1_CTRL;
1136 K3_STATUS &= ~K3_RCTRL;
1139 K1_STATUS &= ~K1_ALT;
1140 K2_STATUS &= ~K2_LALT;
1143 K1_STATUS &= ~K1_ALT;
1144 K3_STATUS &= ~K3_RALT;
1146 case XK_Scroll_Lock:
1147 K2_STATUS &= ~K2_SLOCK;
1150 K2_STATUS &= ~K2_NLOCK;
1153 K2_STATUS &= ~K2_CLOCK;
1156 K2_STATUS &= ~K2_INSERT;
1162 static char buf[128];
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);
1190 K1_STATUS |= K1_LSHIFT;
1193 K1_STATUS |= K1_RSHIFT;
1196 K1_STATUS |= K1_CTRL;
1197 K2_STATUS |= K2_LCTRL;
1200 K1_STATUS |= K1_CTRL;
1201 K3_STATUS |= K3_RCTRL;
1204 K1_STATUS |= K1_ALT;
1205 K2_STATUS |= K2_LALT;
1208 K1_STATUS |= K1_ALT;
1209 K3_STATUS |= K3_RALT;
1211 case XK_Scroll_Lock:
1212 K1_STATUS ^= K1_SLOCK;
1213 K2_STATUS |= K2_SLOCK;
1216 K1_STATUS ^= K1_NLOCK;
1217 K2_STATUS |= K2_NLOCK;
1220 K1_STATUS ^= K1_CLOCK;
1221 K2_STATUS |= K2_CLOCK;
1225 K1_STATUS ^= K1_INSERT;
1226 K2_STATUS |= K2_INSERT;
1235 case XK_ISO_Left_Tab:
1258 scan = ks - XK_F1 + 59;
1279 case XK_KP_Subtract:
1323 /* case XK_Insert: This is above */
1334 scan = flipdelete ? 14 : 83;
1338 scan = flipdelete ? 83 : 14;
1350 scan = Ascii2Scan['/'];
1353 case XK_KP_Multiply:
1354 scan = Ascii2Scan['*'];
1358 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1359 if (ks == 'T' || ks == 't') {
1362 resettrace((regcontext_t *)&saved_sigframe->
1366 if (ks == 'R' || ks == 'r') {
1367 kill(getpid(), SIGALRM); /* redraw */
1371 if (ks < ' ' || ks > '~')
1373 scan = Ascii2Scan[ks];
1378 if ((scan & ~0x100) > 88) {
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;
1390 scan = ScanCodes[scan & 0xff].base;
1394 if (scan != 0xffff) {
1395 break_code = scan >> 8;
1408 tty_move(int r, int c)
1416 tty_report(int *r, int *c)
1425 K_NEXT = K_FREE = K_BUFSTARTP;
1429 tty_index(int scroll)
1433 if (row > (height - 1))
1435 else if (++row >= height) {
1438 memcpy(vmem, &vmem[width], 2 * width * (height - 1));
1439 for (i = 0; i < width; ++i)
1440 vmem[(height - 1) * width + i] = vattr | ' ';
1447 tty_write(int c, int attr)
1449 if (attr == TTYF_REDIRECT) {
1456 if (capture_fd >= 0) {
1458 write(capture_fd, &cc, 1);
1468 write(1, "\007", 1);
1471 if (row > (height - 1) || col > width)
1475 vmem[row * width + col] &= 0xff00;
1478 if (row > (height - 1))
1480 col = (col + 8) & ~0x07;
1497 if (row > (height - 1))
1500 vmem[row * width + col] = attr & 0xff00;
1502 vmem[row * width + col] &= 0xff00;
1503 vmem[row * width + col++] |= c;
1510 tty_rwrite(int n, int c, int attr)
1516 if (VGA_ATC[ATC_ModeCtrl] & 1) {
1517 tty_rwrite_graphics(n, c, attr);
1529 if (row > (height - 1))
1532 vmem[row * width + col] = attr & 0xff00;
1534 vmem[row * width + col] &= 0xff00;
1535 vmem[row * width + col++] |= c;
1543 /* Write a character in graphics mode. Note that the text is put at *text*
1546 tty_rwrite_graphics(int n, int c, int attr)
1548 u_int8_t srow, scol;
1549 int ht = height / CharHeight;
1558 /* tty_index(0); *//* scroll up if last line is filled */
1562 putchar_graphics(row * wd * CharHeight + col, c, attr);
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. */
1578 putchar_graphics(int xy, int c, int attr)
1584 /* get char position in the pixel representation */
1585 cpos = (u_int8_t *)(0xC3000 + c * CharHeight);
1587 for (i = 0; i < CharHeight; i++) {
1589 for (j = 0; j < 4; j++) {
1590 if (attr & 0x8000) {
1592 if (attr & (0x0100 << j))
1593 vram[xy + i * width / 8 + j * 0x10000] ^= cline;
1596 if (attr & (0x0100 << j))
1597 vram[xy + i * width / 8 + j * 0x10000] &= ~cline;
1599 vram[xy + i * width / 8 + j * 0x10000] |= cline;
1608 void tty_pause(void)
1612 sigprocmask(0, 0, &set);
1613 sigdelset(&set, SIGIO);
1614 sigdelset(&set, SIGALRM);
1618 static int nextchar = 0;
1621 tty_read(REGISTERS, int flag)
1625 if ((r = nextchar) != 0) {
1630 if ((flag & TTYF_REDIRECT) && redirect0) {
1632 if (read(STDIN_FILENO, &c, 1) != 1)
1640 if (flag & TTYF_BLOCK) {
1649 if ((r & 0xff) == 0)
1652 if (flag & TTYF_CTRL) {
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);
1665 if (flag & TTYF_ECHO) {
1666 if ((flag & TTYF_ECHONL) && (r == '\n' || r == '\r')) {
1667 tty_write('\r', -1);
1668 tty_write('\n', -1);
1676 tty_peek(REGISTERS, int flag)
1681 return(nextchar & 0xff);
1684 if (flag & TTYF_POLL) {
1688 } else if (flag & TTYF_BLOCK) {
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);
1719 if (K2_STATUS & K2_SYSREQ)
1721 if (K2_STATUS & K2_CLOCK)
1723 if (K2_STATUS & K2_NLOCK)
1725 if (K2_STATUS & K2_SLOCK)
1727 if (K3_STATUS & K3_RALT)
1729 if (K3_STATUS & K3_RCTRL)
1731 if (K2_STATUS & K2_LALT)
1733 if (K2_STATUS & K2_LCTRL)
1739 inrange(int a, int n, int x)
1741 return(a < n ? n : a > x ? x : a);
1745 tty_scroll(int sr, int sc, int er, int ec, int n, int attr)
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)
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));
1770 for (j = er - n; j < er; ) {
1771 for (i = sc; i < ec; ++i)
1772 vmem[j * width + i] = attr;
1778 tty_rscroll(int sr, int sc, int er, int ec, int n, int attr)
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)
1794 if (n > 0 && n < er - sr) {
1795 for (j = er; j > sr + n; ) {
1797 memcpy(&vmem[j * width + sc],
1798 &vmem[(j - n) * width + sc],
1799 sizeof(vmem[0]) * (ec - sc));
1803 for (j = sr + n; j > sr; ) {
1805 for (i = sc; i < ec; ++i)
1806 vmem[j * width + i] = attr;
1811 tty_char(int r, int c)
1817 r = inrange(r, 0, height);
1818 c = inrange(c, 0, width);
1819 return(vmem[r * width + c]);
1825 return(K_NEXT == K_FREE);
1829 KbdWrite(u_short code)
1834 if (kf == K_BUFENDP)
1843 K_BUF(K_FREE) = code;
1852 K_NEXT = K_NEXT + 2;
1853 if (K_NEXT == K_BUFENDP)
1854 K_NEXT = K_BUFSTARTP;
1862 return(K_BUF(K_NEXT));
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();
1878 register_callback(vec, int09, "int 09");
1886 BIOSDATA[0x96] = 0x10; /* MF II kbd, 101 keys */
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. */
1898 dac2rgb(XColor *color, int i)
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;
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;
1923 n = VGA_ATC[ATC_ColorSelect] & 0x0c;
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;
1932 /* Get a connection to the X server and create the window. */
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);
1950 for (i = 0; i < nfds && (i == 0 || fds[i-1] < 63); ++i)
1951 if ((fds[i] = open(_PATH_DEVNULL, 0)) < 0)
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);
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);
1983 gcv.function = GXxor;
1984 cgc = XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1987 XSelectInput(dpy, win, ExposureMask | ButtonPressMask
1988 | ButtonReleaseMask | PointerMotionMask );
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));
2004 /* While we are developing the graphics code ... */
2005 call_on_quit(write_vram, NULL);
2019 font = XLoadQueryFont(dpy, xfont);
2022 font = XLoadQueryFont(dpy, FONTVGA);
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) {
2037 memcpy((void *)0xc3000, font8x8, sizeof(font8x8));
2040 memcpy((void *)0xc3000, font8x14, sizeof(font8x14));
2043 memcpy((void *)0xc3000, font8x16, sizeof(font8x16));
2046 err(1, "load_font: CharHeight = %d?", CharHeight);
2053 /* Get a new, or resize an old XImage as canvas for the graphics display. */
2061 xi = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL,
2062 width, height, 32, 0);
2064 err(1, "Could not get ximage");
2066 xi->data = malloc(width * height * depth / 8);
2067 if (xi->data == NULL) {
2069 err(1, "Could not get memory for ximage data");
2076 /* Get memory for the text line buffer. */
2082 if (lines == NULL) {
2083 lines = (TextLine *)malloc(sizeof(TextLine) * height);
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;
2095 lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
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;
2111 /* Prepare the LUT for the VRAM -> XImage conversion. */
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);
2129 /* Resize the window, using information from 'vga_status[]'. This function is
2130 called after a mode change. */
2138 sh = XAllocSizeHints();
2140 err(1, "Could not get XSizeHints structure");
2144 height = DpyRows + 1;
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;
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);
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. */
2188 /* We support only 16 colors for now. */
2189 for (i = 0; i < 16; i++) {
2193 if (XAllocColor(dpy,
2194 DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
2195 pixels[i] = color.pixel;
2197 pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
2199 pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
2205 write_vram(void *arg __unused)
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);