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