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