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
, int cond
, void *arg
, 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
, regcontext_t
*REGS
)
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
, regcontext_t
*REGS
)
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);