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