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