|
|
1.1 ! root 1: /* ! 2: * io.386/vtnkb.c ! 3: * ! 4: * Keyboard driver, virtual consoles, loadable tables. ! 5: * ! 6: * Revised: Fri Jul 16 08:39:12 1993 CDT ! 7: */ ! 8: ! 9: #define SWANFIX 1 ! 10: #define GREEKFIX 1 ! 11: ! 12: /* ! 13: * User configurable AT keyboard/display driver. ! 14: */ ! 15: #include <sys/coherent.h> ! 16: #include <sys/con.h> ! 17: #include <sys/errno.h> ! 18: #include <sys/stat.h> ! 19: #include <sys/tty.h> ! 20: #include <signal.h> ! 21: #include <sys/seg.h> ! 22: #include <sys/sched.h> ! 23: #include <sys/kb.h> ! 24: #include <sys/devices.h> ! 25: #include <sys/silo.h> ! 26: #include <stddef.h> ! 27: ! 28: #include <sys/vt.h> ! 29: ! 30: #define ISVEC 1 /* Keyboard interrupt vector */ ! 31: #define DEBUG 0 ! 32: ! 33: #define KBDEBUG(x) T_CON(1,printf(x)); /* debugging output */ ! 34: #define KBDEBUG2(x,y) T_CON(1,printf(x,y)); /* debugging output */ ! 35: #define KBDEBUG3(x,y,z) T_CON(1,printf(x,y,z)); /* debugging output */ ! 36: ! 37: /* ! 38: * values for kbstate ! 39: */ ! 40: #define KB_IDLE 0 /* nothing going on right now */ ! 41: #define KB_SINGLE 1 /* sent a single byte cmd to the kbd */ ! 42: #define KB_DOUBLE_1 2 /* sent 1st byte of 2-byte cmd to kbd */ ! 43: #define KB_DOUBLE_2 3 /* sent 2nd byte of 2-byte cmd to kbd */ ! 44: ! 45: /* ! 46: * patchable params for non-standard keyboards ! 47: */ ! 48: int KBDATA = 0x60; /* Keyboard data */ ! 49: int KBCTRL = 0x61; /* Keyboard control */ ! 50: int KBSTS_CMD = 0x64; /* Keyboard status/command */ ! 51: int KBFLAG = 0x80; /* Keyboard reset flag */ ! 52: int KBBOOT = 1; /* 0: disallow reboot from keyboard */ ! 53: int KBTIMEOUT = 10000; /* shouldn't need this much */ ! 54: int KBCMDBYTE = 0x05; /* no translation */ ! 55: ! 56: /* ! 57: * KBSTATUS bits ! 58: */ ! 59: #define STS_OBUF_FULL 0x01 /* kbd output buffer full */ ! 60: #define STS_IBUF_FULL 0x02 /* kbd input buffer full */ ! 61: #define STS_SYSTEM 0x04 ! 62: #define STS_CMD_DATA 0x08 /* 1: command or status */ ! 63: #define STS_INHIBIT 0x10 /* 0: keyboard inhibited */ ! 64: #define STS_AUX_OBUF_FULL 0x20 ! 65: #define STS_TIMEOUT 0x40 /* general timeout */ ! 66: #define STS_PAR_ERR 0x80 /* parity error */ ! 67: ! 68: /* ! 69: * The following are magic commands which read from or write to the ! 70: * controller command byte. These get output to the KBSTS_CMD port. ! 71: */ ! 72: #define C_READ_CMD 0x20 /* read controller command byte */ ! 73: #define C_WRITE_CMD 0x60 /* write controller command byte */ ! 74: #define C_TRANSLATE 0x40 /* translate enable bit in cmd byte */ ! 75: ! 76: /* ! 77: * Globals: ! 78: * The 286 keyboard mapping table is too large to fit into kernel data space, ! 79: * so we need to allocate a segment to it. 386 is easy. ! 80: * The function keys tend to be small and tend to change substantially ! 81: * more often than the mapping table, so we keep them in the kernel data space. ! 82: */ ! 83: static unsigned shift; /* state of all shift/lock keys */ ! 84: static unsigned char **funkeyp = 0; /* ptr to array of func. keys ptrs */ ! 85: static FNKEY *fnkeys = 0; /* pointer to structure of values */ ! 86: static unsigned fklength; /* length of function key text */ ! 87: static unsigned prev_cmd; /* previous command sent to KBD */ ! 88: static unsigned cmd2; /* 2nd byte of command to KBD */ ! 89: static unsigned sh_index; /* shift/lock state index */ ! 90: #ifdef _I386 ! 91: static KBTBL kb[MAX_KEYS]; /* keyboard table */ ! 92: #else ! 93: static SEG *kbsegp; /* keyboard table segment */ ! 94: #endif ! 95: ! 96: /* ! 97: * State variables. ! 98: */ ! 99: int islock; /* Keyboard locked flag */ ! 100: int isbusy; /* Raw input conversion busy */ ! 101: static char table_loaded; /* true == keyboard table resident */ ! 102: static char fk_loaded; /* true == function keys resident */ ! 103: static int kbstate = KB_IDLE; /* current keyboard state */ ! 104: static int xlate = 1; /* scan code translation flag */ ! 105: ! 106: #define ESCAPE_CHAR '\x1B' ! 107: #define ESCAPE_STRING "\x1B" ! 108: ! 109: /* ! 110: * Functions. ! 111: */ ! 112: int isrint(); ! 113: int istime(); ! 114: void isbatch(); ! 115: int vtmmstart(); ! 116: int isopen(); ! 117: int isclose(); ! 118: int isread(); ! 119: int vtmmwrite(); ! 120: int isioctl(); ! 121: void vtmmwatch(); ! 122: int isload(); ! 123: int isuload(); ! 124: int ispoll(); ! 125: int nulldev(); ! 126: int nonedev(); ! 127: int updleds(); ! 128: ! 129: /* ! 130: * Configuration table. ! 131: */ ! 132: ! 133: CON vtnkbcon ={ ! 134: DFCHR|DFPOL, /* Flags */ ! 135: KB_MAJOR, /* Major index */ ! 136: isopen, /* Open */ ! 137: isclose, /* Close */ ! 138: nulldev, /* Block */ ! 139: isread, /* Read */ ! 140: vtmmwrite, /* Write */ ! 141: isioctl, /* Ioctl */ ! 142: nulldev, /* Powerfail */ ! 143: vtmmwatch, /* Timeout */ ! 144: isload, /* Load */ ! 145: isuload, /* Unload */ ! 146: ispoll /* Poll */ ! 147: }; ! 148: ! 149: /* ! 150: ============================================================================== ! 151: ============================================================================== ! 152: */ ! 153: /* constants for vtdata[] */ ! 154: #define VT_VGAPORT 0x3D4 ! 155: #define VT_MONOPORT 0x3B4 ! 156: ! 157: #ifdef _I386 ! 158: #define VT_MONOBASE (SEG_VIDEOa|DPL_1) ! 159: #define VT_VGABASE (SEG_VIDEOb|DPL_1) ! 160: #else ! 161: #define VT_MONOBASE 0xB000 ! 162: #define VT_VGABASE 0xB800 ! 163: #endif ! 164: ! 165: /* ! 166: Patchable table entries, ! 167: we go indirect in order to produce a label which can be addressed ! 168: */ ! 169: #if SWANFIX ! 170: int VTSWAN = 0; /* patch to 1 for epstein's fix for Swan keyboard */ ! 171: #endif ! 172: ! 173: #if GREEKFIX ! 174: static void ToggleGreek(); ! 175: static int ToGreek(); ! 176: int VTGREEK = 0; /* patch to 1 for TECOP Greek mod */ ! 177: #endif ! 178: ! 179: /* Configurable variables - see ker/conf/console/Space.c */ ! 180: extern int vga_count; ! 181: extern int mono_count; ! 182: ! 183: HWentry VTVGA = { 4, 0, VT_VGAPORT, { 0, VT_VGABASE }, { 25, 80 } }; ! 184: HWentry VTMONO = { 4, 0, VT_MONOPORT, { 0, VT_MONOBASE }, { 25, 80 } }; ! 185: ! 186: HWentry *vtHWtable[] = { ! 187: VTVGA, /* VGA followed by MONO is compatible to DOS */ ! 188: VTMONO, ! 189: 0 /* MUST STAY AS LAST ELEMENT !!! */ ! 190: }; ! 191: ! 192: extern int vtmminit(); ! 193: static VTDATA const_vtdata = { ! 194: vtmminit, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 23, 24, 0, 0, 0, 23, 0, 0, 1 ! 195: }; ! 196: ! 197: /* later this should be dynamic */ ! 198: VTDATA *vtconsole, **vtdata; ! 199: ! 200: int vtcount, vtmax; ! 201: extern int vtactive; ! 202: int vt_verbose = { 0 }; ! 203: int vt_opened = { 0 }; ! 204: ! 205: /* Terminal structure. */ ! 206: TTY **vttty; ! 207: ! 208: /* ! 209: ============================================================================== ! 210: ============================================================================== ! 211: */ ! 212: ! 213: static silo_t in_silo; ! 214: ! 215: /* ! 216: * Given hw pointer for one of four types of adapters, see if ! 217: * device is present by write/readback of video memory. ! 218: * ! 219: * return 1 if present, else 0 ! 220: */ ! 221: int ! 222: hwpresent( hw ) ! 223: HWentry *hw; ! 224: { ! 225: int save, present = 1; ! 226: ! 227: PRINTV( "hwpresent: %x:%x", ! 228: hw->vidmemory.seg, hw->vidmemory.off ); ! 229: save = ffword( hw->vidmemory.off, hw->vidmemory.seg ); ! 230: ! 231: sfword( hw->vidmemory.off, hw->vidmemory.seg, 0xAA55 ); ! 232: if( ffword( hw->vidmemory.off, hw->vidmemory.seg ) != 0xAA55 ) ! 233: present = 0; ! 234: ! 235: sfword( hw->vidmemory.off, hw->vidmemory.seg, 0x55AA ); ! 236: if( ffword( hw->vidmemory.off, hw->vidmemory.seg ) != 0x55AA ) ! 237: present = 0; ! 238: ! 239: sfword( hw->vidmemory.off, hw->vidmemory.seg, save ); ! 240: PRINTV( "%s present\n", present ? "" : " NOT" ); ! 241: return present; ! 242: } ! 243: ! 244: /* ! 245: * Load entry point. ! 246: */ ! 247: isload() ! 248: { ! 249: register int i; ! 250: register HWentry **hw; ! 251: register VTDATA *vp; ! 252: ! 253: PRINTV("vtload:\n"); ! 254: fk_loaded = 0; ! 255: table_loaded = 0; ! 256: kbstate = KB_IDLE; ! 257: ! 258: /* Sugar for idtune and kpatch. */ ! 259: VTVGA.count = vga_count; ! 260: VTMONO.count = mono_count; ! 261: ! 262: /* figure out what our current max is */ ! 263: for( vtmax = 0, hw = vtHWtable; *hw; ++hw ) { ! 264: vtmax += (*hw)->count; ! 265: (*hw)->found = 0; /* assume non-exist */ ! 266: } ! 267: PRINTV( "vtload: %d screens possible\n", vtmax ); ! 268: ! 269: vtdata = (VTDATA **) kalloc( vtmax * sizeof( *vtdata ) ); ! 270: if( vtdata == NULL ) { ! 271: printf( "vtload: unable to obtain vtdata[%d]\n", vtmax ); ! 272: u.u_error = -1; ! 273: return; ! 274: } ! 275: PRINTV( "vtload: obtained vtdata[%d] @%x\n", vtmax, vtdata ); ! 276: ! 277: vttty = (TTY **) kalloc( vtmax * sizeof( *vttty ) ); ! 278: if( vttty == NULL ) { ! 279: printf( "vtload: unable to obtain vttty[%d]\n", vtmax ); ! 280: u.u_error = -1; ! 281: return; ! 282: } ! 283: PRINTV( "vtload: obtained vttty[%d] @%x\n", vtmax, vttty ); ! 284: ! 285: /* determine which video adaptors are present */ ! 286: for( vtcount = 0, hw = vtHWtable; *hw; ++hw ) { ! 287: /* suppress board sensing since it seems to confuse some equipment */ ! 288: #if 0 ! 289: if( !hwpresent(*hw) ) ! 290: continue; ! 291: #endif ! 292: ! 293: /* remember our logical start */ ! 294: (*hw)->start = vtcount; ! 295: PRINTV( ", start %d\n", vtcount ); ! 296: ! 297: /* allocate the necessary memory */ ! 298: for ( i = 0; i < (*hw)->count; ++i ) { ! 299: vp = vtdata[vtcount] = kalloc( sizeof(VTDATA) ); ! 300: PRINTV( " vtdata[%d] = @%x\n", vtcount, vp ); ! 301: if( vp == NULL || !VTttyinit(vtcount) ) { ! 302: printf("not enough memory for VTDATA\n" ); ! 303: break; ! 304: } ! 305: ! 306: /* fill in appropriately */ ! 307: *vp = const_vtdata; ! 308: vp->vmm_port = (*hw)->port; ! 309: vp->vmm_vseg = (*hw)->vidmemory.seg; ! 310: vp->vmm_voff = (*hw)->vidmemory.off; ! 311: ! 312: vp->vt_ind = vtcount; ! 313: vtdatainit(vp); ! 314: if (i == 0 ) { ! 315: vp->vmm_visible = VNKB_TRUE; ! 316: vp->vmm_seg = vp->vmm_vseg; ! 317: vp->vmm_off = vp->vmm_voff; ! 318: vtupdscreen(vtcount); ! 319: } ! 320: (*hw)->found++; ! 321: vtcount++; ! 322: } ! 323: } ! 324: ! 325: /* ! 326: * initialize vtconsole ! 327: */ ! 328: vtconsole = vtdata[vtactive = 0]; ! 329: vtconsole->vmm_invis = 0; /* vtconsole cursor visible */ ! 330: ! 331: /* ! 332: * Seize keyboard interrupt. ! 333: */ ! 334: #ifdef _I386 ! 335: setivec(ISVEC, isrint); ! 336: #else ! 337: #if VT_MAJOR == KB_MAJOR ! 338: setivec(1, isrint); ! 339: #else ! 340: /* ! 341: * Map table and vector to us ! 342: */ ! 343: i = sphi(); ! 344: PRINTV( "VTload: unload old vector\n" ); ! 345: kcall( Kclrivec, 1 ); ! 346: setivec(1, isrint); ! 347: spl( i ); ! 348: #endif ! 349: #endif /* _I386 */ ! 350: ! 351: /* ! 352: * Enable mmwatch() invocation every second. ! 353: */ ! 354: drvl[VT_MAJOR].d_time = 1; ! 355: ! 356: /* ! 357: * Initialize video display. ! 358: */ ! 359: for ( i = 0; i < vtcount; ++i ) ! 360: vtmmstart( vttty[i] ); ! 361: ! 362: ! 363: #ifndef _I386 ! 364: /* ! 365: * Allocate a segment to store the in-core keyboard table. ! 366: * This would be a lot more convenient in kernel data space, ! 367: * but small model COHERENT doesn't have that luxury. ! 368: */ ! 369: kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH); ! 370: if (kbsegp == (SEG *)0) ! 371: printf("kb: unable to allocate keyboard table segment\n"); ! 372: KBDEBUG("Exiting kbload()\n"); ! 373: #endif ! 374: fklength = 0; ! 375: } ! 376: ! 377: /* ! 378: * Unload entry point. ! 379: */ ! 380: isuload() ! 381: { ! 382: register int i; ! 383: register level = sphi(); ! 384: ! 385: clrivec(ISVEC); ! 386: #ifndef _I386 ! 387: #if VT_MAJOR != KB_MAJOR ! 388: kcall( Ksetivec, ISVEC, &Kisrint ); ! 389: #endif ! 390: #endif ! 391: spl( level ); ! 392: ! 393: /* Restore pointers to original state. */ ! 394: vtconsole = vtdata[0]; ! 395: vtconsole->vmm_invis = 0; ! 396: vtconsole->vmm_visible = VNKB_TRUE; ! 397: ! 398: if( vt_opened ) ! 399: printf( "VTclose with %d open screens\n", vt_opened ); ! 400: if( kbstate != KB_IDLE ) ! 401: printf("kb: keyboard busy during unload\n"); ! 402: #ifndef _I386 ! 403: if (kbsegp != (SEG *)0) { ! 404: table_loaded = 0; ! 405: sfree(kbsegp); ! 406: } ! 407: #endif ! 408: ! 409: #ifndef _I386 ! 410: for( i = 0; i < vtcount; ++i ) { ! 411: PRINTV( "VTuload: free far %x:%x, tty %x\n", ! 412: vttty[i]->t_buffer->s_faddr, vttty[i] ); ! 413: sfree( vttty[i]->t_buffer ); ! 414: kfree( vttty[i] ); ! 415: sfree( vtdata[i].vt_buffer ); ! 416: } ! 417: #endif ! 418: } ! 419: ! 420: /* ! 421: * Open routine. ! 422: */ ! 423: isopen(dev, mode) ! 424: dev_t dev; ! 425: unsigned int mode; ! 426: { ! 427: register int s; ! 428: register TTY *tp; ! 429: int index = vtindex(dev); ! 430: ! 431: PRINTV("isopen: %x\n", dev); ! 432: if (index < 0 || index >= vtcount) { ! 433: u.u_error = ENXIO; ! 434: return; ! 435: } ! 436: ! 437: tp = vttty[index]; ! 438: if ((tp->t_flags&T_EXCL) != 0 && !super()) { ! 439: u.u_error = ENODEV; ! 440: return; ! 441: } ! 442: ttsetgrp(tp, dev, mode); ! 443: ! 444: s = sphi(); ! 445: if (tp->t_open++ == 0) { ! 446: tp->t_flags = T_CARR; /* indicate "carrier" */ ! 447: ttopen(tp); ! 448: } ! 449: spl(s); ! 450: #if 0 ! 451: updleds(); /* update keyboard status LEDS */ ! 452: #endif ! 453: } ! 454: ! 455: ! 456: void isvtswitch(); ! 457: ! 458: /* ! 459: * Close a tty. ! 460: */ ! 461: isclose(dev) ! 462: { ! 463: register int s; ! 464: int index = vtindex(dev); ! 465: register TTY *tp = vttty[index]; ! 466: ! 467: #if 0 ! 468: s = sphi(); ! 469: if (--tp->t_open == 0) { ! 470: ttclose(tp); ! 471: spl(s); ! 472: if( index == vtactive ) ! 473: isvtswitch( VTKEY_HOME ); ! 474: } else ! 475: spl(s); ! 476: #else ! 477: if (--tp->t_open == 0) ! 478: ttclose(tp); ! 479: #endif ! 480: } ! 481: ! 482: /* ! 483: * Read routine. ! 484: */ ! 485: isread(dev, iop) ! 486: dev_t dev; ! 487: IO *iop; ! 488: { ! 489: int index = vtindex(dev); ! 490: register TTY *tp = vttty[index]; ! 491: ! 492: ttread(tp, iop, 0); ! 493: if (tp->t_oq.cq_cc) ! 494: vtmmtime(tp); ! 495: } ! 496: ! 497: /* ! 498: * special constants/struct for the XWindow/KDMAPDISP calls ! 499: */ ! 500: ! 501: #define KDMAPDISP (('K' << 8) | 2) /* map display into user space */ ! 502: #define KDSKBMODE (('K' << 8) | 6) /* turn scan code xlate on/off */ ! 503: #define KDMEMDISP (('K' << 8) | 7) /* dump byte of virt/phys mem */ ! 504: #define KDENABIO (('K' << 8) | 60) /* enable IO */ ! 505: #define KIOCSOUND (('K' << 8) | 63) /* start sound generation */ ! 506: #define KDSETLED (('K' << 8) | 66) /* set leds */ ! 507: ! 508: #define TIMER_CTL 0x43 /* Timer control */ ! 509: #define TIMER_CNT 0x42 /* Timer counter */ ! 510: #define SPEAKER_CTL 0x61 /* Speaker control */ ! 511: ! 512: struct kd_memloc { ! 513: char *vaddr; /* virtual address to map to */ ! 514: char *physaddr; /* physical address to map to */ ! 515: long length; /* size in bytes to map */ ! 516: long ioflg; /* enable I/O addresses if non-zero */ ! 517: }; ! 518: ! 519: static TIM tp; ! 520: int ! 521: resetkb(action) ! 522: int action; ! 523: { ! 524: int i; ! 525: if (action == 1) { ! 526: timeout(&tp,20,resetkb,2); ! 527: outb(KBCTRL, 0xCC); /* Clock high */ ! 528: } ! 529: if (action == 2) { ! 530: i = inb(KBDATA); ! 531: outb(KBCTRL, 0xCC); /* Clear keyboard */ ! 532: outb(KBCTRL, 0x4D); /* Enable keyboard */ ! 533: } ! 534: } ! 535: ! 536: static int X11led; ! 537: ! 538: /* ! 539: * Ioctl routine. ! 540: * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported. ! 541: */ ! 542: isioctl(dev, com, vec) ! 543: dev_t dev; ! 544: struct sgttyb *vec; ! 545: { ! 546: register int s; ! 547: ! 548: switch (com) { ! 549: #define KDDEBUG 0 ! 550: #if KDDEBUG ! 551: case KDMEMDISP: ! 552: { ! 553: struct kd_memloc* mem; ! 554: unsigned char ub, pb; ! 555: mem = vec; ! 556: pxcopy( mem->physaddr, &pb, 1, SEG_386_KD ); ! 557: ub = getubd( mem->vaddr ); ! 558: printf( "User's byte %x(%x), Physical byte %x, Addresses %x %x\n", ! 559: mem->ioflg, ub, pb, mem->vaddr, mem->physaddr ); ! 560: break;; ! 561: } ! 562: #endif ! 563: case KDMAPDISP: ! 564: { ! 565: struct kd_memloc* mem; ! 566: mem = vec; ! 567: #if KDDEBUG ! 568: printf( "mapPhysUser(%x, %x, %x) = %d\n", ! 569: mem->vaddr, mem->physaddr, mem->length, ! 570: #endif ! 571: mapPhysUser(mem->vaddr, mem->physaddr, mem->length) ! 572: #if KDDEBUG ! 573: ) ! 574: #endif ! 575: ; ! 576: } ! 577: case KDENABIO: ! 578: { ! 579: int i; ! 580: for (i = 0 ; i < 64 ; i++ ) ! 581: iomapAnd(0,i); ! 582: break;; ! 583: } ! 584: case KIOCSOUND: ! 585: { ! 586: if (vec) { ! 587: outb(TIMER_CTL, 0xB6); ! 588: outb(TIMER_CNT, (int)vec&0xFF); ! 589: outb(TIMER_CNT, (int)vec>>8); ! 590: outb(SPEAKER_CTL, inb(SPEAKER_CTL) | 03); /* Turn speaker on */ ! 591: } ! 592: else ! 593: outb(SPEAKER_CTL, inb(SPEAKER_CTL) & ~03 ); /* speaker off */ ! 594: break;; ! 595: } ! 596: case KDSKBMODE: ! 597: { ! 598: static int vtB4X11; ! 599: /* outb(KBCTRL, 0x0C); /* Clock low */ ! 600: /* timeout(&tp,3,resetkb,1); /* wait about 20-30ms */ ! 601: if (xlate > vec) { /* Turning translation off */ ! 602: kb_cmd2(K_SCANCODE_CMD, 1); /* set 1 for X */ ! 603: ! 604: #if 0 ! 605: /* deactivate virtual terminal */ ! 606: vtB4X11 = vtactive; ! 607: vtdeactivate(vtdata[vtactive], vtdata[vtcount]); ! 608: vtactivate(vtdata[vtcount]); ! 609: vtactive = vtcount; ! 610: #endif ! 611: } ! 612: else if (xlate < vec) { /* turning translation on */ ! 613: kb_cmd2(K_SCANCODE_CMD, 3); /* set 3 for COH */ ! 614: #if 0 ! 615: /* reactivate virtual terminal */ ! 616: vtactivate(vtdata[vtB4X11]); ! 617: vtactive = vtB4X11; ! 618: #endif ! 619: } ! 620: xlate = (int)vec; ! 621: /* kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */ ! 622: break;; ! 623: } ! 624: case KDSETLED: ! 625: { ! 626: X11led = (int)vec; ! 627: updleds(); ! 628: break;; ! 629: } ! 630: case TIOCSETF: ! 631: case TIOCGETF: ! 632: isfunction(com, (char *)vec); ! 633: break; ! 634: case TIOCSETKBT: ! 635: issettable(vec); ! 636: break; ! 637: case TIOCGETKBT: ! 638: isgettable(vec); ! 639: break; ! 640: default: /* pass to TTY driver */ ! 641: s = sphi(); ! 642: ttioctl(vttty[vtindex(dev)], com, vec); ! 643: spl(s); ! 644: break; ! 645: } ! 646: } ! 647: ! 648: /* ! 649: * Set the in-core keyboard mapping table. ! 650: * The table is sorted by scan code prior to calling ioctl(). ! 651: * All unused table entries (holes in the scan code map) have ! 652: * a zero for the k_key field. ! 653: * This makes key lookup at interrupt time fast by using the scan code ! 654: * as an index into the table. ! 655: */ ! 656: issettable(vec) ! 657: char *vec; ! 658: { ! 659: register unsigned i; ! 660: register int s; ! 661: int timeout; ! 662: static KBTBL this_key; /* current key from kbd table */ ! 663: unsigned int cmd_byte; ! 664: #ifndef _I386 ! 665: register faddr_t faddr; /* address of keyboard table */ ! 666: #endif ! 667: ! 668: PRINTV(" TIOCSETKBT"); ! 669: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */ ! 670: kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */ ! 671: #ifndef _I386 ! 672: faddr = kbsegp->s_faddr; ! 673: #endif ! 674: for (i = 0; i < MAX_KEYS; ++i) { ! 675: ukcopy(vec, &this_key, sizeof(this_key)); ! 676: #ifdef _I386 ! 677: kb[i] = this_key; /* store away */ ! 678: #else ! 679: kfcopy(&this_key, faddr, sizeof(this_key)); ! 680: faddr += sizeof(this_key); ! 681: #endif ! 682: vec += sizeof(this_key); ! 683: if (this_key.k_key != i && this_key.k_key != 0) { ! 684: printf("kb: incorrect or unsorted table entry %d\n", i); ! 685: #ifdef _I386 ! 686: u.u_error = EINVAL; ! 687: #else ! 688: u.u_error = EBADFMT; ! 689: #endif ! 690: return; ! 691: } ! 692: if (this_key.k_key != i) ! 693: continue; /* no key */ ! 694: switch (this_key.k_flags&TMODE) { ! 695: case T: /* typematic */ ! 696: kb_cmd2(K_KEY_T_CMD, i); ! 697: break; ! 698: case M: /* make only */ ! 699: kb_cmd2(K_KEY_M_CMD, i); ! 700: break; ! 701: case MB: /* make/break */ ! 702: kb_cmd2(K_KEY_MB_CMD, i); ! 703: break; ! 704: case TMB: /* typematic make/break */ ! 705: break; /* this is the default */ ! 706: default: ! 707: printf("kb: bad key mode\n"); ! 708: } ! 709: } ! 710: updleds(); ! 711: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */ ! 712: kb_cmd(K_ENABLE_CMD); /* start scanning */ ! 713: /* ! 714: * The following code disables translation from the on-board ! 715: * keyboard/aux controller. Without disabling translation, the ! 716: * received scan codes still look like code set 1 codes even ! 717: * though we put the keyboard controller in scan code set 3. ! 718: * Yes, this is progress.... ! 719: */ ! 720: #if 0 ! 721: while (inb(KBSTS_CMD) & STS_IBUF_FULL) ! 722: ; ! 723: outb(KBSTS_CMD, C_READ_CMD); /* read controller cmd byte */ ! 724: while (!(inb(KBSTS_CMD) & STS_OBUF_FULL)) ! 725: ; ! 726: cmd_byte = inb(KBDATA); ! 727: KBDEBUG2(" cmd_byte=%x", cmd_byte); ! 728: #endif ! 729: timeout = KBTIMEOUT; ! 730: s = sphi(); ! 731: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 732: ; ! 733: outb(KBSTS_CMD, C_WRITE_CMD); /* write controller cmd byte */ ! 734: for (timeout = 50; --timeout > 0;) ! 735: ; ! 736: timeout = KBTIMEOUT; ! 737: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 738: ; ! 739: outb(KBDATA, KBCMDBYTE); /* turn off translation */ ! 740: timeout = KBTIMEOUT; ! 741: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 742: ; ! 743: spl(s); ! 744: #if DEBUG || 1 ! 745: kb_cmd2(K_SCANCODE_CMD, 0); /* query s.c. mode */ ! 746: #endif ! 747: ++table_loaded; ! 748: PRINTV("... TIOCSETKBT\n"); ! 749: } ! 750: ! 751: /* ! 752: * Get the in-core keyboard mapping table and pass it to the user. ! 753: */ ! 754: isgettable(vec) ! 755: char *vec; ! 756: { ! 757: #ifdef _I386 ! 758: KBDEBUG(" TIOCGETKBT"); ! 759: kucopy(kb, vec, sizeof(kb)); ! 760: #else ! 761: register unsigned i; ! 762: register faddr_t faddr; /* address of keyboard table */ ! 763: static KBTBL this_key; /* current key from kbd table */ ! 764: ! 765: KBDEBUG(" TIOCGETKBT"); ! 766: faddr = kbsegp->s_faddr; ! 767: for (i = 0; i < MAX_KEYS; ++i) { ! 768: fkcopy(faddr, &this_key, sizeof(this_key)); ! 769: kucopy(&this_key, vec, sizeof(this_key)); ! 770: faddr += sizeof(this_key); ! 771: vec += sizeof(this_key); ! 772: } ! 773: #endif ! 774: } ! 775: ! 776: ! 777: /* ! 778: * Set and receive the function keys. ! 779: */ ! 780: isfunction(c, v) ! 781: int c; ! 782: FNKEY *v; ! 783: { ! 784: register unsigned char *cp; ! 785: register unsigned i; ! 786: unsigned char numkeys = 0; ! 787: ! 788: if (c == TIOCGETF) { ! 789: KBDEBUG(" TIOCGETF"); ! 790: if (!fk_loaded) ! 791: u.u_error = EINVAL; ! 792: else ! 793: kucopy(fnkeys, v, fklength); /* copy ours to user */ ! 794: } else { /* TIOCSETF */ ! 795: /* ! 796: * If we had a previous function key arena, free it up. ! 797: * Since we don't know how large the function key arena will ! 798: * be, we must size it in the user data space prior to ! 799: * (re)kalloc()'ing it. This is ugly, but a helluva lot better ! 800: * than the old driver which used a hard coded limit of 150! ! 801: */ ! 802: KBDEBUG(" TIOCSETF"); ! 803: fk_loaded = 0; ! 804: if (fnkeys != (FNKEY *)0) ! 805: kfree(fnkeys); /* free old arena */ ! 806: if (funkeyp != NULL) ! 807: kfree(funkeyp); /* free old ptr array */ ! 808: ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys)); ! 809: /* ! 810: * I'd use offsetof (), but right now it is broken due to a ! 811: * compiler bug. ! 812: */ ! 813: fklength = sizeof (FNKEY); ! 814: cp = (char *) (v + 1); ! 815: for (i = 0; i < numkeys; i++) { ! 816: do { ! 817: ++fklength; ! 818: } while (getubd(cp++) != DELIM); ! 819: } ! 820: fnkeys = (FNKEY *)kalloc(fklength); ! 821: funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *)); ! 822: if (fnkeys == (FNKEY *)0 || funkeyp == NULL) { ! 823: if (fnkeys != (FNKEY *)0) { ! 824: kfree(fnkeys); ! 825: fnkeys = 0; ! 826: } ! 827: if (funkeyp != NULL) { ! 828: kfree(funkeyp); ! 829: funkeyp = 0; ! 830: } ! 831: u.u_error = ENOMEM; ! 832: return; ! 833: } ! 834: cp = (char *) (fnkeys + 1); /* point to Fn ... */ ! 835: v = (char *) (v + 1); /* ... key arena */ ! 836: for (i = 0; i < numkeys; i++) { ! 837: funkeyp[i] = cp; /* save pointer */ ! 838: while ((*cp++ = getubd(v++)) != DELIM) /* copy key */ ! 839: ; ! 840: } ! 841: fnkeys->k_nfkeys = numkeys; ! 842: fk_loaded = 1; ! 843: } ! 844: } ! 845: ! 846: ! 847: /* ! 848: * Poll routine. ! 849: */ ! 850: ispoll(dev, ev, msec) ! 851: dev_t dev; ! 852: int ev; ! 853: int msec; ! 854: { ! 855: register TTY *tp = vttty[vtindex(dev)]; ! 856: ! 857: return ttpoll(tp, ev, msec); ! 858: } ! 859: ! 860: /* ! 861: * Receive interrupt. ! 862: */ ! 863: #define K_E0ESC 0xE0 /* Swan Keyboard, Strange Escape Byte */ ! 864: ! 865: isrint() ! 866: { ! 867: register unsigned c; ! 868: register unsigned r; ! 869: static char keyup; ! 870: #if SWANFIX ! 871: static char e0esc; ! 872: #endif ! 873: ! 874: /* ! 875: * Schedule raw input handler if not already active. ! 876: */ ! 877: if (! isbusy) { ! 878: defer (isbatch, vttty [vtactive]); ! 879: isbusy = 1; ! 880: } ! 881: ! 882: /* ! 883: * Pull character from the data ! 884: * port. Pulse the KBFLAG in the control ! 885: * port to reset the data buffer. ! 886: */ ! 887: ! 888: r = inb (KBDATA) & 0xFF; ! 889: c = inb (KBCTRL); ! 890: outb (KBCTRL, c | KBFLAG); ! 891: outb (KBCTRL, c); ! 892: ! 893: /* ! 894: * check returned value from keyboard to see if it's a command ! 895: * or status back to us. If not, it we assume that it's a key code. ! 896: */ ! 897: KBDEBUG2 ("\nintr(%x) ", r); ! 898: if (!xlate) switch (r) { ! 899: case K_BAT_BAD: ! 900: printf("kb: keyboard BAT failed\n"); ! 901: break; ! 902: case K_RESEND: ! 903: KBDEBUG("\nkb: request to resend command\n"); ! 904: outb(KBDATA, prev_cmd); ! 905: break; ! 906: case K_OVERRUN_23: ! 907: printf("kb: keyboard buffer overrun\n"); ! 908: break; ! 909: case K_ACK: ! 910: /* ! 911: * we received an ACKnowledgement from the keyboard. ! 912: * advance the state machine and continue. ! 913: */ ! 914: KBDEBUG(" ACK "); ! 915: switch (kbstate) { ! 916: case KB_IDLE: /* shouldn't happen */ ! 917: printf("vtnkb: ACK while idle "); ! 918: break; ! 919: case KB_SINGLE: /* done with 1-byte command */ ! 920: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */ ! 921: kbstate = KB_IDLE; ! 922: wakeup(&kbstate); ! 923: break; ! 924: case KB_DOUBLE_1: ! 925: kbstate = KB_DOUBLE_2; ! 926: outb(KBDATA, cmd2); ! 927: break; ! 928: default: ! 929: printf("kb: bad kbstate %d\n", kbstate); ! 930: break; ! 931: } ! 932: break; ! 933: default: ! 934: isin(r); ! 935: break; ! 936: } else switch (r) { ! 937: ! 938: case K_BREAK: ! 939: keyup = 1; /* key going up */ ! 940: break; ! 941: ! 942: case K_ECHO_R: ! 943: case K_BAT_OK: ! 944: break; /* very nice, but ignored */ ! 945: ! 946: case K_BAT_BAD: ! 947: printf ("kb: keyboard BAT failed\n"); ! 948: break; ! 949: ! 950: case K_RESEND: ! 951: KBDEBUG ("\nkb: request to resend command\n"); ! 952: outb (KBDATA, prev_cmd); ! 953: break; ! 954: ! 955: case K_OVERRUN_23: ! 956: printf ("kb: keyboard buffer overrun\n"); ! 957: break; ! 958: ! 959: case K_ACK: ! 960: /* ! 961: * we received an ACKnowledgement from the keyboard. ! 962: * advance the state machine and continue. ! 963: */ ! 964: KBDEBUG (" ACK "); ! 965: switch (kbstate) { ! 966: case KB_IDLE: /* shouldn't happen */ ! 967: printf ("vtnkb: ACK while idle "); ! 968: break; ! 969: ! 970: case KB_SINGLE: /* done with 1-byte command */ ! 971: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */ ! 972: kbstate = KB_IDLE; ! 973: wakeup (& kbstate); ! 974: break; ! 975: ! 976: case KB_DOUBLE_1: ! 977: kbstate = KB_DOUBLE_2; ! 978: outb (KBDATA, cmd2); ! 979: break; ! 980: ! 981: default: ! 982: printf ("kb: bad kbstate %d\n", kbstate); ! 983: break; ! 984: } ! 985: break; ! 986: #if SWANFIX ! 987: case K_E0ESC: ! 988: if (VTSWAN) { ! 989: e0esc = 1; ! 990: break; ! 991: } ! 992: #endif ! 993: default: ! 994: #if SWANFIX ! 995: process_key (r, keyup, e0esc); ! 996: e0esc = 0; ! 997: #else ! 998: process_key (r, keyup); ! 999: #endif ! 1000: keyup = 0; ! 1001: } ! 1002: } ! 1003: ! 1004: /* ! 1005: * Process a key given its scan code and direction. ! 1006: * ! 1007: * In this table driven version of the keyboard driver, we trade off the ! 1008: * code complexity associated with all the black magic that used to be ! 1009: * performed on a per-key basis with the increased memory requirements ! 1010: * associated with the table driven approach. ! 1011: */ ! 1012: #if SWANFIX 1 ! 1013: process_key(key, up, e0esc) ! 1014: unsigned key; ! 1015: char up, e0esc; ! 1016: #else ! 1017: process_key(key, up) ! 1018: unsigned key; ! 1019: int up; ! 1020: #endif ! 1021: { ! 1022: register unsigned char *cp; ! 1023: KBTBL key_vals; /* table values for this key */ ! 1024: unsigned val; ! 1025: unsigned char flags; ! 1026: register TTY *tp = vttty[vtactive]; ! 1027: VTDATA *vp = vtdata[vtactive]; ! 1028: ! 1029: KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down")); ! 1030: if (!table_loaded) ! 1031: return; /* throw away key */ ! 1032: #ifdef _I386 ! 1033: /* ! 1034: * It's ugly but, if e0esc, then we use the ALT_GR field to point ! 1035: * at the actual table entry we want. We weren't really using the ! 1036: * ALT_GR field anyway. Trouble remapping shift keys because ! 1037: * loader requires all entries to be identical, thus ALT_GR is ! 1038: * by default being used. ! 1039: */ ! 1040: ! 1041: #if SWANFIX ! 1042: if (VTSWAN && e0esc && (kb [key].k_flags & S) == 0) ! 1043: key = kb [key].k_val [ALT_GR]; /* Ugly kludge */ ! 1044: #endif ! 1045: key_vals = kb [key]; ! 1046: #else ! 1047: fkcopy (kbsegp->s_faddr + (key * sizeof(KBTBL)), ! 1048: & key_vals, sizeof (key_vals)); ! 1049: #endif ! 1050: if (key_vals.k_key != key) /* empty entry */ ! 1051: return; ! 1052: flags = key_vals.k_flags; ! 1053: ! 1054: if (flags & S) { /* some shift/lock key ? */ ! 1055: switch (key_vals.k_val [BASE]) { ! 1056: case caps: ! 1057: case num: ! 1058: if (!up) { ! 1059: shift ^= (1 << key_vals.k_val[BASE]); ! 1060: updleds2 (); ! 1061: } ! 1062: break; ! 1063: ! 1064: case scroll: ! 1065: if (! up) { ! 1066: shift ^= (1 << key_vals.k_val[BASE]); ! 1067: updleds2 (); ! 1068: if (_IS_RAW_INPUT_MODE (tp)) { ! 1069: if (tp->t_flags & T_STOP) ! 1070: isin (tp->t_tchars.t_startc); ! 1071: else ! 1072: isin (tp->t_tchars.t_stopc); ! 1073: } ! 1074: } ! 1075: break; ! 1076: default: ! 1077: if (up) ! 1078: shift &= ~ (1 << key_vals.k_val [BASE]); ! 1079: else ! 1080: shift |= (1 << key_vals.k_val [BASE]); ! 1081: break; ! 1082: } ! 1083: ! 1084: /* ! 1085: * Calculate the shift index based upon the state of ! 1086: * the shift and lock keys. ! 1087: */ ! 1088: ! 1089: sh_index = BASE; /* default condition */ ! 1090: if (shift & (1 << altgr)) ! 1091: sh_index = ALT_GR; ! 1092: else { ! 1093: if (shift & ((1 << lalt) | (1 << ralt))) ! 1094: sh_index |= ALT; ! 1095: if (shift & ((1 << lctrl) | (1 << rctrl))) ! 1096: sh_index |= CTRL; ! 1097: if (shift & ((1 << lshift) | (1 << rshift))) ! 1098: sh_index |= SHIFT; ! 1099: } ! 1100: T_CON(2, printf("shift=%x sh_index=%d\n", shift, sh_index)); ! 1101: return; ! 1102: } /* if (flags & S) */ ! 1103: ! 1104: /* ! 1105: * If the key has no value in the current ! 1106: * shift state, the key is just tossed away. ! 1107: */ ! 1108: if (up || key_vals.k_val [sh_index] == none) ! 1109: return; ! 1110: ! 1111: if (((flags & C) != 0 && (shift & (1 << caps)) != 0) || ! 1112: ((flags & N) != 0 && (shift & (1 << num))) != 0) ! 1113: val = key_vals.k_val [sh_index ^ SHIFT]; ! 1114: else ! 1115: val = key_vals.k_val [sh_index]; ! 1116: ! 1117: /* ! 1118: * Check for function key or special key implemented as ! 1119: * a function key (reboot == f0, tab and back-tab, etc). ! 1120: */ ! 1121: if (flags & F) { ! 1122: PRINTV ("<{F%d}>", val); ! 1123: if (VTKEY (val)) { ! 1124: T_CON(4, ! 1125: printf( "<{F%d !!}>\b\b\b\b\b\b\b\b\b\b", val)); ! 1126: defer (isvtswitch, val); ! 1127: return; ! 1128: } ! 1129: /* If the tty is not open, ignore it */ ! 1130: if (! tp->t_open) ! 1131: return; ! 1132: #if GREEKFIX ! 1133: if (VTGREEK && val == fgk) { ! 1134: ToggleGreek (); ! 1135: return; ! 1136: } ! 1137: #endif /* GREEKFIX */ ! 1138: if (val == 0 && ! up && KBBOOT) ! 1139: boot (); ! 1140: if (! fk_loaded || val >= fnkeys->k_nfkeys) ! 1141: return; ! 1142: if ((cp = funkeyp [val]) == NULL) /* has a value? */ ! 1143: return; ! 1144: while (* cp != DELIM) ! 1145: isin (* cp ++); /* queue up Fn key value */ ! 1146: return; ! 1147: } ! 1148: ! 1149: /* ! 1150: * Normal key processing. ! 1151: */ ! 1152: /* If the tty is not open, ignore it */ ! 1153: #if GREEKFIX ! 1154: if (tp->t_open) ! 1155: if (VTGREEK) { ! 1156: if (ToGreek (& val)) ! 1157: isin (val); ! 1158: } else ! 1159: isin (val); ! 1160: #else ! 1161: if (tp->t_open) ! 1162: isin (val); /* send the char */ ! 1163: #endif /* GREEKFIX */ ! 1164: } ! 1165: ! 1166: /** ! 1167: * ! 1168: * void ! 1169: * ismmfunc(c) -- process keyboard related output escape sequences ! 1170: * char c; ! 1171: */ ! 1172: void ! 1173: ismmfunc(c) ! 1174: register int c; ! 1175: { ! 1176: ! 1177: switch (c) { ! 1178: case 't': /* Enter numlock */ ! 1179: shift |= (1 << num); ! 1180: updleds (); /* update LED status */ ! 1181: break; ! 1182: ! 1183: case 'u': /* Leave numlock */ ! 1184: shift &= ~ (1 << num); ! 1185: updleds (); /* update LED status */ ! 1186: break; ! 1187: ! 1188: case '=': /* Enter alternate keypad -- ignored */ ! 1189: case '>': /* Exit alternate keypad -- ignored */ ! 1190: break; ! 1191: ! 1192: case 'c': /* Reset terminal */ ! 1193: islock = 0; ! 1194: break; ! 1195: } ! 1196: } ! 1197: ! 1198: /** ! 1199: * ! 1200: * void ! 1201: * isin(c) -- append character to raw input silo ! 1202: * char c; ! 1203: */ ! 1204: static ! 1205: isin(c) ! 1206: register int c; ! 1207: { ! 1208: int cache_it = 1; ! 1209: TTY * tp = vttty[vtactive]; ! 1210: void ttstart(); ! 1211: ! 1212: /* ! 1213: * If using software incoming flow control, process and ! 1214: * discard t_stopc and t_startc. ! 1215: */ ! 1216: if (_IS_IXON_MODE (tp)) { ! 1217: #if _I386 ! 1218: if (_IS_START_CHAR (tp, c) || ! 1219: (_IS_IXANY_MODE (tp) && (tp->t_flags & T_STOP) != 0)) { ! 1220: tp->t_flags &= ~ (T_STOP | T_XSTOP); ! 1221: ttstart (tp); ! 1222: cache_it = 0; ! 1223: } else if (_IS_STOP_CHAR (tp, c)) { ! 1224: if ((tp->t_flags & T_STOP) == 0) ! 1225: tp->t_flags |= (T_STOP | T_XSTOP); ! 1226: cache_it = 0; ! 1227: } ! 1228: #else ! 1229: if (_IS_STOP_CHAR (tp, c)) { ! 1230: if ((tp->t_flags & T_STOP) == 0) ! 1231: tp->t_flags |= T_STOP; ! 1232: cache_it = 0; ! 1233: } ! 1234: if (_IS_START_CHAR (tp, c)) { ! 1235: tp->t_flags &= ~ T_STOP; ! 1236: ttstart (tp); ! 1237: cache_it = 0; ! 1238: } ! 1239: #endif ! 1240: } ! 1241: ! 1242: /* ! 1243: * Cache received character. ! 1244: */ ! 1245: if (cache_it) { ! 1246: in_silo.si_buf [in_silo.si_ix] = c; ! 1247: ! 1248: if (++ in_silo.si_ix >= sizeof (in_silo.si_buf)) ! 1249: in_silo.si_ix = 0; ! 1250: } ! 1251: } ! 1252: ! 1253: /** ! 1254: * ! 1255: * void ! 1256: * isbatch() -- raw input conversion routine ! 1257: * ! 1258: * Action: Enable the video display. ! 1259: * Canonize the raw input silo. ! 1260: * ! 1261: * Notes: isbatch() was scheduled as a deferred process by isrint(). ! 1262: */ ! 1263: static void ! 1264: isbatch(tp) ! 1265: register TTY * tp; ! 1266: { ! 1267: register int c; ! 1268: static int lastc; ! 1269: VTDATA *vp = tp->t_ddp; ! 1270: ! 1271: /* ! 1272: * Ensure video display is enabled. ! 1273: */ ! 1274: if( vp->vmm_visible ) { ! 1275: vtmm_von(vp); ! 1276: } ! 1277: isbusy = 0; ! 1278: ! 1279: /* ! 1280: * Process all cached characters. ! 1281: */ ! 1282: while (in_silo.si_ix != in_silo.si_ox) { ! 1283: /* ! 1284: * Get next cached char. ! 1285: */ ! 1286: c = in_silo.si_buf [in_silo.si_ox]; ! 1287: ! 1288: if (in_silo.si_ox >= sizeof (in_silo.si_buf) - 1) ! 1289: in_silo.si_ox = 0; ! 1290: else ! 1291: in_silo.si_ox ++; ! 1292: ! 1293: if (islock == 0 || _IS_INTERRUPT_CHAR (tp, c) || ! 1294: _IS_QUIT_CHAR (tp, c)) { ! 1295: ttin (tp, c); ! 1296: } else if ((c == 'b') && lastc == ESCAPE_CHAR) { ! 1297: islock = 0; ! 1298: ttin (tp, lastc); ! 1299: ttin (tp, c); ! 1300: } else if (c == 'c' && lastc == ESCAPE_CHAR) { ! 1301: ttin (tp, lastc); ! 1302: ttin (tp, c); ! 1303: } else ! 1304: putchar ('\a'); ! 1305: lastc = c; ! 1306: } ! 1307: } ! 1308: ! 1309: /* ! 1310: * update the keyboard status LEDS. ! 1311: * we chose the shift/lock key positions so this would be easy. ! 1312: * this flavor of routine is called while processing a system call on ! 1313: * behalf of the user. ! 1314: */ ! 1315: ! 1316: updleds() ! 1317: { ! 1318: if (!xlate) ! 1319: kb_cmd2(K_LED_CMD, X11led); ! 1320: else ! 1321: kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7); ! 1322: } ! 1323: ! 1324: /* ! 1325: * same as above, but callable from interrupt routines and other places ! 1326: * which cannot sleep() waiting for the state machine to go idle. ! 1327: */ ! 1328: updleds2() ! 1329: { ! 1330: register timeout; ! 1331: register int s; ! 1332: ! 1333: timeout = KBTIMEOUT; ! 1334: s = sphi(); ! 1335: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 1336: ; ! 1337: kbstate = KB_DOUBLE_1; ! 1338: if (!xlate) ! 1339: cmd2 = X11led; ! 1340: else ! 1341: cmd2 = (shift >> 1) & 0x7; ! 1342: prev_cmd = K_LED_CMD; ! 1343: outb (KBDATA, K_LED_CMD); ! 1344: spl (s); ! 1345: } ! 1346: ! 1347: /* ! 1348: * unlock the scroll in case an interrupt character is received ! 1349: */ ! 1350: kbunscroll() ! 1351: { ! 1352: shift &= ~ (1 << scroll); ! 1353: updleds (); ! 1354: } ! 1355: ! 1356: /* ! 1357: * ship a single byte command to the keyboard ! 1358: */ ! 1359: kb_cmd(cmd) ! 1360: unsigned cmd; ! 1361: { ! 1362: register int timeout; ! 1363: register int s; ! 1364: ! 1365: s = sphi(); ! 1366: KBDEBUG2(" kb_cmd(%x)", cmd); ! 1367: while (kbstate != KB_IDLE) ! 1368: #ifdef _I386 ! 1369: x_sleep(&kbstate, pritty, slpriSigCatch, "kb a"); ! 1370: #else ! 1371: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb a"); ! 1372: #endif ! 1373: kbstate = KB_SINGLE; ! 1374: timeout = KBTIMEOUT; ! 1375: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 1376: ; ! 1377: if (!timeout) ! 1378: printf("kb: command timeout\n"); ! 1379: else { ! 1380: outb(KBDATA, cmd); ! 1381: while (kbstate != KB_IDLE) ! 1382: #ifdef _I386 ! 1383: x_sleep(&kbstate, pritty, slpriSigCatch, "kb b"); ! 1384: #else ! 1385: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb b"); ! 1386: #endif ! 1387: } ! 1388: spl(s); ! 1389: } ! 1390: ! 1391: /* ! 1392: * ship a two byte command to the keyboard ! 1393: */ ! 1394: kb_cmd2(cmd, arg) ! 1395: unsigned cmd, arg; ! 1396: { ! 1397: register int timeout; ! 1398: register int s; ! 1399: ! 1400: s = sphi(); ! 1401: KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg); ! 1402: while (kbstate != KB_IDLE) ! 1403: #ifdef _I386 ! 1404: x_sleep(&kbstate, pritty, slpriSigCatch, "kb c"); ! 1405: #else ! 1406: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb c"); ! 1407: #endif ! 1408: kbstate = KB_DOUBLE_1; ! 1409: cmd2 = arg; ! 1410: prev_cmd = cmd; ! 1411: timeout = KBTIMEOUT; ! 1412: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 1413: ; ! 1414: if (!timeout) ! 1415: printf("kb: command timeout\n"); ! 1416: else { ! 1417: outb(KBDATA, cmd); ! 1418: while (kbstate != KB_IDLE) ! 1419: #ifdef _I386 ! 1420: x_sleep(&kbstate, pritty, slpriSigCatch, "kb d"); ! 1421: #else ! 1422: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb d"); ! 1423: #endif ! 1424: } ! 1425: spl(s); ! 1426: } ! 1427: ! 1428: /* ! 1429: ============================================================================== ! 1430: ============================================================================== ! 1431: */ ! 1432: ! 1433: int ! 1434: VTttyinit(i) ! 1435: int i; ! 1436: { ! 1437: TTY *tp; ! 1438: ! 1439: /* ! 1440: * get pointer to TTY structure from kernal memory space ! 1441: */ ! 1442: if( (tp = vttty[i] = (TTY *)kalloc(sizeof (TTY))) == NULL ) ! 1443: return(0); ! 1444: PRINTV( " vttty[%d]: @%x, ", i, tp ); ! 1445: ! 1446: #if FAR_TTY ! 1447: /* ! 1448: * get pointers to the buffers pointed to by the TTY structure ! 1449: * from user memory space ! 1450: */ ! 1451: tp->t_buffer = salloc( (fsize_t)NCIB+2*SI_BUFSIZ, SFSYST|SFNSWP ); ! 1452: tp->t_ib = 0; ! 1453: tp->t_rawin.si_buf = NCIB; ! 1454: tp->t_rawout.si_buf = NCIB+SI_BUFSIZ; ! 1455: #endif ! 1456: tp->t_param = NULL; ! 1457: tp->t_start = &vtmmstart; ! 1458: ! 1459: #ifndef _I386 ! 1460: #if VT_MAJOR == KB_MAJOR ! 1461: tp->t_cs_sel = 0; ! 1462: #else ! 1463: tp->t_cs_sel = cs_sel(); ! 1464: #endif ! 1465: #endif ! 1466: tp->t_ddp = vtdata[i]; ! 1467: PRINTV( "data @%lx\n", tp->t_ddp ); ! 1468: return(1); ! 1469: } ! 1470: ! 1471: vtdatainit(vp) ! 1472: VTDATA *vp; ! 1473: { ! 1474: #ifndef _I386 ! 1475: VT_FARSEG vt_farseg; ! 1476: #endif ! 1477: /* ! 1478: * vtdata init - vmm part ! 1479: */ ! 1480: vp->vmm_invis = -1; /* cursor invisible */ ! 1481: ! 1482: #ifdef _I386 ! 1483: vp->vt_buffer = kalloc( TEXTBLOCK ); ! 1484: vp->vmm_seg = vp->vmm_mseg = vtds_sel(); ! 1485: vp->vmm_off = vp->vmm_moff = vp->vt_buffer; ! 1486: #else ! 1487: vp->vt_buffer = salloc ( (fsize_t)TEXTBLOCK, SFSYST|SFNSWP|SFHIGH ); ! 1488: vp->vmm_seg = vp->vmm_mseg = FP_SEG( vp->vt_buffer->vt_faddr ); ! 1489: vp->vmm_off = vp->vmm_moff = FP_OFF( vp->vt_buffer->vt_faddr ); ! 1490: #endif ! 1491: PRINTV( "vt@%x init index %d,%d), seg %x, off %x\n", ! 1492: vp, vp->vt_ind, vp->vmm_mseg, vp->vmm_moff ); ! 1493: /* ! 1494: * vtdata init - vnkb part ! 1495: */ ! 1496: /* Make the first memory block active, if present */ ! 1497: vp->vnkb_lastc = 0; ! 1498: vp->vnkb_fnkeys = 0; ! 1499: vp->vnkb_funkeyp = 0; ! 1500: vp->vnkb_fk_loaded = 0; /* no Fn keys yet */ ! 1501: } ! 1502: ! 1503: /* ! 1504: * Given device number, return index for vtdata[], vttty[], etc. ! 1505: * ! 1506: * Major number must be VT_MAJOR for CPU to get here. ! 1507: * ! 1508: * Minor Number Index Value ! 1509: * ----- ------ ----- ----- ! 1510: * 0000 0000 vtactive ... device (2,0) is the active screen ! 1511: * 0000 0001 0 ! 1512: * 0000 0010 1 ! 1513: * 0000 0011 2 ! 1514: * .... ! 1515: * 0000 1111 14 ! 1516: * ! 1517: * 0100 xxxx xxxx ... color devices only ! 1518: * 0101 xxxx xxxx - (# of color devices found) ... monochrome only ! 1519: * ! 1520: * Return value is in range 0 to vtcount-1 for valid minor numbers, ! 1521: * -1 for invalid minor numbers. ! 1522: */ ! 1523: int ! 1524: vtindex( dev ) ! 1525: dev_t dev; ! 1526: { ! 1527: register int ret = -1; ! 1528: ! 1529: if ( dev & VT_PHYSICAL ) { ! 1530: int hw = ( dev >> 4 ) & 3; ! 1531: int hw_index = dev & 0x0F; ! 1532: ! 1533: if( hw_index < vtHWtable[hw]->found ) ! 1534: ret = vtHWtable[hw]->start + hw_index; ! 1535: } else { ! 1536: int lg_index = dev & 0x0F; ! 1537: ! 1538: if (lg_index == 0) ! 1539: ret = vtactive; ! 1540: if (lg_index > 0 && lg_index <= vtcount ) ! 1541: ret = lg_index-1; ! 1542: } ! 1543: if (ret >= 0) ! 1544: ret %= vtcount; ! 1545: else ! 1546: PRINTV( "vtindex: (%x) %d. invalid !\n", dev, ret ); ! 1547: return ret; ! 1548: } ! 1549: ! 1550: /* ! 1551: * ! 1552: * void ! 1553: * isvtswitch() -- deferred virtual terminal switch ! 1554: * ! 1555: * Action: - save current shift key status ! 1556: * - determine new active virtual terminal ! 1557: * - deactivate shift key status of the current virtual terminal ! 1558: * - deactivate current virtual terminal ! 1559: * - activate shift key status of the new virtual terminal with ! 1560: * the previously saved shift key status ! 1561: * - activate new virtual terminal ! 1562: * ! 1563: * Notes: isvtswitch() was scheduled as a deferred process by ! 1564: * process_key() which is a function called by isrint(). ! 1565: */ ! 1566: void ! 1567: isvtswitch(key_val) ! 1568: { ! 1569: register int new_index, i; ! 1570: unsigned lockshift, nolockshift; ! 1571: VTDATA *vp = vtdata[vtactive]; ! 1572: VTDATA *vp_old, *vp_new; ! 1573: static int vtprevious; ! 1574: ! 1575: T_CON(2, printf("old shift=%x sh_index=%d\n", shift, sh_index)); ! 1576: lockshift = shift & ((1<<scroll)|(1<<num)|(1<<caps)); ! 1577: nolockshift = shift & ~((1<<scroll)|(1<<num)|(1<<caps)); ! 1578: ! 1579: PRINTV( "F%d: %d", key_val, vtactive ); ! 1580: #if 0 ! 1581: if( key_val == VTKEY_HOME ) ! 1582: new_index = 0; ! 1583: else if( key_val == VTKEY_NEXT ) { ! 1584: new_index = vtactive; ! 1585: for( i = 0; i < vtcount; ++i ) { ! 1586: new_index = ++new_index % vtcount; ! 1587: if( vttty[new_index]->t_open ) ! 1588: break; ! 1589: } ! 1590: } else { ! 1591: new_index = vtindex(vtkey_to_dev(key_val)); ! 1592: if( new_index < 0) { ! 1593: putchar( '\007' ); ! 1594: return; ! 1595: } ! 1596: } ! 1597: #else ! 1598: switch (key_val) { ! 1599: case VTKEY_HOME: ! 1600: new_index = 0; ! 1601: break; ! 1602: case VTKEY_NEXT: ! 1603: new_index = vtactive; ! 1604: for( i = 0; i < vtcount; ++i ) { ! 1605: new_index = ++new_index % vtcount; ! 1606: if( vttty[new_index]->t_open ) ! 1607: break; ! 1608: } ! 1609: break; ! 1610: case VTKEY_PREV: ! 1611: new_index = vtactive; ! 1612: for( i = 0; i < vtcount; ++i ) { ! 1613: new_index = (--new_index+vtcount) % vtcount; ! 1614: if( vttty[new_index]->t_open ) ! 1615: break; ! 1616: } ! 1617: break; ! 1618: case VTKEY_TOGL: ! 1619: new_index = vtprevious; ! 1620: break; ! 1621: default: ! 1622: new_index = vtindex(vtkey_to_dev(key_val)); ! 1623: if( new_index < 0) { ! 1624: putchar( '\007' ); ! 1625: return; ! 1626: } ! 1627: } ! 1628: #endif ! 1629: T_CON(8, printf("%d->%d ", vtactive, new_index)); ! 1630: if( new_index == vtactive ) ! 1631: return; ! 1632: ! 1633: /* Save which locking shift states are in effect. */ ! 1634: ! 1635: vp_old = vtdata[vtactive]; ! 1636: vp_new = vtdata[new_index]; ! 1637: ! 1638: vp_old->vnkb_shift = lockshift; ! 1639: vtdeactivate(vp_new, vp_old); /* deactivate old virtual terminal */ ! 1640: ! 1641: /* Restore shift lock state, append current momentary shift state. */ ! 1642: shift = vp_new->vnkb_shift | nolockshift; ! 1643: T_CON(2, printf("new shift=%x sh_index=%d\n", shift, sh_index)); ! 1644: vtactivate(vp_new); /* activate new virtual terminal */ ! 1645: updterminal(new_index); ! 1646: vtprevious = vtactive; ! 1647: vtactive = new_index; /* update vtactive */ ! 1648: } ! 1649: ! 1650: vtdeactivate(vp_new, vp_old) ! 1651: register VTDATA *vp_new, *vp_old; ! 1652: { ! 1653: register i; ! 1654: VTDATA *vpi; ! 1655: ! 1656: /* store old screen contents in memory segment */ ! 1657: ffcopy (vp_old->vmm_voff, vp_old->vmm_vseg, ! 1658: vp_old->vmm_moff, vp_old->vmm_mseg, TEXTBLOCK); ! 1659: ! 1660: /* ! 1661: * if changing to another screen on same video board ! 1662: * for all screens on same board as new screen ! 1663: * deactivate, but don't update ! 1664: * else - changing to a screen on different board ! 1665: * for all screens NOT on same board as new screen ! 1666: * deactivate, but don't update ! 1667: */ ! 1668: if ( vp_old->vmm_port == vp_new->vmm_port ) { ! 1669: T_CON(8, printf("deactivate on %x ", vp_new->vmm_port)); ! 1670: for (i = 0; i < vtcount; ++i) { ! 1671: vpi = vtdata[i]; ! 1672: if ( vpi->vmm_port == vp_new->vmm_port ) { ! 1673: /* deactivate, but don't update */ ! 1674: vpi->vmm_invis = ~0; ! 1675: vpi->vmm_visible = VNKB_FALSE; ! 1676: vpi->vmm_seg = vpi->vmm_mseg; ! 1677: vpi->vmm_off = vpi->vmm_moff; ! 1678: if( vpi->vmm_seg == 0 ) ! 1679: printf( "[1]vpi->vmm_seg = 0\n" ); ! 1680: PRINTV( "vt.back %d. seg %x off %x\n", i, ! 1681: vpi->vmm_seg, vpi->vmm_off ); ! 1682: } ! 1683: } ! 1684: } else { ! 1685: T_CON(8, printf("deactivate %x->%x ", ! 1686: vp_old->vmm_port, vp_new->vmm_port)); ! 1687: for (i = 0; i < vtcount; ++i) { ! 1688: vpi = vtdata[i]; ! 1689: if ( (vpi->vmm_port != vp_new->vmm_port) ! 1690: && (vpi->vmm_invis == 0) ) { ! 1691: /* update, but don't deactivate */ ! 1692: vpi->vmm_invis = ~0; ! 1693: vtupdscreen(i); ! 1694: } ! 1695: } ! 1696: } ! 1697: } ! 1698: ! 1699: vtactivate(vp) ! 1700: VTDATA *vp; ! 1701: { ! 1702: register VTDATA *vpi; ! 1703: register i; ! 1704: ! 1705: /* ! 1706: * copy from screen contents from heap segment to video memory ! 1707: * only if necessary ! 1708: */ ! 1709: if (vp->vmm_visible == VNKB_FALSE) ! 1710: ffcopy (vp->vmm_moff, vp->vmm_mseg, ! 1711: vp->vmm_voff, vp->vmm_vseg, TEXTBLOCK); ! 1712: ! 1713: for (i = 0 ; i < vtcount ; ++ i) { ! 1714: vpi = vtdata [i]; ! 1715: if (vpi->vmm_port == vp->vmm_port) { ! 1716: vpi->vmm_invis = -1; ! 1717: vpi->vmm_visible = VNKB_FALSE; ! 1718: vpi->vmm_seg = vpi->vmm_mseg; ! 1719: vpi->vmm_off = vpi->vmm_moff; ! 1720: if (vpi->vmm_seg == 0) ! 1721: printf ("[2]vpi->vmm_seg = 0\n"); ! 1722: PRINTV ("vt.back seg %x off %x\n", ! 1723: vpi->vmm_seg, vpi->vmm_off); ! 1724: } ! 1725: } ! 1726: /* ! 1727: * Set new active terminal ! 1728: */ ! 1729: vp->vmm_invis = 0; ! 1730: vp->vmm_visible = VNKB_TRUE; ! 1731: vp->vmm_seg = vp->vmm_vseg; ! 1732: vp->vmm_off = vp->vmm_voff; ! 1733: if (vp->vmm_seg == 0) ! 1734: printf ("vp->vmm_seg = 0\n"); ! 1735: } ! 1736: ! 1737: /* ! 1738: * update the terminal to match vtactive ! 1739: */ ! 1740: updterminal(index) ! 1741: int index; ! 1742: { ! 1743: vtupdscreen(index); ! 1744: updleds2(); ! 1745: } ! 1746: ! 1747: /* ! 1748: * Given a function key number (e.g. vt0), ! 1749: * return the corresponding minor device number. ! 1750: * ! 1751: * Assume valid key number (VTKEY(fnum) is true) by the time we get here. ! 1752: */ ! 1753: int ! 1754: vtkey_to_dev(fnum) ! 1755: int fnum; ! 1756: { ! 1757: if (fnum >=vt0 && fnum <= vt15) ! 1758: return fnum-vt0+1; ! 1759: if (fnum >=color0 && fnum <= color15) ! 1760: return (fnum-color0)|(VT_PHYSICAL|VT_HW_COLOR); ! 1761: if (fnum >=mono0 && fnum <= mono15) ! 1762: return (fnum-mono0)|(VT_PHYSICAL|VT_HW_MONO); ! 1763: printf("vtkey_to_dev(%d)! ", fnum); ! 1764: return 0; ! 1765: } ! 1766: ! 1767: #if GREEKFIX ! 1768: /* ! 1769: * ToggleGreek() must be called every time Alt+Enter is pressed. ! 1770: * It toggles the "InGreek" flag and resets all others. ! 1771: * ! 1772: * ToGreek(unsigned *) returns FALSE if val is a dead key (Greek ! 1773: * accent key) that must NOT be processed, TRUE otherwise. ! 1774: */ ! 1775: ! 1776: static int InGreek=0; ! 1777: static int Tonos=0; ! 1778: static int Dialytika=0; ! 1779: ! 1780: static int UpperG[26] = { ! 1781: 128,129,150,131,132,148,130,134,136,141,137,138,139, ! 1782: 140,142,143,58,144,145,146,135,151,145,149,147,133}; ! 1783: ! 1784: static int LowerG[26] = { ! 1785: 152,153,175,155,156,173,154,158,160,165,161,162,163, ! 1786: 164,166,167,59,168,169,171,159,224,170,174,172,157}; ! 1787: ! 1788: static int VoyelG[7] = {152,156,158,160,166,172,224}; ! 1789: static int TonedG[7] = {225,226,227,229,230,231,233}; ! 1790: ! 1791: void ! 1792: ToggleGreek() ! 1793: { ! 1794: InGreek ^= 1; ! 1795: Tonos = 0; ! 1796: Dialytika = 0; ! 1797: return; ! 1798: } ! 1799: ! 1800: int ! 1801: ToGreek(ip) ! 1802: unsigned *ip; ! 1803: { ! 1804: unsigned i,j; ! 1805: ! 1806: i = *ip; ! 1807: ! 1808: /* If Not Greek exit */ ! 1809: if(!InGreek) ! 1810: return 1; ! 1811: ! 1812: /* Capture dead keys */ ! 1813: if(i == ';') { ! 1814: Tonos ^= 1; ! 1815: return 0; ! 1816: } ! 1817: ! 1818: if(i == ':') { ! 1819: Dialytika ^= 1; ! 1820: return 0; ! 1821: } ! 1822: ! 1823: /* Check if character translation needed */ ! 1824: if ((i >= 'A') && (i <= 'Z')) ! 1825: i = UpperG[i - 'A']; ! 1826: else if ((i >= 'a') && (i <= 'z')) ! 1827: i = LowerG[i - 'a']; ! 1828: else ! 1829: return 1; ! 1830: ! 1831: /* Check if any accent has to be added */ ! 1832: if (Tonos) { ! 1833: Tonos = 0; ! 1834: for(j = 0;j < 7;j++) ! 1835: if (i == VoyelG[j]) { ! 1836: i = TonedG[j]; ! 1837: break; ! 1838: } ! 1839: } else if (Dialytika) { ! 1840: Dialytika=0; ! 1841: if (i == 160) ! 1842: i = 228; ! 1843: else if (i == 172) ! 1844: i = 232; ! 1845: } ! 1846: ! 1847: /* Exit point for translated characters */ ! 1848: *(ip) = i; ! 1849: return 1; ! 1850: } ! 1851: ! 1852: #endif /* GREEKFIX */ ! 1853: /* End of nkb.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.