xref: /csrg-svn/sys/hp/dev/hil.c (revision 65643)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1988 University of Utah.
363146Sbostic  * Copyright (c) 1990, 1993
463146Sbostic  *	The Regents of the University of California.  All rights reserved.
541480Smckusick  *
641480Smckusick  * This code is derived from software contributed to Berkeley by
741480Smckusick  * the Systems Programming Group of the University of Utah Computer
841480Smckusick  * Science Department.
941480Smckusick  *
1041480Smckusick  * %sccs.include.redist.c%
1141480Smckusick  *
1253923Shibler  * from: Utah $Hdr: hil.c 1.38 92/01/21$
1341480Smckusick  *
14*65643Sbostic  *	@(#)hil.c	8.2 (Berkeley) 01/12/94
1541480Smckusick  */
1641480Smckusick 
1756504Sbostic #include <sys/param.h>
1856504Sbostic #include <sys/conf.h>
1956504Sbostic #include <sys/proc.h>
2056504Sbostic #include <sys/user.h>
2156504Sbostic #include <sys/ioctl.h>
2256504Sbostic #include <sys/file.h>
2356504Sbostic #include <sys/tty.h>
2456504Sbostic #include <sys/systm.h>
2556504Sbostic #include <sys/uio.h>
2656504Sbostic #include <sys/kernel.h>
2741480Smckusick 
2856504Sbostic #include <hp/dev/hilreg.h>
2956504Sbostic #include <hp/dev/hilioctl.h>
3056504Sbostic #include <hp/dev/hilvar.h>
3156504Sbostic #include <hp/dev/kbdmap.h>
3241480Smckusick 
3356504Sbostic #include <machine/cpu.h>
3441480Smckusick 
3556504Sbostic #include <vm/vm_param.h>
3656504Sbostic #include <vm/vm_map.h>
3756504Sbostic #include <vm/vm_kern.h>
3856504Sbostic #include <vm/vm_page.h>
3956504Sbostic #include <vm/vm_pager.h>
4045750Smckusick 
4153923Shibler #ifdef hp300
4253923Shibler #define NHIL	1	/* XXX */
4353923Shibler #else
4453923Shibler #include "hil.h"
4553923Shibler #endif
4653923Shibler 
4753923Shibler struct  hilloop hilloop[NHIL];
4841480Smckusick struct	_hilbell default_bell = { BELLDUR, BELLFREQ };
4953923Shibler #ifdef hp800
5053923Shibler int	hilspl;
5153923Shibler #endif
5241480Smckusick 
5341480Smckusick #ifdef DEBUG
5441480Smckusick int 	hildebug = 0;
5541480Smckusick #define HDB_FOLLOW	0x01
5641480Smckusick #define HDB_MMAP	0x02
5741480Smckusick #define HDB_MASK	0x04
5841480Smckusick #define HDB_CONFIG	0x08
5941480Smckusick #define HDB_KEYBOARD	0x10
6041480Smckusick #define HDB_IDMODULE	0x20
6141480Smckusick #define HDB_EVENTS	0x80
6241480Smckusick #endif
6341480Smckusick 
6442360Smckusick /* symbolic sleep message strings */
6542360Smckusick char hilin[] = "hilin";
6642360Smckusick 
6753923Shibler hilsoftinit(unit, hilbase)
6853923Shibler 	int unit;
6953923Shibler 	struct hil_dev *hilbase;
7041480Smckusick {
7153923Shibler   	register struct hilloop *hilp = &hilloop[unit];
7241480Smckusick 	register int i;
7341480Smckusick 
7453923Shibler #ifdef DEBUG
7553923Shibler 	if (hildebug & HDB_FOLLOW)
7653923Shibler 		printf("hilsoftinit(%d, %x)\n", unit, hilbase);
7753923Shibler #endif
7841480Smckusick 	/*
7941480Smckusick 	 * Initialize loop information
8041480Smckusick 	 */
8153923Shibler 	hilp->hl_addr = hilbase;
8241480Smckusick 	hilp->hl_cmdending = FALSE;
8341480Smckusick 	hilp->hl_actdev = hilp->hl_cmddev = 0;
8441480Smckusick 	hilp->hl_cmddone = FALSE;
8541480Smckusick 	hilp->hl_cmdbp = hilp->hl_cmdbuf;
8641480Smckusick 	hilp->hl_pollbp = hilp->hl_pollbuf;
8741480Smckusick 	hilp->hl_kbddev = 0;
8841480Smckusick 	hilp->hl_kbdlang = KBD_DEFAULT;
8941480Smckusick 	hilp->hl_kbdflags = 0;
9041480Smckusick 	/*
9141480Smckusick 	 * Clear all queues and device associations with queues
9241480Smckusick 	 */
9341480Smckusick 	for (i = 0; i < NHILQ; i++) {
9441480Smckusick 		hilp->hl_queue[i].hq_eventqueue = NULL;
9541480Smckusick 		hilp->hl_queue[i].hq_procp = NULL;
9641480Smckusick 		hilp->hl_queue[i].hq_devmask = 0;
9741480Smckusick 	}
9841480Smckusick 	for (i = 0; i < NHILD; i++)
9941480Smckusick 		hilp->hl_device[i].hd_qmask = 0;
10041480Smckusick 	hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO);
10153923Shibler }
10253923Shibler 
10353923Shibler hilinit(unit, hilbase)
10453923Shibler 	int unit;
10553923Shibler 	struct hil_dev *hilbase;
10653923Shibler {
10753923Shibler   	register struct hilloop *hilp = &hilloop[unit];
10853923Shibler #ifdef DEBUG
10953923Shibler 	if (hildebug & HDB_FOLLOW)
11053923Shibler 		printf("hilinit(%d, %x)\n", unit, hilbase);
11153923Shibler #endif
11241480Smckusick 	/*
11353923Shibler 	 * Initialize software (if not already done).
11453923Shibler 	 */
11553923Shibler 	if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0)
11653923Shibler 		hilsoftinit(unit, hilbase);
11753923Shibler 	/*
11853923Shibler 	 * Initialize hardware.
11941480Smckusick 	 * Reset the loop hardware, and collect keyboard/id info
12041480Smckusick 	 */
12141480Smckusick 	hilreset(hilp);
12253923Shibler 	hilinfo(unit);
12353923Shibler 	kbdenable(unit);
12441480Smckusick }
12541480Smckusick 
12649132Skarels /* ARGSUSED */
12749132Skarels hilopen(dev, flags, mode, p)
12841480Smckusick 	dev_t dev;
12949132Skarels 	int flags, mode;
13049132Skarels 	struct proc *p;
13141480Smckusick {
13253923Shibler   	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
13341480Smckusick 	register struct hilloopdev *dptr;
13441480Smckusick 	u_char device = HILUNIT(dev);
13541480Smckusick 
13641480Smckusick #ifdef DEBUG
13741480Smckusick 	if (hildebug & HDB_FOLLOW)
13853923Shibler 		printf("hilopen(%d): loop %x device %x\n",
13953923Shibler 		       p->p_pid, HILLOOP(dev), device);
14041480Smckusick #endif
14141480Smckusick 
14241480Smckusick 	if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0)
14341480Smckusick 		return(ENXIO);
14441480Smckusick 
14541480Smckusick 	dptr = &hilp->hl_device[device];
14641480Smckusick 	if ((dptr->hd_flags & HIL_ALIVE) == 0)
14741480Smckusick 		return(ENODEV);
14841480Smckusick 
14941480Smckusick 	/*
15041480Smckusick 	 * Pseudo-devices cannot be read, nothing more to do.
15141480Smckusick 	 */
15241480Smckusick 	if (dptr->hd_flags & HIL_PSEUDO)
15341480Smckusick 		return(0);
15441480Smckusick 
15541480Smckusick 	/*
15641480Smckusick 	 * Open semantics:
15741480Smckusick 	 * 1.	Open devices have only one of HIL_READIN/HIL_QUEUEIN.
15841480Smckusick 	 * 2.	HPUX processes always get read syscall interface and
15941480Smckusick 	 *	must have exclusive use of the device.
16041480Smckusick 	 * 3.	BSD processes default to shared queue interface.
16141480Smckusick 	 *	Multiple processes can open the device.
16241480Smckusick 	 */
16357309Shibler 	if (p->p_md.md_flags & MDP_HPUX) {
16441480Smckusick 		if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN))
16541480Smckusick 			return(EBUSY);
16641480Smckusick 		dptr->hd_flags |= HIL_READIN;
16741480Smckusick 	} else {
16841480Smckusick 		if (dptr->hd_flags & HIL_READIN)
16941480Smckusick 			return(EBUSY);
17041480Smckusick 		dptr->hd_flags |= HIL_QUEUEIN;
17141480Smckusick 	}
17249947Smckusick 	if (flags & FNONBLOCK)
17341480Smckusick 		dptr->hd_flags |= HIL_NOBLOCK;
17441480Smckusick 	/*
17541480Smckusick 	 * It is safe to flush the read buffer as we are guarenteed
17641480Smckusick 	 * that no one else is using it.
17741480Smckusick 	 */
17841480Smckusick 	ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);
17941480Smckusick 
18041480Smckusick 	send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL);
18141480Smckusick 	/*
18241480Smckusick 	 * Opened the keyboard, put in raw mode.
18341480Smckusick 	 */
18441480Smckusick 	(void) splhil();
18541480Smckusick 	if (device == hilp->hl_kbddev) {
18641480Smckusick 		u_char mask = 0;
18741480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);
18841480Smckusick 		hilp->hl_kbdflags |= KBD_RAW;
18941480Smckusick #ifdef DEBUG
19041480Smckusick 		if (hildebug & HDB_KEYBOARD)
19141480Smckusick 			printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev);
19241480Smckusick #endif
19341480Smckusick 	}
19441480Smckusick 	(void) spl0();
19541480Smckusick 	return (0);
19641480Smckusick }
19741480Smckusick 
19841480Smckusick /* ARGSUSED */
19952532Skarels hilclose(dev, flags, mode, p)
20041480Smckusick 	dev_t dev;
201*65643Sbostic 	int flags, mode;
20252532Skarels 	struct proc *p;
20341480Smckusick {
20453923Shibler   	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
20541480Smckusick 	register struct hilloopdev *dptr;
20641480Smckusick 	register int i;
20741480Smckusick 	u_char device = HILUNIT(dev);
20841480Smckusick 	char mask, lpctrl;
20941480Smckusick 
21041480Smckusick #ifdef DEBUG
21141480Smckusick 	if (hildebug & HDB_FOLLOW)
21243316Smckusick 		printf("hilclose(%d): device %x\n", p->p_pid, device);
21341480Smckusick #endif
21441480Smckusick 
21541480Smckusick 	dptr = &hilp->hl_device[device];
21641480Smckusick 	if (device && (dptr->hd_flags & HIL_PSEUDO))
21741480Smckusick 		return (0);
21841480Smckusick 
21957309Shibler 	if (p && (p->p_md.md_flags & MDP_HPUX) == 0) {
22041480Smckusick 		/*
22141480Smckusick 		 * If this is the loop device,
22241480Smckusick 		 * free up all queues belonging to this process.
22341480Smckusick 		 */
22441480Smckusick 		if (device == 0) {
22541480Smckusick 			for (i = 0; i < NHILQ; i++)
22643316Smckusick 				if (hilp->hl_queue[i].hq_procp == p)
22753923Shibler 					(void) hilqfree(hilp, i);
22841480Smckusick 		} else {
22941480Smckusick 			mask = ~hildevmask(device);
23041480Smckusick 			(void) splhil();
23141480Smckusick 			for (i = 0; i < NHILQ; i++)
23243316Smckusick 				if (hilp->hl_queue[i].hq_procp == p) {
23341480Smckusick 					dptr->hd_qmask &= ~hilqmask(i);
23441480Smckusick 					hilp->hl_queue[i].hq_devmask &= mask;
23541480Smckusick 				}
23641480Smckusick 			(void) spl0();
23741480Smckusick 		}
23841480Smckusick 	}
23941480Smckusick 	/*
24041480Smckusick 	 * Always flush the read buffer
24141480Smckusick 	 */
24241480Smckusick 	dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK);
24341480Smckusick 	ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);
24441480Smckusick 	/*
24541480Smckusick 	 * Set keyboard back to cooked mode when closed.
24641480Smckusick 	 */
24741480Smckusick 	(void) splhil();
24841480Smckusick 	if (device && device == hilp->hl_kbddev) {
24941480Smckusick 		mask = 1 << (hilp->hl_kbddev - 1);
25041480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);
25141480Smckusick 		hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2);
25241480Smckusick 		/*
25341480Smckusick 		 * XXX: We have had trouble with keyboards remaining raw
25441480Smckusick 		 * after close due to the LPC_KBDCOOK bit getting cleared
25541480Smckusick 		 * somewhere along the line.  Hence we check and reset
25641480Smckusick 		 * LPCTRL if necessary.
25741480Smckusick 		 */
25841480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl);
25941480Smckusick 		if ((lpctrl & LPC_KBDCOOK) == 0) {
26041480Smckusick 			printf("hilclose: bad LPCTRL %x, reset to %x\n",
26141480Smckusick 			       lpctrl, lpctrl|LPC_KBDCOOK);
26241480Smckusick 			lpctrl |= LPC_KBDCOOK;
26341480Smckusick 			send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL,
26441480Smckusick 					&lpctrl, 1, NULL);
26541480Smckusick 		}
26641480Smckusick #ifdef DEBUG
26741480Smckusick 		if (hildebug & HDB_KEYBOARD)
26841480Smckusick 			printf("hilclose: keyboard %d cooked\n",
26941480Smckusick 			       hilp->hl_kbddev);
27041480Smckusick #endif
27153923Shibler 		kbdenable(HILLOOP(dev));
27241480Smckusick 	}
27341480Smckusick 	(void) spl0();
27441480Smckusick 	return (0);
27541480Smckusick }
27641480Smckusick 
27741480Smckusick /*
27841480Smckusick  * Read interface to HIL device.
27941480Smckusick  */
28041480Smckusick hilread(dev, uio)
28141480Smckusick 	dev_t dev;
28241480Smckusick 	register struct uio *uio;
28341480Smckusick {
28453923Shibler 	struct hilloop *hilp = &hilloop[HILLOOP(dev)];
28541480Smckusick 	register struct hilloopdev *dptr;
28641480Smckusick 	register int cc;
28741480Smckusick 	u_char device = HILUNIT(dev);
28841480Smckusick 	char buf[HILBUFSIZE];
28941480Smckusick 	int error;
29041480Smckusick 
29141480Smckusick #if 0
29241480Smckusick 	/*
29341480Smckusick 	 * XXX: Don't do this since HP-UX doesn't.
29441480Smckusick 	 *
29541480Smckusick 	 * Check device number.
29641480Smckusick 	 * This check is necessary since loop can reconfigure.
29741480Smckusick 	 */
29841480Smckusick 	if (device > hilp->hl_maxdev)
29941480Smckusick 		return(ENODEV);
30041480Smckusick #endif
30141480Smckusick 
30241480Smckusick 	dptr = &hilp->hl_device[device];
30341480Smckusick 	if ((dptr->hd_flags & HIL_READIN) == 0)
30441480Smckusick 		return(ENODEV);
30541480Smckusick 
30641480Smckusick 	(void) splhil();
30741480Smckusick 	while (dptr->hd_queue.c_cc == 0) {
30841480Smckusick 		if (dptr->hd_flags & HIL_NOBLOCK) {
30941480Smckusick 			spl0();
31041480Smckusick 			return(EWOULDBLOCK);
31141480Smckusick 		}
31241480Smckusick 		dptr->hd_flags |= HIL_ASLEEP;
31342360Smckusick 		if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) {
31442360Smckusick 			(void) spl0();
31542360Smckusick 			return (error);
31642360Smckusick 		}
31741480Smckusick 	}
31841480Smckusick 	(void) spl0();
31941480Smckusick 
32041480Smckusick 	error = 0;
32141480Smckusick 	while (uio->uio_resid > 0 && error == 0) {
32241480Smckusick 		cc = hilq_to_b(&dptr->hd_queue, buf,
32355070Spendry 			       min(uio->uio_resid, HILBUFSIZE));
32441480Smckusick 		if (cc <= 0)
32541480Smckusick 			break;
32641480Smckusick 		error = uiomove(buf, cc, uio);
32741480Smckusick 	}
32841480Smckusick 	return(error);
32941480Smckusick }
33041480Smckusick 
33149132Skarels hilioctl(dev, cmd, data, flag, p)
33241480Smckusick 	dev_t dev;
333*65643Sbostic 	int cmd, flag;
33441480Smckusick 	caddr_t data;
33549132Skarels 	struct proc *p;
33641480Smckusick {
33753923Shibler 	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
33841480Smckusick 	char device = HILUNIT(dev);
33941480Smckusick 	struct hilloopdev *dptr;
34041480Smckusick 	register int i;
34141480Smckusick 	u_char hold;
34241480Smckusick 	int error;
34341480Smckusick 
34441480Smckusick #ifdef DEBUG
34541480Smckusick 	if (hildebug & HDB_FOLLOW)
34641480Smckusick 		printf("hilioctl(%d): dev %x cmd %x\n",
34743316Smckusick 		       p->p_pid, device, cmd);
34841480Smckusick #endif
34941480Smckusick 
35041480Smckusick 	dptr = &hilp->hl_device[device];
35141480Smckusick 	if ((dptr->hd_flags & HIL_ALIVE) == 0)
35241480Smckusick 		return (ENODEV);
35341480Smckusick 
35441480Smckusick 	/*
35541480Smckusick 	 * Don't allow hardware ioctls on virtual devices.
35641480Smckusick 	 * Note that though these are the BSD names, they have the same
35741480Smckusick 	 * values as the HP-UX equivalents so we catch them as well.
35841480Smckusick 	 */
35941480Smckusick 	if (dptr->hd_flags & HIL_PSEUDO) {
36041480Smckusick 		switch (cmd) {
36141480Smckusick 		case HILIOCSC:
36241480Smckusick 		case HILIOCID:
36353923Shibler 		case OHILIOCID:
36441480Smckusick 		case HILIOCRN:
36541480Smckusick 		case HILIOCRS:
36641480Smckusick 		case HILIOCED:
36741480Smckusick 			return(ENODEV);
36841480Smckusick 
36941480Smckusick 		/*
37041480Smckusick 		 * XXX: should also return ENODEV but HP-UX compat
37141480Smckusick 		 * breaks if we do.  They work ok right now because
37241480Smckusick 		 * we only recognize one keyboard on the loop.  This
37341480Smckusick 		 * will have to change if we remove that restriction.
37441480Smckusick 		 */
37541480Smckusick 		case HILIOCAROFF:
37641480Smckusick 		case HILIOCAR1:
37741480Smckusick 		case HILIOCAR2:
37841480Smckusick 			break;
37941480Smckusick 
38041480Smckusick 		default:
38141480Smckusick 			break;
38241480Smckusick 		}
38341480Smckusick 	}
38441480Smckusick 
38541480Smckusick #ifdef HPUXCOMPAT
38657309Shibler 	if (p->p_md.md_flags & MDP_HPUX)
38741480Smckusick 		return(hpuxhilioctl(dev, cmd, data, flag));
38841480Smckusick #endif
38941480Smckusick 
39041480Smckusick 	hilp->hl_cmdbp = hilp->hl_cmdbuf;
39141480Smckusick 	bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
39241480Smckusick 	hilp->hl_cmddev = device;
39341480Smckusick 	error = 0;
39441480Smckusick 	switch (cmd) {
39541480Smckusick 
39641480Smckusick 	case HILIOCSBP:
39741480Smckusick 		/* Send four data bytes to the tone gererator. */
39841480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
39941480Smckusick 		/* Send the trigger beeper command to the 8042. */
40041480Smckusick 		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
40141480Smckusick 		break;
40241480Smckusick 
40357309Shibler 	case OHILIOCRRT:
40441480Smckusick 	case HILIOCRRT:
40541480Smckusick 		/* Transfer the real time to the 8042 data buffer */
40641480Smckusick 		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
40741480Smckusick 		/* Read each byte of the real time */
40841480Smckusick 		for (i = 0; i < 5; i++) {
40941480Smckusick 			send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
41041480Smckusick 					0, &hold);
41141480Smckusick 			data[4-i] = hold;
41241480Smckusick 		}
41341480Smckusick 		break;
41441480Smckusick 
41541480Smckusick 	case HILIOCRT:
41641480Smckusick 		for (i = 0; i < 4; i++) {
41741480Smckusick 			send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
41841480Smckusick 					NULL, 0, &hold);
41941480Smckusick 			data[i] = hold;
42041480Smckusick 		}
42141480Smckusick 		break;
42241480Smckusick 
42341480Smckusick 	case HILIOCID:
42453923Shibler 	case OHILIOCID:
42541480Smckusick 	case HILIOCSC:
42641480Smckusick 	case HILIOCRN:
42741480Smckusick 	case HILIOCRS:
42841480Smckusick 	case HILIOCED:
42941480Smckusick 	  	send_hildev_cmd(hilp, device, (cmd & 0xFF));
43041480Smckusick 		bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
43141480Smckusick 	  	break;
43241480Smckusick 
43341480Smckusick         case HILIOCAROFF:
43441480Smckusick         case HILIOCAR1:
43541480Smckusick         case HILIOCAR2:
43641480Smckusick 		if (hilp->hl_kbddev) {
43741480Smckusick 			hilp->hl_cmddev = hilp->hl_kbddev;
43841480Smckusick 			send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
43941480Smckusick 			hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
44041480Smckusick 			if (cmd == HILIOCAR1)
44141480Smckusick 				hilp->hl_kbdflags |= KBD_AR1;
44241480Smckusick 			else if (cmd == HILIOCAR2)
44341480Smckusick 				hilp->hl_kbdflags |= KBD_AR2;
44441480Smckusick 		}
44541480Smckusick 		break;
44641480Smckusick 
44741480Smckusick 	case HILIOCBEEP:
44841480Smckusick 		hilbeep(hilp, (struct _hilbell *)data);
44941480Smckusick 		break;
45041480Smckusick 
45141480Smckusick 	case FIONBIO:
45241480Smckusick 		dptr = &hilp->hl_device[device];
45341480Smckusick 		if (*(int *)data)
45441480Smckusick 			dptr->hd_flags |= HIL_NOBLOCK;
45541480Smckusick 		else
45641480Smckusick 			dptr->hd_flags &= ~HIL_NOBLOCK;
45741480Smckusick 		break;
45841480Smckusick 
45941480Smckusick 	/*
46041480Smckusick 	 * FIOASYNC must be present for FIONBIO above to work!
46141480Smckusick 	 * (See fcntl in kern_descrip.c).
46241480Smckusick 	 */
46341480Smckusick 	case FIOASYNC:
46441480Smckusick 		break;
46541480Smckusick 
46641480Smckusick         case HILIOCALLOCQ:
46753923Shibler 		error = hilqalloc(hilp, (struct hilqinfo *)data);
46841480Smckusick 		break;
46941480Smckusick 
47041480Smckusick         case HILIOCFREEQ:
47153923Shibler 		error = hilqfree(hilp, ((struct hilqinfo *)data)->qid);
47241480Smckusick 		break;
47341480Smckusick 
47441480Smckusick         case HILIOCMAPQ:
47553923Shibler 		error = hilqmap(hilp, *(int *)data, device);
47641480Smckusick 		break;
47741480Smckusick 
47841480Smckusick         case HILIOCUNMAPQ:
47953923Shibler 		error = hilqunmap(hilp, *(int *)data, device);
48041480Smckusick 		break;
48141480Smckusick 
48241480Smckusick 	case HILIOCHPUX:
48341480Smckusick 		dptr = &hilp->hl_device[device];
48441480Smckusick 		dptr->hd_flags |= HIL_READIN;
48541480Smckusick 		dptr->hd_flags &= ~HIL_QUEUEIN;
48641480Smckusick 		break;
48741480Smckusick 
48841480Smckusick         case HILIOCRESET:
48941480Smckusick 	        hilreset(hilp);
49041480Smckusick 		break;
49141480Smckusick 
49241480Smckusick #ifdef DEBUG
49341480Smckusick         case HILIOCTEST:
49441480Smckusick 		hildebug = *(int *) data;
49541480Smckusick 		break;
49641480Smckusick #endif
49741480Smckusick 
49841480Smckusick         default:
49941480Smckusick 		error = EINVAL;
50041480Smckusick 		break;
50141480Smckusick 
50241480Smckusick 	}
50341480Smckusick 	hilp->hl_cmddev = 0;
50441480Smckusick 	return(error);
50541480Smckusick }
50641480Smckusick 
50741480Smckusick #ifdef HPUXCOMPAT
50841480Smckusick /* ARGSUSED */
50941480Smckusick hpuxhilioctl(dev, cmd, data, flag)
51041480Smckusick 	dev_t dev;
511*65643Sbostic 	int cmd, flag;
51241480Smckusick 	caddr_t data;
51341480Smckusick {
51453923Shibler 	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
51541480Smckusick 	char device = HILUNIT(dev);
51641480Smckusick 	struct hilloopdev *dptr;
51741480Smckusick 	register int i;
51841480Smckusick 	u_char hold;
51941480Smckusick 
52041480Smckusick 	hilp->hl_cmdbp = hilp->hl_cmdbuf;
52141480Smckusick 	bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
52241480Smckusick 	hilp->hl_cmddev = device;
52341480Smckusick 	switch (cmd) {
52441480Smckusick 
52541480Smckusick 	case HILSC:
52641480Smckusick 	case HILID:
52741480Smckusick 	case HILRN:
52841480Smckusick 	case HILRS:
52941480Smckusick 	case HILED:
53041480Smckusick 	case HILP1:
53141480Smckusick 	case HILP2:
53241480Smckusick 	case HILP3:
53341480Smckusick 	case HILP4:
53441480Smckusick 	case HILP5:
53541480Smckusick 	case HILP6:
53641480Smckusick 	case HILP7:
53741480Smckusick 	case HILP:
53841480Smckusick 	case HILA1:
53941480Smckusick 	case HILA2:
54041480Smckusick 	case HILA3:
54141480Smckusick 	case HILA4:
54241480Smckusick 	case HILA5:
54341480Smckusick 	case HILA6:
54441480Smckusick 	case HILA7:
54541480Smckusick 	case HILA:
54641480Smckusick 		send_hildev_cmd(hilp, device, (cmd & 0xFF));
54741480Smckusick 		bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
54841480Smckusick 	  	break;
54941480Smckusick 
55041480Smckusick         case HILDKR:
55141480Smckusick         case HILER1:
55241480Smckusick         case HILER2:
55341480Smckusick 		if (hilp->hl_kbddev) {
55441480Smckusick 			hilp->hl_cmddev = hilp->hl_kbddev;
55541480Smckusick 			send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
55641480Smckusick 			hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
55741480Smckusick 			if (cmd == HILIOCAR1)
55841480Smckusick 				hilp->hl_kbdflags |= KBD_AR1;
55941480Smckusick 			else if (cmd == HILIOCAR2)
56041480Smckusick 				hilp->hl_kbdflags |= KBD_AR2;
56141480Smckusick 		}
56241480Smckusick 		break;
56341480Smckusick 
56441480Smckusick 	case EFTSBP:
56541480Smckusick 		/* Send four data bytes to the tone gererator. */
56641480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
56741480Smckusick 		/* Send the trigger beeper command to the 8042. */
56841480Smckusick 		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
56941480Smckusick 		break;
57041480Smckusick 
57141480Smckusick 	case EFTRRT:
57241480Smckusick 		/* Transfer the real time to the 8042 data buffer */
57341480Smckusick 		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
57441480Smckusick 		/* Read each byte of the real time */
57541480Smckusick 		for (i = 0; i < 5; i++) {
57641480Smckusick 			send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
57741480Smckusick 					0, &hold);
57841480Smckusick 			data[4-i] = hold;
57941480Smckusick 		}
58041480Smckusick 		break;
58141480Smckusick 
58241480Smckusick 	case EFTRT:
58341480Smckusick 		for (i = 0; i < 4; i++) {
58441480Smckusick 			send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
58541480Smckusick 					NULL, 0, &hold);
58641480Smckusick 			data[i] = hold;
58741480Smckusick 		}
58841480Smckusick 		break;
58941480Smckusick 
59041480Smckusick         case EFTRLC:
59141480Smckusick         case EFTRCC:
59241480Smckusick 		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold);
59341480Smckusick 		*data = hold;
59441480Smckusick 		break;
59541480Smckusick 
59641480Smckusick         case EFTSRPG:
59741480Smckusick         case EFTSRD:
59841480Smckusick         case EFTSRR:
59941480Smckusick 		send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL);
60041480Smckusick 		break;
60141480Smckusick 
60241480Smckusick 	case EFTSBI:
60353923Shibler #ifdef hp800
60453923Shibler 		/* XXX big magic */
60553923Shibler 		hold = 7 - (*(u_char *)data >> 5);
60653923Shibler 		*(int *)data = 0x84069008 | (hold << 8);
60753923Shibler 		send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
60853923Shibler 		send_hil_cmd(hilp->hl_addr, 0xC4, NULL, 0, NULL);
60953923Shibler 		break;
61053923Shibler #else
61141480Smckusick 		hilbeep(hilp, (struct _hilbell *)data);
61253923Shibler #endif
61341480Smckusick 		break;
61441480Smckusick 
61541480Smckusick 	case FIONBIO:
61641480Smckusick 		dptr = &hilp->hl_device[device];
61741480Smckusick 		if (*(int *)data)
61841480Smckusick 			dptr->hd_flags |= HIL_NOBLOCK;
61941480Smckusick 		else
62041480Smckusick 			dptr->hd_flags &= ~HIL_NOBLOCK;
62141480Smckusick 		break;
62241480Smckusick 
62341480Smckusick 	case FIOASYNC:
62441480Smckusick 		break;
62541480Smckusick 
62641480Smckusick         default:
62741480Smckusick 		hilp->hl_cmddev = 0;
62841480Smckusick 		return(EINVAL);
62941480Smckusick 	}
63041480Smckusick 	hilp->hl_cmddev = 0;
63141480Smckusick 	return(0);
63241480Smckusick }
63341480Smckusick #endif
63441480Smckusick 
63541480Smckusick /* ARGSUSED */
63641480Smckusick hilmap(dev, off, prot)
63741480Smckusick 	dev_t dev;
638*65643Sbostic 	int off, prot;
63941480Smckusick {
64041480Smckusick }
64141480Smckusick 
64241480Smckusick /*ARGSUSED*/
64349132Skarels hilselect(dev, rw, p)
64441480Smckusick 	dev_t dev;
645*65643Sbostic 	int rw;
64649132Skarels 	struct proc *p;
64741480Smckusick {
64853923Shibler 	register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
64941480Smckusick 	register struct hilloopdev *dptr;
65041480Smckusick 	register struct hiliqueue *qp;
65141480Smckusick 	register int mask;
65241480Smckusick 	int s, device;
65341480Smckusick 
65441480Smckusick 	if (rw == FWRITE)
65541480Smckusick 		return (1);
65641480Smckusick 	device = HILUNIT(dev);
65741480Smckusick 
65841480Smckusick 	/*
65941480Smckusick 	 * Read interface.
66041480Smckusick 	 * Return 1 if there is something in the queue, 0 ow.
66141480Smckusick 	 */
66241480Smckusick 	dptr = &hilp->hl_device[device];
66341480Smckusick 	if (dptr->hd_flags & HIL_READIN) {
66441480Smckusick 		s = splhil();
66541480Smckusick 		if (dptr->hd_queue.c_cc) {
66641480Smckusick 			splx(s);
66741480Smckusick 			return (1);
66841480Smckusick 		}
66952533Smckusick 		selrecord(p, &dptr->hd_selr);
67041480Smckusick 		splx(s);
67141480Smckusick 		return (0);
67241480Smckusick 	}
67341480Smckusick 
67441480Smckusick 	/*
67541480Smckusick 	 * Make sure device is alive and real (or the loop device).
67641480Smckusick 	 * Note that we do not do this for the read interface.
67741480Smckusick 	 * This is primarily to be consistant with HP-UX.
67841480Smckusick 	 */
67941480Smckusick 	if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE)
68041480Smckusick 		return (1);
68141480Smckusick 
68241480Smckusick 	/*
68341480Smckusick 	 * Select on loop device is special.
68441480Smckusick 	 * Check to see if there are any data for any loop device
68541480Smckusick 	 * provided it is associated with a queue belonging to this user.
68641480Smckusick 	 */
68741480Smckusick 	if (device == 0)
68841480Smckusick 		mask = -1;
68941480Smckusick 	else
69041480Smckusick 		mask = hildevmask(device);
69141480Smckusick 	/*
69241480Smckusick 	 * Must check everybody with interrupts blocked to prevent races.
69341480Smckusick 	 */
69441480Smckusick 	s = splhil();
69541480Smckusick 	for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++)
69643316Smckusick 		if (qp->hq_procp == p && (mask & qp->hq_devmask) &&
69741480Smckusick 		    qp->hq_eventqueue->hil_evqueue.head !=
69841480Smckusick 		    qp->hq_eventqueue->hil_evqueue.tail) {
69941480Smckusick 			splx(s);
70041480Smckusick 			return (1);
70141480Smckusick 		}
70241480Smckusick 
70352533Smckusick 	selrecord(p, &dptr->hd_selr);
70441480Smckusick 	splx(s);
70541480Smckusick 	return (0);
70641480Smckusick }
70741480Smckusick 
70853923Shibler /*ARGSUSED*/
70953923Shibler hilint(unit)
710*65643Sbostic 	int unit;
71141480Smckusick {
71253923Shibler #ifdef hp300
71353923Shibler 	struct hilloop *hilp = &hilloop[0]; /* XXX how do we know on 300? */
71453923Shibler #else
71553923Shibler 	struct hilloop *hilp = &hilloop[unit];
71653923Shibler #endif
71741480Smckusick 	register struct hil_dev *hildevice = hilp->hl_addr;
71841480Smckusick 	u_char c, stat;
71941480Smckusick 
72053923Shibler 	stat = READHILSTAT(hildevice);
72153923Shibler 	c = READHILDATA(hildevice);		/* clears interrupt */
72253923Shibler 	hil_process_int(hilp, stat, c);
72341480Smckusick }
72441480Smckusick 
72541480Smckusick #include "ite.h"
72641480Smckusick 
72753923Shibler hil_process_int(hilp, stat, c)
72853923Shibler 	register struct hilloop *hilp;
72941480Smckusick 	register u_char stat, c;
73041480Smckusick {
73141480Smckusick #ifdef DEBUG
73241480Smckusick 	if (hildebug & HDB_EVENTS)
73341480Smckusick 		printf("hilint: %x %x\n", stat, c);
73441480Smckusick #endif
73541480Smckusick 
73641480Smckusick 	/* the shift enables the compiler to generate a jump table */
73741480Smckusick 	switch ((stat>>HIL_SSHIFT) & HIL_SMASK) {
73841480Smckusick 
73941480Smckusick #if NITE > 0
74041480Smckusick 	case HIL_KEY:
74141480Smckusick 	case HIL_SHIFT:
74241480Smckusick 	case HIL_CTRL:
74341480Smckusick 	case HIL_CTRLSHIFT:
74441480Smckusick 		itefilter(stat, c);
74541480Smckusick 		return;
74641480Smckusick #endif
74741480Smckusick 
74841480Smckusick 	case HIL_STATUS:			/* The status info. */
74941480Smckusick 		if (c & HIL_ERROR) {
75041480Smckusick 		  	hilp->hl_cmddone = TRUE;
75141480Smckusick 			if (c == HIL_RECONFIG)
75241480Smckusick 				hilconfig(hilp);
75341480Smckusick 			break;
75441480Smckusick 		}
75541480Smckusick 		if (c & HIL_COMMAND) {
75641480Smckusick 		  	if (c & HIL_POLLDATA)	/* End of data */
75741480Smckusick 				hilevent(hilp);
75841480Smckusick 			else			/* End of command */
75941480Smckusick 			  	hilp->hl_cmdending = TRUE;
76041480Smckusick 			hilp->hl_actdev = 0;
76141480Smckusick 		} else {
76241480Smckusick 		  	if (c & HIL_POLLDATA) {	/* Start of polled data */
76341480Smckusick 			  	if (hilp->hl_actdev != 0)
76441480Smckusick 					hilevent(hilp);
76541480Smckusick 				hilp->hl_actdev = (c & HIL_DEVMASK);
76641480Smckusick 				hilp->hl_pollbp = hilp->hl_pollbuf;
76741480Smckusick 			} else {		/* Start of command */
76841480Smckusick 				if (hilp->hl_cmddev == (c & HIL_DEVMASK)) {
76941480Smckusick 					hilp->hl_cmdbp = hilp->hl_cmdbuf;
77041480Smckusick 					hilp->hl_actdev = 0;
77141480Smckusick 				}
77241480Smckusick 			}
77341480Smckusick 		}
77441480Smckusick 	        return;
77541480Smckusick 
77641480Smckusick 	case HIL_DATA:
77741480Smckusick 		if (hilp->hl_actdev != 0)	/* Collecting poll data */
77841480Smckusick 			*hilp->hl_pollbp++ = c;
77941480Smckusick 		else if (hilp->hl_cmddev != 0)  /* Collecting cmd data */
78041480Smckusick 			if (hilp->hl_cmdending) {
78141480Smckusick 				hilp->hl_cmddone = TRUE;
78241480Smckusick 				hilp->hl_cmdending = FALSE;
78341480Smckusick 			} else
78441480Smckusick 				*hilp->hl_cmdbp++ = c;
78541480Smckusick 		return;
78641480Smckusick 
78741480Smckusick 	case 0:		/* force full jump table */
78841480Smckusick 	default:
78941480Smckusick 		return;
79041480Smckusick 	}
79141480Smckusick }
79241480Smckusick 
79341480Smckusick #if defined(DEBUG) && !defined(PANICBUTTON)
79441480Smckusick #define PANICBUTTON
79541480Smckusick #endif
79641480Smckusick 
79741480Smckusick /*
79841480Smckusick  * Optimized macro to compute:
79941480Smckusick  *	eq->head == (eq->tail + 1) % eq->size
80041480Smckusick  * i.e. has tail caught up with head.  We do this because 32 bit long
80141480Smckusick  * remaidering is expensive (a function call with our compiler).
80241480Smckusick  */
80341480Smckusick #define HQFULL(eq)	(((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1)
80441480Smckusick #define HQVALID(eq) \
80541480Smckusick 	((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE)
80641480Smckusick 
80741480Smckusick hilevent(hilp)
80841480Smckusick 	struct hilloop *hilp;
80941480Smckusick {
81041480Smckusick 	register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev];
81141480Smckusick 	register int len, mask, qnum;
81241480Smckusick 	register u_char *cp, *pp;
81341480Smckusick 	register HILQ *hq;
81441480Smckusick 	struct timeval ourtime;
81541480Smckusick 	hil_packet *proto;
81641480Smckusick 	int s, len0;
81741480Smckusick 	long tenths;
81841480Smckusick 
81941480Smckusick #ifdef PANICBUTTON
82041480Smckusick 	static int first;
82141480Smckusick 	extern int panicbutton;
82241480Smckusick 
82341480Smckusick 	cp = hilp->hl_pollbuf;
82441480Smckusick 	if (panicbutton && (*cp & HIL_KBDDATA)) {
82541480Smckusick 		if (*++cp == 0x4E)
82641480Smckusick 			first = 1;
82741480Smckusick 		else if (first && *cp == 0x46 && !panicstr)
82841480Smckusick 			panic("are we having fun yet?");
82941480Smckusick 		else
83041480Smckusick 			first = 0;
83141480Smckusick 	}
83241480Smckusick #endif
83341480Smckusick #ifdef DEBUG
83441480Smckusick 	if (hildebug & HDB_EVENTS) {
83541480Smckusick 		printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev);
83641480Smckusick 		printhilpollbuf(hilp);
83741480Smckusick 		printf("\n");
83841480Smckusick 	}
83941480Smckusick #endif
84041480Smckusick 
84141480Smckusick 	/*
84241480Smckusick 	 * Note that HIL_READIN effectively "shuts off" any queues
84341480Smckusick 	 * that may have been in use at the time of an HILIOCHPUX call.
84441480Smckusick 	 */
84541480Smckusick 	if (dptr->hd_flags & HIL_READIN) {
84641480Smckusick 		hpuxhilevent(hilp, dptr);
84741480Smckusick 		return;
84841480Smckusick 	}
84941480Smckusick 
85041480Smckusick 	/*
85141480Smckusick 	 * If this device isn't on any queue or there are no data
85241480Smckusick 	 * in the packet (can this happen?) do nothing.
85341480Smckusick 	 */
85441480Smckusick 	if (dptr->hd_qmask == 0 ||
85541480Smckusick 	    (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0)
85641480Smckusick 		return;
85741480Smckusick 
85841480Smckusick 	/*
85941480Smckusick 	 * Everybody gets the same time stamp
86041480Smckusick 	 */
86141480Smckusick 	s = splclock();
86241480Smckusick 	ourtime = time;
86341480Smckusick 	splx(s);
86441480Smckusick 	tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
86541480Smckusick 
86641480Smckusick 	proto = NULL;
86741480Smckusick 	mask = dptr->hd_qmask;
86841480Smckusick 	for (qnum = 0; mask; qnum++) {
86941480Smckusick 		if ((mask & hilqmask(qnum)) == 0)
87041480Smckusick 			continue;
87141480Smckusick 		mask &= ~hilqmask(qnum);
87241480Smckusick 		hq = hilp->hl_queue[qnum].hq_eventqueue;
87341480Smckusick 
87441480Smckusick 		/*
87541480Smckusick 		 * Ensure that queue fields that we rely on are valid
87641480Smckusick 		 * and that there is space in the queue.  If either
87741480Smckusick 		 * test fails, we just skip this queue.
87841480Smckusick 		 */
87941480Smckusick 		if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue))
88041480Smckusick 			continue;
88141480Smckusick 
88241480Smckusick 		/*
88341480Smckusick 		 * Copy data to queue.
88441480Smckusick 		 * If this is the first queue we construct the packet
88541480Smckusick 		 * with length, timestamp and poll buffer data.
88641480Smckusick 		 * For second and sucessive packets we just duplicate
88741480Smckusick 		 * the first packet.
88841480Smckusick 		 */
88941480Smckusick 		pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail];
89041480Smckusick 		if (proto == NULL) {
89141480Smckusick 			proto = (hil_packet *)pp;
89241480Smckusick 			cp = hilp->hl_pollbuf;
89341480Smckusick 			len = len0;
89441480Smckusick 			*pp++ = len + 6;
89541480Smckusick 			*pp++ = hilp->hl_actdev;
89641480Smckusick 			*(long *)pp = tenths;
89741480Smckusick 			pp += sizeof(long);
89841480Smckusick 			do *pp++ = *cp++; while (--len);
89941480Smckusick 		} else
90041480Smckusick 			*(hil_packet *)pp = *proto;
90141480Smckusick 
90241480Smckusick 		if (++hq->hil_evqueue.tail == hq->hil_evqueue.size)
90341480Smckusick 			hq->hil_evqueue.tail = 0;
90441480Smckusick 	}
90541480Smckusick 
90641480Smckusick 	/*
90741480Smckusick 	 * Wake up anyone selecting on this device or the loop itself
90841480Smckusick 	 */
90952533Smckusick 	selwakeup(&dptr->hd_selr);
91041480Smckusick 	dptr = &hilp->hl_device[HILLOOPDEV];
91152533Smckusick 	selwakeup(&dptr->hd_selr);
91241480Smckusick }
91341480Smckusick 
91441480Smckusick #undef HQFULL
91541480Smckusick 
91641480Smckusick hpuxhilevent(hilp, dptr)
91741480Smckusick 	register struct hilloop *hilp;
91841480Smckusick 	register struct hilloopdev *dptr;
91941480Smckusick {
92041480Smckusick 	register int len;
92141480Smckusick 	struct timeval ourtime;
92241480Smckusick 	long tstamp;
92341480Smckusick 	int s;
92441480Smckusick 
92541480Smckusick 	/*
92641480Smckusick 	 * Everybody gets the same time stamp
92741480Smckusick 	 */
92841480Smckusick 	s = splclock();
92941480Smckusick 	ourtime = time;
93041480Smckusick 	splx(s);
93141480Smckusick 	tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
93241480Smckusick 
93341480Smckusick 	/*
93441480Smckusick 	 * Each packet that goes into the buffer must be preceded by the
93541480Smckusick 	 * number of bytes in the packet, and the timestamp of the packet.
93641480Smckusick 	 * This adds 5 bytes to the packet size. Make sure there is enough
93741480Smckusick 	 * room in the buffer for it, and if not, toss the packet.
93841480Smckusick 	 */
93941480Smckusick 	len = hilp->hl_pollbp - hilp->hl_pollbuf;
94041480Smckusick 	if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) {
94141480Smckusick 		putc(len+5, &dptr->hd_queue);
94241480Smckusick 		(void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue);
94341480Smckusick 		(void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue);
94441480Smckusick 	}
94541480Smckusick 
94641480Smckusick 	/*
94741480Smckusick 	 * Wake up any one blocked on a read or select
94841480Smckusick 	 */
94941480Smckusick 	if (dptr->hd_flags & HIL_ASLEEP) {
95041480Smckusick 		dptr->hd_flags &= ~HIL_ASLEEP;
95141480Smckusick 		wakeup((caddr_t)dptr);
95241480Smckusick 	}
95352533Smckusick 	selwakeup(&dptr->hd_selr);
95441480Smckusick }
95541480Smckusick 
95641480Smckusick /*
95741480Smckusick  * Shared queue manipulation routines
95841480Smckusick  */
95941480Smckusick 
96053923Shibler hilqalloc(hilp, qip)
96153923Shibler 	register struct hilloop *hilp;
96241480Smckusick 	struct hilqinfo *qip;
96341480Smckusick {
96449132Skarels 	struct proc *p = curproc;		/* XXX */
96541480Smckusick 
96641480Smckusick #ifdef DEBUG
96741480Smckusick 	if (hildebug & HDB_FOLLOW)
96845750Smckusick 		printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr);
96941480Smckusick #endif
97041480Smckusick 	return(EINVAL);
97141480Smckusick }
97241480Smckusick 
97353923Shibler hilqfree(hilp, qnum)
974*65643Sbostic 	register struct hilloop *hilp;
97541480Smckusick 	register int qnum;
97641480Smckusick {
97749132Skarels 	struct proc *p = curproc;		/* XXX */
97841480Smckusick 
97941480Smckusick #ifdef DEBUG
98041480Smckusick 	if (hildebug & HDB_FOLLOW)
98145750Smckusick 		printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum);
98241480Smckusick #endif
98341480Smckusick 	return(EINVAL);
98441480Smckusick }
98541480Smckusick 
98653923Shibler hilqmap(hilp, qnum, device)
98753923Shibler 	register struct hilloop *hilp;
98841480Smckusick 	register int qnum, device;
98941480Smckusick {
99049132Skarels 	struct proc *p = curproc;		/* XXX */
99141480Smckusick 	register struct hilloopdev *dptr = &hilp->hl_device[device];
99241480Smckusick 	int s;
99341480Smckusick 
99441480Smckusick #ifdef DEBUG
99541480Smckusick 	if (hildebug & HDB_FOLLOW)
99641480Smckusick 		printf("hilqmap(%d): qnum %d device %x\n",
99743316Smckusick 		       p->p_pid, qnum, device);
99841480Smckusick #endif
99943316Smckusick 	if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
100041480Smckusick 		return(EINVAL);
100141480Smckusick 	if ((dptr->hd_flags & HIL_QUEUEIN) == 0)
100241480Smckusick 		return(EINVAL);
100349132Skarels 	if (dptr->hd_qmask && p->p_ucred->cr_uid &&
100449132Skarels 	    p->p_ucred->cr_uid != dptr->hd_uid)
100541480Smckusick 		return(EPERM);
100641480Smckusick 
100741480Smckusick 	hilp->hl_queue[qnum].hq_devmask |= hildevmask(device);
100841480Smckusick 	if (dptr->hd_qmask == 0)
100949132Skarels 		dptr->hd_uid = p->p_ucred->cr_uid;
101041480Smckusick 	s = splhil();
101141480Smckusick 	dptr->hd_qmask |= hilqmask(qnum);
101241480Smckusick 	splx(s);
101341480Smckusick #ifdef DEBUG
101441480Smckusick 	if (hildebug & HDB_MASK)
101541480Smckusick 		printf("hilqmap(%d): devmask %x qmask %x\n",
101643316Smckusick 		       p->p_pid, hilp->hl_queue[qnum].hq_devmask,
101741480Smckusick 		       dptr->hd_qmask);
101841480Smckusick #endif
101941480Smckusick 	return(0);
102041480Smckusick }
102141480Smckusick 
102253923Shibler hilqunmap(hilp, qnum, device)
102353923Shibler 	register struct hilloop *hilp;
102441480Smckusick 	register int qnum, device;
102541480Smckusick {
102649132Skarels 	struct proc *p = curproc;		/* XXX */
102741480Smckusick 	int s;
102841480Smckusick 
102941480Smckusick #ifdef DEBUG
103041480Smckusick 	if (hildebug & HDB_FOLLOW)
103141480Smckusick 		printf("hilqunmap(%d): qnum %d device %x\n",
103243316Smckusick 		       p->p_pid, qnum, device);
103341480Smckusick #endif
103441480Smckusick 
103543316Smckusick 	if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
103641480Smckusick 		return(EINVAL);
103741480Smckusick 
103841480Smckusick 	hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device);
103941480Smckusick 	s = splhil();
104041480Smckusick 	hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum);
104141480Smckusick 	splx(s);
104241480Smckusick #ifdef DEBUG
104341480Smckusick 	if (hildebug & HDB_MASK)
104441480Smckusick 		printf("hilqunmap(%d): devmask %x qmask %x\n",
104543316Smckusick 		       p->p_pid, hilp->hl_queue[qnum].hq_devmask,
104641480Smckusick 		       hilp->hl_device[device].hd_qmask);
104741480Smckusick #endif
104841480Smckusick 	return(0);
104941480Smckusick }
105041480Smckusick 
105141480Smckusick /*
105241480Smckusick  * Cooked keyboard functions for ite driver.
105341480Smckusick  * There is only one "cooked" ITE keyboard (the first keyboard found)
105441480Smckusick  * per loop.  There may be other keyboards, but they will always be "raw".
105541480Smckusick  */
105641480Smckusick 
105753923Shibler kbdbell(unit)
105853923Shibler 	int unit;
105941480Smckusick {
106053923Shibler 	struct hilloop *hilp = &hilloop[unit];
106141480Smckusick 
106241480Smckusick 	hilbeep(hilp, &default_bell);
106341480Smckusick }
106441480Smckusick 
106553923Shibler kbdenable(unit)
106653923Shibler 	int unit;
106741480Smckusick {
106853923Shibler 	struct hilloop *hilp = &hilloop[unit];
106941480Smckusick 	register struct hil_dev *hildevice = hilp->hl_addr;
107041480Smckusick 	char db;
107141480Smckusick 
107241480Smckusick 	/* Set the autorepeat rate register */
107341480Smckusick 	db = ar_format(KBD_ARR);
107441480Smckusick 	send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL);
107541480Smckusick 
107641480Smckusick 	/* Set the autorepeat delay register */
107741480Smckusick 	db = ar_format(KBD_ARD);
107841480Smckusick 	send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL);
107941480Smckusick 
108041480Smckusick 	/* Enable interrupts */
108141480Smckusick 	send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
108241480Smckusick }
108341480Smckusick 
108453923Shibler kbddisable(unit)
108553923Shibler 	int unit;
108641480Smckusick {
108741480Smckusick }
108841480Smckusick 
108941480Smckusick /*
109041480Smckusick  * XXX: read keyboard directly and return code.
109141480Smckusick  * Used by console getchar routine.  Could really screw up anybody
109241480Smckusick  * reading from the keyboard in the normal, interrupt driven fashion.
109341480Smckusick  */
109453923Shibler kbdgetc(unit, statp)
109553923Shibler 	int unit, *statp;
109641480Smckusick {
109753923Shibler 	struct hilloop *hilp = &hilloop[unit];
109841480Smckusick 	register struct hil_dev *hildevice = hilp->hl_addr;
109941480Smckusick 	register int c, stat;
110041480Smckusick 	int s;
110141480Smckusick 
110241480Smckusick 	s = splhil();
110353923Shibler 	while (((stat = READHILSTAT(hildevice)) & HIL_DATA_RDY) == 0)
110441480Smckusick 		;
110553923Shibler 	c = READHILDATA(hildevice);
110641480Smckusick 	splx(s);
110741480Smckusick 	*statp = stat;
110841480Smckusick 	return(c);
110941480Smckusick }
111041480Smckusick 
111141480Smckusick /*
111241480Smckusick  * Recoginize and clear keyboard generated NMIs.
111341480Smckusick  * Returns 1 if it was ours, 0 otherwise.  Note that we cannot use
111441480Smckusick  * send_hil_cmd() to issue the clear NMI command as that would actually
111541480Smckusick  * lower the priority to splimp() and it doesn't wait for the completion
111641480Smckusick  * of the command.  Either of these conditions could result in the
111741480Smckusick  * interrupt reoccuring.  Note that we issue the CNMT command twice.
111841480Smckusick  * This seems to be needed, once is not always enough!?!
111941480Smckusick  */
112053923Shibler kbdnmi(unit)
112153923Shibler 	int unit;
112241480Smckusick {
112353923Shibler #ifdef hp300
112453923Shibler 	struct hilloop *hilp = &hilloop[0]; /* XXX how do we know on 300? */
112553923Shibler #else
112653923Shibler 	struct hilloop *hilp = &hilloop[unit];
112753923Shibler #endif
112853923Shibler #ifdef hp300
112941480Smckusick 	if ((*KBDNMISTAT & KBDNMI) == 0)
113041480Smckusick 		return(0);
113153923Shibler #endif
113241480Smckusick 	HILWAIT(hilp->hl_addr);
113353923Shibler 	WRITEHILCMD(hilp->hl_addr, HIL_CNMT);
113441480Smckusick 	HILWAIT(hilp->hl_addr);
113553923Shibler 	WRITEHILCMD(hilp->hl_addr, HIL_CNMT);
113641480Smckusick 	HILWAIT(hilp->hl_addr);
113741480Smckusick 	return(1);
113841480Smckusick }
113941480Smckusick 
114041480Smckusick #define HILSECURITY	0x33
114141480Smckusick #define HILIDENTIFY	0x03
114241480Smckusick #define HILSCBIT	0x04
114341480Smckusick 
114441480Smckusick /*
114541480Smckusick  * Called at boot time to print out info about interesting devices
114641480Smckusick  */
114753923Shibler hilinfo(unit)
114853923Shibler 	int unit;
114941480Smckusick {
115053923Shibler   	register struct hilloop *hilp = &hilloop[unit];
115141480Smckusick 	register int id, len;
115241480Smckusick 	register struct kbdmap *km;
115341480Smckusick 
115441480Smckusick 	/*
115541480Smckusick 	 * Keyboard info.
115641480Smckusick 	 */
115741480Smckusick 	if (hilp->hl_kbddev) {
115841480Smckusick 		printf("hil%d: ", hilp->hl_kbddev);
115941480Smckusick 		for (km = kbd_map; km->kbd_code; km++)
116041480Smckusick 			if (km->kbd_code == hilp->hl_kbdlang) {
116141480Smckusick 				printf("%s ", km->kbd_desc);
116241480Smckusick 				break;
116341480Smckusick 			}
116441480Smckusick 		printf("keyboard\n");
116541480Smckusick 	}
116641480Smckusick 	/*
116741480Smckusick 	 * ID module.
116841480Smckusick 	 * Attempt to locate the first ID module and print out its
116941480Smckusick 	 * security code.  Is this a good idea??
117041480Smckusick 	 */
117141480Smckusick 	id = hiliddev(hilp);
117241480Smckusick 	if (id) {
117341480Smckusick 		hilp->hl_cmdbp = hilp->hl_cmdbuf;
117441480Smckusick 		hilp->hl_cmddev = id;
117541480Smckusick 		send_hildev_cmd(hilp, id, HILSECURITY);
117641480Smckusick 		len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
117741480Smckusick 		hilp->hl_cmdbp = hilp->hl_cmdbuf;
117841480Smckusick 		hilp->hl_cmddev = 0;
117941480Smckusick 		printf("hil%d: security code", id);
118041480Smckusick 		for (id = 0; id < len; id++)
118141480Smckusick 			printf(" %x", hilp->hl_cmdbuf[id]);
118241480Smckusick 		while (id++ < 16)
118341480Smckusick 			printf(" 0");
118441480Smckusick 		printf("\n");
118541480Smckusick 	}
118641480Smckusick }
118741480Smckusick 
118841480Smckusick #define HILAR1	0x3E
118941480Smckusick #define HILAR2	0x3F
119041480Smckusick 
119141480Smckusick /*
119241480Smckusick  * Called after the loop has reconfigured.  Here we need to:
119341480Smckusick  *	- determine how many devices are on the loop
119441480Smckusick  *	  (some may have been added or removed)
119541480Smckusick  *	- locate the ITE keyboard (if any) and ensure
119641480Smckusick  *	  that it is in the proper state (raw or cooked)
119741480Smckusick  *	  and is set to use the proper language mapping table
119841480Smckusick  *	- ensure all other keyboards are raw
119941480Smckusick  * Note that our device state is now potentially invalid as
120041480Smckusick  * devices may no longer be where they were.  What we should
120141480Smckusick  * do here is either track where the devices went and move
120241480Smckusick  * state around accordingly or, more simply, just mark all
120341480Smckusick  * devices as HIL_DERROR and don't allow any further use until
120441480Smckusick  * they are closed.  This is a little too brutal for my tastes,
120541480Smckusick  * we prefer to just assume people won't move things around.
120641480Smckusick  */
120741480Smckusick hilconfig(hilp)
120841480Smckusick 	register struct hilloop *hilp;
120941480Smckusick {
121041480Smckusick 	u_char db;
121141480Smckusick 	int s;
121241480Smckusick 
121341480Smckusick 	s = splhil();
121441480Smckusick #ifdef DEBUG
121541480Smckusick 	if (hildebug & HDB_CONFIG) {
121641480Smckusick 		printf("hilconfig: reconfigured: ");
121741480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
121841480Smckusick 		printf("LPSTAT %x, ", db);
121941480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db);
122041480Smckusick 		printf("LPCTRL %x, ", db);
122141480Smckusick 		send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
122241480Smckusick 		printf("KBDSADR %x\n", db);
122341480Smckusick 		hilreport(hilp);
122441480Smckusick 	}
122541480Smckusick #endif
122641480Smckusick 	/*
122741480Smckusick 	 * Determine how many devices are on the loop.
122841480Smckusick 	 * Mark those as alive and real, all others as dead.
122941480Smckusick 	 */
123041480Smckusick 	db = 0;
123141480Smckusick 	send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
123241480Smckusick 	hilp->hl_maxdev = db & LPS_DEVMASK;
123353923Shibler #ifdef DEBUG
123453923Shibler 	if (hildebug & HDB_CONFIG)
123553923Shibler 		printf("hilconfig: %d devices found\n", hilp->hl_maxdev);
123653923Shibler #endif
123741480Smckusick 	for (db = 1; db < NHILD; db++) {
123841480Smckusick 		if (db <= hilp->hl_maxdev)
123941480Smckusick 			hilp->hl_device[db].hd_flags |= HIL_ALIVE;
124041480Smckusick 		else
124141480Smckusick 			hilp->hl_device[db].hd_flags &= ~HIL_ALIVE;
124241480Smckusick 		hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO;
124341480Smckusick 	}
124441480Smckusick #ifdef DEBUG
124541480Smckusick 	if (hildebug & (HDB_CONFIG|HDB_KEYBOARD))
124641480Smckusick 		printf("hilconfig: max device %d\n", hilp->hl_maxdev);
124741480Smckusick #endif
124841480Smckusick 	if (hilp->hl_maxdev == 0) {
124941480Smckusick 		hilp->hl_kbddev = 0;
125041480Smckusick 		splx(s);
125141480Smckusick 		return;
125241480Smckusick 	}
125341480Smckusick 	/*
125441480Smckusick 	 * Find out where the keyboards are and record the ITE keyboard
125541480Smckusick 	 * (first one found).  If no keyboards found, we are all done.
125641480Smckusick 	 */
125741480Smckusick 	db = 0;
125841480Smckusick 	send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
125941480Smckusick #ifdef DEBUG
126041480Smckusick 	if (hildebug & HDB_KEYBOARD)
126141480Smckusick 		printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n",
126241480Smckusick 		       db, hilp->hl_kbddev, ffs((int)db));
126341480Smckusick #endif
126441480Smckusick 	hilp->hl_kbddev = ffs((int)db);
126541480Smckusick 	if (hilp->hl_kbddev == 0) {
126641480Smckusick 		splx(s);
126741480Smckusick 		return;
126841480Smckusick 	}
126941480Smckusick 	/*
127041480Smckusick 	 * Determine if the keyboard should be cooked or raw and configure it.
127141480Smckusick 	 */
127241480Smckusick 	db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1);
127341480Smckusick 	send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL);
127441480Smckusick 	/*
127541480Smckusick 	 * Re-enable autorepeat in raw mode, cooked mode AR is not affected.
127641480Smckusick 	 */
127741480Smckusick 	if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) {
127841480Smckusick 		db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2;
127941480Smckusick 		hilp->hl_cmddev = hilp->hl_kbddev;
128041480Smckusick 		send_hildev_cmd(hilp, hilp->hl_kbddev, db);
128141480Smckusick 		hilp->hl_cmddev = 0;
128241480Smckusick 	}
128341480Smckusick 	/*
128441480Smckusick 	 * Determine the keyboard language configuration, but don't
128541480Smckusick 	 * override a user-specified setting.
128641480Smckusick 	 */
128741480Smckusick 	db = 0;
128841480Smckusick 	send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db);
128941480Smckusick #ifdef DEBUG
129041480Smckusick 	if (hildebug & HDB_KEYBOARD)
129141480Smckusick 		printf("hilconfig: language: old %x new %x\n",
129241480Smckusick 		       hilp->hl_kbdlang, db);
129341480Smckusick #endif
129441480Smckusick 	if (hilp->hl_kbdlang != KBD_SPECIAL) {
129541480Smckusick 		struct kbdmap *km;
129641480Smckusick 
129741480Smckusick 		for (km = kbd_map; km->kbd_code; km++)
129841480Smckusick 			if (km->kbd_code == db) {
129941480Smckusick 				hilp->hl_kbdlang = db;
130041480Smckusick 				/* XXX */
130141480Smckusick 				kbd_keymap = km->kbd_keymap;
130241480Smckusick 				kbd_shiftmap = km->kbd_shiftmap;
130341480Smckusick 				kbd_ctrlmap = km->kbd_ctrlmap;
130441480Smckusick 				kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;
130541480Smckusick 				kbd_stringmap = km->kbd_stringmap;
130641480Smckusick 			}
130741480Smckusick 	}
130841480Smckusick 	splx(s);
130941480Smckusick }
131041480Smckusick 
131141480Smckusick hilreset(hilp)
131241480Smckusick 	struct hilloop *hilp;
131341480Smckusick {
131441480Smckusick 	register struct hil_dev *hildevice = hilp->hl_addr;
131541480Smckusick 	u_char db;
131641480Smckusick 
131753923Shibler #ifdef DEBUG
131853923Shibler 	if (hildebug & HDB_FOLLOW)
131953923Shibler 		printf("hilreset(%x)\n", hilp);
132053923Shibler #endif
132141480Smckusick 	/*
132241480Smckusick 	 * Initialize the loop: reconfigure, don't report errors,
132341480Smckusick 	 * cook keyboards, and enable autopolling.
132441480Smckusick 	 */
132541480Smckusick 	db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
132641480Smckusick 	send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL);
132741480Smckusick 	/*
132841480Smckusick 	 * Delay one second for reconfiguration and then read the the
132941480Smckusick 	 * data register to clear the interrupt (if the loop reconfigured).
133041480Smckusick 	 */
133141480Smckusick 	DELAY(1000000);
133253923Shibler 	if (READHILSTAT(hildevice) & HIL_DATA_RDY)
133353923Shibler 		db = READHILDATA(hildevice);
133441480Smckusick 	/*
133541480Smckusick 	 * The HIL loop may have reconfigured.  If so we proceed on,
133641480Smckusick 	 * if not we loop until a successful reconfiguration is reported
133741480Smckusick 	 * back to us.  The HIL loop will continue to attempt forever.
133841480Smckusick 	 * Probably not very smart.
133941480Smckusick 	 */
134041480Smckusick 	do {
134141480Smckusick 		send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db);
134241480Smckusick         } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0);
134341480Smckusick 	/*
134441480Smckusick 	 * At this point, the loop should have reconfigured.
134541480Smckusick 	 * The reconfiguration interrupt has already called hilconfig()
134643411Shibler 	 * so the keyboard has been determined.
134741480Smckusick 	 */
134841480Smckusick 	send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
134941480Smckusick }
135041480Smckusick 
135141480Smckusick hilbeep(hilp, bp)
135241480Smckusick 	struct hilloop *hilp;
135341480Smckusick 	register struct _hilbell *bp;
135441480Smckusick {
135541480Smckusick 	u_char buf[2];
135641480Smckusick 
135741480Smckusick 	buf[0] = ~((bp->duration - 10) / 10);
135841480Smckusick 	buf[1] = bp->frequency;
135941480Smckusick 	send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL);
136041480Smckusick }
136141480Smckusick 
136241480Smckusick /*
136341480Smckusick  * Locate and return the address of the first ID module, 0 if none present.
136441480Smckusick  */
136541480Smckusick hiliddev(hilp)
136641480Smckusick 	register struct hilloop *hilp;
136741480Smckusick {
136841480Smckusick 	register int i, len;
136941480Smckusick 
137041480Smckusick #ifdef DEBUG
137141480Smckusick 	if (hildebug & HDB_IDMODULE)
137253923Shibler 		printf("hiliddev(%x): max %d, looking for idmodule...",
137353923Shibler 		       hilp, hilp->hl_maxdev);
137441480Smckusick #endif
137541480Smckusick 	for (i = 1; i <= hilp->hl_maxdev; i++) {
137641480Smckusick 		hilp->hl_cmdbp = hilp->hl_cmdbuf;
137741480Smckusick 		hilp->hl_cmddev = i;
137841480Smckusick 		send_hildev_cmd(hilp, i, HILIDENTIFY);
137941480Smckusick 		/*
138041480Smckusick 		 * XXX: the final condition checks to ensure that the
138141480Smckusick 		 * device ID byte is in the range of the ID module (0x30-0x3F)
138241480Smckusick 		 */
138341480Smckusick 		len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
138441480Smckusick 		if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) &&
138541480Smckusick 		    (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) {
138641480Smckusick 			hilp->hl_cmdbp = hilp->hl_cmdbuf;
138741480Smckusick 			hilp->hl_cmddev = i;
138841480Smckusick 			send_hildev_cmd(hilp, i, HILSECURITY);
138941480Smckusick 			break;
139041480Smckusick 		}
139141480Smckusick 	}
139241480Smckusick 	hilp->hl_cmdbp = hilp->hl_cmdbuf;
139341480Smckusick 	hilp->hl_cmddev = 0;
139441480Smckusick #ifdef DEBUG
139541480Smckusick 	if (hildebug & HDB_IDMODULE)
139641480Smckusick 		if (i <= hilp->hl_maxdev)
139741480Smckusick 			printf("found at %d\n", i);
139841480Smckusick 		else
139941480Smckusick 			printf("not found\n");
140041480Smckusick #endif
140141480Smckusick 	return(i <= hilp->hl_maxdev ? i : 0);
140241480Smckusick }
140341480Smckusick 
140453923Shibler #ifdef HPUXCOMPAT
140541480Smckusick /*
140653923Shibler  * XXX map devno as expected by HP-UX
140753923Shibler  */
140853923Shibler hildevno(dev)
140953923Shibler 	dev_t dev;
141053923Shibler {
141153923Shibler 	int newdev;
141253923Shibler 
141353923Shibler 	newdev = 24 << 24;
141453923Shibler #ifdef HILCOMPAT
141553923Shibler 	/*
141653923Shibler 	 * XXX compat check
141753923Shibler 	 * Don't convert old style specfiles already in correct format
141853923Shibler 	 */
141953923Shibler 	if (minor(dev) && (dev & 0xF) == 0)
142053923Shibler 		newdev |= minor(dev);
142153923Shibler 	else
142253923Shibler #endif
142353923Shibler 	newdev |= (HILLOOP(dev) << 8) | (HILUNIT(dev) << 4);
142453923Shibler 	return(newdev);
142553923Shibler }
142653923Shibler #endif
142753923Shibler 
142853923Shibler /*
142941480Smckusick  * Low level routines which actually talk to the 8042 chip.
143041480Smckusick  */
143141480Smckusick 
143241480Smckusick /*
143341480Smckusick  * Send a command to the 8042 with zero or more bytes of data.
143441480Smckusick  * If rdata is non-null, wait for and return a byte of data.
143541480Smckusick  * We run at splimp() to make the transaction as atomic as
143641480Smckusick  * possible without blocking the clock (is this necessary?)
143741480Smckusick  */
143841480Smckusick send_hil_cmd(hildevice, cmd, data, dlen, rdata)
143941480Smckusick 	register struct hil_dev *hildevice;
144041480Smckusick 	u_char cmd, *data, dlen;
144141480Smckusick 	u_char *rdata;
144241480Smckusick {
144341480Smckusick 	u_char status;
144441480Smckusick 	int s = splimp();
144541480Smckusick 
144641480Smckusick 	HILWAIT(hildevice);
144753923Shibler 	WRITEHILCMD(hildevice, cmd);
144841480Smckusick 	while (dlen--) {
144941480Smckusick 	  	HILWAIT(hildevice);
145053923Shibler 		WRITEHILDATA(hildevice, *data++);
145141480Smckusick 	}
145241480Smckusick 	if (rdata) {
145341480Smckusick 		do {
145441480Smckusick 			HILDATAWAIT(hildevice);
145553923Shibler 			status = READHILSTAT(hildevice);
145653923Shibler 			*rdata = READHILDATA(hildevice);
145741480Smckusick 		} while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
145841480Smckusick 	}
145941480Smckusick 	splx(s);
146041480Smckusick }
146141480Smckusick 
146241480Smckusick /*
146341480Smckusick  * Send a command to a device on the loop.
146441480Smckusick  * Since only one command can be active on the loop at any time,
146541480Smckusick  * we must ensure that we are not interrupted during this process.
146641480Smckusick  * Hence we mask interrupts to prevent potential access from most
146741480Smckusick  * interrupt routines and turn off auto-polling to disable the
146841480Smckusick  * internally generated poll commands.
146941480Smckusick  *
147041480Smckusick  * splhigh is extremely conservative but insures atomic operation,
147141480Smckusick  * splimp (clock only interrupts) seems to be good enough in practice.
147241480Smckusick  */
147341480Smckusick send_hildev_cmd(hilp, device, cmd)
147441480Smckusick 	register struct hilloop *hilp;
147541480Smckusick 	char device, cmd;
147641480Smckusick {
147741480Smckusick 	register struct hil_dev *hildevice = hilp->hl_addr;
147841480Smckusick 	u_char status, c;
147941480Smckusick 	int s = splimp();
148041480Smckusick 
148141480Smckusick 	polloff(hildevice);
148241480Smckusick 
148341480Smckusick 	/*
148441480Smckusick 	 * Transfer the command and device info to the chip
148541480Smckusick 	 */
148641480Smckusick 	HILWAIT(hildevice);
148753923Shibler 	WRITEHILCMD(hildevice, HIL_STARTCMD);
148841480Smckusick   	HILWAIT(hildevice);
148953923Shibler 	WRITEHILDATA(hildevice, 8 + device);
149041480Smckusick   	HILWAIT(hildevice);
149153923Shibler 	WRITEHILDATA(hildevice, cmd);
149241480Smckusick   	HILWAIT(hildevice);
149353923Shibler 	WRITEHILDATA(hildevice, HIL_TIMEOUT);
149441480Smckusick 	/*
149541480Smckusick 	 * Trigger the command and wait for completion
149641480Smckusick 	 */
149741480Smckusick 	HILWAIT(hildevice);
149853923Shibler 	WRITEHILCMD(hildevice, HIL_TRIGGER);
149941480Smckusick 	hilp->hl_cmddone = FALSE;
150041480Smckusick 	do {
150141480Smckusick 		HILDATAWAIT(hildevice);
150253923Shibler 		status = READHILSTAT(hildevice);
150353923Shibler 		c = READHILDATA(hildevice);
150453923Shibler 		hil_process_int(hilp, status, c);
150541480Smckusick 	} while (!hilp->hl_cmddone);
150641480Smckusick 
150741480Smckusick 	pollon(hildevice);
150841480Smckusick 	splx(s);
150941480Smckusick }
151041480Smckusick 
151141480Smckusick /*
151241480Smckusick  * Turn auto-polling off and on.
151341480Smckusick  * Also disables and enable auto-repeat.  Why?
151441480Smckusick  */
151541480Smckusick polloff(hildevice)
151641480Smckusick 	register struct hil_dev *hildevice;
151741480Smckusick {
151841480Smckusick 	register char db;
151941480Smckusick 
152041480Smckusick 	/*
152141480Smckusick 	 * Turn off auto repeat
152241480Smckusick 	 */
152341480Smckusick 	HILWAIT(hildevice);
152453923Shibler 	WRITEHILCMD(hildevice, HIL_SETARR);
152541480Smckusick 	HILWAIT(hildevice);
152653923Shibler 	WRITEHILDATA(hildevice, 0);
152741480Smckusick 	/*
152841480Smckusick 	 * Turn off auto-polling
152941480Smckusick 	 */
153041480Smckusick 	HILWAIT(hildevice);
153153923Shibler 	WRITEHILCMD(hildevice, HIL_READLPCTRL);
153241480Smckusick 	HILDATAWAIT(hildevice);
153353923Shibler 	db = READHILDATA(hildevice);
153441480Smckusick 	db &= ~LPC_AUTOPOLL;
153541480Smckusick 	HILWAIT(hildevice);
153653923Shibler 	WRITEHILCMD(hildevice, HIL_WRITELPCTRL);
153741480Smckusick 	HILWAIT(hildevice);
153853923Shibler 	WRITEHILDATA(hildevice, db);
153941480Smckusick 	/*
154041480Smckusick 	 * Must wait til polling is really stopped
154141480Smckusick 	 */
154241480Smckusick 	do {
154341480Smckusick 		HILWAIT(hildevice);
154453923Shibler 		WRITEHILCMD(hildevice, HIL_READBUSY);
154541480Smckusick 		HILDATAWAIT(hildevice);
154653923Shibler 		db = READHILDATA(hildevice);
154741480Smckusick 	} while (db & BSY_LOOPBUSY);
154841480Smckusick }
154941480Smckusick 
155041480Smckusick pollon(hildevice)
155141480Smckusick 	register struct hil_dev *hildevice;
155241480Smckusick {
155341480Smckusick 	register char db;
155441480Smckusick 
155541480Smckusick 	/*
155641480Smckusick 	 * Turn on auto polling
155741480Smckusick 	 */
155841480Smckusick 	HILWAIT(hildevice);
155953923Shibler 	WRITEHILCMD(hildevice, HIL_READLPCTRL);
156041480Smckusick 	HILDATAWAIT(hildevice);
156153923Shibler 	db = READHILDATA(hildevice);
156241480Smckusick 	db |= LPC_AUTOPOLL;
156341480Smckusick 	HILWAIT(hildevice);
156453923Shibler 	WRITEHILCMD(hildevice, HIL_WRITELPCTRL);
156541480Smckusick 	HILWAIT(hildevice);
156653923Shibler 	WRITEHILDATA(hildevice, db);
156741480Smckusick 	/*
156841480Smckusick 	 * Turn on auto repeat
156941480Smckusick 	 */
157041480Smckusick 	HILWAIT(hildevice);
157153923Shibler 	WRITEHILCMD(hildevice, HIL_SETARR);
157241480Smckusick 	HILWAIT(hildevice);
157353923Shibler 	WRITEHILDATA(hildevice, ar_format(KBD_ARR));
157441480Smckusick }
157541480Smckusick 
157641480Smckusick #ifdef DEBUG
157741480Smckusick printhilpollbuf(hilp)
157841480Smckusick 	register struct hilloop *hilp;
157941480Smckusick {
158041480Smckusick   	register u_char *cp;
158141480Smckusick 	register int i, len;
158241480Smckusick 
158341480Smckusick 	cp = hilp->hl_pollbuf;
158441480Smckusick 	len = hilp->hl_pollbp - cp;
158541480Smckusick 	for (i = 0; i < len; i++)
158641480Smckusick 		printf("%x ", hilp->hl_pollbuf[i]);
158741480Smckusick 	printf("\n");
158841480Smckusick }
158941480Smckusick 
159041480Smckusick printhilcmdbuf(hilp)
159141480Smckusick 	register struct hilloop *hilp;
159241480Smckusick {
159341480Smckusick   	register u_char *cp;
159441480Smckusick 	register int i, len;
159541480Smckusick 
159641480Smckusick 	cp = hilp->hl_cmdbuf;
159741480Smckusick 	len = hilp->hl_cmdbp - cp;
159841480Smckusick 	for (i = 0; i < len; i++)
159941480Smckusick 		printf("%x ", hilp->hl_cmdbuf[i]);
160041480Smckusick 	printf("\n");
160141480Smckusick }
160241480Smckusick 
160341480Smckusick hilreport(hilp)
160441480Smckusick 	register struct hilloop *hilp;
160541480Smckusick {
160641480Smckusick 	register int i, len;
160741480Smckusick 	int s = splhil();
160841480Smckusick 
160941480Smckusick 	for (i = 1; i <= hilp->hl_maxdev; i++) {
161041480Smckusick 		hilp->hl_cmdbp = hilp->hl_cmdbuf;
161141480Smckusick 		hilp->hl_cmddev = i;
161241480Smckusick 		send_hildev_cmd(hilp, i, HILIDENTIFY);
161341480Smckusick 		printf("hil%d: id: ", i);
161441480Smckusick 		printhilcmdbuf(hilp);
161541480Smckusick 		len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
161641480Smckusick 		if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) {
161741480Smckusick 			hilp->hl_cmdbp = hilp->hl_cmdbuf;
161841480Smckusick 			hilp->hl_cmddev = i;
161941480Smckusick 			send_hildev_cmd(hilp, i, HILSECURITY);
162041480Smckusick 			printf("hil%d: sc: ", i);
162141480Smckusick 			printhilcmdbuf(hilp);
162241480Smckusick 		}
162341480Smckusick 	}
162441480Smckusick 	hilp->hl_cmdbp = hilp->hl_cmdbuf;
162541480Smckusick 	hilp->hl_cmddev = 0;
162641480Smckusick 	splx(s);
162741480Smckusick }
162841480Smckusick #endif
1629