1 /* $NetBSD: pccons.c,v 1.23 2000/12/24 09:25:27 ur 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 /* NetBSD: pms.c,v 1.21 1995/04/18 02:25:18 mycroft Exp */ 5 6 /*- 7 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved. 8 * Copyright (c) 1990 The Regents of the University of California. 9 * All rights reserved. 10 * 11 * This code is derived from software contributed to Berkeley by 12 * William Jolitz and Don Ahn. 13 * 14 * Copyright (c) 1994 Charles M. Hannum. 15 * Copyright (c) 1992, 1993 Erik Forsberg. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. All advertising materials mentioning features or use of this software 26 * must display the following acknowledgement: 27 * This product includes software developed by the University of 28 * California, Berkeley and its contributors. 29 * 4. Neither the name of the University nor the names of its contributors 30 * may be used to endorse or promote products derived from this software 31 * without specific prior written permission. 32 * 33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 43 * SUCH DAMAGE. 44 * 45 * @(#)pccons.c 5.11 (Berkeley) 5/21/91 46 */ 47 48 /* 49 * code to work keyboard & display for PC-style console 50 */ 51 52 #include "opt_ddb.h" 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/ioctl.h> 57 #include <sys/proc.h> 58 #include <sys/user.h> 59 #include <sys/select.h> 60 #include <sys/tty.h> 61 #include <sys/uio.h> 62 #include <sys/callout.h> 63 #include <sys/syslog.h> 64 #include <sys/device.h> 65 #include <sys/poll.h> 66 #include <sys/conf.h> 67 #include <sys/vnode.h> 68 #include <sys/fcntl.h> 69 #include <sys/kernel.h> 70 #include <sys/kcore.h> 71 72 #include <dev/cons.h> 73 74 #include <machine/cpu.h> 75 #include <machine/pio.h> 76 #include <machine/autoconf.h> 77 #include <machine/bus.h> 78 #include <machine/display.h> 79 #include <machine/pccons.h> 80 #include <arc/arc/arctype.h> 81 #include <arc/arc/arcbios.h> 82 #include <arc/jazz/pica.h> 83 #include <arc/dti/desktech.h> 84 #include <arc/jazz/jazziovar.h> 85 86 #include <dev/isa/isavar.h> 87 #include <machine/isa_machdep.h> 88 #include <machine/kbdreg.h> 89 90 #include <dev/cons.h> 91 92 #include "pc.h" 93 94 #define XFREE86_BUG_COMPAT 95 96 #ifndef BEEP_FREQ 97 #define BEEP_FREQ 1600 98 #endif 99 #ifndef BEEP_TIME 100 #define BEEP_TIME (hz/5) 101 #endif 102 103 #define PCBURST 128 104 105 static u_short *Crtat; /* pointer to backing store */ 106 static u_short *crtat; /* pointer to current char */ 107 static u_char async, kernel, polling; /* Really, you don't want to know. */ 108 static u_char lock_state = 0x00, /* all off */ 109 old_lock_state = 0xff, 110 typematic_rate = 0xff, /* don't update until set by user */ 111 old_typematic_rate = 0xff; 112 static u_short cursor_shape = 0xffff, /* don't update until set by user */ 113 old_cursor_shape = 0xffff; 114 static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */ 115 int pc_xmode = 0; 116 117 cdev_decl(pc); 118 119 /* 120 * Keyboard output queue. 121 */ 122 int kb_oq_put = 0; 123 int kb_oq_get = 0; 124 u_char kb_oq[8]; 125 126 #define PCUNIT(x) (minor(x)) 127 128 static struct video_state { 129 int cx, cy; /* escape parameters */ 130 int row, col; /* current cursor position */ 131 int nrow, ncol, nchr; /* current screen geometry */ 132 int offset; /* Saved cursor pos */ 133 u_char state; /* parser state */ 134 #define VSS_ESCAPE 1 135 #define VSS_EBRACE 2 136 #define VSS_EPARAM 3 137 char so; /* in standout mode? */ 138 char color; /* color or mono display */ 139 char at; /* normal attributes */ 140 char so_at; /* standout attributes */ 141 } vs; 142 143 struct pc_softc { 144 struct device sc_dev; 145 struct tty *sc_tty; 146 }; 147 148 struct opms_softc { /* driver status information */ 149 struct device sc_dev; 150 151 struct clist sc_q; 152 struct selinfo sc_rsel; 153 u_char sc_state; /* mouse driver state */ 154 #define PMS_OPEN 0x01 /* device is open */ 155 #define PMS_ASLP 0x02 /* waiting for mouse data */ 156 u_char sc_status; /* mouse button status */ 157 int sc_x, sc_y; /* accumulated motion in the X,Y axis */ 158 }; 159 160 static struct callout async_update_ch = CALLOUT_INITIALIZER; 161 162 int pcprobe __P((struct device *, struct cfdata *, void *)); 163 void pcattach __P((struct device *, struct device *, void *)); 164 int pcintr __P((void *)); 165 void pc_xmode_on __P((void)); 166 void pc_xmode_off __P((void)); 167 static u_char kbc_get8042cmd __P((void)); 168 static int kbc_put8042cmd __P((u_char)); 169 int kbc_8042sysreset __P((void)); 170 int kbd_cmd __P((u_char, u_char)); 171 static __inline int kbd_wait_output __P((void)); 172 static __inline int kbd_wait_input __P((void)); 173 static __inline void kbd_flush_input __P((void)); 174 void set_cursor_shape __P((void)); 175 void get_cursor_shape __P((void)); 176 void async_update __P((void)); 177 void do_async_update __P((u_char));; 178 179 void pccnattach __P((void)); 180 void pccnputc __P((dev_t, int c)); 181 int pccngetc __P((dev_t)); 182 void pccnpollc __P((dev_t, int)); 183 184 extern struct cfdriver pc_cd; 185 186 struct cfattach pc_jazzio_ca = { 187 sizeof(struct pc_softc), pcprobe, pcattach 188 }; 189 190 struct cfattach pc_isa_ca = { 191 sizeof(struct pc_softc), pcprobe, pcattach 192 }; 193 194 int opmsprobe __P((struct device *, struct cfdata *, void *)); 195 void opmsattach __P((struct device *, struct device *, void *)); 196 int opmsintr __P((void *)); 197 198 #if NOPMS > 0 199 struct cfattach opms_ca = { 200 sizeof(struct opms_softc), opmsprobe, opmsattach 201 }; 202 #endif 203 204 extern struct cfdriver opms_cd; 205 206 #define PMSUNIT(dev) (minor(dev)) 207 208 #define CHR 2 209 210 static unsigned int addr_6845; 211 static unsigned int mono_base = 0x3b4; 212 static unsigned int mono_buf = 0xb0000; 213 static unsigned int cga_base = 0x3d4; 214 static unsigned int cga_buf = 0xb8000; 215 static unsigned int kbd_cmdp = 0x64; 216 static unsigned int kbd_datap = 0x60; 217 218 char *sget __P((void)); 219 void sput __P((u_char *, int)); 220 221 void pcstart __P((struct tty *)); 222 int pcparam __P((struct tty *, struct termios *)); 223 static __inline void wcopy __P((void *, void *, u_int)); 224 void pcinithandle __P((void)); 225 226 extern void fillw __P((int, u_int16_t *, int)); 227 228 #define KBD_DELAY \ 229 DELAY(10); 230 231 void 232 pcinithandle() 233 { 234 static int initialized = 0; 235 236 if (initialized) 237 return; 238 initialized = 1; 239 240 switch (cputype) { 241 242 case ACER_PICA_61: 243 case NEC_R96: /* XXX - not really confirmed */ 244 mono_base += PICA_V_LOCAL_VIDEO_CTRL; 245 mono_buf += PICA_V_LOCAL_VIDEO; 246 cga_base += PICA_V_LOCAL_VIDEO_CTRL; 247 cga_buf += PICA_V_LOCAL_VIDEO; 248 case MAGNUM: 249 case NEC_R94: 250 case NEC_RAx94: 251 case NEC_RD94: 252 kbd_cmdp = PICA_SYS_KBD + 0x61; 253 kbd_datap = PICA_SYS_KBD + 0x60; 254 break; 255 256 case DESKSTATION_TYNE: 257 bus_space_map(&arc_bus_io, mono_base, 2, 0, &mono_base); 258 bus_space_map(&arc_bus_mem, mono_buf, 0x20000, 0, &mono_buf); 259 bus_space_map(&arc_bus_io, cga_base, 2, 0, &cga_base); 260 bus_space_map(&arc_bus_mem, cga_buf, 0x20000, 0, &cga_buf); 261 bus_space_map(&arc_bus_io, 0x64, 1, 0, &kbd_cmdp); 262 bus_space_map(&arc_bus_io, 0x60, 1, 0, &kbd_datap); 263 break; 264 265 case DESKSTATION_RPC44: 266 bus_space_map(&arc_bus_io, mono_base, 2, 0, &mono_base); 267 bus_space_map(&arc_bus_mem, mono_buf, 0x20000, 0, &mono_buf); 268 bus_space_map(&arc_bus_io, cga_base, 2, 0, &cga_base); 269 bus_space_map(&arc_bus_mem, 0xa0000, 0x20000, 0, &cga_buf); 270 bus_space_map(&arc_bus_io, 0x64, 1, 0, &kbd_cmdp); 271 bus_space_map(&arc_bus_io, 0x60, 1, 0, &kbd_datap); 272 break; 273 274 case SNI_RM200: 275 bus_space_map(&arc_bus_io, mono_base, 2, 0, &mono_base); 276 bus_space_map(&arc_bus_mem, mono_buf, 0x20000, 0, &mono_buf); 277 bus_space_map(&arc_bus_io, cga_base, 2, 0, &cga_base); 278 bus_space_map(&arc_bus_mem, cga_buf, 0x20000, 0, &cga_buf); 279 bus_space_map(&arc_bus_io, 0x64, 1, 0, &kbd_cmdp); 280 bus_space_map(&arc_bus_io, 0x60, 1, 0, &kbd_datap); 281 break; 282 } 283 } 284 285 /* 286 * bcopy variant that only moves word-aligned 16-bit entities, 287 * for stupid VGA cards. cnt is required to be an even vale. 288 */ 289 static __inline void 290 wcopy(src, tgt, cnt) 291 void *src, *tgt; 292 u_int cnt; 293 { 294 u_int16_t *from = src; 295 u_int16_t *to = tgt; 296 297 cnt >>= 1; 298 if (to < from || to >= from + cnt) 299 while(cnt--) 300 *to++ = *from++; 301 else { 302 to += cnt; 303 from += cnt; 304 while(cnt--) 305 *--to = *--from; 306 } 307 } 308 309 static __inline int 310 kbd_wait_output() 311 { 312 u_int i; 313 314 for (i = 100000; i; i--) 315 if ((inb(kbd_cmdp) & KBS_IBF) == 0) { 316 KBD_DELAY; 317 return 1; 318 } 319 return 0; 320 } 321 322 static __inline int 323 kbd_wait_input() 324 { 325 u_int i; 326 327 for (i = 100000; i; i--) 328 if ((inb(kbd_cmdp) & KBS_DIB) != 0) { 329 KBD_DELAY; 330 return 1; 331 } 332 return 0; 333 } 334 335 static __inline void 336 kbd_flush_input() 337 { 338 u_char c; 339 340 while ((c = inb(kbd_cmdp)) & 0x03) 341 if ((c & KBS_DIB) == KBS_DIB) { 342 /* XXX - delay is needed to prevent some keyboards from 343 wedging when the system boots */ 344 delay(6); 345 (void) inb(kbd_datap); 346 } 347 } 348 349 350 351 /* 352 * Pass system reset command to keyboard controller (8042). 353 */ 354 int 355 kbc_8042sysreset() 356 { 357 358 pcinithandle(); 359 360 if (!kbd_wait_output()) 361 return 0; 362 outb(kbd_cmdp, 0xd1); 363 if (!kbd_wait_output()) 364 return 0; 365 outb(kbd_datap, 0); /* ZAP */ 366 return 1; 367 } 368 369 #if 1 370 /* 371 * Get the current command byte. 372 */ 373 static u_char 374 kbc_get8042cmd() 375 { 376 377 if (!kbd_wait_output()) 378 return -1; 379 outb(kbd_cmdp, K_RDCMDBYTE); 380 if (!kbd_wait_input()) 381 return -1; 382 return inb(kbd_datap); 383 } 384 #endif 385 386 /* 387 * Pass command byte to keyboard controller (8042). 388 */ 389 static int 390 kbc_put8042cmd(val) 391 u_char val; 392 { 393 394 if (!kbd_wait_output()) 395 return 0; 396 outb(kbd_cmdp, K_LDCMDBYTE); 397 if (!kbd_wait_output()) 398 return 0; 399 outb(kbd_datap, val); 400 return 1; 401 } 402 403 /* 404 * Pass command to keyboard itself 405 */ 406 int 407 kbd_cmd(val, polling) 408 u_char val; 409 u_char polling; 410 { 411 u_int retries = 3; 412 register u_int i; 413 414 if(!polling) { 415 i = spltty(); 416 if(kb_oq_get == kb_oq_put) { 417 outb(kbd_datap, val); 418 } 419 kb_oq[kb_oq_put] = val; 420 kb_oq_put = (kb_oq_put + 1) & 7; 421 splx(i); 422 return(1); 423 } 424 else do { 425 if (!kbd_wait_output()) 426 return 0; 427 outb(kbd_datap, val); 428 for (i = 100000; i; i--) { 429 if (inb(kbd_cmdp) & KBS_DIB) { 430 register u_char c; 431 432 KBD_DELAY; 433 c = inb(kbd_datap); 434 if (c == KBR_ACK || c == KBR_ECHO) { 435 return 1; 436 } 437 if (c == KBR_RESEND) { 438 break; 439 } 440 #ifdef DIAGNOSTIC 441 printf("kbd_cmd: input char %x lost\n", c); 442 #endif 443 } 444 } 445 } while (--retries); 446 return 0; 447 } 448 449 void 450 set_cursor_shape() 451 { 452 register int iobase = addr_6845; 453 454 outb(iobase, 10); 455 outb(iobase+1, cursor_shape >> 8); 456 outb(iobase, 11); 457 outb(iobase+1, cursor_shape); 458 old_cursor_shape = cursor_shape; 459 } 460 461 void 462 get_cursor_shape() 463 { 464 register int iobase = addr_6845; 465 466 outb(iobase, 10); 467 cursor_shape = inb(iobase+1) << 8; 468 outb(iobase, 11); 469 cursor_shape |= inb(iobase+1); 470 471 /* 472 * real 6845's, as found on, MDA, Hercules or CGA cards, do 473 * not support reading the cursor shape registers. the 6845 474 * tri-states it's data bus. This is _normally_ read by the 475 * cpu as either 0x00 or 0xff.. in which case we just use 476 * a line cursor. 477 */ 478 if (cursor_shape == 0x0000 || cursor_shape == 0xffff) 479 cursor_shape = 0x0b10; 480 else 481 cursor_shape &= 0x1f1f; 482 } 483 484 void 485 do_async_update(poll) 486 u_char poll; 487 { 488 int pos; 489 static int old_pos = -1; 490 491 async = 0; 492 493 if (lock_state != old_lock_state) { 494 old_lock_state = lock_state; 495 if (!kbd_cmd(KBC_MODEIND, poll) || 496 !kbd_cmd(lock_state, poll)) { 497 printf("pc: timeout updating leds\n"); 498 (void) kbd_cmd(KBC_ENABLE, poll); 499 } 500 } 501 if (typematic_rate != old_typematic_rate) { 502 old_typematic_rate = typematic_rate; 503 if (!kbd_cmd(KBC_TYPEMATIC, poll) || 504 !kbd_cmd(typematic_rate, poll)) { 505 printf("pc: timeout updating typematic rate\n"); 506 (void) kbd_cmd(KBC_ENABLE, poll); 507 } 508 } 509 510 if (pc_xmode > 0) 511 return; 512 513 pos = crtat - Crtat; 514 if (pos != old_pos) { 515 register int iobase = addr_6845; 516 outb(iobase, 14); 517 outb(iobase+1, pos >> 8); 518 outb(iobase, 15); 519 outb(iobase+1, pos); 520 old_pos = pos; 521 } 522 if (cursor_shape != old_cursor_shape) 523 set_cursor_shape(); 524 } 525 526 void 527 async_update() 528 { 529 530 if (kernel || polling) { 531 if (async) 532 callout_stop(&async_update_ch); 533 do_async_update(1); 534 } else { 535 if (async) 536 return; 537 async = 1; 538 callout_reset(&async_update_ch, 1, 539 (void(*)(void *))do_async_update, NULL); 540 } 541 } 542 543 /* 544 * these are both bad jokes 545 */ 546 int 547 pcprobe(parent, match, aux) 548 struct device *parent; 549 struct cfdata *match; 550 void *aux; 551 { 552 struct jazzio_attach_args *ja = aux; 553 u_int i; 554 555 /* Make shure we're looking for this type of device */ 556 if(!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pica")) { 557 if (strcmp(ja->ja_name, "pckbd") != 0) 558 return(0); 559 560 switch (cputype) { /* XXX ick */ 561 case ACER_PICA_61: 562 case NEC_R96: /* XXX - not really confirmed */ 563 break; 564 default: 565 return (0); 566 } 567 } else { /* ISA */ 568 switch (cputype) { /* XXX ick */ 569 case DESKSTATION_RPC44: 570 case DESKSTATION_TYNE: 571 break; 572 default: 573 return (0); 574 } 575 } 576 577 pcinithandle(); 578 579 /* Enable interrupts and keyboard, etc. */ 580 if (!kbc_put8042cmd(CMDBYTE)) { 581 printf("pcprobe: command error\n"); 582 return 0; 583 } 584 585 #if 1 586 /* Flush any garbage. */ 587 kbd_flush_input(); 588 /* Reset the keyboard. */ 589 if (!kbd_cmd(KBC_RESET, 1)) { 590 printf("pcprobe: reset error %d\n", 1); 591 goto lose; 592 } 593 for (i = 600000; i; i--) 594 if ((inb(kbd_cmdp) & KBS_DIB) != 0) { 595 KBD_DELAY; 596 break; 597 } 598 if (i == 0 || inb(kbd_datap) != KBR_RSTDONE) { 599 printf("pcprobe: reset error %d\n", 2); 600 goto lose; 601 } 602 /* 603 * Some keyboards seem to leave a second ack byte after the reset. 604 * This is kind of stupid, but we account for them anyway by just 605 * flushing the buffer. 606 */ 607 kbd_flush_input(); 608 /* Just to be sure. */ 609 if (!kbd_cmd(KBC_ENABLE, 1)) { 610 printf("pcprobe: reset error %d\n", 3); 611 goto lose; 612 } 613 614 /* 615 * Some keyboard/8042 combinations do not seem to work if the keyboard 616 * is set to table 1; in fact, it would appear that some keyboards just 617 * ignore the command altogether. So by default, we use the AT scan 618 * codes and have the 8042 translate them. Unfortunately, this is 619 * known to not work on some PS/2 machines. We try desparately to deal 620 * with this by checking the (lack of a) translate bit in the 8042 and 621 * attempting to set the keyboard to XT mode. If this all fails, well, 622 * tough luck. 623 * 624 * XXX It would perhaps be a better choice to just use AT scan codes 625 * and not bother with this. 626 */ 627 if (kbc_get8042cmd() & KC8_TRANS) { 628 /* The 8042 is translating for us; use AT codes. */ 629 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) { 630 printf("pcprobe: reset error %d\n", 4); 631 goto lose; 632 } 633 } else { 634 /* Stupid 8042; set keyboard to XT codes. */ 635 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) { 636 printf("pcprobe: reset error %d\n", 5); 637 goto lose; 638 } 639 } 640 641 lose: 642 /* 643 * Technically, we should probably fail the probe. But we'll be nice 644 * and allow keyboard-less machines to boot with the console. 645 */ 646 #endif 647 648 return 1; 649 } 650 651 void 652 pcattach(parent, self, aux) 653 struct device *parent, *self; 654 void *aux; 655 { 656 struct jazzio_attach_args *ja = aux; 657 struct isa_attach_args *ia = aux; 658 struct pc_softc *sc = (void *)self; 659 660 printf(": %s\n", vs.color ? "color" : "mono"); 661 do_async_update(1); 662 663 switch (cputype) { 664 case ACER_PICA_61: 665 case NEC_R96: 666 jazzio_intr_establish(ja->ja_intr, pcintr, (void *)(long)sc); 667 break; 668 case DESKSTATION_RPC44: /* XXX ick */ 669 case DESKSTATION_TYNE: 670 isa_intr_establish(ia->ia_ic, ia->ia_irq, 1, 671 2, pcintr, sc); /*XXX ick */ 672 break; 673 } 674 } 675 676 int 677 pcopen(dev, flag, mode, p) 678 dev_t dev; 679 int flag, mode; 680 struct proc *p; 681 { 682 struct pc_softc *sc; 683 int unit = PCUNIT(dev); 684 struct tty *tp; 685 686 if (unit >= pc_cd.cd_ndevs) 687 return ENXIO; 688 sc = pc_cd.cd_devs[unit]; 689 if (sc == 0) 690 return ENXIO; 691 692 if (!sc->sc_tty) { 693 tp = sc->sc_tty = ttymalloc(); 694 } 695 else { 696 tp = sc->sc_tty; 697 } 698 699 tp->t_oproc = pcstart; 700 tp->t_param = pcparam; 701 tp->t_dev = dev; 702 if ((tp->t_state & TS_ISOPEN) == 0) { 703 ttychars(tp); 704 tp->t_iflag = TTYDEF_IFLAG; 705 tp->t_oflag = TTYDEF_OFLAG; 706 tp->t_cflag = TTYDEF_CFLAG; 707 tp->t_lflag = TTYDEF_LFLAG; 708 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 709 pcparam(tp, &tp->t_termios); 710 ttsetwater(tp); 711 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 712 return EBUSY; 713 tp->t_state |= TS_CARR_ON; 714 715 return ((*tp->t_linesw->l_open)(dev, tp)); 716 } 717 718 int 719 pcclose(dev, flag, mode, p) 720 dev_t dev; 721 int flag, mode; 722 struct proc *p; 723 { 724 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 725 struct tty *tp = sc->sc_tty; 726 727 (*tp->t_linesw->l_close)(tp, flag); 728 ttyclose(tp); 729 #ifdef notyet /* XXX */ 730 ttyfree(tp); 731 #endif 732 return(0); 733 } 734 735 int 736 pcread(dev, uio, flag) 737 dev_t dev; 738 struct uio *uio; 739 int flag; 740 { 741 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 742 struct tty *tp = sc->sc_tty; 743 744 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 745 } 746 747 int 748 pcwrite(dev, uio, flag) 749 dev_t dev; 750 struct uio *uio; 751 int flag; 752 { 753 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 754 struct tty *tp = sc->sc_tty; 755 756 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 757 } 758 759 struct tty * 760 pctty(dev) 761 dev_t dev; 762 { 763 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 764 struct tty *tp = sc->sc_tty; 765 766 return (tp); 767 } 768 769 /* 770 * Got a console receive interrupt - 771 * the console processor wants to give us a character. 772 * Catch the character, and see who it goes to. 773 */ 774 int 775 pcintr(arg) 776 void *arg; 777 { 778 struct pc_softc *sc = arg; 779 register struct tty *tp = sc->sc_tty; 780 u_char *cp; 781 782 if ((inb(kbd_cmdp) & KBS_DIB) == 0) 783 return 0; 784 if (polling) 785 return 1; 786 do { 787 cp = sget(); 788 if (!tp || (tp->t_state & TS_ISOPEN) == 0) 789 return 1; 790 if (cp) 791 do 792 (*tp->t_linesw->l_rint)(*cp++, tp); 793 while (*cp); 794 } while (inb(kbd_cmdp) & KBS_DIB); 795 return 1; 796 } 797 798 int 799 pcioctl(dev, cmd, data, flag, p) 800 dev_t dev; 801 u_long cmd; 802 caddr_t data; 803 int flag; 804 struct proc *p; 805 { 806 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)]; 807 struct tty *tp = sc->sc_tty; 808 int error; 809 810 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 811 if (error >= 0) 812 return error; 813 error = ttioctl(tp, cmd, data, flag, p); 814 if (error >= 0) 815 return error; 816 817 switch (cmd) { 818 case CONSOLE_X_MODE_ON: 819 pc_xmode_on(); 820 return 0; 821 case CONSOLE_X_MODE_OFF: 822 pc_xmode_off(); 823 return 0; 824 case CONSOLE_X_BELL: 825 /* 826 * If set, data is a pointer to a length 2 array of 827 * integers. data[0] is the pitch in Hz and data[1] 828 * is the duration in msec. 829 */ 830 if (data) 831 sysbeep(((int*)data)[0], 832 (((int*)data)[1] * hz) / 1000); 833 else 834 sysbeep(BEEP_FREQ, BEEP_TIME); 835 return 0; 836 case CONSOLE_SET_TYPEMATIC_RATE: { 837 u_char rate; 838 839 if (!data) 840 return EINVAL; 841 rate = *((u_char *)data); 842 /* 843 * Check that it isn't too big (which would cause it to be 844 * confused with a command). 845 */ 846 if (rate & 0x80) 847 return EINVAL; 848 typematic_rate = rate; 849 async_update(); 850 return 0; 851 } 852 case CONSOLE_SET_KEYMAP: { 853 pccons_keymap_t *map = (pccons_keymap_t *) data; 854 int i; 855 856 if (!data) 857 return EINVAL; 858 for (i = 0; i < KB_NUM_KEYS; i++) 859 if (map[i].unshift[KB_CODE_SIZE-1] || 860 map[i].shift[KB_CODE_SIZE-1] || 861 map[i].ctl[KB_CODE_SIZE-1] || 862 map[i].altgr[KB_CODE_SIZE-1] || 863 map[i].shift_altgr[KB_CODE_SIZE-1]) 864 return EINVAL; 865 866 bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS])); 867 return 0; 868 } 869 case CONSOLE_GET_KEYMAP: 870 if (!data) 871 return EINVAL; 872 bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS])); 873 return 0; 874 875 default: 876 return ENOTTY; 877 } 878 879 #ifdef DIAGNOSTIC 880 panic("pcioctl: impossible"); 881 #endif 882 } 883 884 void 885 pcstart(tp) 886 struct tty *tp; 887 { 888 struct clist *cl; 889 int s, len; 890 u_char buf[PCBURST]; 891 892 s = spltty(); 893 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 894 goto out; 895 tp->t_state |= TS_BUSY; 896 splx(s); 897 /* 898 * We need to do this outside spl since it could be fairly 899 * expensive and we don't want our serial ports to overflow. 900 */ 901 cl = &tp->t_outq; 902 len = q_to_b(cl, buf, PCBURST); 903 sput(buf, len); 904 s = spltty(); 905 tp->t_state &= ~TS_BUSY; 906 if (cl->c_cc) { 907 tp->t_state |= TS_TIMEOUT; 908 callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp); 909 } 910 if (cl->c_cc <= tp->t_lowat) { 911 if (tp->t_state & TS_ASLEEP) { 912 tp->t_state &= ~TS_ASLEEP; 913 wakeup(cl); 914 } 915 selwakeup(&tp->t_wsel); 916 } 917 out: 918 splx(s); 919 } 920 921 void 922 pcstop(tp, flag) 923 struct tty *tp; 924 int flag; 925 { 926 } 927 928 /* ARGSUSED */ 929 void 930 pccnattach() 931 { 932 int maj; 933 static struct consdev pccons = { 934 NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, 935 NODEV, CN_NORMAL 936 }; 937 938 /* 939 * For now, don't screw with it. 940 */ 941 /* crtat = 0; */ 942 pcinithandle(); 943 944 switch (cputype) { 945 946 case ACER_PICA_61: 947 case NEC_R96: /* XXX - not really confirmed */ 948 break; 949 950 case DESKSTATION_TYNE: 951 outb(arc_bus_io.bs_vbase + 0x3ce, 6); /* Correct video mode */ 952 outb(arc_bus_io.bs_vbase + 0x3cf, 953 inb(arc_bus_io.bs_vbase + 0x3cf) | 0xc); 954 kbc_put8042cmd(CMDBYTE); /* Want XT codes.. */ 955 break; 956 957 case DESKSTATION_RPC44: 958 kbc_put8042cmd(CMDBYTE); /* Want XT codes.. */ 959 break; 960 961 case SNI_RM200: 962 break; 963 } 964 965 /* locate the major number */ 966 for (maj = 0; maj < nchrdev; maj++) 967 if (cdevsw[maj].d_open == pcopen) 968 break; 969 pccons.cn_dev = makedev(maj, 0); 970 971 cn_tab = &pccons; 972 } 973 974 /* ARGSUSED */ 975 void 976 pccnputc(dev, c) 977 dev_t dev; 978 int c; 979 { 980 u_char cc, oldkernel = kernel; 981 982 kernel = 1; 983 if (c == '\n') { 984 sput("\r\n", 2); 985 } else { 986 cc = c; 987 sput(&cc, 1); 988 } 989 kernel = oldkernel; 990 } 991 992 /* ARGSUSED */ 993 int 994 pccngetc(dev) 995 dev_t dev; 996 { 997 register char *cp; 998 999 if (pc_xmode > 0) 1000 return 0; 1001 1002 do { 1003 /* wait for byte */ 1004 while ((inb(kbd_cmdp) & KBS_DIB) == 0); 1005 /* see if it's worthwhile */ 1006 cp = sget(); 1007 } while (!cp); 1008 if (*cp == '\r') 1009 return '\n'; 1010 return *cp; 1011 } 1012 1013 void 1014 pccnpollc(dev, on) 1015 dev_t dev; 1016 int on; 1017 { 1018 1019 polling = on; 1020 if (!on) { 1021 int unit; 1022 struct pc_softc *sc; 1023 int s; 1024 1025 /* 1026 * If disabling polling on a device that's been configured, 1027 * make sure there are no bytes left in the FIFO, holding up 1028 * the interrupt line. Otherwise we won't get any further 1029 * interrupts. 1030 */ 1031 unit = PCUNIT(dev); 1032 if (pc_cd.cd_ndevs > unit) { 1033 sc = pc_cd.cd_devs[unit]; 1034 if (sc != 0) { 1035 s = spltty(); 1036 pcintr(sc); 1037 splx(s); 1038 } 1039 } 1040 } 1041 } 1042 1043 /* 1044 * Set line parameters. 1045 */ 1046 int 1047 pcparam(tp, t) 1048 struct tty *tp; 1049 struct termios *t; 1050 { 1051 1052 tp->t_ispeed = t->c_ispeed; 1053 tp->t_ospeed = t->c_ospeed; 1054 tp->t_cflag = t->c_cflag; 1055 return 0; 1056 } 1057 1058 #define wrtchar(c, at) do {\ 1059 char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \ 1060 } while (0) 1061 1062 /* translate ANSI color codes to standard pc ones */ 1063 static char fgansitopc[] = { 1064 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, 1065 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY 1066 }; 1067 1068 static char bgansitopc[] = { 1069 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, 1070 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY 1071 }; 1072 1073 static u_char iso2ibm437[] = 1074 { 1075 0, 0, 0, 0, 0, 0, 0, 0, 1076 0, 0, 0, 0, 0, 0, 0, 0, 1077 0, 0, 0, 0, 0, 0, 0, 0, 1078 0, 0, 0, 0, 0, 0, 0, 0, 1079 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40, 1080 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0, 1081 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa, 1082 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8, 1083 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80, 1084 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 1085 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f, 1086 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1, 1087 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87, 1088 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, 1089 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f, 1090 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0 1091 }; 1092 1093 /* 1094 * `pc3' termcap emulation. 1095 */ 1096 void 1097 sput(cp, n) 1098 u_char *cp; 1099 int n; 1100 { 1101 u_char c, scroll = 0; 1102 1103 if (pc_xmode > 0) 1104 return; 1105 1106 if (crtat == 0) { 1107 volatile u_short *cp; 1108 u_short was; 1109 unsigned cursorat; 1110 1111 cp = (volatile u_short *)cga_buf; 1112 was = *cp; 1113 *cp = (volatile u_short) 0xA55A; 1114 if (*cp != 0xA55A) { 1115 cp = (volatile u_short *)mono_buf; 1116 addr_6845 = mono_base; 1117 vs.color = 0; 1118 } else { 1119 *cp = was; 1120 addr_6845 = cga_base; 1121 vs.color = 1; 1122 } 1123 1124 #ifdef FAT_CURSOR 1125 cursor_shape = 0x0012; 1126 #else 1127 get_cursor_shape(); 1128 #endif 1129 1130 bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow); 1131 vs.nchr = vs.ncol * vs.nrow; 1132 vs.col--; 1133 vs.row--; 1134 cursorat = vs.ncol * vs.row + vs.col; 1135 vs.at = FG_LIGHTGREY | BG_BLACK; 1136 1137 Crtat = (u_short *)cp; 1138 crtat = Crtat + cursorat; 1139 1140 if (vs.color == 0) 1141 vs.so_at = FG_BLACK | BG_LIGHTGREY; 1142 else 1143 vs.so_at = FG_YELLOW | BG_BLACK; 1144 1145 fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat); 1146 } 1147 1148 while (n--) { 1149 if (!(c = *cp++)) 1150 continue; 1151 1152 switch (c) { 1153 case 0x1B: 1154 if (vs.state >= VSS_ESCAPE) { 1155 wrtchar(c, vs.so_at); 1156 vs.state = 0; 1157 goto maybe_scroll; 1158 } else 1159 vs.state = VSS_ESCAPE; 1160 break; 1161 1162 case 0x9B: /* CSI */ 1163 vs.cx = vs.cy = 0; 1164 vs.state = VSS_EBRACE; 1165 break; 1166 1167 case '\t': { 1168 int inccol = 8 - (vs.col & 7); 1169 crtat += inccol; 1170 vs.col += inccol; 1171 } 1172 maybe_scroll: 1173 if (vs.col >= vs.ncol) { 1174 vs.col -= vs.ncol; 1175 scroll = 1; 1176 } 1177 break; 1178 1179 case '\b': 1180 if (crtat <= Crtat) 1181 break; 1182 --crtat; 1183 if (--vs.col < 0) 1184 vs.col += vs.ncol; /* non-destructive backspace */ 1185 break; 1186 1187 case '\r': 1188 crtat -= vs.col; 1189 vs.col = 0; 1190 break; 1191 1192 case '\n': 1193 crtat += vs.ncol; 1194 scroll = 1; 1195 break; 1196 1197 default: 1198 switch (vs.state) { 1199 case 0: 1200 if (c == '\a') 1201 sysbeep(BEEP_FREQ, BEEP_TIME); 1202 else { 1203 /* 1204 * If we're outputting multiple printed 1205 * characters, just blast them to the 1206 * screen until we reach the end of the 1207 * buffer or a control character. This 1208 * saves time by short-circuiting the 1209 * switch. 1210 * If we reach the end of the line, we 1211 * break to do a scroll check. 1212 */ 1213 for (;;) { 1214 if (c & 0x80) 1215 c = iso2ibm437[c&0x7f]; 1216 1217 if (vs.so) 1218 wrtchar(c, vs.so_at); 1219 else 1220 wrtchar(c, vs.at); 1221 if (vs.col >= vs.ncol) { 1222 vs.col = 0; 1223 scroll = 1; 1224 break; 1225 } 1226 if (!n || (c = *cp) < ' ') 1227 break; 1228 n--, cp++; 1229 } 1230 } 1231 break; 1232 case VSS_ESCAPE: 1233 switch (c) { 1234 case '[': /* Start ESC [ sequence */ 1235 vs.cx = vs.cy = 0; 1236 vs.state = VSS_EBRACE; 1237 break; 1238 case 'c': /* Create screen & home */ 1239 fillw((vs.at << 8) | ' ', 1240 Crtat, vs.nchr); 1241 crtat = Crtat; 1242 vs.col = 0; 1243 vs.state = 0; 1244 break; 1245 case '7': /* save cursor pos */ 1246 vs.offset = crtat - Crtat; 1247 vs.state = 0; 1248 break; 1249 case '8': /* restore cursor pos */ 1250 crtat = Crtat + vs.offset; 1251 vs.row = vs.offset / vs.ncol; 1252 vs.col = vs.offset % vs.ncol; 1253 vs.state = 0; 1254 break; 1255 default: /* Invalid, clear state */ 1256 wrtchar(c, vs.so_at); 1257 vs.state = 0; 1258 goto maybe_scroll; 1259 } 1260 break; 1261 1262 default: /* VSS_EBRACE or VSS_EPARAM */ 1263 switch (c) { 1264 int pos; 1265 case 'm': 1266 if (!vs.cx) 1267 vs.so = 0; 1268 else 1269 vs.so = 1; 1270 vs.state = 0; 1271 break; 1272 case 'A': { /* back cx rows */ 1273 int cx = vs.cx; 1274 if (cx <= 0) 1275 cx = 1; 1276 else 1277 cx %= vs.nrow; 1278 pos = crtat - Crtat; 1279 pos -= vs.ncol * cx; 1280 if (pos < 0) 1281 pos += vs.nchr; 1282 crtat = Crtat + pos; 1283 vs.state = 0; 1284 break; 1285 } 1286 case 'B': { /* down cx rows */ 1287 int cx = vs.cx; 1288 if (cx <= 0) 1289 cx = 1; 1290 else 1291 cx %= vs.nrow; 1292 pos = crtat - Crtat; 1293 pos += vs.ncol * cx; 1294 if (pos >= vs.nchr) 1295 pos -= vs.nchr; 1296 crtat = Crtat + pos; 1297 vs.state = 0; 1298 break; 1299 } 1300 case 'C': { /* right cursor */ 1301 int cx = vs.cx, 1302 col = vs.col; 1303 if (cx <= 0) 1304 cx = 1; 1305 else 1306 cx %= vs.ncol; 1307 pos = crtat - Crtat; 1308 pos += cx; 1309 col += cx; 1310 if (col >= vs.ncol) { 1311 pos -= vs.ncol; 1312 col -= vs.ncol; 1313 } 1314 vs.col = col; 1315 crtat = Crtat + pos; 1316 vs.state = 0; 1317 break; 1318 } 1319 case 'D': { /* left cursor */ 1320 int cx = vs.cx, 1321 col = vs.col; 1322 if (cx <= 0) 1323 cx = 1; 1324 else 1325 cx %= vs.ncol; 1326 pos = crtat - Crtat; 1327 pos -= cx; 1328 col -= cx; 1329 if (col < 0) { 1330 pos += vs.ncol; 1331 col += vs.ncol; 1332 } 1333 vs.col = col; 1334 crtat = Crtat + pos; 1335 vs.state = 0; 1336 break; 1337 } 1338 case 'J': /* Clear ... */ 1339 switch (vs.cx) { 1340 case 0: 1341 /* ... to end of display */ 1342 fillw((vs.at << 8) | ' ', 1343 crtat, 1344 Crtat + vs.nchr - crtat); 1345 break; 1346 case 1: 1347 /* ... to next location */ 1348 fillw((vs.at << 8) | ' ', 1349 Crtat, 1350 crtat - Crtat + 1); 1351 break; 1352 case 2: 1353 /* ... whole display */ 1354 fillw((vs.at << 8) | ' ', 1355 Crtat, 1356 vs.nchr); 1357 break; 1358 } 1359 vs.state = 0; 1360 break; 1361 case 'K': /* Clear line ... */ 1362 switch (vs.cx) { 1363 case 0: 1364 /* ... current to EOL */ 1365 fillw((vs.at << 8) | ' ', 1366 crtat, 1367 vs.ncol - vs.col); 1368 break; 1369 case 1: 1370 /* ... beginning to next */ 1371 fillw((vs.at << 8) | ' ', 1372 crtat - vs.col, 1373 vs.col + 1); 1374 break; 1375 case 2: 1376 /* ... entire line */ 1377 fillw((vs.at << 8) | ' ', 1378 crtat - vs.col, vs.ncol); 1379 break; 1380 } 1381 vs.state = 0; 1382 break; 1383 case 'f': /* in system V consoles */ 1384 case 'H': { /* Cursor move */ 1385 int cx = vs.cx, 1386 cy = vs.cy; 1387 if (!cx || !cy) { 1388 crtat = Crtat; 1389 vs.col = 0; 1390 } else { 1391 if (cx > vs.nrow) 1392 cx = vs.nrow; 1393 if (cy > vs.ncol) 1394 cy = vs.ncol; 1395 crtat = Crtat + 1396 (cx - 1) * vs.ncol + cy - 1; 1397 vs.col = cy - 1; 1398 } 1399 vs.state = 0; 1400 break; 1401 } 1402 case 'M': { /* delete cx rows */ 1403 u_short *crtAt = crtat - vs.col; 1404 int cx = vs.cx, 1405 row = (crtAt - Crtat) / vs.ncol, 1406 nrow = vs.nrow - row; 1407 if (cx <= 0) 1408 cx = 1; 1409 else if (cx > nrow) 1410 cx = nrow; 1411 if (cx < nrow) 1412 #ifdef PCCONS_FORCE_WORD 1413 wcopy(crtAt + vs.ncol * cx, 1414 crtAt, vs.ncol * (nrow - 1415 cx) * CHR); 1416 #else 1417 bcopy(crtAt + vs.ncol * cx, 1418 crtAt, vs.ncol * (nrow - 1419 cx) * CHR); 1420 #endif 1421 fillw((vs.at << 8) | ' ', 1422 crtAt + vs.ncol * (nrow - cx), 1423 vs.ncol * cx); 1424 vs.state = 0; 1425 break; 1426 } 1427 case 'S': { /* scroll up cx lines */ 1428 int cx = vs.cx; 1429 if (cx <= 0) 1430 cx = 1; 1431 else if (cx > vs.nrow) 1432 cx = vs.nrow; 1433 if (cx < vs.nrow) 1434 #ifdef PCCONS_FORCE_WORD 1435 wcopy(Crtat + vs.ncol * cx, 1436 Crtat, vs.ncol * (vs.nrow - 1437 cx) * CHR); 1438 #else 1439 bcopy(Crtat + vs.ncol * cx, 1440 Crtat, vs.ncol * (vs.nrow - 1441 cx) * CHR); 1442 #endif 1443 fillw((vs.at << 8) | ' ', 1444 Crtat + vs.ncol * (vs.nrow - cx), 1445 vs.ncol * cx); 1446 /* crtat -= vs.ncol * cx; XXX */ 1447 vs.state = 0; 1448 break; 1449 } 1450 case 'L': { /* insert cx rows */ 1451 u_short *crtAt = crtat - vs.col; 1452 int cx = vs.cx, 1453 row = (crtAt - Crtat) / vs.ncol, 1454 nrow = vs.nrow - row; 1455 if (cx <= 0) 1456 cx = 1; 1457 else if (cx > nrow) 1458 cx = nrow; 1459 if (cx < nrow) 1460 #ifdef PCCONS_FORCE_WORD 1461 wcopy(crtAt, 1462 crtAt + vs.ncol * cx, 1463 vs.ncol * (nrow - cx) * 1464 CHR); 1465 #else 1466 bcopy(crtAt, 1467 crtAt + vs.ncol * cx, 1468 vs.ncol * (nrow - cx) * 1469 CHR); 1470 #endif 1471 fillw((vs.at << 8) | ' ', crtAt, 1472 vs.ncol * cx); 1473 vs.state = 0; 1474 break; 1475 } 1476 case 'T': { /* scroll down cx lines */ 1477 int cx = vs.cx; 1478 if (cx <= 0) 1479 cx = 1; 1480 else if (cx > vs.nrow) 1481 cx = vs.nrow; 1482 if (cx < vs.nrow) 1483 #ifdef PCCONS_FORCE_WORD 1484 wcopy(Crtat, 1485 Crtat + vs.ncol * cx, 1486 vs.ncol * (vs.nrow - cx) * 1487 CHR); 1488 #else 1489 bcopy(Crtat, 1490 Crtat + vs.ncol * cx, 1491 vs.ncol * (vs.nrow - cx) * 1492 CHR); 1493 #endif 1494 fillw((vs.at << 8) | ' ', Crtat, 1495 vs.ncol * cx); 1496 /* crtat += vs.ncol * cx; XXX */ 1497 vs.state = 0; 1498 break; 1499 } 1500 case ';': /* Switch params in cursor def */ 1501 vs.state = VSS_EPARAM; 1502 break; 1503 case 'r': 1504 vs.so_at = (vs.cx & FG_MASK) | 1505 ((vs.cy << 4) & BG_MASK); 1506 vs.state = 0; 1507 break; 1508 case 's': /* save cursor pos */ 1509 vs.offset = crtat - Crtat; 1510 vs.state = 0; 1511 break; 1512 case 'u': /* restore cursor pos */ 1513 crtat = Crtat + vs.offset; 1514 vs.row = vs.offset / vs.ncol; 1515 vs.col = vs.offset % vs.ncol; 1516 vs.state = 0; 1517 break; 1518 case 'x': /* set attributes */ 1519 switch (vs.cx) { 1520 case 0: 1521 vs.at = FG_LIGHTGREY | BG_BLACK; 1522 break; 1523 case 1: 1524 /* ansi background */ 1525 if (!vs.color) 1526 break; 1527 vs.at &= FG_MASK; 1528 vs.at |= bgansitopc[vs.cy & 7]; 1529 break; 1530 case 2: 1531 /* ansi foreground */ 1532 if (!vs.color) 1533 break; 1534 vs.at &= BG_MASK; 1535 vs.at |= fgansitopc[vs.cy & 7]; 1536 break; 1537 case 3: 1538 /* pc text attribute */ 1539 if (vs.state >= VSS_EPARAM) 1540 vs.at = vs.cy; 1541 break; 1542 } 1543 vs.state = 0; 1544 break; 1545 1546 default: /* Only numbers valid here */ 1547 if ((c >= '0') && (c <= '9')) { 1548 if (vs.state >= VSS_EPARAM) { 1549 vs.cy *= 10; 1550 vs.cy += c - '0'; 1551 } else { 1552 vs.cx *= 10; 1553 vs.cx += c - '0'; 1554 } 1555 } else 1556 vs.state = 0; 1557 break; 1558 } 1559 break; 1560 } 1561 } 1562 if (scroll) { 1563 scroll = 0; 1564 /* scroll check */ 1565 if (crtat >= Crtat + vs.nchr) { 1566 if (!kernel) { 1567 int s = spltty(); 1568 if (lock_state & KB_SCROLL) 1569 tsleep(&lock_state, 1570 PUSER, "pcputc", 0); 1571 splx(s); 1572 } 1573 #if PCCONS_FORCE_WORD 1574 wcopy(Crtat + vs.ncol, Crtat, 1575 (vs.nchr - vs.ncol) * CHR); 1576 #else 1577 bcopy(Crtat + vs.ncol, Crtat, 1578 (vs.nchr - vs.ncol) * CHR); 1579 #endif 1580 fillw((vs.at << 8) | ' ', 1581 Crtat + vs.nchr - vs.ncol, 1582 vs.ncol); 1583 crtat -= vs.ncol; 1584 } 1585 } 1586 } 1587 async_update(); 1588 } 1589 1590 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between 1591 left and right shift when reading the keyboard map */ 1592 static pccons_keymap_t scan_codes[KB_NUM_KEYS] = { 1593 /* type unshift shift control altgr shift_altgr scancode */ 1594 { KB_NONE, "", "", "", "", ""}, /* 0 unused */ 1595 { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */ 1596 { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */ 1597 { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */ 1598 { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */ 1599 { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */ 1600 { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */ 1601 { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */ 1602 { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */ 1603 { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */ 1604 { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */ 1605 { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */ 1606 { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */ 1607 { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */ 1608 { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */ 1609 { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */ 1610 { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */ 1611 { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */ 1612 { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */ 1613 { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */ 1614 { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */ 1615 { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */ 1616 { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */ 1617 { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */ 1618 { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */ 1619 { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */ 1620 { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */ 1621 { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */ 1622 { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */ 1623 { KB_CTL, "", "", "", "", ""}, /* 29 control */ 1624 { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */ 1625 { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */ 1626 { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */ 1627 { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */ 1628 { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */ 1629 { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */ 1630 { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */ 1631 { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */ 1632 { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */ 1633 { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */ 1634 { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */ 1635 { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */ 1636 { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */ 1637 { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */ 1638 { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */ 1639 { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */ 1640 { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */ 1641 { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */ 1642 { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */ 1643 { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */ 1644 { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */ 1645 { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */ 1646 { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */ 1647 { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */ 1648 { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */ 1649 { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */ 1650 { KB_ALT, "", "", "", "", ""}, /* 56 alt */ 1651 { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */ 1652 { KB_CAPS, "", "", "", "", ""}, /* 58 caps */ 1653 { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */ 1654 { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */ 1655 { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */ 1656 { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */ 1657 { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */ 1658 { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */ 1659 { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */ 1660 { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */ 1661 { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */ 1662 { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */ 1663 { KB_NUM, "", "", "", "", ""}, /* 69 num lock */ 1664 { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */ 1665 { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */ 1666 { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */ 1667 { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */ 1668 { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */ 1669 { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */ 1670 { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */ 1671 { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */ 1672 { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */ 1673 { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */ 1674 { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */ 1675 { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */ 1676 { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */ 1677 { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */ 1678 { KB_NONE, "", "", "", "", ""}, /* 84 0 */ 1679 { KB_NONE, "", "", "", "", ""}, /* 85 0 */ 1680 { KB_NONE, "", "", "", "", ""}, /* 86 0 */ 1681 { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */ 1682 { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */ 1683 { KB_NONE, "", "", "", "", ""}, /* 89 0 */ 1684 { KB_NONE, "", "", "", "", ""}, /* 90 0 */ 1685 { KB_NONE, "", "", "", "", ""}, /* 91 0 */ 1686 { KB_NONE, "", "", "", "", ""}, /* 92 0 */ 1687 { KB_NONE, "", "", "", "", ""}, /* 93 0 */ 1688 { KB_NONE, "", "", "", "", ""}, /* 94 0 */ 1689 { KB_NONE, "", "", "", "", ""}, /* 95 0 */ 1690 { KB_NONE, "", "", "", "", ""}, /* 96 0 */ 1691 { KB_NONE, "", "", "", "", ""}, /* 97 0 */ 1692 { KB_NONE, "", "", "", "", ""}, /* 98 0 */ 1693 { KB_NONE, "", "", "", "", ""}, /* 99 0 */ 1694 { KB_NONE, "", "", "", "", ""}, /* 100 */ 1695 { KB_NONE, "", "", "", "", ""}, /* 101 */ 1696 { KB_NONE, "", "", "", "", ""}, /* 102 */ 1697 { KB_NONE, "", "", "", "", ""}, /* 103 */ 1698 { KB_NONE, "", "", "", "", ""}, /* 104 */ 1699 { KB_NONE, "", "", "", "", ""}, /* 105 */ 1700 { KB_NONE, "", "", "", "", ""}, /* 106 */ 1701 { KB_NONE, "", "", "", "", ""}, /* 107 */ 1702 { KB_NONE, "", "", "", "", ""}, /* 108 */ 1703 { KB_NONE, "", "", "", "", ""}, /* 109 */ 1704 { KB_NONE, "", "", "", "", ""}, /* 110 */ 1705 { KB_NONE, "", "", "", "", ""}, /* 111 */ 1706 { KB_NONE, "", "", "", "", ""}, /* 112 */ 1707 { KB_NONE, "", "", "", "", ""}, /* 113 */ 1708 { KB_NONE, "", "", "", "", ""}, /* 114 */ 1709 { KB_NONE, "", "", "", "", ""}, /* 115 */ 1710 { KB_NONE, "", "", "", "", ""}, /* 116 */ 1711 { KB_NONE, "", "", "", "", ""}, /* 117 */ 1712 { KB_NONE, "", "", "", "", ""}, /* 118 */ 1713 { KB_NONE, "", "", "", "", ""}, /* 119 */ 1714 { KB_NONE, "", "", "", "", ""}, /* 120 */ 1715 { KB_NONE, "", "", "", "", ""}, /* 121 */ 1716 { KB_NONE, "", "", "", "", ""}, /* 122 */ 1717 { KB_NONE, "", "", "", "", ""}, /* 123 */ 1718 { KB_NONE, "", "", "", "", ""}, /* 124 */ 1719 { KB_NONE, "", "", "", "", ""}, /* 125 */ 1720 { KB_NONE, "", "", "", "", ""}, /* 126 */ 1721 { KB_NONE, "", "", "", "", ""} /* 127 */ 1722 }; 1723 1724 /* 1725 * Get characters from the keyboard. If none are present, return NULL. 1726 */ 1727 char * 1728 sget() 1729 { 1730 u_char dt; 1731 static u_char extended = 0, shift_state = 0; 1732 static u_char capchar[2]; 1733 1734 top: 1735 KBD_DELAY; 1736 dt = inb(kbd_datap); 1737 1738 switch (dt) { 1739 case KBR_ACK: case KBR_ECHO: 1740 kb_oq_get = (kb_oq_get + 1) & 7; 1741 if(kb_oq_get != kb_oq_put) { 1742 outb(kbd_datap, kb_oq[kb_oq_get]); 1743 } 1744 goto loop; 1745 case KBR_RESEND: 1746 outb(kbd_datap, kb_oq[kb_oq_get]); 1747 goto loop; 1748 } 1749 1750 if (pc_xmode > 0) { 1751 #if defined(DDB) && defined(XSERVER_DDB) 1752 /* F12 enters the debugger while in X mode */ 1753 if (dt == 88) 1754 Debugger(); 1755 #endif 1756 capchar[0] = dt; 1757 capchar[1] = 0; 1758 /* 1759 * Check for locking keys. 1760 * 1761 * XXX Setting the LEDs this way is a bit bogus. What if the 1762 * keyboard has been remapped in X? 1763 */ 1764 switch (scan_codes[dt & 0x7f].type) { 1765 case KB_NUM: 1766 if (dt & 0x80) { 1767 shift_state &= ~KB_NUM; 1768 break; 1769 } 1770 if (shift_state & KB_NUM) 1771 break; 1772 shift_state |= KB_NUM; 1773 lock_state ^= KB_NUM; 1774 async_update(); 1775 break; 1776 case KB_CAPS: 1777 if (dt & 0x80) { 1778 shift_state &= ~KB_CAPS; 1779 break; 1780 } 1781 if (shift_state & KB_CAPS) 1782 break; 1783 shift_state |= KB_CAPS; 1784 lock_state ^= KB_CAPS; 1785 async_update(); 1786 break; 1787 case KB_SCROLL: 1788 if (dt & 0x80) { 1789 shift_state &= ~KB_SCROLL; 1790 break; 1791 } 1792 if (shift_state & KB_SCROLL) 1793 break; 1794 shift_state |= KB_SCROLL; 1795 lock_state ^= KB_SCROLL; 1796 if ((lock_state & KB_SCROLL) == 0) 1797 wakeup((caddr_t)&lock_state); 1798 async_update(); 1799 break; 1800 } 1801 return capchar; 1802 } 1803 1804 switch (dt) { 1805 case KBR_EXTENDED: 1806 extended = 1; 1807 goto loop; 1808 } 1809 1810 #ifdef DDB 1811 /* 1812 * Check for cntl-alt-esc. 1813 */ 1814 if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) { 1815 /* XXX - check pccons_is_console */ 1816 Debugger(); 1817 dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */ 1818 } 1819 #endif 1820 1821 /* 1822 * Check for make/break. 1823 */ 1824 if (dt & 0x80) { 1825 /* 1826 * break 1827 */ 1828 dt &= 0x7f; 1829 switch (scan_codes[dt].type) { 1830 case KB_NUM: 1831 shift_state &= ~KB_NUM; 1832 break; 1833 case KB_CAPS: 1834 shift_state &= ~KB_CAPS; 1835 break; 1836 case KB_SCROLL: 1837 shift_state &= ~KB_SCROLL; 1838 break; 1839 case KB_SHIFT: 1840 shift_state &= ~KB_SHIFT; 1841 break; 1842 case KB_ALT: 1843 if (extended) 1844 shift_state &= ~KB_ALTGR; 1845 else 1846 shift_state &= ~KB_ALT; 1847 break; 1848 case KB_CTL: 1849 shift_state &= ~KB_CTL; 1850 break; 1851 } 1852 } else { 1853 /* 1854 * make 1855 */ 1856 switch (scan_codes[dt].type) { 1857 /* 1858 * locking keys 1859 */ 1860 case KB_NUM: 1861 if (shift_state & KB_NUM) 1862 break; 1863 shift_state |= KB_NUM; 1864 lock_state ^= KB_NUM; 1865 async_update(); 1866 break; 1867 case KB_CAPS: 1868 if (shift_state & KB_CAPS) 1869 break; 1870 shift_state |= KB_CAPS; 1871 lock_state ^= KB_CAPS; 1872 async_update(); 1873 break; 1874 case KB_SCROLL: 1875 if (shift_state & KB_SCROLL) 1876 break; 1877 shift_state |= KB_SCROLL; 1878 lock_state ^= KB_SCROLL; 1879 if ((lock_state & KB_SCROLL) == 0) 1880 wakeup((caddr_t)&lock_state); 1881 async_update(); 1882 break; 1883 /* 1884 * non-locking keys 1885 */ 1886 case KB_SHIFT: 1887 shift_state |= KB_SHIFT; 1888 break; 1889 case KB_ALT: 1890 if (extended) 1891 shift_state |= KB_ALTGR; 1892 else 1893 shift_state |= KB_ALT; 1894 break; 1895 case KB_CTL: 1896 shift_state |= KB_CTL; 1897 break; 1898 case KB_ASCII: 1899 /* control has highest priority */ 1900 if (shift_state & KB_CTL) 1901 capchar[0] = scan_codes[dt].ctl[0]; 1902 else if (shift_state & KB_ALTGR) { 1903 if (shift_state & KB_SHIFT) 1904 capchar[0] = scan_codes[dt].shift_altgr[0]; 1905 else 1906 capchar[0] = scan_codes[dt].altgr[0]; 1907 } 1908 else { 1909 if (shift_state & KB_SHIFT) 1910 capchar[0] = scan_codes[dt].shift[0]; 1911 else 1912 capchar[0] = scan_codes[dt].unshift[0]; 1913 } 1914 if ((lock_state & KB_CAPS) && capchar[0] >= 'a' && 1915 capchar[0] <= 'z') { 1916 capchar[0] -= ('a' - 'A'); 1917 } 1918 capchar[0] |= (shift_state & KB_ALT); 1919 extended = 0; 1920 return capchar; 1921 case KB_NONE: 1922 printf("keycode %d\n",dt); 1923 break; 1924 case KB_FUNC: { 1925 char *more_chars; 1926 if (shift_state & KB_SHIFT) 1927 more_chars = scan_codes[dt].shift; 1928 else if (shift_state & KB_CTL) 1929 more_chars = scan_codes[dt].ctl; 1930 else 1931 more_chars = scan_codes[dt].unshift; 1932 extended = 0; 1933 return more_chars; 1934 } 1935 case KB_KP: { 1936 char *more_chars; 1937 if (shift_state & (KB_SHIFT | KB_CTL) || 1938 (lock_state & KB_NUM) == 0 || extended) 1939 more_chars = scan_codes[dt].shift; 1940 else 1941 more_chars = scan_codes[dt].unshift; 1942 extended = 0; 1943 return more_chars; 1944 } 1945 } 1946 } 1947 1948 extended = 0; 1949 loop: 1950 if ((inb(kbd_cmdp) & KBS_DIB) == 0) 1951 return 0; 1952 goto top; 1953 } 1954 1955 paddr_t 1956 pcmmap(dev, offset, nprot) 1957 dev_t dev; 1958 off_t offset; 1959 int nprot; 1960 { 1961 1962 switch(cputype) { 1963 1964 case ACER_PICA_61: 1965 case NEC_R96: 1966 if (offset >= 0xa0000 && offset < 0xc0000) 1967 return mips_btop(PICA_P_LOCAL_VIDEO + offset); 1968 if (offset >= 0x0000 && offset < 0x10000) 1969 return mips_btop(PICA_P_LOCAL_VIDEO_CTRL + offset); 1970 if (offset >= 0x40000000 && offset < 0x40800000) 1971 return mips_btop(PICA_P_LOCAL_VIDEO + offset - 0x40000000); 1972 return -1; 1973 1974 case DESKSTATION_RPC44: 1975 if (offset >= 0xa0000 && offset < 0xc0000) 1976 return mips_btop(RPC44_P_ISA_MEM + offset); 1977 if (offset >= 0x0000 && offset < 0x10000) 1978 return mips_btop(RPC44_P_ISA_IO + offset); 1979 if (offset >= 0x40000000 && offset < 0x40800000) 1980 return mips_btop(RPC44_P_ISA_MEM + offset - 0x40000000); 1981 return -1; 1982 1983 case DESKSTATION_TYNE: 1984 if (offset >= 0xa0000 && offset < 0xc0000) 1985 return mips_btop(TYNE_P_ISA_MEM + offset); 1986 if (offset >= 0x0000 && offset < 0x10000) 1987 return mips_btop(TYNE_P_ISA_IO + offset); 1988 if (offset >= 0x40000000 && offset < 0x40800000) 1989 return mips_btop(TYNE_P_ISA_MEM + offset - 0x40000000); 1990 return -1; 1991 } 1992 return -1; 1993 } 1994 1995 void 1996 pc_xmode_on() 1997 { 1998 if (pc_xmode) 1999 return; 2000 pc_xmode = 1; 2001 2002 #ifdef XFREE86_BUG_COMPAT 2003 /* If still unchanged, get current shape. */ 2004 if (cursor_shape == 0xffff) 2005 get_cursor_shape(); 2006 #endif 2007 } 2008 2009 void 2010 pc_xmode_off() 2011 { 2012 if (pc_xmode == 0) 2013 return; 2014 pc_xmode = 0; 2015 2016 #ifdef XFREE86_BUG_COMPAT 2017 /* XXX It would be hard to justify why the X server doesn't do this. */ 2018 set_cursor_shape(); 2019 #endif 2020 async_update(); 2021 } 2022 2023 #include <machine/mouse.h> 2024 2025 /* status bits */ 2026 #define PMS_OBUF_FULL 0x01 2027 #define PMS_IBUF_FULL 0x02 2028 2029 /* controller commands */ 2030 #define PMS_INT_ENABLE 0x47 /* enable controller interrupts */ 2031 #define PMS_INT_DISABLE 0x65 /* disable controller interrupts */ 2032 #define PMS_AUX_ENABLE 0xa7 /* enable auxiliary port */ 2033 #define PMS_AUX_DISABLE 0xa8 /* disable auxiliary port */ 2034 #define PMS_MAGIC_1 0xa9 /* XXX */ 2035 2036 #define PMS_8042_CMD 0x65 2037 2038 /* mouse commands */ 2039 #define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */ 2040 #define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */ 2041 #define PMS_SET_RES 0xe8 /* set resolution */ 2042 #define PMS_GET_SCALE 0xe9 /* get scaling factor */ 2043 #define PMS_SET_STREAM 0xea /* set streaming mode */ 2044 #define PMS_SET_SAMPLE 0xf3 /* set sampling rate */ 2045 #define PMS_DEV_ENABLE 0xf4 /* mouse on */ 2046 #define PMS_DEV_DISABLE 0xf5 /* mouse off */ 2047 #define PMS_RESET 0xff /* reset */ 2048 2049 #define PMS_CHUNK 128 /* chunk size for read */ 2050 #define PMS_BSIZE 1020 /* buffer size */ 2051 2052 #define FLUSHQ(q) { if((q)->c_cc) ndflush(q, (q)->c_cc); } 2053 2054 #if NOPMS > 0 2055 2056 int opmsopen __P((dev_t, int)); 2057 int opmsclose __P((dev_t, int)); 2058 int opmsread __P((dev_t, struct uio *, int)); 2059 int opmsioctl __P((dev_t, u_long, caddr_t, int)); 2060 int opmsselect __P((dev_t, int, struct proc *)); 2061 int opmspoll __P((dev_t, int, struct proc *)); 2062 static __inline void pms_dev_cmd __P((u_char)); 2063 static __inline void pms_aux_cmd __P((u_char)); 2064 static __inline void pms_pit_cmd __P((u_char)); 2065 2066 static __inline void 2067 pms_dev_cmd(value) 2068 u_char value; 2069 { 2070 kbd_flush_input(); 2071 outb(kbd_cmdp, 0xd4); 2072 kbd_flush_input(); 2073 outb(kbd_datap, value); 2074 } 2075 2076 static __inline void 2077 pms_aux_cmd(value) 2078 u_char value; 2079 { 2080 kbd_flush_input(); 2081 outb(kbd_cmdp, value); 2082 } 2083 2084 static __inline void 2085 pms_pit_cmd(value) 2086 u_char value; 2087 { 2088 kbd_flush_input(); 2089 outb(kbd_cmdp, 0x60); 2090 kbd_flush_input(); 2091 outb(kbd_datap, value); 2092 } 2093 2094 int 2095 opmsprobe(parent, match, aux) 2096 struct device *parent; 2097 struct cfdata *match; 2098 void *aux; 2099 { 2100 struct confargs *ca = aux; 2101 u_char x; 2102 2103 /* Make shure we're looking for this type of device */ 2104 if(!BUS_MATCHNAME(ca, "pms")) 2105 return(0); 2106 2107 pcinithandle(); 2108 pms_dev_cmd(KBC_RESET); 2109 pms_aux_cmd(PMS_MAGIC_1); 2110 delay(10000); 2111 x = inb(kbd_datap); 2112 pms_pit_cmd(PMS_INT_DISABLE); 2113 if (x & 0x04) 2114 return 0; 2115 2116 return 1; 2117 } 2118 2119 void 2120 opmsattach(parent, self, aux) 2121 struct device *parent, *self; 2122 void *aux; 2123 { 2124 struct opms_softc *sc = (void *)self; 2125 struct confargs *ca = aux; 2126 2127 printf("\n"); 2128 2129 /* Other initialization was done by opmsprobe. */ 2130 sc->sc_state = 0; 2131 2132 BUS_INTR_ESTABLISH(ca, opmsintr, (void *)(long)sc); 2133 } 2134 2135 int 2136 opmsopen(dev, flag) 2137 dev_t dev; 2138 int flag; 2139 { 2140 int unit = PMSUNIT(dev); 2141 struct opms_softc *sc; 2142 2143 if (unit >= opms_cd.cd_ndevs) 2144 return ENXIO; 2145 sc = opms_cd.cd_devs[unit]; 2146 if (!sc) 2147 return ENXIO; 2148 2149 if (sc->sc_state & PMS_OPEN) 2150 return EBUSY; 2151 2152 if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1) 2153 return ENOMEM; 2154 2155 sc->sc_state |= PMS_OPEN; 2156 sc->sc_status = 0; 2157 sc->sc_x = sc->sc_y = 0; 2158 2159 /* Enable interrupts. */ 2160 pms_dev_cmd(PMS_DEV_ENABLE); 2161 pms_aux_cmd(PMS_AUX_ENABLE); 2162 pms_dev_cmd(PMS_SET_RES); 2163 pms_dev_cmd(3); /* 8 counts/mm */ 2164 pms_dev_cmd(PMS_SET_SCALE21); 2165 #if 0 2166 pms_dev_cmd(PMS_SET_SAMPLE); 2167 pms_dev_cmd(100); /* 100 samples/sec */ 2168 pms_dev_cmd(PMS_SET_STREAM); 2169 #endif 2170 pms_pit_cmd(PMS_INT_ENABLE); 2171 2172 return 0; 2173 } 2174 2175 int 2176 opmsclose(dev, flag) 2177 dev_t dev; 2178 int flag; 2179 { 2180 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)]; 2181 2182 /* Disable interrupts. */ 2183 pms_dev_cmd(PMS_DEV_DISABLE); 2184 pms_pit_cmd(PMS_INT_DISABLE); 2185 pms_aux_cmd(PMS_AUX_DISABLE); 2186 2187 sc->sc_state &= ~PMS_OPEN; 2188 2189 clfree(&sc->sc_q); 2190 2191 return 0; 2192 } 2193 2194 int 2195 opmsread(dev, uio, flag) 2196 dev_t dev; 2197 struct uio *uio; 2198 int flag; 2199 { 2200 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)]; 2201 int s; 2202 int error = 0; 2203 size_t length; 2204 u_char buffer[PMS_CHUNK]; 2205 2206 /* Block until mouse activity occured. */ 2207 2208 s = spltty(); 2209 while (sc->sc_q.c_cc == 0) { 2210 if (flag & IO_NDELAY) { 2211 splx(s); 2212 return EWOULDBLOCK; 2213 } 2214 sc->sc_state |= PMS_ASLP; 2215 error = tsleep((caddr_t)sc, PZERO | PCATCH, "pmsrea", 0); 2216 if (error) { 2217 sc->sc_state &= ~PMS_ASLP; 2218 splx(s); 2219 return error; 2220 } 2221 } 2222 splx(s); 2223 2224 /* Transfer as many chunks as possible. */ 2225 2226 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) { 2227 length = min(sc->sc_q.c_cc, uio->uio_resid); 2228 if (length > sizeof(buffer)) 2229 length = sizeof(buffer); 2230 2231 /* Remove a small chunk from the input queue. */ 2232 (void) q_to_b(&sc->sc_q, buffer, length); 2233 2234 /* Copy the data to the user process. */ 2235 error = uiomove(buffer, length, uio); 2236 if (error) 2237 break; 2238 } 2239 2240 return error; 2241 } 2242 2243 int 2244 opmsioctl(dev, cmd, addr, flag) 2245 dev_t dev; 2246 u_long cmd; 2247 caddr_t addr; 2248 int flag; 2249 { 2250 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)]; 2251 struct mouseinfo info; 2252 int s; 2253 int error; 2254 2255 switch (cmd) { 2256 case MOUSEIOCREAD: 2257 s = spltty(); 2258 2259 info.status = sc->sc_status; 2260 if (sc->sc_x || sc->sc_y) 2261 info.status |= MOVEMENT; 2262 2263 if (sc->sc_x > 127) 2264 info.xmotion = 127; 2265 else if (sc->sc_x < -127) 2266 /* Bounding at -127 avoids a bug in XFree86. */ 2267 info.xmotion = -127; 2268 else 2269 info.xmotion = sc->sc_x; 2270 2271 if (sc->sc_y > 127) 2272 info.ymotion = 127; 2273 else if (sc->sc_y < -127) 2274 info.ymotion = -127; 2275 else 2276 info.ymotion = sc->sc_y; 2277 2278 /* Reset historical information. */ 2279 sc->sc_x = sc->sc_y = 0; 2280 sc->sc_status &= ~BUTCHNGMASK; 2281 ndflush(&sc->sc_q, sc->sc_q.c_cc); 2282 2283 splx(s); 2284 error = copyout(&info, addr, sizeof(struct mouseinfo)); 2285 break; 2286 default: 2287 error = EINVAL; 2288 break; 2289 } 2290 2291 return error; 2292 } 2293 2294 /* Masks for the first byte of a packet */ 2295 #define PS2LBUTMASK 0x01 2296 #define PS2RBUTMASK 0x02 2297 #define PS2MBUTMASK 0x04 2298 2299 int 2300 opmsintr(arg) 2301 void *arg; 2302 { 2303 struct opms_softc *sc = arg; 2304 static int state = 0; 2305 static u_char buttons; 2306 u_char changed; 2307 static char dx, dy; 2308 u_char buffer[5]; 2309 2310 if ((sc->sc_state & PMS_OPEN) == 0) { 2311 /* Interrupts are not expected. Discard the byte. */ 2312 kbd_flush_input(); 2313 return 0; 2314 } 2315 2316 switch (state) { 2317 2318 case 0: 2319 buttons = inb(kbd_datap); 2320 if ((buttons & 0xc0) == 0) 2321 ++state; 2322 break; 2323 2324 case 1: 2325 dx = inb(kbd_datap); 2326 /* Bounding at -127 avoids a bug in XFree86. */ 2327 dx = (dx == -128) ? -127 : dx; 2328 ++state; 2329 break; 2330 2331 case 2: 2332 dy = inb(kbd_datap); 2333 dy = (dy == -128) ? -127 : dy; 2334 state = 0; 2335 2336 buttons = ((buttons & PS2LBUTMASK) << 2) | 2337 ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1); 2338 changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3; 2339 sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed; 2340 2341 if (dx || dy || changed) { 2342 /* Update accumulated movements. */ 2343 sc->sc_x += dx; 2344 sc->sc_y += dy; 2345 2346 /* Add this event to the queue. */ 2347 buffer[0] = 0x80 | (buttons & BUTSTATMASK); 2348 if(dx < 0) 2349 buffer[0] |= 0x10; 2350 buffer[1] = dx & 0x7f; 2351 if(dy < 0) 2352 buffer[0] |= 0x20; 2353 buffer[2] = dy & 0x7f; 2354 buffer[3] = buffer[4] = 0; 2355 (void) b_to_q(buffer, sizeof buffer, &sc->sc_q); 2356 2357 if (sc->sc_state & PMS_ASLP) { 2358 sc->sc_state &= ~PMS_ASLP; 2359 wakeup((caddr_t)sc); 2360 } 2361 selwakeup(&sc->sc_rsel); 2362 } 2363 2364 break; 2365 } 2366 return -1; 2367 } 2368 2369 int 2370 opmspoll(dev, events, p) 2371 dev_t dev; 2372 int events; 2373 struct proc *p; 2374 { 2375 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)]; 2376 int revents = 0; 2377 int s = spltty(); 2378 2379 if (events & (POLLIN | POLLRDNORM)) { 2380 if (sc->sc_q.c_cc > 0) 2381 revents |= events & (POLLIN | POLLRDNORM); 2382 else 2383 selrecord(p, &sc->sc_rsel); 2384 } 2385 2386 splx(s); 2387 return (revents); 2388 } 2389 2390 #endif /* NOPMS > 0 */ 2391