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