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