1 /* $NetBSD: pccons.c,v 1.31 2002/10/23 09:10:38 jdolecek Exp $ */ 2 /* $OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $ */ 3 /* NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp */ 4 5 /*- 6 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved. 7 * Copyright (c) 1990 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * William Jolitz and Don Ahn. 12 * 13 * Copyright (c) 1994 Charles M. Hannum. 14 * Copyright (c) 1992, 1993 Erik Forsberg. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * @(#)pccons.c 5.11 (Berkeley) 5/21/91 45 */ 46 47 /* 48 * code to work keyboard & display for PC-style console 49 */ 50 51 #include "opt_ddb.h" 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/tty.h> 56 #include <sys/callout.h> 57 #include <sys/poll.h> 58 #include <sys/conf.h> 59 #include <sys/vnode.h> 60 #include <sys/kernel.h> 61 #include <sys/kcore.h> 62 #include <sys/device.h> 63 #include <sys/proc.h> 64 65 #include <machine/bus.h> 66 67 #include <machine/display.h> 68 #include <machine/pccons.h> 69 #include <machine/kbdreg.h> 70 71 #include <dev/cons.h> 72 #include <dev/isa/isavar.h> 73 74 #include <arc/arc/arcbios.h> 75 #include <arc/dev/pcconsvar.h> 76 77 #define XFREE86_BUG_COMPAT 78 79 #ifndef BEEP_FREQ 80 #define BEEP_FREQ 1600 81 #endif 82 #ifndef BEEP_TIME 83 #define BEEP_TIME (hz/5) 84 #endif 85 86 #define PCBURST 128 87 88 static u_short *Crtat; /* pointer to backing store */ 89 static u_short *crtat; /* pointer to current char */ 90 static u_char async, kernel, polling; /* Really, you don't want to know. */ 91 static u_char lock_state = 0x00, /* all off */ 92 old_lock_state = 0xff, 93 typematic_rate = 0xff, /* don't update until set by user */ 94 old_typematic_rate = 0xff; 95 static u_short cursor_shape = 0xffff, /* don't update until set by user */ 96 old_cursor_shape = 0xffff; 97 static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */ 98 int pc_xmode = 0; 99 100 /* 101 * Keyboard output queue. 102 */ 103 int kb_oq_put = 0; 104 int kb_oq_get = 0; 105 u_char kb_oq[8]; 106 107 #define PCUNIT(x) (minor(x)) 108 109 static struct video_state { 110 int cx, cy; /* escape parameters */ 111 int row, col; /* current cursor position */ 112 int nrow, ncol, nchr; /* current screen geometry */ 113 int offset; /* Saved cursor pos */ 114 u_char state; /* parser state */ 115 #define VSS_ESCAPE 1 116 #define VSS_EBRACE 2 117 #define VSS_EPARAM 3 118 char so; /* in standout mode? */ 119 char color; /* color or mono display */ 120 char at; /* normal attributes */ 121 char so_at; /* standout attributes */ 122 } vs; 123 124 static struct callout async_update_ch = CALLOUT_INITIALIZER; 125 126 void pc_xmode_on __P((void)); 127 void pc_xmode_off __P((void)); 128 static u_char kbc_get8042cmd __P((void)); 129 int kbd_cmd __P((u_char, u_char)); 130 static __inline int kbd_wait_output __P((void)); 131 static __inline int kbd_wait_input __P((void)); 132 void kbd_flush_input __P((void)); 133 void set_cursor_shape __P((void)); 134 void get_cursor_shape __P((void)); 135 void async_update __P((void)); 136 void do_async_update __P((u_char));; 137 138 void pccnputc __P((dev_t, int c)); 139 int pccngetc __P((dev_t)); 140 void pccnpollc __P((dev_t, int)); 141 142 extern struct cfdriver pc_cd; 143 144 dev_type_open(pcopen); 145 dev_type_close(pcclose); 146 dev_type_read(pcread); 147 dev_type_write(pcwrite); 148 dev_type_ioctl(pcioctl); 149 dev_type_tty(pctty); 150 dev_type_poll(pcpoll); 151 dev_type_mmap(pcmmap); 152 153 const struct cdevsw pc_cdevsw = { 154 pcopen, pcclose, pcread, pcwrite, pcioctl, 155 nostop, pctty, pcpoll, pcmmap, ttykqfilter, D_TTY 156 }; 157 158 #define CHR 2 159 160 char *sget __P((void)); 161 void sput __P((u_char *, int)); 162 163 void pcstart __P((struct tty *)); 164 int pcparam __P((struct tty *, struct termios *)); 165 static __inline void wcopy __P((void *, void *, u_int)); 166 void pc_context_init __P((bus_space_tag_t, bus_space_tag_t, bus_space_tag_t, 167 struct pccons_config *)); 168 169 extern void fillw __P((int, u_int16_t *, int)); 170 171 #define KBD_DELAY \ 172 DELAY(10); 173 174 #define crtc_read_1(reg) \ 175 bus_space_read_1(pccons_console_context.pc_crt_iot, \ 176 pccons_console_context.pc_6845_ioh, reg) 177 #define crtc_write_1(reg, data) \ 178 bus_space_write_1(pccons_console_context.pc_crt_iot, \ 179 pccons_console_context.pc_6845_ioh, reg, data) 180 181 struct pccons_context pccons_console_context; 182 183 void 184 kbd_context_init(kbd_iot, config) 185 bus_space_tag_t kbd_iot; 186 struct pccons_config *config; 187 { 188 struct pccons_kbd_context *pkc = &pccons_console_context.pc_pkc; 189 190 if (pkc->pkc_initialized) 191 return; 192 pkc->pkc_initialized = 1; 193 194 pkc->pkc_iot = kbd_iot; 195 196 bus_space_map(kbd_iot, config->pc_kbd_cmdp, 1, 0, 197 &pkc->pkc_cmd_ioh); 198 bus_space_map(kbd_iot, config->pc_kbd_datap, 1, 0, 199 &pkc->pkc_data_ioh); 200 } 201 202 void 203 pc_context_init(crt_iot, crt_memt, kbd_iot, config) 204 bus_space_tag_t crt_iot, crt_memt, kbd_iot; 205 struct pccons_config *config; 206 { 207 struct pccons_context *pc = &pccons_console_context; 208 209 if (pc->pc_initialized) 210 return; 211 pc->pc_initialized = 1; 212 213 kbd_context_init(kbd_iot, config); 214 215 pc->pc_crt_iot = crt_iot; 216 pc->pc_crt_memt = crt_memt; 217 218 bus_space_map(crt_iot, config->pc_mono_iobase, 2, 0, 219 &pc->pc_mono_ioh); 220 bus_space_map(crt_memt, config->pc_mono_memaddr, 0x20000, 0, 221 &pc->pc_mono_memh); 222 bus_space_map(crt_iot, config->pc_cga_iobase, 2, 0, 223 &pc->pc_cga_ioh); 224 bus_space_map(crt_memt, config->pc_cga_memaddr, 0x20000, 0, 225 &pc->pc_cga_memh); 226 227 /* 228 * pc->pc_6845_ioh and pc->pc_crt_memh will be initialized later, 229 * when `Crtat' is initialized. 230 */ 231 232 pc->pc_config = config; 233 234 (*config->pc_init)(); 235 } 236 237 /* 238 * bcopy variant that only moves word-aligned 16-bit entities, 239 * for stupid VGA cards. cnt is required to be an even vale. 240 */ 241 static __inline void 242 wcopy(src, tgt, cnt) 243 void *src, *tgt; 244 u_int cnt; 245 { 246 u_int16_t *from = src; 247 u_int16_t *to = tgt; 248 249 cnt >>= 1; 250 if (to < from || to >= from + cnt) 251 while(cnt--) 252 *to++ = *from++; 253 else { 254 to += cnt; 255 from += cnt; 256 while(cnt--) 257 *--to = *--from; 258 } 259 } 260 261 static __inline int 262 kbd_wait_output() 263 { 264 u_int i; 265 266 for (i = 100000; i; i--) 267 if ((kbd_cmd_read_1() & KBS_IBF) == 0) { 268 KBD_DELAY; 269 return 1; 270 } 271 return 0; 272 } 273 274 static __inline int 275 kbd_wait_input() 276 { 277 u_int i; 278 279 for (i = 100000; i; i--) 280 if ((kbd_cmd_read_1() & KBS_DIB) != 0) { 281 KBD_DELAY; 282 return 1; 283 } 284 return 0; 285 } 286 287 void 288 kbd_flush_input() 289 { 290 u_char c; 291 292 while ((c = kbd_cmd_read_1()) & 0x03) 293 if ((c & KBS_DIB) == KBS_DIB) { 294 /* XXX - delay is needed to prevent some keyboards from 295 wedging when the system boots */ 296 delay(6); 297 (void) kbd_data_read_1(); 298 } 299 } 300 301 #if 1 302 /* 303 * Get the current command byte. 304 */ 305 static u_char 306 kbc_get8042cmd() 307 { 308 309 if (!kbd_wait_output()) 310 return -1; 311 kbd_cmd_write_1(K_RDCMDBYTE); 312 if (!kbd_wait_input()) 313 return -1; 314 return kbd_data_read_1(); 315 } 316 #endif 317 318 /* 319 * Pass command byte to keyboard controller (8042). 320 */ 321 int 322 kbc_put8042cmd(val) 323 u_char val; 324 { 325 326 if (!kbd_wait_output()) 327 return 0; 328 kbd_cmd_write_1(K_LDCMDBYTE); 329 if (!kbd_wait_output()) 330 return 0; 331 kbd_data_write_1(val); 332 return 1; 333 } 334 335 /* 336 * Pass command to keyboard itself 337 */ 338 int 339 kbd_cmd(val, polling) 340 u_char val; 341 u_char polling; 342 { 343 u_int retries = 3; 344 register u_int i; 345 346 if(!polling) { 347 i = spltty(); 348 if(kb_oq_get == kb_oq_put) { 349 kbd_data_write_1(val); 350 } 351 kb_oq[kb_oq_put] = val; 352 kb_oq_put = (kb_oq_put + 1) & 7; 353 splx(i); 354 return(1); 355 } 356 else do { 357 if (!kbd_wait_output()) 358 return 0; 359 kbd_data_write_1(val); 360 for (i = 100000; i; i--) { 361 if (kbd_cmd_read_1() & KBS_DIB) { 362 register u_char c; 363 364 KBD_DELAY; 365 c = kbd_data_read_1(); 366 if (c == KBR_ACK || c == KBR_ECHO) { 367 return 1; 368 } 369 if (c == KBR_RESEND) { 370 break; 371 } 372 #ifdef DIAGNOSTIC 373 printf("kbd_cmd: input char %x lost\n", c); 374 #endif 375 } 376 } 377 } while (--retries); 378 return 0; 379 } 380 381 void 382 set_cursor_shape() 383 { 384 crtc_write_1(0, 10); 385 crtc_write_1(1, cursor_shape >> 8); 386 crtc_write_1(0, 11); 387 crtc_write_1(1, cursor_shape); 388 old_cursor_shape = cursor_shape; 389 } 390 391 void 392 get_cursor_shape() 393 { 394 crtc_write_1(0, 10); 395 cursor_shape = crtc_read_1(1) << 8; 396 crtc_write_1(0, 11); 397 cursor_shape |= crtc_read_1(1); 398 399 /* 400 * real 6845's, as found on, MDA, Hercules or CGA cards, do 401 * not support reading the cursor shape registers. the 6845 402 * tri-states it's data bus. This is _normally_ read by the 403 * cpu as either 0x00 or 0xff.. in which case we just use 404 * a line cursor. 405 */ 406 if (cursor_shape == 0x0000 || cursor_shape == 0xffff) 407 cursor_shape = 0x0b10; 408 else 409 cursor_shape &= 0x1f1f; 410 } 411 412 void 413 do_async_update(poll) 414 u_char poll; 415 { 416 int pos; 417 static int old_pos = -1; 418 419 async = 0; 420 421 if (lock_state != old_lock_state) { 422 old_lock_state = lock_state; 423 if (!kbd_cmd(KBC_MODEIND, poll) || 424 !kbd_cmd(lock_state, poll)) { 425 printf("pc: timeout updating leds\n"); 426 (void) kbd_cmd(KBC_ENABLE, poll); 427 } 428 } 429 if (typematic_rate != old_typematic_rate) { 430 old_typematic_rate = typematic_rate; 431 if (!kbd_cmd(KBC_TYPEMATIC, poll) || 432 !kbd_cmd(typematic_rate, poll)) { 433 printf("pc: timeout updating typematic rate\n"); 434 (void) kbd_cmd(KBC_ENABLE, poll); 435 } 436 } 437 438 if (pc_xmode > 0) 439 return; 440 441 pos = crtat - Crtat; 442 if (pos != old_pos) { 443 crtc_write_1(0, 14); 444 crtc_write_1(1, pos >> 8); 445 crtc_write_1(0, 15); 446 crtc_write_1(1, pos); 447 old_pos = pos; 448 } 449 if (cursor_shape != old_cursor_shape) 450 set_cursor_shape(); 451 } 452 453 void 454 async_update() 455 { 456 457 if (kernel || polling) { 458 if (async) 459 callout_stop(&async_update_ch); 460 do_async_update(1); 461 } else { 462 if (async) 463 return; 464 async = 1; 465 callout_reset(&async_update_ch, 1, 466 (void(*)(void *))do_async_update, NULL); 467 } 468 } 469 470 /* 471 * these are both bad jokes 472 */ 473 int 474 pccons_common_match(crt_iot, crt_memt, kbd_iot, config) 475 bus_space_tag_t crt_iot, crt_memt, kbd_iot; 476 struct pccons_config *config; 477 { 478 int i; 479 480 pc_context_init(crt_iot, crt_memt, kbd_iot, config); 481 482 /* Enable interrupts and keyboard, etc. */ 483 if (!kbc_put8042cmd(CMDBYTE)) { 484 printf("pcprobe: command error\n"); 485 return 0; 486 } 487 488 #if 1 489 /* Flush any garbage. */ 490 kbd_flush_input(); 491 /* Reset the keyboard. */ 492 if (!kbd_cmd(KBC_RESET, 1)) { 493 printf("pcprobe: reset error %d\n", 1); 494 goto lose; 495 } 496 for (i = 600000; i; i--) 497 if ((kbd_cmd_read_1() & KBS_DIB) != 0) { 498 KBD_DELAY; 499 break; 500 } 501 if (i == 0 || kbd_data_read_1() != KBR_RSTDONE) { 502 printf("pcprobe: reset error %d\n", 2); 503 goto lose; 504 } 505 /* 506 * Some keyboards seem to leave a second ack byte after the reset. 507 * This is kind of stupid, but we account for them anyway by just 508 * flushing the buffer. 509 */ 510 kbd_flush_input(); 511 /* Just to be sure. */ 512 if (!kbd_cmd(KBC_ENABLE, 1)) { 513 printf("pcprobe: reset error %d\n", 3); 514 goto lose; 515 } 516 517 /* 518 * Some keyboard/8042 combinations do not seem to work if the keyboard 519 * is set to table 1; in fact, it would appear that some keyboards just 520 * ignore the command altogether. So by default, we use the AT scan 521 * codes and have the 8042 translate them. Unfortunately, this is 522 * known to not work on some PS/2 machines. We try desparately to deal 523 * with this by checking the (lack of a) translate bit in the 8042 and 524 * attempting to set the keyboard to XT mode. If this all fails, well, 525 * tough luck. 526 * 527 * XXX It would perhaps be a better choice to just use AT scan codes 528 * and not bother with this. 529 */ 530 if (kbc_get8042cmd() & KC8_TRANS) { 531 /* The 8042 is translating for us; use AT codes. */ 532 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) { 533 printf("pcprobe: reset error %d\n", 4); 534 goto lose; 535 } 536 } else { 537 /* Stupid 8042; set keyboard to XT codes. */ 538 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) { 539 printf("pcprobe: reset error %d\n", 5); 540 goto lose; 541 } 542 } 543 544 lose: 545 /* 546 * Technically, we should probably fail the probe. But we'll be nice 547 * and allow keyboard-less machines to boot with the console. 548 */ 549 #endif 550 551 return 1; 552 } 553 554 void pccons_common_attach(sc, crt_iot, crt_memt, kbd_iot, config) 555 struct pc_softc *sc; 556 bus_space_tag_t crt_iot, crt_memt, kbd_iot; 557 struct pccons_config *config; 558 { 559 printf(": %s\n", vs.color ? "color" : "mono"); 560 do_async_update(1); 561 } 562 563 int 564 pcopen(dev, flag, mode, p) 565 dev_t dev; 566 int flag, mode; 567 struct proc *p; 568 { 569 struct pc_softc *sc; 570 int unit = PCUNIT(dev); 571 struct tty *tp; 572 573 if (unit >= pc_cd.cd_ndevs) 574 return ENXIO; 575 sc = pc_cd.cd_devs[unit]; 576 if (sc == 0) 577 return ENXIO; 578 579 if (!sc->sc_tty) { 580 tp = sc->sc_tty = ttymalloc(); 581 } 582 else { 583 tp = sc->sc_tty; 584 } 585 586 tp->t_oproc = pcstart; 587 tp->t_param = pcparam; 588 tp->t_dev = dev; 589 if ((tp->t_state & TS_ISOPEN) == 0) { 590 ttychars(tp); 591 tp->t_iflag = TTYDEF_IFLAG; 592 tp->t_oflag = TTYDEF_OFLAG; 593 tp->t_cflag = TTYDEF_CFLAG; 594 tp->t_lflag = TTYDEF_LFLAG; 595 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 596 pcparam(tp, &tp->t_termios); 597 ttsetwater(tp); 598 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 599 return EBUSY; 600 tp->t_state |= TS_CARR_ON; 601 602 return ((*tp->t_linesw->l_open)(dev, tp)); 603 } 604 605 int 606 pcclose(dev, flag, mode, p) 607 dev_t dev; 608 int flag, mode; 609 struct proc *p; 610 { 611 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 612 struct tty *tp = sc->sc_tty; 613 614 (*tp->t_linesw->l_close)(tp, flag); 615 ttyclose(tp); 616 #ifdef notyet /* XXX */ 617 ttyfree(tp); 618 #endif 619 return(0); 620 } 621 622 int 623 pcread(dev, uio, flag) 624 dev_t dev; 625 struct uio *uio; 626 int flag; 627 { 628 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 629 struct tty *tp = sc->sc_tty; 630 631 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 632 } 633 634 int 635 pcwrite(dev, uio, flag) 636 dev_t dev; 637 struct uio *uio; 638 int flag; 639 { 640 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 641 struct tty *tp = sc->sc_tty; 642 643 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 644 } 645 646 int 647 pcpoll(dev, events, p) 648 dev_t dev; 649 int events; 650 struct proc *p; 651 { 652 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 653 struct tty *tp = sc->sc_tty; 654 655 return ((*tp->t_linesw->l_poll)(tp, events, p)); 656 } 657 658 struct tty * 659 pctty(dev) 660 dev_t dev; 661 { 662 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 663 struct tty *tp = sc->sc_tty; 664 665 return (tp); 666 } 667 668 /* 669 * Got a console receive interrupt - 670 * the console processor wants to give us a character. 671 * Catch the character, and see who it goes to. 672 */ 673 int 674 pcintr(arg) 675 void *arg; 676 { 677 struct pc_softc *sc = arg; 678 register struct tty *tp = sc->sc_tty; 679 u_char *cp; 680 681 if ((kbd_cmd_read_1() & KBS_DIB) == 0) 682 return 0; 683 if (polling) 684 return 1; 685 do { 686 cp = sget(); 687 if (!tp || (tp->t_state & TS_ISOPEN) == 0) 688 return 1; 689 if (cp) 690 do 691 (*tp->t_linesw->l_rint)(*cp++, tp); 692 while (*cp); 693 } while (kbd_cmd_read_1() & KBS_DIB); 694 return 1; 695 } 696 697 int 698 pcioctl(dev, cmd, data, flag, p) 699 dev_t dev; 700 u_long cmd; 701 caddr_t data; 702 int flag; 703 struct proc *p; 704 { 705 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 706 struct tty *tp = sc->sc_tty; 707 int error; 708 709 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 710 if (error != EPASSTHROUGH) 711 return error; 712 error = ttioctl(tp, cmd, data, flag, p); 713 if (error != EPASSTHROUGH) 714 return error; 715 716 switch (cmd) { 717 case CONSOLE_X_MODE_ON: 718 pc_xmode_on(); 719 return 0; 720 case CONSOLE_X_MODE_OFF: 721 pc_xmode_off(); 722 return 0; 723 case CONSOLE_X_BELL: 724 /* 725 * If set, data is a pointer to a length 2 array of 726 * integers. data[0] is the pitch in Hz and data[1] 727 * is the duration in msec. 728 */ 729 if (data) 730 sysbeep(((int*)data)[0], 731 (((int*)data)[1] * hz) / 1000); 732 else 733 sysbeep(BEEP_FREQ, BEEP_TIME); 734 return 0; 735 case CONSOLE_SET_TYPEMATIC_RATE: { 736 u_char rate; 737 738 if (!data) 739 return EINVAL; 740 rate = *((u_char *)data); 741 /* 742 * Check that it isn't too big (which would cause it to be 743 * confused with a command). 744 */ 745 if (rate & 0x80) 746 return EINVAL; 747 typematic_rate = rate; 748 async_update(); 749 return 0; 750 } 751 case CONSOLE_SET_KEYMAP: { 752 pccons_keymap_t *map = (pccons_keymap_t *) data; 753 int i; 754 755 if (!data) 756 return EINVAL; 757 for (i = 0; i < KB_NUM_KEYS; i++) 758 if (map[i].unshift[KB_CODE_SIZE-1] || 759 map[i].shift[KB_CODE_SIZE-1] || 760 map[i].ctl[KB_CODE_SIZE-1] || 761 map[i].altgr[KB_CODE_SIZE-1] || 762 map[i].shift_altgr[KB_CODE_SIZE-1]) 763 return EINVAL; 764 765 bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS])); 766 return 0; 767 } 768 case CONSOLE_GET_KEYMAP: 769 if (!data) 770 return EINVAL; 771 bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS])); 772 return 0; 773 774 default: 775 return EPASSTHROUGH; 776 } 777 778 #ifdef DIAGNOSTIC 779 panic("pcioctl: impossible"); 780 #endif 781 } 782 783 void 784 pcstart(tp) 785 struct tty *tp; 786 { 787 struct clist *cl; 788 int s, len; 789 u_char buf[PCBURST]; 790 791 s = spltty(); 792 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 793 goto out; 794 tp->t_state |= TS_BUSY; 795 splx(s); 796 /* 797 * We need to do this outside spl since it could be fairly 798 * expensive and we don't want our serial ports to overflow. 799 */ 800 cl = &tp->t_outq; 801 len = q_to_b(cl, buf, PCBURST); 802 sput(buf, len); 803 s = spltty(); 804 tp->t_state &= ~TS_BUSY; 805 if (cl->c_cc) { 806 tp->t_state |= TS_TIMEOUT; 807 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp); 808 } 809 if (cl->c_cc <= tp->t_lowat) { 810 if (tp->t_state & TS_ASLEEP) { 811 tp->t_state &= ~TS_ASLEEP; 812 wakeup(cl); 813 } 814 selwakeup(&tp->t_wsel); 815 } 816 out: 817 splx(s); 818 } 819 820 /* ARGSUSED */ 821 void pccons_common_cnattach(crt_iot, crt_memt, kbd_iot, config) 822 bus_space_tag_t crt_iot, crt_memt, kbd_iot; 823 struct pccons_config *config; 824 { 825 int maj; 826 static struct consdev pccons = { 827 NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, 828 NODEV, CN_NORMAL 829 }; 830 831 /* 832 * For now, don't screw with it. 833 */ 834 /* crtat = 0; */ 835 836 pc_context_init(crt_iot, crt_memt, kbd_iot, config); 837 838 /* locate the major number */ 839 maj = cdevsw_lookup_major(&pc_cdevsw); 840 pccons.cn_dev = makedev(maj, 0); 841 842 cn_tab = &pccons; 843 } 844 845 /* ARGSUSED */ 846 void 847 pccnputc(dev, c) 848 dev_t dev; 849 int c; 850 { 851 u_char cc, oldkernel = kernel; 852 853 kernel = 1; 854 if (c == '\n') { 855 sput("\r\n", 2); 856 } else { 857 cc = c; 858 sput(&cc, 1); 859 } 860 kernel = oldkernel; 861 } 862 863 /* ARGSUSED */ 864 int 865 pccngetc(dev) 866 dev_t dev; 867 { 868 register char *cp; 869 870 if (pc_xmode > 0) 871 return 0; 872 873 do { 874 /* wait for byte */ 875 while ((kbd_cmd_read_1() & KBS_DIB) == 0); 876 /* see if it's worthwhile */ 877 cp = sget(); 878 } while (!cp); 879 if (*cp == '\r') 880 return '\n'; 881 return *cp; 882 } 883 884 void 885 pccnpollc(dev, on) 886 dev_t dev; 887 int on; 888 { 889 890 polling = on; 891 if (!on) { 892 int unit; 893 struct pc_softc *sc; 894 int s; 895 896 /* 897 * If disabling polling on a device that's been configured, 898 * make sure there are no bytes left in the FIFO, holding up 899 * the interrupt line. Otherwise we won't get any further 900 * interrupts. 901 */ 902 unit = PCUNIT(dev); 903 if (pc_cd.cd_ndevs > unit) { 904 sc = pc_cd.cd_devs[unit]; 905 if (sc != 0) { 906 s = spltty(); 907 pcintr(sc); 908 splx(s); 909 } 910 } 911 } 912 } 913 914 /* 915 * Set line parameters. 916 */ 917 int 918 pcparam(tp, t) 919 struct tty *tp; 920 struct termios *t; 921 { 922 923 tp->t_ispeed = t->c_ispeed; 924 tp->t_ospeed = t->c_ospeed; 925 tp->t_cflag = t->c_cflag; 926 return 0; 927 } 928 929 #define wrtchar(c, at) do {\ 930 char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \ 931 } while (0) 932 933 /* translate ANSI color codes to standard pc ones */ 934 static char fgansitopc[] = { 935 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, 936 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY 937 }; 938 939 static char bgansitopc[] = { 940 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, 941 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY 942 }; 943 944 static u_char iso2ibm437[] = 945 { 946 0, 0, 0, 0, 0, 0, 0, 0, 947 0, 0, 0, 0, 0, 0, 0, 0, 948 0, 0, 0, 0, 0, 0, 0, 0, 949 0, 0, 0, 0, 0, 0, 0, 0, 950 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40, 951 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0, 952 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa, 953 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8, 954 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80, 955 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 956 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f, 957 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1, 958 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87, 959 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, 960 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f, 961 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0 962 }; 963 964 /* 965 * `pc3' termcap emulation. 966 */ 967 void 968 sput(cp, n) 969 u_char *cp; 970 int n; 971 { 972 struct pccons_context *pc = &pccons_console_context; 973 u_char c, scroll = 0; 974 975 if (pc_xmode > 0) 976 return; 977 978 if (crtat == 0) { 979 volatile u_short *cp; 980 u_short was; 981 unsigned cursorat; 982 983 cp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh); 984 was = *cp; 985 *cp = 0xA55A; 986 if (*cp != 0xA55A) { 987 cp = bus_space_vaddr(pc->pc_crt_memt, 988 pc->pc_mono_memh); 989 pc->pc_6845_ioh = pc->pc_mono_ioh; 990 pc->pc_crt_memh = pc->pc_mono_memh; 991 vs.color = 0; 992 } else { 993 *cp = was; 994 pc->pc_6845_ioh = pc->pc_cga_ioh; 995 pc->pc_crt_memh = pc->pc_cga_memh; 996 vs.color = 1; 997 } 998 999 #ifdef FAT_CURSOR 1000 cursor_shape = 0x0012; 1001 #else 1002 get_cursor_shape(); 1003 #endif 1004 1005 bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow); 1006 vs.nchr = vs.ncol * vs.nrow; 1007 vs.col--; 1008 vs.row--; 1009 cursorat = vs.ncol * vs.row + vs.col; 1010 vs.at = FG_LIGHTGREY | BG_BLACK; 1011 1012 Crtat = (u_short *)cp; 1013 crtat = Crtat + cursorat; 1014 1015 if (vs.color == 0) 1016 vs.so_at = FG_BLACK | BG_LIGHTGREY; 1017 else 1018 vs.so_at = FG_YELLOW | BG_BLACK; 1019 1020 fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat); 1021 } 1022 1023 while (n--) { 1024 if (!(c = *cp++)) 1025 continue; 1026 1027 switch (c) { 1028 case 0x1B: 1029 if (vs.state >= VSS_ESCAPE) { 1030 wrtchar(c, vs.so_at); 1031 vs.state = 0; 1032 goto maybe_scroll; 1033 } else 1034 vs.state = VSS_ESCAPE; 1035 break; 1036 1037 case 0x9B: /* CSI */ 1038 vs.cx = vs.cy = 0; 1039 vs.state = VSS_EBRACE; 1040 break; 1041 1042 case '\t': { 1043 int inccol = 8 - (vs.col & 7); 1044 crtat += inccol; 1045 vs.col += inccol; 1046 } 1047 maybe_scroll: 1048 if (vs.col >= vs.ncol) { 1049 vs.col -= vs.ncol; 1050 scroll = 1; 1051 } 1052 break; 1053 1054 case '\b': 1055 if (crtat <= Crtat) 1056 break; 1057 --crtat; 1058 if (--vs.col < 0) 1059 vs.col += vs.ncol; /* non-destructive backspace */ 1060 break; 1061 1062 case '\r': 1063 crtat -= vs.col; 1064 vs.col = 0; 1065 break; 1066 1067 case '\n': 1068 crtat += vs.ncol; 1069 scroll = 1; 1070 break; 1071 1072 default: 1073 switch (vs.state) { 1074 case 0: 1075 if (c == '\a') 1076 sysbeep(BEEP_FREQ, BEEP_TIME); 1077 else { 1078 /* 1079 * If we're outputting multiple printed 1080 * characters, just blast them to the 1081 * screen until we reach the end of the 1082 * buffer or a control character. This 1083 * saves time by short-circuiting the 1084 * switch. 1085 * If we reach the end of the line, we 1086 * break to do a scroll check. 1087 */ 1088 for (;;) { 1089 if (c & 0x80) 1090 c = iso2ibm437[c&0x7f]; 1091 1092 if (vs.so) 1093 wrtchar(c, vs.so_at); 1094 else 1095 wrtchar(c, vs.at); 1096 if (vs.col >= vs.ncol) { 1097 vs.col = 0; 1098 scroll = 1; 1099 break; 1100 } 1101 if (!n || (c = *cp) < ' ') 1102 break; 1103 n--, cp++; 1104 } 1105 } 1106 break; 1107 case VSS_ESCAPE: 1108 switch (c) { 1109 case '[': /* Start ESC [ sequence */ 1110 vs.cx = vs.cy = 0; 1111 vs.state = VSS_EBRACE; 1112 break; 1113 case 'c': /* Create screen & home */ 1114 fillw((vs.at << 8) | ' ', 1115 Crtat, vs.nchr); 1116 crtat = Crtat; 1117 vs.col = 0; 1118 vs.state = 0; 1119 break; 1120 case '7': /* save cursor pos */ 1121 vs.offset = crtat - Crtat; 1122 vs.state = 0; 1123 break; 1124 case '8': /* restore cursor pos */ 1125 crtat = Crtat + vs.offset; 1126 vs.row = vs.offset / vs.ncol; 1127 vs.col = vs.offset % vs.ncol; 1128 vs.state = 0; 1129 break; 1130 default: /* Invalid, clear state */ 1131 wrtchar(c, vs.so_at); 1132 vs.state = 0; 1133 goto maybe_scroll; 1134 } 1135 break; 1136 1137 default: /* VSS_EBRACE or VSS_EPARAM */ 1138 switch (c) { 1139 int pos; 1140 case 'm': 1141 if (!vs.cx) 1142 vs.so = 0; 1143 else 1144 vs.so = 1; 1145 vs.state = 0; 1146 break; 1147 case 'A': { /* back cx rows */ 1148 int cx = vs.cx; 1149 if (cx <= 0) 1150 cx = 1; 1151 else 1152 cx %= vs.nrow; 1153 pos = crtat - Crtat; 1154 pos -= vs.ncol * cx; 1155 if (pos < 0) 1156 pos += vs.nchr; 1157 crtat = Crtat + pos; 1158 vs.state = 0; 1159 break; 1160 } 1161 case 'B': { /* down cx rows */ 1162 int cx = vs.cx; 1163 if (cx <= 0) 1164 cx = 1; 1165 else 1166 cx %= vs.nrow; 1167 pos = crtat - Crtat; 1168 pos += vs.ncol * cx; 1169 if (pos >= vs.nchr) 1170 pos -= vs.nchr; 1171 crtat = Crtat + pos; 1172 vs.state = 0; 1173 break; 1174 } 1175 case 'C': { /* right cursor */ 1176 int cx = vs.cx, 1177 col = vs.col; 1178 if (cx <= 0) 1179 cx = 1; 1180 else 1181 cx %= vs.ncol; 1182 pos = crtat - Crtat; 1183 pos += cx; 1184 col += cx; 1185 if (col >= vs.ncol) { 1186 pos -= vs.ncol; 1187 col -= vs.ncol; 1188 } 1189 vs.col = col; 1190 crtat = Crtat + pos; 1191 vs.state = 0; 1192 break; 1193 } 1194 case 'D': { /* left cursor */ 1195 int cx = vs.cx, 1196 col = vs.col; 1197 if (cx <= 0) 1198 cx = 1; 1199 else 1200 cx %= vs.ncol; 1201 pos = crtat - Crtat; 1202 pos -= cx; 1203 col -= cx; 1204 if (col < 0) { 1205 pos += vs.ncol; 1206 col += vs.ncol; 1207 } 1208 vs.col = col; 1209 crtat = Crtat + pos; 1210 vs.state = 0; 1211 break; 1212 } 1213 case 'J': /* Clear ... */ 1214 switch (vs.cx) { 1215 case 0: 1216 /* ... to end of display */ 1217 fillw((vs.at << 8) | ' ', 1218 crtat, 1219 Crtat + vs.nchr - crtat); 1220 break; 1221 case 1: 1222 /* ... to next location */ 1223 fillw((vs.at << 8) | ' ', 1224 Crtat, 1225 crtat - Crtat + 1); 1226 break; 1227 case 2: 1228 /* ... whole display */ 1229 fillw((vs.at << 8) | ' ', 1230 Crtat, 1231 vs.nchr); 1232 break; 1233 } 1234 vs.state = 0; 1235 break; 1236 case 'K': /* Clear line ... */ 1237 switch (vs.cx) { 1238 case 0: 1239 /* ... current to EOL */ 1240 fillw((vs.at << 8) | ' ', 1241 crtat, 1242 vs.ncol - vs.col); 1243 break; 1244 case 1: 1245 /* ... beginning to next */ 1246 fillw((vs.at << 8) | ' ', 1247 crtat - vs.col, 1248 vs.col + 1); 1249 break; 1250 case 2: 1251 /* ... entire line */ 1252 fillw((vs.at << 8) | ' ', 1253 crtat - vs.col, vs.ncol); 1254 break; 1255 } 1256 vs.state = 0; 1257 break; 1258 case 'f': /* in system V consoles */ 1259 case 'H': { /* Cursor move */ 1260 int cx = vs.cx, 1261 cy = vs.cy; 1262 if (!cx || !cy) { 1263 crtat = Crtat; 1264 vs.col = 0; 1265 } else { 1266 if (cx > vs.nrow) 1267 cx = vs.nrow; 1268 if (cy > vs.ncol) 1269 cy = vs.ncol; 1270 crtat = Crtat + 1271 (cx - 1) * vs.ncol + cy - 1; 1272 vs.col = cy - 1; 1273 } 1274 vs.state = 0; 1275 break; 1276 } 1277 case 'M': { /* delete cx rows */ 1278 u_short *crtAt = crtat - vs.col; 1279 int cx = vs.cx, 1280 row = (crtAt - Crtat) / vs.ncol, 1281 nrow = vs.nrow - row; 1282 if (cx <= 0) 1283 cx = 1; 1284 else if (cx > nrow) 1285 cx = nrow; 1286 if (cx < nrow) 1287 #ifdef PCCONS_FORCE_WORD 1288 wcopy(crtAt + vs.ncol * cx, 1289 crtAt, vs.ncol * (nrow - 1290 cx) * CHR); 1291 #else 1292 bcopy(crtAt + vs.ncol * cx, 1293 crtAt, vs.ncol * (nrow - 1294 cx) * CHR); 1295 #endif 1296 fillw((vs.at << 8) | ' ', 1297 crtAt + vs.ncol * (nrow - cx), 1298 vs.ncol * cx); 1299 vs.state = 0; 1300 break; 1301 } 1302 case 'S': { /* scroll up cx lines */ 1303 int cx = vs.cx; 1304 if (cx <= 0) 1305 cx = 1; 1306 else if (cx > vs.nrow) 1307 cx = vs.nrow; 1308 if (cx < vs.nrow) 1309 #ifdef PCCONS_FORCE_WORD 1310 wcopy(Crtat + vs.ncol * cx, 1311 Crtat, vs.ncol * (vs.nrow - 1312 cx) * CHR); 1313 #else 1314 bcopy(Crtat + vs.ncol * cx, 1315 Crtat, vs.ncol * (vs.nrow - 1316 cx) * CHR); 1317 #endif 1318 fillw((vs.at << 8) | ' ', 1319 Crtat + vs.ncol * (vs.nrow - cx), 1320 vs.ncol * cx); 1321 /* crtat -= vs.ncol * cx; XXX */ 1322 vs.state = 0; 1323 break; 1324 } 1325 case 'L': { /* insert cx rows */ 1326 u_short *crtAt = crtat - vs.col; 1327 int cx = vs.cx, 1328 row = (crtAt - Crtat) / vs.ncol, 1329 nrow = vs.nrow - row; 1330 if (cx <= 0) 1331 cx = 1; 1332 else if (cx > nrow) 1333 cx = nrow; 1334 if (cx < nrow) 1335 #ifdef PCCONS_FORCE_WORD 1336 wcopy(crtAt, 1337 crtAt + vs.ncol * cx, 1338 vs.ncol * (nrow - cx) * 1339 CHR); 1340 #else 1341 bcopy(crtAt, 1342 crtAt + vs.ncol * cx, 1343 vs.ncol * (nrow - cx) * 1344 CHR); 1345 #endif 1346 fillw((vs.at << 8) | ' ', crtAt, 1347 vs.ncol * cx); 1348 vs.state = 0; 1349 break; 1350 } 1351 case 'T': { /* scroll down cx lines */ 1352 int cx = vs.cx; 1353 if (cx <= 0) 1354 cx = 1; 1355 else if (cx > vs.nrow) 1356 cx = vs.nrow; 1357 if (cx < vs.nrow) 1358 #ifdef PCCONS_FORCE_WORD 1359 wcopy(Crtat, 1360 Crtat + vs.ncol * cx, 1361 vs.ncol * (vs.nrow - cx) * 1362 CHR); 1363 #else 1364 bcopy(Crtat, 1365 Crtat + vs.ncol * cx, 1366 vs.ncol * (vs.nrow - cx) * 1367 CHR); 1368 #endif 1369 fillw((vs.at << 8) | ' ', Crtat, 1370 vs.ncol * cx); 1371 /* crtat += vs.ncol * cx; XXX */ 1372 vs.state = 0; 1373 break; 1374 } 1375 case ';': /* Switch params in cursor def */ 1376 vs.state = VSS_EPARAM; 1377 break; 1378 case 'r': 1379 vs.so_at = (vs.cx & FG_MASK) | 1380 ((vs.cy << 4) & BG_MASK); 1381 vs.state = 0; 1382 break; 1383 case 's': /* save cursor pos */ 1384 vs.offset = crtat - Crtat; 1385 vs.state = 0; 1386 break; 1387 case 'u': /* restore cursor pos */ 1388 crtat = Crtat + vs.offset; 1389 vs.row = vs.offset / vs.ncol; 1390 vs.col = vs.offset % vs.ncol; 1391 vs.state = 0; 1392 break; 1393 case 'x': /* set attributes */ 1394 switch (vs.cx) { 1395 case 0: 1396 vs.at = FG_LIGHTGREY | BG_BLACK; 1397 break; 1398 case 1: 1399 /* ansi background */ 1400 if (!vs.color) 1401 break; 1402 vs.at &= FG_MASK; 1403 vs.at |= bgansitopc[vs.cy & 7]; 1404 break; 1405 case 2: 1406 /* ansi foreground */ 1407 if (!vs.color) 1408 break; 1409 vs.at &= BG_MASK; 1410 vs.at |= fgansitopc[vs.cy & 7]; 1411 break; 1412 case 3: 1413 /* pc text attribute */ 1414 if (vs.state >= VSS_EPARAM) 1415 vs.at = vs.cy; 1416 break; 1417 } 1418 vs.state = 0; 1419 break; 1420 1421 default: /* Only numbers valid here */ 1422 if ((c >= '0') && (c <= '9')) { 1423 if (vs.state >= VSS_EPARAM) { 1424 vs.cy *= 10; 1425 vs.cy += c - '0'; 1426 } else { 1427 vs.cx *= 10; 1428 vs.cx += c - '0'; 1429 } 1430 } else 1431 vs.state = 0; 1432 break; 1433 } 1434 break; 1435 } 1436 } 1437 if (scroll) { 1438 scroll = 0; 1439 /* scroll check */ 1440 if (crtat >= Crtat + vs.nchr) { 1441 if (!kernel) { 1442 int s = spltty(); 1443 if (lock_state & KB_SCROLL) 1444 tsleep(&lock_state, 1445 PUSER, "pcputc", 0); 1446 splx(s); 1447 } 1448 #if PCCONS_FORCE_WORD 1449 wcopy(Crtat + vs.ncol, Crtat, 1450 (vs.nchr - vs.ncol) * CHR); 1451 #else 1452 bcopy(Crtat + vs.ncol, Crtat, 1453 (vs.nchr - vs.ncol) * CHR); 1454 #endif 1455 fillw((vs.at << 8) | ' ', 1456 Crtat + vs.nchr - vs.ncol, 1457 vs.ncol); 1458 crtat -= vs.ncol; 1459 } 1460 } 1461 } 1462 async_update(); 1463 } 1464 1465 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between 1466 left and right shift when reading the keyboard map */ 1467 static pccons_keymap_t scan_codes[KB_NUM_KEYS] = { 1468 /* type unshift shift control altgr shift_altgr scancode */ 1469 { KB_NONE, "", "", "", "", ""}, /* 0 unused */ 1470 { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */ 1471 { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */ 1472 { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */ 1473 { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */ 1474 { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */ 1475 { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */ 1476 { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */ 1477 { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */ 1478 { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */ 1479 { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */ 1480 { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */ 1481 { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */ 1482 { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */ 1483 { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */ 1484 { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */ 1485 { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */ 1486 { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */ 1487 { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */ 1488 { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */ 1489 { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */ 1490 { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */ 1491 { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */ 1492 { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */ 1493 { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */ 1494 { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */ 1495 { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */ 1496 { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */ 1497 { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */ 1498 { KB_CTL, "", "", "", "", ""}, /* 29 control */ 1499 { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */ 1500 { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */ 1501 { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */ 1502 { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */ 1503 { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */ 1504 { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */ 1505 { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */ 1506 { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */ 1507 { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */ 1508 { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */ 1509 { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */ 1510 { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */ 1511 { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */ 1512 { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */ 1513 { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */ 1514 { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */ 1515 { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */ 1516 { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */ 1517 { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */ 1518 { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */ 1519 { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */ 1520 { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */ 1521 { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */ 1522 { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */ 1523 { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */ 1524 { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */ 1525 { KB_ALT, "", "", "", "", ""}, /* 56 alt */ 1526 { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */ 1527 { KB_CAPS, "", "", "", "", ""}, /* 58 caps */ 1528 { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */ 1529 { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */ 1530 { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */ 1531 { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */ 1532 { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */ 1533 { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */ 1534 { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */ 1535 { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */ 1536 { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */ 1537 { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */ 1538 { KB_NUM, "", "", "", "", ""}, /* 69 num lock */ 1539 { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */ 1540 { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */ 1541 { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */ 1542 { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */ 1543 { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */ 1544 { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */ 1545 { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */ 1546 { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */ 1547 { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */ 1548 { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */ 1549 { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */ 1550 { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */ 1551 { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */ 1552 { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */ 1553 { KB_NONE, "", "", "", "", ""}, /* 84 0 */ 1554 { KB_NONE, "", "", "", "", ""}, /* 85 0 */ 1555 { KB_NONE, "", "", "", "", ""}, /* 86 0 */ 1556 { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */ 1557 { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */ 1558 { KB_NONE, "", "", "", "", ""}, /* 89 0 */ 1559 { KB_NONE, "", "", "", "", ""}, /* 90 0 */ 1560 { KB_NONE, "", "", "", "", ""}, /* 91 0 */ 1561 { KB_NONE, "", "", "", "", ""}, /* 92 0 */ 1562 { KB_NONE, "", "", "", "", ""}, /* 93 0 */ 1563 { KB_NONE, "", "", "", "", ""}, /* 94 0 */ 1564 { KB_NONE, "", "", "", "", ""}, /* 95 0 */ 1565 { KB_NONE, "", "", "", "", ""}, /* 96 0 */ 1566 { KB_NONE, "", "", "", "", ""}, /* 97 0 */ 1567 { KB_NONE, "", "", "", "", ""}, /* 98 0 */ 1568 { KB_NONE, "", "", "", "", ""}, /* 99 0 */ 1569 { KB_NONE, "", "", "", "", ""}, /* 100 */ 1570 { KB_NONE, "", "", "", "", ""}, /* 101 */ 1571 { KB_NONE, "", "", "", "", ""}, /* 102 */ 1572 { KB_NONE, "", "", "", "", ""}, /* 103 */ 1573 { KB_NONE, "", "", "", "", ""}, /* 104 */ 1574 { KB_NONE, "", "", "", "", ""}, /* 105 */ 1575 { KB_NONE, "", "", "", "", ""}, /* 106 */ 1576 { KB_NONE, "", "", "", "", ""}, /* 107 */ 1577 { KB_NONE, "", "", "", "", ""}, /* 108 */ 1578 { KB_NONE, "", "", "", "", ""}, /* 109 */ 1579 { KB_NONE, "", "", "", "", ""}, /* 110 */ 1580 { KB_NONE, "", "", "", "", ""}, /* 111 */ 1581 { KB_NONE, "", "", "", "", ""}, /* 112 */ 1582 { KB_NONE, "", "", "", "", ""}, /* 113 */ 1583 { KB_NONE, "", "", "", "", ""}, /* 114 */ 1584 { KB_NONE, "", "", "", "", ""}, /* 115 */ 1585 { KB_NONE, "", "", "", "", ""}, /* 116 */ 1586 { KB_NONE, "", "", "", "", ""}, /* 117 */ 1587 { KB_NONE, "", "", "", "", ""}, /* 118 */ 1588 { KB_NONE, "", "", "", "", ""}, /* 119 */ 1589 { KB_NONE, "", "", "", "", ""}, /* 120 */ 1590 { KB_NONE, "", "", "", "", ""}, /* 121 */ 1591 { KB_NONE, "", "", "", "", ""}, /* 122 */ 1592 { KB_NONE, "", "", "", "", ""}, /* 123 */ 1593 { KB_NONE, "", "", "", "", ""}, /* 124 */ 1594 { KB_NONE, "", "", "", "", ""}, /* 125 */ 1595 { KB_NONE, "", "", "", "", ""}, /* 126 */ 1596 { KB_NONE, "", "", "", "", ""} /* 127 */ 1597 }; 1598 1599 /* 1600 * Get characters from the keyboard. If none are present, return NULL. 1601 */ 1602 char * 1603 sget() 1604 { 1605 u_char dt; 1606 static u_char extended = 0, shift_state = 0; 1607 static u_char capchar[2]; 1608 1609 top: 1610 KBD_DELAY; 1611 dt = kbd_data_read_1(); 1612 1613 switch (dt) { 1614 case KBR_ACK: case KBR_ECHO: 1615 kb_oq_get = (kb_oq_get + 1) & 7; 1616 if(kb_oq_get != kb_oq_put) { 1617 kbd_data_write_1(kb_oq[kb_oq_get]); 1618 } 1619 goto loop; 1620 case KBR_RESEND: 1621 kbd_data_write_1(kb_oq[kb_oq_get]); 1622 goto loop; 1623 } 1624 1625 if (pc_xmode > 0) { 1626 #if defined(DDB) && defined(XSERVER_DDB) 1627 /* F12 enters the debugger while in X mode */ 1628 if (dt == 88) 1629 Debugger(); 1630 #endif 1631 capchar[0] = dt; 1632 capchar[1] = 0; 1633 /* 1634 * Check for locking keys. 1635 * 1636 * XXX Setting the LEDs this way is a bit bogus. What if the 1637 * keyboard has been remapped in X? 1638 */ 1639 switch (scan_codes[dt & 0x7f].type) { 1640 case KB_NUM: 1641 if (dt & 0x80) { 1642 shift_state &= ~KB_NUM; 1643 break; 1644 } 1645 if (shift_state & KB_NUM) 1646 break; 1647 shift_state |= KB_NUM; 1648 lock_state ^= KB_NUM; 1649 async_update(); 1650 break; 1651 case KB_CAPS: 1652 if (dt & 0x80) { 1653 shift_state &= ~KB_CAPS; 1654 break; 1655 } 1656 if (shift_state & KB_CAPS) 1657 break; 1658 shift_state |= KB_CAPS; 1659 lock_state ^= KB_CAPS; 1660 async_update(); 1661 break; 1662 case KB_SCROLL: 1663 if (dt & 0x80) { 1664 shift_state &= ~KB_SCROLL; 1665 break; 1666 } 1667 if (shift_state & KB_SCROLL) 1668 break; 1669 shift_state |= KB_SCROLL; 1670 lock_state ^= KB_SCROLL; 1671 if ((lock_state & KB_SCROLL) == 0) 1672 wakeup((caddr_t)&lock_state); 1673 async_update(); 1674 break; 1675 } 1676 return capchar; 1677 } 1678 1679 switch (dt) { 1680 case KBR_EXTENDED: 1681 extended = 1; 1682 goto loop; 1683 } 1684 1685 #ifdef DDB 1686 /* 1687 * Check for cntl-alt-esc. 1688 */ 1689 if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) { 1690 /* XXX - check pccons_is_console */ 1691 Debugger(); 1692 dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */ 1693 } 1694 #endif 1695 1696 /* 1697 * Check for make/break. 1698 */ 1699 if (dt & 0x80) { 1700 /* 1701 * break 1702 */ 1703 dt &= 0x7f; 1704 switch (scan_codes[dt].type) { 1705 case KB_NUM: 1706 shift_state &= ~KB_NUM; 1707 break; 1708 case KB_CAPS: 1709 shift_state &= ~KB_CAPS; 1710 break; 1711 case KB_SCROLL: 1712 shift_state &= ~KB_SCROLL; 1713 break; 1714 case KB_SHIFT: 1715 shift_state &= ~KB_SHIFT; 1716 break; 1717 case KB_ALT: 1718 if (extended) 1719 shift_state &= ~KB_ALTGR; 1720 else 1721 shift_state &= ~KB_ALT; 1722 break; 1723 case KB_CTL: 1724 shift_state &= ~KB_CTL; 1725 break; 1726 } 1727 } else { 1728 /* 1729 * make 1730 */ 1731 switch (scan_codes[dt].type) { 1732 /* 1733 * locking keys 1734 */ 1735 case KB_NUM: 1736 if (shift_state & KB_NUM) 1737 break; 1738 shift_state |= KB_NUM; 1739 lock_state ^= KB_NUM; 1740 async_update(); 1741 break; 1742 case KB_CAPS: 1743 if (shift_state & KB_CAPS) 1744 break; 1745 shift_state |= KB_CAPS; 1746 lock_state ^= KB_CAPS; 1747 async_update(); 1748 break; 1749 case KB_SCROLL: 1750 if (shift_state & KB_SCROLL) 1751 break; 1752 shift_state |= KB_SCROLL; 1753 lock_state ^= KB_SCROLL; 1754 if ((lock_state & KB_SCROLL) == 0) 1755 wakeup((caddr_t)&lock_state); 1756 async_update(); 1757 break; 1758 /* 1759 * non-locking keys 1760 */ 1761 case KB_SHIFT: 1762 shift_state |= KB_SHIFT; 1763 break; 1764 case KB_ALT: 1765 if (extended) 1766 shift_state |= KB_ALTGR; 1767 else 1768 shift_state |= KB_ALT; 1769 break; 1770 case KB_CTL: 1771 shift_state |= KB_CTL; 1772 break; 1773 case KB_ASCII: 1774 /* control has highest priority */ 1775 if (shift_state & KB_CTL) 1776 capchar[0] = scan_codes[dt].ctl[0]; 1777 else if (shift_state & KB_ALTGR) { 1778 if (shift_state & KB_SHIFT) 1779 capchar[0] = scan_codes[dt].shift_altgr[0]; 1780 else 1781 capchar[0] = scan_codes[dt].altgr[0]; 1782 } 1783 else { 1784 if (shift_state & KB_SHIFT) 1785 capchar[0] = scan_codes[dt].shift[0]; 1786 else 1787 capchar[0] = scan_codes[dt].unshift[0]; 1788 } 1789 if ((lock_state & KB_CAPS) && capchar[0] >= 'a' && 1790 capchar[0] <= 'z') { 1791 capchar[0] -= ('a' - 'A'); 1792 } 1793 capchar[0] |= (shift_state & KB_ALT); 1794 extended = 0; 1795 return capchar; 1796 case KB_NONE: 1797 printf("keycode %d\n",dt); 1798 break; 1799 case KB_FUNC: { 1800 char *more_chars; 1801 if (shift_state & KB_SHIFT) 1802 more_chars = scan_codes[dt].shift; 1803 else if (shift_state & KB_CTL) 1804 more_chars = scan_codes[dt].ctl; 1805 else 1806 more_chars = scan_codes[dt].unshift; 1807 extended = 0; 1808 return more_chars; 1809 } 1810 case KB_KP: { 1811 char *more_chars; 1812 if (shift_state & (KB_SHIFT | KB_CTL) || 1813 (lock_state & KB_NUM) == 0 || extended) 1814 more_chars = scan_codes[dt].shift; 1815 else 1816 more_chars = scan_codes[dt].unshift; 1817 extended = 0; 1818 return more_chars; 1819 } 1820 } 1821 } 1822 1823 extended = 0; 1824 loop: 1825 if ((kbd_cmd_read_1() & KBS_DIB) == 0) 1826 return 0; 1827 goto top; 1828 } 1829 1830 paddr_t 1831 pcmmap(dev, offset, nprot) 1832 dev_t dev; 1833 off_t offset; 1834 int nprot; 1835 { 1836 struct pccons_context *pc = &pccons_console_context; 1837 paddr_t pa; 1838 1839 if (offset >= 0xa0000 && offset < 0xc0000) { 1840 if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa)) 1841 return (-1); 1842 pa += offset - pc->pc_config->pc_mono_memaddr; 1843 return (mips_btop(pa)); 1844 } 1845 if (offset >= 0x0000 && offset < 0x10000) { 1846 if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa)) 1847 return (-1); 1848 pa += offset - pc->pc_config->pc_mono_iobase; 1849 return (mips_btop(pa)); 1850 } 1851 if (offset >= 0x40000000 && offset < 0x40800000) { 1852 if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa)) 1853 return (-1); 1854 pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr; 1855 return (mips_btop(pa)); 1856 } 1857 return (-1); 1858 } 1859 1860 void 1861 pc_xmode_on() 1862 { 1863 if (pc_xmode) 1864 return; 1865 pc_xmode = 1; 1866 1867 #ifdef XFREE86_BUG_COMPAT 1868 /* If still unchanged, get current shape. */ 1869 if (cursor_shape == 0xffff) 1870 get_cursor_shape(); 1871 #endif 1872 } 1873 1874 void 1875 pc_xmode_off() 1876 { 1877 if (pc_xmode == 0) 1878 return; 1879 pc_xmode = 0; 1880 1881 #ifdef XFREE86_BUG_COMPAT 1882 /* XXX It would be hard to justify why the X server doesn't do this. */ 1883 set_cursor_shape(); 1884 #endif 1885 async_update(); 1886 } 1887