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