|
|
1.1 root 1: /*
2: * User configurable AT keyboard/display driver.
3: * 286/386 AT COHERENT
4: */
5: #include <sys/coherent.h>
6: #include <sys/i8086.h>
7: #include <sys/con.h>
8: #include <errno.h>
9: #include <sys/stat.h>
10: #include <sys/tty.h>
11: #include <sys/uproc.h>
12: #include <signal.h>
13: #include <sys/seg.h>
14: #include <sys/sched.h>
15: #include <sys/kb.h>
16: #include <sys/devices.h>
17:
18: #define ISVEC 1 /* Keyboard interrupt vector */
19:
20: #if DEBUG
21: #define KBDEBUG(x) printf(x) /* debugging output */
22: #define KBDEBUG2(x,y) printf(x,y) /* debugging output */
23: #define KBDEBUG3(x,y,z) printf(x,y,z) /* debugging output */
24: #else
25: #define KBDEBUG(x) /* no output */
26: #define KBDEBUG2(x,y) /* no output */
27: #define KBDEBUG3(x,y,z) /* no output */
28: #endif
29:
30: /*
31: * values for kbstate
32: */
33: #define KB_IDLE 0 /* nothing going on right now */
34: #define KB_SINGLE 1 /* sent a single byte cmd to the kbd */
35: #define KB_DOUBLE_1 2 /* sent 1st byte of 2-byte cmd to kbd */
36: #define KB_DOUBLE_2 3 /* sent 2nd byte of 2-byte cmd to kbd */
37:
38: /*
39: * patchable params for non-standard keyboards
40: */
41: int KBDATA = 0x60; /* Keyboard data */
42: int KBCTRL = 0x61; /* Keyboard control */
43: int KBSTS_CMD = 0x64; /* Keyboard status/command */
44: int KBFLAG = 0x80; /* Keyboard reset flag */
45: int KBBOOT = 1; /* 0: disallow reboot from keyboard */
46: int KBTIMEOUT = 10000; /* shouldn't need this much */
47: int KBCMDBYTE = 0x05; /* no translation */
48:
49: /*
50: * KBSTATUS bits
51: */
52: #define STS_OBUF_FULL 0x01 /* kbd output buffer full */
53: #define STS_IBUF_FULL 0x02 /* kbd input buffer full */
54: #define STS_SYSTEM 0x04
55: #define STS_CMD_DATA 0x08 /* 1: command or status */
56: #define STS_INHIBIT 0x10 /* 0: keyboard inhibited */
57: #define STS_AUX_OBUF_FULL 0x20
58: #define STS_TIMEOUT 0x40 /* general timeout */
59: #define STS_PAR_ERR 0x80 /* parity error */
60:
61: /*
62: * The following are magic commands which read from or write to the
63: * controller command byte. These get output to the KBSTS_CMD port.
64: */
65: #define C_READ_CMD 0x20 /* read controller command byte */
66: #define C_WRITE_CMD 0x60 /* write controller command byte */
67: #define C_TRANSLATE 0x40 /* translate enable bit in cmd byte */
68:
69: /*
70: * Globals:
71: * The 286 keyboard mapping table is too large to fit into kernel data space,
72: * so we need to allocate a segment to it. 386 is easy.
73: * The function keys tend to be small and tend to change substantially
74: * more often than the mapping table, so we keep them in the kernel data space.
75: */
76: static unsigned shift; /* state of all shift/lock keys */
77: static unsigned char **funkeyp = 0; /* ptr to array of func. keys ptrs */
78: static FNKEY *fnkeys = 0; /* pointer to structure of values */
79: static unsigned fklength; /* length of k_fnval field in fnkeys */
80: static unsigned prev_cmd; /* previous command sent to KBD */
81: static unsigned cmd2; /* 2nd byte of command to KBD */
82: static unsigned sh_index; /* shift/lock state index */
83: #if COH386
84: static KBTBL kb[MAX_KEYS]; /* keyboard table */
85: #else
86: static SEG *kbsegp; /* keyboard table segment */
87: #endif
88:
89: /*
90: * State variables.
91: */
92: int islock; /* Keyboard locked flag */
93: int isbusy; /* Raw input conversion busy */
94: static char table_loaded; /* true == keyboard table resident */
95: static char fk_loaded; /* true == function keys resident */
96: static int kbstate = KB_IDLE; /* current keyboard state */
97:
98: /*
99: * Functions.
100: */
101: int isrint();
102: int istime();
103: void isbatch();
104: int mmstart();
105: int isopen();
106: int isclose();
107: int isread();
108: int mmwrite();
109: int isioctl();
110: void mmwatch();
111: int isload();
112: int isuload();
113: int ispoll();
114: int nulldev();
115: int nonedev();
116: int updleds();
117:
118: /*
119: * Configuration table.
120: */
121: CON iscon ={
122: DFCHR|DFPOL, /* Flags */
123: KB_MAJOR, /* Major index */
124: isopen, /* Open */
125: isclose, /* Close */
126: nulldev, /* Block */
127: isread, /* Read */
128: mmwrite, /* Write */
129: isioctl, /* Ioctl */
130: nulldev, /* Powerfail */
131: mmwatch, /* Timeout */
132: isload, /* Load */
133: isuload, /* Unload */
134: ispoll /* Poll */
135: };
136:
137: /*
138: * Terminal structure.
139: */
140: TTY istty = {
141: {0}, {0}, 0, mmstart, NULL, 0, 0
142: };
143:
144: /*
145: * Load entry point.
146: */
147: isload()
148: {
149: kbstate = KB_IDLE;
150: table_loaded = 0; /* no keyboard table yet */
151: fk_loaded = 0; /* no Fn keys yet */
152:
153: /*
154: * Enable mmwatch() invocation every second.
155: */
156: drvl[KB_MAJOR].d_time = 1;
157:
158: /*
159: * Seize keyboard interrupt.
160: */
161: setivec(ISVEC, isrint);
162:
163: /*
164: * Initiailize video display.
165: */
166: mmstart( &istty );
167:
168: #if !COH386
169: /*
170: * Allocate a 286 segment to store the in-core keyboard table.
171: * This would be a lot more convenient in kernel data space,
172: * but small model COHERENT doesn't have that luxury.
173: */
174: kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH);
175: if (kbsegp == (SEG *)0)
176: printf("kb: unable to allocate keyboard table segment\n");
177: #endif
178: fklength = 0;
179: KBDEBUG("Exiting kbload()\n");
180: }
181:
182: /*
183: * Unload entry point.
184: */
185: isuload()
186: {
187: if (kbstate != KB_IDLE)
188: printf("kb: keyboard busy during unload\n");
189: clrivec(ISVEC);
190: #if !COH386
191: if (kbsegp != (SEG *)0) {
192: table_loaded = 0;
193: sfree(kbsegp);
194: }
195: #endif
196: }
197:
198: /*
199: * Open routine.
200: */
201: isopen(dev)
202: dev_t dev;
203: {
204: register int s;
205:
206: KBDEBUG(" kbopen()");
207: if (minor(dev) != 0) {
208: u.u_error = ENXIO;
209: return;
210: }
211: if ((istty.t_flags&T_EXCL) != 0 && !super()) {
212: u.u_error = ENODEV;
213: return;
214: }
215: ttsetgrp(&istty, dev);
216:
217: s = sphi();
218: if (istty.t_open++ == 0) {
219: istty.t_flags = T_CARR; /* indicate "carrier" */
220: ttopen(&istty);
221: }
222: spl(s);
223: #if 0
224: updleds(); /* update keyboard status LEDS */
225: #endif
226: }
227:
228: /*
229: * Close a tty.
230: */
231: isclose(dev)
232: {
233: register int s;
234:
235: s = sphi();
236: if (--istty.t_open == 0) {
237: ttclose(&istty);
238: }
239: spl(s);
240: }
241:
242: /*
243: * Read routine.
244: */
245: isread(dev, iop)
246: dev_t dev;
247: IO *iop;
248: {
249: ttread(&istty, iop, 0);
250: if (istty.t_oq.cq_cc)
251: mmtime(&istty);
252: }
253:
254: /*
255: * Ioctl routine.
256: * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported.
257: */
258: isioctl(dev, com, vec)
259: dev_t dev;
260: struct sgttyb *vec;
261: {
262: register int s;
263:
264: switch (com) {
265: case TIOCSETF:
266: case TIOCGETF:
267: isfunction(com, (char *)vec);
268: break;
269: case TIOCSETKBT:
270: issettable(vec);
271: break;
272: case TIOCGETKBT:
273: isgettable(vec);
274: break;
275: default: /* pass to TTY driver */
276: s = sphi();
277: ttioctl(&istty, com, vec);
278: spl(s);
279: break;
280: }
281: }
282:
283: /*
284: * Set the in-core keyboard mapping table.
285: * The table is sorted by scan code prior to calling ioctl().
286: * All unused table entries (holes in the scan code map) have
287: * a zero for the k_key field.
288: * This makes key lookup at interrupt time fast by using the scan code
289: * as an index into the table.
290: */
291: issettable(vec)
292: char *vec;
293: {
294: register unsigned i;
295: register int s;
296: int timeout;
297: static KBTBL this_key; /* current key from kbd table */
298: unsigned int cmd_byte;
299: #if !COH386
300: register faddr_t faddr; /* address of keyboard table */
301: #endif
302:
303: KBDEBUG(" TIOCSETKBT");
304: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */
305: kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */
306: #if !COH386
307: faddr = kbsegp->s_faddr;
308: #endif
309: for (i = 0; i < MAX_KEYS; ++i) {
310: ukcopy(vec, &this_key, sizeof(this_key));
311: #if COH386
312: kb[i] = this_key; /* store away */
313: #else
314: kfcopy(&this_key, faddr, sizeof(this_key));
315: faddr += sizeof(this_key);
316: #endif
317: vec += sizeof(this_key);
318: if (this_key.k_key != i && this_key.k_key != 0) {
319: printf("kb: incorrect or unsorted table entry %d\n", i);
320: u.u_error = EBADFMT;
321: return;
322: }
323: if (this_key.k_key != i)
324: continue; /* no key */
325: switch (this_key.k_flags&TMODE) {
326: case T: /* typematic */
327: kb_cmd2(K_KEY_T_CMD, i);
328: break;
329: case M: /* make only */
330: kb_cmd2(K_KEY_M_CMD, i);
331: break;
332: case MB: /* make/break */
333: kb_cmd2(K_KEY_MB_CMD, i);
334: break;
335: case TMB: /* typematic make/break */
336: break; /* this is the default */
337: default:
338: printf("kb: bad key mode\n");
339: }
340: }
341: updleds();
342: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */
343: kb_cmd(K_ENABLE_CMD); /* start scanning */
344: /*
345: * The following code disables translation from the on-board
346: * keyboard/aux controller. Without disabling translation, the
347: * received scan codes still look like code set 1 codes even
348: * though we put the keyboard controller in scan code set 3.
349: * Yes, this is progress....
350: */
351: #if 0
352: while (inb(KBSTS_CMD) & STS_IBUF_FULL)
353: ;
354: outb(KBSTS_CMD, C_READ_CMD); /* read controller cmd byte */
355: while (!(inb(KBSTS_CMD) & STS_OBUF_FULL))
356: ;
357: cmd_byte = inb(KBDATA);
358: KBDEBUG2(" cmd_byte=%x", cmd_byte);
359: #endif
360: timeout = KBTIMEOUT;
361: s = sphi();
362: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
363: ;
364: outb(KBSTS_CMD, C_WRITE_CMD); /* write controller cmd byte */
365: for (timeout = 50; --timeout > 0; )
366: ;
367: timeout = KBTIMEOUT;
368: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
369: ;
370: outb(KBDATA, KBCMDBYTE); /* turn off translation */
371: timeout = KBTIMEOUT;
372: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
373: ;
374: spl(s);
375: #if DEBUG
376: kb_cmd2(K_SCANCODE_CMD, 0); /* query s.c. mode */
377: #endif
378: ++table_loaded;
379: }
380:
381: /*
382: * Get the in-core keyboard mapping table and pass it to the user.
383: */
384: isgettable(vec)
385: char *vec;
386: {
387: #if COH386
388: KBDEBUG(" TIOCGETKBT");
389: kucopy(kb, vec, sizeof(kb));
390: #else
391: register unsigned i;
392: register faddr_t faddr; /* address of keyboard table */
393: static KBTBL this_key; /* current key from kbd table */
394:
395: KBDEBUG(" TIOCGETKBT");
396: faddr = kbsegp->s_faddr;
397: for (i = 0; i < MAX_KEYS; ++i) {
398: fkcopy( faddr, &this_key, sizeof(this_key));
399: kucopy( &this_key, vec, sizeof(this_key));
400: faddr += sizeof(this_key);
401: vec += sizeof(this_key);
402: }
403: #endif
404: }
405:
406:
407: /*
408: * Set and receive the function keys.
409: */
410: isfunction(c, v)
411: int c;
412: FNKEY *v;
413: {
414: register unsigned char *cp;
415: register unsigned i;
416: unsigned char numkeys = 0;
417:
418: if (c == TIOCGETF) {
419: KBDEBUG(" TIOCGETF");
420: if (!fk_loaded)
421: u.u_error = EINVAL;
422: else
423: kucopy(fnkeys, v, fklength); /* copy ours to user */
424: } else { /* TIOCSETF */
425: /*
426: * If we had a previous function key arena, free it up.
427: * Since we don't know how large the function key arena will
428: * be, we must size it in the user data space prior to
429: * (re)kalloc()'ing it. This is ugly, but a helluva lot better
430: * than the old driver which used a hard coded limit of 150!
431: */
432: KBDEBUG(" TIOCSETF");
433: fk_loaded = 0;
434: if (fnkeys != (FNKEY *)0)
435: kfree(fnkeys); /* free old arena */
436: if (funkeyp != NULL)
437: kfree(funkeyp); /* free old ptr array */
438: ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys));
439: fklength = sizeof(FNKEY);
440: cp = v->k_fnval;
441: for (i = 0; i < numkeys; i++) {
442: do {
443: ++fklength;
444: } while (getubd(cp++) != DELIM);
445: }
446: fnkeys = (FNKEY *)kalloc(fklength);
447: funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *));
448: if (fnkeys == (FNKEY *)0 || funkeyp == NULL) {
449: if (fnkeys != (FNKEY *)0) {
450: kfree(fnkeys);
451: fnkeys = 0;
452: }
453: if (funkeyp != NULL) {
454: kfree(funkeyp);
455: funkeyp = 0;
456: }
457: u.u_error = ENOMEM;
458: return;
459: }
460: cp = fnkeys->k_fnval; /* point to Fn ... */
461: v = v->k_fnval; /* ... key arena */
462: for (i = 0; i < numkeys; i++) {
463: funkeyp[i] = cp; /* save pointer */
464: while ((*cp++ = getubd(v++)) != DELIM) /* copy key */
465: ;
466: }
467: fnkeys->k_nfkeys = numkeys;
468: fk_loaded = 1;
469: }
470: }
471:
472:
473: /*
474: * Poll routine.
475: */
476: ispoll( dev, ev, msec )
477: dev_t dev;
478: int ev;
479: int msec;
480: {
481: /*
482: * Priority polls not supported.
483: */
484: ev &= ~POLLPRI;
485:
486: /*
487: * Input poll failure.
488: */
489: if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {
490: if ( msec != 0 )
491: pollopen( &istty.t_ipolls );
492: /*
493: * Second look AFTER enabling monitor, avoiding interrupt race.
494: */
495: if ( istty.t_iq.cq_cc == 0 )
496: ev &= ~POLLIN;
497: }
498: return ev;
499: }
500:
501: /*
502: * Receive interrupt.
503: */
504: isrint()
505: {
506: register unsigned c;
507: register unsigned r;
508: static char keyup;
509:
510: /*
511: * Schedule raw input handler if not already active.
512: */
513: if ( !isbusy ) {
514: defer( isbatch, &istty );
515: isbusy = 1;
516: }
517:
518: /*
519: * Pull character from the data
520: * port. Pulse the KBFLAG in the control
521: * port to reset the data buffer.
522: */
523: r = inb(KBDATA) & 0xFF;
524: c = inb(KBCTRL);
525: outb(KBCTRL, c|KBFLAG);
526: outb(KBCTRL, c);
527:
528: /*
529: * check returned value from keyboard to see if it's a command
530: * or status back to us. If not, it we assume that it's a key code.
531: */
532: KBDEBUG2(" intr(%x)", r);
533: switch (r) {
534: case K_BREAK:
535: keyup = 1; /* key going up */
536: break;
537: case K_ECHO_R:
538: case K_BAT_OK:
539: break; /* very nice, but ignored */
540: case K_BAT_BAD:
541: printf("kb: keyboard BAT failed\n");
542: break;
543: case K_RESEND:
544: KBDEBUG("\nkb: request to resend command\n");
545: outb(KBDATA, prev_cmd);
546: break;
547: case K_OVERRUN_23:
548: printf("kb: keyboard buffer overrun\n");
549: break;
550: case K_ACK:
551: /*
552: * we received an ACKnowledgement from the keyboard.
553: * advance the state machine and continue.
554: */
555: KBDEBUG(" ACK");
556: switch (kbstate) {
557: case KB_IDLE: /* shouldn't happen */
558: printf("kb: ACK while keyboard idle\n");
559: break;
560: case KB_SINGLE: /* done with 1-byte command */
561: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */
562: kbstate = KB_IDLE;
563: wakeup(&kbstate);
564: break;
565: case KB_DOUBLE_1:
566: kbstate = KB_DOUBLE_2;
567: outb(KBDATA, cmd2);
568: break;
569: default:
570: printf("kb: bad kbstate %d\n", kbstate);
571: break;
572: }
573: break;
574: default:
575: process_key(r, keyup);
576: keyup = 0;
577: }
578: }
579:
580: /*
581: * Process a key given its scan code and direction.
582: *
583: * In this table driven version of the keyboard driver, we trade off the
584: * code complexity associated with all the black magic that used to be
585: * performed on a per-key basis with the increased memory requirements
586: * associated with the table driven approach.
587: */
588: process_key( key, up)
589: unsigned key;
590: int up;
591: {
592: register unsigned char *cp;
593: KBTBL key_vals; /* table values for this key */
594: unsigned val;
595: unsigned char flags;
596:
597: KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down"));
598: if (!table_loaded)
599: return; /* throw away key */
600: #if COH386
601: key_vals = kb[key];
602: #else
603: fkcopy( kbsegp->s_faddr + (key * sizeof(KBTBL)),
604: &key_vals, sizeof(key_vals));
605: #endif
606: if (key_vals.k_key != key) /* empty entry */
607: return;
608: flags = key_vals.k_flags;
609:
610: if (flags & S) { /* some shift/lock key ? */
611: switch (key_vals.k_val[BASE]) {
612: case caps:
613: case num:
614: if (!up) {
615: shift ^= (1 << key_vals.k_val[BASE]);
616: updleds2();
617: }
618: break;
619: case scroll:
620: if (!up) {
621: shift ^= (1 << key_vals.k_val[BASE]);
622: updleds2();
623: if (!(istty.t_sgttyb.sg_flags&RAWIN)) {
624: if (istty.t_flags & T_STOP) {
625: isin(istty.t_tchars.t_startc);
626: } else {
627: isin(istty.t_tchars.t_stopc);
628: }
629: }
630: }
631: break;
632: default:
633: if (up)
634: shift &= ~(1 << key_vals.k_val[BASE]);
635: else
636: shift |= (1 << key_vals.k_val[BASE]);
637: break;
638: }
639: /*
640: * Calculate the shift index based upon the state of
641: * the shift and lock keys.
642: */
643: sh_index = BASE; /* default condition */
644: if (shift & (1 << altgr))
645: sh_index = ALT_GR;
646: else {
647: if (shift & ((1 << lalt)|(1 << ralt)))
648: sh_index |= ALT;
649: if (shift & ((1 << lctrl)|(1 << rctrl)))
650: sh_index |= CTRL;
651: if (shift & ((1 << lshift)|(1 << rshift)))
652: sh_index |= SHIFT;
653: }
654: return;
655: } /* if (flags & S) */
656:
657: /*
658: * If the tty is not open or the key has no value in the current
659: * shift state, the key is just tossed away.
660: */
661: if (up || !istty.t_open || key_vals.k_val[sh_index] == none)
662: return;
663: if (((flags & C) && (shift & (1 << caps)))
664: || ((flags & N) && (shift & (1 << num))))
665: val = key_vals.k_val[sh_index^SHIFT];
666: else
667: val = key_vals.k_val[sh_index];
668:
669: /*
670: * Check for function key or special key implemented as
671: * a function key (reboot == f0, tab and back-tab, etc).
672: */
673: if (flags & F) {
674: if (val == 0 && !up && KBBOOT)
675: boot();
676: if (!fk_loaded || val >= fnkeys->k_nfkeys)
677: return;
678: if ((cp = funkeyp[val]) == NULL) /* has a value? */
679: return;
680: while (*cp != DELIM)
681: isin(*cp++); /* queue up Fn key value */
682: return;
683: }
684:
685: /*
686: * Normal key processing.
687: */
688: isin(val); /* send the char */
689: return;
690: }
691:
692: /**
693: *
694: * void
695: * ismmfunc( c ) -- process keyboard related output escape sequences
696: * char c;
697: */
698: void
699: ismmfunc(c)
700: register int c;
701: {
702: switch (c) {
703: case 't': /* Enter numlock */
704: shift |= (1 << num);
705: updleds(); /* update LED status */
706: break;
707: case 'u': /* Leave numlock */
708: shift &= ~(1 << num);
709: updleds(); /* update LED status */
710: break;
711: case '=': /* Enter alternate keypad -- ignored */
712: case '>': /* Exit alternate keypad -- ignored */
713: break;
714: case 'c': /* Reset terminal */
715: islock = 0;
716: break;
717: }
718: }
719:
720: /**
721: *
722: * void
723: * isin( c ) -- append character to raw input silo
724: * char c;
725: */
726: static
727: isin( c )
728: register int c;
729: {
730: int cache_it = 1;
731: TTY * tp = &istty;
732:
733: /*
734: * If using software incoming flow control, process and
735: * discard t_stopc and t_startc.
736: */
737: if (!ISRIN) {
738: if (ISSTOP) {
739: if ((tp->t_flags&T_STOP) == 0)
740: tp->t_flags |= T_STOP;
741: cache_it = 0;
742: }
743: if (ISSTART) {
744: tp->t_flags &= ~T_STOP;
745: ttstart(tp);
746: cache_it = 0;
747: }
748: }
749:
750: /*
751: * Cache received character.
752: */
753: if (cache_it) {
754: istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;
755:
756: if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
757: istty.t_rawin.si_ix = 0;
758: }
759: }
760:
761: /**
762: *
763: * void
764: * isbatch() -- raw input conversion routine
765: *
766: * Action: Enable the video display.
767: * Canonize the raw input silo.
768: *
769: * Notes: isbatch() was scheduled as a deferred process by isrint().
770: */
771: static void
772: isbatch( tp )
773: register TTY * tp;
774: {
775: register int c;
776: static int lastc;
777:
778: /*
779: * Ensure video display is enabled.
780: */
781: mm_von();
782: isbusy = 0;
783:
784: /*
785: * Process all cached characters.
786: */
787: while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
788: /*
789: * Get next cached char.
790: */
791: c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];
792:
793: if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
794: tp->t_rawin.si_ox = 0;
795: else
796: tp->t_rawin.si_ox++;
797:
798: if ( (islock == 0) || ISINTR || ISQUIT ) {
799: ttin( tp, c );
800: } else if ( (c == 'b') && (lastc == '\033') ) {
801: islock = 0;
802: ttin( tp, lastc );
803: ttin( tp, c );
804: } else if ( (c == 'c') && (lastc == '\033') ) {
805: ttin( tp, lastc );
806: ttin( tp, c );
807: } else
808: putchar('\007');
809: lastc = c;
810: }
811: }
812:
813: /*
814: * update the keyboard status LEDS.
815: * we chose the shift/lock key positions so this would be easy.
816: * this flavor of routine is called while processing a system call on
817: * behalf of the user.
818: */
819: updleds()
820: {
821: kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7);
822: }
823:
824: /*
825: * same as above, but callable from interrupt routines and other places
826: * which cannot sleep() waiting for the state machine to go idle.
827: */
828: updleds2()
829: {
830: register timeout;
831: register int s;
832:
833: timeout = KBTIMEOUT;
834: s = sphi();
835: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
836: ;
837: kbstate = KB_DOUBLE_1;
838: cmd2 = (shift >> 1) & 0x7;
839: prev_cmd = K_LED_CMD;
840: outb(KBDATA, K_LED_CMD);
841: spl(s);
842: }
843:
844: /*
845: * unlock the scroll in case an interrupt character is received
846: */
847: kbunscroll()
848: {
849: shift &= ~(1 << scroll);
850: updleds();
851: }
852:
853: /*
854: * ship a single byte command to the keyboard
855: */
856: kb_cmd(cmd)
857: unsigned cmd;
858: {
859: register int timeout;
860: register int s;
861:
862: s = sphi();
863: KBDEBUG2(" kb_cmd(%x)", cmd);
864: while (kbstate != KB_IDLE)
865: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
866: kbstate = KB_SINGLE;
867: timeout = KBTIMEOUT;
868: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
869: ;
870: if (!timeout)
871: printf("kb: command timeout\n");
872: else {
873: outb(KBDATA, cmd);
874: while (kbstate != KB_IDLE)
875: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
876: }
877: spl(s);
878: }
879:
880: /*
881: * ship a two byte command to the keyboard
882: */
883: kb_cmd2(cmd, arg)
884: unsigned cmd, arg;
885: {
886: register int timeout;
887: register int s;
888:
889: s = sphi();
890: KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg);
891: while (kbstate != KB_IDLE)
892: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
893: kbstate = KB_DOUBLE_1;
894: cmd2 = arg;
895: prev_cmd = cmd;
896: timeout = KBTIMEOUT;
897: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
898: ;
899: if (!timeout)
900: printf("kb: command timeout\n");
901: else {
902: outb(KBDATA, cmd);
903: while (kbstate != KB_IDLE)
904: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
905: }
906: spl(s);
907: }
908:
909: /* End of nkb.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.