|
|
1.1 ! root 1: /* ! 2: * Keyboard/display driver for German keyboard. ! 3: * Coherent, IBM PC/XT/AT (286 and 386). ! 4: */ ! 5: #include <sys/coherent.h> ! 6: #ifdef _I386 ! 7: #include <sys/reg.h> ! 8: #else ! 9: #include <sys/i8086.h> ! 10: #endif ! 11: #include <sys/con.h> ! 12: #include <sys/devices.h> ! 13: #include <errno.h> ! 14: #include <sys/stat.h> ! 15: #include <sys/tty.h> ! 16: #include <signal.h> ! 17: #include <sys/sched.h> ! 18: #include <sys/silo.h> ! 19: #include <sys/kb.h> ! 20: #include <sys/vt.h> ! 21: ! 22: #define ISVEC 1 /* Keyboard interrupt vector */ ! 23: #define DEBUG 0 ! 24: ! 25: #define SPC 0376 /* Special encoding */ ! 26: #define XXX 0377 /* Non-character */ ! 27: #define KBDATA 0x60 /* Keyboard data */ ! 28: #define KBCTRL 0x61 /* Keyboard control */ ! 29: #define KBFLAG 0x80 /* Keyboard reset flag */ ! 30: #define LEDCMD 0xED /* status indicator command */ ! 31: #define KBACK 0xFA /* status indicator acknowledge */ ! 32: #define EXTENDED0 0xE0 /* extended key seq initiator */ ! 33: #define EXTENDED1 0xE1 /* extended key seq initiator */ ! 34: ! 35: #define KEYUP 0x80 /* Key up change */ ! 36: #define KEYSC 0x7F /* Key scan code mask */ ! 37: #define LSHIFT 0x2A-1 /* Left shift key */ ! 38: #define LSHIFTA 0x2B-1 /* Alternate left-shift key */ ! 39: #define RSHIFT 0x36-1 /* Right shift key */ ! 40: #define CTRLkb 0x1D-1 /* Control key */ ! 41: /*-- #define CAPLOCK 0x1D-1 --*/ /* Control key */ ! 42: #define ALTkb 0x38-1 /* Alt key or ALT GR */ ! 43: #define CAPLOCK 0x3A-1 /* Caps lock key */ ! 44: /*-- #define CTRL 0x3A-1 --*/ /* Caps lock key */ ! 45: #define NUMLOCK 0x45-1 /* Numeric lock key */ ! 46: #define DELETE 0x53-1 /* Del, as in CTRL-ALT-DEL */ ! 47: #define BACKSP 0x0E-1 /* Back space */ ! 48: #define SCRLOCK 0x46-1 /* Scroll lock */ ! 49: ! 50: /* Shift flags */ ! 51: #define SRS 0x01 /* Right shift key on */ ! 52: #define SLS 0x02 /* Left shift key on */ ! 53: #define CTS 0x04 /* Ctrl key on */ ! 54: #define ALS 0x08 /* Alt key on */ ! 55: #define CPLS 0x10 /* Caps lock on */ ! 56: #define NMLS 0x20 /* Num lock on */ ! 57: #define AKPS 0x40 /* Alternate keypad shift */ ! 58: #define SHFT 0x80 /* Shift key flag */ ! 59: #define AGS 0x100 /* Alt Graphics on */ ! 60: ! 61: /* Function key information */ ! 62: #define NFKEY 20 /* Number of settable functions */ ! 63: #define NFCHAR 150 /* Number of characters settable */ ! 64: #define NFBUF (NFKEY*2+NFCHAR+1) /* Size of buffer */ ! 65: ! 66: /* ! 67: * Functions. ! 68: */ ! 69: int isrint(); ! 70: int istime(); ! 71: void isbatch(); ! 72: int mmstart(); ! 73: int isopen(); ! 74: int isclose(); ! 75: int isread(); ! 76: int mmwrite(); ! 77: int isioctl(); ! 78: void mmwatch(); ! 79: int isload(); ! 80: int isuload(); ! 81: int ispoll(); ! 82: int nulldev(); ! 83: int nonedev(); ! 84: ! 85: /* ! 86: * Configuration table. ! 87: */ ! 88: CON iscon ={ ! 89: DFCHR|DFPOL, /* Flags */ ! 90: KB_MAJOR, /* Major index */ ! 91: isopen, /* Open */ ! 92: isclose, /* Close */ ! 93: nulldev, /* Block */ ! 94: isread, /* Read */ ! 95: mmwrite, /* Write */ ! 96: isioctl, /* Ioctl */ ! 97: nulldev, /* Powerfail */ ! 98: mmwatch, /* Timeout */ ! 99: isload, /* Load */ ! 100: isuload, /* Unload */ ! 101: ispoll /* Poll */ ! 102: }; ! 103: ! 104: /* ! 105: * Flag indicating turbo machine. ! 106: */ ! 107: int isturbo = 0; ! 108: ! 109: /* ! 110: ============================================================================== ! 111: ============================================================================== ! 112: */ ! 113: /* constants for vtdata[] */ ! 114: #define VT_VGAPORT 0x3D4 ! 115: #define VT_MONOPORT 0x3B4 ! 116: ! 117: #ifdef _I386 ! 118: #define VT_MONOBASE SEG_VIDEOa ! 119: #define VT_VGABASE SEG_VIDEOb ! 120: #else ! 121: #define VT_MONOBASE 0xB000 ! 122: #define VT_VGABASE 0xB800 ! 123: #endif ! 124: ! 125: /* ! 126: Patchable table entrys, ! 127: we go indirect in order to produce a label which can be addressed ! 128: */ ! 129: HWentry VTVGA = { 4, 0, VT_VGAPORT, { 0, VT_VGABASE }, { 25, 80 } }; ! 130: HWentry VTMONO = { 4, 0, VT_MONOPORT, { 0, VT_MONOBASE }, { 25, 80 } }; ! 131: ! 132: HWentry *vtHWtable[] = { ! 133: VTVGA, /* VGA followed by MONO is compatible to DOS */ ! 134: VTMONO, ! 135: 0 /* MUST STAY AS LAST ELEMENT !!! */ ! 136: }; ! 137: ! 138: extern int mminit(); ! 139: static VTDATA const_vtdata = { ! 140: mminit, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 23, 24, 0, 0, 0, 23, 0, 0, 1 ! 141: }; ! 142: ! 143: /* later this should be dynamic */ ! 144: VTDATA *vtconsole, **vtdata; ! 145: ! 146: int vtcount, vtmax; ! 147: extern int vtactive; ! 148: int vt_verbose = { 0 }; ! 149: int vt_opened = { 0 }; ! 150: ! 151: /* Terminal structure. */ ! 152: TTY **vttty; ! 153: ! 154: /* ! 155: ============================================================================== ! 156: ============================================================================== ! 157: */ ! 158: ! 159: static silo_t in_silo; ! 160: ! 161: /* ! 162: * State variables. ! 163: */ ! 164: int islock; /* Keyboard locked flag */ ! 165: int isbusy; /* Raw input conversion busy */ ! 166: static unsigned shift; /* Overall shift state */ ! 167: static char scrollkb; /* Scroll lock state */ ! 168: static char lshiftkb = LSHIFT; /* Left shift alternate state */ ! 169: static char isfbuf[NFBUF]; /* Function key values */ ! 170: static char *isfval[NFKEY]; /* Function key string pointers */ ! 171: static int ledcmd; /* LED update command flag */ ! 172: static int extended; /* extended key scan count */ ! 173: static char extmode; /* use extended mode for this key */ ! 174: static char ext0seen; /* 0xE0 prefix seen */ ! 175: static char fk_loaded; /* true == funcion keys resident */ ! 176: ! 177: /* ! 178: * Tables for converting key code to ASCII. ! 179: * lmaptab specifies unshifted conversion, ! 180: * umaptab specifies shifted conversion, ! 181: * smaptab specifies the shift states which are active. ! 182: * An entry of XXX says the key is dead. ! 183: * An entry of SPC requires further processing. ! 184: * ! 185: * Key codes: ! 186: * ESC .. <- == 1 .. 14 ! 187: * -> .. \n == 15 .. 28 ! 188: * CTRL .. ` == 29 .. 41 ! 189: * ^Shift .. PrtSc == 42 .. 55 ! 190: * ALT .. CapsLock == 56 .. 58 ! 191: * F1 .. F10 == 59 .. 68 ! 192: * NumLock .. Del == 69 .. 83 ! 193: * ISO, F11, F12 == 86 .. 88 ! 194: */ ! 195: unsigned char agmaptab[] ={ /* Alt Gr */ ! 196: XXX, XXX,'\375','\374',XXX, XXX, XXX, /* 1 - 7 */ ! 197: '{', '[', ']', '}', '\\', XXX, XXX, XXX, /* 8 - 15 */ ! 198: '@', XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 16 - 23 */ ! 199: XXX, XXX, XXX, '~', XXX, XXX, XXX, XXX, /* 24 - 31 */ ! 200: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 32 - 39 */ ! 201: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 40 - 47 */ ! 202: XXX, XXX,'\346', XXX, XXX, XXX, XXX, XXX, /* 48 - 55 */ ! 203: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 56 - 63 */ ! 204: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 64 - 71 */ ! 205: XXX, XXX, XXX, XXX, XXX, XXX, XXX, XXX, /* 72 - 79 */ ! 206: XXX, XXX, XXX, XXX, XXX, XXX, '|', XXX, /* 80 - 87 */ ! 207: XXX /* 88 */ ! 208: }; ! 209: ! 210: static unsigned char lmaptab[] ={ ! 211: '\33', '1', '2', '3', '4', '5', '6', /* 1 - 7 */ ! 212: '7', '8', '9', '0','\341','\'', '\b', '\t', /* 8 - 15 */ ! 213: 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* 16 - 23 */ ! 214: 'o', 'p','\201', '+', '\r', XXX, 'a', 's', /* 24 - 31 */ ! 215: 'd', 'f', 'g', 'h', 'j', 'k', 'l','\224', /* 32 - 39 */ ! 216: '\204','^', XXX, '#', 'y', 'x', 'c', 'v', /* 40 - 47 */ ! 217: 'b', 'n', 'm', ',', '.', SPC, XXX, SPC, /* 48 - 55 */ ! 218: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */ ! 219: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */ ! 220: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */ ! 221: SPC, SPC, SPC, SPC, XXX, XXX, '<', XXX, /* 80 - 87 */ ! 222: XXX /* 88 */ ! 223: }; ! 224: ! 225: static unsigned char umaptab[] ={ ! 226: '\33', '!', '"','\025', '$', '%', '&', /* 1 - 7 */ ! 227: '/', '(', ')', '=', '?', '`', '\b', SPC, /* 8 - 15 */ ! 228: 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* 16 - 23 */ ! 229: 'O', 'P','\232', '*', '\r', XXX, 'A', 'S', /* 24 - 31 */ ! 230: 'D', 'F', 'G', 'H', 'J', 'K', 'L','\231', /* 32 - 39 */ ! 231: '\216','\370',XXX,'\'', 'Y', 'X', 'C', 'V', /* 40 - 47 */ ! 232: 'B', 'N', 'M', ';', ':', SPC, XXX, SPC, /* 48 - 55 */ ! 233: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */ ! 234: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */ ! 235: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */ ! 236: SPC, SPC, SPC, SPC, XXX, XXX, '>', XXX, /* 80 - 87 */ ! 237: XXX /* 88 */ ! 238: }; ! 239: ! 240: #define SS0 0 /* No shift */ ! 241: #define SS1 (SLS|SRS|CTS) /* Shift, Ctrl */ ! 242: #define SES (SLS|SRS) /* Shift */ ! 243: #define LET (SLS|SRS|CPLS|CTS) /* Shift, Caps, Ctrl */ ! 244: #define KEY (SLS|SRS|NMLS|AKPS) /* Shift, Num, Alt keypad */ ! 245: ! 246: static unsigned char smaptab[] ={ ! 247: SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */ ! 248: SES, SES, SES, SES, SS1, SES, CTS, SES, /* 8 - 15 */ ! 249: LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */ ! 250: LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */ ! 251: LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */ ! 252: SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */ ! 253: LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */ ! 254: SHFT, SS1, SHFT, SS0, SS0, SS0, SS0, SS0, /* 56 - 63 */ ! 255: SS0, SS0, SS0, SS0, SS0, SHFT, KEY, KEY, /* 64 - 71 */ ! 256: KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */ ! 257: KEY, KEY, KEY, KEY, SS0, SS0, SES, SS0, /* 80 - 87 */ ! 258: SS0 ! 259: }; ! 260: ! 261: /* ! 262: * Load entry point. ! 263: * Do reset the keyboard because it gets terribly munged ! 264: * if you type during the boot. ! 265: */ ! 266: isload() ! 267: { ! 268: register short i; /* was: int i */ ! 269: register HWentry **hw; ! 270: register VTDATA *vp; ! 271: ! 272: /* ! 273: * Reset keyboard if NOT an XT turbo. ! 274: */ ! 275: if ( ! isturbo ) { ! 276: outb(KBCTRL, 0x0C); /* Clock low */ ! 277: for (i = 10582; --i >= 0; ); /* For 20ms */ ! 278: outb(KBCTRL, 0xCC); /* Clock high */ ! 279: for (i = 0; --i != 0; ) ! 280: ; ! 281: i = inb(KBDATA); ! 282: outb(KBCTRL, 0xCC); /* Clear keyboard */ ! 283: outb(KBCTRL, 0x4D); /* Enable keyboard */ ! 284: } ! 285: ! 286: PRINTV("vtload:\n"); ! 287: fk_loaded = 0; ! 288: ! 289: /* figure out what our current max is */ ! 290: for( vtmax = 0, hw = vtHWtable; *hw; ++hw ) { ! 291: vtmax += (*hw)->count; ! 292: (*hw)->found = 0; /* assume non-exist */ ! 293: } ! 294: PRINTV( "vtload: %d screens possible\n", vtmax ); ! 295: ! 296: vtdata = (VTDATA **) kalloc( vtmax * sizeof( *vtdata ) ); ! 297: if( vtdata == NULL ) { ! 298: printf( "vtload: unable to obtain vtdata[%d]\n", vtmax ); ! 299: u.u_error = -1; ! 300: return; ! 301: } ! 302: PRINTV( "vtload: obtained vtdata[%d] @%x\n", vtmax, vtdata ); ! 303: ! 304: vttty = (TTY **) kalloc( vtmax * sizeof( *vttty ) ); ! 305: if( vttty == NULL ) { ! 306: printf( "vtload: unable to obtain vttty[%d]\n", vtmax ); ! 307: u.u_error = -1; ! 308: return; ! 309: } ! 310: PRINTV( "vtload: obtained vttty[%d] @%x\n", vtmax, vttty ); ! 311: ! 312: /* determine which video adaptors are present */ ! 313: for( vtcount = 0, hw = vtHWtable; *hw; ++hw ) { ! 314: /* remember our logical start */ ! 315: (*hw)->start = vtcount; ! 316: PRINTV( ", start %d\n", vtcount ); ! 317: ! 318: /* allocate the necessary memory */ ! 319: for ( i = 0; i < (*hw)->count; ++i ) { ! 320: vp = vtdata[vtcount] = kalloc( sizeof(VTDATA) ); ! 321: PRINTV( " vtdata[%d] = @%x\n", vtcount, vp ); ! 322: if( vp == NULL || !VTttyinit(vtcount) ) { ! 323: printf("not enough memory for VTDATA\n" ); ! 324: break; ! 325: } ! 326: ! 327: /* fill in appropriately */ ! 328: *vp = const_vtdata; ! 329: vp->vmm_port = (*hw)->port; ! 330: vp->vmm_vseg = (*hw)->vidmemory.seg; ! 331: vp->vmm_voff = (*hw)->vidmemory.off; ! 332: ! 333: vp->vt_ind = vtcount; ! 334: vtdatainit(vp); ! 335: if (i == 0 ) { ! 336: vp->vmm_visible = VNKB_TRUE; ! 337: vp->vmm_seg = vp->vmm_vseg; ! 338: vp->vmm_off = vp->vmm_voff; ! 339: updscreen(vtcount); ! 340: } ! 341: (*hw)->found++; ! 342: vtcount++; ! 343: } ! 344: } ! 345: ! 346: /* ! 347: * initialize vtconsole ! 348: */ ! 349: vtconsole = vtdata[vtactive = 0]; ! 350: vtconsole->vmm_invis = 0; /* vtconsole cursor visible */ ! 351: ! 352: /* ! 353: * Seize keyboard interrupt. ! 354: */ ! 355: #ifdef _I386 ! 356: setivec(ISVEC, isrint); ! 357: #else ! 358: #if VT_MAJOR == KB_MAJOR ! 359: setivec(1, isrint); ! 360: #else ! 361: ! 362: /* ! 363: * Map table and vector to us ! 364: */ ! 365: i = sphi(); ! 366: PRINTV( "VTload: unload old vector\n" ); ! 367: kcall( Kclrivec, 1 ); ! 368: setivec(1, isrint); ! 369: spl( i ); ! 370: #endif ! 371: #endif /* _I386 */ ! 372: ! 373: /* ! 374: * Enable mmwatch() invocation every second. ! 375: */ ! 376: drvl[VT_MAJOR].d_time = 1; ! 377: ! 378: /* ! 379: * Initialize video display. ! 380: */ ! 381: for ( i = 0; i < vtcount; ++i ) ! 382: mmstart( vttty[i] ); ! 383: } ! 384: ! 385: /* ! 386: * Unload entry point. ! 387: */ ! 388: isuload() ! 389: { ! 390: register int i; ! 391: register level = sphi(); ! 392: ! 393: clrivec(ISVEC); ! 394: #ifndef _I386 ! 395: #if VT_MAJOR != KB_MAJOR ! 396: kcall( Ksetivec, ISVEC, &Kisrint ); ! 397: #endif ! 398: #endif ! 399: spl( level ); ! 400: ! 401: /* Restore pointers to original state. */ ! 402: vtconsole = vtdata[0]; ! 403: vtconsole->vmm_invis = 0; ! 404: vtconsole->vmm_visible = VNKB_TRUE; ! 405: ! 406: if( vt_opened ) ! 407: printf( "VTclose with %d open screens\n", vt_opened ); ! 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: * Default function key strings (terminated by -1 [\377]) ! 422: */ ! 423: static char *deffuncs[] = { ! 424: "\33[1x\377", /* F1 */ ! 425: "\33[2x\377", /* F2 */ ! 426: "\33[3x\377", /* F3 */ ! 427: "\33[4x\377", /* F4 */ ! 428: "\33[5x\377", /* F5 */ ! 429: "\33[6x\377", /* F6 */ ! 430: "\33[7x\377", /* F7 */ ! 431: "\33[8x\377", /* F8 */ ! 432: "\33[9x\377", /* F9 */ ! 433: "\33[0x\377", /* F10 - historical value */ ! 434: "\33[1y\377", /* F11 */ ! 435: "\33[2y\377", /* F12 */ ! 436: "\33[3y\377", /* F13 */ ! 437: "\33[4y\377", /* F14 */ ! 438: "\33[5y\377", /* F15 */ ! 439: "\33[6y\377", /* F16 */ ! 440: "\33[7y\377", /* F17 */ ! 441: "\33[8y\377", /* F18 */ ! 442: "\33[9y\377", /* F19 */ ! 443: "\33[0y\377" /* F20 */ ! 444: }; ! 445: ! 446: /* ! 447: * Open routine. ! 448: */ ! 449: isopen(dev, mode) ! 450: dev_t dev; ! 451: unsigned int mode; ! 452: { ! 453: register int s; ! 454: register TTY *tp; ! 455: int index = vtindex(dev); ! 456: ! 457: PRINTV("isopen: %x\n", dev); ! 458: if (index < 0 || index >= vtcount) { ! 459: u.u_error = ENXIO; ! 460: return; ! 461: } ! 462: ! 463: tp = vttty[index]; ! 464: if ((tp->t_flags&T_EXCL) != 0 && !super()) { ! 465: u.u_error = ENODEV; ! 466: return; ! 467: } ! 468: ttsetgrp(tp, dev, mode); ! 469: ! 470: s = sphi(); ! 471: if (tp->t_open++ == 0) { ! 472: initkeys(); /* init function keys */ ! 473: tp->t_flags = T_CARR; /* indicate "carrier" */ ! 474: ttopen(tp); ! 475: } ! 476: spl(s); ! 477: #if 0 ! 478: updleds(); /* update keyboard status LEDS */ ! 479: #endif ! 480: } ! 481: ! 482: /* Init function keys */ ! 483: initkeys() ! 484: { register int i; ! 485: register char *cp1, *cp2; ! 486: ! 487: for (i=0; i<NFKEY; i++) ! 488: isfval[i] = 0; /* clear function key buffer */ ! 489: cp2 = isfbuf; /* pointer to key buffer */ ! 490: for (i=0; i<NFKEY; i++) ! 491: { isfval[i] = cp2; /* save pointer to key string */ ! 492: cp1 = deffuncs[i]; /* get init string pointer */ ! 493: while ((*cp2++ = *cp1++) != -1) /* copy key data */ ! 494: if (cp2 >= &isfbuf[NFBUF-3]) /* overflow? */ ! 495: return; ! 496: } ! 497: } ! 498: ! 499: void isvtswitch(); /* deferred virtual terminal switch */ ! 500: ! 501: /* ! 502: * Close a tty. ! 503: */ ! 504: isclose(dev) ! 505: { ! 506: register int s; ! 507: int index = vtindex(dev); ! 508: register TTY *tp = vttty[index]; ! 509: ! 510: if (--tp->t_open == 0) ! 511: ttclose(tp); ! 512: ! 513: } ! 514: ! 515: /* ! 516: * Read routine. ! 517: */ ! 518: isread(dev, iop) ! 519: dev_t dev; ! 520: IO *iop; ! 521: { ! 522: int index = vtindex(dev); ! 523: register TTY *tp = vttty[index]; ! 524: ! 525: ttread(tp, iop, 0); ! 526: if (tp->t_oq.cq_cc) ! 527: mmtime(tp); ! 528: } ! 529: ! 530: /* ! 531: * Ioctl routine. ! 532: */ ! 533: isioctl(dev, com, vec) ! 534: dev_t dev; ! 535: struct sgttyb *vec; ! 536: { ! 537: register int s; ! 538: ! 539: switch(com) { ! 540: case TIOCSETF: ! 541: case TIOCGETF: ! 542: isfunction(com, (char *)vec); ! 543: goto ioc_done;; ! 544: case TIOCSHIFT: /* switch left-SHIFT and "\" */ ! 545: lshiftkb = LSHIFTA; /* alternate values */ ! 546: lmaptab[41] = '\\'; ! 547: lmaptab[42] = XXX; ! 548: umaptab[41] = '|'; ! 549: umaptab[42] = XXX; ! 550: smaptab[41] = SS1; ! 551: smaptab[42] = SHFT; ! 552: goto ioc_done;; ! 553: case TIOCCSHIFT: /* normal (default) left-SHIFT and "\" */ ! 554: lshiftkb = LSHIFT; /* normal values */ ! 555: lmaptab[41] = XXX; ! 556: lmaptab[42] = '\\'; ! 557: umaptab[41] = XXX; ! 558: umaptab[42] = '|'; ! 559: smaptab[41] = SHFT; ! 560: smaptab[42] = SS1; ! 561: goto ioc_done;; ! 562: } ! 563: s = sphi(); ! 564: ttioctl(vttty[vtindex(dev)], com, vec); ! 565: spl(s); ! 566: ! 567: ioc_done: ! 568: return; ! 569: } ! 570: ! 571: /* ! 572: * Set and receive the function keys. ! 573: */ ! 574: isfunction(c, v) ! 575: int c; ! 576: char *v; ! 577: { ! 578: register char *cp; ! 579: register int i; ! 580: ! 581: if (c == TIOCGETF) { ! 582: for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++) ! 583: putubd(v++, *cp); ! 584: } else { ! 585: for (i=0; i<NFKEY; i++) /* zap current settings */ ! 586: isfval[i] = 0; ! 587: cp = isfbuf; /* pointer to key buffer */ ! 588: for (i=0; i<NFKEY; i++) { ! 589: isfval[i] = cp; /* save pointer to key string */ ! 590: while ((*cp++ = getubd(v++)) != -1) /* copy key data */ ! 591: if (cp >= &isfbuf[NFBUF-3]) /* overflow? */ ! 592: return; ! 593: } ! 594: } ! 595: } ! 596: ! 597: ! 598: /* ! 599: * Poll routine. ! 600: */ ! 601: ispoll( dev, ev, msec ) ! 602: dev_t dev; ! 603: int ev; ! 604: int msec; ! 605: { ! 606: register TTY *tp = vttty[vtindex(dev)]; ! 607: ! 608: return ttpoll(tp, ev, msec); ! 609: } ! 610: ! 611: /* ! 612: * Receive interrupt. ! 613: */ ! 614: isrint() ! 615: { ! 616: register int c; ! 617: register int s; ! 618: register int r; ! 619: int savests; ! 620: int update_leds = 0; ! 621: ! 622: /* ! 623: * Schedule raw input handler if not already active. ! 624: */ ! 625: if ( isbusy == 0 ) { ! 626: isbusy = 1; ! 627: defer(isbatch, vttty[vtactive]); ! 628: } ! 629: ! 630: /* ! 631: * Pull character from the data ! 632: * port. Pulse the KBFLAG in the control ! 633: * port to reset the data buffer. ! 634: */ ! 635: r = inb(KBDATA) & 0xFF; ! 636: c = inb(KBCTRL); ! 637: outb(KBCTRL, c|KBFLAG); ! 638: outb(KBCTRL, c); ! 639: #if KBDEBUG ! 640: printf("kbd: %d\n", r); /* print scan code/direction */ ! 641: #endif ! 642: if (ledcmd) { ! 643: ledcmd = 0; ! 644: if (r == KBACK) { /* output to status LEDS */ ! 645: c = scrollkb & 1; ! 646: if (shift & NMLS) ! 647: c |= 2; ! 648: if (shift & CPLS) ! 649: c |= 4; ! 650: outb(KBDATA, c); ! 651: } ! 652: return; ! 653: } ! 654: if (extended > 0) { /* if multi-character seq, */ ! 655: --extended; /* ... ignore this char */ ! 656: return; ! 657: } ! 658: switch (r) { ! 659: case EXTENDED0: /* 0xE0 prefix found */ ! 660: ext0seen = 1; ! 661: return; ! 662: case EXTENDED1: /* ignore extended sequences */ ! 663: extended = 5; ! 664: return; ! 665: case 0xFF: /* Overrun */ ! 666: return; ! 667: } ! 668: ! 669: if (ext0seen) { ! 670: ext0seen = 0; ! 671: extmode = 1; ! 672: } else ! 673: extmode = 0; ! 674: ! 675: c = (r & KEYSC) - 1; ! 676: /* ! 677: * Check for reset. ! 678: */ ! 679: if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS)) ! 680: boot(); ! 681: ! 682: /* ! 683: * Track "shift" keys. ! 684: */ ! 685: s = smaptab[c]; ! 686: if (s&SHFT) { ! 687: if (r&KEYUP) { /* "shift" released */ ! 688: if (c == RSHIFT) ! 689: shift &= ~SRS; ! 690: else if (c == lshiftkb) ! 691: shift &= ~SLS; ! 692: else if (c == CTRLkb) ! 693: shift &= ~CTS; ! 694: else if (c == ALTkb) ! 695: shift &= extmode ? ~AGS : ~ALS; ! 696: } else { /* "shift" pressed */ ! 697: if (c == lshiftkb) ! 698: shift |= SLS; ! 699: else if (c == RSHIFT) ! 700: shift |= SRS; ! 701: else if (c == CTRLkb) ! 702: shift |= CTS; ! 703: else if (c == ALTkb) ! 704: shift |= extmode ? AGS : ALS; ! 705: else if (c == CAPLOCK) { ! 706: shift ^= CPLS; /* toggle cap lock */ ! 707: updleds(); ! 708: } else if (c == NUMLOCK) { ! 709: shift ^= NMLS; /* toggle num lock */ ! 710: updleds(); ! 711: } ! 712: } ! 713: return; ! 714: } ! 715: ! 716: /* ! 717: * No other key up codes of interest. ! 718: */ ! 719: if (r&KEYUP) ! 720: return; ! 721: ! 722: /* ! 723: * Map character, based on the ! 724: * current state of the shift, control, alt graphics, ! 725: * meta (ALT) and lock flags. ! 726: */ ! 727: if (shift & AGS) /* Alt Graphics ? */ ! 728: c = agmaptab[c]; ! 729: else if (shift & CTS) { ! 730: if (s == CTS) /* Map Ctrl (BS | NL) */ ! 731: c = (c == BACKSP) ? 0x7F : 0x0A; ! 732: else if (s==SS1 || s==LET) /* Normal Ctrl map */ ! 733: c = umaptab[c]&0x1F; /* Clear bits 5-6 */ ! 734: else { if (s==KEY || s==SS0) ! 735: vtnumeric(r); ! 736: return; /* Ignore this char */ ! 737: } ! 738: } else if (s &= shift) { ! 739: if (shift & SES) { /* if shift on */ ! 740: if (s & (CPLS|NMLS)) /* if caps/num lock */ ! 741: c = lmaptab[c]; /* use unshifted */ ! 742: else ! 743: c = umaptab[c]; /* use shifted */ ! 744: } else { /* if shift not on */ ! 745: if (s & (CPLS|NMLS)) /* if caps/num lock */ ! 746: c = umaptab[c]; /* use shifted */ ! 747: else ! 748: c = lmaptab[c]; /* use unshifted */ ! 749: } ! 750: } else ! 751: c = lmaptab[c]; /* use unshifted */ ! 752: ! 753: /* ! 754: * Act on character. ! 755: */ ! 756: if (c == XXX) ! 757: return; /* char to ignore */ ! 758: ! 759: if (c != SPC) { /* not special char? */ ! 760: if (shift & ALS) /* ALT (meta bit)? */ ! 761: c |= 0x80; /* set meta */ ! 762: isin(c); /* send the char */ ! 763: } else ! 764: update_leds += isspecial(r); /* special chars */ ! 765: if (update_leds) { ! 766: savests = sphi(); ! 767: outb(KBDATA, LEDCMD); ! 768: ledcmd = 1; ! 769: spl(savests); ! 770: } ! 771: } ! 772: ! 773: /* ! 774: * Process numeric keypad for virtual terminals. ! 775: */ ! 776: vtnumeric(c) ! 777: int c; ! 778: { ! 779: switch (c) { ! 780: case 71: case 72: case 73: /* ctrl 7/8/9 (vt7, vt8, vt9) */ ! 781: defer(isvtswitch, c + 16); ! 782: break; ! 783: case 74: /* ctrl - */ ! 784: defer(isvtswitch, vtp); ! 785: break; ! 786: case 75: case 76: case 77: /* ctrl 4/5/6 (vt5, vt6, vt7) */ ! 787: defer(isvtswitch, c + 10); ! 788: break; ! 789: case 78: /* ctrl + */ ! 790: defer(isvtswitch, vtn); ! 791: break; ! 792: case 79: case 80: case 81: /* ctrl 1/2/3 */ ! 793: defer(isvtswitch, c + 2); ! 794: break; ! 795: case 82: /* ctrl 0 (vt0) */ ! 796: defer(isvtswitch, vt0); ! 797: break; ! 798: case 83: /* ctrl del (toggle) */ ! 799: c = vtt; ! 800: defer(isvtswitch, vtt); ! 801: break; ! 802: } ! 803: } ! 804: ! 805: /* ! 806: * Handle special input sequences. ! 807: * The character passed is the key number. ! 808: * ! 809: * The keypad is translated by the following table, ! 810: * the first entry is the normal sequence, the second the shifted, ! 811: * and the third the alternate keypad sequence. ! 812: */ ! 813: static char *keypad[][3] = { ! 814: { "\33[H", "7", "\33?w" }, /* 71 */ ! 815: { "\33[A", "8", "\33?x" }, /* 72 */ ! 816: { "\33[V", "9", "\33?y" }, /* 73 */ ! 817: { "\33[D", "4", "\33?t" }, /* 75 */ ! 818: { "\0337", "5", "\33?u" }, /* 76 */ ! 819: { "\33[C", "6", "\33?v" }, /* 77 */ ! 820: { "\33[24H","1", "\33?q" }, /* 79 */ ! 821: { "\33[B", "2", "\33?r" }, /* 80 */ ! 822: { "\33[U", "3", "\33?s" }, /* 81 */ ! 823: { "\33[@", "0", "\33?p" }, /* 82 */ ! 824: { "\33[P", ".", "\33?n" } /* 83 */ ! 825: }; ! 826: ! 827: isspecial(c) ! 828: int c; ! 829: { ! 830: register char *cp; ! 831: register int s; ! 832: int update_leds = 0; ! 833: ! 834: cp = 0; ! 835: ! 836: switch (c) { ! 837: case 15: /* cursor back tab */ ! 838: cp = "\033[Z"; ! 839: break; ! 840: case 53: ! 841: if (extmode) ! 842: cp = "/"; ! 843: else if (shift & SES) ! 844: cp = "_"; ! 845: else ! 846: cp = "-"; ! 847: break; ! 848: case 55: /* ignore PrtScr */ ! 849: if (!extmode) ! 850: cp = "*"; ! 851: break; ! 852: case 59: case 60: case 61: case 62: case 63: /* Function keys */ ! 853: case 64: case 65: case 66: ! 854: /* offset to function string */ ! 855: /* Magic numbers 21 and 61 to mach vtnkb constants */ ! 856: if ( shift & ALS ) ! 857: defer(isvtswitch, c + 21); ! 858: else ! 859: cp = isfval[c-59]; ! 860: break; ! 861: case 67: case 68: ! 862: /* offset to function string */ ! 863: if ( shift & ALS ) ! 864: defer(isvtswitch, c + 61); ! 865: else ! 866: cp = isfval[c-59]; ! 867: break; ! 868: case 70: /* Scroll Lock -- stop/start output */ ! 869: { ! 870: static char cbuf[2]; ! 871: ! 872: cp = &cbuf[0]; /* working buffer */ ! 873: if (!(vttty[vtactive]->t_sgttyb.sg_flags ! 874: & RAWIN)) { /* not if in RAW mode */ ! 875: ! 876: ++update_leds; ! 877: if (vttty[vtactive]->t_flags&T_STOP){/* output stopped? */ ! 878: cbuf[0] = vttty[vtactive]->t_tchars.t_startc; ! 879: scrollkb = 0; ! 880: } else { ! 881: cbuf[0] = vttty[vtactive]->t_tchars.t_stopc; ! 882: scrollkb = 1; ! 883: } ! 884: } ! 885: break; ! 886: } ! 887: ! 888: case 79: /* 1/End */ ! 889: case 80: /* 2/DOWN */ ! 890: case 81: /* 3/PgDn */ ! 891: case 82: /* 0/Ins */ ! 892: case 83: /* ./Del */ ! 893: --c; /* adjust code */ ! 894: case 75: /* 4/LEFT */ ! 895: case 76: /* 5 */ ! 896: case 77: /* 6/RIGHT */ ! 897: --c; /* adjust code */ ! 898: case 71: /* 7/Home/Clear */ ! 899: case 72: /* 8/UP */ ! 900: case 73: /* 9/PgUp */ ! 901: s = 0; /* start off with normal keypad */ ! 902: if (shift & NMLS) /* num lock? */ ! 903: s = 1; /* set shift pad */ ! 904: if (shift & SES) /* shift? */ ! 905: s ^= 1; /* toggle shift pad */ ! 906: if (shift & AKPS) /* alternate pad? */ ! 907: s = 2; /* set alternate pad */ ! 908: if (extmode) /* not from keypad? */ ! 909: s = 0; /* force normal sequence */ ! 910: cp = keypad[c-71][s]; /* get keypad value */ ! 911: break; ! 912: } ! 913: if (cp) /* send string */ ! 914: while ((*cp != 0) && (*cp != -1)) ! 915: isin( *cp++ & 0377 ); ! 916: return update_leds; ! 917: } ! 918: ! 919: /** ! 920: * ! 921: * void ! 922: * ismmfunc( c ) -- process keyboard related output escape sequences ! 923: * char c; ! 924: */ ! 925: void ! 926: ismmfunc(c) ! 927: register int c; ! 928: { ! 929: switch (c) { ! 930: case 't': /* Enter numlock */ ! 931: shift |= NMLS; ! 932: updleds(); /* update LED status */ ! 933: break; ! 934: case 'u': /* Leave numlock */ ! 935: shift &= ~NMLS; ! 936: updleds(); /* update LED status */ ! 937: break; ! 938: case '=': /* Enter alternate keypad */ ! 939: shift |= AKPS; ! 940: break; ! 941: case '>': /* Exit alternate keypad */ ! 942: shift &= ~AKPS; ! 943: break; ! 944: case 'c': /* Reset terminal */ ! 945: islock = 0; ! 946: shift = 0; ! 947: initkeys(); ! 948: updleds(); /* update LED status */ ! 949: break; ! 950: } ! 951: } ! 952: ! 953: /** ! 954: * ! 955: * void ! 956: * isin( c ) -- append character to raw input silo ! 957: * char c; ! 958: */ ! 959: static ! 960: isin( c ) ! 961: register int c; ! 962: { ! 963: int cache_it = 1; ! 964: TTY * tp = vttty[vtactive]; ! 965: ! 966: /* ! 967: * If using software incoming flow control, process and ! 968: * discard t_stopc and t_startc. ! 969: */ ! 970: if (ISIXON) { ! 971: #if _I386 ! 972: if (ISSTART || (ISIXANY && ISXSTOP)) { ! 973: tp->t_flags &= ~(T_STOP | T_XSTOP); ! 974: ttstart(tp); ! 975: cache_it = 0; ! 976: } else if (ISSTOP) { ! 977: if ((tp->t_flags&T_STOP) == 0) ! 978: tp->t_flags |= (T_STOP | T_XSTOP); ! 979: cache_it = 0; ! 980: } ! 981: #else ! 982: if (ISSTOP) { ! 983: if ((tp->t_flags&T_STOP) == 0) ! 984: tp->t_flags |= T_STOP; ! 985: cache_it = 0; ! 986: } ! 987: if (ISSTART) { ! 988: tp->t_flags &= ~T_STOP; ! 989: ttstart(tp); ! 990: cache_it = 0; ! 991: } ! 992: #endif ! 993: } ! 994: /* ! 995: * If the tty is not open the character is ! 996: * just tossed away. ! 997: */ ! 998: if (vttty[vtactive]->t_open == 0) ! 999: return; ! 1000: ! 1001: ! 1002: /* ! 1003: * Cache received character. ! 1004: */ ! 1005: if (cache_it) { ! 1006: in_silo.si_buf[ in_silo.si_ix ] = c; ! 1007: ! 1008: if ( ++in_silo.si_ix >= sizeof(in_silo.si_buf) ) ! 1009: in_silo.si_ix = 0; ! 1010: } ! 1011: } ! 1012: ! 1013: /** ! 1014: * ! 1015: * void ! 1016: * isbatch() -- raw input conversion routine ! 1017: * ! 1018: * Action: Enable the video display. ! 1019: * Canonize the raw input silo. ! 1020: * ! 1021: * Notes: isbatch() was scheduled as a deferred process by isrint(). ! 1022: */ ! 1023: static void ! 1024: isbatch( tp ) ! 1025: register TTY * tp; ! 1026: { ! 1027: register int c; ! 1028: static int lastc; ! 1029: VTDATA *vp = tp->t_ddp; ! 1030: ! 1031: /* ! 1032: * Ensure video display is enabled. ! 1033: */ ! 1034: if (vp->vmm_visible) ! 1035: mm_von(vp); ! 1036: ! 1037: isbusy = 0; ! 1038: ! 1039: /* ! 1040: * Process all cached characters. ! 1041: */ ! 1042: while ( in_silo.si_ix != in_silo.si_ox ) { ! 1043: ! 1044: /* ! 1045: * Get next cached char. ! 1046: */ ! 1047: c = in_silo.si_buf[ in_silo.si_ox ]; ! 1048: ! 1049: if ( in_silo.si_ox >= sizeof(in_silo.si_buf) - 1 ) ! 1050: in_silo.si_ox = 0; ! 1051: else ! 1052: in_silo.si_ox++; ! 1053: ! 1054: if ( (islock == 0) || ISINTR || ISQUIT ) { ! 1055: ttin( tp, c ); ! 1056: } ! 1057: ! 1058: else if ( (c == 'b') && (lastc == '\033') ) { ! 1059: islock = 0; ! 1060: ttin( tp, lastc ); ! 1061: ttin( tp, c ); ! 1062: } ! 1063: ! 1064: else if ( (c == 'c') && (lastc == '\033') ) { ! 1065: ttin( tp, lastc ); ! 1066: ttin( tp, c ); ! 1067: } ! 1068: ! 1069: else ! 1070: putchar('\007'); ! 1071: ! 1072: lastc = c; ! 1073: } ! 1074: } ! 1075: ! 1076: /* ! 1077: * update the keyboard status LEDS ! 1078: */ ! 1079: updleds() ! 1080: { ! 1081: int s; ! 1082: ! 1083: s = sphi(); ! 1084: outb(KBDATA, LEDCMD); ! 1085: ledcmd = 1; ! 1086: spl(s); ! 1087: } ! 1088: ! 1089: /* ! 1090: * unlock the scroll in case an interrupt character is received ! 1091: */ ! 1092: kbunscroll() ! 1093: { ! 1094: scrollkb = 0; ! 1095: updleds(); ! 1096: } ! 1097: int ! 1098: VTttyinit(i) ! 1099: int i; ! 1100: { ! 1101: TTY *tp; ! 1102: ! 1103: /* ! 1104: * get pointer to TTY structure from kernal memory space ! 1105: */ ! 1106: if( (tp = vttty[i] = (TTY *)kalloc(sizeof (TTY))) == NULL ) ! 1107: return(0); ! 1108: PRINTV( " vttty[%d]: @%x, ", i, tp ); ! 1109: ! 1110: #if FAR_TTY ! 1111: /* ! 1112: * get pointers to the buffers pointed to by the TTY structure ! 1113: * from user memory space ! 1114: */ ! 1115: tp->t_buffer = salloc( (fsize_t)NCIB+2*SI_BUFSIZ, SFSYST|SFNSWP ); ! 1116: tp->t_ib = 0; ! 1117: tp->t_rawin.si_buf = NCIB; ! 1118: tp->t_rawout.si_buf = NCIB+SI_BUFSIZ; ! 1119: #endif ! 1120: tp->t_param = NULL; ! 1121: tp->t_start = &mmstart; ! 1122: ! 1123: #ifndef _I386 ! 1124: #if VT_MAJOR == KB_MAJOR ! 1125: tp->t_cs_sel = 0; ! 1126: #else ! 1127: tp->t_cs_sel = cs_sel(); ! 1128: #endif ! 1129: #endif ! 1130: tp->t_ddp = vtdata[i]; ! 1131: PRINTV( "data @%lx\n", tp->t_ddp ); ! 1132: return(1); ! 1133: } ! 1134: ! 1135: vtdatainit(vp) ! 1136: VTDATA *vp; ! 1137: { ! 1138: #ifndef _I386 ! 1139: VT_FARSEG vt_farseg; ! 1140: #endif ! 1141: /* ! 1142: * vtdata init - vmm part ! 1143: */ ! 1144: vp->vmm_invis = -1; /* cursor invisible */ ! 1145: ! 1146: #ifdef _I386 ! 1147: vp->vt_buffer = kalloc( TEXTBLOCK ); ! 1148: vp->vmm_seg = vp->vmm_mseg = ds_sel(); ! 1149: vp->vmm_off = vp->vmm_moff = vp->vt_buffer; ! 1150: #else ! 1151: vp->vt_buffer = salloc ( (fsize_t)TEXTBLOCK, SFSYST|SFNSWP|SFHIGH ); ! 1152: vp->vmm_seg = vp->vmm_mseg = FP_SEG( vp->vt_buffer->vt_faddr ); ! 1153: vp->vmm_off = vp->vmm_moff = FP_OFF( vp->vt_buffer->vt_faddr ); ! 1154: #endif ! 1155: PRINTV( "vt@%x init index %d,%d), seg %x, off %x\n", ! 1156: vp, vp->vt_ind, vp->vmm_mseg, vp->vmm_moff ); ! 1157: /* ! 1158: * vtdata init - vnkb part ! 1159: */ ! 1160: /* Make the first memory block active, if present */ ! 1161: vp->vnkb_lastc = 0; ! 1162: vp->vnkb_fnkeys = 0; ! 1163: vp->vnkb_funkeyp = 0; ! 1164: vp->vnkb_fk_loaded = 0; /* no Fn keys yet */ ! 1165: } ! 1166: ! 1167: /* ! 1168: * Given device number, return index for vtdata[], vttty[], etc. ! 1169: * ! 1170: * Major number must be VT_MAJOR for CPU to get here. ! 1171: * ! 1172: * Minor Number Index Value ! 1173: * ----- ------ ----- ----- ! 1174: * 0000 0000 vtactive ... device (2,0) is the active screen ! 1175: * 0000 0001 0 ! 1176: * 0000 0010 1 ! 1177: * 0000 0011 2 ! 1178: * .... ! 1179: * 0000 1111 14 ! 1180: * ! 1181: * 0100 xxxx xxxx ... color devices only ! 1182: * 0101 xxxx xxxx - (# of color devices found) ... monochrome only ! 1183: * ! 1184: * Return value is in range 0 to vtcount-1 for valid minor numbers, ! 1185: * -1 for invalid minor numbers. ! 1186: */ ! 1187: int ! 1188: vtindex( dev ) ! 1189: dev_t dev; ! 1190: { ! 1191: register int ret = -1; ! 1192: ! 1193: if ( dev & VT_PHYSICAL ) { ! 1194: int hw = ( dev >> 4 ) & 3; ! 1195: int hw_index = dev & 0x0F; ! 1196: ! 1197: if( hw_index < vtHWtable[hw]->found ) ! 1198: ret = vtHWtable[hw]->start + hw_index; ! 1199: } else { ! 1200: int lg_index = dev & 0x0F; ! 1201: ! 1202: if (lg_index == 0) ! 1203: ret = vtactive; ! 1204: if (lg_index > 0 && lg_index <= vtcount ) ! 1205: ret = lg_index-1; ! 1206: } ! 1207: if (ret >= 0) ! 1208: ret %= vtcount; ! 1209: else ! 1210: PRINTV( "vtindex: (%x) %d. invalid !\n", dev, ret ); ! 1211: return ret; ! 1212: } ! 1213: ! 1214: /* ! 1215: * ! 1216: * void ! 1217: * isvtswitch() -- deferred virtual terminal switch ! 1218: * ! 1219: * Action: - save current shift key status ! 1220: * - determine new active virtual terminal ! 1221: * - deactivate shift key status of the current virtual terminal ! 1222: * - deactivate current virtual terminal ! 1223: * - activate shift key status of the new virtual terminal with ! 1224: * the previously saved shift key status ! 1225: * - activate new virtual terminal ! 1226: * ! 1227: * Notes: isvtswitch() was scheduled as a deferred process by ! 1228: * process_key() which is a function called by isrint(). ! 1229: */ ! 1230: void ! 1231: isvtswitch(key_val) ! 1232: { ! 1233: register int new_index, i; ! 1234: unsigned lockshift, nolockshift; ! 1235: VTDATA *vp = vtdata[vtactive]; ! 1236: VTDATA *vp_old, *vp_new; ! 1237: static int vtprevious; ! 1238: ! 1239: lockshift = shift & (CPLS | NMLS); ! 1240: nolockshift = shift & ~(CPLS | NMLS); ! 1241: PRINTV( "F%d: %d", key_val, vtactive ); ! 1242: ! 1243: switch (key_val) { ! 1244: case VTKEY_HOME: ! 1245: new_index = 0; ! 1246: break; ! 1247: case VTKEY_NEXT: ! 1248: new_index = vtactive; ! 1249: for( i = 0; i < vtcount; ++i ) { ! 1250: new_index = ++new_index % vtcount; ! 1251: if( vttty[new_index]->t_open ) ! 1252: break; ! 1253: } ! 1254: break; ! 1255: case VTKEY_PREV: ! 1256: new_index = vtactive; ! 1257: for( i = 0; i < vtcount; ++i ) { ! 1258: new_index = (--new_index+vtcount) % vtcount; ! 1259: if( vttty[new_index]->t_open ) ! 1260: break; ! 1261: } ! 1262: break; ! 1263: case VTKEY_TOGL: ! 1264: new_index = vtprevious; ! 1265: break; ! 1266: default: ! 1267: new_index = vtindex(vtkey_to_dev(key_val)); ! 1268: if( new_index < 0) { ! 1269: putchar( '\007' ); ! 1270: return; ! 1271: } ! 1272: } ! 1273: ! 1274: T_CON(8, printf("%d->%d ", vtactive, new_index)); ! 1275: if( new_index == vtactive ) ! 1276: return; ! 1277: ! 1278: /* Save which locking shift states are in effect. */ ! 1279: ! 1280: vp_old = vtdata[vtactive]; ! 1281: vp_new = vtdata[new_index]; ! 1282: ! 1283: vp_old->vnkb_shift = lockshift; ! 1284: vtdeactivate(vp_new, vp_old); /* deactivate old virtual terminal */ ! 1285: ! 1286: /* Restore shift lock state, append current momentary shift state. */ ! 1287: shift = vp_new->vnkb_shift | nolockshift; ! 1288: ! 1289: vtactivate(vp_new); /* activate new virtual terminal */ ! 1290: updterminal(new_index); ! 1291: vtprevious = vtactive; ! 1292: vtactive = new_index; /* update vtactive */ ! 1293: } ! 1294: ! 1295: vtdeactivate(vp_new, vp_old) ! 1296: register VTDATA *vp_new, *vp_old; ! 1297: { ! 1298: register i; ! 1299: VTDATA *vpi; ! 1300: ! 1301: /* store old screen contents in memory segment */ ! 1302: FFCOPY( vp_old->vmm_voff, vp_old->vmm_vseg, ! 1303: vp_old->vmm_moff, vp_old->vmm_mseg, TEXTBLOCK ); ! 1304: ! 1305: /* ! 1306: * if changing to another screen on same video board ! 1307: * for all screens on same board as new screen ! 1308: * deactivate, but don't update ! 1309: * else - changing to a screen on different board ! 1310: * for all screens NOT on same board as new screen ! 1311: * deactivate, but don't update ! 1312: */ ! 1313: if ( vp_old->vmm_port == vp_new->vmm_port ) { ! 1314: T_CON(8, printf("deactivate on %x ", vp_new->vmm_port)); ! 1315: for (i = 0; i < vtcount; ++i) { ! 1316: vpi = vtdata[i]; ! 1317: if ( vpi->vmm_port == vp_new->vmm_port ) { ! 1318: /* deactivate, but don't update */ ! 1319: vpi->vmm_invis = ~0; ! 1320: vpi->vmm_visible = VNKB_FALSE; ! 1321: vpi->vmm_seg = vpi->vmm_mseg; ! 1322: vpi->vmm_off = vpi->vmm_moff; ! 1323: if( vpi->vmm_seg == 0 ) ! 1324: printf( "[1]vpi->vmm_seg = 0\n" ); ! 1325: PRINTV( "vt.back %d. seg %x off %x\n", i, ! 1326: vpi->vmm_seg, vpi->vmm_off ); ! 1327: } ! 1328: } ! 1329: } else { ! 1330: T_CON(8, printf("deactivate %x->%x ", ! 1331: vp_old->vmm_port, vp_new->vmm_port)); ! 1332: for (i = 0; i < vtcount; ++i) { ! 1333: vpi = vtdata[i]; ! 1334: if ( (vpi->vmm_port != vp_new->vmm_port) ! 1335: && (vpi->vmm_invis == 0) ) { ! 1336: /* update, but don't deactivate */ ! 1337: vpi->vmm_invis = ~0; ! 1338: updscreen(i); ! 1339: } ! 1340: } ! 1341: } ! 1342: } ! 1343: ! 1344: vtactivate(vp) ! 1345: VTDATA *vp; ! 1346: { ! 1347: register VTDATA *vpi; ! 1348: register i; ! 1349: ! 1350: /* ! 1351: * copy from screen contents from heap segment to video memory ! 1352: * only if necessary ! 1353: */ ! 1354: if ( vp->vmm_visible == VNKB_FALSE ) ! 1355: FFCOPY( vp->vmm_moff, vp->vmm_mseg, ! 1356: vp->vmm_voff, vp->vmm_vseg, TEXTBLOCK ); ! 1357: ! 1358: for (i = 0; i < vtcount; ++i) { ! 1359: vpi = vtdata[i]; ! 1360: if (vpi->vmm_port == vp->vmm_port) { ! 1361: vpi->vmm_invis = -1; ! 1362: vpi->vmm_visible = VNKB_FALSE; ! 1363: vpi->vmm_seg = vpi->vmm_mseg; ! 1364: vpi->vmm_off = vpi->vmm_moff; ! 1365: if( vpi->vmm_seg == 0 ) ! 1366: printf( "[2]vpi->vmm_seg = 0\n" ); ! 1367: PRINTV( "vt.back seg %x off %x\n", ! 1368: vpi->vmm_seg, vpi->vmm_off ); ! 1369: } ! 1370: } ! 1371: /* ! 1372: * Set new active terminal ! 1373: */ ! 1374: vp->vmm_invis = 0; ! 1375: vp->vmm_visible = VNKB_TRUE; ! 1376: vp->vmm_seg = vp->vmm_vseg; ! 1377: vp->vmm_off = vp->vmm_voff; ! 1378: if( vp->vmm_seg == 0 ) ! 1379: printf( "vp->vmm_seg = 0\n" ); ! 1380: } ! 1381: ! 1382: /* ! 1383: * update the terminal to match vtactive ! 1384: */ ! 1385: updterminal(index) ! 1386: int index; ! 1387: { ! 1388: updscreen(index); ! 1389: updleds(); ! 1390: } ! 1391: ! 1392: #undef si ! 1393: asmdump( cs, ds, es, di, si, bp, sp, bx, dx, cx, i, ip, ax ) ! 1394: int cs, ds, es, di, si, bp, sp, bx, dx, cx, i, ip, ax; ! 1395: { ! 1396: if( vt_verbose < 2 ) ! 1397: return; ! 1398: ! 1399: printf( "asmdump %d: es %x, ds %x, cs:ip %x:%x\n", i, es, ds, cs, ip ); ! 1400: printf( " ax %x, bx %x, cx %x, dx %x\n", ax, bx, cx, dx ); ! 1401: printf( " di %x, si %x, bp %x, sp %d\n", di, si, bp, sp ); ! 1402: #if USING_RS232 ! 1403: if( vt_verbose > 2 ) ! 1404: getchar(); ! 1405: #endif ! 1406: } ! 1407: ! 1408: vtdataprint( vp ) ! 1409: register VTDATA *vp; ! 1410: { ! 1411: if( vt_verbose < 2 ) ! 1412: return; ! 1413: ! 1414: printf( "VTDATA: @%x, esc %x, func %x()\n", ! 1415: vp, vp->vmm_esc, vp->vmm_func ); ! 1416: printf( " hw: port %x, seg %x, off %x\n", ! 1417: vp->vmm_port, vp->vmm_vseg, vp->vmm_voff ); ! 1418: printf( " memory: size %x, seg %x, off %x\n", ! 1419: 0/*vp->vmm_size*/, vp->vmm_mseg, vp->vmm_moff ); ! 1420: printf( " cursor: seg %x, off %x, visible %d\n", ! 1421: vp->vmm_seg, vp->vmm_off, !vp->vmm_invis ); ! 1422: printf( " row %d, col %d = offset %d.\n", ! 1423: vp->vmm_rowl, vp->vmm_col, vp->vmm_pos ); ! 1424: printf( " saved row %d, col %d\n", ! 1425: vp->vmm_srow, vp->vmm_scol ); ! 1426: printf( " screen: visible %d, attr %x, wrap %d, slow %d\n", ! 1427: vp->vmm_visible, vp->vmm_attr, vp->vmm_wrap, vp->vmm_slow ); ! 1428: printf( " row base %d, end %d, limit %d\n", ! 1429: vp->vmm_brow, vp->vmm_erow, vp->vmm_lrow ); ! 1430: printf( " row initial base %d, initial end %d\n", ! 1431: vp->vmm_ibrow, vp->vmm_ierow ); ! 1432: #if USING_RS232 ! 1433: if( vt_verbose > 2 ) ! 1434: getchar(); ! 1435: #endif ! 1436: } ! 1437: ! 1438: FFCOPY( src_off, src_seg, dst_off, dst_seg, count ) ! 1439: { ! 1440: register i; ! 1441: ! 1442: #if 0 ! 1443: i = ffcopy( src_off, src_seg, dst_off, dst_seg, count ); ! 1444: #else ! 1445: for( i = 0; i < count; i += 2 ) { ! 1446: register word = ffword( src_off, src_seg ); ! 1447: sfword( dst_off, dst_seg, word ); ! 1448: src_off += 2; ! 1449: dst_off += 2; ! 1450: } ! 1451: #endif ! 1452: return i; ! 1453: } ! 1454: ! 1455: /* ! 1456: * Given a function key number (e.g. vt0), ! 1457: * return the corresponding minor device number. ! 1458: * ! 1459: * Assume valid key number (VTKEY(fnum) is true) by the time we get here. ! 1460: */ ! 1461: int ! 1462: vtkey_to_dev(fnum) ! 1463: int fnum; ! 1464: { ! 1465: if (fnum >=vt0 && fnum <= vt15) ! 1466: return fnum-vt0+1; ! 1467: if (fnum >=color0 && fnum <= color15) ! 1468: return (fnum-color0)|(VT_PHYSICAL|VT_HW_COLOR); ! 1469: if (fnum >=mono0 && fnum <= mono15) ! 1470: return (fnum-mono0)|(VT_PHYSICAL|VT_HW_MONO); ! 1471: printf("vtkey_to_dev(%d)! ", fnum); ! 1472: return 0; ! 1473: } ! 1474: /* End of vtkb_d.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.