|
|
1.1 root 1: /*
2: * Copyright (c) 1988 University of Utah.
3: * Copyright (c) 1990 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * This code is derived from software contributed to Berkeley by
7: * the Systems Programming Group of the University of Utah Computer
8: * Science Department.
9: *
10: * Redistribution is only permitted until one year after the first shipment
11: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
12: * binary forms are permitted provided that: (1) source distributions retain
13: * this entire copyright notice and comment, and (2) distributions including
14: * binaries display the following acknowledgement: This product includes
15: * software developed by the University of California, Berkeley and its
16: * contributors'' in the documentation or other materials provided with the
17: * distribution and in all advertising materials mentioning features or use
18: * of this software. Neither the name of the University nor the names of
19: * its contributors may be used to endorse or promote products derived from
20: * this software without specific prior written permission.
21: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
22: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
23: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24: *
25: * from: Utah $Hdr: hil.c 1.33 89/12/22$
26: *
27: * @(#)hil.c 7.4 (Berkeley) 6/22/90
28: */
29:
30: #include "param.h"
31: #include "conf.h"
32: #include "user.h"
33: #include "proc.h"
34: #include "ioctl.h"
35: #include "file.h"
36: #include "tty.h"
37: #include "systm.h"
38: #include "uio.h"
39: #include "kernel.h"
40: #include "mapmem.h"
41:
42: #include "hilreg.h"
43: #include "hilioctl.h"
44: #include "hilvar.h"
45: #include "kbdmap.h"
46:
47: #include "machine/cpu.h"
48:
49: struct hilloop hil0;
50: struct _hilbell default_bell = { BELLDUR, BELLFREQ };
51:
52: #ifdef MAPMEM
53: int hilqfork(), hilqvfork(), hilqexit();
54: struct mapmemops hilqops = { hilqfork, hilqvfork, hilqexit, hilqexit };
55: #endif
56:
57: #ifdef DEBUG
58: int hildebug = 0;
59: #define HDB_FOLLOW 0x01
60: #define HDB_MMAP 0x02
61: #define HDB_MASK 0x04
62: #define HDB_CONFIG 0x08
63: #define HDB_KEYBOARD 0x10
64: #define HDB_IDMODULE 0x20
65: #define HDB_EVENTS 0x80
66: #endif
67:
68: /* symbolic sleep message strings */
69: char hilin[] = "hilin";
70:
71: hilinit()
72: {
73: register struct hilloop *hilp = &hil0; /* XXX */
74: register int i;
75:
76: /*
77: * Initialize loop information
78: */
79: hilp->hl_addr = HILADDR;
80: hilp->hl_cmdending = FALSE;
81: hilp->hl_actdev = hilp->hl_cmddev = 0;
82: hilp->hl_cmddone = FALSE;
83: hilp->hl_cmdbp = hilp->hl_cmdbuf;
84: hilp->hl_pollbp = hilp->hl_pollbuf;
85: hilp->hl_kbddev = 0;
86: hilp->hl_kbdlang = KBD_DEFAULT;
87: hilp->hl_kbdflags = 0;
88: /*
89: * Clear all queues and device associations with queues
90: */
91: for (i = 0; i < NHILQ; i++) {
92: hilp->hl_queue[i].hq_eventqueue = NULL;
93: hilp->hl_queue[i].hq_procp = NULL;
94: hilp->hl_queue[i].hq_devmask = 0;
95: }
96: for (i = 0; i < NHILD; i++)
97: hilp->hl_device[i].hd_qmask = 0;
98: hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO);
99: /*
100: * Reset the loop hardware, and collect keyboard/id info
101: */
102: hilreset(hilp);
103: hilinfo(hilp);
104: kbdenable();
105: }
106:
107: hilopen(dev, flags)
108: dev_t dev;
109: {
110: struct proc *p = u.u_procp; /* XXX */
111: register struct hilloop *hilp = &hil0; /* XXX */
112: register struct hilloopdev *dptr;
113: u_char device = HILUNIT(dev);
114:
115: #ifdef DEBUG
116: if (hildebug & HDB_FOLLOW)
117: printf("hilopen(%d): device %x\n", p->p_pid, device);
118: #endif
119:
120: if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0)
121: return(ENXIO);
122:
123: dptr = &hilp->hl_device[device];
124: if ((dptr->hd_flags & HIL_ALIVE) == 0)
125: return(ENODEV);
126:
127: /*
128: * Pseudo-devices cannot be read, nothing more to do.
129: */
130: if (dptr->hd_flags & HIL_PSEUDO)
131: return(0);
132:
133: /*
134: * Open semantics:
135: * 1. Open devices have only one of HIL_READIN/HIL_QUEUEIN.
136: * 2. HPUX processes always get read syscall interface and
137: * must have exclusive use of the device.
138: * 3. BSD processes default to shared queue interface.
139: * Multiple processes can open the device.
140: */
141: if (p->p_flag & SHPUX) {
142: if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN))
143: return(EBUSY);
144: dptr->hd_flags |= HIL_READIN;
145: } else {
146: if (dptr->hd_flags & HIL_READIN)
147: return(EBUSY);
148: dptr->hd_flags |= HIL_QUEUEIN;
149: }
150: if (flags & FNDELAY)
151: dptr->hd_flags |= HIL_NOBLOCK;
152: /*
153: * It is safe to flush the read buffer as we are guarenteed
154: * that no one else is using it.
155: */
156: ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);
157:
158: send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL);
159: /*
160: * Opened the keyboard, put in raw mode.
161: */
162: (void) splhil();
163: if (device == hilp->hl_kbddev) {
164: u_char mask = 0;
165: send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);
166: hilp->hl_kbdflags |= KBD_RAW;
167: #ifdef DEBUG
168: if (hildebug & HDB_KEYBOARD)
169: printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev);
170: #endif
171: }
172: (void) spl0();
173: return (0);
174: }
175:
176: /* ARGSUSED */
177: hilclose(dev, flags)
178: dev_t dev;
179: {
180: struct proc *p = u.u_procp; /* XXX */
181: register struct hilloop *hilp = &hil0; /* XXX */
182: register struct hilloopdev *dptr;
183: register int i;
184: u_char device = HILUNIT(dev);
185: char mask, lpctrl;
186:
187: #ifdef DEBUG
188: if (hildebug & HDB_FOLLOW)
189: printf("hilclose(%d): device %x\n", p->p_pid, device);
190: #endif
191:
192: dptr = &hilp->hl_device[device];
193: if (device && (dptr->hd_flags & HIL_PSEUDO))
194: return (0);
195:
196: if ((p->p_flag & SHPUX) == 0) {
197: /*
198: * If this is the loop device,
199: * free up all queues belonging to this process.
200: */
201: if (device == 0) {
202: for (i = 0; i < NHILQ; i++)
203: if (hilp->hl_queue[i].hq_procp == p)
204: (void) hilqfree(i);
205: } else {
206: mask = ~hildevmask(device);
207: (void) splhil();
208: for (i = 0; i < NHILQ; i++)
209: if (hilp->hl_queue[i].hq_procp == p) {
210: dptr->hd_qmask &= ~hilqmask(i);
211: hilp->hl_queue[i].hq_devmask &= mask;
212: }
213: (void) spl0();
214: }
215: }
216: /*
217: * Always flush the read buffer
218: */
219: dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK);
220: ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);
221: /*
222: * Set keyboard back to cooked mode when closed.
223: */
224: (void) splhil();
225: if (device && device == hilp->hl_kbddev) {
226: mask = 1 << (hilp->hl_kbddev - 1);
227: send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);
228: hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2);
229: /*
230: * XXX: We have had trouble with keyboards remaining raw
231: * after close due to the LPC_KBDCOOK bit getting cleared
232: * somewhere along the line. Hence we check and reset
233: * LPCTRL if necessary.
234: */
235: send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl);
236: if ((lpctrl & LPC_KBDCOOK) == 0) {
237: printf("hilclose: bad LPCTRL %x, reset to %x\n",
238: lpctrl, lpctrl|LPC_KBDCOOK);
239: lpctrl |= LPC_KBDCOOK;
240: send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL,
241: &lpctrl, 1, NULL);
242: }
243: #ifdef DEBUG
244: if (hildebug & HDB_KEYBOARD)
245: printf("hilclose: keyboard %d cooked\n",
246: hilp->hl_kbddev);
247: #endif
248: kbdenable();
249: }
250: (void) spl0();
251: return (0);
252: }
253:
254: /*
255: * Read interface to HIL device.
256: */
257: hilread(dev, uio)
258: dev_t dev;
259: register struct uio *uio;
260: {
261: struct hilloop *hilp = &hil0; /* XXX */
262: register struct hilloopdev *dptr;
263: register int cc;
264: u_char device = HILUNIT(dev);
265: char buf[HILBUFSIZE];
266: int error;
267:
268: #if 0
269: /*
270: * XXX: Don't do this since HP-UX doesn't.
271: *
272: * Check device number.
273: * This check is necessary since loop can reconfigure.
274: */
275: if (device > hilp->hl_maxdev)
276: return(ENODEV);
277: #endif
278:
279: dptr = &hilp->hl_device[device];
280: if ((dptr->hd_flags & HIL_READIN) == 0)
281: return(ENODEV);
282:
283: (void) splhil();
284: while (dptr->hd_queue.c_cc == 0) {
285: if (dptr->hd_flags & HIL_NOBLOCK) {
286: spl0();
287: return(EWOULDBLOCK);
288: }
289: dptr->hd_flags |= HIL_ASLEEP;
290: if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) {
291: (void) spl0();
292: return (error);
293: }
294: }
295: (void) spl0();
296:
297: error = 0;
298: while (uio->uio_resid > 0 && error == 0) {
299: cc = hilq_to_b(&dptr->hd_queue, buf,
300: MIN(uio->uio_resid, HILBUFSIZE));
301: if (cc <= 0)
302: break;
303: error = uiomove(buf, cc, uio);
304: }
305: return(error);
306: }
307:
308: hilioctl(dev, cmd, data, flag)
309: dev_t dev;
310: caddr_t data;
311: {
312: struct proc *p = u.u_procp; /* XXX */
313: register struct hilloop *hilp = &hil0; /* XXX */
314: char device = HILUNIT(dev);
315: struct hilloopdev *dptr;
316: register int i;
317: u_char hold;
318: int error;
319:
320: #ifdef DEBUG
321: if (hildebug & HDB_FOLLOW)
322: printf("hilioctl(%d): dev %x cmd %x\n",
323: p->p_pid, device, cmd);
324: #endif
325:
326: dptr = &hilp->hl_device[device];
327: if ((dptr->hd_flags & HIL_ALIVE) == 0)
328: return (ENODEV);
329:
330: /*
331: * Don't allow hardware ioctls on virtual devices.
332: * Note that though these are the BSD names, they have the same
333: * values as the HP-UX equivalents so we catch them as well.
334: */
335: if (dptr->hd_flags & HIL_PSEUDO) {
336: switch (cmd) {
337: case HILIOCSC:
338: case HILIOCID:
339: case HILIOCRN:
340: case HILIOCRS:
341: case HILIOCED:
342: return(ENODEV);
343:
344: /*
345: * XXX: should also return ENODEV but HP-UX compat
346: * breaks if we do. They work ok right now because
347: * we only recognize one keyboard on the loop. This
348: * will have to change if we remove that restriction.
349: */
350: case HILIOCAROFF:
351: case HILIOCAR1:
352: case HILIOCAR2:
353: break;
354:
355: default:
356: break;
357: }
358: }
359:
360: #ifdef HPUXCOMPAT
361: if (p->p_flag & SHPUX)
362: return(hpuxhilioctl(dev, cmd, data, flag));
363: #endif
364:
365: hilp->hl_cmdbp = hilp->hl_cmdbuf;
366: bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
367: hilp->hl_cmddev = device;
368: error = 0;
369: switch (cmd) {
370:
371: case HILIOCSBP:
372: /* Send four data bytes to the tone gererator. */
373: send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
374: /* Send the trigger beeper command to the 8042. */
375: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
376: break;
377:
378: case HILIOCRRT:
379: /* Transfer the real time to the 8042 data buffer */
380: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
381: /* Read each byte of the real time */
382: for (i = 0; i < 5; i++) {
383: send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
384: 0, &hold);
385: data[4-i] = hold;
386: }
387: break;
388:
389: case HILIOCRT:
390: for (i = 0; i < 4; i++) {
391: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
392: NULL, 0, &hold);
393: data[i] = hold;
394: }
395: break;
396:
397: case HILIOCID:
398: case HILIOCSC:
399: case HILIOCRN:
400: case HILIOCRS:
401: case HILIOCED:
402: send_hildev_cmd(hilp, device, (cmd & 0xFF));
403: bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
404: break;
405:
406: case HILIOCAROFF:
407: case HILIOCAR1:
408: case HILIOCAR2:
409: if (hilp->hl_kbddev) {
410: hilp->hl_cmddev = hilp->hl_kbddev;
411: send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
412: hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
413: if (cmd == HILIOCAR1)
414: hilp->hl_kbdflags |= KBD_AR1;
415: else if (cmd == HILIOCAR2)
416: hilp->hl_kbdflags |= KBD_AR2;
417: }
418: break;
419:
420: case HILIOCBEEP:
421: hilbeep(hilp, (struct _hilbell *)data);
422: break;
423:
424: case FIONBIO:
425: dptr = &hilp->hl_device[device];
426: if (*(int *)data)
427: dptr->hd_flags |= HIL_NOBLOCK;
428: else
429: dptr->hd_flags &= ~HIL_NOBLOCK;
430: break;
431:
432: /*
433: * FIOASYNC must be present for FIONBIO above to work!
434: * (See fcntl in kern_descrip.c).
435: */
436: case FIOASYNC:
437: break;
438:
439: case HILIOCALLOCQ:
440: error = hilqalloc((struct hilqinfo *)data);
441: break;
442:
443: case HILIOCFREEQ:
444: error = hilqfree(((struct hilqinfo *)data)->qid);
445: break;
446:
447: case HILIOCMAPQ:
448: error = hilqmap(*(int *)data, device);
449: break;
450:
451: case HILIOCUNMAPQ:
452: error = hilqunmap(*(int *)data, device);
453: break;
454:
455: case HILIOCHPUX:
456: dptr = &hilp->hl_device[device];
457: dptr->hd_flags |= HIL_READIN;
458: dptr->hd_flags &= ~HIL_QUEUEIN;
459: break;
460:
461: case HILIOCRESET:
462: hilreset(hilp);
463: break;
464:
465: #ifdef DEBUG
466: case HILIOCTEST:
467: hildebug = *(int *) data;
468: break;
469: #endif
470:
471: default:
472: error = EINVAL;
473: break;
474:
475: }
476: hilp->hl_cmddev = 0;
477: return(error);
478: }
479:
480: #ifdef HPUXCOMPAT
481: /* ARGSUSED */
482: hpuxhilioctl(dev, cmd, data, flag)
483: dev_t dev;
484: caddr_t data;
485: {
486: register struct hilloop *hilp = &hil0; /* XXX */
487: char device = HILUNIT(dev);
488: struct hilloopdev *dptr;
489: register int i;
490: u_char hold;
491:
492: hilp->hl_cmdbp = hilp->hl_cmdbuf;
493: bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
494: hilp->hl_cmddev = device;
495: switch (cmd) {
496:
497: case HILSC:
498: case HILID:
499: case HILRN:
500: case HILRS:
501: case HILED:
502: case HILP1:
503: case HILP2:
504: case HILP3:
505: case HILP4:
506: case HILP5:
507: case HILP6:
508: case HILP7:
509: case HILP:
510: case HILA1:
511: case HILA2:
512: case HILA3:
513: case HILA4:
514: case HILA5:
515: case HILA6:
516: case HILA7:
517: case HILA:
518: send_hildev_cmd(hilp, device, (cmd & 0xFF));
519: bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
520: break;
521:
522: case HILDKR:
523: case HILER1:
524: case HILER2:
525: if (hilp->hl_kbddev) {
526: hilp->hl_cmddev = hilp->hl_kbddev;
527: send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
528: hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
529: if (cmd == HILIOCAR1)
530: hilp->hl_kbdflags |= KBD_AR1;
531: else if (cmd == HILIOCAR2)
532: hilp->hl_kbdflags |= KBD_AR2;
533: }
534: break;
535:
536: case EFTSBP:
537: /* Send four data bytes to the tone gererator. */
538: send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
539: /* Send the trigger beeper command to the 8042. */
540: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
541: break;
542:
543: case EFTRRT:
544: /* Transfer the real time to the 8042 data buffer */
545: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
546: /* Read each byte of the real time */
547: for (i = 0; i < 5; i++) {
548: send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
549: 0, &hold);
550: data[4-i] = hold;
551: }
552: break;
553:
554: case EFTRT:
555: for (i = 0; i < 4; i++) {
556: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
557: NULL, 0, &hold);
558: data[i] = hold;
559: }
560: break;
561:
562: case EFTRLC:
563: case EFTRCC:
564: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold);
565: *data = hold;
566: break;
567:
568: case EFTSRPG:
569: case EFTSRD:
570: case EFTSRR:
571: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL);
572: break;
573:
574: case EFTSBI:
575: hilbeep(hilp, (struct _hilbell *)data);
576: break;
577:
578: case FIONBIO:
579: dptr = &hilp->hl_device[device];
580: if (*(int *)data)
581: dptr->hd_flags |= HIL_NOBLOCK;
582: else
583: dptr->hd_flags &= ~HIL_NOBLOCK;
584: break;
585:
586: case FIOASYNC:
587: break;
588:
589: default:
590: hilp->hl_cmddev = 0;
591: return(EINVAL);
592: }
593: hilp->hl_cmddev = 0;
594: return(0);
595: }
596: #endif
597:
598: /*
599: * XXX: the mmap inteface for HIL devices should be rethought.
600: * We used it only briefly in conjuntion with shared queues
601: * (instead of HILIOCMAPQ ioctl). Perhaps mmap()ing a device
602: * should give a single queue per process.
603: */
604: /* ARGSUSED */
605: hilmap(dev, off, prot)
606: dev_t dev;
607: register int off;
608: {
609: #ifdef MMAP
610: struct proc *p = u.u_procp; /* XXX */
611: register struct hilloop *hilp = &hil0; /* XXX */
612: register struct hiliqueue *qp;
613: register int qnum;
614:
615: /*
616: * Only allow mmap() on loop device
617: */
618: if (HILUNIT(dev) != 0 || off >= NHILQ*sizeof(HILQ))
619: return(-1);
620: /*
621: * Determine which queue we want based on the offset.
622: * Queue must belong to calling process.
623: */
624: qp = &hilp->hl_queue[off / sizeof(HILQ)];
625: if (qp->hq_procp != p)
626: return(-1);
627:
628: off %= sizeof(HILQ);
629: return(kvtop((u_int)qp->hq_eventqueue + off) >> PGSHIFT);
630: #endif
631: }
632:
633: /*ARGSUSED*/
634: hilselect(dev, rw)
635: dev_t dev;
636: {
637: struct proc *p = u.u_procp; /* XXX */
638: register struct hilloop *hilp = &hil0; /* XXX */
639: register struct hilloopdev *dptr;
640: register struct hiliqueue *qp;
641: register int mask;
642: int s, device;
643:
644: if (rw == FWRITE)
645: return (1);
646: device = HILUNIT(dev);
647:
648: /*
649: * Read interface.
650: * Return 1 if there is something in the queue, 0 ow.
651: */
652: dptr = &hilp->hl_device[device];
653: if (dptr->hd_flags & HIL_READIN) {
654: s = splhil();
655: if (dptr->hd_queue.c_cc) {
656: splx(s);
657: return (1);
658: }
659: if (dptr->hd_selr &&
660: dptr->hd_selr->p_wchan == (caddr_t)&selwait)
661: dptr->hd_flags |= HIL_SELCOLL;
662: else
663: dptr->hd_selr = p;
664: splx(s);
665: return (0);
666: }
667:
668: /*
669: * Make sure device is alive and real (or the loop device).
670: * Note that we do not do this for the read interface.
671: * This is primarily to be consistant with HP-UX.
672: */
673: if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE)
674: return (1);
675:
676: /*
677: * Select on loop device is special.
678: * Check to see if there are any data for any loop device
679: * provided it is associated with a queue belonging to this user.
680: */
681: if (device == 0)
682: mask = -1;
683: else
684: mask = hildevmask(device);
685: /*
686: * Must check everybody with interrupts blocked to prevent races.
687: */
688: s = splhil();
689: for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++)
690: if (qp->hq_procp == p && (mask & qp->hq_devmask) &&
691: qp->hq_eventqueue->hil_evqueue.head !=
692: qp->hq_eventqueue->hil_evqueue.tail) {
693: splx(s);
694: return (1);
695: }
696:
697: if (dptr->hd_selr && dptr->hd_selr->p_wchan == (caddr_t)&selwait)
698: dptr->hd_flags |= HIL_SELCOLL;
699: else
700: dptr->hd_selr = p;
701: splx(s);
702: return (0);
703: }
704:
705: hilint()
706: {
707: struct hilloop *hilp = &hil0; /* XXX */
708: register struct hil_dev *hildevice = hilp->hl_addr;
709: u_char c, stat;
710:
711: stat = hildevice->hil_stat;
712: c = hildevice->hil_data; /* clears interrupt */
713: hil_process_int(stat, c);
714: }
715:
716: #include "ite.h"
717:
718: hil_process_int(stat, c)
719: register u_char stat, c;
720: {
721: register struct hilloop *hilp;
722:
723: #ifdef DEBUG
724: if (hildebug & HDB_EVENTS)
725: printf("hilint: %x %x\n", stat, c);
726: #endif
727:
728: /* the shift enables the compiler to generate a jump table */
729: switch ((stat>>HIL_SSHIFT) & HIL_SMASK) {
730:
731: #if NITE > 0
732: case HIL_KEY:
733: case HIL_SHIFT:
734: case HIL_CTRL:
735: case HIL_CTRLSHIFT:
736: itefilter(stat, c);
737: return;
738: #endif
739:
740: case HIL_STATUS: /* The status info. */
741: hilp = &hil0; /* XXX */
742: if (c & HIL_ERROR) {
743: hilp->hl_cmddone = TRUE;
744: if (c == HIL_RECONFIG)
745: hilconfig(hilp);
746: break;
747: }
748: if (c & HIL_COMMAND) {
749: if (c & HIL_POLLDATA) /* End of data */
750: hilevent(hilp);
751: else /* End of command */
752: hilp->hl_cmdending = TRUE;
753: hilp->hl_actdev = 0;
754: } else {
755: if (c & HIL_POLLDATA) { /* Start of polled data */
756: if (hilp->hl_actdev != 0)
757: hilevent(hilp);
758: hilp->hl_actdev = (c & HIL_DEVMASK);
759: hilp->hl_pollbp = hilp->hl_pollbuf;
760: } else { /* Start of command */
761: if (hilp->hl_cmddev == (c & HIL_DEVMASK)) {
762: hilp->hl_cmdbp = hilp->hl_cmdbuf;
763: hilp->hl_actdev = 0;
764: }
765: }
766: }
767: return;
768:
769: case HIL_DATA:
770: hilp = &hil0; /* XXX */
771: if (hilp->hl_actdev != 0) /* Collecting poll data */
772: *hilp->hl_pollbp++ = c;
773: else if (hilp->hl_cmddev != 0) /* Collecting cmd data */
774: if (hilp->hl_cmdending) {
775: hilp->hl_cmddone = TRUE;
776: hilp->hl_cmdending = FALSE;
777: } else
778: *hilp->hl_cmdbp++ = c;
779: return;
780:
781: case 0: /* force full jump table */
782: default:
783: return;
784: }
785: }
786:
787: #if defined(DEBUG) && !defined(PANICBUTTON)
788: #define PANICBUTTON
789: #endif
790:
791: /*
792: * Optimized macro to compute:
793: * eq->head == (eq->tail + 1) % eq->size
794: * i.e. has tail caught up with head. We do this because 32 bit long
795: * remaidering is expensive (a function call with our compiler).
796: */
797: #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1)
798: #define HQVALID(eq) \
799: ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE)
800:
801: hilevent(hilp)
802: struct hilloop *hilp;
803: {
804: register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev];
805: register int len, mask, qnum;
806: register u_char *cp, *pp;
807: register HILQ *hq;
808: struct timeval ourtime;
809: hil_packet *proto;
810: int s, len0;
811: long tenths;
812:
813: #ifdef PANICBUTTON
814: static int first;
815: extern int panicbutton;
816:
817: cp = hilp->hl_pollbuf;
818: if (panicbutton && (*cp & HIL_KBDDATA)) {
819: if (*++cp == 0x4E)
820: first = 1;
821: else if (first && *cp == 0x46 && !panicstr)
822: panic("are we having fun yet?");
823: else
824: first = 0;
825: }
826: #endif
827: #ifdef DEBUG
828: if (hildebug & HDB_EVENTS) {
829: printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev);
830: printhilpollbuf(hilp);
831: printf("\n");
832: }
833: #endif
834:
835: /*
836: * Note that HIL_READIN effectively "shuts off" any queues
837: * that may have been in use at the time of an HILIOCHPUX call.
838: */
839: if (dptr->hd_flags & HIL_READIN) {
840: hpuxhilevent(hilp, dptr);
841: return;
842: }
843:
844: /*
845: * If this device isn't on any queue or there are no data
846: * in the packet (can this happen?) do nothing.
847: */
848: if (dptr->hd_qmask == 0 ||
849: (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0)
850: return;
851:
852: /*
853: * Everybody gets the same time stamp
854: */
855: s = splclock();
856: ourtime = time;
857: splx(s);
858: tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
859:
860: proto = NULL;
861: mask = dptr->hd_qmask;
862: for (qnum = 0; mask; qnum++) {
863: if ((mask & hilqmask(qnum)) == 0)
864: continue;
865: mask &= ~hilqmask(qnum);
866: hq = hilp->hl_queue[qnum].hq_eventqueue;
867:
868: /*
869: * Ensure that queue fields that we rely on are valid
870: * and that there is space in the queue. If either
871: * test fails, we just skip this queue.
872: */
873: if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue))
874: continue;
875:
876: /*
877: * Copy data to queue.
878: * If this is the first queue we construct the packet
879: * with length, timestamp and poll buffer data.
880: * For second and sucessive packets we just duplicate
881: * the first packet.
882: */
883: pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail];
884: if (proto == NULL) {
885: proto = (hil_packet *)pp;
886: cp = hilp->hl_pollbuf;
887: len = len0;
888: *pp++ = len + 6;
889: *pp++ = hilp->hl_actdev;
890: *(long *)pp = tenths;
891: pp += sizeof(long);
892: do *pp++ = *cp++; while (--len);
893: } else
894: *(hil_packet *)pp = *proto;
895:
896: if (++hq->hil_evqueue.tail == hq->hil_evqueue.size)
897: hq->hil_evqueue.tail = 0;
898: }
899:
900: /*
901: * Wake up anyone selecting on this device or the loop itself
902: */
903: if (dptr->hd_selr) {
904: selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL);
905: dptr->hd_selr = NULL;
906: dptr->hd_flags &= ~HIL_SELCOLL;
907: }
908: dptr = &hilp->hl_device[HILLOOPDEV];
909: if (dptr->hd_selr) {
910: selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL);
911: dptr->hd_selr = NULL;
912: dptr->hd_flags &= ~HIL_SELCOLL;
913: }
914: }
915:
916: #undef HQFULL
917:
918: hpuxhilevent(hilp, dptr)
919: register struct hilloop *hilp;
920: register struct hilloopdev *dptr;
921: {
922: register int len;
923: struct timeval ourtime;
924: long tstamp;
925: int s;
926:
927: /*
928: * Everybody gets the same time stamp
929: */
930: s = splclock();
931: ourtime = time;
932: splx(s);
933: tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
934:
935: /*
936: * Each packet that goes into the buffer must be preceded by the
937: * number of bytes in the packet, and the timestamp of the packet.
938: * This adds 5 bytes to the packet size. Make sure there is enough
939: * room in the buffer for it, and if not, toss the packet.
940: */
941: len = hilp->hl_pollbp - hilp->hl_pollbuf;
942: if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) {
943: putc(len+5, &dptr->hd_queue);
944: (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue);
945: (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue);
946: }
947:
948: /*
949: * Wake up any one blocked on a read or select
950: */
951: if (dptr->hd_flags & HIL_ASLEEP) {
952: dptr->hd_flags &= ~HIL_ASLEEP;
953: wakeup((caddr_t)dptr);
954: }
955: if (dptr->hd_selr) {
956: selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL);
957: dptr->hd_selr = NULL;
958: dptr->hd_flags &= ~HIL_SELCOLL;
959: }
960: }
961:
962: /*
963: * Shared queue manipulation routines
964: */
965:
966: hilqalloc(qip)
967: struct hilqinfo *qip;
968: {
969: #ifdef MAPMEM
970: struct proc *p = u.u_procp; /* XXX */
971: register struct hilloop *hilp = &hil0; /* XXX */
972: register HILQ *hq;
973: register int qnum;
974: struct mapmem *mp;
975: int error, hilqmapin();
976:
977: #ifdef DEBUG
978: if (hildebug & HDB_FOLLOW)
979: printf("hilqalloc(%d): addr %x\n",
980: p->p_pid, qip->addr);
981: #endif
982: /*
983: * Find a free queue
984: */
985: for (qnum = 0; qnum < NHILQ; qnum++)
986: if (hilp->hl_queue[qnum].hq_procp == NULL)
987: break;
988: if (qnum == NHILQ)
989: return(EMFILE);
990:
991: /*
992: * Allocate and clear memory for the queue
993: */
994: if (hilp->hl_queue[qnum].hq_eventqueue)
995: panic("hilqalloc");
996: hq = (HILQ *) cialloc(sizeof(HILQ));
997: if (hq == NULL)
998: return(ENOMEM);
999: bzero((caddr_t)hq, sizeof(HILQ));
1000: hilp->hl_queue[qnum].hq_eventqueue = hq;
1001: hq->hil_evqueue.size = HEVQSIZE;
1002:
1003: /*
1004: * Map queue into user address space as instructed
1005: */
1006: error = mmalloc(p, qnum, &qip->addr, sizeof(HILQ), MM_RW|MM_CI,
1007: &hilqops, &mp);
1008: if (error) {
1009: cifree((caddr_t)hq, sizeof(HILQ));
1010: hilp->hl_queue[qnum].hq_eventqueue = NULL;
1011: return(error);
1012: }
1013: qip->qid = qnum;
1014: if (error = mmmapin(p, mp, hilqmapin)) {
1015: (void) mmfree(p, mp);
1016: cifree((caddr_t)hq, sizeof(HILQ));
1017: hilp->hl_queue[qnum].hq_eventqueue = NULL;
1018: return(error);
1019: }
1020: hilp->hl_queue[qnum].hq_procp = p;
1021: hilp->hl_queue[qnum].hq_devmask = 0;
1022: return(0);
1023: #else
1024: return(EINVAL);
1025: #endif
1026: }
1027:
1028: hilqfree(qnum)
1029: register int qnum;
1030: {
1031: #ifdef MAPMEM
1032: struct proc *p = u.u_procp; /* XXX */
1033: register struct hilloop *hilp = &hil0; /* XXX */
1034: register struct mapmem *mp;
1035:
1036: #ifdef DEBUG
1037: if (hildebug & HDB_FOLLOW)
1038: printf("hilqfree(%d): qnum %d\n",
1039: p->p_pid, qnum);
1040: #endif
1041: if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
1042: return(EINVAL);
1043: for (mp = u.u_mmap; mp; mp = mp->mm_next)
1044: if (qnum == mp->mm_id && mp->mm_ops == &hilqops) {
1045: (void) hilqexit(mp);
1046: return(0);
1047: }
1048: panic("hilqfree");
1049: /* NOTREACHED */
1050: #else
1051: return(EINVAL);
1052: #endif
1053: }
1054:
1055: hilqmap(qnum, device)
1056: register int qnum, device;
1057: {
1058: struct proc *p = u.u_procp; /* XXX */
1059: register struct hilloop *hilp = &hil0; /* XXX */
1060: register struct hilloopdev *dptr = &hilp->hl_device[device];
1061: int s;
1062:
1063: #ifdef DEBUG
1064: if (hildebug & HDB_FOLLOW)
1065: printf("hilqmap(%d): qnum %d device %x\n",
1066: p->p_pid, qnum, device);
1067: #endif
1068: if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
1069: return(EINVAL);
1070: if ((dptr->hd_flags & HIL_QUEUEIN) == 0)
1071: return(EINVAL);
1072: if (dptr->hd_qmask && u.u_uid && u.u_uid != dptr->hd_uid)
1073: return(EPERM);
1074:
1075: hilp->hl_queue[qnum].hq_devmask |= hildevmask(device);
1076: if (dptr->hd_qmask == 0)
1077: dptr->hd_uid = u.u_uid;
1078: s = splhil();
1079: dptr->hd_qmask |= hilqmask(qnum);
1080: splx(s);
1081: #ifdef DEBUG
1082: if (hildebug & HDB_MASK)
1083: printf("hilqmap(%d): devmask %x qmask %x\n",
1084: p->p_pid, hilp->hl_queue[qnum].hq_devmask,
1085: dptr->hd_qmask);
1086: #endif
1087: return(0);
1088: }
1089:
1090: hilqunmap(qnum, device)
1091: register int qnum, device;
1092: {
1093: struct proc *p = u.u_procp; /* XXX */
1094: register struct hilloop *hilp = &hil0; /* XXX */
1095: int s;
1096:
1097: #ifdef DEBUG
1098: if (hildebug & HDB_FOLLOW)
1099: printf("hilqunmap(%d): qnum %d device %x\n",
1100: p->p_pid, qnum, device);
1101: #endif
1102:
1103: if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
1104: return(EINVAL);
1105:
1106: hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device);
1107: s = splhil();
1108: hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum);
1109: splx(s);
1110: #ifdef DEBUG
1111: if (hildebug & HDB_MASK)
1112: printf("hilqunmap(%d): devmask %x qmask %x\n",
1113: p->p_pid, hilp->hl_queue[qnum].hq_devmask,
1114: hilp->hl_device[device].hd_qmask);
1115: #endif
1116: return(0);
1117: }
1118:
1119: #ifdef MAPMEM
1120: hilqmapin(mp, off)
1121: struct mapmem *mp;
1122: {
1123: struct hilloop *hilp = &hil0; /* XXX */
1124: register HILQ *hq = hilp->hl_queue[mp->mm_id].hq_eventqueue;
1125:
1126: if (hq == NULL || off >= sizeof(HILQ))
1127: return(-1);
1128: return(kvtop((u_int)hq + off) >> PGSHIFT);
1129: }
1130:
1131: /*
1132: * Fork hook.
1133: * Unmap queue from child's address space
1134: */
1135: hilqfork(mp, ischild)
1136: struct mapmem *mp;
1137: {
1138: struct proc *p = u.u_procp; /* XXX */
1139: #ifdef DEBUG
1140: if (hildebug & HDB_MMAP)
1141: printf("hilqfork(%d): %s qnum %d\n", p->p_pid,
1142: ischild ? "child" : "parent", mp->mm_id);
1143: #endif
1144: if (ischild) {
1145: mmmapout(p, mp);
1146: (void) mmfree(p, mp);
1147: }
1148: }
1149:
1150: /*
1151: * Vfork hook.
1152: * Associate queue with child when VM resources are passed.
1153: */
1154: hilqvfork(mp, fup, tup)
1155: struct mapmem *mp;
1156: struct user *fup, *tup;
1157: {
1158: struct hilloop *hilp = &hil0; /* XXX */
1159: register struct hiliqueue *qp = &hilp->hl_queue[mp->mm_id];
1160:
1161: #ifdef DEBUG
1162: if (hildebug & HDB_MMAP)
1163: printf("hilqvfork(%d): from %x to %x qnum %d, qprocp %x\n",
1164: u.u_procp->p_pid, fup->u_procp, tup->u_procp,
1165: mp->mm_id, qp->hq_procp);
1166: #endif
1167: if (qp->hq_procp == fup->u_procp)
1168: qp->hq_procp = tup->u_procp;
1169: }
1170:
1171: /*
1172: * Exit hook.
1173: * Unmap all devices and free all queues.
1174: */
1175: hilqexit(mp)
1176: struct mapmem *mp;
1177: {
1178: struct proc *p = u.u_procp; /* XXX */
1179: register struct hilloop *hilp = &hil0; /* XXX */
1180: register int mask, i;
1181: int s;
1182:
1183: #ifdef DEBUG
1184: if (hildebug & HDB_MMAP)
1185: printf("hilqexit(%d): qnum %d\n", p->p_pid, mp->mm_id);
1186: #endif
1187: /*
1188: * Atomically take all devices off the queue
1189: */
1190: mask = ~hilqmask(mp->mm_id);
1191: s = splhil();
1192: for (i = 0; i < NHILD; i++)
1193: hilp->hl_device[i].hd_qmask &= mask;
1194: splx(s);
1195: /*
1196: * Now unmap from user address space and free queue
1197: */
1198: i = mp->mm_id;
1199: cifree((caddr_t)hilp->hl_queue[i].hq_eventqueue, sizeof(HILQ));
1200: hilp->hl_queue[i].hq_eventqueue = NULL;
1201: hilp->hl_queue[i].hq_procp = NULL;
1202: return(mmfree(p, mp));
1203: }
1204: #endif
1205:
1206: #include "clist.h"
1207:
1208: /*
1209: * This is just a copy of the virgin q_to_b routine with minor
1210: * optimizations for HIL use. It is used for two reasons:
1211: * 1. If we have PAGE mode defined, the normal q_to_b processes
1212: * chars one at a time and breaks on newlines.
1213: * 2. We don't have to raise the priority to spltty() for most
1214: * of the clist manipulations.
1215: */
1216: hilq_to_b(q, cp, cc)
1217: register struct clist *q;
1218: register char *cp;
1219: {
1220: register struct cblock *bp;
1221: register int nc;
1222: char *acp;
1223: int s;
1224: extern char cwaiting;
1225:
1226: if (cc <= 0)
1227: return (0);
1228: s = splhil();
1229: if (q->c_cc <= 0) {
1230: q->c_cc = 0;
1231: q->c_cf = q->c_cl = NULL;
1232: splx(s);
1233: return (0);
1234: }
1235: acp = cp;
1236:
1237: while (cc) {
1238: nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
1239: nc = MIN(nc, cc);
1240: nc = MIN(nc, q->c_cc);
1241: (void) bcopy(q->c_cf, cp, (unsigned)nc);
1242: q->c_cf += nc;
1243: q->c_cc -= nc;
1244: cc -= nc;
1245: cp += nc;
1246: if (q->c_cc <= 0) {
1247: bp = (struct cblock *)(q->c_cf - 1);
1248: bp = (struct cblock *)((int)bp & ~CROUND);
1249: q->c_cf = q->c_cl = NULL;
1250: spltty();
1251: bp->c_next = cfreelist;
1252: cfreelist = bp;
1253: cfreecount += CBSIZE;
1254: if (cwaiting) {
1255: wakeup(&cwaiting);
1256: cwaiting = 0;
1257: }
1258: break;
1259: }
1260: if (((int)q->c_cf & CROUND) == 0) {
1261: bp = (struct cblock *)(q->c_cf);
1262: bp--;
1263: q->c_cf = bp->c_next->c_info;
1264: spltty();
1265: bp->c_next = cfreelist;
1266: cfreelist = bp;
1267: cfreecount += CBSIZE;
1268: if (cwaiting) {
1269: wakeup(&cwaiting);
1270: cwaiting = 0;
1271: }
1272: splhil();
1273: }
1274: }
1275: splx(s);
1276: return (cp-acp);
1277: }
1278:
1279: /*
1280: * Cooked keyboard functions for ite driver.
1281: * There is only one "cooked" ITE keyboard (the first keyboard found)
1282: * per loop. There may be other keyboards, but they will always be "raw".
1283: */
1284:
1285: kbdbell()
1286: {
1287: struct hilloop *hilp = &hil0; /* XXX */
1288:
1289: hilbeep(hilp, &default_bell);
1290: }
1291:
1292: kbdenable()
1293: {
1294: struct hilloop *hilp = &hil0; /* XXX */
1295: register struct hil_dev *hildevice = hilp->hl_addr;
1296: char db;
1297:
1298: /* Set the autorepeat rate register */
1299: db = ar_format(KBD_ARR);
1300: send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL);
1301:
1302: /* Set the autorepeat delay register */
1303: db = ar_format(KBD_ARD);
1304: send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL);
1305:
1306: /* Enable interrupts */
1307: send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
1308: }
1309:
1310: kbddisable()
1311: {
1312: }
1313:
1314: /*
1315: * XXX: read keyboard directly and return code.
1316: * Used by console getchar routine. Could really screw up anybody
1317: * reading from the keyboard in the normal, interrupt driven fashion.
1318: */
1319: kbdgetc(statp)
1320: int *statp;
1321: {
1322: struct hilloop *hilp = &hil0; /* XXX */
1323: register struct hil_dev *hildevice = hilp->hl_addr;
1324: register int c, stat;
1325: int s;
1326:
1327: s = splhil();
1328: while (((stat = hildevice->hil_stat) & HIL_DATA_RDY) == 0)
1329: ;
1330: c = hildevice->hil_data;
1331: splx(s);
1332: *statp = stat;
1333: return(c);
1334: }
1335:
1336: /*
1337: * Recoginize and clear keyboard generated NMIs.
1338: * Returns 1 if it was ours, 0 otherwise. Note that we cannot use
1339: * send_hil_cmd() to issue the clear NMI command as that would actually
1340: * lower the priority to splimp() and it doesn't wait for the completion
1341: * of the command. Either of these conditions could result in the
1342: * interrupt reoccuring. Note that we issue the CNMT command twice.
1343: * This seems to be needed, once is not always enough!?!
1344: */
1345: kbdnmi()
1346: {
1347: register struct hilloop *hilp = &hil0; /* XXX */
1348:
1349: if ((*KBDNMISTAT & KBDNMI) == 0)
1350: return(0);
1351: HILWAIT(hilp->hl_addr);
1352: hilp->hl_addr->hil_cmd = HIL_CNMT;
1353: HILWAIT(hilp->hl_addr);
1354: hilp->hl_addr->hil_cmd = HIL_CNMT;
1355: HILWAIT(hilp->hl_addr);
1356: return(1);
1357: }
1358:
1359: #define HILSECURITY 0x33
1360: #define HILIDENTIFY 0x03
1361: #define HILSCBIT 0x04
1362:
1363: /*
1364: * Called at boot time to print out info about interesting devices
1365: */
1366: hilinfo(hilp)
1367: register struct hilloop *hilp;
1368: {
1369: register int id, len;
1370: register struct kbdmap *km;
1371:
1372: /*
1373: * Keyboard info.
1374: */
1375: if (hilp->hl_kbddev) {
1376: printf("hil%d: ", hilp->hl_kbddev);
1377: for (km = kbd_map; km->kbd_code; km++)
1378: if (km->kbd_code == hilp->hl_kbdlang) {
1379: printf("%s ", km->kbd_desc);
1380: break;
1381: }
1382: printf("keyboard\n");
1383: }
1384: /*
1385: * ID module.
1386: * Attempt to locate the first ID module and print out its
1387: * security code. Is this a good idea??
1388: */
1389: id = hiliddev(hilp);
1390: if (id) {
1391: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1392: hilp->hl_cmddev = id;
1393: send_hildev_cmd(hilp, id, HILSECURITY);
1394: len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
1395: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1396: hilp->hl_cmddev = 0;
1397: printf("hil%d: security code", id);
1398: for (id = 0; id < len; id++)
1399: printf(" %x", hilp->hl_cmdbuf[id]);
1400: while (id++ < 16)
1401: printf(" 0");
1402: printf("\n");
1403: }
1404: }
1405:
1406: #define HILAR1 0x3E
1407: #define HILAR2 0x3F
1408:
1409: /*
1410: * Called after the loop has reconfigured. Here we need to:
1411: * - determine how many devices are on the loop
1412: * (some may have been added or removed)
1413: * - locate the ITE keyboard (if any) and ensure
1414: * that it is in the proper state (raw or cooked)
1415: * and is set to use the proper language mapping table
1416: * - ensure all other keyboards are raw
1417: * Note that our device state is now potentially invalid as
1418: * devices may no longer be where they were. What we should
1419: * do here is either track where the devices went and move
1420: * state around accordingly or, more simply, just mark all
1421: * devices as HIL_DERROR and don't allow any further use until
1422: * they are closed. This is a little too brutal for my tastes,
1423: * we prefer to just assume people won't move things around.
1424: */
1425: hilconfig(hilp)
1426: register struct hilloop *hilp;
1427: {
1428: u_char db;
1429: int s;
1430:
1431: s = splhil();
1432: #ifdef DEBUG
1433: if (hildebug & HDB_CONFIG) {
1434: printf("hilconfig: reconfigured: ");
1435: send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
1436: printf("LPSTAT %x, ", db);
1437: send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db);
1438: printf("LPCTRL %x, ", db);
1439: send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
1440: printf("KBDSADR %x\n", db);
1441: hilreport(hilp);
1442: }
1443: #endif
1444: /*
1445: * Determine how many devices are on the loop.
1446: * Mark those as alive and real, all others as dead.
1447: */
1448: db = 0;
1449: send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
1450: hilp->hl_maxdev = db & LPS_DEVMASK;
1451: for (db = 1; db < NHILD; db++) {
1452: if (db <= hilp->hl_maxdev)
1453: hilp->hl_device[db].hd_flags |= HIL_ALIVE;
1454: else
1455: hilp->hl_device[db].hd_flags &= ~HIL_ALIVE;
1456: hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO;
1457: }
1458: #ifdef DEBUG
1459: if (hildebug & (HDB_CONFIG|HDB_KEYBOARD))
1460: printf("hilconfig: max device %d\n", hilp->hl_maxdev);
1461: #endif
1462: if (hilp->hl_maxdev == 0) {
1463: hilp->hl_kbddev = 0;
1464: splx(s);
1465: return;
1466: }
1467: /*
1468: * Find out where the keyboards are and record the ITE keyboard
1469: * (first one found). If no keyboards found, we are all done.
1470: */
1471: db = 0;
1472: send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
1473: #ifdef DEBUG
1474: if (hildebug & HDB_KEYBOARD)
1475: printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n",
1476: db, hilp->hl_kbddev, ffs((int)db));
1477: #endif
1478: hilp->hl_kbddev = ffs((int)db);
1479: if (hilp->hl_kbddev == 0) {
1480: splx(s);
1481: return;
1482: }
1483: /*
1484: * Determine if the keyboard should be cooked or raw and configure it.
1485: */
1486: db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1);
1487: send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL);
1488: /*
1489: * Re-enable autorepeat in raw mode, cooked mode AR is not affected.
1490: */
1491: if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) {
1492: db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2;
1493: hilp->hl_cmddev = hilp->hl_kbddev;
1494: send_hildev_cmd(hilp, hilp->hl_kbddev, db);
1495: hilp->hl_cmddev = 0;
1496: }
1497: /*
1498: * Determine the keyboard language configuration, but don't
1499: * override a user-specified setting.
1500: */
1501: db = 0;
1502: send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db);
1503: #ifdef DEBUG
1504: if (hildebug & HDB_KEYBOARD)
1505: printf("hilconfig: language: old %x new %x\n",
1506: hilp->hl_kbdlang, db);
1507: #endif
1508: if (hilp->hl_kbdlang != KBD_SPECIAL) {
1509: struct kbdmap *km;
1510:
1511: for (km = kbd_map; km->kbd_code; km++)
1512: if (km->kbd_code == db) {
1513: hilp->hl_kbdlang = db;
1514: /* XXX */
1515: kbd_keymap = km->kbd_keymap;
1516: kbd_shiftmap = km->kbd_shiftmap;
1517: kbd_ctrlmap = km->kbd_ctrlmap;
1518: kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;
1519: kbd_stringmap = km->kbd_stringmap;
1520: }
1521: }
1522: splx(s);
1523: }
1524:
1525: hilreset(hilp)
1526: struct hilloop *hilp;
1527: {
1528: register struct hil_dev *hildevice = hilp->hl_addr;
1529: u_char db;
1530:
1531: /*
1532: * Initialize the loop: reconfigure, don't report errors,
1533: * cook keyboards, and enable autopolling.
1534: */
1535: db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
1536: send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL);
1537: /*
1538: * Delay one second for reconfiguration and then read the the
1539: * data register to clear the interrupt (if the loop reconfigured).
1540: */
1541: DELAY(1000000);
1542: if (hildevice->hil_stat & HIL_DATA_RDY)
1543: db = hildevice->hil_data;
1544: /*
1545: * The HIL loop may have reconfigured. If so we proceed on,
1546: * if not we loop until a successful reconfiguration is reported
1547: * back to us. The HIL loop will continue to attempt forever.
1548: * Probably not very smart.
1549: */
1550: do {
1551: send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db);
1552: } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0);
1553: /*
1554: * At this point, the loop should have reconfigured.
1555: * The reconfiguration interrupt has already called hilconfig()
1556: * so the keyboard has been determined.
1557: */
1558: send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
1559: }
1560:
1561: hilbeep(hilp, bp)
1562: struct hilloop *hilp;
1563: register struct _hilbell *bp;
1564: {
1565: u_char buf[2];
1566:
1567: buf[0] = ~((bp->duration - 10) / 10);
1568: buf[1] = bp->frequency;
1569: send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL);
1570: }
1571:
1572: /*
1573: * Locate and return the address of the first ID module, 0 if none present.
1574: */
1575: hiliddev(hilp)
1576: register struct hilloop *hilp;
1577: {
1578: register int i, len;
1579:
1580: #ifdef DEBUG
1581: if (hildebug & HDB_IDMODULE)
1582: printf("hiliddev(%x): looking for idmodule...", hilp);
1583: #endif
1584: for (i = 1; i <= hilp->hl_maxdev; i++) {
1585: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1586: hilp->hl_cmddev = i;
1587: send_hildev_cmd(hilp, i, HILIDENTIFY);
1588: /*
1589: * XXX: the final condition checks to ensure that the
1590: * device ID byte is in the range of the ID module (0x30-0x3F)
1591: */
1592: len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
1593: if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) &&
1594: (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) {
1595: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1596: hilp->hl_cmddev = i;
1597: send_hildev_cmd(hilp, i, HILSECURITY);
1598: break;
1599: }
1600: }
1601: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1602: hilp->hl_cmddev = 0;
1603: #ifdef DEBUG
1604: if (hildebug & HDB_IDMODULE)
1605: if (i <= hilp->hl_maxdev)
1606: printf("found at %d\n", i);
1607: else
1608: printf("not found\n");
1609: #endif
1610: return(i <= hilp->hl_maxdev ? i : 0);
1611: }
1612:
1613: /*
1614: * Low level routines which actually talk to the 8042 chip.
1615: */
1616:
1617: /*
1618: * Send a command to the 8042 with zero or more bytes of data.
1619: * If rdata is non-null, wait for and return a byte of data.
1620: * We run at splimp() to make the transaction as atomic as
1621: * possible without blocking the clock (is this necessary?)
1622: */
1623: send_hil_cmd(hildevice, cmd, data, dlen, rdata)
1624: register struct hil_dev *hildevice;
1625: u_char cmd, *data, dlen;
1626: u_char *rdata;
1627: {
1628: u_char status;
1629: int s = splimp();
1630:
1631: HILWAIT(hildevice);
1632: hildevice->hil_cmd = cmd;
1633: while (dlen--) {
1634: HILWAIT(hildevice);
1635: hildevice->hil_data = *data++;
1636: }
1637: if (rdata) {
1638: do {
1639: HILDATAWAIT(hildevice);
1640: status = hildevice->hil_stat;
1641: *rdata = hildevice->hil_data;
1642: } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
1643: }
1644: splx(s);
1645: }
1646:
1647: /*
1648: * Send a command to a device on the loop.
1649: * Since only one command can be active on the loop at any time,
1650: * we must ensure that we are not interrupted during this process.
1651: * Hence we mask interrupts to prevent potential access from most
1652: * interrupt routines and turn off auto-polling to disable the
1653: * internally generated poll commands.
1654: *
1655: * splhigh is extremely conservative but insures atomic operation,
1656: * splimp (clock only interrupts) seems to be good enough in practice.
1657: */
1658: send_hildev_cmd(hilp, device, cmd)
1659: register struct hilloop *hilp;
1660: char device, cmd;
1661: {
1662: register struct hil_dev *hildevice = hilp->hl_addr;
1663: u_char status, c;
1664: int s = splimp();
1665:
1666: polloff(hildevice);
1667:
1668: /*
1669: * Transfer the command and device info to the chip
1670: */
1671: HILWAIT(hildevice);
1672: hildevice->hil_cmd = HIL_STARTCMD;
1673: HILWAIT(hildevice);
1674: hildevice->hil_data = 8 + device;
1675: HILWAIT(hildevice);
1676: hildevice->hil_data = cmd;
1677: HILWAIT(hildevice);
1678: hildevice->hil_data = HIL_TIMEOUT;
1679: /*
1680: * Trigger the command and wait for completion
1681: */
1682: HILWAIT(hildevice);
1683: hildevice->hil_cmd = HIL_TRIGGER;
1684: hilp->hl_cmddone = FALSE;
1685: do {
1686: HILDATAWAIT(hildevice);
1687: status = hildevice->hil_stat;
1688: c = hildevice->hil_data;
1689: hil_process_int(status, c);
1690: } while (!hilp->hl_cmddone);
1691:
1692: pollon(hildevice);
1693: splx(s);
1694: }
1695:
1696: /*
1697: * Turn auto-polling off and on.
1698: * Also disables and enable auto-repeat. Why?
1699: */
1700: polloff(hildevice)
1701: register struct hil_dev *hildevice;
1702: {
1703: register char db;
1704:
1705: /*
1706: * Turn off auto repeat
1707: */
1708: HILWAIT(hildevice);
1709: hildevice->hil_cmd = HIL_SETARR;
1710: HILWAIT(hildevice);
1711: hildevice->hil_data = 0;
1712: /*
1713: * Turn off auto-polling
1714: */
1715: HILWAIT(hildevice);
1716: hildevice->hil_cmd = HIL_READLPCTRL;
1717: HILDATAWAIT(hildevice);
1718: db = hildevice->hil_data;
1719: db &= ~LPC_AUTOPOLL;
1720: HILWAIT(hildevice);
1721: hildevice->hil_cmd = HIL_WRITELPCTRL;
1722: HILWAIT(hildevice);
1723: hildevice->hil_data = db;
1724: /*
1725: * Must wait til polling is really stopped
1726: */
1727: do {
1728: HILWAIT(hildevice);
1729: hildevice->hil_cmd = HIL_READBUSY;
1730: HILDATAWAIT(hildevice);
1731: db = hildevice->hil_data;
1732: } while (db & BSY_LOOPBUSY);
1733: }
1734:
1735: pollon(hildevice)
1736: register struct hil_dev *hildevice;
1737: {
1738: register char db;
1739:
1740: /*
1741: * Turn on auto polling
1742: */
1743: HILWAIT(hildevice);
1744: hildevice->hil_cmd = HIL_READLPCTRL;
1745: HILDATAWAIT(hildevice);
1746: db = hildevice->hil_data;
1747: db |= LPC_AUTOPOLL;
1748: HILWAIT(hildevice);
1749: hildevice->hil_cmd = HIL_WRITELPCTRL;
1750: HILWAIT(hildevice);
1751: hildevice->hil_data = db;
1752: /*
1753: * Turn on auto repeat
1754: */
1755: HILWAIT(hildevice);
1756: hildevice->hil_cmd = HIL_SETARR;
1757: HILWAIT(hildevice);
1758: hildevice->hil_data = ar_format(KBD_ARR);
1759: }
1760:
1761: #ifdef DEBUG
1762: printhilpollbuf(hilp)
1763: register struct hilloop *hilp;
1764: {
1765: register u_char *cp;
1766: register int i, len;
1767:
1768: cp = hilp->hl_pollbuf;
1769: len = hilp->hl_pollbp - cp;
1770: for (i = 0; i < len; i++)
1771: printf("%x ", hilp->hl_pollbuf[i]);
1772: printf("\n");
1773: }
1774:
1775: printhilcmdbuf(hilp)
1776: register struct hilloop *hilp;
1777: {
1778: register u_char *cp;
1779: register int i, len;
1780:
1781: cp = hilp->hl_cmdbuf;
1782: len = hilp->hl_cmdbp - cp;
1783: for (i = 0; i < len; i++)
1784: printf("%x ", hilp->hl_cmdbuf[i]);
1785: printf("\n");
1786: }
1787:
1788: hilreport(hilp)
1789: register struct hilloop *hilp;
1790: {
1791: register int i, len;
1792: int s = splhil();
1793:
1794: for (i = 1; i <= hilp->hl_maxdev; i++) {
1795: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1796: hilp->hl_cmddev = i;
1797: send_hildev_cmd(hilp, i, HILIDENTIFY);
1798: printf("hil%d: id: ", i);
1799: printhilcmdbuf(hilp);
1800: len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
1801: if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) {
1802: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1803: hilp->hl_cmddev = i;
1804: send_hildev_cmd(hilp, i, HILSECURITY);
1805: printf("hil%d: sc: ", i);
1806: printhilcmdbuf(hilp);
1807: }
1808: }
1809: hilp->hl_cmdbp = hilp->hl_cmdbuf;
1810: hilp->hl_cmddev = 0;
1811: splx(s);
1812: }
1813: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.