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 $
35 #include <sys/ioctl.h>
37 #include <sys/types.h>
49 # include <osreldate.h>
50 # include <machine/console.h>
55 #include <X11/Xutil.h>
56 #include <X11/keysym.h>
73 int flipdelete = 0; /* Flip meaning of delete and backspace */
74 static u_short break_code = 0x00;
75 static u_short scan_code = 0x00;
79 const char *xfont = NULL;
95 /* LUT for the vram -> XImage conversion */
96 u_int8_t lut[4][256][8];
98 /* X pixel values for the RGB triples */
99 unsigned long pixels[16];
102 typedef struct TextLine {
104 u_char max_length; /* Not used, but here for future use */
107 TextLine *lines = NULL;
112 static struct termios tty_cook, tty_raw;
114 #define row (CursRow0)
115 #define col (CursCol0)
117 /* Local functions */
118 static void _kbd_event(int, int, void *, regcontext_t *);
119 static void Failure(void *);
120 static void SetVREGCur(void);
121 static void debug_event(int, int, void *, regcontext_t *);
122 static unsigned char inb_port60(int);
123 static int inrange(int, int, int);
124 static void kbd_event(int, int, void *, regcontext_t *);
125 static u_short read_raw_kbd(int, u_short *);
126 static void setgc(u_short);
127 static void video_async_event(int, int, void *, regcontext_t *);
130 static void dac2rgb(XColor *, int);
131 static void prepare_lut(void);
132 static void putchar_graphics(int, int, int);
133 static void tty_rwrite_graphics(int, int, int);
134 static int video_event(XEvent *ev);
135 static void video_update_graphics(void);
136 static void video_update_text(void);
137 static void vram2ximage(void);
142 #define K_NEXT *(u_short *)0x41a
143 #define K_FREE *(u_short *)0x41c
144 #define K_BUFSTARTP *(u_short *)0x480
145 #define K_BUFENDP *(u_short *)0x482
146 #define K_BUFSTART ((u_short *)(0x400 + *(u_short *)0x480))
147 #define K_BUFEND ((u_short *)(0x400 + *(u_short *)0x482))
148 #define K_BUF(i) *((u_short *)((u_char *)0x400 + (i)))
150 #define K1_STATUS BIOSDATA[0x17]
151 #define K1_RSHIFT 0x01
152 #define K1_LSHIFT 0x02
153 #define K1_SHIFT 0x03
156 #define K1_SLOCK 0x10 /* Active */
157 #define K1_NLOCK 0x20 /* Active */
158 #define K1_CLOCK 0x40 /* Active */
159 #define K1_INSERT 0x80 /* Active */
161 #define K2_STATUS BIOSDATA[0x18]
162 #define K2_LCTRL 0x01
164 #define K2_SYSREQ 0x04
165 #define K2_PAUSE 0x08
166 #define K2_SLOCK 0x10 /* Actually held down */
167 #define K2_NLOCK 0x20 /* Actually held down */
168 #define K2_CLOCK 0x40 /* Actually held down */
169 #define K2_INSERT 0x80 /* Actually held down */
171 #define K3_STATUS BIOSDATA[0x96]
172 #define K3_E1 0x01 /* Last code read was e1 */
173 #define K3_E2 0x02 /* Last code read was e2 */
174 #define K3_RCTRL 0x04
176 #define K3_ENHANCED 0x10
177 #define K3_FORCENLOCK 0x20
178 #define K3_TWOBYTE 0x40 /* last code was first of 2 */
179 #define K3_READID 0x80 /* read ID in progress */
181 #define K4_STATUS BIOSDATA[0x97]
182 #define K4_SLOCK_LED 0x01
183 #define K4_NLOCK_LED 0x02
184 #define K4_CLOCK_LED 0x04
185 #define K4_ACK 0x10 /* ACK recieved from keyboard */
186 #define K4_RESEND 0x20 /* RESEND recieved from keyboard */
187 #define K4_LED 0x40 /* LED update in progress */
188 #define K4_ERROR 0x80
191 Failure(void *arg __unused)
193 fprintf(stderr, "X Connection shutdown\n");
200 int cp = row * width + col;
201 VGA_CRTC[CRTC_CurLocHi] = cp >> 8;
202 VGA_CRTC[CRTC_CurLocLo] = cp & 0xff;
206 console_denit(void *arg)
208 int fd = *(int *)arg;
210 #if defined (__DragonFly__)
211 if (ioctl(fd, KDSKBMODE, K_XLATE))
212 perror("KDSKBMODE/K_XLATE");
215 if (ioctl(fd, CONSOLE_X_MODE_OFF, 0))
216 perror("CONSOLE_X_MODE_OFF");
218 if (ioctl(fd, PCCONIOCCOOK, 0))
219 perror("PCCONIOCCOOK");
222 if (tcsetattr(fd, TCSANOW, &tty_cook))
227 _kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
231 printf("_kbd_event: fd=%d\n", fd);
241 if ((fd = open(_PATH_DEV "vga", 2)) < 0) {
242 perror(_PATH_DEV "vga");
245 addr = mmap((caddr_t)0xA0000, 5 * 64 * 1024,
246 PROT_EXEC | PROT_READ | PROT_WRITE,
247 MAP_FILE | MAP_FIXED | MAP_SHARED,
249 if (addr != (caddr_t)0xA0000) {
255 addr = mmap((caddr_t)0x100000 - 0x1000, 0x1000,
256 PROT_EXEC | PROT_READ | PROT_WRITE,
257 MAP_FILE | MAP_FIXED | MAP_SHARED,
259 if (addr != (caddr_t)(0x100000 - 0x1000)) {
265 if ((fd = open(_PATH_CONSOLE, 2)) < 0) {
266 perror(_PATH_CONSOLE);
270 fd = squirrel_fd(fd);
273 #if defined (__DragonFly__)
274 if (ioctl(fd, KDSKBMODE, K_RAW)) {
275 perror("KDSKBMODE/K_RAW");
280 if (ioctl(fd, CONSOLE_X_MODE_ON, 0)) {
281 perror("CONSOLE_X_MODE_ON");
285 if (ioctl(fd, PCCONIOCRAW, 0)) {
286 perror("PCCONIOCRAW");
292 call_on_quit(console_denit, &kbd_fd);
294 if (fcntl(fd, F_SETFL, O_NDELAY|O_ASYNC) < 0) {
298 if (tcgetattr(fd, &tty_cook)) {
304 if (tcsetattr(fd, TCSANOW, &tty_raw)) {
310 _RegisterIO(STDIN_FILENO, debug_event, 0, Failure);
311 _RegisterIO(fd, kbd_event, 0, Failure);
313 _RegisterIO(fd, _kbd_event, 0, Failure);
317 video_setborder(int color)
320 XSetWindowBackground(dpy, win, pixels[color & 0xf]);
324 video_blink(int mode)
334 if (blink && !show && (attr & 0x8000))
335 v.foreground = pixels[(attr >> 12) & 0x07];
337 v.foreground = pixels[(attr >> 8) & 0x0f];
339 v.background = pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
340 XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
345 video_update(regcontext_t *REGS __unused)
351 kbd_event(kbd_fd, AS_RD, 0, REGS);
356 lpt_poll(); /* Handle timeout on lpt code */
358 /* quick and dirty */
359 if (VGA_ATC[ATC_ModeCtrl] & 1)
360 video_update_graphics();
369 video_update_graphics(void)
373 XPutImage(dpy, win, DefaultGC(dpy, DefaultScreen(dpy)),
374 xi, 0, 0, 0, 0, width, height);
381 video_update_text(void)
387 static char buf[256];
389 int attr = vmem[0] & 0xff00;
393 wakeup_poll(); /* Wake up anyone waiting on kbd poll */
399 for (r = 0; r < height; ++r) {
402 if (!lines[r].changed) {
403 if ((r == or || r == row) && (or != row || oc != col))
404 lines[r].changed = 1;
406 for (c = 0; c < width; ++c) {
407 if (lines[r].data[c] != vmem[r * width + c]) {
408 lines[r].changed = 1;
411 if (blink && lines[r].data[c] & 0x8000) {
412 lines[r].changed = 1;
419 if (!lines[r].changed)
423 lines[r].changed = 0;
424 memcpy(lines[r].data,
425 &vmem[r * width], sizeof(u_short) * width);
427 for (c = 0; c < width; ++c) {
428 int cv = vmem[r * width + c];
429 if ((cv & 0xff00) != attr) {
431 XDrawImageString(dpy, win, gc,
439 buf[c] = (cv & 0xff) ? cv & 0xff : ' ';
442 XDrawImageString(dpy, win, gc,
451 if (CursStart <= CursEnd && CursEnd <= FH &&
452 show && row < height && col < width) {
454 attr = vmem[row * width + col] & 0xff00;
455 v.foreground = pixels[(attr >> 8) & 0x0f] ^
456 pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
460 v.foreground = pixels[7];
463 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
464 XFillRectangle(dpy, win, cgc,
466 2 + row * FH + CursStart + FD,
467 FW, CursEnd + 1 - CursStart);
470 if (mouse_status.installed && mouse_status.show) {
471 c = mouse_status.x / mouse_status.hmickey;
472 r = mouse_status.y / mouse_status.vmickey;
474 lines[r].changed = 1;
475 attr = vmem[r * width + c] & 0xff00;
476 v.foreground = pixels[(attr >> 8) & 0x0f] ^
477 pixels[(attr >> 12) & 0x0f];
481 v.foreground = pixels[7];
484 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
485 XFillRectangle(dpy, win, cgc,
495 /* Convert the contents of the video RAM into an XImage.
497 Bugs: - The function is way too slow.
498 - It only works for the 16 color modes.
499 - It only works on 15/16-bit TrueColor visuals. */
503 int i, x, y, yoffset;
504 u_int16_t *image = (u_int16_t *)xi->data;
507 for (y = 0; y < height; y++) {
508 yoffset += width / 8;
509 for (x = 0; x < width; x += 8) {
510 int offset = yoffset + x / 8;
511 for (i = 0; i < 8; i++) {
512 int color = lut[0][vplane0[offset]][i] |
513 lut[1][vplane1[offset]][i] |
514 lut[2][vplane2[offset]][i] |
515 lut[3][vplane3[offset]][i];
516 *image++ = (u_int16_t)pixels[color];
525 static u_short Ascii2Scan[] = {
526 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
527 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
528 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
529 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
530 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
531 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
532 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
533 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
534 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
535 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
536 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
537 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
538 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
539 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
540 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
541 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
550 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */
551 { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */
552 { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */
553 { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */
554 { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */
555 { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */
556 { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */
557 { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */
558 { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */
559 { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */
560 { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
561 { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
562 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
563 { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
564 { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
565 { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
566 { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
567 { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
568 { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
569 { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
570 { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
571 { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
572 { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
573 { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
574 { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
575 { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
576 { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
577 { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
578 { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
579 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
580 { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
581 { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
582 { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
583 { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
584 { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
585 { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
586 { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
587 { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
588 { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
589 { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
590 { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
591 { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
592 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
593 { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
594 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
595 { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
596 { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
597 { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
598 { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
599 { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
600 { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
601 { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
602 { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
603 { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
604 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
605 { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
606 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
607 { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
608 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */
609 { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
610 { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
611 { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
612 { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
613 { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
614 { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
615 { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
616 { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
617 { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
618 { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
619 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
620 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */
621 { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
622 { 0x4800, 0x4838, 0xffff, 0xffff }, /* key 72 - cursor up */
623 { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
624 { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
625 { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
626 { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
627 { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
628 { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
629 { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
630 { 0x5000, 0x5032, 0xffff, 0xffff }, /* key 80 - cursor down */
631 { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
632 { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
633 { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
634 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
635 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
636 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
637 { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
638 { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
642 debug_event(int fd __unused, int cond, void *arg __unused, regcontext_t *REGS)
644 static char ibuf[1024];
646 static u_short ds = 0;
647 static u_short di = 0;
648 static u_short cnt = 16 * 8;
655 r = read(STDIN_FILENO, ibuf + icnt, sizeof(ibuf) - icnt);
662 while ((ep = strchr(ibuf, '\n')) != NULL) {
668 ac = ParseBuffer(ibuf, av = _av, 16);
671 if (!strcasecmp(av[0], "dump")) {
674 if ((c = strchr(av[1], ':')) != NULL) {
675 ds = strtol(av[1], 0, 16);
676 di = strtol(c+1, 0, 16);
678 di = strtol(av[1], 0, 16);
681 cnt = strtol(av[2], 0, 0);
682 cnt = (cnt + 0xf) & ~0xf;
687 for (r = 0; r < cnt; r += 0x10, di = (di + 0x10) & 0xffff) {
689 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
691 printf("%04x:%04x:", ds, di);
692 for (i = 0; i < 8; ++i)
693 printf(" %02x", ap[i]);
695 for (i = 8; i < 16; ++i)
696 printf(" %02x", ap[i]);
698 for (i = 0; i < 8; ++i)
699 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
701 for (i = 8; i < 16; ++i)
702 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
705 } else if (!strcasecmp(av[0], "dis")) {
706 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
710 if ((c = strchr(av[1], ':')) != NULL) {
711 ds = strtol(av[1], 0, 16);
712 di = strtol(c+1, 0, 16);
714 di = strtol(av[1], 0, 16);
717 cnt = strtol(av[2], 0, 0);
719 for (r = 0; r < cnt; ++r) {
721 int c = i386dis(ds, di, ap, buf, 0);
722 printf("%04x:%04x %s\n", ds, di, buf);
726 } else if (!strcasecmp(av[0], "regs")) {
728 } else if (!strcasecmp(av[0], "force")) {
731 while ((p = *++av) != NULL) {
733 if (*p >= ' ' && *p <= '~')
734 KbdWrite(ScanCodes[Ascii2Scan[(int)*p] & 0xff].base);
738 KbdWrite(ScanCodes[28].base);
739 } else if (!strcasecmp(av[0], "bell")) {
745 fprintf(stderr, "%s: unknown command\n", av[0]);
749 if (ep < ibuf + icnt) {
762 inb_port60(int port __unused)
771 kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
778 printf("kbd_event: fd=%d\n", fd);
779 if ((break_code = read_raw_kbd(fd, &scan_code)) != 0xffff)
784 int09(REGISTERS __unused)
787 if (scan_code != 0xffff) {
792 kbd_event(kbd_fd, 0, sc, REGS);
800 read_raw_kbd(int fd, u_short *code)
806 if (read(fd, &c, 1) == 1) {
808 K3_STATUS |= K3_TWOBYTE;
812 case 29: /* Control */
813 K1_STATUS |= K1_CTRL;
814 if (K3_STATUS & K3_TWOBYTE)
815 K3_STATUS |= K3_RCTRL;
817 K2_STATUS |= K2_LCTRL;
819 case 29 | 0x80: /* Control */
820 K1_STATUS &= ~K1_CTRL;
821 if (K3_STATUS & K3_TWOBYTE)
822 K3_STATUS &= ~K3_RCTRL;
824 K2_STATUS &= ~K2_LCTRL;
827 case 42: /* left shift */
828 K1_STATUS |= K1_LSHIFT;
830 case 42 | 0x80: /* left shift */
831 K1_STATUS &= ~K1_LSHIFT;
834 case 54: /* right shift */
835 K1_STATUS |= K1_RSHIFT;
837 case 54 | 0x80: /* right shift */
838 K1_STATUS &= ~K1_RSHIFT;
843 if (K3_STATUS & K3_TWOBYTE)
844 K3_STATUS |= K3_RALT;
846 K2_STATUS |= K2_LALT;
848 case 56 | 0x80: /* Alt */
849 K1_STATUS &= ~K1_ALT;
850 if (K3_STATUS & K3_TWOBYTE)
851 K3_STATUS &= ~K3_RALT;
853 K2_STATUS &= ~K2_LALT;
856 case 58: /* caps-lock */
857 K1_STATUS ^= K1_CLOCK;
858 if (K1_STATUS & K1_CLOCK)
859 K4_STATUS |= K4_CLOCK_LED;
861 K4_STATUS &= ~K4_CLOCK_LED;
862 K2_STATUS |= K2_CLOCK;
864 case 58 | 0x80: /* caps-lock */
865 K2_STATUS &= ~K2_CLOCK;
868 case 69: /* num-lock */
869 K1_STATUS ^= K1_NLOCK;
870 if (K1_STATUS & K1_NLOCK)
871 K4_STATUS |= K4_NLOCK_LED;
873 K4_STATUS &= ~K4_NLOCK_LED;
874 K2_STATUS |= K2_NLOCK;
876 case 69 | 0x80: /* num-lock */
877 K2_STATUS &= ~K2_NLOCK;
880 case 70: /* scroll-lock */
881 K1_STATUS ^= K1_SLOCK;
882 if (K1_STATUS & K1_SLOCK)
883 K4_STATUS |= K4_SLOCK_LED;
885 K4_STATUS &= ~K4_SLOCK_LED;
886 K2_STATUS |= K2_SLOCK;
888 case 70 | 0x80: /* scroll-lock */
889 K2_STATUS &= ~K2_SLOCK;
892 case 82: /* insert */
893 K1_STATUS ^= K1_INSERT;
894 K2_STATUS |= K2_INSERT;
896 case 82 | 0x80: /* insert */
897 K2_STATUS &= ~K2_INSERT;
903 if ((K4_STATUS & 0x07) != oldled) {
904 oldled = K4_STATUS & 0x07;
905 ioctl (fd, PCCONIOCSETLED, &oldled);
909 if (c == 83 && (K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL))
915 if (K1_STATUS & K1_ALT) {
916 scode = ScanCodes[c].alt;
917 } else if (K1_STATUS & K1_CTRL) {
918 scode = ScanCodes[c].ctrl;
919 } else if (K1_STATUS & K1_SHIFT) {
920 scode = ScanCodes[c].shift;
922 scode = ScanCodes[c].base;
923 if (K1_STATUS & K1_CLOCK) {
924 if (islower(scode & 0xff)) {
925 scode = (scode & 0xff00) | toupper(scode & 0xff);
928 if ((K1_STATUS & K1_NLOCK) && (K3_STATUS & K3_TWOBYTE) == 0) {
931 case 72: /* cursor up */
932 case 73: /* page up */
933 case 75: /* cursor left */
934 case 76: /* center key */
935 case 77: /* cursor right */
937 case 80: /* cursor down */
938 case 81: /* page down */
939 case 82: /* insert */
940 case 83: /* delete */
941 scode = ScanCodes[c].shift;
948 K3_STATUS &= ~K3_TWOBYTE;
949 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
952 kill(getpid(), SIGALRM); /* force redraw */
953 printf("FORCED REDRAW\n");
958 resettrace((regcontext_t *)&saved_sigframe->
972 video_async_event(int fd, int cond, void *arg __unused,
973 regcontext_t *REGS __unused)
985 static struct timeval tv;
988 * Handle any events just sitting around...
991 while (QLength(dpy) > 0) {
992 XNextEvent(dpy, &ev);
993 int9 |= video_event(&ev);
999 x = select(FD_SETSIZE, &fdset, 0, 0, &tv);
1004 * Errno might be wrong, so we just select again.
1005 * This could cause a problem is something really
1006 * was wrong with select....
1016 if (FD_ISSET(fd, &fdset)) {
1018 XNextEvent(dpy, &ev);
1019 int9 |= video_event(&ev);
1020 } while (QLength(dpy));
1030 video_event(XEvent *ev)
1033 case MotionNotify: {
1034 XMotionEvent *me = (XMotionEvent *)ev;
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;
1048 case ButtonRelease: {
1049 XButtonEvent *be = (XButtonEvent *)ev;
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;
1067 XButtonEvent *be = (XButtonEvent *)ev;
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)) {
1090 case GraphicsExpose:
1093 for (r = 0; r < height; ++r)
1094 lines[r].changed = 1;
1098 static char buf[128];
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);
1124 K1_STATUS &= ~K1_LSHIFT;
1127 K1_STATUS &= ~K1_RSHIFT;
1130 K1_STATUS &= ~K1_CTRL;
1131 K2_STATUS &= ~K2_LCTRL;
1134 K1_STATUS &= ~K1_CTRL;
1135 K3_STATUS &= ~K3_RCTRL;
1138 K1_STATUS &= ~K1_ALT;
1139 K2_STATUS &= ~K2_LALT;
1142 K1_STATUS &= ~K1_ALT;
1143 K3_STATUS &= ~K3_RALT;
1145 case XK_Scroll_Lock:
1146 K2_STATUS &= ~K2_SLOCK;
1149 K2_STATUS &= ~K2_NLOCK;
1152 K2_STATUS &= ~K2_CLOCK;
1155 K2_STATUS &= ~K2_INSERT;
1161 static char buf[128];
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);
1189 K1_STATUS |= K1_LSHIFT;
1192 K1_STATUS |= K1_RSHIFT;
1195 K1_STATUS |= K1_CTRL;
1196 K2_STATUS |= K2_LCTRL;
1199 K1_STATUS |= K1_CTRL;
1200 K3_STATUS |= K3_RCTRL;
1203 K1_STATUS |= K1_ALT;
1204 K2_STATUS |= K2_LALT;
1207 K1_STATUS |= K1_ALT;
1208 K3_STATUS |= K3_RALT;
1210 case XK_Scroll_Lock:
1211 K1_STATUS ^= K1_SLOCK;
1212 K2_STATUS |= K2_SLOCK;
1215 K1_STATUS ^= K1_NLOCK;
1216 K2_STATUS |= K2_NLOCK;
1219 K1_STATUS ^= K1_CLOCK;
1220 K2_STATUS |= K2_CLOCK;
1224 K1_STATUS ^= K1_INSERT;
1225 K2_STATUS |= K2_INSERT;
1234 case XK_ISO_Left_Tab:
1257 scan = ks - XK_F1 + 59;
1278 case XK_KP_Subtract:
1322 /* case XK_Insert: This is above */
1333 scan = flipdelete ? 14 : 83;
1337 scan = flipdelete ? 83 : 14;
1349 scan = Ascii2Scan['/'];
1352 case XK_KP_Multiply:
1353 scan = Ascii2Scan['*'];
1357 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1358 if (ks == 'T' || ks == 't') {
1361 resettrace((regcontext_t *)&saved_sigframe->
1365 if (ks == 'R' || ks == 'r') {
1366 kill(getpid(), SIGALRM); /* redraw */
1370 if (ks < ' ' || ks > '~')
1372 scan = Ascii2Scan[ks];
1377 if ((scan & ~0x100) > 88) {
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;
1389 scan = ScanCodes[scan & 0xff].base;
1393 if (scan != 0xffff) {
1394 break_code = scan >> 8;
1407 tty_move(int r, int c)
1415 tty_report(int *r, int *c)
1424 K_NEXT = K_FREE = K_BUFSTARTP;
1428 tty_index(int scroll)
1432 if (row > (height - 1))
1434 else if (++row >= height) {
1437 memcpy(vmem, &vmem[width], 2 * width * (height - 1));
1438 for (i = 0; i < width; ++i)
1439 vmem[(height - 1) * width + i] = vattr | ' ';
1446 tty_write(int c, int attr)
1448 if (attr == TTYF_REDIRECT) {
1455 if (capture_fd >= 0) {
1457 write(capture_fd, &cc, 1);
1467 write(1, "\007", 1);
1470 if (row > (height - 1) || col > width)
1474 vmem[row * width + col] &= 0xff00;
1477 if (row > (height - 1))
1479 col = (col + 8) & ~0x07;
1496 if (row > (height - 1))
1499 vmem[row * width + col] = attr & 0xff00;
1501 vmem[row * width + col] &= 0xff00;
1502 vmem[row * width + col++] |= c;
1509 tty_rwrite(int n, int c, int attr)
1515 if (VGA_ATC[ATC_ModeCtrl] & 1) {
1516 tty_rwrite_graphics(n, c, attr);
1528 if (row > (height - 1))
1531 vmem[row * width + col] = attr & 0xff00;
1533 vmem[row * width + col] &= 0xff00;
1534 vmem[row * width + col++] |= c;
1542 /* Write a character in graphics mode. Note that the text is put at *text*
1545 tty_rwrite_graphics(int n, int c, int attr)
1547 u_int8_t srow, scol;
1548 int ht = height / CharHeight;
1557 /* tty_index(0); *//* scroll up if last line is filled */
1561 putchar_graphics(row * wd * CharHeight + col, c, attr);
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. */
1577 putchar_graphics(int xy, int c, int attr)
1583 /* get char position in the pixel representation */
1584 cpos = (u_int8_t *)(0xC3000 + c * CharHeight);
1586 for (i = 0; i < CharHeight; i++) {
1588 for (j = 0; j < 4; j++) {
1589 if (attr & 0x8000) {
1591 if (attr & (0x0100 << j))
1592 vram[xy + i * width / 8 + j * 0x10000] ^= cline;
1595 if (attr & (0x0100 << j))
1596 vram[xy + i * width / 8 + j * 0x10000] &= ~cline;
1598 vram[xy + i * width / 8 + j * 0x10000] |= cline;
1607 void tty_pause(void)
1611 sigprocmask(0, 0, &set);
1612 sigdelset(&set, SIGIO);
1613 sigdelset(&set, SIGALRM);
1617 static int nextchar = 0;
1620 tty_read(REGISTERS, int flag)
1624 if ((r = nextchar) != 0) {
1629 if ((flag & TTYF_REDIRECT) && redirect0) {
1631 if (read(STDIN_FILENO, &c, 1) != 1)
1639 if (flag & TTYF_BLOCK) {
1648 if ((r & 0xff) == 0)
1651 if (flag & TTYF_CTRL) {
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);
1664 if (flag & TTYF_ECHO) {
1665 if ((flag & TTYF_ECHONL) && (r == '\n' || r == '\r')) {
1666 tty_write('\r', -1);
1667 tty_write('\n', -1);
1675 tty_peek(REGISTERS, int flag)
1680 return(nextchar & 0xff);
1683 if (flag & TTYF_POLL) {
1687 } else if (flag & TTYF_BLOCK) {
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);
1718 if (K2_STATUS & K2_SYSREQ)
1720 if (K2_STATUS & K2_CLOCK)
1722 if (K2_STATUS & K2_NLOCK)
1724 if (K2_STATUS & K2_SLOCK)
1726 if (K3_STATUS & K3_RALT)
1728 if (K3_STATUS & K3_RCTRL)
1730 if (K2_STATUS & K2_LALT)
1732 if (K2_STATUS & K2_LCTRL)
1738 inrange(int a, int n, int x)
1740 return(a < n ? n : a > x ? x : a);
1744 tty_scroll(int sr, int sc, int er, int ec, int n, int attr)
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)
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));
1769 for (j = er - n; j < er; ) {
1770 for (i = sc; i < ec; ++i)
1771 vmem[j * width + i] = attr;
1777 tty_rscroll(int sr, int sc, int er, int ec, int n, int attr)
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)
1793 if (n > 0 && n < er - sr) {
1794 for (j = er; j > sr + n; ) {
1796 memcpy(&vmem[j * width + sc],
1797 &vmem[(j - n) * width + sc],
1798 sizeof(vmem[0]) * (ec - sc));
1802 for (j = sr + n; j > sr; ) {
1804 for (i = sc; i < ec; ++i)
1805 vmem[j * width + i] = attr;
1810 tty_char(int r, int c)
1816 r = inrange(r, 0, height);
1817 c = inrange(c, 0, width);
1818 return(vmem[r * width + c]);
1824 return(K_NEXT == K_FREE);
1828 KbdWrite(u_short code)
1833 if (kf == K_BUFENDP)
1842 K_BUF(K_FREE) = code;
1851 K_NEXT = K_NEXT + 2;
1852 if (K_NEXT == K_BUFENDP)
1853 K_NEXT = K_BUFSTARTP;
1861 return(K_BUF(K_NEXT));
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();
1877 register_callback(vec, int09, "int 09");
1885 BIOSDATA[0x96] = 0x10; /* MF II kbd, 101 keys */
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. */
1897 dac2rgb(XColor *color, int i)
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;
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;
1922 n = VGA_ATC[ATC_ColorSelect] & 0x0c;
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;
1931 /* Get a connection to the X server and create the window. */
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);
1949 for (i = 0; i < nfds && (i == 0 || fds[i-1] < 63); ++i)
1950 if ((fds[i] = open(_PATH_DEVNULL, 0)) < 0)
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);
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);
1982 gcv.function = GXxor;
1983 cgc = XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1986 XSelectInput(dpy, win, ExposureMask | ButtonPressMask
1987 | ButtonReleaseMask | PointerMotionMask );
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));
2003 /* While we are developing the graphics code ... */
2004 call_on_quit(write_vram, NULL);
2018 font = XLoadQueryFont(dpy, xfont);
2021 font = XLoadQueryFont(dpy, FONTVGA);
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) {
2036 memcpy((void *)0xc3000, font8x8, sizeof(font8x8));
2039 memcpy((void *)0xc3000, font8x14, sizeof(font8x14));
2042 memcpy((void *)0xc3000, font8x16, sizeof(font8x16));
2045 err(1, "load_font: CharHeight = %d?", CharHeight);
2052 /* Get a new, or resize an old XImage as canvas for the graphics display. */
2060 xi = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL,
2061 width, height, 32, 0);
2063 err(1, "Could not get ximage");
2065 xi->data = malloc(width * height * depth / 8);
2066 if (xi->data == NULL) {
2068 err(1, "Could not get memory for ximage data");
2075 /* Get memory for the text line buffer. */
2081 if (lines == NULL) {
2082 lines = (TextLine *)malloc(sizeof(TextLine) * height);
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;
2094 lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
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;
2110 /* Prepare the LUT for the VRAM -> XImage conversion. */
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);
2128 /* Resize the window, using information from 'vga_status[]'. This function is
2129 called after a mode change. */
2137 sh = XAllocSizeHints();
2139 err(1, "Could not get XSizeHints structure");
2143 height = DpyRows + 1;
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;
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);
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. */
2187 /* We support only 16 colors for now. */
2188 for (i = 0; i < 16; i++) {
2192 if (XAllocColor(dpy,
2193 DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
2194 pixels[i] = color.pixel;
2196 pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
2198 pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
2204 write_vram(void *arg __unused)
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);