|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "../port/error.h" ! 8: ! 9: #include <libg.h> ! 10: #include <gnot.h> ! 11: #include "screen.h" ! 12: ! 13: enum { ! 14: Data= 0x60, /* data port */ ! 15: ! 16: Status= 0x64, /* status port */ ! 17: Inready= 0x01, /* input character ready */ ! 18: Outbusy= 0x02, /* output busy */ ! 19: Sysflag= 0x04, /* system flag */ ! 20: Cmddata= 0x08, /* cmd==0, data==1 */ ! 21: Inhibit= 0x10, /* keyboard/mouse inhibited */ ! 22: Minready= 0x20, /* mouse character ready */ ! 23: Rtimeout= 0x40, /* general timeout */ ! 24: Parity= 0x80, ! 25: ! 26: Cmd= 0x64, /* command port (write only) */ ! 27: ! 28: CTdata= 0x0, /* chips & Technologies ps2 data port */ ! 29: CTstatus= 0x1, /* chips & Technologies ps2 status port */ ! 30: Enable= 1<<7, ! 31: Clear= 1<<6, ! 32: Error= 1<<5, ! 33: Intenable= 1<<4, ! 34: Reset= 1<<3, ! 35: Tready= 1<<2, ! 36: Rready= 1<<1, ! 37: Idle= 1<<0, ! 38: ! 39: Spec= 0x80, ! 40: ! 41: PF= Spec|0x20, /* num pad function key */ ! 42: View= Spec|0x00, /* view (shift window up) */ ! 43: KF= Spec|0x40, /* function key */ ! 44: Shift= Spec|0x60, ! 45: Break= Spec|0x61, ! 46: Ctrl= Spec|0x62, ! 47: Latin= Spec|0x63, ! 48: Caps= Spec|0x64, ! 49: Num= Spec|0x65, ! 50: Middle= Spec|0x66, ! 51: No= 0x00, /* peter */ ! 52: ! 53: Home= KF|13, ! 54: Up= KF|14, ! 55: Pgup= KF|15, ! 56: Print= KF|16, ! 57: Left= View, ! 58: Right= View, ! 59: End= '\r', ! 60: Down= View, ! 61: Pgdown= View, ! 62: Ins= KF|20, ! 63: Del= 0x7F, ! 64: ! 65: Rbutton=4, ! 66: Mbutton=2, ! 67: Lbutton=1, ! 68: }; ! 69: ! 70: uchar kbtab[] = ! 71: { ! 72: [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6', ! 73: [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t', ! 74: [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', ! 75: [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's', ! 76: [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', ! 77: [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v', ! 78: [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*', ! 79: [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, ! 80: [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, '7', ! 81: [0x48] '8', '9', '-', '4', '5', '6', '+', '1', ! 82: [0x50] '2', '3', '0', '.', Del, No, No, KF|11, ! 83: [0x58] KF|12, No, No, No, No, No, No, No, ! 84: }; ! 85: ! 86: uchar kbtabshift[] = ! 87: { ! 88: [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^', ! 89: [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t', ! 90: [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', ! 91: [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S', ! 92: [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', ! 93: [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V', ! 94: [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*', ! 95: [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, ! 96: [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, '7', ! 97: [0x48] '8', '9', '-', '4', '5', '6', '+', '1', ! 98: [0x50] '2', '3', '0', '.', No, No, No, KF|11, ! 99: [0x58] KF|12, No, No, No, No, No, No, No, ! 100: }; ! 101: ! 102: uchar kbtabesc1[] = ! 103: { ! 104: [0x00] No, No, No, No, No, No, No, No, ! 105: [0x08] No, No, No, No, No, No, No, No, ! 106: [0x10] No, No, No, No, No, No, No, No, ! 107: [0x18] No, No, No, No, '\n', Ctrl, No, No, ! 108: [0x20] No, No, No, No, No, No, No, No, ! 109: [0x28] No, No, Shift, No, No, No, No, No, ! 110: [0x30] No, No, No, No, No, '/', No, Print, ! 111: [0x38] Latin, No, No, No, No, No, No, No, ! 112: [0x40] No, No, No, No, No, No, Break, Home, ! 113: [0x48] Up, Pgup, No, Left, No, Right, No, End, ! 114: [0x50] Down, Pgdown, Ins, Del, No, No, No, No, ! 115: [0x58] No, No, No, No, No, No, No, No, ! 116: }; ! 117: ! 118: /* ! 119: * keyboard input q ! 120: */ ! 121: KIOQ kbdq; ! 122: ! 123: static int keybuttons; ! 124: static uchar ccc; ! 125: static int shift; ! 126: ulong ctport; ! 127: ! 128: enum ! 129: { ! 130: /* controller command byte */ ! 131: Cscs1= (1<<6), /* scan code set 1 */ ! 132: Cmousedis= (1<<5), /* mouse disable */ ! 133: Ckbddis= (1<<4), /* kbd disable */ ! 134: Csf= (1<<2), /* system flag */ ! 135: Cmouseint= (1<<1), /* mouse interrupt enable */ ! 136: Ckbdint= (1<<0), /* kbd interrupt enable */ ! 137: }; ! 138: ! 139: static void kbdintr(Ureg*, void*); ! 140: static void ctps2intr(Ureg*, void*); ! 141: static int ps2mouseputc(IOQ*, int); ! 142: ! 143: /* ! 144: * wait for output no longer busy ! 145: */ ! 146: static int ! 147: outready(void) ! 148: { ! 149: int tries; ! 150: ! 151: for(tries = 0; (inb(Status) & Outbusy); tries++){ ! 152: if(tries > 500) ! 153: return -1; ! 154: delay(2); ! 155: } ! 156: return 0; ! 157: } ! 158: ! 159: /* ! 160: * wait for input ! 161: */ ! 162: static int ! 163: inready(void) ! 164: { ! 165: int tries; ! 166: ! 167: for(tries = 0; !(inb(Status) & Inready); tries++){ ! 168: if(tries > 500) ! 169: return -1; ! 170: delay(2); ! 171: } ! 172: return 0; ! 173: } ! 174: ! 175: /* ! 176: * send a command to the mouse ! 177: */ ! 178: static int ! 179: mousecmd(int cmd) ! 180: { ! 181: unsigned int c; ! 182: int tries; ! 183: ! 184: c = 0; ! 185: tries = 0; ! 186: do{ ! 187: if(tries++ > 2) ! 188: break; ! 189: if(outready() < 0) ! 190: break; ! 191: outb(Cmd, 0xD4); ! 192: if(outready() < 0) ! 193: break; ! 194: outb(Data, cmd); ! 195: if(outready() < 0) ! 196: break; ! 197: if(inready() < 0) ! 198: break; ! 199: c = inb(Data); ! 200: } while(c == 0xFE || c == 0); ! 201: if(c != 0xFA){ ! 202: kprint("mouse returns %2.2ux to the %2.2ux command\n", c, cmd); ! 203: return -1; ! 204: } ! 205: return 0; ! 206: } ! 207: ! 208: /* ! 209: * ask 8042 to enable the use of address bit 20 ! 210: */ ! 211: void ! 212: i8042a20(void) ! 213: { ! 214: outready(); ! 215: outb(Cmd, 0xD1); ! 216: outready(); ! 217: outb(Data, 0xDF); ! 218: outready(); ! 219: } ! 220: ! 221: /* ! 222: * ask 8042 to reset the machine ! 223: */ ! 224: void ! 225: i8042reset(void) ! 226: { ! 227: ushort *s = (ushort*)(KZERO|0x472); ! 228: int i, x; ! 229: ! 230: *s = 0x1234; /* BIOS warm-boot flag */ ! 231: ! 232: /* ! 233: * this works for dhog ! 234: */ ! 235: outready(); ! 236: outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */ ! 237: outready(); ! 238: ! 239: /* ! 240: * Pulse it by hand (old somewhat reliable) ! 241: */ ! 242: x = 0xDF; ! 243: for(i = 0; i < 5; i++){ ! 244: x ^= 1; ! 245: outready(); ! 246: outb(Cmd, 0xD1); ! 247: outready(); ! 248: outb(Data, x); /* toggle reset */ ! 249: delay(100); ! 250: } ! 251: } ! 252: ! 253: ! 254: void ! 255: kbdinit(void) ! 256: { ! 257: int c; ! 258: ! 259: setvec(Kbdvec, kbdintr, 0); ! 260: ! 261: /* wait for a quiescent controller */ ! 262: while((c = inb(Status)) & (Outbusy | Inready)) ! 263: if(c & Inready) ! 264: inb(Data); ! 265: ! 266: /* get current controller command byte */ ! 267: outb(Cmd, 0x20); ! 268: if(inready() < 0){ ! 269: print("kbdinit: can't read ccc\n"); ! 270: ccc = 0; ! 271: } else ! 272: ccc = inb(Data); ! 273: ! 274: /* enable kbd xfers and interrupts */ ! 275: ccc &= ~Ckbddis; ! 276: ccc |= Csf | Ckbdint | Cscs1; ! 277: if(outready() < 0) ! 278: print("kbd init failed\n"); ! 279: outb(Cmd, 0x60); ! 280: if(outready() < 0) ! 281: print("kbd init failed\n"); ! 282: outb(Data, ccc); ! 283: outready(); ! 284: } ! 285: ! 286: /* ! 287: * setup a serial mouse ! 288: */ ! 289: static void ! 290: serialmouse(int port, char *type, int setspeed) ! 291: { ! 292: if(mousetype) ! 293: error(Emouseset); ! 294: ! 295: if(port >= 2 || port < 0) ! 296: error(Ebadarg); ! 297: ! 298: /* set up /dev/eia0 as the mouse */ ! 299: uartspecial(port, 0, &mouseq, setspeed ? 1200 : 0); ! 300: if(type && *type == 'M') ! 301: mouseq.putc = m3mouseputc; ! 302: mousetype = Mouseserial; ! 303: } ! 304: ! 305: static void nop(void){}; ! 306: ! 307: /* ! 308: * look for a chips & technologies 82c710 ps2 mouse on a TI travelmate ! 309: */ ! 310: static int ! 311: ct82c710(void) ! 312: { ! 313: int c; ! 314: ! 315: /* on non-C&T 2fa and 3fa are input only ports */ ! 316: /* get chips attention */ ! 317: outb(0x2fa, 0x55); nop(); nop(); ! 318: outb(0x3fa, ~0x55); nop(); nop(); ! 319: outb(0x3fa, 0x36); nop(); nop(); ! 320: ! 321: /* tell it where its config register should be */ ! 322: outb(0x3fa, 0x390>>2); nop(); nop(); ! 323: outb(0x2fa, ~(0x390>>2)); nop(); nop(); ! 324: ! 325: /* see if this is really a 710 */ ! 326: outb(0x390, 0xf); nop(); nop(); ! 327: if(inb(0x391) != (0x390>>2)) ! 328: return -1; ! 329: ! 330: /* get data port address */ ! 331: outb(0x390, 0xd); nop(); nop(); ! 332: c = inb(0x391); ! 333: if(c == 0 || c == 0xff) ! 334: return -1; ! 335: ctport = c<<2; ! 336: ! 337: /* turn off config mode */ ! 338: outb(0x390, 0xf); nop(); nop(); ! 339: outb(0x391, 0xf); ! 340: ! 341: setvec(Mousevec, ctps2intr, 0); ! 342: ! 343: /* enable for interrupts */ ! 344: c = inb(ctport + CTstatus); ! 345: c &= ~(Clear|Reset); ! 346: c |= Enable|Intenable; ! 347: outb(ctport + CTstatus, c); ! 348: ! 349: mousetype = MousePS2; ! 350: return 0; ! 351: } ! 352: ! 353: /* ! 354: * set up a ps2 mouse ! 355: */ ! 356: static void ! 357: ps2mouse(void) ! 358: { ! 359: int x; ! 360: ! 361: if(mousetype) ! 362: error(Emouseset); ! 363: ! 364: if(ct82c710() == 0) ! 365: return; ! 366: ! 367: /* enable kbd/mouse xfers and interrupts */ ! 368: setvec(Mousevec, kbdintr, 0); ! 369: x = splhi(); ! 370: ccc &= ~Cmousedis; ! 371: ccc |= Cmouseint; ! 372: if(outready() < 0) ! 373: print("mouse init failed\n"); ! 374: outb(Cmd, 0x60); ! 375: if(outready() < 0) ! 376: print("mouse init failed\n"); ! 377: outb(Data, ccc); ! 378: if(outready() < 0) ! 379: print("mouse init failed\n"); ! 380: outb(Cmd, 0xA8); ! 381: if(outready() < 0) ! 382: print("mouse init failed\n"); ! 383: ! 384: /* make mouse streaming, enabled */ ! 385: mousecmd(0xEA); ! 386: mousecmd(0xF4); ! 387: ! 388: /* set high resolution */ ! 389: mousecmd(0xE8); ! 390: mousecmd(0x03); ! 391: ! 392: /* set high resolution finger point mouse */ ! 393: mousecmd(0x5A); ! 394: mousecmd(0x37); ! 395: mousecmd(0x5A); ! 396: mousecmd(0x24); ! 397: splx(x); ! 398: ! 399: mousetype = MousePS2; ! 400: } ! 401: ! 402: /* ! 403: * ps/2 mouse message is three bytes ! 404: * ! 405: * byte 0 - 0 0 SDY SDX 1 M R L ! 406: * byte 1 - DX ! 407: * byte 2 - DY ! 408: * ! 409: * shift & left button is the same as middle button ! 410: */ ! 411: static int ! 412: ps2mouseputc(IOQ *q, int c) ! 413: { ! 414: static short msg[3]; ! 415: static int nb; ! 416: static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 5, 2, 3, 6, 7 }; ! 417: int buttons, dx, dy; ! 418: ! 419: USED(q); /* not */ ! 420: /* ! 421: * check byte 0 for consistency ! 422: */ ! 423: if(nb==0 && (c&0xc8)!=0x08) ! 424: return 0; ! 425: ! 426: msg[nb] = c; ! 427: if(++nb == 3){ ! 428: nb = 0; ! 429: if(msg[0] & 0x10) ! 430: msg[1] |= 0xFF00; ! 431: if(msg[0] & 0x20) ! 432: msg[2] |= 0xFF00; ! 433: ! 434: buttons = b[(msg[0]&7) | (shift ? 8 : 0)] | keybuttons; ! 435: dx = msg[1]; ! 436: dy = -msg[2]; ! 437: mousetrack(buttons, dx, dy); ! 438: } ! 439: return 0; ! 440: } ! 441: ! 442: /* ! 443: * set/change mouse configuration ! 444: */ ! 445: void ! 446: mousectl(char *arg) ! 447: { ! 448: int m, n, x; ! 449: char *field[10]; ! 450: ! 451: n = getfields(arg, field, 10, " \t\n"); ! 452: if(strncmp(field[0], "serial", 6) == 0){ ! 453: switch(n){ ! 454: case 1: ! 455: serialmouse(atoi(field[0]+6), 0, 1); ! 456: break; ! 457: case 2: ! 458: serialmouse(atoi(field[1]), 0, 0); ! 459: break; ! 460: case 3: ! 461: default: ! 462: serialmouse(atoi(field[1]), field[2], 0); ! 463: break; ! 464: } ! 465: } else if(strcmp(field[0], "ps2") == 0){ ! 466: ps2mouse(); ! 467: } else if(strcmp(field[0], "accelerated") == 0){ ! 468: switch(mousetype){ ! 469: case MousePS2: ! 470: x = splhi(); ! 471: mousecmd(0xE7); ! 472: splx(x); ! 473: break; ! 474: } ! 475: } else if(strcmp(field[0], "linear") == 0){ ! 476: switch(mousetype){ ! 477: case MousePS2: ! 478: x = splhi(); ! 479: mousecmd(0xE6); ! 480: splx(x); ! 481: break; ! 482: } ! 483: } else if(strcmp(field[0], "res") == 0){ ! 484: switch(n){ ! 485: default: ! 486: n = 0x02; ! 487: m = 0x23; ! 488: break; ! 489: case 2: ! 490: n = atoi(field[1])&0x3; ! 491: m = 0x7; ! 492: break; ! 493: case 3: ! 494: n = atoi(field[1])&0x3; ! 495: m = atoi(field[2])&0x7; ! 496: break; ! 497: } ! 498: ! 499: switch(mousetype){ ! 500: case MousePS2: ! 501: x = splhi(); ! 502: mousecmd(0xE8); ! 503: mousecmd(n); ! 504: mousecmd(0x5A); ! 505: mousecmd(0x30|m); ! 506: mousecmd(0x5A); ! 507: mousecmd(0x20|(m>>1)); ! 508: splx(x); ! 509: break; ! 510: } ! 511: } else if(strcmp(field[0], "swap") == 0) ! 512: mouseswap ^= 1; ! 513: } ! 514: ! 515: /* ! 516: * keyboard interrupt ! 517: */ ! 518: void ! 519: kbdintr(Ureg *ur, void *a) ! 520: { ! 521: int s, c, i; ! 522: static int esc1, esc2; ! 523: static int caps; ! 524: static int ctl; ! 525: static int num; ! 526: static int collecting, nk; ! 527: static int alt; ! 528: static uchar kc[5]; ! 529: int keyup; ! 530: ! 531: USED(ur, a); ! 532: ! 533: /* ! 534: * get status ! 535: */ ! 536: s = inb(Status); ! 537: if(!(s&Inready)) ! 538: return; ! 539: ! 540: /* ! 541: * get the character ! 542: */ ! 543: c = inb(Data); ! 544: ! 545: /* ! 546: * if it's the mouse... ! 547: */ ! 548: if(s & Minready){ ! 549: ps2mouseputc(&mouseq, c); ! 550: return; ! 551: } ! 552: ! 553: /* ! 554: * e0's is the first of a 2 character sequence ! 555: */ ! 556: if(c == 0xe0){ ! 557: esc1 = 1; ! 558: return; ! 559: } else if(c == 0xe1){ ! 560: esc2 = 2; ! 561: return; ! 562: } ! 563: ! 564: keyup = c&0x80; ! 565: c &= 0x7f; ! 566: if(c > sizeof kbtab){ ! 567: print("unknown key %ux\n", c|keyup); ! 568: return; ! 569: } ! 570: ! 571: if(esc1){ ! 572: c = kbtabesc1[c]; ! 573: esc1 = 0; ! 574: } else if(esc2){ ! 575: esc2--; ! 576: return; ! 577: } else if(shift) ! 578: c = kbtabshift[c]; ! 579: else ! 580: c = kbtab[c]; ! 581: ! 582: if(caps && c<='z' && c>='a') ! 583: c += 'A' - 'a'; ! 584: ! 585: /* ! 586: * keyup only important for shifts ! 587: */ ! 588: if(keyup){ ! 589: switch(c){ ! 590: case Latin: ! 591: alt = 0; ! 592: break; ! 593: case Shift: ! 594: mouseshifted = shift = 0; ! 595: break; ! 596: case Ctrl: ! 597: ctl = 0; ! 598: break; ! 599: } ! 600: return; ! 601: } ! 602: ! 603: /* ! 604: * normal character ! 605: */ ! 606: if(!(c & Spec)){ ! 607: if(ctl){ ! 608: if(alt && c == Del) ! 609: exit(0); ! 610: c &= 0x1f; ! 611: } ! 612: if(!collecting){ ! 613: kbdputc(&kbdq, c); ! 614: return; ! 615: } ! 616: kc[nk++] = c; ! 617: c = latin1(kc, nk); ! 618: if(c < -1) /* need more keystrokes */ ! 619: return; ! 620: if(c != -1) /* valid sequence */ ! 621: kbdputc(&kbdq, c); ! 622: else /* dump characters */ ! 623: for(i=0; i<nk; i++) ! 624: kbdputc(&kbdq, kc[i]); ! 625: nk = 0; ! 626: collecting = 0; ! 627: return; ! 628: } else { ! 629: switch(c){ ! 630: case Caps: ! 631: caps ^= 1; ! 632: return; ! 633: case Num: ! 634: num ^= 1; ! 635: return; ! 636: case Shift: ! 637: mouseshifted = shift = 1; ! 638: return; ! 639: case Latin: ! 640: alt = 1; ! 641: collecting = 1; ! 642: nk = 0; ! 643: return; ! 644: case Ctrl: ! 645: ctl = 1; ! 646: return; ! 647: } ! 648: } ! 649: kbdputc(&kbdq, c); ! 650: } ! 651: ! 652: void ! 653: ctps2intr(Ureg *ur, void *a) ! 654: { ! 655: uchar c; ! 656: ! 657: USED(ur, a); ! 658: c = inb(ctport + CTstatus); ! 659: if(c & Error) ! 660: return; ! 661: if((c & Rready) == 0) ! 662: return; ! 663: c = inb(ctport + CTdata); ! 664: ps2mouseputc(&mouseq, c); ! 665: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.