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