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