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