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