1 /*- 2 * Copyright (c) 1992-1994 S�ren Schmidt 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz and Don Ahn. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer 14 * in this position and unchanged. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * $Id: syscons.c,v 1.59 1994/09/29 08:29:21 sos Exp $ 39 */ 40 41 #include "sc.h" 42 43 #if NSC > 0 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/conf.h> 48 #include <sys/ioctl.h> 49 #include <sys/proc.h> 50 #include <sys/user.h> 51 #include <sys/tty.h> 52 #include <sys/uio.h> 53 #include <sys/callout.h> 54 #include <sys/kernel.h> 55 #include <sys/syslog.h> 56 #include <sys/errno.h> 57 #include <sys/malloc.h> 58 #include <machine/console.h> 59 #include <machine/psl.h> 60 #include <machine/frame.h> 61 #include <machine/pc/display.h> 62 #include <i386/isa/isa.h> 63 #include <i386/isa/isa_device.h> 64 #include <i386/isa/timerreg.h> 65 #include <i386/isa/kbdtables.h> 66 #include <i386/i386/cons.h> 67 68 #if !defined(NCONS) 69 #define NCONS 12 70 #endif 71 72 #if defined(HARDFONTS) 73 #include <i386/isa/iso8859.font> 74 #endif 75 76 /* status flags */ 77 #define LOCK_KEY_MASK 0x0000F 78 #define LED_MASK 0x00007 79 #define UNKNOWN_MODE 0x00010 80 #define KBD_RAW_MODE 0x00020 81 #define SWITCH_WAIT_REL 0x00040 82 #define SWITCH_WAIT_ACQ 0x00080 83 84 /* video hardware memory addresses */ 85 #define VIDEOMEM 0x000A0000 86 87 /* misc defines */ 88 #define MAX_ESC_PAR 5 89 #define LOAD 1 90 #define SAVE 0 91 #define COL 80 92 #define ROW 25 93 #define BELL_DURATION 5 94 #define BELL_PITCH 800 95 #define TIMER_FREQ 1193182 /* should be in isa.h */ 96 #define CONSOLE_BUFSIZE 1024 97 #define PCBURST 128 98 #define FONT_8_LOADED 0x001 99 #define FONT_14_LOADED 0x002 100 #define FONT_16_LOADED 0x004 101 102 /* defines related to hardware addresses */ 103 #define MONO_BASE 0x3B4 /* crt controller base mono */ 104 #define COLOR_BASE 0x3D4 /* crt controller base color */ 105 #define MISC 0x3C2 /* misc output register */ 106 #define ATC IO_VGA+0x00 /* attribute controller */ 107 #define TSIDX IO_VGA+0x04 /* timing sequencer idx */ 108 #define TSREG IO_VGA+0x05 /* timing sequencer data */ 109 #define PIXMASK IO_VGA+0x06 /* pixel write mask */ 110 #define PALRADR IO_VGA+0x07 /* palette read address */ 111 #define PALWADR IO_VGA+0x08 /* palette write address */ 112 #define PALDATA IO_VGA+0x09 /* palette data register */ 113 #define GDCIDX IO_VGA+0x0E /* graph data controller idx */ 114 #define GDCREG IO_VGA+0x0F /* graph data controller data */ 115 116 /* special characters */ 117 #define cntlc 0x03 118 #define cntld 0x04 119 #define bs 0x08 120 #define lf 0x0a 121 #define cr 0x0d 122 #define del 0x7f 123 124 typedef struct term_stat { 125 int esc; /* processing escape sequence */ 126 int num_param; /* # of parameters to ESC */ 127 int last_param; /* last parameter # */ 128 int param[MAX_ESC_PAR]; /* contains ESC parameters */ 129 int cur_attr; /* current attributes */ 130 int std_attr; /* normal attributes */ 131 int rev_attr; /* reverse attributes */ 132 } term_stat; 133 134 typedef struct scr_stat { 135 u_short *crt_base; /* address of screen memory */ 136 u_short *scr_buf; /* buffer when off screen */ 137 u_short *crtat; /* cursor address */ 138 int xpos; /* current X position */ 139 int ypos; /* current Y position */ 140 int xsize; /* X size */ 141 int ysize; /* Y size */ 142 term_stat term; /* terminal emulation stuff */ 143 char cursor_start; /* cursor start line # */ 144 char cursor_end; /* cursor end line # */ 145 u_char border; /* border color */ 146 u_short bell_duration; 147 u_short bell_pitch; 148 u_short status; /* status (bitfield) */ 149 u_short mode; /* mode */ 150 pid_t pid; /* pid of controlling proc */ 151 struct proc *proc; /* proc* of controlling proc */ 152 struct vt_mode smode; /* switch mode */ 153 } scr_stat; 154 155 typedef struct default_attr { 156 int std_attr; /* normal attributes */ 157 int rev_attr; /* reverse attributes */ 158 } default_attr; 159 160 static default_attr user_default = { 161 (FG_LIGHTGREY | BG_BLACK) << 8, 162 (FG_BLACK | BG_LIGHTGREY) << 8 163 }; 164 165 static default_attr kernel_default = { 166 (FG_WHITE | BG_BLACK) << 8, 167 (FG_BLACK | BG_LIGHTGREY) << 8 168 }; 169 170 static scr_stat console[NCONS]; 171 static scr_stat *cur_console = &console[0]; 172 static scr_stat *new_scp, *old_scp; 173 static term_stat kernel_console; 174 static default_attr *current_default; 175 static int console_buffer_count; 176 static char console_buffer[CONSOLE_BUFSIZE]; 177 static int switch_in_progress = 0; 178 static u_short *crtat = 0; 179 static u_int crtc_addr = MONO_BASE; 180 static char crtc_vga = 0; 181 static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 182 static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 183 static char *font_8 = NULL, *font_14 = NULL, *font_16 = NULL; 184 static int fonts_loaded = 0; 185 static char palette[3*256]; 186 static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 187 static int cur_cursor_pos = -1; 188 static char in_putc = 0; 189 static char polling = 0; 190 #if ASYNCH 191 static u_char kbd_reply = 0; 192 #endif 193 static int delayed_next_scr; 194 static char saved_console = -1; /* saved console number */ 195 static long scrn_blank_time = 0; /* screen saver timeout value */ 196 static int scrn_blanked = 0; /* screen saver active flag */ 197 static int scrn_saver = 0; /* screen saver routine */ 198 static long scrn_time_stamp; 199 static u_char scr_map[256]; 200 201 /* function prototypes */ 202 int pcprobe(struct isa_device *dev); 203 int pcattach(struct isa_device *dev); 204 int pcopen(dev_t dev, int flag, int mode, struct proc *p); 205 int pcclose(dev_t dev, int flag, int mode, struct proc *p); 206 int pcread(dev_t dev, struct uio *uio, int flag); 207 int pcwrite(dev_t dev, struct uio *uio, int flag); 208 int pcparam(struct tty *tp, struct termios *t); 209 int pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p); 210 void pcxint(dev_t dev); 211 void pcstart(struct tty *tp); 212 void pccnprobe(struct consdev *cp); 213 void pccninit(struct consdev *cp); 214 void pccnputc(dev_t dev, char c); 215 int pccngetc(dev_t dev); 216 void scintr(int unit); 217 int pcmmap(dev_t dev, int offset, int nprot); 218 u_int sgetc(int noblock); 219 int getchar(void); 220 static void scinit(void); 221 static void scput(u_char c); 222 static u_int scgetc(int noblock); 223 static struct tty *get_tty_ptr(dev_t dev); 224 static scr_stat *get_scr_stat(dev_t dev); 225 static int get_scr_num(); 226 static void cursor_shape(int start, int end); 227 static void get_cursor_shape(int *start, int *end); 228 static void cursor_pos(int force); 229 static void clear_screen(scr_stat *scp); 230 static int switch_scr(u_int next_scr); 231 static void exchange_scr(void); 232 static void move_crsr(scr_stat *scp, int x, int y); 233 static void move_up(u_short *s, u_short *d, u_int len); 234 static void move_down(u_short *s, u_short *d, u_int len); 235 static void scan_esc(scr_stat *scp, u_char c); 236 static void ansi_put(scr_stat *scp, u_char c); 237 static u_char *get_fstr(u_int c, u_int *len); 238 static void update_leds(int which); 239 static void kbd_wait(void); 240 static void kbd_cmd(u_char command); 241 static void set_mode(scr_stat *scp); 242 static void set_border(int color); 243 static void set_vgaregs(char *modetable); 244 static void copy_font(int direction, int segment, int size, char* font); 245 static void save_palette(void); 246 static void load_palette(void); 247 248 /* available screen savers */ 249 static void none_saver(int test); 250 static void blank_saver(int test); 251 static void fade_saver(int test); 252 static void star_saver(int test); 253 static void snake_saver(int test); 254 static void green_saver(int test); 255 256 static const struct { 257 char *name; 258 void (*routine)(); 259 } screen_savers[] = { 260 { "none", none_saver }, /* 0 */ 261 { "blank", blank_saver }, /* 1 */ 262 { "fade", fade_saver }, /* 2 */ 263 { "star", star_saver }, /* 3 */ 264 { "snake", snake_saver }, /* 4 */ 265 { "green", green_saver }, /* 5 */ 266 }; 267 #define SCRN_SAVER(arg) (*screen_savers[scrn_saver].routine)(arg) 268 #define NUM_SCRN_SAVERS (sizeof(screen_savers) / sizeof(screen_savers[0])) 269 270 /* OS specific stuff */ 271 #if 0 272 #define VIRTUAL_TTY(x) (pccons[x] = ttymalloc(pccons[x])) 273 #define CONSOLE_TTY (pccons[NCONS] = ttymalloc(pccons[NCONS])) 274 struct tty *pccons[NCONS+1]; 275 #else 276 #define VIRTUAL_TTY(x) &pccons[x] 277 #define CONSOLE_TTY &pccons[NCONS] 278 struct tty pccons[NCONS+1]; 279 #endif 280 #define timeout_t timeout_func_t 281 #define MONO_BUF (KERNBASE+0xB0000) 282 #define CGA_BUF (KERNBASE+0xB8000) 283 u_short *Crtat = (u_short *)MONO_BUF; 284 void consinit(void) {scinit();} 285 extern char *video_mode_ptr; 286 287 struct isa_driver scdriver = { 288 pcprobe, pcattach, "sc", 289 }; 290 291 int 292 pcprobe(struct isa_device *dev) 293 { 294 int i, retries = 5; 295 unsigned char val; 296 297 /* Enable interrupts and keyboard controller */ 298 kbd_wait(); 299 outb(KB_STAT, KB_WRITE); 300 kbd_wait(); 301 outb(KB_DATA, KB_MODE); 302 303 /* flush any noise in the buffer */ 304 while (inb(KB_STAT) & KB_BUF_FULL) { 305 DELAY(10); 306 (void) inb(KB_DATA); 307 } 308 309 /* Reset keyboard hardware */ 310 while (retries--) { 311 kbd_wait(); 312 outb(KB_DATA, KB_RESET); 313 for (i=0; i<100000; i++) { 314 DELAY(10); 315 val = inb(KB_DATA); 316 if (val == KB_ACK || val == KB_ECHO) 317 goto gotres; 318 if (val == KB_RESEND) 319 break; 320 } 321 } 322 gotres: 323 if (!retries) 324 printf("scprobe: keyboard won't accept RESET command\n"); 325 else { 326 gotack: 327 DELAY(10); 328 while ((inb(KB_STAT) & KB_BUF_FULL) == 0) DELAY(10); 329 DELAY(10); 330 val = inb(KB_DATA); 331 if (val == KB_ACK) 332 goto gotack; 333 if (val != KB_RESET_DONE) 334 printf("scprobe: keyboard RESET failed %02x\n", val); 335 } 336 return (IO_KBDSIZE); 337 } 338 339 int 340 pcattach(struct isa_device *dev) 341 { 342 int i; 343 struct scr_stat *scp; 344 345 printf("sc%d: ", dev->id_unit); 346 if (crtc_vga) 347 if (crtc_addr == MONO_BASE) 348 printf("VGA mono"); 349 else 350 printf("VGA color"); 351 else 352 if (crtc_addr == MONO_BASE) 353 printf("MDA/hercules"); 354 else 355 printf("CGA/EGA"); 356 if (NCONS > 1) 357 printf(" <%d virtual consoles>\n", NCONS); 358 else 359 printf("\n"); 360 if (crtc_vga) { 361 #if defined(HARDFONTS) 362 font_8 = font_8x8; 363 font_14 = font_8x14; 364 font_16 = font_8x16; 365 fonts_loaded = FONT_8_LOADED|FONT_14_LOADED|FONT_16_LOADED; 366 copy_font(LOAD, 1, 8, font_8); 367 copy_font(LOAD, 2, 14, font_14); 368 copy_font(LOAD, 0, 16, font_16); 369 #else 370 font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT); 371 font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT); 372 font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT); 373 copy_font(SAVE, 0, 16, font_16); 374 fonts_loaded = FONT_16_LOADED; 375 #endif 376 save_palette(); 377 } 378 for (i = 0; i < NCONS; i++) { 379 scp = &console[i]; 380 scp->scr_buf = (u_short *)malloc(COL*ROW*2, M_DEVBUF, M_NOWAIT); 381 if (i > 0) { 382 scp->crt_base = scp->crtat = scp->scr_buf; 383 clear_screen(scp); 384 } 385 } 386 /* get cursor going */ 387 #if defined(FAT_CURSOR) 388 if (crtc_vga) 389 cursor_shape(console[0].cursor_start, 390 console[0].cursor_end); 391 #endif 392 cursor_pos(1); 393 update_leds(console[0].status); 394 return 0; 395 } 396 397 static struct tty 398 *get_tty_ptr(dev_t dev) 399 { 400 int unit = minor(dev); 401 402 if (unit > NCONS) 403 return(NULL); 404 if (unit == NCONS) 405 return(CONSOLE_TTY); 406 return(VIRTUAL_TTY(unit)); 407 } 408 409 static scr_stat 410 *get_scr_stat(dev_t dev) 411 { 412 int unit = minor(dev); 413 414 if (unit > NCONS) 415 return(NULL); 416 if (unit == NCONS) 417 return(&console[0]); 418 return(&console[unit]); 419 } 420 421 static int 422 get_scr_num() 423 { 424 int i = 0; 425 426 while ((i < NCONS) && (cur_console != &console[i])) i++; 427 return i < NCONS ? i : 0; 428 } 429 430 int 431 pcopen(dev_t dev, int flag, int mode, struct proc *p) 432 { 433 struct tty *tp = get_tty_ptr(dev); 434 435 if (!tp) 436 return(ENXIO); 437 438 tp->t_oproc = pcstart; 439 tp->t_param = pcparam; 440 tp->t_dev = dev; 441 if (!(tp->t_state & TS_ISOPEN)) { 442 ttychars(tp); 443 tp->t_iflag = TTYDEF_IFLAG; 444 tp->t_oflag = TTYDEF_OFLAG; 445 tp->t_cflag = TTYDEF_CFLAG; 446 tp->t_lflag = TTYDEF_LFLAG; 447 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 448 pcparam(tp, &tp->t_termios); 449 ttsetwater(tp); 450 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 451 return(EBUSY); 452 tp->t_state |= TS_CARR_ON; 453 tp->t_cflag |= CLOCAL; 454 return((*linesw[tp->t_line].l_open)(dev, tp)); 455 } 456 457 int 458 pcclose(dev_t dev, int flag, int mode, struct proc *p) 459 { 460 struct tty *tp = get_tty_ptr(dev); 461 struct scr_stat *scp; 462 463 if (!tp) 464 return(ENXIO); 465 if (minor(dev) < NCONS) { 466 scp = get_scr_stat(tp->t_dev); 467 if (scp->status & SWITCH_WAIT_ACQ) 468 wakeup((caddr_t)&scp->smode); 469 scp->pid = 0; 470 scp->proc = NULL; 471 scp->smode.mode = VT_AUTO; 472 } 473 (*linesw[tp->t_line].l_close)(tp, flag); 474 ttyclose(tp); 475 return(0); 476 } 477 478 int 479 pcread(dev_t dev, struct uio *uio, int flag) 480 { 481 struct tty *tp = get_tty_ptr(dev); 482 483 if (!tp) 484 return(ENXIO); 485 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 486 } 487 488 int 489 pcwrite(dev_t dev, struct uio *uio, int flag) 490 { 491 struct tty *tp = get_tty_ptr(dev); 492 493 if (!tp) 494 return(ENXIO); 495 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 496 } 497 498 void 499 scintr(int unit) 500 { 501 static struct tty *cur_tty; 502 int c, len; 503 u_char *cp; 504 505 /* make screensaver happy */ 506 scrn_time_stamp = time.tv_sec; 507 if (scrn_blanked) 508 SCRN_SAVER(0); 509 510 c = scgetc(1); 511 512 cur_tty = VIRTUAL_TTY(get_scr_num()); 513 if (!(cur_tty->t_state & TS_ISOPEN)) 514 cur_tty = CONSOLE_TTY; 515 516 if (!(cur_tty->t_state & TS_ISOPEN) || polling) 517 return; 518 519 switch (c & 0xff00) { 520 case 0x0000: /* normal key */ 521 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 522 break; 523 case NOKEY: /* nothing there */ 524 break; 525 case FKEY: /* function key, return string */ 526 if (cp = get_fstr((u_int)c, (u_int *)&len)) { 527 while (len-- > 0) 528 (*linesw[cur_tty->t_line].l_rint) 529 (*cp++ & 0xFF, cur_tty); 530 } 531 break; 532 case MKEY: /* meta is active, prepend ESC */ 533 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 534 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 535 break; 536 } 537 } 538 539 int 540 pcparam(struct tty *tp, struct termios *t) 541 { 542 int cflag = t->c_cflag; 543 544 /* and copy to tty */ 545 tp->t_ispeed = t->c_ispeed; 546 tp->t_ospeed = t->c_ospeed; 547 tp->t_cflag = cflag; 548 return 0; 549 } 550 551 int 552 pcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 553 { 554 int i, error; 555 struct tty *tp; 556 struct trapframe *fp; 557 scr_stat *scp; 558 559 tp = get_tty_ptr(dev); 560 if (!tp) 561 return ENXIO; 562 scp = get_scr_stat(tp->t_dev); 563 564 switch (cmd) { /* process console hardware related ioctl's */ 565 566 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 567 scrn_blank_time = *(int*)data; 568 return 0; 569 570 #define SAVER(p) ((ssaver_t *)(p)) 571 case CONS_SSAVER: /* set screen saver */ 572 if (SAVER(data)->num < 0 573 || SAVER(data)->num >= NUM_SCRN_SAVERS) 574 return EIO; 575 SCRN_SAVER(0); 576 scrn_saver = SAVER(data)->num; 577 scrn_blank_time = SAVER(data)->time; 578 return 0; 579 580 case CONS_GSAVER: /* get screen saver info */ 581 if (SAVER(data)->num < 0) 582 SAVER(data)->num = scrn_saver; 583 else if (SAVER(data)->num >= NUM_SCRN_SAVERS) 584 return EIO; 585 SAVER(data)->time = scrn_blank_time; 586 strcpy(SAVER(data)->name, screen_savers[SAVER(data)->num].name); 587 return 0; 588 589 case SW_VGA_C40x25: case SW_VGA_C80x25: /* VGA TEXT MODES */ 590 case SW_VGA_M80x25: 591 case SW_VGA_C80x50: case SW_VGA_M80x50: 592 case SW_B40x25: case SW_C40x25: 593 case SW_B80x25: case SW_C80x25: 594 case SW_ENH_B40x25: case SW_ENH_C40x25: 595 case SW_ENH_B80x25: case SW_ENH_C80x25: 596 case SW_ENH_B80x43: case SW_ENH_C80x43: 597 598 if (!crtc_vga) 599 return ENXIO; 600 cmd &= 0xFF; 601 i = cmd < M_VGA_C80x50 ? 602 *(video_mode_ptr + (cmd*64) + 2) : 0x08; 603 switch (i) { 604 default: 605 case 0x08: 606 if (!(fonts_loaded & FONT_8_LOADED)) 607 return EINVAL; 608 break; 609 case 0x0E: 610 if (!(fonts_loaded & FONT_14_LOADED)) 611 return EINVAL; 612 break; 613 case 0x10: 614 if (!(fonts_loaded & FONT_16_LOADED)) 615 return EINVAL; 616 break; 617 } 618 scp->mode = cmd; 619 scp->status &= ~UNKNOWN_MODE; /* text mode */ 620 if (scp->mode < M_VGA_C80x50) { 621 scp->xsize = *(video_mode_ptr + (scp->mode*64)); 622 scp->ysize = *(video_mode_ptr + (scp->mode*64) + 1) + 1; 623 } 624 else switch (scp->mode) { 625 case M_VGA_C80x50: case M_VGA_M80x50: 626 scp->xsize = 80; 627 scp->ysize = 50; 628 break; 629 case M_ENH_B80x43: case M_ENH_C80x43: 630 scp->xsize = 80; 631 scp->ysize = 43; 632 break; 633 } 634 free(scp->scr_buf, M_DEVBUF); 635 scp->scr_buf = (u_short *)malloc(scp->xsize * scp->ysize * 2, 636 M_DEVBUF, M_NOWAIT); 637 if (scp == cur_console) 638 set_mode(scp); 639 else 640 scp->crt_base = scp->scr_buf; 641 clear_screen(scp); 642 if (tp->t_winsize.ws_col != scp->xsize 643 || tp->t_winsize.ws_row != scp->ysize) { 644 tp->t_winsize.ws_col = scp->xsize; 645 tp->t_winsize.ws_row = scp->ysize; 646 pgsignal(tp->t_pgrp, SIGWINCH, 1); 647 } 648 return 0; 649 650 /* GRAPHICS MODES */ 651 case SW_BG320: case SW_CG320: case SW_BG640: 652 case SW_CG320_D: case SW_CG640_E: 653 case SW_CG640x350: case SW_ENH_CG640: 654 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 655 656 scp->mode = cmd & 0xFF; 657 scp->status |= UNKNOWN_MODE; /* graphics mode */ 658 if (scp == cur_console) 659 set_mode(scp); 660 /* clear_graphics();*/ 661 return 0; 662 663 case CONS_GETVERS: /* get version number */ 664 *(int*)data = 0x103; /* version 1.3 */ 665 return 0; 666 667 case CONS_GETINFO: /* get current (virtual) console info */ 668 { 669 vid_info_t *ptr = (vid_info_t*)data; 670 if (ptr->size == sizeof(struct vid_info)) { 671 ptr->m_num = get_scr_num(); 672 ptr->mv_col = scp->xpos; 673 ptr->mv_row = scp->ypos; 674 ptr->mv_csz = scp->xsize; 675 ptr->mv_rsz = scp->ysize; 676 ptr->mv_norm.fore = (scp->term.std_attr & 0x0f00)>>8; 677 ptr->mv_norm.back = (scp->term.std_attr & 0xf000)>>12; 678 ptr->mv_rev.fore = (scp->term.rev_attr & 0x0f00)>>8; 679 ptr->mv_rev.back = (scp->term.rev_attr & 0xf000)>>12; 680 ptr->mv_grfc.fore = 0; /* not supported */ 681 ptr->mv_grfc.back = 0; /* not supported */ 682 ptr->mv_ovscan = scp->border; 683 ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 684 return 0; 685 } 686 return EINVAL; 687 } 688 689 case VT_SETMODE: /* set screen switcher mode */ 690 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 691 if (scp->smode.mode == VT_PROCESS) { 692 scp->proc = p; 693 scp->pid = scp->proc->p_pid; 694 } 695 return 0; 696 697 case VT_GETMODE: /* get screen switcher mode */ 698 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 699 return 0; 700 701 case VT_RELDISP: /* screen switcher ioctl */ 702 switch(*data) { 703 case VT_FALSE: /* user refuses to release screen, abort */ 704 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 705 old_scp->status &= ~SWITCH_WAIT_REL; 706 switch_in_progress = 0; 707 return 0; 708 } 709 return EINVAL; 710 711 case VT_TRUE: /* user has released screen, go on */ 712 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 713 scp->status &= ~SWITCH_WAIT_REL; 714 exchange_scr(); 715 if (new_scp->smode.mode == VT_PROCESS) { 716 new_scp->status |= SWITCH_WAIT_ACQ; 717 psignal(new_scp->proc, 718 new_scp->smode.acqsig); 719 } 720 else 721 switch_in_progress = 0; 722 return 0; 723 } 724 return EINVAL; 725 726 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 727 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 728 scp->status &= ~SWITCH_WAIT_ACQ; 729 switch_in_progress = 0; 730 return 0; 731 } 732 return EINVAL; 733 734 default: 735 return EINVAL; 736 } 737 /* NOT REACHED */ 738 739 case VT_OPENQRY: /* return free virtual console */ 740 for (i = 0; i < NCONS; i++) { 741 tp = VIRTUAL_TTY(i); 742 if (!(tp->t_state & TS_ISOPEN)) { 743 *data = i + 1; 744 return 0; 745 } 746 } 747 return EINVAL; 748 749 case VT_ACTIVATE: /* switch to screen *data */ 750 return switch_scr((*data) - 1); 751 752 case VT_WAITACTIVE: /* wait for switch to occur */ 753 if (*data > NCONS) 754 return EINVAL; 755 if (minor(dev) == (*data) - 1) 756 return 0; 757 if (*data == 0) { 758 if (scp == cur_console) 759 return 0; 760 while ((error=tsleep((caddr_t)&scp->smode, 761 PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; 762 } 763 else 764 while ((error=tsleep( 765 (caddr_t)&console[*(data-1)].smode, 766 PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; 767 return error; 768 769 case VT_GETACTIVE: 770 *data = get_scr_num()+1; 771 return 0; 772 773 case KDENABIO: /* allow io operations */ 774 fp = (struct trapframe *)p->p_md.md_regs; 775 fp->tf_eflags |= PSL_IOPL; 776 return 0; 777 778 case KDDISABIO: /* disallow io operations (default) */ 779 fp = (struct trapframe *)p->p_md.md_regs; 780 fp->tf_eflags &= ~PSL_IOPL; 781 return 0; 782 783 case KDSETMODE: /* set current mode of this (virtual) console */ 784 switch (*data) { 785 case KD_TEXT: /* switch to TEXT (known) mode */ 786 /* restore fonts & palette ! */ 787 if (crtc_vga) { 788 if (fonts_loaded & FONT_16_LOADED) 789 copy_font(LOAD, 0, 16, font_16); 790 if (fonts_loaded & FONT_8_LOADED) 791 copy_font(LOAD, 1, 8, font_8); 792 if (fonts_loaded & FONT_14_LOADED) 793 copy_font(LOAD, 2, 14, font_14); 794 load_palette(); 795 } 796 /* FALL THROUGH */ 797 798 case KD_TEXT1: /* switch to TEXT (known) mode */ 799 /* no restore fonts & palette */ 800 scp->status &= ~UNKNOWN_MODE; 801 set_mode(scp); 802 clear_screen(scp); 803 return 0; 804 805 case KD_GRAPHICS:/* switch to GRAPHICS (unknown) mode */ 806 scp->status |= UNKNOWN_MODE; 807 return 0; 808 default: 809 return EINVAL; 810 } 811 /* NOT REACHED */ 812 813 case KDGETMODE: /* get current mode of this (virtual) console */ 814 *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 815 return 0; 816 817 case KDSBORDER: /* set border color of this (virtual) console */ 818 if (!crtc_vga) 819 return ENXIO; 820 scp->border = *data; 821 if (scp == cur_console) 822 set_border(scp->border); 823 return 0; 824 825 case KDSKBSTATE: /* set keyboard state (locks) */ 826 if (*data >= 0 && *data <= LOCK_KEY_MASK) { 827 scp->status &= ~LOCK_KEY_MASK; 828 scp->status |= *data; 829 if (scp == cur_console) 830 update_leds(scp->status); 831 return 0; 832 } 833 return EINVAL; 834 835 case KDGKBSTATE: /* get keyboard state (locks) */ 836 *data = scp->status & LOCK_KEY_MASK; 837 return 0; 838 839 case KDSETRAD: /* set keyboard repeat & delay rates */ 840 if (*data & 0x80) 841 return EINVAL; 842 i = spltty(); 843 kbd_cmd(KB_SETRAD); 844 kbd_cmd(*data); 845 splx(i); 846 return 0; 847 848 case KDSKBMODE: /* set keyboard mode */ 849 switch (*data) { 850 case K_RAW: /* switch to RAW scancode mode */ 851 scp->status |= KBD_RAW_MODE; 852 return 0; 853 854 case K_XLATE: /* switch to XLT ascii mode */ 855 if (scp == cur_console && scp->status == KBD_RAW_MODE) 856 shfts = ctls = alts = agrs = metas = 0; 857 scp->status &= ~KBD_RAW_MODE; 858 return 0; 859 default: 860 return EINVAL; 861 } 862 /* NOT REACHED */ 863 864 case KDGKBMODE: /* get keyboard mode */ 865 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE; 866 return 0; 867 868 case KDMKTONE: /* sound the bell */ 869 if (scp == cur_console) 870 sysbeep(scp->bell_pitch, scp->bell_duration); 871 return 0; 872 873 case KIOCSOUND: /* make tone (*data) hz */ 874 if (scp == cur_console) { 875 if (*(int*)data) { 876 int pitch = TIMER_FREQ/(*(int*)data); 877 /* set command for counter 2, 2 byte write */ 878 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) { 879 return EBUSY; 880 } 881 /* set pitch */ 882 outb(TIMER_CNTR2, pitch); 883 outb(TIMER_CNTR2, (pitch>>8)); 884 /* enable counter 2 output to speaker */ 885 outb(IO_PPI, inb(IO_PPI) | 3); 886 } 887 else { 888 /* disable counter 2 output to speaker */ 889 outb(IO_PPI, inb(IO_PPI) & 0xFC); 890 release_timer2(); 891 } 892 } 893 return 0; 894 895 case KDGKBTYPE: /* get keyboard type */ 896 *data = 0; /* type not known (yet) */ 897 return 0; 898 899 case KDSETLED: /* set keyboard LED status */ 900 if (*data >= 0 && *data <= LED_MASK) { 901 scp->status &= ~LED_MASK; 902 scp->status |= *data; 903 if (scp == cur_console) 904 update_leds(scp->status); 905 return 0; 906 } 907 return EINVAL; 908 909 case KDGETLED: /* get keyboard LED status */ 910 *data = scp->status & LED_MASK; 911 return 0; 912 913 case GETFKEY: /* get functionkey string */ 914 if (*(u_short*)data < n_fkey_tab) { 915 fkeyarg_t *ptr = (fkeyarg_t*)data; 916 bcopy(&fkey_tab[ptr->keynum].str, 917 ptr->keydef, 918 fkey_tab[ptr->keynum].len); 919 ptr->flen = fkey_tab[ptr->keynum].len; 920 return 0; 921 } 922 else 923 return EINVAL; 924 925 case SETFKEY: /* set functionkey string */ 926 if (*(u_short*)data < n_fkey_tab) { 927 fkeyarg_t *ptr = (fkeyarg_t*)data; 928 bcopy(ptr->keydef, 929 &fkey_tab[ptr->keynum].str, 930 min(ptr->flen, MAXFK)); 931 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 932 return 0; 933 } 934 else 935 return EINVAL; 936 937 case GIO_SCRNMAP: /* get output translation table */ 938 bcopy(&scr_map, data, sizeof(scr_map)); 939 return 0; 940 941 case PIO_SCRNMAP: /* set output translation table */ 942 bcopy(data, &scr_map, sizeof(scr_map)); 943 return 0; 944 945 case GIO_KEYMAP: /* get keyboard translation table */ 946 bcopy(&key_map, data, sizeof(key_map)); 947 return 0; 948 949 case PIO_KEYMAP: /* set keyboard translation table */ 950 bcopy(data, &key_map, sizeof(key_map)); 951 return 0; 952 953 case PIO_FONT8x8: /* set 8x8 dot font */ 954 if (!crtc_vga) 955 return ENXIO; 956 bcopy(data, font_8, 8*256); 957 fonts_loaded |= FONT_8_LOADED; 958 copy_font(LOAD, 1, 8, font_8); 959 return 0; 960 961 case GIO_FONT8x8: /* get 8x8 dot font */ 962 if (!crtc_vga) 963 return ENXIO; 964 if (fonts_loaded & FONT_8_LOADED) { 965 bcopy(font_8, data, 8*256); 966 return 0; 967 } 968 else 969 return ENXIO; 970 971 case PIO_FONT8x14: /* set 8x14 dot font */ 972 if (!crtc_vga) 973 return ENXIO; 974 bcopy(data, font_14, 14*256); 975 fonts_loaded |= FONT_14_LOADED; 976 copy_font(LOAD, 2, 14, font_14); 977 return 0; 978 979 case GIO_FONT8x14: /* get 8x14 dot font */ 980 if (!crtc_vga) 981 return ENXIO; 982 if (fonts_loaded & FONT_14_LOADED) { 983 bcopy(font_14, data, 14*256); 984 return 0; 985 } 986 else 987 return ENXIO; 988 989 case PIO_FONT8x16: /* set 8x16 dot font */ 990 if (!crtc_vga) 991 return ENXIO; 992 bcopy(data, font_16, 16*256); 993 fonts_loaded |= FONT_16_LOADED; 994 copy_font(LOAD, 0, 16, font_16); 995 return 0; 996 997 case GIO_FONT8x16: /* get 8x16 dot font */ 998 if (!crtc_vga) 999 return ENXIO; 1000 if (fonts_loaded & FONT_16_LOADED) { 1001 bcopy(font_16, data, 16*256); 1002 return 0; 1003 } 1004 else 1005 return ENXIO; 1006 1007 case CONSOLE_X_MODE_ON: /* just to be compatible */ 1008 if (saved_console < 0) { 1009 saved_console = get_scr_num(); 1010 switch_scr(minor(dev)); 1011 fp = (struct trapframe *)p->p_md.md_regs; 1012 fp->tf_eflags |= PSL_IOPL; 1013 scp->status |= UNKNOWN_MODE; 1014 scp->status |= KBD_RAW_MODE; 1015 return 0; 1016 } 1017 return EAGAIN; 1018 1019 case CONSOLE_X_MODE_OFF:/* just to be compatible */ 1020 fp = (struct trapframe *)p->p_md.md_regs; 1021 fp->tf_eflags &= ~PSL_IOPL; 1022 if (crtc_vga) { 1023 if (fonts_loaded & FONT_16_LOADED) 1024 copy_font(LOAD, 0, 16, font_16); 1025 if (fonts_loaded & FONT_8_LOADED) 1026 copy_font(LOAD, 1, 8, font_8); 1027 if (fonts_loaded & FONT_14_LOADED) 1028 copy_font(LOAD, 2, 14, font_14); 1029 load_palette(); 1030 } 1031 scp->status &= ~UNKNOWN_MODE; 1032 set_mode(scp); 1033 clear_screen(scp); 1034 scp->status &= ~KBD_RAW_MODE; 1035 switch_scr(saved_console); 1036 saved_console = -1; 1037 return 0; 1038 1039 case CONSOLE_X_BELL: /* more compatibility */ 1040 /* 1041 * if set, data is a pointer to a length 2 array of 1042 * integers. data[0] is the pitch in Hz and data[1] 1043 * is the duration in msec. 1044 */ 1045 if (data) 1046 sysbeep(TIMER_FREQ/((int*)data)[0], 1047 ((int*)data)[1]*hz/1000); 1048 else 1049 sysbeep(scp->bell_pitch, scp->bell_duration); 1050 return 0; 1051 1052 default: 1053 break; 1054 } 1055 1056 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1057 if (error >= 0) 1058 return(error); 1059 error = ttioctl(tp, cmd, data, flag); 1060 if (error >= 0) 1061 return(error); 1062 return(ENOTTY); 1063 } 1064 1065 void 1066 pcxint(dev_t dev) 1067 { 1068 struct tty *tp = get_tty_ptr(dev); 1069 1070 if (!tp) 1071 return; 1072 tp->t_state &= ~TS_BUSY; 1073 if (tp->t_line) 1074 (*linesw[tp->t_line].l_start)(tp); 1075 else 1076 pcstart(tp); 1077 } 1078 1079 void 1080 pcstart(struct tty *tp) 1081 { 1082 struct clist *rbp; 1083 int i, s, len; 1084 u_char buf[PCBURST]; 1085 scr_stat *scp = get_scr_stat(tp->t_dev); 1086 1087 if (scp->status & SLKED) 1088 return; 1089 s = spltty(); 1090 if (!(tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { 1091 tp->t_state |= TS_BUSY; 1092 splx(s); 1093 rbp = &tp->t_outq; 1094 while (rbp->c_cc) { 1095 len = q_to_b(rbp, buf, PCBURST); 1096 for (i=0; i<len; i++) 1097 if (buf[i]) ansi_put(scp, buf[i]); 1098 } 1099 s = spltty(); 1100 tp->t_state &= ~TS_BUSY; 1101 #if 0 1102 if (rbp->c_cc) { 1103 tp->t_state |= TS_TIMEOUT; 1104 timeout((timeout_t)ttrstrt, (caddr_t)tp, 1); 1105 } 1106 #endif 1107 if (rbp->c_cc <= tp->t_lowat) { 1108 if (tp->t_state & TS_ASLEEP) { 1109 tp->t_state &= ~TS_ASLEEP; 1110 wakeup((caddr_t)rbp); 1111 } 1112 selwakeup(&tp->t_wsel); 1113 } 1114 } 1115 splx(s); 1116 } 1117 1118 void 1119 pccnprobe(struct consdev *cp) 1120 { 1121 int maj; 1122 1123 /* locate the major number */ 1124 for (maj = 0; maj < nchrdev; maj++) 1125 if ((void*)cdevsw[maj].d_open == (void*)pcopen) 1126 break; 1127 1128 /* initialize required fields */ 1129 cp->cn_dev = makedev(maj, NCONS); 1130 cp->cn_pri = CN_INTERNAL; 1131 } 1132 1133 void 1134 pccninit(struct consdev *cp) 1135 { 1136 scinit(); 1137 } 1138 1139 void 1140 pccnputc(dev_t dev, char c) 1141 { 1142 if (c == '\n') 1143 scput('\r'); 1144 scput(c); 1145 if (cur_console == &console[0]) { 1146 int pos = cur_console->crtat - cur_console->crt_base; 1147 if (pos != cur_cursor_pos) { 1148 cur_cursor_pos = pos; 1149 outb(crtc_addr,14); 1150 outb(crtc_addr+1,pos >> 8); 1151 outb(crtc_addr,15); 1152 outb(crtc_addr+1,pos&0xff); 1153 } 1154 } 1155 } 1156 1157 int 1158 pccngetc(dev_t dev) 1159 { 1160 int s = spltty(); /* block scintr while we poll */ 1161 int c = scgetc(0); 1162 splx(s); 1163 if (c == '\r') c = '\n'; 1164 return(c); 1165 } 1166 1167 static void 1168 none_saver(int test) 1169 { 1170 } 1171 1172 static void 1173 fade_saver(int test) 1174 { 1175 static int count = 0; 1176 int i; 1177 1178 if (test) { 1179 scrn_blanked = 1; 1180 if (count < 64) { 1181 outb(PIXMASK, 0xFF); /* no pixelmask */ 1182 outb(PALWADR, 0x00); 1183 outb(PALDATA, 0); 1184 outb(PALDATA, 0); 1185 outb(PALDATA, 0); 1186 for (i = 3; i < 768; i++) { 1187 if (palette[i] - count > 15) 1188 outb(PALDATA, palette[i]-count); 1189 else 1190 outb(PALDATA, 15); 1191 } 1192 inb(crtc_addr+6); /* reset flip/flop */ 1193 outb(ATC, 0x20); /* enable palette */ 1194 count++; 1195 } 1196 } 1197 else { 1198 count = scrn_blanked = 0; 1199 load_palette(); 1200 } 1201 } 1202 1203 static void 1204 blank_saver(int test) 1205 { 1206 u_char val; 1207 if (test) { 1208 scrn_blanked = 1; 1209 outb(TSIDX, 0x01); val = inb(TSREG); 1210 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 1211 } 1212 else { 1213 scrn_blanked = 0; 1214 outb(TSIDX, 0x01); val = inb(TSREG); 1215 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 1216 } 1217 } 1218 1219 static void 1220 green_saver(int test) 1221 { 1222 u_char val; 1223 if (test) { 1224 scrn_blanked = 1; 1225 outb(TSIDX, 0x01); val = inb(TSREG); 1226 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 1227 outb(crtc_addr, 0x17); val = inb(crtc_addr + 1); 1228 outb(crtc_addr + 1, val & ~0x80); 1229 } 1230 else { 1231 scrn_blanked = 0; 1232 outb(TSIDX, 0x01); val = inb(TSREG); 1233 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 1234 outb(crtc_addr, 0x17); val = inb(crtc_addr + 1); 1235 outb(crtc_addr + 1, val | 0x80); 1236 } 1237 } 1238 1239 #define NUM_STARS 50 1240 1241 /* 1242 * Alternate saver that got its inspiration from a well known utility 1243 * package for an inferior^H^H^H^H^H^Hfamous OS. 1244 */ 1245 static void 1246 star_saver(int test) 1247 { 1248 scr_stat *scp = cur_console; 1249 int cell, i; 1250 char pattern[] = {"...........++++*** "}; 1251 char colors[] = {FG_DARKGREY, FG_LIGHTGREY, 1252 FG_WHITE, FG_LIGHTCYAN}; 1253 static u_short stars[NUM_STARS][2]; 1254 1255 if (test) { 1256 if (!scrn_blanked) { 1257 bcopy(Crtat, scp->scr_buf, 1258 scp->xsize * scp->ysize * 2); 1259 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], Crtat, 1260 scp->xsize * scp->ysize); 1261 set_border(0); 1262 i = scp->ysize * scp->xsize + 5; 1263 outb(crtc_addr, 14); 1264 outb(crtc_addr+1, i >> 8); 1265 outb(crtc_addr, 15); 1266 outb(crtc_addr+1, i & 0xff); 1267 scrn_blanked = 1; 1268 for(i=0; i<NUM_STARS; i++) { 1269 stars[i][0] = 1270 random() % (scp->xsize*scp->ysize); 1271 stars[i][1] = 0; 1272 } 1273 } 1274 cell = random() % NUM_STARS; 1275 *((u_short*)(Crtat + stars[cell][0])) = 1276 scr_map[pattern[stars[cell][1]]] | 1277 colors[random()%sizeof(colors)] << 8; 1278 if ((stars[cell][1]+=(random()%4)) >= sizeof(pattern)-1) { 1279 stars[cell][0] = random() % (scp->xsize*scp->ysize); 1280 stars[cell][1] = 0; 1281 } 1282 } 1283 else { 1284 if (scrn_blanked) { 1285 bcopy(scp->scr_buf, Crtat, scp->xsize*scp->ysize*2); 1286 cur_cursor_pos = -1; 1287 set_border(scp->border); 1288 scrn_blanked = 0; 1289 } 1290 } 1291 } 1292 1293 static void 1294 snake_saver(int test) 1295 { 1296 const char saves[] = {"FreeBSD-2.0"}; 1297 static u_char *savs[sizeof(saves)-1]; 1298 static int dirx, diry; 1299 int f; 1300 scr_stat *scp = cur_console; 1301 1302 if (test) { 1303 if (!scrn_blanked) { 1304 bcopy(Crtat, scp->scr_buf, 1305 scp->xsize * scp->ysize * 2); 1306 fillw((FG_LIGHTGREY|BG_BLACK)<<8 | scr_map[0x20], 1307 Crtat, scp->xsize * scp->ysize); 1308 set_border(0); 1309 dirx = (scp->xpos ? 1 : -1); 1310 diry = (scp->ypos ? 1311 scp->xsize : -scp->xsize); 1312 for (f=0; f< sizeof(saves)-1; f++) 1313 savs[f] = (u_char *)Crtat + 2 * 1314 (scp->xpos+scp->ypos*scp->xsize); 1315 *(savs[0]) = scr_map[*saves]; 1316 f = scp->ysize * scp->xsize + 5; 1317 outb(crtc_addr, 14); 1318 outb(crtc_addr+1, f >> 8); 1319 outb(crtc_addr, 15); 1320 outb(crtc_addr+1, f & 0xff); 1321 scrn_blanked = 1; 1322 } 1323 if (scrn_blanked++ < 4) 1324 return; 1325 scrn_blanked = 1; 1326 *(savs[sizeof(saves)-2]) = scr_map[0x20]; 1327 for (f=sizeof(saves)-2; f > 0; f--) 1328 savs[f] = savs[f-1]; 1329 f = (savs[0] - (u_char *)Crtat) / 2; 1330 if ((f % scp->xsize) == 0 || 1331 (f % scp->xsize) == scp->xsize - 1 || 1332 (random() % 50) == 0) 1333 dirx = -dirx; 1334 if ((f / scp->xsize) == 0 || 1335 (f / scp->xsize) == scp->ysize - 1 || 1336 (random() % 20) == 0) 1337 diry = -diry; 1338 savs[0] += 2*dirx + 2*diry; 1339 for (f=sizeof(saves)-2; f>=0; f--) 1340 *(savs[f]) = scr_map[saves[f]]; 1341 } 1342 else { 1343 if (scrn_blanked) { 1344 bcopy(scp->scr_buf, Crtat, 1345 scp->xsize * scp->ysize * 2); 1346 cur_cursor_pos = -1; 1347 set_border(scp->border); 1348 scrn_blanked = 0; 1349 } 1350 } 1351 } 1352 1353 static void 1354 cursor_shape(int start, int end) 1355 { 1356 outb(crtc_addr, 10); 1357 outb(crtc_addr+1, start & 0xFF); 1358 outb(crtc_addr, 11); 1359 outb(crtc_addr+1, end & 0xFF); 1360 } 1361 1362 #if !defined(FAT_CURSOR) 1363 static void 1364 get_cursor_shape(int *start, int *end) 1365 { 1366 outb(crtc_addr, 10); 1367 *start = inb(crtc_addr+1) & 0x1F; 1368 outb(crtc_addr, 11); 1369 *end = inb(crtc_addr+1) & 0x1F; 1370 } 1371 #endif 1372 1373 static void 1374 cursor_pos(int force) 1375 { 1376 int pos; 1377 1378 if (cur_console->status & UNKNOWN_MODE) 1379 return; 1380 if (scrn_blank_time && (time.tv_sec > scrn_time_stamp+scrn_blank_time)) 1381 SCRN_SAVER(1); 1382 pos = cur_console->crtat - cur_console->crt_base; 1383 if (force || (!scrn_blanked && pos != cur_cursor_pos)) { 1384 cur_cursor_pos = pos; 1385 outb(crtc_addr, 14); 1386 outb(crtc_addr+1, pos>>8); 1387 outb(crtc_addr, 15); 1388 outb(crtc_addr+1, pos&0xff); 1389 } 1390 timeout((timeout_t)cursor_pos, 0, hz/20); 1391 } 1392 1393 static void 1394 clear_screen(scr_stat *scp) 1395 { 1396 move_crsr(scp, 0, 0); 1397 fillw(scp->term.cur_attr | scr_map[0x20], scp->crt_base, 1398 scp->xsize * scp->ysize); 1399 } 1400 1401 static int 1402 switch_scr(u_int next_scr) 1403 { 1404 if (switch_in_progress && 1405 (cur_console->proc != pfind(cur_console->pid))) 1406 switch_in_progress = 0; 1407 1408 if (next_scr >= NCONS || switch_in_progress 1409 || (cur_console->smode.mode == VT_AUTO 1410 && cur_console->status & UNKNOWN_MODE)) { 1411 sysbeep(BELL_PITCH, BELL_DURATION); 1412 return EINVAL; 1413 } 1414 1415 /* is the wanted virtual console open ? */ 1416 if (next_scr) { 1417 struct tty *tp = VIRTUAL_TTY(next_scr); 1418 if (!(tp->t_state & TS_ISOPEN)) { 1419 sysbeep(BELL_PITCH, BELL_DURATION); 1420 return EINVAL; 1421 } 1422 } 1423 if (in_putc) { /* delay switch if in putc */ 1424 delayed_next_scr = next_scr+1; 1425 return 0; 1426 } 1427 switch_in_progress = 1; 1428 old_scp = cur_console; 1429 new_scp = &console[next_scr]; 1430 wakeup((caddr_t)&new_scp->smode); 1431 if (new_scp == old_scp) { 1432 switch_in_progress = 0; 1433 return 0; 1434 } 1435 1436 /* has controlling process died? */ 1437 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1438 old_scp->smode.mode = VT_AUTO; 1439 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1440 new_scp->smode.mode = VT_AUTO; 1441 1442 /* check the modes and switch approbiatly */ 1443 if (old_scp->smode.mode == VT_PROCESS) { 1444 old_scp->status |= SWITCH_WAIT_REL; 1445 psignal(old_scp->proc, old_scp->smode.relsig); 1446 } 1447 else { 1448 exchange_scr(); 1449 if (new_scp->smode.mode == VT_PROCESS) { 1450 new_scp->status |= SWITCH_WAIT_ACQ; 1451 psignal(new_scp->proc, new_scp->smode.acqsig); 1452 } 1453 else 1454 switch_in_progress = 0; 1455 } 1456 return 0; 1457 } 1458 1459 static void 1460 exchange_scr(void) 1461 { 1462 struct tty *tp; 1463 1464 bcopy(Crtat, old_scp->scr_buf, old_scp->xsize * old_scp->ysize * 2); 1465 old_scp->crt_base = old_scp->scr_buf; 1466 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1467 cur_console = new_scp; 1468 if (old_scp->mode != new_scp->mode) 1469 set_mode(new_scp); 1470 new_scp->crt_base = Crtat; 1471 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1472 bcopy(new_scp->scr_buf, Crtat, new_scp->xsize * new_scp->ysize * 2); 1473 update_leds(new_scp->status); 1474 if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) { 1475 if (fonts_loaded & FONT_16_LOADED) 1476 copy_font(LOAD, 0, 16, font_16); 1477 if (fonts_loaded & FONT_8_LOADED) 1478 copy_font(LOAD, 1, 8, font_8); 1479 if (fonts_loaded & FONT_14_LOADED) 1480 copy_font(LOAD, 2, 14, font_14); 1481 load_palette(); 1482 } 1483 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1484 shfts = ctls = alts = agrs = metas = 0; 1485 delayed_next_scr = 0; 1486 } 1487 1488 static void 1489 move_crsr(scr_stat *scp, int x, int y) 1490 { 1491 if (x < 0 || y < 0 || x >= scp->xsize || y >= scp->ysize) 1492 return; 1493 scp->xpos = x; 1494 scp->ypos = y; 1495 scp->crtat = scp->crt_base + scp->ypos * scp->xsize + scp->xpos; 1496 } 1497 1498 static void 1499 move_up(u_short *s, u_short *d, u_int len) 1500 { 1501 s += len; 1502 d += len; 1503 while (len-- > 0) 1504 *--d = *--s; 1505 } 1506 1507 static void 1508 move_down(u_short *s, u_short *d, u_int len) 1509 { 1510 while (len-- > 0) 1511 *d++ = *s++; 1512 } 1513 1514 static void 1515 scan_esc(scr_stat *scp, u_char c) 1516 { 1517 static u_char ansi_col[16] = 1518 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1519 int i, n; 1520 u_short *src, *dst, count; 1521 1522 if (scp->term.esc == 1) { 1523 switch (c) { 1524 1525 case '[': /* Start ESC [ sequence */ 1526 scp->term.esc = 2; 1527 scp->term.last_param = -1; 1528 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1529 scp->term.param[i] = 1; 1530 scp->term.num_param = 0; 1531 return; 1532 1533 case 'M': /* Move cursor up 1 line, scroll if at top */ 1534 if (scp->ypos > 0) 1535 move_crsr(scp, scp->xpos, scp->ypos - 1); 1536 else { 1537 move_up(scp->crt_base, 1538 scp->crt_base + scp->xsize, 1539 (scp->ysize - 1) * scp->xsize); 1540 fillw(scp->term.cur_attr | scr_map[0x20], 1541 scp->crt_base, scp->xsize); 1542 } 1543 break; 1544 #if notyet 1545 case 'Q': 1546 scp->term.esc = 4; 1547 break; 1548 #endif 1549 case 'c': /* Clear screen & home */ 1550 clear_screen(scp); 1551 break; 1552 } 1553 } 1554 else if (scp->term.esc == 2) { 1555 if (c >= '0' && c <= '9') { 1556 if (scp->term.num_param < MAX_ESC_PAR) { 1557 if (scp->term.last_param != scp->term.num_param) { 1558 scp->term.last_param = scp->term.num_param; 1559 scp->term.param[scp->term.num_param] = 0; 1560 } 1561 else 1562 scp->term.param[scp->term.num_param] *= 10; 1563 scp->term.param[scp->term.num_param] += c - '0'; 1564 return; 1565 } 1566 } 1567 scp->term.num_param = scp->term.last_param + 1; 1568 switch (c) { 1569 1570 case ';': 1571 if (scp->term.num_param < MAX_ESC_PAR) 1572 return; 1573 break; 1574 1575 case '=': 1576 scp->term.esc = 3; 1577 scp->term.last_param = -1; 1578 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1579 scp->term.param[i] = 1; 1580 scp->term.num_param = 0; 1581 return; 1582 1583 case 'A': /* up n rows */ 1584 n = scp->term.param[0]; if (n < 1) n = 1; 1585 move_crsr(scp, scp->xpos, scp->ypos - n); 1586 break; 1587 1588 case 'B': /* down n rows */ 1589 n = scp->term.param[0]; if (n < 1) n = 1; 1590 move_crsr(scp, scp->xpos, scp->ypos + n); 1591 break; 1592 1593 case 'C': /* right n columns */ 1594 n = scp->term.param[0]; if (n < 1) n = 1; 1595 move_crsr(scp, scp->xpos + n, scp->ypos); 1596 break; 1597 1598 case 'D': /* left n columns */ 1599 n = scp->term.param[0]; if (n < 1) n = 1; 1600 move_crsr(scp, scp->xpos - n, scp->ypos); 1601 break; 1602 1603 case 'E': /* cursor to start of line n lines down */ 1604 n = scp->term.param[0]; if (n < 1) n = 1; 1605 move_crsr(scp, 0, scp->ypos + n); 1606 break; 1607 1608 case 'F': /* cursor to start of line n lines up */ 1609 n = scp->term.param[0]; if (n < 1) n = 1; 1610 move_crsr(scp, 0, scp->ypos - n); 1611 break; 1612 1613 case 'f': /* System V consoles .. */ 1614 case 'H': /* Cursor move */ 1615 if (scp->term.num_param == 0) 1616 move_crsr(scp, 0, 0); 1617 else if (scp->term.num_param == 2) 1618 move_crsr(scp, scp->term.param[1] - 1, 1619 scp->term.param[0] - 1); 1620 break; 1621 1622 case 'J': /* Clear all or part of display */ 1623 if (scp->term.num_param == 0) 1624 n = 0; 1625 else 1626 n = scp->term.param[0]; 1627 switch (n) { 1628 case 0: /* clear form cursor to end of display */ 1629 fillw(scp->term.cur_attr | scr_map[0x20], 1630 scp->crtat, scp->crt_base + 1631 scp->xsize * scp->ysize - 1632 scp->crtat); 1633 break; 1634 case 1: /* clear from beginning of display to cursor */ 1635 fillw(scp->term.cur_attr | scr_map[0x20], 1636 scp->crt_base, 1637 scp->crtat - scp->crt_base); 1638 break; 1639 case 2: /* clear entire display */ 1640 clear_screen(scp); 1641 break; 1642 } 1643 break; 1644 1645 case 'K': /* Clear all or part of line */ 1646 if (scp->term.num_param == 0) 1647 n = 0; 1648 else 1649 n = scp->term.param[0]; 1650 switch (n) { 1651 case 0: /* clear form cursor to end of line */ 1652 fillw(scp->term.cur_attr | scr_map[0x20], 1653 scp->crtat, scp->xsize - scp->xpos); 1654 break; 1655 case 1: /* clear from beginning of line to cursor */ 1656 fillw(scp->term.cur_attr|scr_map[0x20], 1657 scp->crtat - (scp->xsize - scp->xpos), 1658 (scp->xsize - scp->xpos) + 1); 1659 break; 1660 case 2: /* clear entire line */ 1661 fillw(scp->term.cur_attr|scr_map[0x20], 1662 scp->crtat - (scp->xsize - scp->xpos), 1663 scp->xsize); 1664 break; 1665 } 1666 break; 1667 1668 case 'L': /* Insert n lines */ 1669 n = scp->term.param[0]; if (n < 1) n = 1; 1670 if (n > scp->ysize - scp->ypos) 1671 n = scp->ysize - scp->ypos; 1672 src = scp->crt_base + scp->ypos * scp->xsize; 1673 dst = src + n * scp->xsize; 1674 count = scp->ysize - (scp->ypos + n); 1675 move_up(src, dst, count * scp->xsize); 1676 fillw(scp->term.cur_attr | scr_map[0x20], src, 1677 n * scp->xsize); 1678 break; 1679 1680 case 'M': /* Delete n lines */ 1681 n = scp->term.param[0]; if (n < 1) n = 1; 1682 if (n > scp->ysize - scp->ypos) 1683 n = scp->ysize - scp->ypos; 1684 dst = scp->crt_base + scp->ypos * scp->xsize; 1685 src = dst + n * scp->xsize; 1686 count = scp->ysize - (scp->ypos + n); 1687 move_down(src, dst, count * scp->xsize); 1688 src = dst + count * scp->xsize; 1689 fillw(scp->term.cur_attr | scr_map[0x20], src, 1690 n * scp->xsize); 1691 break; 1692 1693 case 'P': /* Delete n chars */ 1694 n = scp->term.param[0]; if (n < 1) n = 1; 1695 if (n > scp->xsize - scp->xpos) 1696 n = scp->xsize - scp->xpos; 1697 dst = scp->crtat; 1698 src = dst + n; 1699 count = scp->xsize - (scp->xpos + n); 1700 move_down(src, dst, count); 1701 src = dst + count; 1702 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1703 break; 1704 1705 case '@': /* Insert n chars */ 1706 n = scp->term.param[0]; if (n < 1) n = 1; 1707 if (n > scp->xsize - scp->xpos) 1708 n = scp->xsize - scp->xpos; 1709 src = scp->crtat; 1710 dst = src + n; 1711 count = scp->xsize - (scp->xpos + n); 1712 move_up(src, dst, count); 1713 fillw(scp->term.cur_attr | scr_map[0x20], src, n); 1714 break; 1715 1716 case 'S': /* scroll up n lines */ 1717 n = scp->term.param[0]; if (n < 1) n = 1; 1718 if (n > scp->ypos) 1719 n = scp->ypos; 1720 bcopy(scp->crt_base + (scp->xsize * n), 1721 scp->crt_base, 1722 scp->xsize * (scp->ysize - n) * 1723 sizeof(u_short)); 1724 fillw(scp->term.cur_attr | scr_map[0x20], 1725 scp->crt_base + scp->xsize * 1726 (scp->ysize - 1), 1727 scp->xsize); 1728 break; 1729 1730 case 'T': /* scroll down n lines */ 1731 n = scp->term.param[0]; if (n < 1) n = 1; 1732 if (n > scp->ysize - scp->ypos) 1733 n = scp->ysize - scp->ypos; 1734 bcopy(scp->crt_base, 1735 scp->crt_base + (scp->xsize * n), 1736 scp->xsize * (scp->ysize - n) * 1737 sizeof(u_short)); 1738 fillw(scp->term.cur_attr | scr_map[0x20], 1739 scp->crt_base, scp->xsize); 1740 break; 1741 1742 case 'X': /* delete n characters in line */ 1743 n = scp->term.param[0]; if (n < 1) n = 1; 1744 if (n > scp->xsize - scp->xpos) 1745 n = scp->xsize - scp->xpos; 1746 fillw(scp->term.cur_attr | scr_map[0x20], 1747 scp->crt_base + scp->xpos + 1748 ((scp->xsize*scp->ypos) * sizeof(u_short)), n); 1749 break; 1750 1751 case 'Z': /* move n tabs backwards */ 1752 n = scp->term.param[0]; if (n < 1) n = 1; 1753 if ((i = scp->xpos & 0xf8) == scp->xpos) 1754 i -= 8*n; 1755 else 1756 i -= 8*(n-1); 1757 if (i < 0) 1758 i = 0; 1759 move_crsr(scp, i, scp->ypos); 1760 break; 1761 1762 case '`': /* move cursor to column n */ 1763 n = scp->term.param[0]; if (n < 1) n = 1; 1764 move_crsr(scp, n, scp->ypos); 1765 break; 1766 1767 case 'a': /* move cursor n columns to the right */ 1768 n = scp->term.param[0]; if (n < 1) n = 1; 1769 move_crsr(scp, scp->xpos + n, scp->ypos); 1770 break; 1771 1772 case 'd': /* move cursor to row n */ 1773 n = scp->term.param[0]; if (n < 1) n = 1; 1774 move_crsr(scp, scp->xpos, n); 1775 break; 1776 1777 case 'e': /* move cursor n rows down */ 1778 n = scp->term.param[0]; if (n < 1) n = 1; 1779 move_crsr(scp, scp->xpos, scp->ypos + n); 1780 break; 1781 1782 case 'm': /* change attribute */ 1783 if (scp->term.num_param == 0) { 1784 scp->term.cur_attr = scp->term.std_attr; 1785 break; 1786 } 1787 for (i = 0; i < scp->term.num_param; i++) { 1788 switch (n = scp->term.param[i]) { 1789 case 0: /* back to normal */ 1790 scp->term.cur_attr = scp->term.std_attr; 1791 break; 1792 case 1: /* highlight (bold) */ 1793 scp->term.cur_attr &= 0xFF00; 1794 scp->term.cur_attr |= 0x0800; 1795 break; 1796 case 4: /* highlight (underline) */ 1797 scp->term.cur_attr &= 0xFF00; 1798 scp->term.cur_attr |= 0x0800; 1799 break; 1800 case 5: /* blink */ 1801 scp->term.cur_attr &= 0xFF00; 1802 scp->term.cur_attr |= 0x8000; 1803 break; 1804 case 7: /* reverse video */ 1805 scp->term.cur_attr = scp->term.rev_attr; 1806 break; 1807 case 30: case 31: /* set fg color */ 1808 case 32: case 33: case 34: 1809 case 35: case 36: case 37: 1810 scp->term.cur_attr = 1811 (scp->term.cur_attr & 0xF8FF) 1812 | (ansi_col[(n-30) & 7] << 8); 1813 break; 1814 case 40: case 41: /* set bg color */ 1815 case 42: case 43: case 44: 1816 case 45: case 46: case 47: 1817 scp->term.cur_attr = 1818 (scp->term.cur_attr & 0x8FFF) 1819 | (ansi_col[(n-40) & 7] << 12); 1820 break; 1821 } 1822 } 1823 break; 1824 1825 case 'x': 1826 if (scp->term.num_param == 0) 1827 n = 0; 1828 else 1829 n = scp->term.param[0]; 1830 switch (n) { 1831 case 0: /* reset attributes */ 1832 scp->term.cur_attr = scp->term.std_attr = 1833 current_default->std_attr; 1834 scp->term.rev_attr = current_default->rev_attr; 1835 break; 1836 case 1: /* set ansi background */ 1837 scp->term.cur_attr = scp->term.std_attr = 1838 (scp->term.std_attr & 0x0F00) | 1839 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1840 break; 1841 case 2: /* set ansi foreground */ 1842 scp->term.cur_attr = scp->term.std_attr = 1843 (scp->term.std_attr & 0xF000) | 1844 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1845 break; 1846 case 3: /* set ansi attribute directly */ 1847 scp->term.cur_attr = scp->term.std_attr = 1848 (scp->term.param[1]&0xFF)<<8; 1849 break; 1850 case 5: /* set ansi reverse video background */ 1851 scp->term.rev_attr = 1852 (scp->term.rev_attr & 0x0F00) | 1853 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1854 break; 1855 case 6: /* set ansi reverse video foreground */ 1856 scp->term.rev_attr = 1857 (scp->term.rev_attr & 0xF000) | 1858 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1859 break; 1860 case 7: /* set ansi reverse video directly */ 1861 scp->term.rev_attr = (scp->term.param[1]&0xFF)<<8; 1862 break; 1863 } 1864 break; 1865 1866 case 'z': /* switch to (virtual) console n */ 1867 if (scp->term.num_param == 1) 1868 switch_scr(scp->term.param[0]); 1869 break; 1870 } 1871 } 1872 else if (scp->term.esc == 3) { 1873 if (c >= '0' && c <= '9') { 1874 if (scp->term.num_param < MAX_ESC_PAR) { 1875 if (scp->term.last_param != scp->term.num_param) { 1876 scp->term.last_param = scp->term.num_param; 1877 scp->term.param[scp->term.num_param] = 0; 1878 } 1879 else 1880 scp->term.param[scp->term.num_param] *= 10; 1881 scp->term.param[scp->term.num_param] += c - '0'; 1882 return; 1883 } 1884 } 1885 scp->term.num_param = scp->term.last_param + 1; 1886 switch (c) { 1887 1888 case ';': 1889 if (scp->term.num_param < MAX_ESC_PAR) 1890 return; 1891 break; 1892 1893 case 'A': /* set display border color */ 1894 if (scp->term.num_param == 1) 1895 scp->border=scp->term.param[0] & 0xff; 1896 if (scp == cur_console) 1897 set_border(scp->border); 1898 break; 1899 1900 case 'B': /* set bell pitch and duration */ 1901 if (scp->term.num_param == 2) { 1902 scp->bell_pitch = scp->term.param[0]; 1903 scp->bell_duration = scp->term.param[1]*10; 1904 } 1905 break; 1906 1907 case 'C': /* set cursor shape (start & end line) */ 1908 if (scp->term.num_param == 2) { 1909 scp->cursor_start = scp->term.param[0] & 0x1F; 1910 scp->cursor_end = scp->term.param[1] & 0x1F; 1911 if (scp == cur_console) 1912 cursor_shape(scp->cursor_start, 1913 scp->cursor_end); 1914 } 1915 break; 1916 1917 case 'F': /* set ansi foreground */ 1918 if (scp->term.num_param == 1) 1919 scp->term.cur_attr = scp->term.std_attr = 1920 (scp->term.std_attr & 0xF000) 1921 | ((scp->term.param[0] & 0x0F) << 8); 1922 break; 1923 1924 case 'G': /* set ansi background */ 1925 if (scp->term.num_param == 1) 1926 scp->term.cur_attr = scp->term.std_attr = 1927 (scp->term.std_attr & 0x0F00) 1928 | ((scp->term.param[0] & 0x0F) << 12); 1929 break; 1930 1931 case 'H': /* set ansi reverse video foreground */ 1932 if (scp->term.num_param == 1) 1933 scp->term.rev_attr = 1934 (scp->term.rev_attr & 0xF000) 1935 | ((scp->term.param[0] & 0x0F) << 8); 1936 break; 1937 1938 case 'I': /* set ansi reverse video background */ 1939 if (scp->term.num_param == 1) 1940 scp->term.rev_attr = 1941 (scp->term.rev_attr & 0x0F00) 1942 | ((scp->term.param[0] & 0x0F) << 12); 1943 break; 1944 } 1945 } 1946 scp->term.esc = 0; 1947 } 1948 1949 static void 1950 ansi_put(scr_stat *scp, u_char c) 1951 { 1952 if (scp->status & UNKNOWN_MODE) 1953 return; 1954 1955 /* make screensaver happy */ 1956 if (scp == cur_console) { 1957 scrn_time_stamp = time.tv_sec; 1958 if (scrn_blanked) 1959 SCRN_SAVER(0); 1960 } 1961 in_putc++; 1962 if (scp->term.esc) 1963 scan_esc(scp, c); 1964 else switch(c) { 1965 case 0x1B: /* start escape sequence */ 1966 scp->term.esc = 1; 1967 scp->term.num_param = 0; 1968 break; 1969 case 0x07: 1970 if (scp == cur_console) 1971 sysbeep(scp->bell_pitch, scp->bell_duration); 1972 break; 1973 case '\t': /* non-destructive tab */ 1974 scp->crtat += (8 - scp->xpos % 8); 1975 scp->xpos += (8 - scp->xpos % 8); 1976 break; 1977 case '\b': /* non-destructive backspace */ 1978 if (scp->crtat > scp->crt_base) { 1979 scp->crtat--; 1980 if (scp->xpos > 0) 1981 scp->xpos--; 1982 else { 1983 scp->xpos += scp->xsize - 1; 1984 scp->ypos--; 1985 } 1986 } 1987 break; 1988 case '\r': /* return to pos 0 */ 1989 move_crsr(scp, 0, scp->ypos); 1990 break; 1991 case '\n': /* newline, same pos */ 1992 scp->crtat += scp->xsize; 1993 scp->ypos++; 1994 break; 1995 case '\f': /* form feed, clears screen */ 1996 clear_screen(scp); 1997 break; 1998 default: 1999 /* Print only printables */ 2000 *scp->crtat = (scp->term.cur_attr | scr_map[c]); 2001 scp->crtat++; 2002 if (++scp->xpos >= scp->xsize) { 2003 scp->xpos = 0; 2004 scp->ypos++; 2005 } 2006 break; 2007 } 2008 if (scp->crtat >= scp->crt_base + scp->ysize * scp->xsize) { 2009 bcopy(scp->crt_base + scp->xsize, scp->crt_base, 2010 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2011 fillw(scp->term.cur_attr | scr_map[0x20], 2012 scp->crt_base + scp->xsize * (scp->ysize - 1), 2013 scp->xsize); 2014 scp->crtat -= scp->xsize; 2015 scp->ypos--; 2016 } 2017 in_putc--; 2018 if (delayed_next_scr) 2019 switch_scr(delayed_next_scr - 1); 2020 } 2021 2022 static void 2023 scinit(void) 2024 { 2025 u_short volatile *cp = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short), was; 2026 unsigned cursorat; 2027 int start = -1, end = -1, i; 2028 scr_stat *scp; 2029 2030 /* 2031 * catch that once in a blue moon occurence when scinit is called 2032 * TWICE, adding the CGA_BUF offset again -> poooff 2033 */ 2034 if (crtat != 0) 2035 return; 2036 /* 2037 * Crtat initialized to point to MONO buffer, if not present change 2038 * to CGA_BUF offset. ONLY ADD the difference since locore.s adds 2039 * in the remapped offset at the "right" time 2040 */ 2041 was = *cp; 2042 *cp = (u_short) 0xA55A; 2043 if (*cp != 0xA55A) { 2044 crtc_addr = MONO_BASE; 2045 } else { 2046 *cp = was; 2047 crtc_addr = COLOR_BASE; 2048 Crtat = Crtat + (CGA_BUF-MONO_BUF)/sizeof(u_short); 2049 } 2050 2051 /* Extract cursor location */ 2052 outb(crtc_addr,14); 2053 cursorat = inb(crtc_addr+1)<<8 ; 2054 outb(crtc_addr,15); 2055 cursorat |= inb(crtc_addr+1); 2056 crtat = Crtat + cursorat; 2057 2058 /* is this a VGA or higher ? */ 2059 outb(crtc_addr, 7); 2060 if (inb(crtc_addr) == 7) { 2061 crtc_vga = 1; 2062 #if defined(FAT_CURSOR) 2063 start = 0; 2064 end = 18; 2065 #else 2066 get_cursor_shape(&start, &end); 2067 #endif 2068 } 2069 current_default = &user_default; 2070 for (i = 0; i < NCONS; i++) { 2071 scp = &console[i]; 2072 scp->mode = M_VGA_C80x25; 2073 scp->term.esc = 0; 2074 scp->term.std_attr = current_default->std_attr; 2075 scp->term.rev_attr = current_default->rev_attr; 2076 scp->term.cur_attr = scp->term.std_attr; 2077 scp->border = BG_BLACK; 2078 scp->cursor_start = start; 2079 scp->cursor_end = end; 2080 scp->xsize = COL; 2081 scp->ysize = ROW; 2082 scp->bell_pitch = BELL_PITCH; 2083 scp->bell_duration = BELL_DURATION; 2084 scp->status = NLKED; 2085 scp->pid = 0; 2086 scp->proc = NULL; 2087 scp->smode.mode = VT_AUTO; 2088 if (i == 0) { 2089 scp->xpos = cursorat % COL; 2090 scp->ypos = cursorat / COL; 2091 scp->crt_base = Crtat; 2092 scp->crtat = crtat; 2093 } 2094 } 2095 kernel_console.esc = 0; 2096 kernel_console.std_attr = kernel_default.std_attr; 2097 kernel_console.rev_attr = kernel_default.rev_attr; 2098 kernel_console.cur_attr = kernel_default.std_attr; 2099 /* initialize mapscrn array to a one to one map */ 2100 for (i=0; i<sizeof(scr_map); i++) 2101 scr_map[i] = i; 2102 } 2103 2104 static void 2105 scput(u_char c) 2106 { 2107 scr_stat *scp = &console[0]; 2108 term_stat save; 2109 2110 if (crtat == 0) 2111 scinit(); 2112 if( in_putc == 0) { 2113 ++in_putc; 2114 save = scp->term; 2115 scp->term = kernel_console; 2116 current_default = &kernel_default; 2117 ansi_put(scp, c); 2118 kernel_console = scp->term; 2119 current_default = &user_default; 2120 scp->term = save; 2121 --in_putc; 2122 } else { 2123 if( console_buffer_count < CONSOLE_BUFSIZE) 2124 console_buffer[console_buffer_count++] = c; 2125 } 2126 } 2127 2128 static u_char 2129 *get_fstr(u_int c, u_int *len) 2130 { 2131 u_int i; 2132 2133 if (!(c & FKEY)) 2134 return(NULL); 2135 i = (c & 0xFF) - F_FN; 2136 if (i > n_fkey_tab) 2137 return(NULL); 2138 *len = fkey_tab[i].len; 2139 return(fkey_tab[i].str); 2140 } 2141 2142 static void 2143 update_leds(int which) 2144 { 2145 int s; 2146 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 2147 2148 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 2149 if (key_map.n_keys > ALTGR_OFFSET) { 2150 if (which & ALKED) 2151 which |= CLKED; 2152 else 2153 which &= ~CLKED; 2154 } 2155 s = spltty(); 2156 kbd_cmd(KB_SETLEDS); 2157 kbd_cmd(xlate_leds[which & LED_MASK]); 2158 splx(s); 2159 } 2160 2161 /* 2162 * scgetc(noblock) - get character from keyboard. 2163 * If noblock = 0 wait until a key is pressed. 2164 * Else return NOKEY. 2165 */ 2166 u_int 2167 scgetc(int noblock) 2168 { 2169 u_char scancode, keycode; 2170 u_int state, action; 2171 struct key_t *key; 2172 static u_char esc_flag = 0, compose = 0; 2173 static u_int chr = 0; 2174 2175 next_code: 2176 kbd_wait(); 2177 /* First see if there is something in the keyboard port */ 2178 if (inb(KB_STAT) & KB_BUF_FULL) 2179 scancode = inb(KB_DATA); 2180 else if (noblock) 2181 return(NOKEY); 2182 else 2183 goto next_code; 2184 2185 if (cur_console->status & KBD_RAW_MODE) 2186 return scancode; 2187 #if ASYNCH 2188 if (scancode == KB_ACK || scancode == KB_RESEND) { 2189 kbd_reply = scancode; 2190 if (noblock) 2191 return(NOKEY); 2192 goto next_code; 2193 } 2194 #endif 2195 keycode = scancode & 0x7F; 2196 switch (esc_flag) { 2197 case 0x00: /* normal scancode */ 2198 switch(scancode) { 2199 case 0xB8: /* left alt (compose key) */ 2200 if (compose) { 2201 compose = 0; 2202 if (chr > 255) { 2203 sysbeep(BELL_PITCH, BELL_DURATION); 2204 chr = 0; 2205 } 2206 } 2207 break; 2208 case 0x38: 2209 if (!compose) { 2210 compose = 1; 2211 chr = 0; 2212 } 2213 break; 2214 case 0xE0: 2215 case 0xE1: 2216 esc_flag = scancode; 2217 goto next_code; 2218 } 2219 break; 2220 case 0xE0: /* 0xE0 prefix */ 2221 esc_flag = 0; 2222 switch (keycode) { 2223 case 0x1C: /* right enter key */ 2224 keycode = 0x59; 2225 break; 2226 case 0x1D: /* right ctrl key */ 2227 keycode = 0x5A; 2228 break; 2229 case 0x35: /* keypad divide key */ 2230 keycode = 0x5B; 2231 break; 2232 case 0x37: /* print scrn key */ 2233 keycode = 0x5C; 2234 break; 2235 case 0x38: /* right alt key (alt gr) */ 2236 keycode = 0x5D; 2237 break; 2238 case 0x47: /* grey home key */ 2239 keycode = 0x5E; 2240 break; 2241 case 0x48: /* grey up arrow key */ 2242 keycode = 0x5F; 2243 break; 2244 case 0x49: /* grey page up key */ 2245 keycode = 0x60; 2246 break; 2247 case 0x4B: /* grey left arrow key */ 2248 keycode = 0x61; 2249 break; 2250 case 0x4D: /* grey right arrow key */ 2251 keycode = 0x62; 2252 break; 2253 case 0x4F: /* grey end key */ 2254 keycode = 0x63; 2255 break; 2256 case 0x50: /* grey down arrow key */ 2257 keycode = 0x64; 2258 break; 2259 case 0x51: /* grey page down key */ 2260 keycode = 0x65; 2261 break; 2262 case 0x52: /* grey insert key */ 2263 keycode = 0x66; 2264 break; 2265 case 0x53: /* grey delete key */ 2266 keycode = 0x67; 2267 break; 2268 default: /* ignore everything else */ 2269 goto next_code; 2270 } 2271 break; 2272 case 0xE1: /* 0xE1 prefix */ 2273 esc_flag = 0; 2274 if (keycode == 0x1D) 2275 esc_flag = 0x1D; 2276 goto next_code; 2277 /* NOT REACHED */ 2278 case 0x1D: /* pause / break */ 2279 esc_flag = 0; 2280 if (keycode != 0x45) 2281 goto next_code; 2282 keycode = 0x68; 2283 break; 2284 } 2285 2286 if (compose) { 2287 switch (scancode) { 2288 /* key pressed process it */ 2289 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 2290 chr = (scancode - 0x40) + chr*10; 2291 goto next_code; 2292 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 2293 chr = (scancode - 0x47) + chr*10; 2294 goto next_code; 2295 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 2296 chr = (scancode - 0x4E) + chr*10; 2297 goto next_code; 2298 case 0x52: /* keypad 0 */ 2299 chr *= 10; 2300 goto next_code; 2301 2302 /* key release, no interest here */ 2303 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 2304 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 2305 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 2306 case 0xD2: /* keypad 0 */ 2307 goto next_code; 2308 2309 case 0x38: /* left alt key */ 2310 break; 2311 default: 2312 if (chr) { 2313 compose = chr = 0; 2314 sysbeep(BELL_PITCH, BELL_DURATION); 2315 goto next_code; 2316 } 2317 break; 2318 } 2319 } 2320 2321 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2322 if ((!agrs && (cur_console->status & ALKED)) 2323 || (agrs && !(cur_console->status & ALKED))) 2324 keycode += ALTGR_OFFSET; 2325 key = &key_map.key[keycode]; 2326 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2327 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2328 state ^= 1; 2329 2330 /* Check for make/break */ 2331 action = key->map[state]; 2332 if (scancode & 0x80) { /* key released */ 2333 if (key->spcl & 0x80) { 2334 switch (action) { 2335 case LSH: 2336 shfts &= ~1; 2337 break; 2338 case RSH: 2339 shfts &= ~2; 2340 break; 2341 case LCTR: 2342 ctls &= ~1; 2343 break; 2344 case RCTR: 2345 ctls &= ~2; 2346 break; 2347 case LALT: 2348 alts &= ~1; 2349 break; 2350 case RALT: 2351 alts &= ~2; 2352 break; 2353 case NLK: 2354 nlkcnt = 0; 2355 break; 2356 case CLK: 2357 clkcnt = 0; 2358 break; 2359 case SLK: 2360 slkcnt = 0; 2361 break; 2362 case ASH: 2363 agrs = 0; 2364 break; 2365 case ALK: 2366 alkcnt = 0; 2367 break; 2368 case META: 2369 metas = 0; 2370 break; 2371 } 2372 } 2373 if (chr && !compose) { 2374 action = chr; 2375 chr = 0; 2376 return(action); 2377 } 2378 } else { 2379 /* key pressed */ 2380 if (key->spcl & (0x80>>state)) { 2381 switch (action) { 2382 /* LOCKING KEYS */ 2383 case NLK: 2384 if (!nlkcnt) { 2385 nlkcnt++; 2386 if (cur_console->status & NLKED) 2387 cur_console->status &= ~NLKED; 2388 else 2389 cur_console->status |= NLKED; 2390 update_leds(cur_console->status); 2391 } 2392 break; 2393 case CLK: 2394 if (!clkcnt) { 2395 clkcnt++; 2396 if (cur_console->status & CLKED) 2397 cur_console->status &= ~CLKED; 2398 else 2399 cur_console->status |= CLKED; 2400 update_leds(cur_console->status); 2401 } 2402 break; 2403 case SLK: 2404 if (!slkcnt) { 2405 slkcnt++; 2406 if (cur_console->status & SLKED) { 2407 cur_console->status &= ~SLKED; 2408 pcstart(VIRTUAL_TTY(get_scr_num())); 2409 } 2410 else 2411 cur_console->status |= SLKED; 2412 update_leds(cur_console->status); 2413 } 2414 break; 2415 case ALK: 2416 if (!alkcnt) { 2417 alkcnt++; 2418 if (cur_console->status & ALKED) 2419 cur_console->status &= ~ALKED; 2420 else 2421 cur_console->status |= ALKED; 2422 update_leds(cur_console->status); 2423 } 2424 break; 2425 2426 /* NON-LOCKING KEYS */ 2427 case NOP: 2428 break; 2429 case RBT: 2430 shutdown_nice(); 2431 break; 2432 case DBG: 2433 #ifdef DDB /* try to switch to console 0 */ 2434 if (cur_console->smode.mode == VT_AUTO && 2435 console[0].smode.mode == VT_AUTO) 2436 switch_scr(0); 2437 Debugger("manual escape to debugger"); 2438 return(NOKEY); 2439 #else 2440 printf("No debugger in kernel\n"); 2441 #endif 2442 break; 2443 case LSH: 2444 shfts |= 1; 2445 break; 2446 case RSH: 2447 shfts |= 2; 2448 break; 2449 case LCTR: 2450 ctls |= 1; 2451 break; 2452 case RCTR: 2453 ctls |= 2; 2454 break; 2455 case LALT: 2456 alts |= 1; 2457 break; 2458 case RALT: 2459 alts |= 2; 2460 break; 2461 case ASH: 2462 agrs = 1; 2463 break; 2464 case META: 2465 metas = 1; 2466 break; 2467 case NEXT: 2468 switch_scr((get_scr_num()+1)%NCONS); 2469 break; 2470 default: 2471 if (action >= F_SCR && action <= L_SCR) { 2472 switch_scr(action - F_SCR); 2473 break; 2474 } 2475 if (action >= F_FN && action <= L_FN) 2476 action |= FKEY; 2477 return(action); 2478 } 2479 } 2480 else { 2481 if (metas) 2482 action |= MKEY; 2483 return(action); 2484 } 2485 } 2486 goto next_code; 2487 } 2488 2489 int 2490 getchar(void) 2491 { 2492 u_char thechar; 2493 int s; 2494 2495 polling = 1; 2496 s = splhigh(); 2497 scput('>'); 2498 thechar = (u_char) scgetc(0); 2499 polling = 0; 2500 splx(s); 2501 switch (thechar) { 2502 default: 2503 if (thechar >= scr_map[0x20]) 2504 scput(thechar); 2505 return(thechar); 2506 case cr: 2507 case lf: 2508 scput(cr); scput(lf); 2509 return(lf); 2510 case bs: 2511 case del: 2512 scput(bs); scput(scr_map[0x20]); scput(bs); 2513 return(thechar); 2514 case cntld: 2515 scput('^'); scput('D'); scput('\r'); scput('\n'); 2516 return(0); 2517 } 2518 } 2519 2520 u_int 2521 sgetc(int noblock) 2522 { 2523 return (scgetc(noblock) & 0xff); 2524 } 2525 2526 int 2527 pcmmap(dev_t dev, int offset, int nprot) 2528 { 2529 if (offset > 0x20000) 2530 return EINVAL; 2531 return i386_btop((VIDEOMEM + offset)); 2532 } 2533 2534 static void 2535 kbd_wait(void) 2536 { 2537 int i = 1000; 2538 2539 while (i--) { 2540 if ((inb(KB_STAT) & KB_READY) == 0) 2541 break; 2542 DELAY (10); 2543 } 2544 } 2545 2546 static void 2547 kbd_cmd(u_char command) 2548 { 2549 int retry = 5; 2550 do { 2551 int i = 100000; 2552 2553 kbd_wait(); 2554 #if ASYNCH 2555 kbd_reply = 0; 2556 outb(KB_DATA, command); 2557 while (i--) { 2558 if (kbd_reply == KB_ACK) 2559 return; 2560 if (kbd_reply == KB_RESEND) 2561 break; 2562 } 2563 #else 2564 outb(KB_DATA, command); 2565 while (i--) { 2566 if (inb(KB_STAT) & KB_BUF_FULL) { 2567 int val; 2568 DELAY(10); 2569 val = inb(KB_DATA); 2570 if (val == KB_ACK) 2571 return; 2572 if (val == KB_RESEND) 2573 break; 2574 } 2575 } 2576 #endif 2577 } while (retry--); 2578 } 2579 2580 static void 2581 set_mode(scr_stat *scp) 2582 { 2583 char *modetable; 2584 char special_modetable[64]; 2585 int mode, font_size; 2586 2587 if (scp != cur_console) 2588 return; 2589 2590 /* mode change only on VGA's */ 2591 if (!crtc_vga) { 2592 /* (re)activate cursor */ 2593 untimeout((timeout_t)cursor_pos, 0); 2594 cursor_pos(1); 2595 return; 2596 } 2597 2598 /* setup video hardware for the given mode */ 2599 switch (scp->mode) { 2600 case M_VGA_C80x50: 2601 bcopy(video_mode_ptr+(64*M_VGA_C80x25), &special_modetable, 64); 2602 special_modetable[2] = 8; 2603 special_modetable[19] = 7; 2604 modetable = special_modetable; 2605 goto setup_mode; 2606 2607 case M_VGA_M80x50: 2608 bcopy(video_mode_ptr+(64*M_VGA_M80x25), &special_modetable, 64); 2609 special_modetable[2] = 8; 2610 special_modetable[19] = 7; 2611 modetable = special_modetable; 2612 goto setup_mode; 2613 2614 case M_ENH_B80x43: 2615 bcopy(video_mode_ptr+(64*M_ENH_B80x25), &special_modetable, 64); 2616 special_modetable[2] = 8; 2617 special_modetable[19] = 7; 2618 special_modetable[28] = 87; 2619 modetable = special_modetable; 2620 goto setup_mode; 2621 2622 case M_ENH_C80x43: 2623 bcopy(video_mode_ptr+(64*M_ENH_C80x25), &special_modetable, 64); 2624 special_modetable[2] = 8; 2625 special_modetable[19] = 7; 2626 special_modetable[28] = 87; 2627 modetable = special_modetable; 2628 goto setup_mode; 2629 2630 case M_VGA_C40x25: case M_VGA_C80x25: /* VGA TEXT MODES */ 2631 case M_VGA_M80x25: 2632 case M_B40x25: case M_C40x25: 2633 case M_B80x25: case M_C80x25: 2634 case M_ENH_B40x25: case M_ENH_C40x25: 2635 case M_ENH_B80x25: case M_ENH_C80x25: 2636 2637 modetable = (char*)(video_mode_ptr + (scp->mode * 64)); 2638 setup_mode: 2639 set_vgaregs(modetable); 2640 font_size = *(modetable + 2); 2641 /* change cursor type if set */ 2642 if (scp->cursor_start != -1 && scp->cursor_end != -1) 2643 cursor_shape( 2644 (scp->cursor_start >= font_size) 2645 ? font_size - 1 2646 : scp->cursor_start, 2647 (scp->cursor_end >= font_size) 2648 ? font_size - 1 2649 : scp->cursor_end); 2650 2651 /* set font type (size) */ 2652 switch (font_size) { 2653 case 0x08: 2654 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 2655 break; 2656 case 0x0E: 2657 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 2658 break; 2659 case 0x10: 2660 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 2661 break; 2662 default: 2663 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 2664 } 2665 2666 /* (re)activate cursor */ 2667 untimeout((timeout_t)cursor_pos, 0); 2668 cursor_pos(1); 2669 break; 2670 2671 case M_BG320: case M_CG320: case M_BG640: 2672 case M_CG320_D: case M_CG640_E: 2673 case M_CG640x350: case M_ENH_CG640: 2674 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 2675 2676 set_vgaregs(video_mode_ptr + (scp->mode * 64)); 2677 break; 2678 2679 default: 2680 /* call user defined function XXX */ 2681 break; 2682 } 2683 2684 /* set border color for this (virtual) console */ 2685 set_border(scp->border); 2686 return; 2687 } 2688 2689 static void 2690 set_border(int color) 2691 { 2692 inb(crtc_addr+6); /* reset flip-flop */ 2693 outb(ATC, 0x11); outb(ATC, color); 2694 inb(crtc_addr+6); /* reset flip-flop */ 2695 outb(ATC, 0x20); /* enable Palette */ 2696 } 2697 2698 static void 2699 set_vgaregs(char *modetable) 2700 { 2701 int i, s = splhigh(); 2702 2703 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 2704 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 2705 for (i=0; i<4; i++) { /* program sequencer */ 2706 outb(TSIDX, i+1); 2707 outb(TSREG, modetable[i+5]); 2708 } 2709 outb(MISC, modetable[9]); /* set dot-clock */ 2710 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 2711 outb(crtc_addr, 0x11); 2712 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 2713 for (i=0; i<25; i++) { /* program crtc */ 2714 outb(crtc_addr, i); 2715 outb(crtc_addr+1, modetable[i+10]); 2716 } 2717 inb(crtc_addr+6); /* reset flip-flop */ 2718 for (i=0; i<20; i++) { /* program attribute ctrl */ 2719 outb(ATC, i); 2720 outb(ATC, modetable[i+35]); 2721 } 2722 for (i=0; i<9; i++) { /* program graph data ctrl */ 2723 outb(GDCIDX, i); 2724 outb(GDCREG, modetable[i+55]); 2725 } 2726 inb(crtc_addr+6); /* reset flip-flop */ 2727 outb(ATC ,0x20); /* enable palette */ 2728 splx(s); 2729 } 2730 2731 static void 2732 copy_font(int direction, int segment, int size, char* font) 2733 { 2734 int ch, line, s; 2735 u_char val; 2736 2737 outb(TSIDX, 0x01); val = inb(TSREG); /* blank screen */ 2738 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 2739 2740 /* setup vga for loading fonts (graphics plane mode) */ 2741 inb(crtc_addr+6); /* reset flip/flop */ 2742 outb(ATC, 0x30); outb(ATC, 0x01); 2743 outb(TSIDX, 0x02); outb(TSREG, 0x04); 2744 outb(TSIDX, 0x04); outb(TSREG, 0x06); 2745 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 2746 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 2747 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); /* addr = a0000, 64kb */ 2748 for (ch=0; ch < 256; ch++) 2749 for (line=0; line < size; line++) 2750 if (direction) 2751 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line) = 2752 font[(ch*size)+line]; 2753 else 2754 font[(ch*size)+line] = 2755 *((char *)atdevbase+(segment*0x4000)+(ch*32)+line); 2756 /* setup vga for text mode again */ 2757 s = splhigh(); 2758 inb(crtc_addr+6); /* reset flip/flop */ 2759 outb(ATC, 0x30); outb(ATC, 0x0C); 2760 outb(TSIDX, 0x02); outb(TSREG, 0x03); 2761 outb(TSIDX, 0x04); outb(TSREG, 0x02); 2762 outb(GDCIDX, 0x04); outb(GDCREG, 0x00); 2763 outb(GDCIDX, 0x05); outb(GDCREG, 0x10); 2764 if (crtc_addr == MONO_BASE) { 2765 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */ 2766 } 2767 else { 2768 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */ 2769 } 2770 splx(s); 2771 outb(TSIDX, 0x01); val = inb(TSREG); /* unblank screen */ 2772 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); 2773 } 2774 2775 static void 2776 load_palette(void) 2777 { 2778 int i; 2779 2780 outb(PIXMASK, 0xFF); /* no pixelmask */ 2781 outb(PALWADR, 0x00); 2782 for (i=0x00; i<0x300; i++) 2783 outb(PALDATA, palette[i]); 2784 inb(crtc_addr+6); /* reset flip/flop */ 2785 outb(ATC, 0x20); /* enable palette */ 2786 } 2787 2788 static void 2789 save_palette(void) 2790 { 2791 int i; 2792 2793 outb(PALRADR, 0x00); 2794 for (i=0x00; i<0x300; i++) 2795 palette[i] = inb(PALDATA); 2796 inb(crtc_addr+6); /* reset flip/flop */ 2797 } 2798 2799 #endif /* NSC */ 2800