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