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.3 2003/10/04 20:36:43 hmp Exp $
36 #include <sys/ioctl.h>
38 #include <sys/types.h>
50 # include <osreldate.h>
51 # if __FreeBSD_version >= 500014
52 # include <sys/kbio.h>
54 # include <machine/console.h>
58 # include "machine/pccons.h"
60 # include "/sys/i386/isa/pcconsioctl.h"
66 #include <X11/Xutil.h>
67 #include <X11/keysym.h>
84 int flipdelete = 0; /* Flip meaning of delete and backspace */
85 static u_short break_code = 0x00;
86 static u_short scan_code = 0x00;
90 const char *xfont = 0;
106 /* LUT for the vram -> XImage conversion */
107 u_int8_t lut[4][256][8];
109 /* X pixel values for the RGB triples */
110 unsigned long pixels[16];
113 typedef struct TextLine {
115 u_char max_length; /* Not used, but here for future use */
118 TextLine *lines = NULL;
123 static struct termios tty_cook, tty_raw;
125 #define row (CursRow0)
126 #define col (CursCol0)
128 /* Local functions */
129 static void _kbd_event(int, int, void *, regcontext_t *);
130 static void Failure(void *);
131 static void SetVREGCur(void);
132 static void debug_event(int, int, void *, regcontext_t *);
133 static unsigned char inb_port60(int);
134 static int inrange(int, int, int);
135 static void kbd_event(int, int, void *, regcontext_t *);
136 static u_short read_raw_kbd(int, u_short *);
137 static void setgc(u_short);
138 static void video_async_event(int, int, void *, regcontext_t *);
141 static void dac2rgb(XColor *, int);
142 static void prepare_lut(void);
143 static void putchar_graphics(int, int, int);
144 static void tty_rwrite_graphics(int, int, int);
145 static int video_event(XEvent *ev);
146 static void video_update_graphics(void);
147 static void video_update_text(void);
148 static void vram2ximage(void);
153 #define K_NEXT *(u_short *)0x41a
154 #define K_FREE *(u_short *)0x41c
155 #define K_BUFSTARTP *(u_short *)0x480
156 #define K_BUFENDP *(u_short *)0x482
157 #define K_BUFSTART ((u_short *)(0x400 + *(u_short *)0x480))
158 #define K_BUFEND ((u_short *)(0x400 + *(u_short *)0x482))
159 #define K_BUF(i) *((u_short *)((u_char *)0x400 + (i)))
161 #define K1_STATUS BIOSDATA[0x17]
162 #define K1_RSHIFT 0x01
163 #define K1_LSHIFT 0x02
164 #define K1_SHIFT 0x03
167 #define K1_SLOCK 0x10 /* Active */
168 #define K1_NLOCK 0x20 /* Active */
169 #define K1_CLOCK 0x40 /* Active */
170 #define K1_INSERT 0x80 /* Active */
172 #define K2_STATUS BIOSDATA[0x18]
173 #define K2_LCTRL 0x01
175 #define K2_SYSREQ 0x04
176 #define K2_PAUSE 0x08
177 #define K2_SLOCK 0x10 /* Actually held down */
178 #define K2_NLOCK 0x20 /* Actually held down */
179 #define K2_CLOCK 0x40 /* Actually held down */
180 #define K2_INSERT 0x80 /* Actually held down */
182 #define K3_STATUS BIOSDATA[0x96]
183 #define K3_E1 0x01 /* Last code read was e1 */
184 #define K3_E2 0x02 /* Last code read was e2 */
185 #define K3_RCTRL 0x04
187 #define K3_ENHANCED 0x10
188 #define K3_FORCENLOCK 0x20
189 #define K3_TWOBYTE 0x40 /* last code was first of 2 */
190 #define K3_READID 0x80 /* read ID in progress */
192 #define K4_STATUS BIOSDATA[0x97]
193 #define K4_SLOCK_LED 0x01
194 #define K4_NLOCK_LED 0x02
195 #define K4_CLOCK_LED 0x04
196 #define K4_ACK 0x10 /* ACK recieved from keyboard */
197 #define K4_RESEND 0x20 /* RESEND recieved from keyboard */
198 #define K4_LED 0x40 /* LED update in progress */
199 #define K4_ERROR 0x80
202 Failure(void *arg __unused)
204 fprintf(stderr, "X Connection shutdown\n");
211 int cp = row * width + col;
212 VGA_CRTC[CRTC_CurLocHi] = cp >> 8;
213 VGA_CRTC[CRTC_CurLocLo] = cp & 0xff;
217 console_denit(void *arg)
219 int fd = *(int *)arg;
222 if (ioctl(fd, KDSKBMODE, K_XLATE))
223 perror("KDSKBMODE/K_XLATE");
226 if (ioctl(fd, CONSOLE_X_MODE_OFF, 0))
227 perror("CONSOLE_X_MODE_OFF");
229 if (ioctl(fd, PCCONIOCCOOK, 0))
230 perror("PCCONIOCCOOK");
233 if (tcsetattr(fd, TCSANOW, &tty_cook))
238 _kbd_event(int fd, int cond, void *arg __unused, regcontext_t *REGS __unused)
242 printf("_kbd_event: fd=%d\n", fd);
252 if ((fd = open(_PATH_DEV "vga", 2)) < 0) {
253 perror(_PATH_DEV "vga");
256 addr = mmap((caddr_t)0xA0000, 5 * 64 * 1024,
257 PROT_EXEC | PROT_READ | PROT_WRITE,
258 MAP_FILE | MAP_FIXED | MAP_SHARED,
260 if (addr != (caddr_t)0xA0000) {
266 addr = mmap((caddr_t)0x100000 - 0x1000, 0x1000,
267 PROT_EXEC | PROT_READ | PROT_WRITE,
268 MAP_FILE | MAP_FIXED | MAP_SHARED,
270 if (addr != (caddr_t)(0x100000 - 0x1000)) {
276 if ((fd = open(_PATH_CONSOLE, 2)) < 0) {
277 perror(_PATH_CONSOLE);
281 fd = squirrel_fd(fd);
285 if (ioctl(fd, KDSKBMODE, K_RAW)) {
286 perror("KDSKBMODE/K_RAW");
291 if (ioctl(fd, CONSOLE_X_MODE_ON, 0)) {
292 perror("CONSOLE_X_MODE_ON");
296 if (ioctl(fd, PCCONIOCRAW, 0)) {
297 perror("PCCONIOCRAW");
303 call_on_quit(console_denit, &kbd_fd);
305 if (fcntl(fd, F_SETFL, O_NDELAY|O_ASYNC) < 0) {
309 if (tcgetattr(fd, &tty_cook)) {
315 if (tcsetattr(fd, TCSANOW, &tty_raw)) {
321 _RegisterIO(STDIN_FILENO, debug_event, 0, Failure);
322 _RegisterIO(fd, kbd_event, 0, Failure);
324 _RegisterIO(fd, _kbd_event, 0, Failure);
328 video_setborder(int color)
331 XSetWindowBackground(dpy, win, pixels[color & 0xf]);
335 video_blink(int mode)
345 if (blink && !show && (attr & 0x8000))
346 v.foreground = pixels[(attr >> 12) & 0x07];
348 v.foreground = pixels[(attr >> 8) & 0x0f];
350 v.background = pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
351 XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
356 video_update(regcontext_t *REGS __unused)
362 kbd_event(kbd_fd, AS_RD, 0, REGS);
367 lpt_poll(); /* Handle timeout on lpt code */
369 /* quick and dirty */
370 if (VGA_ATC[ATC_ModeCtrl] & 1)
371 video_update_graphics();
380 video_update_graphics(void)
384 XPutImage(dpy, win, DefaultGC(dpy, DefaultScreen(dpy)),
385 xi, 0, 0, 0, 0, width, height);
392 video_update_text(void)
398 static char buf[256];
400 int attr = vmem[0] & 0xff00;
404 wakeup_poll(); /* Wake up anyone waiting on kbd poll */
410 for (r = 0; r < height; ++r) {
413 if (!lines[r].changed) {
414 if ((r == or || r == row) && (or != row || oc != col))
415 lines[r].changed = 1;
417 for (c = 0; c < width; ++c) {
418 if (lines[r].data[c] != vmem[r * width + c]) {
419 lines[r].changed = 1;
422 if (blink && lines[r].data[c] & 0x8000) {
423 lines[r].changed = 1;
430 if (!lines[r].changed)
434 lines[r].changed = 0;
435 memcpy(lines[r].data,
436 &vmem[r * width], sizeof(u_short) * width);
438 for (c = 0; c < width; ++c) {
439 int cv = vmem[r * width + c];
440 if ((cv & 0xff00) != attr) {
442 XDrawImageString(dpy, win, gc,
450 buf[c] = (cv & 0xff) ? cv & 0xff : ' ';
453 XDrawImageString(dpy, win, gc,
462 if (CursStart <= CursEnd && CursEnd <= FH &&
463 show && row < height && col < width) {
465 attr = vmem[row * width + col] & 0xff00;
466 v.foreground = pixels[(attr >> 8) & 0x0f] ^
467 pixels[(attr >> 12) & (blink ? 0x07 : 0x0f)];
471 v.foreground = pixels[7];
474 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
475 XFillRectangle(dpy, win, cgc,
477 2 + row * FH + CursStart + FD,
478 FW, CursEnd + 1 - CursStart);
481 if (mouse_status.installed && mouse_status.show) {
482 c = mouse_status.x / mouse_status.hmickey;
483 r = mouse_status.y / mouse_status.vmickey;
485 lines[r].changed = 1;
486 attr = vmem[r * width + c] & 0xff00;
487 v.foreground = pixels[(attr >> 8) & 0x0f] ^
488 pixels[(attr >> 12) & 0x0f];
492 v.foreground = pixels[7];
495 XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
496 XFillRectangle(dpy, win, cgc,
506 /* Convert the contents of the video RAM into an XImage.
508 Bugs: - The function is way too slow.
509 - It only works for the 16 color modes.
510 - It only works on 15/16-bit TrueColor visuals. */
514 int i, x, y, yoffset;
515 u_int16_t *image = (u_int16_t *)xi->data;
518 for (y = 0; y < height; y++) {
519 yoffset += width / 8;
520 for (x = 0; x < width; x += 8) {
521 int offset = yoffset + x / 8;
522 for (i = 0; i < 8; i++) {
523 int color = lut[0][vplane0[offset]][i] |
524 lut[1][vplane1[offset]][i] |
525 lut[2][vplane2[offset]][i] |
526 lut[3][vplane3[offset]][i];
527 *image++ = (u_int16_t)pixels[color];
536 static u_short Ascii2Scan[] = {
537 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
538 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
539 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
540 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
541 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
542 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
543 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
544 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
545 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
546 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
547 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
548 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
549 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
550 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
551 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
552 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
561 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */
562 { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */
563 { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */
564 { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' - special handling */
565 { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */
566 { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */
567 { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */
568 { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */
569 { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */
570 { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */
571 { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
572 { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
573 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
574 { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
575 { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
576 { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
577 { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
578 { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
579 { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
580 { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
581 { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
582 { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
583 { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
584 { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
585 { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
586 { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
587 { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
588 { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
589 { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
590 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
591 { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
592 { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
593 { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
594 { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
595 { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
596 { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
597 { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
598 { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
599 { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
600 { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
601 { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
602 { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
603 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
604 { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
605 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
606 { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
607 { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
608 { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
609 { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
610 { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
611 { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
612 { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
613 { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
614 { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
615 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
616 { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
617 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
618 { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
619 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */
620 { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
621 { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
622 { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
623 { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
624 { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
625 { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
626 { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
627 { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
628 { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
629 { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
630 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
631 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */
632 { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
633 { 0x4800, 0x4838, 0xffff, 0xffff }, /* key 72 - cursor up */
634 { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
635 { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
636 { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
637 { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
638 { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
639 { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
640 { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
641 { 0x5000, 0x5032, 0xffff, 0xffff }, /* key 80 - cursor down */
642 { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
643 { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
644 { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
645 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
646 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
647 { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
648 { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
649 { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
653 debug_event(int fd, int cond, void *arg, regcontext_t *REGS)
655 static char ibuf[1024];
657 static u_short ds = 0;
658 static u_short di = 0;
659 static u_short cnt = 16 * 8;
666 r = read(STDIN_FILENO, ibuf + icnt, sizeof(ibuf) - icnt);
673 while ((ep = strchr(ibuf, '\n')) != 0) {
679 ac = ParseBuffer(ibuf, av = _av, 16);
682 if (!strcasecmp(av[0], "dump")) {
685 if ((c = strchr(av[1], ':')) != 0) {
686 ds = strtol(av[1], 0, 16);
687 di = strtol(c+1, 0, 16);
689 di = strtol(av[1], 0, 16);
692 cnt = strtol(av[2], 0, 0);
693 cnt = (cnt + 0xf) & ~0xf;
698 for (r = 0; r < cnt; r += 0x10, di = (di + 0x10) & 0xffff) {
700 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
702 printf("%04x:%04x:", ds, di);
703 for (i = 0; i < 8; ++i)
704 printf(" %02x", ap[i]);
706 for (i = 8; i < 16; ++i)
707 printf(" %02x", ap[i]);
709 for (i = 0; i < 8; ++i)
710 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
712 for (i = 8; i < 16; ++i)
713 printf("%c",(ap[i] < ' ' || ap[i] > '~') ? '.' : ap[i]);
716 } else if (!strcasecmp(av[0], "dis")) {
717 u_char *ap = (u_char *)(((u_long)ds << 4) + di);
721 if ((c = strchr(av[1], ':')) != 0) {
722 ds = strtol(av[1], 0, 16);
723 di = strtol(c+1, 0, 16);
725 di = strtol(av[1], 0, 16);
728 cnt = strtol(av[2], 0, 0);
730 for (r = 0; r < cnt; ++r) {
732 int c = i386dis(ds, di, ap, buf, 0);
733 printf("%04x:%04x %s\n", ds, di, buf);
737 } else if (!strcasecmp(av[0], "regs")) {
739 } else if (!strcasecmp(av[0], "force")) {
742 while ((p = *++av) != 0) {
744 if (*p >= ' ' && *p <= '~')
745 KbdWrite(ScanCodes[Ascii2Scan[(int)*p] & 0xff].base);
749 KbdWrite(ScanCodes[28].base);
750 } else if (!strcasecmp(av[0], "bell")) {
756 fprintf(stderr, "%s: unknown command\n", av[0]);
760 if (ep < ibuf + icnt) {
773 inb_port60(int port __unused)
782 kbd_event(int fd, int cond, void *arg, regcontext_t *REGS)
789 printf("kbd_event: fd=%d\n", fd);
790 if ((break_code = read_raw_kbd(fd, &scan_code)) != 0xffff)
795 int09(REGISTERS __unused)
798 if (scan_code != 0xffff) {
803 kbd_event(kbd_fd, 0, sc, REGS);
811 read_raw_kbd(int fd, u_short *code)
817 if (read(fd, &c, 1) == 1) {
819 K3_STATUS |= K3_TWOBYTE;
823 case 29: /* Control */
824 K1_STATUS |= K1_CTRL;
825 if (K3_STATUS & K3_TWOBYTE)
826 K3_STATUS |= K3_RCTRL;
828 K2_STATUS |= K2_LCTRL;
830 case 29 | 0x80: /* Control */
831 K1_STATUS &= ~K1_CTRL;
832 if (K3_STATUS & K3_TWOBYTE)
833 K3_STATUS &= ~K3_RCTRL;
835 K2_STATUS &= ~K2_LCTRL;
838 case 42: /* left shift */
839 K1_STATUS |= K1_LSHIFT;
841 case 42 | 0x80: /* left shift */
842 K1_STATUS &= ~K1_LSHIFT;
845 case 54: /* right shift */
846 K1_STATUS |= K1_RSHIFT;
848 case 54 | 0x80: /* right shift */
849 K1_STATUS &= ~K1_RSHIFT;
854 if (K3_STATUS & K3_TWOBYTE)
855 K3_STATUS |= K3_RALT;
857 K2_STATUS |= K2_LALT;
859 case 56 | 0x80: /* Alt */
860 K1_STATUS &= ~K1_ALT;
861 if (K3_STATUS & K3_TWOBYTE)
862 K3_STATUS &= ~K3_RALT;
864 K2_STATUS &= ~K2_LALT;
867 case 58: /* caps-lock */
868 K1_STATUS ^= K1_CLOCK;
869 if (K1_STATUS & K1_CLOCK)
870 K4_STATUS |= K4_CLOCK_LED;
872 K4_STATUS &= ~K4_CLOCK_LED;
873 K2_STATUS |= K2_CLOCK;
875 case 58 | 0x80: /* caps-lock */
876 K2_STATUS &= ~K2_CLOCK;
879 case 69: /* num-lock */
880 K1_STATUS ^= K1_NLOCK;
881 if (K1_STATUS & K1_NLOCK)
882 K4_STATUS |= K4_NLOCK_LED;
884 K4_STATUS &= ~K4_NLOCK_LED;
885 K2_STATUS |= K2_NLOCK;
887 case 69 | 0x80: /* num-lock */
888 K2_STATUS &= ~K2_NLOCK;
891 case 70: /* scroll-lock */
892 K1_STATUS ^= K1_SLOCK;
893 if (K1_STATUS & K1_SLOCK)
894 K4_STATUS |= K4_SLOCK_LED;
896 K4_STATUS &= ~K4_SLOCK_LED;
897 K2_STATUS |= K2_SLOCK;
899 case 70 | 0x80: /* scroll-lock */
900 K2_STATUS &= ~K2_SLOCK;
903 case 82: /* insert */
904 K1_STATUS ^= K1_INSERT;
905 K2_STATUS |= K2_INSERT;
907 case 82 | 0x80: /* insert */
908 K2_STATUS &= ~K2_INSERT;
914 if ((K4_STATUS & 0x07) != oldled) {
915 oldled = K4_STATUS & 0x07;
916 ioctl (fd, PCCONIOCSETLED, &oldled);
920 if (c == 83 && (K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL))
926 if (K1_STATUS & K1_ALT) {
927 scode = ScanCodes[c].alt;
928 } else if (K1_STATUS & K1_CTRL) {
929 scode = ScanCodes[c].ctrl;
930 } else if (K1_STATUS & K1_SHIFT) {
931 scode = ScanCodes[c].shift;
933 scode = ScanCodes[c].base;
934 if (K1_STATUS & K1_CLOCK) {
935 if (islower(scode & 0xff)) {
936 scode = (scode & 0xff00) | toupper(scode & 0xff);
939 if ((K1_STATUS & K1_NLOCK) && (K3_STATUS & K3_TWOBYTE) == 0) {
942 case 72: /* cursor up */
943 case 73: /* page up */
944 case 75: /* cursor left */
945 case 76: /* center key */
946 case 77: /* cursor right */
948 case 80: /* cursor down */
949 case 81: /* page down */
950 case 82: /* insert */
951 case 83: /* delete */
952 scode = ScanCodes[c].shift;
959 K3_STATUS &= ~K3_TWOBYTE;
960 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
963 kill(getpid(), SIGALRM); /* force redraw */
964 printf("FORCED REDRAW\n");
969 resettrace((regcontext_t *)&saved_sigframe->
983 video_async_event(int fd, int cond, void *arg, regcontext_t *REGS)
995 static struct timeval tv;
998 * Handle any events just sitting around...
1001 while (QLength(dpy) > 0) {
1002 XNextEvent(dpy, &ev);
1003 int9 |= video_event(&ev);
1009 x = select(FD_SETSIZE, &fdset, 0, 0, &tv);
1014 * Errno might be wrong, so we just select again.
1015 * This could cause a problem is something really
1016 * was wrong with select....
1026 if (FD_ISSET(fd, &fdset)) {
1028 XNextEvent(dpy, &ev);
1029 int9 |= video_event(&ev);
1030 } while (QLength(dpy));
1040 video_event(XEvent *ev)
1043 case MotionNotify: {
1044 XMotionEvent *me = (XMotionEvent *)ev;
1048 mouse_status.x = (me->x < mouse_status.range.x)
1049 ? mouse_status.range.x
1050 : (me->x > mouse_status.range.w)
1051 ? mouse_status.range.w : me->x;
1052 mouse_status.y = (me->y < mouse_status.range.y)
1053 ? mouse_status.range.y
1054 : (me->y > mouse_status.range.h)
1055 ? mouse_status.range.h : me->y;
1058 case ButtonRelease: {
1059 XButtonEvent *be = (XButtonEvent *)ev;
1064 mouse_status.ups[be->button]++;
1066 mouse_status.x = (be->x < mouse_status.range.x)
1067 ? mouse_status.range.x
1068 : (be->x > mouse_status.range.w)
1069 ? mouse_status.range.w : be->x;
1070 mouse_status.y = (be->y < mouse_status.range.y)
1071 ? mouse_status.range.y
1072 : (be->y > mouse_status.range.h)
1073 ? mouse_status.range.h : be->y;
1077 XButtonEvent *be = (XButtonEvent *)ev;
1082 mouse_status.downs[be->button]++;
1084 mouse_status.x = (be->x < mouse_status.range.x)
1085 ? mouse_status.range.x
1086 : (be->x > mouse_status.range.w)
1087 ? mouse_status.range.w : be->x;
1088 mouse_status.y = (be->y < mouse_status.range.y)
1089 ? mouse_status.range.y
1090 : (be->y > mouse_status.range.h)
1091 ? mouse_status.range.h : be->y;
1093 if ((K1_STATUS & (K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1100 case GraphicsExpose:
1103 for (r = 0; r < height; ++r)
1104 lines[r].changed = 1;
1108 static char buf[128];
1113 if (!(ev->xkey.state & ShiftMask)) {
1114 K1_STATUS &= ~K1_LSHIFT;
1115 K1_STATUS &= ~K1_RSHIFT;
1117 if (!(ev->xkey.state & ControlMask)) {
1118 K1_STATUS &= ~K1_CTRL;
1119 K2_STATUS &= ~K2_LCTRL;
1120 K3_STATUS &= ~K3_RCTRL;
1122 if (!(ev->xkey.state & Mod1Mask)) {
1123 K1_STATUS &= ~K1_ALT;
1124 K2_STATUS &= ~K2_LALT;
1125 K3_STATUS &= ~K3_RALT;
1127 if (!(ev->xkey.state & LockMask)) {
1128 K2_STATUS &= ~K2_CLOCK;
1131 XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1134 K1_STATUS &= ~K1_LSHIFT;
1137 K1_STATUS &= ~K1_RSHIFT;
1140 K1_STATUS &= ~K1_CTRL;
1141 K2_STATUS &= ~K2_LCTRL;
1144 K1_STATUS &= ~K1_CTRL;
1145 K3_STATUS &= ~K3_RCTRL;
1148 K1_STATUS &= ~K1_ALT;
1149 K2_STATUS &= ~K2_LALT;
1152 K1_STATUS &= ~K1_ALT;
1153 K3_STATUS &= ~K3_RALT;
1155 case XK_Scroll_Lock:
1156 K2_STATUS &= ~K2_SLOCK;
1159 K2_STATUS &= ~K2_NLOCK;
1162 K2_STATUS &= ~K2_CLOCK;
1165 K2_STATUS &= ~K2_INSERT;
1171 static char buf[128];
1175 u_short scan = 0xffff;
1177 if (!(ev->xkey.state & ShiftMask)) {
1178 K1_STATUS &= ~K1_LSHIFT;
1179 K1_STATUS &= ~K1_RSHIFT;
1181 if (!(ev->xkey.state & ControlMask)) {
1182 K1_STATUS &= ~K1_CTRL;
1183 K2_STATUS &= ~K2_LCTRL;
1184 K3_STATUS &= ~K3_RCTRL;
1186 if (!(ev->xkey.state & Mod1Mask)) {
1187 K1_STATUS &= ~K1_ALT;
1188 K2_STATUS &= ~K2_LALT;
1189 K3_STATUS &= ~K3_RALT;
1191 if (!(ev->xkey.state & LockMask)) {
1192 K2_STATUS &= ~K2_CLOCK;
1195 n = XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
1199 K1_STATUS |= K1_LSHIFT;
1202 K1_STATUS |= K1_RSHIFT;
1205 K1_STATUS |= K1_CTRL;
1206 K2_STATUS |= K2_LCTRL;
1209 K1_STATUS |= K1_CTRL;
1210 K3_STATUS |= K3_RCTRL;
1213 K1_STATUS |= K1_ALT;
1214 K2_STATUS |= K2_LALT;
1217 K1_STATUS |= K1_ALT;
1218 K3_STATUS |= K3_RALT;
1220 case XK_Scroll_Lock:
1221 K1_STATUS ^= K1_SLOCK;
1222 K2_STATUS |= K2_SLOCK;
1225 K1_STATUS ^= K1_NLOCK;
1226 K2_STATUS |= K2_NLOCK;
1229 K1_STATUS ^= K1_CLOCK;
1230 K2_STATUS |= K2_CLOCK;
1234 K1_STATUS ^= K1_INSERT;
1235 K2_STATUS |= K2_INSERT;
1244 case XK_ISO_Left_Tab:
1267 scan = ks - XK_F1 + 59;
1288 case XK_KP_Subtract:
1332 /* case XK_Insert: This is above */
1343 scan = flipdelete ? 14 : 83;
1347 scan = flipdelete ? 83 : 14;
1359 scan = Ascii2Scan['/'];
1362 case XK_KP_Multiply:
1363 scan = Ascii2Scan['*'];
1367 if ((K1_STATUS&(K1_ALT|K1_CTRL)) == (K1_ALT|K1_CTRL)) {
1368 if (ks == 'T' || ks == 't') {
1371 resettrace((regcontext_t *)&saved_sigframe->
1375 if (ks == 'R' || ks == 'r') {
1376 kill(getpid(), SIGALRM); /* redraw */
1380 if (ks < ' ' || ks > '~')
1382 scan = Ascii2Scan[ks];
1387 if ((scan & ~0x100) > 88) {
1392 if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
1393 scan = ScanCodes[scan & 0xff].shift;
1394 } else if (K1_STATUS & K1_CTRL) {
1395 scan = ScanCodes[scan & 0xff].ctrl;
1396 } else if (K1_STATUS & K1_ALT) {
1397 scan = ScanCodes[scan & 0xff].alt;
1399 scan = ScanCodes[scan & 0xff].base;
1403 if (scan != 0xffff) {
1404 break_code = scan >> 8;
1417 tty_move(int r, int c)
1425 tty_report(int *r, int *c)
1434 K_NEXT = K_FREE = K_BUFSTARTP;
1438 tty_index(int scroll)
1442 if (row > (height - 1))
1444 else if (++row >= height) {
1447 memcpy(vmem, &vmem[width], 2 * width * (height - 1));
1448 for (i = 0; i < width; ++i)
1449 vmem[(height - 1) * width + i] = vattr | ' ';
1456 tty_write(int c, int attr)
1458 if (attr == TTYF_REDIRECT) {
1465 if (capture_fd >= 0) {
1467 write(capture_fd, &cc, 1);
1477 write(1, "\007", 1);
1480 if (row > (height - 1) || col > width)
1484 vmem[row * width + col] &= 0xff00;
1487 if (row > (height - 1))
1489 col = (col + 8) & ~0x07;
1506 if (row > (height - 1))
1509 vmem[row * width + col] = attr & 0xff00;
1511 vmem[row * width + col] &= 0xff00;
1512 vmem[row * width + col++] |= c;
1519 tty_rwrite(int n, int c, int attr)
1525 if (VGA_ATC[ATC_ModeCtrl] & 1) {
1526 tty_rwrite_graphics(n, c, attr);
1538 if (row > (height - 1))
1541 vmem[row * width + col] = attr & 0xff00;
1543 vmem[row * width + col] &= 0xff00;
1544 vmem[row * width + col++] |= c;
1552 /* Write a character in graphics mode. Note that the text is put at *text*
1555 tty_rwrite_graphics(int n, int c, int attr)
1557 u_int8_t srow, scol;
1558 int ht = height / CharHeight;
1567 /* tty_index(0); *//* scroll up if last line is filled */
1571 putchar_graphics(row * wd * CharHeight + col, c, attr);
1581 /* Put the character together from its pixel representation in 'font8xXX[]'
1582 and write it to 'vram'. The attribute byte gives the desired color; if bit
1583 7 is set, the pixels are XOR'd with the underlying color(s).
1585 XXX This must be updated for the 256 color modes. */
1587 putchar_graphics(int xy, int c, int attr)
1593 /* get char position in the pixel representation */
1594 cpos = (u_int8_t *)(0xC3000 + c * CharHeight);
1596 for (i = 0; i < CharHeight; i++) {
1598 for (j = 0; j < 4; j++) {
1599 if (attr & 0x8000) {
1601 if (attr & (0x0100 << j))
1602 vram[xy + i * width / 8 + j * 0x10000] ^= cline;
1605 if (attr & (0x0100 << j))
1606 vram[xy + i * width / 8 + j * 0x10000] &= ~cline;
1608 vram[xy + i * width / 8 + j * 0x10000] |= cline;
1617 void tty_pause(void)
1621 sigprocmask(0, 0, &set);
1622 sigdelset(&set, SIGIO);
1623 sigdelset(&set, SIGALRM);
1627 static int nextchar = 0;
1630 tty_read(REGISTERS, int flag)
1634 if ((r = nextchar) != 0) {
1639 if ((flag & TTYF_REDIRECT) && redirect0) {
1641 if (read(STDIN_FILENO, &c, 1) != 1)
1649 if (flag & TTYF_BLOCK) {
1658 if ((r & 0xff) == 0)
1661 if (flag & TTYF_CTRL) {
1664 * XXX - Not quite sure where we should return, maybe not
1665 * all the way to the user, but...
1667 if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1668 fake_int(REGS, 0x23);
1674 if (flag & TTYF_ECHO) {
1675 if ((flag & TTYF_ECHONL) && (r == '\n' || r == '\r')) {
1676 tty_write('\r', -1);
1677 tty_write('\n', -1);
1685 tty_peek(REGISTERS, int flag)
1690 return(nextchar & 0xff);
1693 if (flag & TTYF_POLL) {
1697 } else if (flag & TTYF_BLOCK) {
1704 if ((c & 0xff) == 3) {
1706 * XXX - Not quite sure where we should return, maybe not
1707 * all the way to the user, but...
1709 if (ivec[0x23] && (ivec[0x23] >> 16) != 0xF000) {
1710 fake_int(REGS, 0x23);
1728 if (K2_STATUS & K2_SYSREQ)
1730 if (K2_STATUS & K2_CLOCK)
1732 if (K2_STATUS & K2_NLOCK)
1734 if (K2_STATUS & K2_SLOCK)
1736 if (K3_STATUS & K3_RALT)
1738 if (K3_STATUS & K3_RCTRL)
1740 if (K2_STATUS & K2_LALT)
1742 if (K2_STATUS & K2_LCTRL)
1748 inrange(int a, int n, int x)
1750 return(a < n ? n : a > x ? x : a);
1754 tty_scroll(int sr, int sc, int er, int ec, int n, int attr)
1758 sr = inrange(sr, 0, height);
1759 er = inrange(er, 0, height);
1760 sc = inrange(sc, 0, width);
1761 ec = inrange(ec, 0, width);
1762 if (sr > er || sc > ec)
1770 if (n > 0 && n < er - sr) {
1771 for (j = sr; j < er - n; ) {
1772 memcpy(&vmem[j * width + sc],
1773 &vmem[(j + n) * width + sc],
1774 sizeof(vmem[0]) * (ec - sc));
1779 for (j = er - n; j < er; ) {
1780 for (i = sc; i < ec; ++i)
1781 vmem[j * width + i] = attr;
1787 tty_rscroll(int sr, int sc, int er, int ec, int n, int attr)
1791 sr = inrange(sr, 0, height);
1792 er = inrange(er, 0, height);
1793 sc = inrange(sc, 0, width);
1794 ec = inrange(ec, 0, width);
1795 if (sr > er || sc > ec)
1803 if (n > 0 && n < er - sr) {
1804 for (j = er; j > sr + n; ) {
1806 memcpy(&vmem[j * width + sc],
1807 &vmem[(j - n) * width + sc],
1808 sizeof(vmem[0]) * (ec - sc));
1812 for (j = sr + n; j > sr; ) {
1814 for (i = sc; i < ec; ++i)
1815 vmem[j * width + i] = attr;
1820 tty_char(int r, int c)
1826 r = inrange(r, 0, height);
1827 c = inrange(c, 0, width);
1828 return(vmem[r * width + c]);
1834 return(K_NEXT == K_FREE);
1838 KbdWrite(u_short code)
1843 if (kf == K_BUFENDP)
1852 K_BUF(K_FREE) = code;
1861 K_NEXT = K_NEXT + 2;
1862 if (K_NEXT == K_BUFENDP)
1863 K_NEXT = K_BUFSTARTP;
1871 return(K_BUF(K_NEXT));
1879 define_input_port_handler(0x60, inb_port60);
1881 K_BUFSTARTP = 0x1e; /* Start of keyboard buffer */
1882 K_BUFENDP = 0x3e; /* End of keyboard buffer */
1883 K_NEXT = K_FREE = K_BUFSTARTP;
1885 vec = insert_hardint_trampoline();
1887 register_callback(vec, int09, "int 09");
1895 BIOSDATA[0x96] = 0x10; /* MF II kbd, 101 keys */
1903 /* Calculate 16 bit RGB values for X from the 6 bit DAC values and the
1904 palette. This works for 16 and 256 color modes, although we don't really
1905 support the latter yet. */
1907 dac2rgb(XColor *color, int i)
1911 /* 256 colors are easy; just take the RGB values from the DAC and
1912 shift left. For the pedants: multiplication with 65535./63. and
1913 rounding makes a difference of less than two percent. */
1914 if (VGA_ATC[ATC_ModeCtrl] & 0x40) {
1915 color->red = dac_rgb[i].red << 10;
1916 color->green = dac_rgb[i].green << 10;
1917 color->blue = dac_rgb[i].blue << 10;
1922 /* For the 16 color modes, check bit 7 of the Mode Control register in
1923 the ATC. If set, we take bits 0-3 of the Color Select register and
1924 bits 0-3 of the palette register 'i' to build the index into the
1925 DAC table; otherwise, bits 2 and 3 of the CS reg and bits 0-5 of
1926 the palette register are used. Note that the entries in 'palette[]'
1927 are supposed to be already masked to 6 bits. */
1928 if (VGA_ATC[ATC_ModeCtrl] & 0x80) {
1929 n = VGA_ATC[ATC_ColorSelect] & 0x0f;
1930 m = palette[i] & 0x0f;
1932 n = VGA_ATC[ATC_ColorSelect] & 0x0c;
1935 color->red = dac_rgb[16*n + m].red << 10;
1936 color->green = dac_rgb[16*n + m].green << 10;
1937 color->blue = dac_rgb[16*n + m].blue << 10;
1941 /* Get a connection to the X server and create the window. */
1951 * Arg... I can no longer change X's fd out from under it.
1952 * Open up all the available fd's, leave 3 behind for X
1953 * to play with, open X and then release all the other fds
1955 int nfds = sysconf(_SC_OPEN_MAX);
1956 int *fds = malloc(sizeof(int) * nfds);
1959 for (i = 0; i < nfds && (i == 0 || fds[i-1] < 63); ++i)
1960 if ((fds[i] = open(_PATH_DEVNULL, 0)) < 0)
1963 * Leave 3 fds behind for X to play with
1965 if (i > 0) close(fds[--i]);
1966 if (i > 0) close(fds[--i]);
1967 if (i > 0) close(fds[--i]);
1969 dpy = XOpenDisplay(NULL);
1975 err(1, "Could not open display ``%s''\n", XDisplayName(NULL));
1976 xfd = ConnectionNumber(dpy);
1978 _RegisterIO(xfd, video_async_event, 0, Failure);
1979 if (debug_flags & D_DEBUGIN)
1980 _RegisterIO(0, debug_event, 0, Failure);
1982 /* Create window, but defer setting a size and GC. */
1983 win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
1984 1, 1, 2, black, black);
1986 gcv.foreground = white;
1987 gcv.background = black;
1988 gc = XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
1992 gcv.function = GXxor;
1993 cgc = XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
1996 XSelectInput(dpy, win, ExposureMask | ButtonPressMask
1997 | ButtonReleaseMask | PointerMotionMask );
1999 XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
2000 ExposureMask | ButtonPressMask
2001 | ButtonReleaseMask | PointerMotionMask );
2004 XStoreName(dpy, win, "DOS");
2006 /* Get the default visual and depth for later use. */
2007 depth = DefaultDepth(dpy, DefaultScreen(dpy));
2008 visual = DefaultVisual(dpy, DefaultScreen(dpy));
2013 /* While we are developing the graphics code ... */
2014 call_on_quit(write_vram, NULL);
2028 font = XLoadQueryFont(dpy, xfont);
2031 font = XLoadQueryFont(dpy, FONTVGA);
2034 err(1, "Could not open font ``%s''\n", xfont);
2036 gcv.font = font->fid;
2037 XChangeGC(dpy, gc, GCFont, &gcv);
2039 FW = font->max_bounds.width;
2040 FH = font->max_bounds.ascent + font->max_bounds.descent;
2041 FD = font->max_bounds.descent;
2043 /* Put the pixel representation at c000:3000. */
2044 switch (CharHeight) {
2046 memcpy((void *)0xc3000, font8x8, sizeof(font8x8));
2049 memcpy((void *)0xc3000, font8x14, sizeof(font8x14));
2052 memcpy((void *)0xc3000, font8x16, sizeof(font8x16));
2055 err(1, "load_font: CharHeight = %d?", CharHeight);
2062 /* Get a new, or resize an old XImage as canvas for the graphics display. */
2070 xi = XCreateImage(dpy, visual, depth, ZPixmap, 0, NULL,
2071 width, height, 32, 0);
2073 err(1, "Could not get ximage");
2075 xi->data = malloc(width * height * depth / 8);
2076 if (xi->data == NULL) {
2078 err(1, "Could not get memory for ximage data");
2085 /* Get memory for the text line buffer. */
2091 if (lines == NULL) {
2092 lines = (TextLine *)malloc(sizeof(TextLine) * height);
2094 err(1, "Could not allocate data structure for text lines\n");
2096 for (i = 0; i < height; ++i) {
2097 lines[i].max_length = width;
2098 lines[i].data = (u_short *)malloc(width * sizeof(u_short));
2099 if (lines[i].data == NULL)
2100 err(1, "Could not allocate data structure for text lines\n");
2101 lines[i].changed = 1;
2104 lines = (TextLine *)realloc(lines, sizeof(TextLine) * height);
2106 err(1, "Could not allocate data structure for text lines\n");
2108 for (i = 0; i < height; ++i) {
2109 lines[i].max_length = width;
2110 lines[i].data = (u_short *)realloc(lines[i].data,
2111 width * sizeof(u_short));
2112 if (lines[i].data == NULL)
2113 err(1, "Could not allocate data structure for text lines\n");
2114 lines[i].changed = 1;
2120 /* Prepare the LUT for the VRAM -> XImage conversion. */
2126 for (i = 0; i < 4; i++) {
2127 for (j = 0; j < 256; j++) {
2128 for (k = 0; k < 8; k++) {
2129 lut[i][j][7 - k] = ((j & (1 << k)) ? (1 << i) : 0);
2138 /* Resize the window, using information from 'vga_status[]'. This function is
2139 called after a mode change. */
2147 sh = XAllocSizeHints();
2149 err(1, "Could not get XSizeHints structure");
2153 height = DpyRows + 1;
2156 vmode = vmodelist[find_vmode(VideoMode)];
2157 if (vmode.type == TEXT) {
2158 sh->base_width = FW * width + 4;
2159 sh->base_height = FH * height + 4;
2160 sh->base_width += 4;
2161 sh->base_height += 4;
2164 height *= CharHeight;
2165 sh->base_width = width;
2166 sh->base_height = height;
2169 sh->min_width = sh->max_width = sh->base_width;
2170 sh->min_height = sh->max_height = sh->base_height;
2171 sh->flags = USSize | PMinSize | PMaxSize | PSize;
2173 debug(D_VIDEO, "VGA: Set window size %dx%d\n",
2174 sh->base_width, sh->base_height);
2176 XSetWMNormalHints(dpy, win, sh);
2177 XResizeWindow(dpy, win, sh->base_width, sh->base_height);
2178 XMapWindow(dpy, win);
2187 /* Calculate 'pixels[]' from the current DAC table and palette.
2189 To do: do not use 'pixels[]', use an array of 'XColor's which we can
2190 allocate and free on demand. Install a private colormap if necessary. */
2197 /* We support only 16 colors for now. */
2198 for (i = 0; i < 16; i++) {
2202 if (XAllocColor(dpy,
2203 DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
2204 pixels[i] = color.pixel;
2206 pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
2208 pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
2214 write_vram(void *arg __unused)
2218 if ((fd = open("vram", O_WRONLY | O_CREAT, 0644)) == -1)
2219 err(1, "Can't open vram file");
2220 (void)write(fd, (void *)vram, 256 * 1024);