syscons.c revision 16633
1/*- 2 * Copyright (c) 1992-1996 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: syscons.c,v 1.153 1996/06/21 11:31:09 sos Exp $ 29 */ 30 31#include "sc.h" 32#include "apm.h" 33#include "opt_ddb.h" 34 35#if NSC > 0 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/conf.h> 39#include <sys/ioctl.h> 40#include <sys/proc.h> 41#include <sys/signalvar.h> 42#include <sys/tty.h> 43#include <sys/uio.h> 44#include <sys/callout.h> 45#include <sys/kernel.h> 46#include <sys/syslog.h> 47#include <sys/errno.h> 48#include <sys/malloc.h> 49#include <sys/devconf.h> 50#ifdef DEVFS 51#include <sys/devfsext.h> 52#endif 53 54#include <machine/clock.h> 55#include <machine/cons.h> 56#include <machine/console.h> 57#include <machine/psl.h> 58#include <machine/frame.h> 59#include <machine/pc/display.h> 60#include <machine/apm_bios.h> 61#include <machine/random.h> 62 63#include <vm/vm.h> 64#include <vm/vm_param.h> 65#include <vm/pmap.h> 66 67#include <i386/isa/isa.h> 68#include <i386/isa/isa_device.h> 69#include <i386/isa/timerreg.h> 70#include <i386/isa/kbdtables.h> 71#include <i386/isa/syscons.h> 72 73#if !defined(MAXCONS) 74#define MAXCONS 16 75#endif 76 77 78/* this may break on older VGA's but is usefull on real 32 bit systems */ 79#define bcopyw bcopy 80 81static default_attr user_default = { 82 (FG_LIGHTGREY | BG_BLACK) << 8, 83 (FG_BLACK | BG_LIGHTGREY) << 8 84}; 85 86static default_attr kernel_default = { 87 (FG_WHITE | BG_BLACK) << 8, 88 (FG_BLACK | BG_LIGHTGREY) << 8 89}; 90 91static scr_stat main_console; 92static scr_stat *console[MAXCONS]; 93#ifdef DEVFS 94static void *sc_devfs_token[MAXCONS]; 95#endif 96 scr_stat *cur_console; 97static scr_stat *new_scp, *old_scp; 98static term_stat kernel_console; 99static default_attr *current_default; 100static char init_done = FALSE; 101static int configuration = 0; 102static char switch_in_progress = FALSE; 103static char blink_in_progress = FALSE; 104static char write_in_progress = FALSE; 105 u_int crtc_addr = MONO_BASE; 106static char crtc_vga = FALSE; 107static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; 108static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; 109static char *font_8 = NULL, *font_14 = NULL, *font_16 = NULL; 110static int fonts_loaded = 0; 111 char palette[3*256]; 112static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); 113static int delayed_next_scr = FALSE; 114static long scrn_blank_time = 0; /* screen saver timeout value */ 115 int scrn_blanked = FALSE; /* screen saver active flag */ 116static long scrn_time_stamp; 117 u_char scr_map[256]; 118static char *video_mode_ptr = NULL; 119static char *cut_buffer; 120static u_short mouse_and_mask[16] = { 121 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 122 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000 123}; 124static u_short mouse_or_mask[16] = { 125 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800, 126 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 127}; 128 129static void none_saver(int blank) { } 130 131void (*current_saver) __P((int blank)) = none_saver; 132 133static int scattach(struct isa_device *dev); 134static int scparam(struct tty *tp, struct termios *t); 135static int scprobe(struct isa_device *dev); 136static void scstart(struct tty *tp); 137 138/* OS specific stuff */ 139#ifdef not_yet_done 140#define VIRTUAL_TTY(x) (sccons[x] = ttymalloc(sccons[x])) 141struct CONSOLE_TTY (sccons[MAXCONS] = ttymalloc(sccons[MAXCONS])) 142struct tty *sccons[MAXCONS+1]; 143#else 144#define VIRTUAL_TTY(x) &sccons[x] 145#define CONSOLE_TTY &sccons[MAXCONS] 146static struct tty sccons[MAXCONS+1]; 147#endif 148#define MONO_BUF pa_to_va(0xB0000) 149#define CGA_BUF pa_to_va(0xB8000) 150u_short *Crtat; 151 152#define WRAPHIST(scp, pointer, offset)\ 153 ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\ 154 + (offset)) % (scp->history_size))) 155 156static void scinit(void); 157static u_int scgetc(int noblock); 158static scr_stat *get_scr_stat(dev_t dev); 159static scr_stat *alloc_scp(void); 160static void init_scp(scr_stat *scp); 161static int get_scr_num(void); 162static void scrn_timer(void); 163static void clear_screen(scr_stat *scp); 164static int switch_scr(scr_stat *scp, u_int next_scr); 165static void exchange_scr(void); 166static inline void move_crsr(scr_stat *scp, int x, int y); 167static void scan_esc(scr_stat *scp, u_char c); 168static inline void draw_cursor(scr_stat *scp, int show); 169static void ansi_put(scr_stat *scp, u_char *buf, int len); 170static u_char *get_fstr(u_int c, u_int *len); 171static void update_leds(int which); 172static void history_to_screen(scr_stat *scp); 173static int history_up_line(scr_stat *scp); 174static int history_down_line(scr_stat *scp); 175static void kbd_wait(void); 176static void kbd_cmd(u_char command); 177static void set_mode(scr_stat *scp); 178static void set_vgaregs(char *modetable); 179static void set_font_mode(void); 180static void set_normal_mode(void); 181static void copy_font(int operation, int font_type, char* font_image); 182static void set_destructive_cursor(scr_stat *scp, int force); 183static void reverse_mouse_cut(scr_stat *scp, int cut); 184static void draw_mouse_image(scr_stat *scp); 185static void save_palette(void); 186static void do_bell(scr_stat *scp, int pitch, int duration); 187static void blink_screen(scr_stat *scp); 188 189struct isa_driver scdriver = { 190 scprobe, scattach, "sc", 1 191}; 192 193static d_open_t scopen; 194static d_close_t scclose; 195static d_read_t scread; 196static d_write_t scwrite; 197static d_ioctl_t scioctl; 198static d_devtotty_t scdevtotty; 199static d_mmap_t scmmap; 200 201#define CDEV_MAJOR 12 202static struct cdevsw scdevsw = { 203 scopen, scclose, scread, scwrite, 204 scioctl, nullstop, noreset, scdevtotty, 205 ttselect, scmmap, nostrategy, "sc", NULL, -1 }; 206 207/* 208 * Calculate hardware attributes word using logical attributes mask and 209 * hardware colors 210 */ 211 212static int 213mask2attr(struct term_stat *term) 214{ 215 int attr, mask = term->attr_mask; 216 217 if (mask & REVERSE_ATTR) { 218 attr = ((mask & FOREGROUND_CHANGED) ? 219 ((term->cur_color & 0xF000) >> 4) : 220 (term->rev_color & 0x0F00)) | 221 ((mask & BACKGROUND_CHANGED) ? 222 ((term->cur_color & 0x0F00) << 4) : 223 (term->rev_color & 0xF000)); 224 } else 225 attr = term->cur_color; 226 227 /* XXX: underline mapping for Hercules adapter can be better */ 228 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 229 attr ^= 0x0800; 230 if (mask & BLINK_ATTR) 231 attr ^= 0x8000; 232 233 return attr; 234} 235 236static int 237scprobe(struct isa_device *dev) 238{ 239 int i, j, retries = 5; 240 unsigned char val; 241 242 /* Enable interrupts and keyboard controller */ 243 kbd_wait(); 244 outb(KB_STAT, KB_WRITE); 245 kbd_wait(); 246 outb(KB_DATA, KB_MODE); 247 248 /* flush any noise in the buffer */ 249 while (inb(KB_STAT) & KB_BUF_FULL) { 250 DELAY(25); 251 (void) inb(KB_DATA); 252 } 253 254 /* Reset keyboard hardware */ 255 while (retries--) { 256 kbd_wait(); 257 outb(KB_DATA, KB_RESET); 258 for (i=0; i<10000; i++) { 259 DELAY(100); 260 val = inb(KB_DATA); 261 if (val == KB_ACK || val == KB_ECHO) 262 goto gotres; 263 if (val == KB_RESEND) 264 break; 265 } 266 } 267gotres: 268 if (retries < 0) 269 printf("scprobe: keyboard won't accept RESET command\n"); 270 else { 271 i = 10; /* At most 10 retries. */ 272gotack: 273 DELAY(25); 274 j = 1000; /* Wait at most 50 ms (supposedly). */ 275 while ((inb(KB_STAT) & KB_BUF_FULL) == 0 && --j > 0) DELAY(50); 276 DELAY(25); 277 val = inb(KB_DATA); 278 if (val == KB_ACK && --i > 0) 279 goto gotack; 280 if (val != KB_RESET_DONE) 281 printf("scprobe: keyboard RESET failed (result = 0x%02x)\n", val); 282 } 283#ifdef XT_KEYBOARD 284 kbd_wait(); 285 outb(KB_DATA, 0xF0); 286 kbd_wait(); 287 outb(KB_DATA, 1); 288 kbd_wait(); 289#endif /* XT_KEYBOARD */ 290 return (IO_KBDSIZE); 291} 292 293static struct kern_devconf kdc_sc[NSC] = { 294 0, 0, 0, /* filled in by dev_attach */ 295 "sc", 0, { MDDT_ISA, 0, "tty" }, 296 isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, 297 &kdc_isa0, /* parent */ 298 0, /* parentdata */ 299 DC_BUSY, /* the console is almost always busy */ 300 "Graphics console", 301 DC_CLS_DISPLAY /* class */ 302}; 303 304static inline void 305sc_registerdev(struct isa_device *id) 306{ 307 if(id->id_unit) 308 kdc_sc[id->id_unit] = kdc_sc[0]; 309 kdc_sc[id->id_unit].kdc_unit = id->id_unit; 310 kdc_sc[id->id_unit].kdc_isa = id; 311 dev_attach(&kdc_sc[id->id_unit]); 312} 313 314#if NAPM > 0 315static int 316scresume(void *dummy) 317{ 318 shfts = 0; 319 ctls = 0; 320 alts = 0; 321 agrs = 0; 322 metas = 0; 323 return 0; 324} 325#endif 326 327/* 328 * These functions need to be before calls to them so they can be inlined. 329 */ 330static inline void 331draw_cursor(scr_stat *scp, int show) 332{ 333 if (show && !(scp->status & CURSOR_SHOWN)) { 334 u_short cursor_image = *(Crtat + (scp->cursor_pos - scp->scr_buf)); 335 336 scp->cursor_saveunder = cursor_image; 337 if (configuration & CHAR_CURSOR) { 338 set_destructive_cursor(scp, FALSE); 339 cursor_image = (cursor_image & 0xff00) | DEAD_CHAR; 340 } 341 else { 342 if ((cursor_image & 0x7000) == 0x7000) { 343 cursor_image &= 0x8fff; 344 if(!(cursor_image & 0x0700)) 345 cursor_image |= 0x0700; 346 } else { 347 cursor_image |= 0x7000; 348 if ((cursor_image & 0x0700) == 0x0700) 349 cursor_image &= 0xf0ff; 350 } 351 } 352 *(Crtat + (scp->cursor_pos - scp->scr_buf)) = cursor_image; 353 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 354 scp->status |= CURSOR_SHOWN; 355 } 356 if (!show && (scp->status & CURSOR_SHOWN)) { 357 *(Crtat + (scp->cursor_pos - scp->scr_buf)) = scp->cursor_saveunder; 358 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 359 scp->status &= ~CURSOR_SHOWN; 360 } 361} 362 363static inline void 364move_crsr(scr_stat *scp, int x, int y) 365{ 366 if (x < 0) 367 x = 0; 368 if (y < 0) 369 y = 0; 370 if (x >= scp->xsize) 371 x = scp->xsize-1; 372 if (y >= scp->ysize) 373 y = scp->ysize-1; 374 scp->xpos = x; 375 scp->ypos = y; 376 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 377 scp->cursor_pos = scp->scr_buf + scp->ypos * scp->xsize + scp->xpos; 378 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 379} 380 381static int 382scattach(struct isa_device *dev) 383{ 384 scr_stat *scp; 385#ifdef DEVFS 386 int vc; 387#endif 388 389 scinit(); 390 configuration = dev->id_flags; 391 392 scp = console[0]; 393 394 if (crtc_vga) { 395 cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 396 font_8 = (char *)malloc(8*256, M_DEVBUF, M_NOWAIT); 397 font_14 = (char *)malloc(14*256, M_DEVBUF, M_NOWAIT); 398 font_16 = (char *)malloc(16*256, M_DEVBUF, M_NOWAIT); 399 copy_font(SAVE, FONT_16, font_16); 400 fonts_loaded = FONT_16; 401 scp->font = FONT_16; 402 save_palette(); 403 } 404 405 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 406 M_DEVBUF, M_NOWAIT); 407 /* copy screen to buffer */ 408 bcopyw(Crtat, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); 409 scp->cursor_pos = scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; 410 scp->mouse_pos = scp->scr_buf; 411 412 /* initialize history buffer & pointers */ 413 scp->history_head = scp->history_pos = scp->history = 414 (u_short *)malloc(scp->history_size*sizeof(u_short), 415 M_DEVBUF, M_NOWAIT); 416 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 417 418 /* initialize cursor stuff */ 419 draw_cursor(scp, TRUE); 420 if (crtc_vga && (configuration & CHAR_CURSOR)) 421 set_destructive_cursor(scp, TRUE); 422 423 /* get screen update going */ 424 scrn_timer(); 425 426 update_leds(scp->status); 427 sc_registerdev(dev); 428 429 printf("sc%d: ", dev->id_unit); 430 if (crtc_vga) 431 if (crtc_addr == MONO_BASE) 432 printf("VGA mono"); 433 else 434 printf("VGA color"); 435 else 436 if (crtc_addr == MONO_BASE) 437 printf("MDA/hercules"); 438 else 439 printf("CGA/EGA"); 440 printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, configuration); 441 442#if NAPM > 0 443 scp->r_hook.ah_fun = scresume; 444 scp->r_hook.ah_arg = NULL; 445 scp->r_hook.ah_name = "system keyboard"; 446 scp->r_hook.ah_order = APM_MID_ORDER; 447 apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); 448#endif 449 450 { 451 dev_t dev = makedev(CDEV_MAJOR, 0); 452 453 cdevsw_add(&dev, &scdevsw, NULL); 454 } 455#ifdef DEVFS 456 for (vc = 0; vc < MAXCONS; vc++) 457 sc_devfs_token[vc] = devfs_add_devswf(&scdevsw, vc, DV_CHR, 458 UID_ROOT, GID_WHEEL, 0600, 459 "ttyv%n", vc); 460#endif 461 462 return 0; 463} 464 465struct tty 466*scdevtotty(dev_t dev) 467{ 468 int unit = minor(dev); 469 470 if (!init_done) 471 return(NULL); 472 if (unit > MAXCONS || unit < 0) 473 return(NULL); 474 if (unit == MAXCONS) 475 return CONSOLE_TTY; 476 return VIRTUAL_TTY(unit); 477} 478 479static scr_stat 480*get_scr_stat(dev_t dev) 481{ 482 int unit = minor(dev); 483 484 if (unit > MAXCONS || unit < 0) 485 return(NULL); 486 if (unit == MAXCONS) 487 return console[0]; 488 return console[unit]; 489} 490 491static int 492get_scr_num() 493{ 494 int i = 0; 495 496 while ((i < MAXCONS) && (cur_console != console[i])) 497 i++; 498 return i < MAXCONS ? i : 0; 499} 500 501int 502scopen(dev_t dev, int flag, int mode, struct proc *p) 503{ 504 struct tty *tp = scdevtotty(dev); 505 506 if (!tp) 507 return(ENXIO); 508 509 tp->t_oproc = scstart; 510 tp->t_param = scparam; 511 tp->t_dev = dev; 512 if (!(tp->t_state & TS_ISOPEN)) { 513 ttychars(tp); 514 tp->t_iflag = TTYDEF_IFLAG; 515 tp->t_oflag = TTYDEF_OFLAG; 516 tp->t_cflag = TTYDEF_CFLAG; 517 tp->t_lflag = TTYDEF_LFLAG; 518 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 519 scparam(tp, &tp->t_termios); 520 ttsetwater(tp); 521 (*linesw[tp->t_line].l_modem)(tp, 1); 522 } 523 else 524 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 525 return(EBUSY); 526 if (!console[minor(dev)]) 527 console[minor(dev)] = alloc_scp(); 528 return((*linesw[tp->t_line].l_open)(dev, tp)); 529} 530 531int 532scclose(dev_t dev, int flag, int mode, struct proc *p) 533{ 534 struct tty *tp = scdevtotty(dev); 535 struct scr_stat *scp; 536 537 if (!tp) 538 return(ENXIO); 539 if (minor(dev) < MAXCONS) { 540 scp = get_scr_stat(tp->t_dev); 541 if (scp->status & SWITCH_WAIT_ACQ) 542 wakeup((caddr_t)&scp->smode); 543#if not_yet_done 544 if (scp == &main_console) { 545 scp->pid = 0; 546 scp->proc = NULL; 547 scp->smode.mode = VT_AUTO; 548 } 549 else { 550 free(scp->scr_buf, M_DEVBUF); 551 free(scp->history, M_DEVBUF); 552 free(scp, M_DEVBUF); 553 console[minor(dev)] = NULL; 554 } 555#else 556 scp->pid = 0; 557 scp->proc = NULL; 558 scp->smode.mode = VT_AUTO; 559#endif 560 } 561 (*linesw[tp->t_line].l_close)(tp, flag); 562 ttyclose(tp); 563 return(0); 564} 565 566int 567scread(dev_t dev, struct uio *uio, int flag) 568{ 569 struct tty *tp = scdevtotty(dev); 570 571 if (!tp) 572 return(ENXIO); 573 return((*linesw[tp->t_line].l_read)(tp, uio, flag)); 574} 575 576int 577scwrite(dev_t dev, struct uio *uio, int flag) 578{ 579 struct tty *tp = scdevtotty(dev); 580 581 if (!tp) 582 return(ENXIO); 583 return((*linesw[tp->t_line].l_write)(tp, uio, flag)); 584} 585 586void 587scintr(int unit) 588{ 589 static struct tty *cur_tty; 590 int c, len; 591 u_char *cp; 592 593 /* make screensaver happy */ 594 scrn_time_stamp = time.tv_sec; 595 if (scrn_blanked) { 596 (*current_saver)(FALSE); 597 cur_console->start = 0; 598 cur_console->end = cur_console->xsize * cur_console->ysize; 599 } 600 601 c = scgetc(1); 602 603 cur_tty = VIRTUAL_TTY(get_scr_num()); 604 if (!(cur_tty->t_state & TS_ISOPEN)) 605 if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) 606 return; 607 608 switch (c & 0xff00) { 609 case 0x0000: /* normal key */ 610 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 611 break; 612 case NOKEY: /* nothing there */ 613 break; 614 case FKEY: /* function key, return string */ 615 if (cp = get_fstr((u_int)c, (u_int *)&len)) { 616 while (len-- > 0) 617 (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); 618 } 619 break; 620 case MKEY: /* meta is active, prepend ESC */ 621 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 622 (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); 623 break; 624 case BKEY: /* backtab fixed sequence (esc [ Z) */ 625 (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); 626 (*linesw[cur_tty->t_line].l_rint)('[', cur_tty); 627 (*linesw[cur_tty->t_line].l_rint)('Z', cur_tty); 628 break; 629 } 630} 631 632static int 633scparam(struct tty *tp, struct termios *t) 634{ 635 tp->t_ispeed = t->c_ispeed; 636 tp->t_ospeed = t->c_ospeed; 637 tp->t_cflag = t->c_cflag; 638 return 0; 639} 640 641int 642scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 643{ 644 int i, error; 645 struct tty *tp; 646 struct trapframe *fp; 647 scr_stat *scp; 648 649 tp = scdevtotty(dev); 650 if (!tp) 651 return ENXIO; 652 scp = get_scr_stat(tp->t_dev); 653 654 switch (cmd) { /* process console hardware related ioctl's */ 655 656 case GIO_ATTR: /* get current attributes */ 657 *(int*)data = scp->term.cur_attr; 658 return 0; 659 660 case GIO_COLOR: /* is this a color console ? */ 661 if (crtc_addr == COLOR_BASE) 662 *(int*)data = 1; 663 else 664 *(int*)data = 0; 665 return 0; 666 667 case CONS_CURRENT: /* get current adapter type */ 668 if (crtc_vga) 669 *(int*)data = KD_VGA; 670 else 671 if (crtc_addr == MONO_BASE) 672 *(int*)data = KD_MONO; 673 else 674 *(int*)data = KD_CGA; 675 return 0; 676 677 case CONS_GET: /* get current video mode */ 678 *(int*)data = scp->mode; 679 return 0; 680 681 case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ 682 scrn_blank_time = *(int*)data; 683 return 0; 684 685 case CONS_CURSORTYPE: /* set cursor type blink/noblink */ 686 if ((*(int*)data) & 0x01) 687 configuration |= BLINK_CURSOR; 688 else 689 configuration &= ~BLINK_CURSOR; 690 if ((*(int*)data) & 0x02) { 691 configuration |= CHAR_CURSOR; 692 set_destructive_cursor(scp, TRUE); 693 } else 694 configuration &= ~CHAR_CURSOR; 695 return 0; 696 697 case CONS_BELLTYPE: /* set bell type sound/visual */ 698 if (*data) 699 configuration |= VISUAL_BELL; 700 else 701 configuration &= ~VISUAL_BELL; 702 return 0; 703 704 case CONS_HISTORY: /* set history size */ 705 if (*data) { 706 free(scp->history, M_DEVBUF); 707 scp->history_size = *(int*)data; 708 if (scp->history_size < scp->ysize) 709 scp->history = NULL; 710 else { 711 scp->history_size *= scp->xsize; 712 scp->history_head = scp->history_pos = scp->history = 713 (u_short *)malloc(scp->history_size*sizeof(u_short), 714 M_DEVBUF, M_WAITOK); 715 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 716 } 717 return 0; 718 } 719 else 720 return EINVAL; 721 722 case CONS_MOUSECTL: /* control mouse arrow */ 723 { 724 mouse_info_t *mouse = (mouse_info_t*)data; 725 int fontsize; 726 scr_stat *mscp = cur_console; 727 728 switch (mscp->font) { 729 default: 730 case FONT_8: 731 fontsize = 8; break; 732 case FONT_14: 733 fontsize = 14; break; 734 case FONT_16: 735 fontsize = 16; break; 736 } 737 switch (mouse->operation) { 738 case MOUSE_SHOW: 739 if (!(mscp->status & MOUSE_ENABLED)) { 740 mscp->mouse_oldpos = Crtat + (mscp->mouse_pos - mscp->scr_buf); 741 mscp->status |= MOUSE_ENABLED; 742 mark_all(mscp); 743 } 744 else 745 return EINVAL; 746 break; 747 748 case MOUSE_HIDE: 749 if (mscp->status & MOUSE_ENABLED) { 750 mscp->status &= ~MOUSE_ENABLED; 751 mark_all(mscp); 752 } 753 else 754 return EINVAL; 755 break; 756 757 case MOUSE_CUT_START: 758 if (mscp->status & MOUSE_ENABLED) { 759 if (mscp->mouse_cut_start != NULL) 760 reverse_mouse_cut(mscp, 0); 761 mscp->mouse_cut_start = mscp->mouse_cut_end = mscp->mouse_pos; 762 *mscp->mouse_cut_start = (*mscp->mouse_cut_start & 0x88ff) | 763 (*mscp->mouse_cut_start & 0x7000) >> 4 | 764 (*mscp->mouse_cut_start & 0x0700) << 4; 765 cut_buffer[0] = *mscp->mouse_cut_start & 0xff; 766 cut_buffer[1] = 0; 767 mscp->status |= MOUSE_CUTTING; 768 /* delete all other screens cut markings */ 769 for (i=0; i<MAXCONS; i++) { 770 if (console[i] == NULL || console[i] == mscp) 771 continue; 772 reverse_mouse_cut(console[i], 0); 773 console[i]->mouse_cut_start=console[i]->mouse_cut_end=NULL; 774 } 775 mark_for_update(mscp, mscp->mouse_cut_start - mscp->scr_buf); 776 } 777 else 778 return EINVAL; 779 break; 780 781 case MOUSE_CUT_END: 782 if (mscp->status & MOUSE_ENABLED) { 783 mscp->status &= ~MOUSE_CUTTING; 784 } 785 else 786 return EINVAL; 787 break; 788 789 case MOUSE_CUT_RESET: 790 if (mscp->status & MOUSE_ENABLED) { 791 mscp->status &= ~MOUSE_CUTTING; 792 reverse_mouse_cut(mscp, 0); 793 mscp->mouse_cut_start = mscp->mouse_cut_end = NULL; 794 } 795 else 796 return EINVAL; 797 break; 798 799 case MOUSE_RETURN_CUTBUFFER: 800 if (mscp->status & MOUSE_ENABLED) { 801 struct tty *tp; 802 char *ptr = cut_buffer; 803 804 tp = VIRTUAL_TTY(get_scr_num()); 805 while (*ptr) 806 (*linesw[tp->t_line].l_rint)(*ptr++, tp); 807 } 808 else 809 return EINVAL; 810 break; 811 812 case MOUSE_MOVEABS: 813 mscp->mouse_xpos = mouse->x; 814 mscp->mouse_ypos = mouse->y; 815 goto set_mouse_pos; 816 817 case MOUSE_MOVEREL: 818 mscp->mouse_xpos += mouse->x; 819 mscp->mouse_ypos += mouse->y; 820set_mouse_pos: 821 /* 822 * the margins imposed here are not ideal, we loose 823 * a couble of pixels on the borders.. 824 */ 825 if (mscp->mouse_xpos < 0) 826 mscp->mouse_xpos = 0; 827 if (mscp->mouse_ypos < 0) 828 mscp->mouse_ypos = 0; 829 if (mscp->mouse_xpos > (mscp->xsize*8-2)) 830 mscp->mouse_xpos = (mscp->xsize*8)-2; 831 if (mscp->mouse_ypos > (mscp->ysize*fontsize)-2) 832 mscp->mouse_ypos = (mscp->ysize*fontsize)-2; 833 834 mscp->mouse_pos = mscp->scr_buf + 835 ((mscp->mouse_ypos/fontsize)*mscp->xsize + mscp->mouse_xpos/8); 836 837 if ((mscp->status&MOUSE_ENABLED) && (mscp->status&MOUSE_CUTTING)) { 838 int s = splclock(); 839 reverse_mouse_cut(mscp, 0); 840 mscp->mouse_cut_end = mscp->mouse_pos; 841 reverse_mouse_cut(mscp, 1); 842 mark_all(mscp); 843 splx(s); 844 } 845 break; 846 847 case MOUSE_GETPOS: 848 mouse->x = mscp->mouse_xpos; 849 mouse->y = mscp->mouse_ypos; 850 return 0; 851 852 default: 853 return EINVAL; 854 } 855 /* make screensaver happy */ 856 if (scp == cur_console) { 857 scrn_time_stamp = time.tv_sec; 858 if (scrn_blanked) { 859 (*current_saver)(FALSE); 860 cur_console->start = 0; 861 cur_console->end = cur_console->xsize * cur_console->ysize; 862 } 863 } 864 return 0; 865 } 866 867 case CONS_GETINFO: /* get current (virtual) console info */ 868 { 869 vid_info_t *ptr = (vid_info_t*)data; 870 if (ptr->size == sizeof(struct vid_info)) { 871 ptr->m_num = get_scr_num(); 872 ptr->mv_col = scp->xpos; 873 ptr->mv_row = scp->ypos; 874 ptr->mv_csz = scp->xsize; 875 ptr->mv_rsz = scp->ysize; 876 ptr->mv_norm.fore = (scp->term.std_color & 0x0f00)>>8; 877 ptr->mv_norm.back = (scp->term.std_color & 0xf000)>>12; 878 ptr->mv_rev.fore = (scp->term.rev_color & 0x0f00)>>8; 879 ptr->mv_rev.back = (scp->term.rev_color & 0xf000)>>12; 880 ptr->mv_grfc.fore = 0; /* not supported */ 881 ptr->mv_grfc.back = 0; /* not supported */ 882 ptr->mv_ovscan = scp->border; 883 ptr->mk_keylock = scp->status & LOCK_KEY_MASK; 884 return 0; 885 } 886 return EINVAL; 887 } 888 889 case CONS_GETVERS: /* get version number */ 890 *(int*)data = 0x200; /* version 2.0 */ 891 return 0; 892 893 /* VGA TEXT MODES */ 894 case SW_VGA_C40x25: 895 case SW_VGA_C80x25: case SW_VGA_M80x25: 896 case SW_VGA_C80x30: case SW_VGA_M80x30: 897 case SW_VGA_C80x50: case SW_VGA_M80x50: 898 case SW_VGA_C80x60: case SW_VGA_M80x60: 899 case SW_B40x25: case SW_C40x25: 900 case SW_B80x25: case SW_C80x25: 901 case SW_ENH_B40x25: case SW_ENH_C40x25: 902 case SW_ENH_B80x25: case SW_ENH_C80x25: 903 case SW_ENH_B80x43: case SW_ENH_C80x43: 904 905 if (!crtc_vga || video_mode_ptr == NULL) 906 return ENXIO; 907 switch (cmd & 0xff) { 908 case M_VGA_C80x60: case M_VGA_M80x60: 909 if (!(fonts_loaded & FONT_8)) 910 return EINVAL; 911 scp->xsize = 80; 912 scp->ysize = 60; 913 break; 914 case M_VGA_C80x50: case M_VGA_M80x50: 915 if (!(fonts_loaded & FONT_8)) 916 return EINVAL; 917 scp->xsize = 80; 918 scp->ysize = 50; 919 break; 920 case M_ENH_B80x43: case M_ENH_C80x43: 921 if (!(fonts_loaded & FONT_8)) 922 return EINVAL; 923 scp->xsize = 80; 924 scp->ysize = 43; 925 break; 926 case M_VGA_C80x30: case M_VGA_M80x30: 927 scp->xsize = 80; 928 scp->ysize = 30; 929 break; 930 default: 931 if ((cmd & 0xff) > M_VGA_CG320) 932 return EINVAL; 933 else 934 scp->xsize = *(video_mode_ptr+((cmd&0xff)*64)); 935 scp->ysize = *(video_mode_ptr+((cmd&0xff)*64)+1)+1; 936 break; 937 } 938 scp->mode = cmd & 0xff; 939 scp->status &= ~UNKNOWN_MODE; 940 free(scp->scr_buf, M_DEVBUF); 941 scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 942 M_DEVBUF, M_WAITOK); 943 free(cut_buffer, M_DEVBUF); 944 cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT); 945 cut_buffer[0] = 0x00; 946 if (scp == cur_console) 947 set_mode(scp); 948 clear_screen(scp); 949 if (tp->t_winsize.ws_col != scp->xsize 950 || tp->t_winsize.ws_row != scp->ysize) { 951 tp->t_winsize.ws_col = scp->xsize; 952 tp->t_winsize.ws_row = scp->ysize; 953 pgsignal(tp->t_pgrp, SIGWINCH, 1); 954 } 955 return 0; 956 957 /* GRAPHICS MODES */ 958 case SW_BG320: case SW_BG640: 959 case SW_CG320: case SW_CG320_D: case SW_CG640_E: 960 case SW_CG640x350: case SW_ENH_CG640: 961 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 962 963 if (!crtc_vga || video_mode_ptr == NULL) 964 return ENXIO; 965 scp->mode = cmd & 0xFF; 966 scp->status |= UNKNOWN_MODE; /* graphics mode */ 967 scp->xsize = (*(video_mode_ptr + (scp->mode*64))) * 8; 968 scp->ysize = (*(video_mode_ptr + (scp->mode*64) + 1) + 1) * 969 (*(video_mode_ptr + (scp->mode*64) + 2)); 970 set_mode(scp); 971 /* clear_graphics();*/ 972 973 if (tp->t_winsize.ws_xpixel != scp->xsize 974 || tp->t_winsize.ws_ypixel != scp->ysize) { 975 tp->t_winsize.ws_xpixel = scp->xsize; 976 tp->t_winsize.ws_ypixel = scp->ysize; 977 pgsignal(tp->t_pgrp, SIGWINCH, 1); 978 } 979 return 0; 980 981 case VT_SETMODE: /* set screen switcher mode */ 982 bcopy(data, &scp->smode, sizeof(struct vt_mode)); 983 if (scp->smode.mode == VT_PROCESS) { 984 scp->proc = p; 985 scp->pid = scp->proc->p_pid; 986 } 987 return 0; 988 989 case VT_GETMODE: /* get screen switcher mode */ 990 bcopy(&scp->smode, data, sizeof(struct vt_mode)); 991 return 0; 992 993 case VT_RELDISP: /* screen switcher ioctl */ 994 switch(*data) { 995 case VT_FALSE: /* user refuses to release screen, abort */ 996 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 997 old_scp->status &= ~SWITCH_WAIT_REL; 998 switch_in_progress = FALSE; 999 return 0; 1000 } 1001 return EINVAL; 1002 1003 case VT_TRUE: /* user has released screen, go on */ 1004 if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { 1005 scp->status &= ~SWITCH_WAIT_REL; 1006 exchange_scr(); 1007 if (new_scp->smode.mode == VT_PROCESS) { 1008 new_scp->status |= SWITCH_WAIT_ACQ; 1009 psignal(new_scp->proc, new_scp->smode.acqsig); 1010 } 1011 else 1012 switch_in_progress = FALSE; 1013 return 0; 1014 } 1015 return EINVAL; 1016 1017 case VT_ACKACQ: /* acquire acknowledged, switch completed */ 1018 if (scp == new_scp && (scp->status & SWITCH_WAIT_ACQ)) { 1019 scp->status &= ~SWITCH_WAIT_ACQ; 1020 switch_in_progress = FALSE; 1021 return 0; 1022 } 1023 return EINVAL; 1024 1025 default: 1026 return EINVAL; 1027 } 1028 /* NOT REACHED */ 1029 1030 case VT_OPENQRY: /* return free virtual console */ 1031 for (i = 0; i < MAXCONS; i++) { 1032 tp = VIRTUAL_TTY(i); 1033 if (!(tp->t_state & TS_ISOPEN)) { 1034 *data = i + 1; 1035 return 0; 1036 } 1037 } 1038 return EINVAL; 1039 1040 case VT_ACTIVATE: /* switch to screen *data */ 1041 return switch_scr(scp, (*data) - 1); 1042 1043 case VT_WAITACTIVE: /* wait for switch to occur */ 1044 if (*data > MAXCONS || *data < 0) 1045 return EINVAL; 1046 if (minor(dev) == (*data) - 1) 1047 return 0; 1048 if (*data == 0) { 1049 if (scp == cur_console) 1050 return 0; 1051 } 1052 else 1053 scp = console[(*data) - 1]; 1054 while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, 1055 "waitvt", 0)) == ERESTART) ; 1056 return error; 1057 1058 case VT_GETACTIVE: 1059 *data = get_scr_num()+1; 1060 return 0; 1061 1062 case KDENABIO: /* allow io operations */ 1063 error = suser(p->p_ucred, &p->p_acflag); 1064 if (error != 0) 1065 return error; 1066 fp = (struct trapframe *)p->p_md.md_regs; 1067 fp->tf_eflags |= PSL_IOPL; 1068 return 0; 1069 1070 case KDDISABIO: /* disallow io operations (default) */ 1071 fp = (struct trapframe *)p->p_md.md_regs; 1072 fp->tf_eflags &= ~PSL_IOPL; 1073 return 0; 1074 1075 case KDSETMODE: /* set current mode of this (virtual) console */ 1076 switch (*data) { 1077 case KD_TEXT: /* switch to TEXT (known) mode */ 1078 /* restore fonts & palette ! */ 1079 if (crtc_vga) { 1080 if (fonts_loaded & FONT_8) 1081 copy_font(LOAD, FONT_8, font_8); 1082 if (fonts_loaded & FONT_14) 1083 copy_font(LOAD, FONT_14, font_14); 1084 if (fonts_loaded & FONT_16) 1085 copy_font(LOAD, FONT_16, font_16); 1086 if (configuration & CHAR_CURSOR) 1087 set_destructive_cursor(scp, TRUE); 1088 load_palette(); 1089 } 1090 /* FALL THROUGH */ 1091 1092 case KD_TEXT1: /* switch to TEXT (known) mode */ 1093 /* no restore fonts & palette */ 1094 scp->status &= ~UNKNOWN_MODE; 1095 if (crtc_vga && video_mode_ptr) 1096 set_mode(scp); 1097 clear_screen(scp); 1098 return 0; 1099 1100 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 1101 scp->status |= UNKNOWN_MODE; 1102 return 0; 1103 default: 1104 return EINVAL; 1105 } 1106 /* NOT REACHED */ 1107 1108 case KDGETMODE: /* get current mode of this (virtual) console */ 1109 *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; 1110 return 0; 1111 1112 case KDSBORDER: /* set border color of this (virtual) console */ 1113 if (!crtc_vga) 1114 return ENXIO; 1115 scp->border = *data; 1116 if (scp == cur_console) 1117 set_border(scp->border); 1118 return 0; 1119 1120 case KDSKBSTATE: /* set keyboard state (locks) */ 1121 if (*data >= 0 && *data <= LOCK_KEY_MASK) { 1122 scp->status &= ~LOCK_KEY_MASK; 1123 scp->status |= *data; 1124 if (scp == cur_console) 1125 update_leds(scp->status); 1126 return 0; 1127 } 1128 return EINVAL; 1129 1130 case KDGKBSTATE: /* get keyboard state (locks) */ 1131 *data = scp->status & LOCK_KEY_MASK; 1132 return 0; 1133 1134 case KDSETRAD: /* set keyboard repeat & delay rates */ 1135 if (*data & 0x80) 1136 return EINVAL; 1137 i = spltty(); 1138 kbd_cmd(KB_SETRAD); 1139 kbd_cmd(*data); 1140 splx(i); 1141 return 0; 1142 1143 case KDSKBMODE: /* set keyboard mode */ 1144 switch (*data) { 1145 case K_RAW: /* switch to RAW scancode mode */ 1146 scp->status |= KBD_RAW_MODE; 1147 return 0; 1148 1149 case K_XLATE: /* switch to XLT ascii mode */ 1150 if (scp == cur_console && scp->status == KBD_RAW_MODE) 1151 shfts = ctls = alts = agrs = metas = 0; 1152 scp->status &= ~KBD_RAW_MODE; 1153 return 0; 1154 default: 1155 return EINVAL; 1156 } 1157 /* NOT REACHED */ 1158 1159 case KDGKBMODE: /* get keyboard mode */ 1160 *data = (scp->status & KBD_RAW_MODE) ? K_RAW : K_XLATE; 1161 return 0; 1162 1163 case KDMKTONE: /* sound the bell */ 1164 if (*(int*)data) 1165 do_bell(scp, (*(int*)data)&0xffff, 1166 (((*(int*)data)>>16)&0xffff)*hz/1000); 1167 else 1168 do_bell(scp, scp->bell_pitch, scp->bell_duration); 1169 return 0; 1170 1171 case KIOCSOUND: /* make tone (*data) hz */ 1172 if (scp == cur_console) { 1173 if (*(int*)data) { 1174 int pitch = TIMER_FREQ/(*(int*)data); 1175 1176 /* set command for counter 2, 2 byte write */ 1177 if (acquire_timer2(TIMER_16BIT|TIMER_SQWAVE)) 1178 return EBUSY; 1179 1180 /* set pitch */ 1181 outb(TIMER_CNTR2, pitch); 1182 outb(TIMER_CNTR2, (pitch>>8)); 1183 1184 /* enable counter 2 output to speaker */ 1185 outb(IO_PPI, inb(IO_PPI) | 3); 1186 } 1187 else { 1188 /* disable counter 2 output to speaker */ 1189 outb(IO_PPI, inb(IO_PPI) & 0xFC); 1190 release_timer2(); 1191 } 1192 } 1193 return 0; 1194 1195 case KDGKBTYPE: /* get keyboard type */ 1196 *data = 0; /* type not known (yet) */ 1197 return 0; 1198 1199 case KDSETLED: /* set keyboard LED status */ 1200 if (*data >= 0 && *data <= LED_MASK) { 1201 scp->status &= ~LED_MASK; 1202 scp->status |= *data; 1203 if (scp == cur_console) 1204 update_leds(scp->status); 1205 return 0; 1206 } 1207 return EINVAL; 1208 1209 case KDGETLED: /* get keyboard LED status */ 1210 *data = scp->status & LED_MASK; 1211 return 0; 1212 1213 case GETFKEY: /* get functionkey string */ 1214 if (*(u_short*)data < n_fkey_tab) { 1215 fkeyarg_t *ptr = (fkeyarg_t*)data; 1216 bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, 1217 fkey_tab[ptr->keynum].len); 1218 ptr->flen = fkey_tab[ptr->keynum].len; 1219 return 0; 1220 } 1221 else 1222 return EINVAL; 1223 1224 case SETFKEY: /* set functionkey string */ 1225 if (*(u_short*)data < n_fkey_tab) { 1226 fkeyarg_t *ptr = (fkeyarg_t*)data; 1227 bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, 1228 min(ptr->flen, MAXFK)); 1229 fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); 1230 return 0; 1231 } 1232 else 1233 return EINVAL; 1234 1235 case GIO_SCRNMAP: /* get output translation table */ 1236 bcopy(&scr_map, data, sizeof(scr_map)); 1237 return 0; 1238 1239 case PIO_SCRNMAP: /* set output translation table */ 1240 bcopy(data, &scr_map, sizeof(scr_map)); 1241 return 0; 1242 1243 case GIO_KEYMAP: /* get keyboard translation table */ 1244 bcopy(&key_map, data, sizeof(key_map)); 1245 return 0; 1246 1247 case PIO_KEYMAP: /* set keyboard translation table */ 1248 bcopy(data, &key_map, sizeof(key_map)); 1249 return 0; 1250 1251 case PIO_FONT8x8: /* set 8x8 dot font */ 1252 if (!crtc_vga) 1253 return ENXIO; 1254 bcopy(data, font_8, 8*256); 1255 fonts_loaded |= FONT_8; 1256 copy_font(LOAD, FONT_8, font_8); 1257 if (configuration & CHAR_CURSOR) 1258 set_destructive_cursor(scp, TRUE); 1259 return 0; 1260 1261 case GIO_FONT8x8: /* get 8x8 dot font */ 1262 if (!crtc_vga) 1263 return ENXIO; 1264 if (fonts_loaded & FONT_8) { 1265 bcopy(font_8, data, 8*256); 1266 return 0; 1267 } 1268 else 1269 return ENXIO; 1270 1271 case PIO_FONT8x14: /* set 8x14 dot font */ 1272 if (!crtc_vga) 1273 return ENXIO; 1274 bcopy(data, font_14, 14*256); 1275 fonts_loaded |= FONT_14; 1276 copy_font(LOAD, FONT_14, font_14); 1277 if (configuration & CHAR_CURSOR) 1278 set_destructive_cursor(scp, TRUE); 1279 return 0; 1280 1281 case GIO_FONT8x14: /* get 8x14 dot font */ 1282 if (!crtc_vga) 1283 return ENXIO; 1284 if (fonts_loaded & FONT_14) { 1285 bcopy(font_14, data, 14*256); 1286 return 0; 1287 } 1288 else 1289 return ENXIO; 1290 1291 case PIO_FONT8x16: /* set 8x16 dot font */ 1292 if (!crtc_vga) 1293 return ENXIO; 1294 bcopy(data, font_16, 16*256); 1295 fonts_loaded |= FONT_16; 1296 copy_font(LOAD, FONT_16, font_16); 1297 if (configuration & CHAR_CURSOR) 1298 set_destructive_cursor(scp, TRUE); 1299 return 0; 1300 1301 case GIO_FONT8x16: /* get 8x16 dot font */ 1302 if (!crtc_vga) 1303 return ENXIO; 1304 if (fonts_loaded & FONT_16) { 1305 bcopy(font_16, data, 16*256); 1306 return 0; 1307 } 1308 else 1309 return ENXIO; 1310 default: 1311 break; 1312 } 1313 1314 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1315 if (error >= 0) 1316 return(error); 1317 error = ttioctl(tp, cmd, data, flag); 1318 if (error >= 0) 1319 return(error); 1320 return(ENOTTY); 1321} 1322 1323static void 1324scstart(struct tty *tp) 1325{ 1326 struct clist *rbp; 1327 int s, len; 1328 u_char buf[PCBURST]; 1329 scr_stat *scp = get_scr_stat(tp->t_dev); 1330 1331 /* XXX who repeats the call when the above flags are cleared? */ 1332 if (scp->status & SLKED || blink_in_progress) 1333 return; 1334 s = spltty(); 1335 if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { 1336 tp->t_state |= TS_BUSY; 1337 rbp = &tp->t_outq; 1338 while (rbp->c_cc) { 1339 len = q_to_b(rbp, buf, PCBURST); 1340 splx(s); 1341 ansi_put(scp, buf, len); 1342 s = spltty(); 1343 } 1344 tp->t_state &= ~TS_BUSY; 1345 ttwwakeup(tp); 1346 } 1347 splx(s); 1348} 1349 1350void 1351sccnprobe(struct consdev *cp) 1352{ 1353 struct isa_device *dvp; 1354 1355 /* 1356 * Take control if we are the highest priority enabled display device. 1357 */ 1358 dvp = find_display(); 1359 if (dvp != NULL && dvp->id_driver != &scdriver) { 1360 cp->cn_pri = CN_DEAD; 1361 return; 1362 } 1363 1364 /* initialize required fields */ 1365 cp->cn_dev = makedev(CDEV_MAJOR, MAXCONS); 1366 cp->cn_pri = CN_INTERNAL; 1367} 1368 1369void 1370sccninit(struct consdev *cp) 1371{ 1372 scinit(); 1373} 1374 1375void 1376sccnputc(dev_t dev, int c) 1377{ 1378 u_char buf[1]; 1379 int s; 1380 scr_stat *scp = console[0]; 1381 term_stat save = scp->term; 1382 1383 scp->term = kernel_console; 1384 current_default = &kernel_default; 1385 if (scp->scr_buf == Crtat) 1386 draw_cursor(scp, FALSE); 1387 buf[0] = c; 1388 ansi_put(scp, buf, 1); 1389 kernel_console = scp->term; 1390 current_default = &user_default; 1391 scp->term = save; 1392 s = splclock(); 1393 if (scp == cur_console) { 1394 if (scp->scr_buf != Crtat && (scp->start <= scp->end)) { 1395 bcopyw(scp->scr_buf + scp->start, Crtat + scp->start, 1396 (1 + scp->end - scp->start) * sizeof(u_short)); 1397 scp->start = scp->xsize * scp->ysize; 1398 scp->end = 0; 1399 scp->status &= ~CURSOR_SHOWN; 1400 } 1401 draw_cursor(scp, TRUE); 1402 } 1403 splx(s); 1404} 1405 1406int 1407sccngetc(dev_t dev) 1408{ 1409 int s = spltty(); /* block scintr while we poll */ 1410 int c = scgetc(0); 1411 splx(s); 1412 return(c); 1413} 1414 1415int 1416sccncheckc(dev_t dev) 1417{ 1418 return (scgetc(1) & 0xff); 1419} 1420 1421static void 1422scrn_timer() 1423{ 1424 static int cursor_blinkrate; 1425 static ushort *last_mouse_pos = NULL; 1426 scr_stat *scp = cur_console; 1427 1428 /* should we just return ? */ 1429 if ((scp->status&UNKNOWN_MODE) || blink_in_progress || switch_in_progress) { 1430 timeout((timeout_func_t)scrn_timer, 0, hz/10); 1431 return; 1432 } 1433 1434 if (!scrn_blanked) { 1435 /* update screen image */ 1436 if (scp->start <= scp->end) { 1437 bcopyw(scp->scr_buf + scp->start, Crtat + scp->start, 1438 (1 + scp->end - scp->start) * sizeof(u_short)); 1439 scp->status &= ~CURSOR_SHOWN; 1440 scp->start = scp->xsize * scp->ysize; 1441 scp->end = 0; 1442 last_mouse_pos = NULL; 1443 } 1444 /* update "pseudo" mouse arrow */ 1445 if (scp->mouse_pos != last_mouse_pos && (scp->status & MOUSE_ENABLED)) { 1446 last_mouse_pos = scp->mouse_pos; 1447 draw_mouse_image(scp); 1448 } 1449 1450 /* update cursor image */ 1451 if (scp->status & CURSOR_ENABLED) 1452 draw_cursor(scp, 1453 !(configuration&BLINK_CURSOR) || !(cursor_blinkrate++&0x04)); 1454 } 1455 if (scrn_blank_time && (time.tv_sec>scrn_time_stamp+scrn_blank_time)) 1456 (*current_saver)(TRUE); 1457 timeout((timeout_func_t)scrn_timer, 0, hz/25); 1458} 1459 1460static void 1461clear_screen(scr_stat *scp) 1462{ 1463 move_crsr(scp, 0, 0); 1464 fillw(scp->term.cur_color | scr_map[0x20], scp->scr_buf, 1465 scp->xsize * scp->ysize); 1466 mark_all(scp); 1467} 1468 1469static int 1470switch_scr(scr_stat *scp, u_int next_scr) 1471{ 1472 if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) 1473 switch_in_progress = FALSE; 1474 1475 if (next_scr >= MAXCONS || switch_in_progress || 1476 (cur_console->smode.mode == VT_AUTO 1477 && cur_console->status & UNKNOWN_MODE)) { 1478 do_bell(scp, BELL_PITCH, BELL_DURATION); 1479 return EINVAL; 1480 } 1481 1482 /* is the wanted virtual console open ? */ 1483 if (next_scr) { 1484 struct tty *tp = VIRTUAL_TTY(next_scr); 1485 if (!(tp->t_state & TS_ISOPEN)) { 1486 do_bell(scp, BELL_PITCH, BELL_DURATION); 1487 return EINVAL; 1488 } 1489 } 1490 /* delay switch if actively updating screen */ 1491 if (write_in_progress || blink_in_progress) { 1492 delayed_next_scr = next_scr+1; 1493 return 0; 1494 } 1495 switch_in_progress = TRUE; 1496 old_scp = cur_console; 1497 new_scp = console[next_scr]; 1498 wakeup((caddr_t)&new_scp->smode); 1499 if (new_scp == old_scp) { 1500 switch_in_progress = FALSE; 1501 delayed_next_scr = FALSE; 1502 return 0; 1503 } 1504 1505 /* has controlling process died? */ 1506 if (old_scp->proc && (old_scp->proc != pfind(old_scp->pid))) 1507 old_scp->smode.mode = VT_AUTO; 1508 if (new_scp->proc && (new_scp->proc != pfind(new_scp->pid))) 1509 new_scp->smode.mode = VT_AUTO; 1510 1511 /* check the modes and switch approbiatly */ 1512 if (old_scp->smode.mode == VT_PROCESS) { 1513 old_scp->status |= SWITCH_WAIT_REL; 1514 psignal(old_scp->proc, old_scp->smode.relsig); 1515 } 1516 else { 1517 exchange_scr(); 1518 if (new_scp->smode.mode == VT_PROCESS) { 1519 new_scp->status |= SWITCH_WAIT_ACQ; 1520 psignal(new_scp->proc, new_scp->smode.acqsig); 1521 } 1522 else 1523 switch_in_progress = FALSE; 1524 } 1525 return 0; 1526} 1527 1528static void 1529exchange_scr(void) 1530{ 1531 move_crsr(old_scp, old_scp->xpos, old_scp->ypos); 1532 cur_console = new_scp; 1533 if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ 1534 if (crtc_vga && video_mode_ptr) 1535 set_mode(new_scp); 1536 } 1537 move_crsr(new_scp, new_scp->xpos, new_scp->ypos); 1538 if ((old_scp->status & UNKNOWN_MODE) && crtc_vga) { 1539 if (fonts_loaded & FONT_8) 1540 copy_font(LOAD, FONT_8, font_8); 1541 if (fonts_loaded & FONT_14) 1542 copy_font(LOAD, FONT_14, font_14); 1543 if (fonts_loaded & FONT_16) 1544 copy_font(LOAD, FONT_16, font_16); 1545 if (configuration & CHAR_CURSOR) 1546 set_destructive_cursor(new_scp, TRUE); 1547 load_palette(); 1548 } 1549 if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE) 1550 shfts = ctls = alts = agrs = metas = 0; 1551 update_leds(new_scp->status); 1552 delayed_next_scr = FALSE; 1553 mark_all(new_scp); 1554} 1555 1556static void 1557scan_esc(scr_stat *scp, u_char c) 1558{ 1559 static u_char ansi_col[16] = 1560 {0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15}; 1561 int i, n; 1562 u_short *src, *dst, count; 1563 1564 if (scp->term.esc == 1) { 1565 switch (c) { 1566 1567 case '[': /* Start ESC [ sequence */ 1568 scp->term.esc = 2; 1569 scp->term.last_param = -1; 1570 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1571 scp->term.param[i] = 1; 1572 scp->term.num_param = 0; 1573 return; 1574 1575 case 'M': /* Move cursor up 1 line, scroll if at top */ 1576 if (scp->ypos > 0) 1577 move_crsr(scp, scp->xpos, scp->ypos - 1); 1578 else { 1579 bcopyw(scp->scr_buf, scp->scr_buf + scp->xsize, 1580 (scp->ysize - 1) * scp->xsize * sizeof(u_short)); 1581 fillw(scp->term.cur_color | scr_map[0x20], 1582 scp->scr_buf, scp->xsize); 1583 mark_all(scp); 1584 } 1585 break; 1586#if notyet 1587 case 'Q': 1588 scp->term.esc = 4; 1589 break; 1590#endif 1591 case 'c': /* Clear screen & home */ 1592 clear_screen(scp); 1593 break; 1594 } 1595 } 1596 else if (scp->term.esc == 2) { 1597 if (c >= '0' && c <= '9') { 1598 if (scp->term.num_param < MAX_ESC_PAR) { 1599 if (scp->term.last_param != scp->term.num_param) { 1600 scp->term.last_param = scp->term.num_param; 1601 scp->term.param[scp->term.num_param] = 0; 1602 } 1603 else 1604 scp->term.param[scp->term.num_param] *= 10; 1605 scp->term.param[scp->term.num_param] += c - '0'; 1606 return; 1607 } 1608 } 1609 scp->term.num_param = scp->term.last_param + 1; 1610 switch (c) { 1611 1612 case ';': 1613 if (scp->term.num_param < MAX_ESC_PAR) 1614 return; 1615 break; 1616 1617 case '=': 1618 scp->term.esc = 3; 1619 scp->term.last_param = -1; 1620 for (i = scp->term.num_param; i < MAX_ESC_PAR; i++) 1621 scp->term.param[i] = 1; 1622 scp->term.num_param = 0; 1623 return; 1624 1625 case 'A': /* up n rows */ 1626 n = scp->term.param[0]; if (n < 1) n = 1; 1627 move_crsr(scp, scp->xpos, scp->ypos - n); 1628 break; 1629 1630 case 'B': /* down n rows */ 1631 n = scp->term.param[0]; if (n < 1) n = 1; 1632 move_crsr(scp, scp->xpos, scp->ypos + n); 1633 break; 1634 1635 case 'C': /* right n columns */ 1636 n = scp->term.param[0]; if (n < 1) n = 1; 1637 move_crsr(scp, scp->xpos + n, scp->ypos); 1638 break; 1639 1640 case 'D': /* left n columns */ 1641 n = scp->term.param[0]; if (n < 1) n = 1; 1642 move_crsr(scp, scp->xpos - n, scp->ypos); 1643 break; 1644 1645 case 'E': /* cursor to start of line n lines down */ 1646 n = scp->term.param[0]; if (n < 1) n = 1; 1647 move_crsr(scp, 0, scp->ypos + n); 1648 break; 1649 1650 case 'F': /* cursor to start of line n lines up */ 1651 n = scp->term.param[0]; if (n < 1) n = 1; 1652 move_crsr(scp, 0, scp->ypos - n); 1653 break; 1654 1655 case 'f': /* Cursor move */ 1656 case 'H': 1657 if (scp->term.num_param == 0) 1658 move_crsr(scp, 0, 0); 1659 else if (scp->term.num_param == 2) 1660 move_crsr(scp, scp->term.param[1] - 1, scp->term.param[0] - 1); 1661 break; 1662 1663 case 'J': /* Clear all or part of display */ 1664 if (scp->term.num_param == 0) 1665 n = 0; 1666 else 1667 n = scp->term.param[0]; 1668 switch (n) { 1669 case 0: /* clear form cursor to end of display */ 1670 fillw(scp->term.cur_color | scr_map[0x20], 1671 scp->cursor_pos, 1672 scp->scr_buf + scp->xsize * scp->ysize - scp->cursor_pos); 1673 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1674 mark_for_update(scp, scp->xsize * scp->ysize); 1675 break; 1676 case 1: /* clear from beginning of display to cursor */ 1677 fillw(scp->term.cur_color | scr_map[0x20], 1678 scp->scr_buf, 1679 scp->cursor_pos - scp->scr_buf); 1680 mark_for_update(scp, 0); 1681 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1682 break; 1683 case 2: /* clear entire display */ 1684 clear_screen(scp); 1685 break; 1686 } 1687 break; 1688 1689 case 'K': /* Clear all or part of line */ 1690 if (scp->term.num_param == 0) 1691 n = 0; 1692 else 1693 n = scp->term.param[0]; 1694 switch (n) { 1695 case 0: /* clear form cursor to end of line */ 1696 fillw(scp->term.cur_color | scr_map[0x20], 1697 scp->cursor_pos, 1698 scp->xsize - scp->xpos); 1699 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1700 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + 1701 scp->xsize - scp->xpos); 1702 break; 1703 case 1: /* clear from beginning of line to cursor */ 1704 fillw(scp->term.cur_color | scr_map[0x20], 1705 scp->cursor_pos - scp->xpos, 1706 scp->xpos + 1); 1707 mark_for_update(scp, scp->ypos * scp->xsize); 1708 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1709 break; 1710 case 2: /* clear entire line */ 1711 fillw(scp->term.cur_color | scr_map[0x20], 1712 scp->cursor_pos - scp->xpos, 1713 scp->xsize); 1714 mark_for_update(scp, scp->ypos * scp->xsize); 1715 mark_for_update(scp, (scp->ypos + 1) * scp->xsize); 1716 break; 1717 } 1718 break; 1719 1720 case 'L': /* Insert n lines */ 1721 n = scp->term.param[0]; if (n < 1) n = 1; 1722 if (n > scp->ysize - scp->ypos) 1723 n = scp->ysize - scp->ypos; 1724 src = scp->scr_buf + scp->ypos * scp->xsize; 1725 dst = src + n * scp->xsize; 1726 count = scp->ysize - (scp->ypos + n); 1727 bcopyw(src, dst, count * scp->xsize * sizeof(u_short)); 1728 fillw(scp->term.cur_color | scr_map[0x20], src, 1729 n * scp->xsize); 1730 mark_for_update(scp, scp->ypos * scp->xsize); 1731 mark_for_update(scp, scp->xsize * scp->ysize); 1732 break; 1733 1734 case 'M': /* Delete n lines */ 1735 n = scp->term.param[0]; if (n < 1) n = 1; 1736 if (n > scp->ysize - scp->ypos) 1737 n = scp->ysize - scp->ypos; 1738 dst = scp->scr_buf + scp->ypos * scp->xsize; 1739 src = dst + n * scp->xsize; 1740 count = scp->ysize - (scp->ypos + n); 1741 bcopyw(src, dst, count * scp->xsize * sizeof(u_short)); 1742 src = dst + count * scp->xsize; 1743 fillw(scp->term.cur_color | scr_map[0x20], src, 1744 n * scp->xsize); 1745 mark_for_update(scp, scp->ypos * scp->xsize); 1746 mark_for_update(scp, scp->xsize * scp->ysize); 1747 break; 1748 1749 case 'P': /* Delete n chars */ 1750 n = scp->term.param[0]; if (n < 1) n = 1; 1751 if (n > scp->xsize - scp->xpos) 1752 n = scp->xsize - scp->xpos; 1753 dst = scp->cursor_pos; 1754 src = dst + n; 1755 count = scp->xsize - (scp->xpos + n); 1756 bcopyw(src, dst, count * sizeof(u_short)); 1757 src = dst + count; 1758 fillw(scp->term.cur_color | scr_map[0x20], src, n); 1759 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1760 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 1761 break; 1762 1763 case '@': /* Insert n chars */ 1764 n = scp->term.param[0]; if (n < 1) n = 1; 1765 if (n > scp->xsize - scp->xpos) 1766 n = scp->xsize - scp->xpos; 1767 src = scp->cursor_pos; 1768 dst = src + n; 1769 count = scp->xsize - (scp->xpos + n); 1770 bcopyw(src, dst, count * sizeof(u_short)); 1771 fillw(scp->term.cur_color | scr_map[0x20], src, n); 1772 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1773 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); 1774 break; 1775 1776 case 'S': /* scroll up n lines */ 1777 n = scp->term.param[0]; if (n < 1) n = 1; 1778 if (n > scp->ysize) 1779 n = scp->ysize; 1780 bcopyw(scp->scr_buf + (scp->xsize * n), 1781 scp->scr_buf, 1782 scp->xsize * (scp->ysize - n) * sizeof(u_short)); 1783 fillw(scp->term.cur_color | scr_map[0x20], 1784 scp->scr_buf + scp->xsize * (scp->ysize - n), 1785 scp->xsize * n); 1786 mark_all(scp); 1787 break; 1788 1789 case 'T': /* scroll down n lines */ 1790 n = scp->term.param[0]; if (n < 1) n = 1; 1791 if (n > scp->ysize) 1792 n = scp->ysize; 1793 bcopyw(scp->scr_buf, 1794 scp->scr_buf + (scp->xsize * n), 1795 scp->xsize * (scp->ysize - n) * 1796 sizeof(u_short)); 1797 fillw(scp->term.cur_color | scr_map[0x20], 1798 scp->scr_buf, scp->xsize * n); 1799 mark_all(scp); 1800 break; 1801 1802 case 'X': /* erase n characters in line */ 1803 n = scp->term.param[0]; if (n < 1) n = 1; 1804 if (n > scp->xsize - scp->xpos) 1805 n = scp->xsize - scp->xpos; 1806 fillw(scp->term.cur_color | scr_map[0x20], 1807 scp->cursor_pos, n); 1808 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 1809 mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n); 1810 break; 1811 1812 case 'Z': /* move n tabs backwards */ 1813 n = scp->term.param[0]; if (n < 1) n = 1; 1814 if ((i = scp->xpos & 0xf8) == scp->xpos) 1815 i -= 8*n; 1816 else 1817 i -= 8*(n-1); 1818 if (i < 0) 1819 i = 0; 1820 move_crsr(scp, i, scp->ypos); 1821 break; 1822 1823 case '`': /* move cursor to column n */ 1824 n = scp->term.param[0]; if (n < 1) n = 1; 1825 move_crsr(scp, n - 1, scp->ypos); 1826 break; 1827 1828 case 'a': /* move cursor n columns to the right */ 1829 n = scp->term.param[0]; if (n < 1) n = 1; 1830 move_crsr(scp, scp->xpos + n, scp->ypos); 1831 break; 1832 1833 case 'd': /* move cursor to row n */ 1834 n = scp->term.param[0]; if (n < 1) n = 1; 1835 move_crsr(scp, scp->xpos, n - 1); 1836 break; 1837 1838 case 'e': /* move cursor n rows down */ 1839 n = scp->term.param[0]; if (n < 1) n = 1; 1840 move_crsr(scp, scp->xpos, scp->ypos + n); 1841 break; 1842 1843 case 'm': /* change attribute */ 1844 if (scp->term.num_param == 0) { 1845 scp->term.attr_mask = NORMAL_ATTR; 1846 scp->term.cur_attr = 1847 scp->term.cur_color = scp->term.std_color; 1848 break; 1849 } 1850 for (i = 0; i < scp->term.num_param; i++) { 1851 switch (n = scp->term.param[i]) { 1852 case 0: /* back to normal */ 1853 scp->term.attr_mask = NORMAL_ATTR; 1854 scp->term.cur_attr = 1855 scp->term.cur_color = scp->term.std_color; 1856 break; 1857 case 1: /* bold */ 1858 scp->term.attr_mask |= BOLD_ATTR; 1859 scp->term.cur_attr = mask2attr(&scp->term); 1860 break; 1861 case 4: /* underline */ 1862 scp->term.attr_mask |= UNDERLINE_ATTR; 1863 scp->term.cur_attr = mask2attr(&scp->term); 1864 break; 1865 case 5: /* blink */ 1866 scp->term.attr_mask |= BLINK_ATTR; 1867 scp->term.cur_attr = mask2attr(&scp->term); 1868 break; 1869 case 7: /* reverse video */ 1870 scp->term.attr_mask |= REVERSE_ATTR; 1871 scp->term.cur_attr = mask2attr(&scp->term); 1872 break; 1873 case 30: case 31: /* set fg color */ 1874 case 32: case 33: case 34: 1875 case 35: case 36: case 37: 1876 scp->term.attr_mask |= FOREGROUND_CHANGED; 1877 scp->term.cur_color = 1878 (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); 1879 scp->term.cur_attr = mask2attr(&scp->term); 1880 break; 1881 case 40: case 41: /* set bg color */ 1882 case 42: case 43: case 44: 1883 case 45: case 46: case 47: 1884 scp->term.attr_mask |= BACKGROUND_CHANGED; 1885 scp->term.cur_color = 1886 (scp->term.cur_color&0x0F00) | (ansi_col[(n-40)&7]<<12); 1887 scp->term.cur_attr = mask2attr(&scp->term); 1888 break; 1889 } 1890 } 1891 break; 1892 1893 case 'x': 1894 if (scp->term.num_param == 0) 1895 n = 0; 1896 else 1897 n = scp->term.param[0]; 1898 switch (n) { 1899 case 0: /* reset attributes */ 1900 scp->term.attr_mask = NORMAL_ATTR; 1901 scp->term.cur_attr = 1902 scp->term.cur_color = scp->term.std_color = 1903 current_default->std_color; 1904 scp->term.rev_color = current_default->rev_color; 1905 break; 1906 case 1: /* set ansi background */ 1907 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 1908 scp->term.cur_color = scp->term.std_color = 1909 (scp->term.std_color & 0x0F00) | 1910 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1911 scp->term.cur_attr = mask2attr(&scp->term); 1912 break; 1913 case 2: /* set ansi foreground */ 1914 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 1915 scp->term.cur_color = scp->term.std_color = 1916 (scp->term.std_color & 0xF000) | 1917 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1918 scp->term.cur_attr = mask2attr(&scp->term); 1919 break; 1920 case 3: /* set ansi attribute directly */ 1921 scp->term.attr_mask &= ~(FOREGROUND_CHANGED|BACKGROUND_CHANGED); 1922 scp->term.cur_color = scp->term.std_color = 1923 (scp->term.param[1]&0xFF)<<8; 1924 scp->term.cur_attr = mask2attr(&scp->term); 1925 break; 1926 case 5: /* set ansi reverse video background */ 1927 scp->term.rev_color = 1928 (scp->term.rev_color & 0x0F00) | 1929 (ansi_col[(scp->term.param[1])&0x0F]<<12); 1930 scp->term.cur_attr = mask2attr(&scp->term); 1931 break; 1932 case 6: /* set ansi reverse video foreground */ 1933 scp->term.rev_color = 1934 (scp->term.rev_color & 0xF000) | 1935 (ansi_col[(scp->term.param[1])&0x0F]<<8); 1936 scp->term.cur_attr = mask2attr(&scp->term); 1937 break; 1938 case 7: /* set ansi reverse video directly */ 1939 scp->term.rev_color = 1940 (scp->term.param[1]&0xFF)<<8; 1941 scp->term.cur_attr = mask2attr(&scp->term); 1942 break; 1943 } 1944 break; 1945 1946 case 'z': /* switch to (virtual) console n */ 1947 if (scp->term.num_param == 1) 1948 switch_scr(scp, scp->term.param[0]); 1949 break; 1950 } 1951 } 1952 else if (scp->term.esc == 3) { 1953 if (c >= '0' && c <= '9') { 1954 if (scp->term.num_param < MAX_ESC_PAR) { 1955 if (scp->term.last_param != scp->term.num_param) { 1956 scp->term.last_param = scp->term.num_param; 1957 scp->term.param[scp->term.num_param] = 0; 1958 } 1959 else 1960 scp->term.param[scp->term.num_param] *= 10; 1961 scp->term.param[scp->term.num_param] += c - '0'; 1962 return; 1963 } 1964 } 1965 scp->term.num_param = scp->term.last_param + 1; 1966 switch (c) { 1967 1968 case ';': 1969 if (scp->term.num_param < MAX_ESC_PAR) 1970 return; 1971 break; 1972 1973 case 'A': /* set display border color */ 1974 if (scp->term.num_param == 1) 1975 scp->border=scp->term.param[0] & 0xff; 1976 if (scp == cur_console) 1977 set_border(scp->border); 1978 break; 1979 1980 case 'B': /* set bell pitch and duration */ 1981 if (scp->term.num_param == 2) { 1982 scp->bell_pitch = scp->term.param[0]; 1983 scp->bell_duration = scp->term.param[1]*10; 1984 } 1985 break; 1986 1987 case 'C': /* set cursor type & shape */ 1988 if (scp->term.num_param == 1) { 1989 if (scp->term.param[0] & 0x01) 1990 configuration |= BLINK_CURSOR; 1991 else 1992 configuration &= ~BLINK_CURSOR; 1993 if (scp->term.param[0] & 0x02) { 1994 configuration |= CHAR_CURSOR; 1995 set_destructive_cursor(scp, TRUE); 1996 } else 1997 configuration &= ~CHAR_CURSOR; 1998 } 1999 else if (scp->term.num_param == 2) { 2000 scp->cursor_start = scp->term.param[0] & 0x1F; 2001 scp->cursor_end = scp->term.param[1] & 0x1F; 2002 if (configuration & CHAR_CURSOR) 2003 set_destructive_cursor(scp, TRUE); 2004 } 2005 break; 2006 2007 case 'F': /* set ansi foreground */ 2008 if (scp->term.num_param == 1) { 2009 scp->term.attr_mask &= ~FOREGROUND_CHANGED; 2010 scp->term.cur_color = scp->term.std_color = 2011 (scp->term.std_color & 0xF000) 2012 | ((scp->term.param[0] & 0x0F) << 8); 2013 scp->term.cur_attr = mask2attr(&scp->term); 2014 } 2015 break; 2016 2017 case 'G': /* set ansi background */ 2018 if (scp->term.num_param == 1) { 2019 scp->term.attr_mask &= ~BACKGROUND_CHANGED; 2020 scp->term.cur_color = scp->term.std_color = 2021 (scp->term.std_color & 0x0F00) 2022 | ((scp->term.param[0] & 0x0F) << 12); 2023 scp->term.cur_attr = mask2attr(&scp->term); 2024 } 2025 break; 2026 2027 case 'H': /* set ansi reverse video foreground */ 2028 if (scp->term.num_param == 1) { 2029 scp->term.rev_color = 2030 (scp->term.rev_color & 0xF000) 2031 | ((scp->term.param[0] & 0x0F) << 8); 2032 scp->term.cur_attr = mask2attr(&scp->term); 2033 } 2034 break; 2035 2036 case 'I': /* set ansi reverse video background */ 2037 if (scp->term.num_param == 1) { 2038 scp->term.rev_color = 2039 (scp->term.rev_color & 0x0F00) 2040 | ((scp->term.param[0] & 0x0F) << 12); 2041 scp->term.cur_attr = mask2attr(&scp->term); 2042 } 2043 break; 2044 } 2045 } 2046 scp->term.esc = 0; 2047} 2048 2049static void 2050ansi_put(scr_stat *scp, u_char *buf, int len) 2051{ 2052 u_char *ptr = buf; 2053 2054 if (scp->status & UNKNOWN_MODE) 2055 return; 2056 2057 /* make screensaver happy */ 2058 if (scp == cur_console) { 2059 scrn_time_stamp = time.tv_sec; 2060 if (scrn_blanked) { 2061 (*current_saver)(FALSE); 2062 cur_console->start = 0; 2063 cur_console->end = cur_console->xsize * cur_console->ysize; 2064 } 2065 } 2066 write_in_progress++; 2067outloop: 2068 if (scp->term.esc) { 2069 scan_esc(scp, *ptr++); 2070 len--; 2071 } 2072 else if (PRINTABLE(*ptr)) { /* Print only printables */ 2073 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); 2074 u_short cur_attr = scp->term.cur_attr; 2075 u_short *cursor_pos = scp->cursor_pos; 2076 do { 2077 /* 2078 * gcc-2.6.3 generates poor (un)sign extension code. Casting the 2079 * pointers in the following to volatile should have no effect, 2080 * but in fact speeds up this inner loop from 26 to 18 cycles 2081 * (+ cache misses) on i486's. 2082 */ 2083#define UCVP(ucp) ((u_char volatile *)(ucp)) 2084 *cursor_pos++ = UCVP(scr_map)[*UCVP(ptr)] | cur_attr; 2085 ptr++; 2086 cnt--; 2087 } while (cnt && PRINTABLE(*ptr)); 2088 len -= (cursor_pos - scp->cursor_pos); 2089 scp->xpos += (cursor_pos - scp->cursor_pos); 2090 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2091 mark_for_update(scp, cursor_pos - scp->scr_buf); 2092 scp->cursor_pos = cursor_pos; 2093 if (scp->xpos >= scp->xsize) { 2094 scp->xpos = 0; 2095 scp->ypos++; 2096 } 2097 } 2098 else { 2099 switch(*ptr) { 2100 case 0x07: 2101 do_bell(scp, scp->bell_pitch, scp->bell_duration); 2102 break; 2103 2104 case 0x08: /* non-destructive backspace */ 2105 if (scp->cursor_pos > scp->scr_buf) { 2106 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2107 scp->cursor_pos--; 2108 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2109 if (scp->xpos > 0) 2110 scp->xpos--; 2111 else { 2112 scp->xpos += scp->xsize - 1; 2113 scp->ypos--; 2114 } 2115 } 2116 break; 2117 2118 case 0x09: /* non-destructive tab */ 2119 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2120 scp->cursor_pos += (8 - scp->xpos % 8u); 2121 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2122 if ((scp->xpos += (8 - scp->xpos % 8u)) >= scp->xsize) { 2123 scp->xpos = 0; 2124 scp->ypos++; 2125 } 2126 break; 2127 2128 case 0x0a: /* newline, same pos */ 2129 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2130 scp->cursor_pos += scp->xsize; 2131 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2132 scp->ypos++; 2133 break; 2134 2135 case 0x0c: /* form feed, clears screen */ 2136 clear_screen(scp); 2137 break; 2138 2139 case 0x0d: /* return, return to pos 0 */ 2140 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2141 scp->cursor_pos -= scp->xpos; 2142 mark_for_update(scp, scp->cursor_pos - scp->scr_buf); 2143 scp->xpos = 0; 2144 break; 2145 2146 case 0x1b: /* start escape sequence */ 2147 scp->term.esc = 1; 2148 scp->term.num_param = 0; 2149 break; 2150 } 2151 ptr++; len--; 2152 } 2153 /* do we have to scroll ?? */ 2154 if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { 2155 reverse_mouse_cut(scp, 0); 2156 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 2157 if (scp->history) { 2158 bcopyw(scp->scr_buf, scp->history_head, 2159 scp->xsize * sizeof(u_short)); 2160 scp->history_head += scp->xsize; 2161 if (scp->history_head + scp->xsize > 2162 scp->history + scp->history_size) 2163 scp->history_head = scp->history; 2164 } 2165 bcopyw(scp->scr_buf + scp->xsize, scp->scr_buf, 2166 scp->xsize * (scp->ysize - 1) * sizeof(u_short)); 2167 fillw(scp->term.cur_color | scr_map[0x20], 2168 scp->scr_buf + scp->xsize * (scp->ysize - 1), 2169 scp->xsize); 2170 scp->cursor_pos -= scp->xsize; 2171 scp->ypos--; 2172 mark_all(scp); 2173 } 2174 if (len) 2175 goto outloop; 2176 write_in_progress--; 2177 if (delayed_next_scr) 2178 switch_scr(scp, delayed_next_scr - 1); 2179} 2180 2181static void 2182scinit(void) 2183{ 2184 u_short volatile *cp; 2185 u_short was; 2186 unsigned hw_cursor; 2187 int i; 2188 2189 if (init_done) 2190 return; 2191 init_done = TRUE; 2192 /* 2193 * Finish defaulting crtc variables for a mono screen. Crtat is a 2194 * bogus common variable so that it can be shared with pcvt, so it 2195 * can't be statically initialized. XXX. 2196 */ 2197 Crtat = (u_short *)MONO_BUF; 2198 /* 2199 * If CGA memory seems to work, switch to color. 2200 */ 2201 cp = (u_short *)CGA_BUF; 2202 was = *cp; 2203 *cp = (u_short) 0xA55A; 2204 if (*cp == 0xA55A) { 2205 Crtat = (u_short *)cp; 2206 crtc_addr = COLOR_BASE; 2207 } 2208 *cp = was; 2209 2210 /* 2211 * Ensure a zero start address. This is mainly to recover after 2212 * switching from pcvt using userconfig(). The registers are w/o 2213 * for old hardware so it's too hard to relocate the active screen 2214 * memory. 2215 */ 2216 outb(crtc_addr, 12); 2217 outb(crtc_addr + 1, 0); 2218 outb(crtc_addr, 13); 2219 outb(crtc_addr + 1, 0); 2220 2221 /* extract cursor location */ 2222 outb(crtc_addr, 14); 2223 hw_cursor = inb(crtc_addr + 1) << 8; 2224 outb(crtc_addr, 15); 2225 hw_cursor |= inb(crtc_addr + 1); 2226 2227 /* move hardware cursor out of the way */ 2228 outb(crtc_addr, 14); 2229 outb(crtc_addr + 1, 0xff); 2230 outb(crtc_addr, 15); 2231 outb(crtc_addr + 1, 0xff); 2232 2233 /* is this a VGA or higher ? */ 2234 outb(crtc_addr, 7); 2235 if (inb(crtc_addr) == 7) { 2236 u_long pa; 2237 u_long segoff; 2238 2239 crtc_vga = TRUE; 2240 /* 2241 * Get the BIOS video mode pointer. 2242 */ 2243 segoff = *(u_long *)pa_to_va(0x4a8); 2244 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 2245 if (ISMAPPED(pa, sizeof(u_long))) { 2246 segoff = *(u_long *)pa_to_va(pa); 2247 pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); 2248 if (ISMAPPED(pa, 64)) 2249 video_mode_ptr = (char *)pa_to_va(pa); 2250 } 2251 } 2252 current_default = &user_default; 2253 console[0] = &main_console; 2254 init_scp(console[0]); 2255 console[0]->scr_buf = console[0]->mouse_pos = Crtat; 2256 console[0]->cursor_pos = Crtat + hw_cursor; 2257 console[0]->xpos = hw_cursor % COL; 2258 console[0]->ypos = hw_cursor / COL; 2259 cur_console = console[0]; 2260 for (i=1; i<MAXCONS; i++) 2261 console[i] = NULL; 2262 kernel_console.esc = 0; 2263 kernel_console.attr_mask = NORMAL_ATTR; 2264 kernel_console.cur_attr = 2265 kernel_console.cur_color = kernel_console.std_color = 2266 kernel_default.std_color; 2267 kernel_console.rev_color = kernel_default.rev_color; 2268 /* initialize mapscrn array to a one to one map */ 2269 for (i=0; i<sizeof(scr_map); i++) 2270 scr_map[i] = i; 2271} 2272 2273static scr_stat 2274*alloc_scp() 2275{ 2276 scr_stat *scp; 2277 2278 scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); 2279 init_scp(scp); 2280 scp->scr_buf = scp->cursor_pos = scp->mouse_pos = 2281 (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), 2282 M_DEVBUF, M_WAITOK); 2283 scp->history_head = scp->history_pos = scp->history = 2284 (u_short *)malloc(scp->history_size*sizeof(u_short), 2285 M_DEVBUF, M_WAITOK); 2286 bzero(scp->history_head, scp->history_size*sizeof(u_short)); 2287 if (crtc_vga && video_mode_ptr) 2288 set_mode(scp); 2289 clear_screen(scp); 2290 return scp; 2291} 2292 2293static void 2294init_scp(scr_stat *scp) 2295{ 2296 scp->mode = M_VGA_C80x25; 2297 scp->font = FONT_16; 2298 scp->xsize = COL; 2299 scp->ysize = ROW; 2300 scp->start = COL * ROW; 2301 scp->end = 0; 2302 scp->term.esc = 0; 2303 scp->term.attr_mask = NORMAL_ATTR; 2304 scp->term.cur_attr = 2305 scp->term.cur_color = scp->term.std_color = 2306 current_default->std_color; 2307 scp->term.rev_color = current_default->rev_color; 2308 scp->border = BG_BLACK; 2309 scp->cursor_start = *(char *)pa_to_va(0x461); 2310 scp->cursor_end = *(char *)pa_to_va(0x460); 2311 scp->mouse_xpos = scp->mouse_ypos = 0; 2312 scp->mouse_cut_start = scp->mouse_cut_end = NULL; 2313 scp->bell_pitch = BELL_PITCH; 2314 scp->bell_duration = BELL_DURATION; 2315 scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; 2316 scp->status |= CURSOR_ENABLED; 2317 scp->pid = 0; 2318 scp->proc = NULL; 2319 scp->smode.mode = VT_AUTO; 2320 scp->history_head = scp->history_pos = scp->history = NULL; 2321 scp->history_size = HISTORY_SIZE; 2322} 2323 2324static u_char 2325*get_fstr(u_int c, u_int *len) 2326{ 2327 u_int i; 2328 2329 if (!(c & FKEY)) 2330 return(NULL); 2331 i = (c & 0xFF) - F_FN; 2332 if (i > n_fkey_tab) 2333 return(NULL); 2334 *len = fkey_tab[i].len; 2335 return(fkey_tab[i].str); 2336} 2337 2338static void 2339update_leds(int which) 2340{ 2341 int s; 2342 static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; 2343 2344 /* replace CAPS led with ALTGR led for ALTGR keyboards */ 2345 if (key_map.n_keys > ALTGR_OFFSET) { 2346 if (which & ALKED) 2347 which |= CLKED; 2348 else 2349 which &= ~CLKED; 2350 } 2351 s = spltty(); 2352 kbd_cmd(KB_SETLEDS); 2353 kbd_cmd(xlate_leds[which & LED_MASK]); 2354 splx(s); 2355} 2356 2357static void 2358history_to_screen(scr_stat *scp) 2359{ 2360 int i; 2361 2362 for (i=0; i<scp->ysize; i++) 2363 bcopyw(scp->history + (((scp->history_pos - scp->history) + 2364 scp->history_size-((i+1)*scp->xsize))%scp->history_size), 2365 scp->scr_buf + (scp->xsize * (scp->ysize-1 - i)), 2366 scp->xsize * sizeof(u_short)); 2367 mark_all(scp); 2368} 2369 2370static int 2371history_up_line(scr_stat *scp) 2372{ 2373 if (WRAPHIST(scp, scp->history_pos, -(scp->xsize*scp->ysize)) != 2374 scp->history_head) { 2375 scp->history_pos = WRAPHIST(scp, scp->history_pos, -scp->xsize); 2376 history_to_screen(scp); 2377 return 0; 2378 } 2379 else 2380 return -1; 2381} 2382 2383static int 2384history_down_line(scr_stat *scp) 2385{ 2386 if (scp->history_pos != scp->history_head) { 2387 scp->history_pos = WRAPHIST(scp, scp->history_pos, scp->xsize); 2388 history_to_screen(scp); 2389 return 0; 2390 } 2391 else 2392 return -1; 2393} 2394 2395/* 2396 * scgetc(noblock) - get character from keyboard. 2397 * If noblock = 0 wait until a key is pressed. 2398 * Else return NOKEY. 2399 */ 2400u_int 2401scgetc(int noblock) 2402{ 2403 u_char scancode, keycode; 2404 u_int state, action; 2405 struct key_t *key; 2406 static u_char esc_flag = 0, compose = 0; 2407 static u_int chr = 0; 2408 2409next_code: 2410 kbd_wait(); 2411 /* First see if there is something in the keyboard port */ 2412 if (inb(KB_STAT) & KB_BUF_FULL) 2413 scancode = inb(KB_DATA); 2414 else if (noblock) 2415 return(NOKEY); 2416 else 2417 goto next_code; 2418 2419 add_keyboard_randomness(scancode); 2420 2421 if (cur_console->status & KBD_RAW_MODE) 2422 return scancode; 2423 2424 keycode = scancode & 0x7F; 2425 switch (esc_flag) { 2426 case 0x00: /* normal scancode */ 2427 switch(scancode) { 2428 case 0xB8: /* left alt (compose key) */ 2429 if (compose) { 2430 compose = 0; 2431 if (chr > 255) { 2432 do_bell(cur_console, 2433 BELL_PITCH, BELL_DURATION); 2434 chr = 0; 2435 } 2436 } 2437 break; 2438 case 0x38: 2439 if (!compose) { 2440 compose = 1; 2441 chr = 0; 2442 } 2443 break; 2444 case 0xE0: 2445 case 0xE1: 2446 esc_flag = scancode; 2447 goto next_code; 2448 } 2449 break; 2450 case 0xE0: /* 0xE0 prefix */ 2451 esc_flag = 0; 2452 switch (keycode) { 2453 case 0x1C: /* right enter key */ 2454 keycode = 0x59; 2455 break; 2456 case 0x1D: /* right ctrl key */ 2457 keycode = 0x5A; 2458 break; 2459 case 0x35: /* keypad divide key */ 2460 keycode = 0x5B; 2461 break; 2462 case 0x37: /* print scrn key */ 2463 keycode = 0x5C; 2464 break; 2465 case 0x38: /* right alt key (alt gr) */ 2466 keycode = 0x5D; 2467 break; 2468 case 0x47: /* grey home key */ 2469 keycode = 0x5E; 2470 break; 2471 case 0x48: /* grey up arrow key */ 2472 keycode = 0x5F; 2473 break; 2474 case 0x49: /* grey page up key */ 2475 keycode = 0x60; 2476 break; 2477 case 0x4B: /* grey left arrow key */ 2478 keycode = 0x61; 2479 break; 2480 case 0x4D: /* grey right arrow key */ 2481 keycode = 0x62; 2482 break; 2483 case 0x4F: /* grey end key */ 2484 keycode = 0x63; 2485 break; 2486 case 0x50: /* grey down arrow key */ 2487 keycode = 0x64; 2488 break; 2489 case 0x51: /* grey page down key */ 2490 keycode = 0x65; 2491 break; 2492 case 0x52: /* grey insert key */ 2493 keycode = 0x66; 2494 break; 2495 case 0x53: /* grey delete key */ 2496 keycode = 0x67; 2497 break; 2498 2499 /* the following 3 are only used on the MS "Natural" keyboard */ 2500 case 0x5b: /* left Window key */ 2501 keycode = 0x69; 2502 break; 2503 case 0x5c: /* right Window key */ 2504 keycode = 0x6a; 2505 break; 2506 case 0x5d: /* menu key */ 2507 keycode = 0x6b; 2508 break; 2509 default: /* ignore everything else */ 2510 goto next_code; 2511 } 2512 break; 2513 case 0xE1: /* 0xE1 prefix */ 2514 esc_flag = 0; 2515 if (keycode == 0x1D) 2516 esc_flag = 0x1D; 2517 goto next_code; 2518 /* NOT REACHED */ 2519 case 0x1D: /* pause / break */ 2520 esc_flag = 0; 2521 if (keycode != 0x45) 2522 goto next_code; 2523 keycode = 0x68; 2524 break; 2525 } 2526 2527 /* if scroll-lock pressed allow history browsing */ 2528 if (cur_console->history && cur_console->status & SLKED) { 2529 int i; 2530 2531 cur_console->status &= ~CURSOR_ENABLED; 2532 if (!(cur_console->status & BUFFER_SAVED)) { 2533 cur_console->status |= BUFFER_SAVED; 2534 cur_console->history_save = cur_console->history_head; 2535 2536 /* copy screen into top of history buffer */ 2537 for (i=0; i<cur_console->ysize; i++) { 2538 bcopyw(cur_console->scr_buf + (cur_console->xsize * i), 2539 cur_console->history_head, 2540 cur_console->xsize * sizeof(u_short)); 2541 cur_console->history_head += cur_console->xsize; 2542 if (cur_console->history_head + cur_console->xsize > 2543 cur_console->history + cur_console->history_size) 2544 cur_console->history_head=cur_console->history; 2545 } 2546 cur_console->history_pos = cur_console->history_head; 2547 history_to_screen(cur_console); 2548 } 2549 switch (scancode) { 2550 case 0x47: /* home key */ 2551 cur_console->history_pos = cur_console->history_head; 2552 history_to_screen(cur_console); 2553 goto next_code; 2554 2555 case 0x4F: /* end key */ 2556 cur_console->history_pos = 2557 WRAPHIST(cur_console, cur_console->history_head, 2558 cur_console->xsize*cur_console->ysize); 2559 history_to_screen(cur_console); 2560 goto next_code; 2561 2562 case 0x48: /* up arrow key */ 2563 if (history_up_line(cur_console)) 2564 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2565 goto next_code; 2566 2567 case 0x50: /* down arrow key */ 2568 if (history_down_line(cur_console)) 2569 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2570 goto next_code; 2571 2572 case 0x49: /* page up key */ 2573 for (i=0; i<cur_console->ysize; i++) 2574 if (history_up_line(cur_console)) { 2575 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2576 break; 2577 } 2578 goto next_code; 2579 2580 case 0x51: /* page down key */ 2581 for (i=0; i<cur_console->ysize; i++) 2582 if (history_down_line(cur_console)) { 2583 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2584 break; 2585 } 2586 goto next_code; 2587 } 2588 } 2589 2590 if (compose) { 2591 switch (scancode) { 2592 /* key pressed process it */ 2593 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 2594 chr = (scancode - 0x40) + chr*10; 2595 goto next_code; 2596 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 2597 chr = (scancode - 0x47) + chr*10; 2598 goto next_code; 2599 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 2600 chr = (scancode - 0x4E) + chr*10; 2601 goto next_code; 2602 case 0x52: /* keypad 0 */ 2603 chr *= 10; 2604 goto next_code; 2605 2606 /* key release, no interest here */ 2607 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 2608 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 2609 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 2610 case 0xD2: /* keypad 0 */ 2611 goto next_code; 2612 2613 case 0x38: /* left alt key */ 2614 break; 2615 default: 2616 if (chr) { 2617 compose = chr = 0; 2618 do_bell(cur_console, BELL_PITCH, BELL_DURATION); 2619 goto next_code; 2620 } 2621 break; 2622 } 2623 } 2624 2625 state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); 2626 if ((!agrs && (cur_console->status & ALKED)) 2627 || (agrs && !(cur_console->status & ALKED))) 2628 keycode += ALTGR_OFFSET; 2629 key = &key_map.key[keycode]; 2630 if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) 2631 || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) 2632 state ^= 1; 2633 2634 /* Check for make/break */ 2635 action = key->map[state]; 2636 if (scancode & 0x80) { /* key released */ 2637 if (key->spcl & 0x80) { 2638 switch (action) { 2639 case LSH: 2640 shfts &= ~1; 2641 break; 2642 case RSH: 2643 shfts &= ~2; 2644 break; 2645 case LCTR: 2646 ctls &= ~1; 2647 break; 2648 case RCTR: 2649 ctls &= ~2; 2650 break; 2651 case LALT: 2652 alts &= ~1; 2653 break; 2654 case RALT: 2655 alts &= ~2; 2656 break; 2657 case NLK: 2658 nlkcnt = 0; 2659 break; 2660 case CLK: 2661 clkcnt = 0; 2662 break; 2663 case SLK: 2664 slkcnt = 0; 2665 break; 2666 case ASH: 2667 agrs = 0; 2668 break; 2669 case ALK: 2670 alkcnt = 0; 2671 break; 2672 case META: 2673 metas = 0; 2674 break; 2675 } 2676 } 2677 if (chr && !compose) { 2678 action = chr; 2679 chr = 0; 2680 return(action); 2681 } 2682 } else { 2683 /* key pressed */ 2684 if (key->spcl & (0x80>>state)) { 2685 switch (action) { 2686 /* LOCKING KEYS */ 2687 case NLK: 2688 if (!nlkcnt) { 2689 nlkcnt++; 2690 if (cur_console->status & NLKED) 2691 cur_console->status &= ~NLKED; 2692 else 2693 cur_console->status |= NLKED; 2694 update_leds(cur_console->status); 2695 } 2696 break; 2697 case CLK: 2698 if (!clkcnt) { 2699 clkcnt++; 2700 if (cur_console->status & CLKED) 2701 cur_console->status &= ~CLKED; 2702 else 2703 cur_console->status |= CLKED; 2704 update_leds(cur_console->status); 2705 } 2706 break; 2707 case SLK: 2708 if (!slkcnt) { 2709 slkcnt++; 2710 if (cur_console->status & SLKED) { 2711 cur_console->status &= ~SLKED; 2712 if (cur_console->status & BUFFER_SAVED){ 2713 int i; 2714 u_short *ptr = cur_console->history_save; 2715 2716 for (i=0; i<cur_console->ysize; i++) { 2717 bcopyw(ptr, 2718 cur_console->scr_buf + 2719 (cur_console->xsize*i), 2720 cur_console->xsize * sizeof(u_short)); 2721 ptr += cur_console->xsize; 2722 if (ptr + cur_console->xsize > 2723 cur_console->history + 2724 cur_console->history_size) 2725 ptr = cur_console->history; 2726 } 2727 cur_console->status &= ~BUFFER_SAVED; 2728 cur_console->history_head=cur_console->history_save; 2729 cur_console->status |= CURSOR_ENABLED; 2730 mark_all(cur_console); 2731 } 2732 scstart(VIRTUAL_TTY(get_scr_num())); 2733 } 2734 else 2735 cur_console->status |= SLKED; 2736 update_leds(cur_console->status); 2737 } 2738 break; 2739 case ALK: 2740 if (!alkcnt) { 2741 alkcnt++; 2742 if (cur_console->status & ALKED) 2743 cur_console->status &= ~ALKED; 2744 else 2745 cur_console->status |= ALKED; 2746 update_leds(cur_console->status); 2747 } 2748 break; 2749 2750 /* NON-LOCKING KEYS */ 2751 case NOP: 2752 break; 2753 case RBT: 2754 shutdown_nice(); 2755 break; 2756 case SUSP: 2757#if NAPM > 0 2758 apm_suspend(); 2759#endif 2760 break; 2761 2762 case DBG: 2763#ifdef DDB /* try to switch to console 0 */ 2764 if (cur_console->smode.mode == VT_AUTO && 2765 console[0]->smode.mode == VT_AUTO) 2766 switch_scr(cur_console, 0); 2767 Debugger("manual escape to debugger"); 2768 return(NOKEY); 2769#else 2770 printf("No debugger in kernel\n"); 2771#endif 2772 break; 2773 case LSH: 2774 shfts |= 1; 2775 break; 2776 case RSH: 2777 shfts |= 2; 2778 break; 2779 case LCTR: 2780 ctls |= 1; 2781 break; 2782 case RCTR: 2783 ctls |= 2; 2784 break; 2785 case LALT: 2786 alts |= 1; 2787 break; 2788 case RALT: 2789 alts |= 2; 2790 break; 2791 case ASH: 2792 agrs = 1; 2793 break; 2794 case META: 2795 metas = 1; 2796 break; 2797 case NEXT: 2798 switch_scr(cur_console, (get_scr_num() + 1) % MAXCONS); 2799 break; 2800 case BTAB: 2801 return(BKEY); 2802 default: 2803 if (action >= F_SCR && action <= L_SCR) { 2804 switch_scr(cur_console, action - F_SCR); 2805 break; 2806 } 2807 if (action >= F_FN && action <= L_FN) 2808 action |= FKEY; 2809 return(action); 2810 } 2811 } 2812 else { 2813 if (metas) 2814 action |= MKEY; 2815 return(action); 2816 } 2817 } 2818 goto next_code; 2819} 2820 2821int 2822scmmap(dev_t dev, int offset, int nprot) 2823{ 2824 if (offset > 0x20000 - PAGE_SIZE) 2825 return -1; 2826 return i386_btop((VIDEOMEM + offset)); 2827} 2828 2829static void 2830kbd_wait(void) 2831{ 2832 int i = 500; 2833 2834 while (i--) { 2835 if ((inb(KB_STAT) & KB_READY) == 0) 2836 break; 2837 DELAY (25); 2838 } 2839} 2840 2841static void 2842kbd_cmd(u_char command) 2843{ 2844 int i, retry = 5; 2845 do { 2846 kbd_wait(); 2847 outb(KB_DATA, command); 2848 i = 50000; 2849 while (i--) { 2850 if (inb(KB_STAT) & KB_BUF_FULL) { 2851 int val; 2852 DELAY(25); 2853 val = inb(KB_DATA); 2854 if (val == KB_ACK) 2855 return; 2856 if (val == KB_RESEND) 2857 break; 2858 } 2859 } 2860 } while (retry--); 2861} 2862 2863static void 2864set_mode(scr_stat *scp) 2865{ 2866 char *modetable; 2867 char special_modetable[64]; 2868 int font_size; 2869 2870 if (scp != cur_console) 2871 return; 2872 2873 /* setup video hardware for the given mode */ 2874 switch (scp->mode) { 2875 case M_VGA_M80x60: 2876 bcopyw(video_mode_ptr+(64*M_VGA_M80x25),&special_modetable, 64); 2877 goto special_80x60; 2878 2879 case M_VGA_C80x60: 2880 bcopyw(video_mode_ptr+(64*M_VGA_C80x25),&special_modetable, 64); 2881special_80x60: 2882 special_modetable[2] = 0x08; 2883 special_modetable[19] = 0x47; 2884 goto special_480l; 2885 2886 case M_VGA_M80x30: 2887 bcopyw(video_mode_ptr+(64*M_VGA_M80x25),&special_modetable, 64); 2888 goto special_80x30; 2889 2890 case M_VGA_C80x30: 2891 bcopyw(video_mode_ptr+(64*M_VGA_C80x25),&special_modetable, 64); 2892special_80x30: 2893 special_modetable[19] = 0x4f; 2894special_480l: 2895 special_modetable[9] |= 0xc0; 2896 special_modetable[16] = 0x08; 2897 special_modetable[17] = 0x3e; 2898 special_modetable[26] = 0xea; 2899 special_modetable[28] = 0xdf; 2900 special_modetable[31] = 0xe7; 2901 special_modetable[32] = 0x04; 2902 modetable = special_modetable; 2903 goto setup_mode; 2904 2905 case M_ENH_B80x43: 2906 bcopyw(video_mode_ptr+(64*M_ENH_B80x25),&special_modetable, 64); 2907 goto special_80x43; 2908 2909 case M_ENH_C80x43: 2910 bcopyw(video_mode_ptr+(64*M_ENH_C80x25),&special_modetable, 64); 2911special_80x43: 2912 special_modetable[28] = 87; 2913 goto special_80x50; 2914 2915 case M_VGA_M80x50: 2916 bcopyw(video_mode_ptr+(64*M_VGA_M80x25),&special_modetable, 64); 2917 goto special_80x50; 2918 2919 case M_VGA_C80x50: 2920 bcopyw(video_mode_ptr+(64*M_VGA_C80x25),&special_modetable, 64); 2921special_80x50: 2922 special_modetable[2] = 8; 2923 special_modetable[19] = 7; 2924 modetable = special_modetable; 2925 goto setup_mode; 2926 2927 case M_VGA_C40x25: case M_VGA_C80x25: 2928 case M_VGA_M80x25: 2929 case M_B40x25: case M_C40x25: 2930 case M_B80x25: case M_C80x25: 2931 case M_ENH_B40x25: case M_ENH_C40x25: 2932 case M_ENH_B80x25: case M_ENH_C80x25: 2933 2934 modetable = video_mode_ptr + (scp->mode * 64); 2935setup_mode: 2936 set_vgaregs(modetable); 2937 font_size = *(modetable + 2); 2938 2939 /* set font type (size) */ 2940 switch (font_size) { 2941 case 0x10: 2942 outb(TSIDX, 0x03); outb(TSREG, 0x00); /* font 0 */ 2943 scp->font = FONT_16; 2944 break; 2945 case 0x0E: 2946 outb(TSIDX, 0x03); outb(TSREG, 0x05); /* font 1 */ 2947 scp->font = FONT_14; 2948 break; 2949 default: 2950 case 0x08: 2951 outb(TSIDX, 0x03); outb(TSREG, 0x0A); /* font 2 */ 2952 scp->font = FONT_8; 2953 break; 2954 } 2955 if (configuration & CHAR_CURSOR) 2956 set_destructive_cursor(scp, TRUE); 2957 break; 2958 2959 case M_BG320: case M_CG320: case M_BG640: 2960 case M_CG320_D: case M_CG640_E: 2961 case M_CG640x350: case M_ENH_CG640: 2962 case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 2963 2964 set_vgaregs(video_mode_ptr + (scp->mode * 64)); 2965 break; 2966 2967 default: 2968 /* call user defined function XXX */ 2969 break; 2970 } 2971 2972 /* set border color for this (virtual) console */ 2973 set_border(scp->border); 2974 return; 2975} 2976 2977void 2978set_border(int color) 2979{ 2980 inb(crtc_addr+6); /* reset flip-flop */ 2981 outb(ATC, 0x11); outb(ATC, color); 2982 inb(crtc_addr+6); /* reset flip-flop */ 2983 outb(ATC, 0x20); /* enable Palette */ 2984} 2985 2986static void 2987set_vgaregs(char *modetable) 2988{ 2989 int i, s = splhigh(); 2990 2991 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 2992 outb(TSIDX, 0x07); outb(TSREG, 0x00); /* unlock registers */ 2993 for (i=0; i<4; i++) { /* program sequencer */ 2994 outb(TSIDX, i+1); 2995 outb(TSREG, modetable[i+5]); 2996 } 2997 outb(MISC, modetable[9]); /* set dot-clock */ 2998 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 2999 outb(crtc_addr, 0x11); 3000 outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); 3001 for (i=0; i<25; i++) { /* program crtc */ 3002 outb(crtc_addr, i); 3003 if (i == 14 || i == 15) /* no hardware cursor */ 3004 outb(crtc_addr+1, 0xff); 3005 else 3006 outb(crtc_addr+1, modetable[i+10]); 3007 } 3008 inb(crtc_addr+6); /* reset flip-flop */ 3009 for (i=0; i<20; i++) { /* program attribute ctrl */ 3010 outb(ATC, i); 3011 outb(ATC, modetable[i+35]); 3012 } 3013 for (i=0; i<9; i++) { /* program graph data ctrl */ 3014 outb(GDCIDX, i); 3015 outb(GDCREG, modetable[i+55]); 3016 } 3017 inb(crtc_addr+6); /* reset flip-flop */ 3018 outb(ATC ,0x20); /* enable palette */ 3019 splx(s); 3020} 3021 3022static void 3023set_font_mode() 3024{ 3025 /* setup vga for loading fonts (graphics plane mode) */ 3026 inb(crtc_addr+6); 3027 outb(ATC, 0x30); outb(ATC, 0x01); 3028#if SLOW_VGA 3029 outb(TSIDX, 0x02); outb(TSREG, 0x04); 3030 outb(TSIDX, 0x04); outb(TSREG, 0x06); 3031 outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 3032 outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 3033 outb(GDCIDX, 0x06); outb(GDCREG, 0x05); 3034#else 3035 outw(TSIDX, 0x0402); 3036 outw(TSIDX, 0x0604); 3037 outw(GDCIDX, 0x0204); 3038 outw(GDCIDX, 0x0005); 3039 outw(GDCIDX, 0x0506); /* addr = a0000, 64kb */ 3040#endif 3041} 3042 3043static void 3044set_normal_mode() 3045{ 3046 int s = splhigh(); 3047 3048 /* setup vga for normal operation mode again */ 3049 inb(crtc_addr+6); 3050 outb(ATC, 0x30); outb(ATC, 0x0C); 3051#if SLOW_VGA 3052 outb(TSIDX, 0x02); outb(TSREG, 0x03); 3053 outb(TSIDX, 0x04); outb(TSREG, 0x02); 3054 outb(GDCIDX, 0x04); outb(GDCREG, 0x00); 3055 outb(GDCIDX, 0x05); outb(GDCREG, 0x10); 3056 if (crtc_addr == MONO_BASE) { 3057 outb(GDCIDX, 0x06); outb(GDCREG, 0x0A); /* addr = b0000, 32kb */ 3058 } 3059 else { 3060 outb(GDCIDX, 0x06); outb(GDCREG, 0x0E); /* addr = b8000, 32kb */ 3061 } 3062#else 3063 outw(TSIDX, 0x0302); 3064 outw(TSIDX, 0x0204); 3065 outw(GDCIDX, 0x0004); 3066 outw(GDCIDX, 0x1005); 3067 if (crtc_addr == MONO_BASE) 3068 outw(GDCIDX, 0x0A06); /* addr = b0000, 32kb */ 3069 else 3070 outw(GDCIDX, 0x0E06); /* addr = b8000, 32kb */ 3071#endif 3072 splx(s); 3073} 3074 3075static void 3076copy_font(int operation, int font_type, char* font_image) 3077{ 3078 int ch, line, segment, fontsize; 3079 u_char val; 3080 3081 switch (font_type) { 3082 default: 3083 case FONT_8: 3084 segment = 0x8000; 3085 fontsize = 8; 3086 break; 3087 case FONT_14: 3088 segment = 0x4000; 3089 fontsize = 14; 3090 break; 3091 case FONT_16: 3092 segment = 0x0000; 3093 fontsize = 16; 3094 break; 3095 } 3096 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 3097 outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 3098 set_font_mode(); 3099 for (ch=0; ch < 256; ch++) 3100 for (line=0; line < fontsize; line++) 3101 if (operation) 3102 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) = 3103 font_image[(ch*fontsize)+line]; 3104 else 3105 font_image[(ch*fontsize)+line] = 3106 *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line); 3107 set_normal_mode(); 3108 outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ 3109} 3110 3111static void 3112set_destructive_cursor(scr_stat *scp, int force) 3113{ 3114 u_char cursor[32]; 3115 caddr_t address; 3116 int i, font_size; 3117 char *font_buffer; 3118 static u_char old_saveunder = DEAD_CHAR; 3119 3120 if (!force && (scp->cursor_saveunder & 0xFF) == old_saveunder) 3121 return; 3122 old_saveunder = force ? DEAD_CHAR : scp->cursor_saveunder & 0xFF; 3123 switch (scp->font) { 3124 default: 3125 case FONT_8: 3126 font_size = 8; 3127 font_buffer = font_8; 3128 address = (caddr_t)VIDEOMEM + 0x8000; 3129 break; 3130 case FONT_14: 3131 font_size = 14; 3132 font_buffer = font_14; 3133 address = (caddr_t)VIDEOMEM + 0x4000; 3134 break; 3135 case FONT_16: 3136 font_size = 16; 3137 font_buffer = font_16; 3138 address = (caddr_t)VIDEOMEM; 3139 break; 3140 } 3141 bcopyw(font_buffer + ((scp->cursor_saveunder & 0xff) * font_size), 3142 cursor, font_size); 3143 for (i=0; i<32; i++) 3144 if ((i >= scp->cursor_start && i <= scp->cursor_end) || 3145 (scp->cursor_start >= font_size && i == font_size - 1)) 3146 cursor[i] |= 0xff; 3147 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 3148 set_font_mode(); 3149 bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); 3150 set_normal_mode(); 3151} 3152 3153static void 3154reverse_mouse_cut(scr_stat *scp, int cut) 3155{ 3156 ushort *ptr; 3157 int i = 0; 3158 3159 if (scp->mouse_cut_start != NULL) { 3160 for (ptr = (scp->mouse_cut_start > scp->mouse_cut_end 3161 ? scp->mouse_cut_end : scp->mouse_cut_start); 3162 ptr <= (scp->mouse_cut_start > scp->mouse_cut_end 3163 ? scp->mouse_cut_start : scp->mouse_cut_end); 3164 ptr++) { 3165 *ptr = (*ptr & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; 3166 if (cut) 3167 cut_buffer[i++] = *ptr & 0xff; 3168 } 3169 if (cut) 3170 cut_buffer[i] = 0x00; 3171 } 3172} 3173 3174static void 3175draw_mouse_image(scr_stat *scp) 3176{ 3177 caddr_t address; 3178 int i, font_size; 3179 char *font_buffer; 3180 u_short buffer[32]; 3181 u_short xoffset, yoffset; 3182 u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf); 3183 u_short *ptr = scp->scr_buf + (scp->mouse_oldpos - Crtat); 3184 3185 xoffset = scp->mouse_xpos % 8; 3186 switch (scp->font) { 3187 default: 3188 case FONT_8: 3189 font_size = 8; 3190 font_buffer = font_8; 3191 yoffset = scp->mouse_ypos % 8; 3192 address = (caddr_t)VIDEOMEM + 0x8000; 3193 break; 3194 case FONT_14: 3195 font_size = 14; 3196 font_buffer = font_14; 3197 yoffset = scp->mouse_ypos % 14; 3198 address = (caddr_t)VIDEOMEM + 0x4000; 3199 break; 3200 case FONT_16: 3201 font_size = 16; 3202 font_buffer = font_16; 3203 yoffset = scp->mouse_ypos % 16; 3204 address = (caddr_t)VIDEOMEM; 3205 break; 3206 } 3207 3208 bcopyw(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), 3209 &scp->mouse_cursor[0], font_size); 3210 bcopyw(font_buffer + ((*(scp->mouse_pos+1) & 0xff) * font_size), 3211 &scp->mouse_cursor[32], font_size); 3212 bcopyw(font_buffer + ((*(scp->mouse_pos+scp->xsize) & 0xff) * font_size), 3213 &scp->mouse_cursor[64], font_size); 3214 bcopyw(font_buffer + ((*(scp->mouse_pos+scp->xsize+1) & 0xff) * font_size), 3215 &scp->mouse_cursor[96], font_size); 3216 3217 for (i=0; i<font_size; i++) { 3218 buffer[i] = scp->mouse_cursor[i]<<8 | scp->mouse_cursor[i+32]; 3219 buffer[i+font_size]=scp->mouse_cursor[i+64]<<8|scp->mouse_cursor[i+96]; 3220 } 3221 for (i=0; i<16; i++) { 3222 buffer[i+yoffset] = 3223 ( buffer[i+yoffset] & ~(mouse_and_mask[i] >> xoffset)) 3224 | (mouse_or_mask[i] >> xoffset); 3225 } 3226 for (i=0; i<font_size; i++) { 3227 scp->mouse_cursor[i] = (buffer[i] & 0xff00) >> 8; 3228 scp->mouse_cursor[i+32] = buffer[i] & 0xff; 3229 scp->mouse_cursor[i+64] = (buffer[i+font_size] & 0xff00) >> 8; 3230 scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; 3231 } 3232 3233 if (crt_pos != scp->mouse_oldpos) { 3234 *(scp->mouse_oldpos) = scp->mouse_saveunder[0]; 3235 *(scp->mouse_oldpos+1) = scp->mouse_saveunder[1]; 3236 *(scp->mouse_oldpos+scp->xsize) = scp->mouse_saveunder[2]; 3237 *(scp->mouse_oldpos+scp->xsize+1) = scp->mouse_saveunder[3]; 3238 } 3239 scp->mouse_saveunder[0] = *(scp->mouse_pos); 3240 scp->mouse_saveunder[1] = *(scp->mouse_pos+1); 3241 scp->mouse_saveunder[2] = *(scp->mouse_pos+scp->xsize); 3242 scp->mouse_saveunder[3] = *(scp->mouse_pos+scp->xsize+1); 3243 if ((scp->cursor_pos == (ptr)) || 3244 (scp->cursor_pos == (ptr+1)) || 3245 (scp->cursor_pos == (ptr+scp->xsize)) || 3246 (scp->cursor_pos == (ptr+scp->xsize+1)) || 3247 (scp->cursor_pos == (scp->mouse_pos)) || 3248 (scp->cursor_pos == (scp->mouse_pos+1)) || 3249 (scp->cursor_pos == (scp->mouse_pos+scp->xsize)) || 3250 (scp->cursor_pos == (scp->mouse_pos+scp->xsize+1))) 3251 scp->status &= ~CURSOR_SHOWN; 3252 scp->mouse_oldpos = crt_pos; 3253 while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; 3254 *(crt_pos) = (*(scp->mouse_pos)&0xff00)|0xd0; 3255 *(crt_pos+scp->xsize) = (*(scp->mouse_pos+scp->xsize)&0xff00)|0xd2; 3256 if (scp->mouse_xpos < (scp->xsize-1)*8) { 3257 *(crt_pos+1) = (*(scp->mouse_pos+1)&0xff00)|0xd1; 3258 *(crt_pos+scp->xsize+1) = (*(scp->mouse_pos+scp->xsize+1)&0xff00)|0xd3; 3259 } 3260 set_font_mode(); 3261 bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + 0xd0 * 32, 128); 3262 set_normal_mode(); 3263} 3264 3265static void 3266save_palette(void) 3267{ 3268 int i; 3269 3270 outb(PALRADR, 0x00); 3271 for (i=0x00; i<0x300; i++) 3272 palette[i] = inb(PALDATA); 3273 inb(crtc_addr+6); /* reset flip/flop */ 3274} 3275 3276void 3277load_palette(void) 3278{ 3279 int i; 3280 3281 outb(PIXMASK, 0xFF); /* no pixelmask */ 3282 outb(PALWADR, 0x00); 3283 for (i=0x00; i<0x300; i++) 3284 outb(PALDATA, palette[i]); 3285 inb(crtc_addr+6); /* reset flip/flop */ 3286 outb(ATC, 0x20); /* enable palette */ 3287} 3288 3289static void 3290do_bell(scr_stat *scp, int pitch, int duration) 3291{ 3292 if (configuration & VISUAL_BELL) { 3293 if (blink_in_progress) 3294 return; 3295 blink_in_progress = 4; 3296 if (scp != cur_console) 3297 blink_in_progress += 2; 3298 blink_screen(cur_console); 3299 timeout((timeout_func_t)blink_screen, cur_console, hz/10); 3300 } else { 3301 if (scp != cur_console) 3302 pitch *= 2; 3303 sysbeep(pitch, duration); 3304 } 3305} 3306 3307static void 3308blink_screen(scr_stat *scp) 3309{ 3310 if (blink_in_progress > 1) { 3311 if (blink_in_progress & 1) 3312 fillw(kernel_default.std_color | scr_map[0x20], 3313 Crtat, scp->xsize * scp->ysize); 3314 else 3315 fillw(kernel_default.rev_color | scr_map[0x20], 3316 Crtat, scp->xsize * scp->ysize); 3317 blink_in_progress--; 3318 timeout((timeout_func_t)blink_screen, scp, hz/10); 3319 } 3320 else { 3321 blink_in_progress = FALSE; 3322 mark_all(scp); 3323 if (delayed_next_scr) 3324 switch_scr(scp, delayed_next_scr - 1); 3325 } 3326} 3327 3328#endif /* NSC */ 3329