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*68159Scgd * @(#)hil.c 8.3 (Berkeley) 01/09/95
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
hilsoftinit(unit,hilbase)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
hilinit(unit,hilbase)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 */
hilopen(dev,flags,mode,p)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 */
hilclose(dev,flags,mode,p)19952532Skarels hilclose(dev, flags, mode, p)
20041480Smckusick dev_t dev;
20165643Sbostic 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 */
hilread(dev,uio)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
hilioctl(dev,cmd,data,flag,p)33149132Skarels hilioctl(dev, cmd, data, flag, p)
33241480Smckusick dev_t dev;
333*68159Scgd u_long cmd;
33441480Smckusick caddr_t data;
335*68159Scgd int flag;
33649132Skarels struct proc *p;
33741480Smckusick {
33853923Shibler register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
33941480Smckusick char device = HILUNIT(dev);
34041480Smckusick struct hilloopdev *dptr;
34141480Smckusick register int i;
34241480Smckusick u_char hold;
34341480Smckusick int error;
34441480Smckusick
34541480Smckusick #ifdef DEBUG
34641480Smckusick if (hildebug & HDB_FOLLOW)
34741480Smckusick printf("hilioctl(%d): dev %x cmd %x\n",
34843316Smckusick p->p_pid, device, cmd);
34941480Smckusick #endif
35041480Smckusick
35141480Smckusick dptr = &hilp->hl_device[device];
35241480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0)
35341480Smckusick return (ENODEV);
35441480Smckusick
35541480Smckusick /*
35641480Smckusick * Don't allow hardware ioctls on virtual devices.
35741480Smckusick * Note that though these are the BSD names, they have the same
35841480Smckusick * values as the HP-UX equivalents so we catch them as well.
35941480Smckusick */
36041480Smckusick if (dptr->hd_flags & HIL_PSEUDO) {
36141480Smckusick switch (cmd) {
36241480Smckusick case HILIOCSC:
36341480Smckusick case HILIOCID:
36453923Shibler case OHILIOCID:
36541480Smckusick case HILIOCRN:
36641480Smckusick case HILIOCRS:
36741480Smckusick case HILIOCED:
36841480Smckusick return(ENODEV);
36941480Smckusick
37041480Smckusick /*
37141480Smckusick * XXX: should also return ENODEV but HP-UX compat
37241480Smckusick * breaks if we do. They work ok right now because
37341480Smckusick * we only recognize one keyboard on the loop. This
37441480Smckusick * will have to change if we remove that restriction.
37541480Smckusick */
37641480Smckusick case HILIOCAROFF:
37741480Smckusick case HILIOCAR1:
37841480Smckusick case HILIOCAR2:
37941480Smckusick break;
38041480Smckusick
38141480Smckusick default:
38241480Smckusick break;
38341480Smckusick }
38441480Smckusick }
38541480Smckusick
38641480Smckusick #ifdef HPUXCOMPAT
38757309Shibler if (p->p_md.md_flags & MDP_HPUX)
38841480Smckusick return(hpuxhilioctl(dev, cmd, data, flag));
38941480Smckusick #endif
39041480Smckusick
39141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
39241480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
39341480Smckusick hilp->hl_cmddev = device;
39441480Smckusick error = 0;
39541480Smckusick switch (cmd) {
39641480Smckusick
39741480Smckusick case HILIOCSBP:
39841480Smckusick /* Send four data bytes to the tone gererator. */
39941480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
40041480Smckusick /* Send the trigger beeper command to the 8042. */
40141480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
40241480Smckusick break;
40341480Smckusick
40457309Shibler case OHILIOCRRT:
40541480Smckusick case HILIOCRRT:
40641480Smckusick /* Transfer the real time to the 8042 data buffer */
40741480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
40841480Smckusick /* Read each byte of the real time */
40941480Smckusick for (i = 0; i < 5; i++) {
41041480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
41141480Smckusick 0, &hold);
41241480Smckusick data[4-i] = hold;
41341480Smckusick }
41441480Smckusick break;
41541480Smckusick
41641480Smckusick case HILIOCRT:
41741480Smckusick for (i = 0; i < 4; i++) {
41841480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
41941480Smckusick NULL, 0, &hold);
42041480Smckusick data[i] = hold;
42141480Smckusick }
42241480Smckusick break;
42341480Smckusick
42441480Smckusick case HILIOCID:
42553923Shibler case OHILIOCID:
42641480Smckusick case HILIOCSC:
42741480Smckusick case HILIOCRN:
42841480Smckusick case HILIOCRS:
42941480Smckusick case HILIOCED:
43041480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF));
43141480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
43241480Smckusick break;
43341480Smckusick
43441480Smckusick case HILIOCAROFF:
43541480Smckusick case HILIOCAR1:
43641480Smckusick case HILIOCAR2:
43741480Smckusick if (hilp->hl_kbddev) {
43841480Smckusick hilp->hl_cmddev = hilp->hl_kbddev;
43941480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
44041480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
44141480Smckusick if (cmd == HILIOCAR1)
44241480Smckusick hilp->hl_kbdflags |= KBD_AR1;
44341480Smckusick else if (cmd == HILIOCAR2)
44441480Smckusick hilp->hl_kbdflags |= KBD_AR2;
44541480Smckusick }
44641480Smckusick break;
44741480Smckusick
44841480Smckusick case HILIOCBEEP:
44941480Smckusick hilbeep(hilp, (struct _hilbell *)data);
45041480Smckusick break;
45141480Smckusick
45241480Smckusick case FIONBIO:
45341480Smckusick dptr = &hilp->hl_device[device];
45441480Smckusick if (*(int *)data)
45541480Smckusick dptr->hd_flags |= HIL_NOBLOCK;
45641480Smckusick else
45741480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK;
45841480Smckusick break;
45941480Smckusick
46041480Smckusick /*
46141480Smckusick * FIOASYNC must be present for FIONBIO above to work!
46241480Smckusick * (See fcntl in kern_descrip.c).
46341480Smckusick */
46441480Smckusick case FIOASYNC:
46541480Smckusick break;
46641480Smckusick
46741480Smckusick case HILIOCALLOCQ:
46853923Shibler error = hilqalloc(hilp, (struct hilqinfo *)data);
46941480Smckusick break;
47041480Smckusick
47141480Smckusick case HILIOCFREEQ:
47253923Shibler error = hilqfree(hilp, ((struct hilqinfo *)data)->qid);
47341480Smckusick break;
47441480Smckusick
47541480Smckusick case HILIOCMAPQ:
47653923Shibler error = hilqmap(hilp, *(int *)data, device);
47741480Smckusick break;
47841480Smckusick
47941480Smckusick case HILIOCUNMAPQ:
48053923Shibler error = hilqunmap(hilp, *(int *)data, device);
48141480Smckusick break;
48241480Smckusick
48341480Smckusick case HILIOCHPUX:
48441480Smckusick dptr = &hilp->hl_device[device];
48541480Smckusick dptr->hd_flags |= HIL_READIN;
48641480Smckusick dptr->hd_flags &= ~HIL_QUEUEIN;
48741480Smckusick break;
48841480Smckusick
48941480Smckusick case HILIOCRESET:
49041480Smckusick hilreset(hilp);
49141480Smckusick break;
49241480Smckusick
49341480Smckusick #ifdef DEBUG
49441480Smckusick case HILIOCTEST:
49541480Smckusick hildebug = *(int *) data;
49641480Smckusick break;
49741480Smckusick #endif
49841480Smckusick
49941480Smckusick default:
50041480Smckusick error = EINVAL;
50141480Smckusick break;
50241480Smckusick
50341480Smckusick }
50441480Smckusick hilp->hl_cmddev = 0;
50541480Smckusick return(error);
50641480Smckusick }
50741480Smckusick
50841480Smckusick #ifdef HPUXCOMPAT
50941480Smckusick /* ARGSUSED */
hpuxhilioctl(dev,cmd,data,flag)51041480Smckusick hpuxhilioctl(dev, cmd, data, flag)
51141480Smckusick dev_t dev;
512*68159Scgd u_long cmd;
51341480Smckusick caddr_t data;
514*68159Scgd int flag;
51541480Smckusick {
51653923Shibler register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
51741480Smckusick char device = HILUNIT(dev);
51841480Smckusick struct hilloopdev *dptr;
51941480Smckusick register int i;
52041480Smckusick u_char hold;
52141480Smckusick
52241480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
52341480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
52441480Smckusick hilp->hl_cmddev = device;
52541480Smckusick switch (cmd) {
52641480Smckusick
52741480Smckusick case HILSC:
52841480Smckusick case HILID:
52941480Smckusick case HILRN:
53041480Smckusick case HILRS:
53141480Smckusick case HILED:
53241480Smckusick case HILP1:
53341480Smckusick case HILP2:
53441480Smckusick case HILP3:
53541480Smckusick case HILP4:
53641480Smckusick case HILP5:
53741480Smckusick case HILP6:
53841480Smckusick case HILP7:
53941480Smckusick case HILP:
54041480Smckusick case HILA1:
54141480Smckusick case HILA2:
54241480Smckusick case HILA3:
54341480Smckusick case HILA4:
54441480Smckusick case HILA5:
54541480Smckusick case HILA6:
54641480Smckusick case HILA7:
54741480Smckusick case HILA:
54841480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF));
54941480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
55041480Smckusick break;
55141480Smckusick
55241480Smckusick case HILDKR:
55341480Smckusick case HILER1:
55441480Smckusick case HILER2:
55541480Smckusick if (hilp->hl_kbddev) {
55641480Smckusick hilp->hl_cmddev = hilp->hl_kbddev;
55741480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
55841480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
55941480Smckusick if (cmd == HILIOCAR1)
56041480Smckusick hilp->hl_kbdflags |= KBD_AR1;
56141480Smckusick else if (cmd == HILIOCAR2)
56241480Smckusick hilp->hl_kbdflags |= KBD_AR2;
56341480Smckusick }
56441480Smckusick break;
56541480Smckusick
56641480Smckusick case EFTSBP:
56741480Smckusick /* Send four data bytes to the tone gererator. */
56841480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
56941480Smckusick /* Send the trigger beeper command to the 8042. */
57041480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
57141480Smckusick break;
57241480Smckusick
57341480Smckusick case EFTRRT:
57441480Smckusick /* Transfer the real time to the 8042 data buffer */
57541480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
57641480Smckusick /* Read each byte of the real time */
57741480Smckusick for (i = 0; i < 5; i++) {
57841480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
57941480Smckusick 0, &hold);
58041480Smckusick data[4-i] = hold;
58141480Smckusick }
58241480Smckusick break;
58341480Smckusick
58441480Smckusick case EFTRT:
58541480Smckusick for (i = 0; i < 4; i++) {
58641480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
58741480Smckusick NULL, 0, &hold);
58841480Smckusick data[i] = hold;
58941480Smckusick }
59041480Smckusick break;
59141480Smckusick
59241480Smckusick case EFTRLC:
59341480Smckusick case EFTRCC:
59441480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold);
59541480Smckusick *data = hold;
59641480Smckusick break;
59741480Smckusick
59841480Smckusick case EFTSRPG:
59941480Smckusick case EFTSRD:
60041480Smckusick case EFTSRR:
60141480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL);
60241480Smckusick break;
60341480Smckusick
60441480Smckusick case EFTSBI:
60553923Shibler #ifdef hp800
60653923Shibler /* XXX big magic */
60753923Shibler hold = 7 - (*(u_char *)data >> 5);
60853923Shibler *(int *)data = 0x84069008 | (hold << 8);
60953923Shibler send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
61053923Shibler send_hil_cmd(hilp->hl_addr, 0xC4, NULL, 0, NULL);
61153923Shibler break;
61253923Shibler #else
61341480Smckusick hilbeep(hilp, (struct _hilbell *)data);
61453923Shibler #endif
61541480Smckusick break;
61641480Smckusick
61741480Smckusick case FIONBIO:
61841480Smckusick dptr = &hilp->hl_device[device];
61941480Smckusick if (*(int *)data)
62041480Smckusick dptr->hd_flags |= HIL_NOBLOCK;
62141480Smckusick else
62241480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK;
62341480Smckusick break;
62441480Smckusick
62541480Smckusick case FIOASYNC:
62641480Smckusick break;
62741480Smckusick
62841480Smckusick default:
62941480Smckusick hilp->hl_cmddev = 0;
63041480Smckusick return(EINVAL);
63141480Smckusick }
63241480Smckusick hilp->hl_cmddev = 0;
63341480Smckusick return(0);
63441480Smckusick }
63541480Smckusick #endif
63641480Smckusick
63741480Smckusick /* ARGSUSED */
hilmap(dev,off,prot)63841480Smckusick hilmap(dev, off, prot)
63941480Smckusick dev_t dev;
64065643Sbostic int off, prot;
64141480Smckusick {
64241480Smckusick }
64341480Smckusick
64441480Smckusick /*ARGSUSED*/
hilselect(dev,rw,p)64549132Skarels hilselect(dev, rw, p)
64641480Smckusick dev_t dev;
64765643Sbostic int rw;
64849132Skarels struct proc *p;
64941480Smckusick {
65053923Shibler register struct hilloop *hilp = &hilloop[HILLOOP(dev)];
65141480Smckusick register struct hilloopdev *dptr;
65241480Smckusick register struct hiliqueue *qp;
65341480Smckusick register int mask;
65441480Smckusick int s, device;
65541480Smckusick
65641480Smckusick if (rw == FWRITE)
65741480Smckusick return (1);
65841480Smckusick device = HILUNIT(dev);
65941480Smckusick
66041480Smckusick /*
66141480Smckusick * Read interface.
66241480Smckusick * Return 1 if there is something in the queue, 0 ow.
66341480Smckusick */
66441480Smckusick dptr = &hilp->hl_device[device];
66541480Smckusick if (dptr->hd_flags & HIL_READIN) {
66641480Smckusick s = splhil();
66741480Smckusick if (dptr->hd_queue.c_cc) {
66841480Smckusick splx(s);
66941480Smckusick return (1);
67041480Smckusick }
67152533Smckusick selrecord(p, &dptr->hd_selr);
67241480Smckusick splx(s);
67341480Smckusick return (0);
67441480Smckusick }
67541480Smckusick
67641480Smckusick /*
67741480Smckusick * Make sure device is alive and real (or the loop device).
67841480Smckusick * Note that we do not do this for the read interface.
67941480Smckusick * This is primarily to be consistant with HP-UX.
68041480Smckusick */
68141480Smckusick if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE)
68241480Smckusick return (1);
68341480Smckusick
68441480Smckusick /*
68541480Smckusick * Select on loop device is special.
68641480Smckusick * Check to see if there are any data for any loop device
68741480Smckusick * provided it is associated with a queue belonging to this user.
68841480Smckusick */
68941480Smckusick if (device == 0)
69041480Smckusick mask = -1;
69141480Smckusick else
69241480Smckusick mask = hildevmask(device);
69341480Smckusick /*
69441480Smckusick * Must check everybody with interrupts blocked to prevent races.
69541480Smckusick */
69641480Smckusick s = splhil();
69741480Smckusick for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++)
69843316Smckusick if (qp->hq_procp == p && (mask & qp->hq_devmask) &&
69941480Smckusick qp->hq_eventqueue->hil_evqueue.head !=
70041480Smckusick qp->hq_eventqueue->hil_evqueue.tail) {
70141480Smckusick splx(s);
70241480Smckusick return (1);
70341480Smckusick }
70441480Smckusick
70552533Smckusick selrecord(p, &dptr->hd_selr);
70641480Smckusick splx(s);
70741480Smckusick return (0);
70841480Smckusick }
70941480Smckusick
71053923Shibler /*ARGSUSED*/
hilint(unit)71153923Shibler hilint(unit)
71265643Sbostic int unit;
71341480Smckusick {
71453923Shibler #ifdef hp300
71553923Shibler struct hilloop *hilp = &hilloop[0]; /* XXX how do we know on 300? */
71653923Shibler #else
71753923Shibler struct hilloop *hilp = &hilloop[unit];
71853923Shibler #endif
71941480Smckusick register struct hil_dev *hildevice = hilp->hl_addr;
72041480Smckusick u_char c, stat;
72141480Smckusick
72253923Shibler stat = READHILSTAT(hildevice);
72353923Shibler c = READHILDATA(hildevice); /* clears interrupt */
72453923Shibler hil_process_int(hilp, stat, c);
72541480Smckusick }
72641480Smckusick
72741480Smckusick #include "ite.h"
72841480Smckusick
hil_process_int(hilp,stat,c)72953923Shibler hil_process_int(hilp, stat, c)
73053923Shibler register struct hilloop *hilp;
73141480Smckusick register u_char stat, c;
73241480Smckusick {
73341480Smckusick #ifdef DEBUG
73441480Smckusick if (hildebug & HDB_EVENTS)
73541480Smckusick printf("hilint: %x %x\n", stat, c);
73641480Smckusick #endif
73741480Smckusick
73841480Smckusick /* the shift enables the compiler to generate a jump table */
73941480Smckusick switch ((stat>>HIL_SSHIFT) & HIL_SMASK) {
74041480Smckusick
74141480Smckusick #if NITE > 0
74241480Smckusick case HIL_KEY:
74341480Smckusick case HIL_SHIFT:
74441480Smckusick case HIL_CTRL:
74541480Smckusick case HIL_CTRLSHIFT:
74641480Smckusick itefilter(stat, c);
74741480Smckusick return;
74841480Smckusick #endif
74941480Smckusick
75041480Smckusick case HIL_STATUS: /* The status info. */
75141480Smckusick if (c & HIL_ERROR) {
75241480Smckusick hilp->hl_cmddone = TRUE;
75341480Smckusick if (c == HIL_RECONFIG)
75441480Smckusick hilconfig(hilp);
75541480Smckusick break;
75641480Smckusick }
75741480Smckusick if (c & HIL_COMMAND) {
75841480Smckusick if (c & HIL_POLLDATA) /* End of data */
75941480Smckusick hilevent(hilp);
76041480Smckusick else /* End of command */
76141480Smckusick hilp->hl_cmdending = TRUE;
76241480Smckusick hilp->hl_actdev = 0;
76341480Smckusick } else {
76441480Smckusick if (c & HIL_POLLDATA) { /* Start of polled data */
76541480Smckusick if (hilp->hl_actdev != 0)
76641480Smckusick hilevent(hilp);
76741480Smckusick hilp->hl_actdev = (c & HIL_DEVMASK);
76841480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf;
76941480Smckusick } else { /* Start of command */
77041480Smckusick if (hilp->hl_cmddev == (c & HIL_DEVMASK)) {
77141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
77241480Smckusick hilp->hl_actdev = 0;
77341480Smckusick }
77441480Smckusick }
77541480Smckusick }
77641480Smckusick return;
77741480Smckusick
77841480Smckusick case HIL_DATA:
77941480Smckusick if (hilp->hl_actdev != 0) /* Collecting poll data */
78041480Smckusick *hilp->hl_pollbp++ = c;
78141480Smckusick else if (hilp->hl_cmddev != 0) /* Collecting cmd data */
78241480Smckusick if (hilp->hl_cmdending) {
78341480Smckusick hilp->hl_cmddone = TRUE;
78441480Smckusick hilp->hl_cmdending = FALSE;
78541480Smckusick } else
78641480Smckusick *hilp->hl_cmdbp++ = c;
78741480Smckusick return;
78841480Smckusick
78941480Smckusick case 0: /* force full jump table */
79041480Smckusick default:
79141480Smckusick return;
79241480Smckusick }
79341480Smckusick }
79441480Smckusick
79541480Smckusick #if defined(DEBUG) && !defined(PANICBUTTON)
79641480Smckusick #define PANICBUTTON
79741480Smckusick #endif
79841480Smckusick
79941480Smckusick /*
80041480Smckusick * Optimized macro to compute:
80141480Smckusick * eq->head == (eq->tail + 1) % eq->size
80241480Smckusick * i.e. has tail caught up with head. We do this because 32 bit long
80341480Smckusick * remaidering is expensive (a function call with our compiler).
80441480Smckusick */
80541480Smckusick #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1)
80641480Smckusick #define HQVALID(eq) \
80741480Smckusick ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE)
80841480Smckusick
80941480Smckusick hilevent(hilp)
81041480Smckusick struct hilloop *hilp;
81141480Smckusick {
81241480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev];
81341480Smckusick register int len, mask, qnum;
81441480Smckusick register u_char *cp, *pp;
81541480Smckusick register HILQ *hq;
81641480Smckusick struct timeval ourtime;
81741480Smckusick hil_packet *proto;
81841480Smckusick int s, len0;
81941480Smckusick long tenths;
82041480Smckusick
82141480Smckusick #ifdef PANICBUTTON
82241480Smckusick static int first;
82341480Smckusick extern int panicbutton;
82441480Smckusick
82541480Smckusick cp = hilp->hl_pollbuf;
82641480Smckusick if (panicbutton && (*cp & HIL_KBDDATA)) {
82741480Smckusick if (*++cp == 0x4E)
82841480Smckusick first = 1;
82941480Smckusick else if (first && *cp == 0x46 && !panicstr)
83041480Smckusick panic("are we having fun yet?");
83141480Smckusick else
83241480Smckusick first = 0;
83341480Smckusick }
83441480Smckusick #endif
83541480Smckusick #ifdef DEBUG
83641480Smckusick if (hildebug & HDB_EVENTS) {
83741480Smckusick printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev);
83841480Smckusick printhilpollbuf(hilp);
83941480Smckusick printf("\n");
84041480Smckusick }
84141480Smckusick #endif
84241480Smckusick
84341480Smckusick /*
84441480Smckusick * Note that HIL_READIN effectively "shuts off" any queues
84541480Smckusick * that may have been in use at the time of an HILIOCHPUX call.
84641480Smckusick */
84741480Smckusick if (dptr->hd_flags & HIL_READIN) {
84841480Smckusick hpuxhilevent(hilp, dptr);
84941480Smckusick return;
85041480Smckusick }
85141480Smckusick
85241480Smckusick /*
85341480Smckusick * If this device isn't on any queue or there are no data
85441480Smckusick * in the packet (can this happen?) do nothing.
85541480Smckusick */
85641480Smckusick if (dptr->hd_qmask == 0 ||
85741480Smckusick (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0)
85841480Smckusick return;
85941480Smckusick
86041480Smckusick /*
86141480Smckusick * Everybody gets the same time stamp
86241480Smckusick */
86341480Smckusick s = splclock();
86441480Smckusick ourtime = time;
86541480Smckusick splx(s);
86641480Smckusick tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
86741480Smckusick
86841480Smckusick proto = NULL;
86941480Smckusick mask = dptr->hd_qmask;
87041480Smckusick for (qnum = 0; mask; qnum++) {
87141480Smckusick if ((mask & hilqmask(qnum)) == 0)
87241480Smckusick continue;
87341480Smckusick mask &= ~hilqmask(qnum);
87441480Smckusick hq = hilp->hl_queue[qnum].hq_eventqueue;
87541480Smckusick
87641480Smckusick /*
87741480Smckusick * Ensure that queue fields that we rely on are valid
87841480Smckusick * and that there is space in the queue. If either
87941480Smckusick * test fails, we just skip this queue.
88041480Smckusick */
88141480Smckusick if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue))
88241480Smckusick continue;
88341480Smckusick
88441480Smckusick /*
88541480Smckusick * Copy data to queue.
88641480Smckusick * If this is the first queue we construct the packet
88741480Smckusick * with length, timestamp and poll buffer data.
88841480Smckusick * For second and sucessive packets we just duplicate
88941480Smckusick * the first packet.
89041480Smckusick */
89141480Smckusick pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail];
89241480Smckusick if (proto == NULL) {
89341480Smckusick proto = (hil_packet *)pp;
89441480Smckusick cp = hilp->hl_pollbuf;
89541480Smckusick len = len0;
89641480Smckusick *pp++ = len + 6;
89741480Smckusick *pp++ = hilp->hl_actdev;
89841480Smckusick *(long *)pp = tenths;
89941480Smckusick pp += sizeof(long);
90041480Smckusick do *pp++ = *cp++; while (--len);
90141480Smckusick } else
90241480Smckusick *(hil_packet *)pp = *proto;
90341480Smckusick
90441480Smckusick if (++hq->hil_evqueue.tail == hq->hil_evqueue.size)
90541480Smckusick hq->hil_evqueue.tail = 0;
90641480Smckusick }
90741480Smckusick
90841480Smckusick /*
90941480Smckusick * Wake up anyone selecting on this device or the loop itself
91041480Smckusick */
91152533Smckusick selwakeup(&dptr->hd_selr);
91241480Smckusick dptr = &hilp->hl_device[HILLOOPDEV];
91352533Smckusick selwakeup(&dptr->hd_selr);
91441480Smckusick }
91541480Smckusick
91641480Smckusick #undef HQFULL
91741480Smckusick
hpuxhilevent(hilp,dptr)91841480Smckusick hpuxhilevent(hilp, dptr)
91941480Smckusick register struct hilloop *hilp;
92041480Smckusick register struct hilloopdev *dptr;
92141480Smckusick {
92241480Smckusick register int len;
92341480Smckusick struct timeval ourtime;
92441480Smckusick long tstamp;
92541480Smckusick int s;
92641480Smckusick
92741480Smckusick /*
92841480Smckusick * Everybody gets the same time stamp
92941480Smckusick */
93041480Smckusick s = splclock();
93141480Smckusick ourtime = time;
93241480Smckusick splx(s);
93341480Smckusick tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
93441480Smckusick
93541480Smckusick /*
93641480Smckusick * Each packet that goes into the buffer must be preceded by the
93741480Smckusick * number of bytes in the packet, and the timestamp of the packet.
93841480Smckusick * This adds 5 bytes to the packet size. Make sure there is enough
93941480Smckusick * room in the buffer for it, and if not, toss the packet.
94041480Smckusick */
94141480Smckusick len = hilp->hl_pollbp - hilp->hl_pollbuf;
94241480Smckusick if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) {
94341480Smckusick putc(len+5, &dptr->hd_queue);
94441480Smckusick (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue);
94541480Smckusick (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue);
94641480Smckusick }
94741480Smckusick
94841480Smckusick /*
94941480Smckusick * Wake up any one blocked on a read or select
95041480Smckusick */
95141480Smckusick if (dptr->hd_flags & HIL_ASLEEP) {
95241480Smckusick dptr->hd_flags &= ~HIL_ASLEEP;
95341480Smckusick wakeup((caddr_t)dptr);
95441480Smckusick }
95552533Smckusick selwakeup(&dptr->hd_selr);
95641480Smckusick }
95741480Smckusick
95841480Smckusick /*
95941480Smckusick * Shared queue manipulation routines
96041480Smckusick */
96141480Smckusick
hilqalloc(hilp,qip)96253923Shibler hilqalloc(hilp, qip)
96353923Shibler register struct hilloop *hilp;
96441480Smckusick struct hilqinfo *qip;
96541480Smckusick {
96649132Skarels struct proc *p = curproc; /* XXX */
96741480Smckusick
96841480Smckusick #ifdef DEBUG
96941480Smckusick if (hildebug & HDB_FOLLOW)
97045750Smckusick printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr);
97141480Smckusick #endif
97241480Smckusick return(EINVAL);
97341480Smckusick }
97441480Smckusick
hilqfree(hilp,qnum)97553923Shibler hilqfree(hilp, qnum)
97665643Sbostic register struct hilloop *hilp;
97741480Smckusick register int qnum;
97841480Smckusick {
97949132Skarels struct proc *p = curproc; /* XXX */
98041480Smckusick
98141480Smckusick #ifdef DEBUG
98241480Smckusick if (hildebug & HDB_FOLLOW)
98345750Smckusick printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum);
98441480Smckusick #endif
98541480Smckusick return(EINVAL);
98641480Smckusick }
98741480Smckusick
hilqmap(hilp,qnum,device)98853923Shibler hilqmap(hilp, qnum, device)
98953923Shibler register struct hilloop *hilp;
99041480Smckusick register int qnum, device;
99141480Smckusick {
99249132Skarels struct proc *p = curproc; /* XXX */
99341480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[device];
99441480Smckusick int s;
99541480Smckusick
99641480Smckusick #ifdef DEBUG
99741480Smckusick if (hildebug & HDB_FOLLOW)
99841480Smckusick printf("hilqmap(%d): qnum %d device %x\n",
99943316Smckusick p->p_pid, qnum, device);
100041480Smckusick #endif
100143316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
100241480Smckusick return(EINVAL);
100341480Smckusick if ((dptr->hd_flags & HIL_QUEUEIN) == 0)
100441480Smckusick return(EINVAL);
100549132Skarels if (dptr->hd_qmask && p->p_ucred->cr_uid &&
100649132Skarels p->p_ucred->cr_uid != dptr->hd_uid)
100741480Smckusick return(EPERM);
100841480Smckusick
100941480Smckusick hilp->hl_queue[qnum].hq_devmask |= hildevmask(device);
101041480Smckusick if (dptr->hd_qmask == 0)
101149132Skarels dptr->hd_uid = p->p_ucred->cr_uid;
101241480Smckusick s = splhil();
101341480Smckusick dptr->hd_qmask |= hilqmask(qnum);
101441480Smckusick splx(s);
101541480Smckusick #ifdef DEBUG
101641480Smckusick if (hildebug & HDB_MASK)
101741480Smckusick printf("hilqmap(%d): devmask %x qmask %x\n",
101843316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask,
101941480Smckusick dptr->hd_qmask);
102041480Smckusick #endif
102141480Smckusick return(0);
102241480Smckusick }
102341480Smckusick
hilqunmap(hilp,qnum,device)102453923Shibler hilqunmap(hilp, qnum, device)
102553923Shibler register struct hilloop *hilp;
102641480Smckusick register int qnum, device;
102741480Smckusick {
102849132Skarels struct proc *p = curproc; /* XXX */
102941480Smckusick int s;
103041480Smckusick
103141480Smckusick #ifdef DEBUG
103241480Smckusick if (hildebug & HDB_FOLLOW)
103341480Smckusick printf("hilqunmap(%d): qnum %d device %x\n",
103443316Smckusick p->p_pid, qnum, device);
103541480Smckusick #endif
103641480Smckusick
103743316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
103841480Smckusick return(EINVAL);
103941480Smckusick
104041480Smckusick hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device);
104141480Smckusick s = splhil();
104241480Smckusick hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum);
104341480Smckusick splx(s);
104441480Smckusick #ifdef DEBUG
104541480Smckusick if (hildebug & HDB_MASK)
104641480Smckusick printf("hilqunmap(%d): devmask %x qmask %x\n",
104743316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask,
104841480Smckusick hilp->hl_device[device].hd_qmask);
104941480Smckusick #endif
105041480Smckusick return(0);
105141480Smckusick }
105241480Smckusick
105341480Smckusick /*
105441480Smckusick * Cooked keyboard functions for ite driver.
105541480Smckusick * There is only one "cooked" ITE keyboard (the first keyboard found)
105641480Smckusick * per loop. There may be other keyboards, but they will always be "raw".
105741480Smckusick */
105841480Smckusick
kbdbell(unit)105953923Shibler kbdbell(unit)
106053923Shibler int unit;
106141480Smckusick {
106253923Shibler struct hilloop *hilp = &hilloop[unit];
106341480Smckusick
106441480Smckusick hilbeep(hilp, &default_bell);
106541480Smckusick }
106641480Smckusick
kbdenable(unit)106753923Shibler kbdenable(unit)
106853923Shibler int unit;
106941480Smckusick {
107053923Shibler struct hilloop *hilp = &hilloop[unit];
107141480Smckusick register struct hil_dev *hildevice = hilp->hl_addr;
107241480Smckusick char db;
107341480Smckusick
107441480Smckusick /* Set the autorepeat rate register */
107541480Smckusick db = ar_format(KBD_ARR);
107641480Smckusick send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL);
107741480Smckusick
107841480Smckusick /* Set the autorepeat delay register */
107941480Smckusick db = ar_format(KBD_ARD);
108041480Smckusick send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL);
108141480Smckusick
108241480Smckusick /* Enable interrupts */
108341480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
108441480Smckusick }
108541480Smckusick
kbddisable(unit)108653923Shibler kbddisable(unit)
108753923Shibler int unit;
108841480Smckusick {
108941480Smckusick }
109041480Smckusick
109141480Smckusick /*
109241480Smckusick * XXX: read keyboard directly and return code.
109341480Smckusick * Used by console getchar routine. Could really screw up anybody
109441480Smckusick * reading from the keyboard in the normal, interrupt driven fashion.
109541480Smckusick */
kbdgetc(unit,statp)109653923Shibler kbdgetc(unit, statp)
109753923Shibler int unit, *statp;
109841480Smckusick {
109953923Shibler struct hilloop *hilp = &hilloop[unit];
110041480Smckusick register struct hil_dev *hildevice = hilp->hl_addr;
110141480Smckusick register int c, stat;
110241480Smckusick int s;
110341480Smckusick
110441480Smckusick s = splhil();
110553923Shibler while (((stat = READHILSTAT(hildevice)) & HIL_DATA_RDY) == 0)
110641480Smckusick ;
110753923Shibler c = READHILDATA(hildevice);
110841480Smckusick splx(s);
110941480Smckusick *statp = stat;
111041480Smckusick return(c);
111141480Smckusick }
111241480Smckusick
111341480Smckusick /*
111441480Smckusick * Recoginize and clear keyboard generated NMIs.
111541480Smckusick * Returns 1 if it was ours, 0 otherwise. Note that we cannot use
111641480Smckusick * send_hil_cmd() to issue the clear NMI command as that would actually
111741480Smckusick * lower the priority to splimp() and it doesn't wait for the completion
111841480Smckusick * of the command. Either of these conditions could result in the
111941480Smckusick * interrupt reoccuring. Note that we issue the CNMT command twice.
112041480Smckusick * This seems to be needed, once is not always enough!?!
112141480Smckusick */
kbdnmi(unit)112253923Shibler kbdnmi(unit)
112353923Shibler int unit;
112441480Smckusick {
112553923Shibler #ifdef hp300
112653923Shibler struct hilloop *hilp = &hilloop[0]; /* XXX how do we know on 300? */
112753923Shibler #else
112853923Shibler struct hilloop *hilp = &hilloop[unit];
112953923Shibler #endif
113053923Shibler #ifdef hp300
113141480Smckusick if ((*KBDNMISTAT & KBDNMI) == 0)
113241480Smckusick return(0);
113353923Shibler #endif
113441480Smckusick HILWAIT(hilp->hl_addr);
113553923Shibler WRITEHILCMD(hilp->hl_addr, HIL_CNMT);
113641480Smckusick HILWAIT(hilp->hl_addr);
113753923Shibler WRITEHILCMD(hilp->hl_addr, HIL_CNMT);
113841480Smckusick HILWAIT(hilp->hl_addr);
113941480Smckusick return(1);
114041480Smckusick }
114141480Smckusick
114241480Smckusick #define HILSECURITY 0x33
114341480Smckusick #define HILIDENTIFY 0x03
114441480Smckusick #define HILSCBIT 0x04
114541480Smckusick
114641480Smckusick /*
114741480Smckusick * Called at boot time to print out info about interesting devices
114841480Smckusick */
hilinfo(unit)114953923Shibler hilinfo(unit)
115053923Shibler int unit;
115141480Smckusick {
115253923Shibler register struct hilloop *hilp = &hilloop[unit];
115341480Smckusick register int id, len;
115441480Smckusick register struct kbdmap *km;
115541480Smckusick
115641480Smckusick /*
115741480Smckusick * Keyboard info.
115841480Smckusick */
115941480Smckusick if (hilp->hl_kbddev) {
116041480Smckusick printf("hil%d: ", hilp->hl_kbddev);
116141480Smckusick for (km = kbd_map; km->kbd_code; km++)
116241480Smckusick if (km->kbd_code == hilp->hl_kbdlang) {
116341480Smckusick printf("%s ", km->kbd_desc);
116441480Smckusick break;
116541480Smckusick }
116641480Smckusick printf("keyboard\n");
116741480Smckusick }
116841480Smckusick /*
116941480Smckusick * ID module.
117041480Smckusick * Attempt to locate the first ID module and print out its
117141480Smckusick * security code. Is this a good idea??
117241480Smckusick */
117341480Smckusick id = hiliddev(hilp);
117441480Smckusick if (id) {
117541480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
117641480Smckusick hilp->hl_cmddev = id;
117741480Smckusick send_hildev_cmd(hilp, id, HILSECURITY);
117841480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
117941480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
118041480Smckusick hilp->hl_cmddev = 0;
118141480Smckusick printf("hil%d: security code", id);
118241480Smckusick for (id = 0; id < len; id++)
118341480Smckusick printf(" %x", hilp->hl_cmdbuf[id]);
118441480Smckusick while (id++ < 16)
118541480Smckusick printf(" 0");
118641480Smckusick printf("\n");
118741480Smckusick }
118841480Smckusick }
118941480Smckusick
119041480Smckusick #define HILAR1 0x3E
119141480Smckusick #define HILAR2 0x3F
119241480Smckusick
119341480Smckusick /*
119441480Smckusick * Called after the loop has reconfigured. Here we need to:
119541480Smckusick * - determine how many devices are on the loop
119641480Smckusick * (some may have been added or removed)
119741480Smckusick * - locate the ITE keyboard (if any) and ensure
119841480Smckusick * that it is in the proper state (raw or cooked)
119941480Smckusick * and is set to use the proper language mapping table
120041480Smckusick * - ensure all other keyboards are raw
120141480Smckusick * Note that our device state is now potentially invalid as
120241480Smckusick * devices may no longer be where they were. What we should
120341480Smckusick * do here is either track where the devices went and move
120441480Smckusick * state around accordingly or, more simply, just mark all
120541480Smckusick * devices as HIL_DERROR and don't allow any further use until
120641480Smckusick * they are closed. This is a little too brutal for my tastes,
120741480Smckusick * we prefer to just assume people won't move things around.
120841480Smckusick */
hilconfig(hilp)120941480Smckusick hilconfig(hilp)
121041480Smckusick register struct hilloop *hilp;
121141480Smckusick {
121241480Smckusick u_char db;
121341480Smckusick int s;
121441480Smckusick
121541480Smckusick s = splhil();
121641480Smckusick #ifdef DEBUG
121741480Smckusick if (hildebug & HDB_CONFIG) {
121841480Smckusick printf("hilconfig: reconfigured: ");
121941480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
122041480Smckusick printf("LPSTAT %x, ", db);
122141480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db);
122241480Smckusick printf("LPCTRL %x, ", db);
122341480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
122441480Smckusick printf("KBDSADR %x\n", db);
122541480Smckusick hilreport(hilp);
122641480Smckusick }
122741480Smckusick #endif
122841480Smckusick /*
122941480Smckusick * Determine how many devices are on the loop.
123041480Smckusick * Mark those as alive and real, all others as dead.
123141480Smckusick */
123241480Smckusick db = 0;
123341480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
123441480Smckusick hilp->hl_maxdev = db & LPS_DEVMASK;
123553923Shibler #ifdef DEBUG
123653923Shibler if (hildebug & HDB_CONFIG)
123753923Shibler printf("hilconfig: %d devices found\n", hilp->hl_maxdev);
123853923Shibler #endif
123941480Smckusick for (db = 1; db < NHILD; db++) {
124041480Smckusick if (db <= hilp->hl_maxdev)
124141480Smckusick hilp->hl_device[db].hd_flags |= HIL_ALIVE;
124241480Smckusick else
124341480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_ALIVE;
124441480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO;
124541480Smckusick }
124641480Smckusick #ifdef DEBUG
124741480Smckusick if (hildebug & (HDB_CONFIG|HDB_KEYBOARD))
124841480Smckusick printf("hilconfig: max device %d\n", hilp->hl_maxdev);
124941480Smckusick #endif
125041480Smckusick if (hilp->hl_maxdev == 0) {
125141480Smckusick hilp->hl_kbddev = 0;
125241480Smckusick splx(s);
125341480Smckusick return;
125441480Smckusick }
125541480Smckusick /*
125641480Smckusick * Find out where the keyboards are and record the ITE keyboard
125741480Smckusick * (first one found). If no keyboards found, we are all done.
125841480Smckusick */
125941480Smckusick db = 0;
126041480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
126141480Smckusick #ifdef DEBUG
126241480Smckusick if (hildebug & HDB_KEYBOARD)
126341480Smckusick printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n",
126441480Smckusick db, hilp->hl_kbddev, ffs((int)db));
126541480Smckusick #endif
126641480Smckusick hilp->hl_kbddev = ffs((int)db);
126741480Smckusick if (hilp->hl_kbddev == 0) {
126841480Smckusick splx(s);
126941480Smckusick return;
127041480Smckusick }
127141480Smckusick /*
127241480Smckusick * Determine if the keyboard should be cooked or raw and configure it.
127341480Smckusick */
127441480Smckusick db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1);
127541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL);
127641480Smckusick /*
127741480Smckusick * Re-enable autorepeat in raw mode, cooked mode AR is not affected.
127841480Smckusick */
127941480Smckusick if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) {
128041480Smckusick db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2;
128141480Smckusick hilp->hl_cmddev = hilp->hl_kbddev;
128241480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, db);
128341480Smckusick hilp->hl_cmddev = 0;
128441480Smckusick }
128541480Smckusick /*
128641480Smckusick * Determine the keyboard language configuration, but don't
128741480Smckusick * override a user-specified setting.
128841480Smckusick */
128941480Smckusick db = 0;
129041480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db);
129141480Smckusick #ifdef DEBUG
129241480Smckusick if (hildebug & HDB_KEYBOARD)
129341480Smckusick printf("hilconfig: language: old %x new %x\n",
129441480Smckusick hilp->hl_kbdlang, db);
129541480Smckusick #endif
129641480Smckusick if (hilp->hl_kbdlang != KBD_SPECIAL) {
129741480Smckusick struct kbdmap *km;
129841480Smckusick
129941480Smckusick for (km = kbd_map; km->kbd_code; km++)
130041480Smckusick if (km->kbd_code == db) {
130141480Smckusick hilp->hl_kbdlang = db;
130241480Smckusick /* XXX */
130341480Smckusick kbd_keymap = km->kbd_keymap;
130441480Smckusick kbd_shiftmap = km->kbd_shiftmap;
130541480Smckusick kbd_ctrlmap = km->kbd_ctrlmap;
130641480Smckusick kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;
130741480Smckusick kbd_stringmap = km->kbd_stringmap;
130841480Smckusick }
130941480Smckusick }
131041480Smckusick splx(s);
131141480Smckusick }
131241480Smckusick
131341480Smckusick hilreset(hilp)
131441480Smckusick struct hilloop *hilp;
131541480Smckusick {
131641480Smckusick register struct hil_dev *hildevice = hilp->hl_addr;
131741480Smckusick u_char db;
131841480Smckusick
131953923Shibler #ifdef DEBUG
132053923Shibler if (hildebug & HDB_FOLLOW)
132153923Shibler printf("hilreset(%x)\n", hilp);
132253923Shibler #endif
132341480Smckusick /*
132441480Smckusick * Initialize the loop: reconfigure, don't report errors,
132541480Smckusick * cook keyboards, and enable autopolling.
132641480Smckusick */
132741480Smckusick db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
132841480Smckusick send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL);
132941480Smckusick /*
133041480Smckusick * Delay one second for reconfiguration and then read the the
133141480Smckusick * data register to clear the interrupt (if the loop reconfigured).
133241480Smckusick */
133341480Smckusick DELAY(1000000);
133453923Shibler if (READHILSTAT(hildevice) & HIL_DATA_RDY)
133553923Shibler db = READHILDATA(hildevice);
133641480Smckusick /*
133741480Smckusick * The HIL loop may have reconfigured. If so we proceed on,
133841480Smckusick * if not we loop until a successful reconfiguration is reported
133941480Smckusick * back to us. The HIL loop will continue to attempt forever.
134041480Smckusick * Probably not very smart.
134141480Smckusick */
134241480Smckusick do {
134341480Smckusick send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db);
134441480Smckusick } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0);
134541480Smckusick /*
134641480Smckusick * At this point, the loop should have reconfigured.
134741480Smckusick * The reconfiguration interrupt has already called hilconfig()
134843411Shibler * so the keyboard has been determined.
134941480Smckusick */
135041480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
135141480Smckusick }
135241480Smckusick
135341480Smckusick hilbeep(hilp, bp)
135441480Smckusick struct hilloop *hilp;
135541480Smckusick register struct _hilbell *bp;
135641480Smckusick {
135741480Smckusick u_char buf[2];
135841480Smckusick
135941480Smckusick buf[0] = ~((bp->duration - 10) / 10);
136041480Smckusick buf[1] = bp->frequency;
136141480Smckusick send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL);
136241480Smckusick }
136341480Smckusick
136441480Smckusick /*
136541480Smckusick * Locate and return the address of the first ID module, 0 if none present.
136641480Smckusick */
hiliddev(hilp)136741480Smckusick hiliddev(hilp)
136841480Smckusick register struct hilloop *hilp;
136941480Smckusick {
137041480Smckusick register int i, len;
137141480Smckusick
137241480Smckusick #ifdef DEBUG
137341480Smckusick if (hildebug & HDB_IDMODULE)
137453923Shibler printf("hiliddev(%x): max %d, looking for idmodule...",
137553923Shibler hilp, hilp->hl_maxdev);
137641480Smckusick #endif
137741480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) {
137841480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
137941480Smckusick hilp->hl_cmddev = i;
138041480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY);
138141480Smckusick /*
138241480Smckusick * XXX: the final condition checks to ensure that the
138341480Smckusick * device ID byte is in the range of the ID module (0x30-0x3F)
138441480Smckusick */
138541480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
138641480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) &&
138741480Smckusick (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) {
138841480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
138941480Smckusick hilp->hl_cmddev = i;
139041480Smckusick send_hildev_cmd(hilp, i, HILSECURITY);
139141480Smckusick break;
139241480Smckusick }
139341480Smckusick }
139441480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
139541480Smckusick hilp->hl_cmddev = 0;
139641480Smckusick #ifdef DEBUG
139741480Smckusick if (hildebug & HDB_IDMODULE)
139841480Smckusick if (i <= hilp->hl_maxdev)
139941480Smckusick printf("found at %d\n", i);
140041480Smckusick else
140141480Smckusick printf("not found\n");
140241480Smckusick #endif
140341480Smckusick return(i <= hilp->hl_maxdev ? i : 0);
140441480Smckusick }
140541480Smckusick
140653923Shibler #ifdef HPUXCOMPAT
140741480Smckusick /*
140853923Shibler * XXX map devno as expected by HP-UX
140953923Shibler */
hildevno(dev)141053923Shibler hildevno(dev)
141153923Shibler dev_t dev;
141253923Shibler {
141353923Shibler int newdev;
141453923Shibler
141553923Shibler newdev = 24 << 24;
141653923Shibler #ifdef HILCOMPAT
141753923Shibler /*
141853923Shibler * XXX compat check
141953923Shibler * Don't convert old style specfiles already in correct format
142053923Shibler */
142153923Shibler if (minor(dev) && (dev & 0xF) == 0)
142253923Shibler newdev |= minor(dev);
142353923Shibler else
142453923Shibler #endif
142553923Shibler newdev |= (HILLOOP(dev) << 8) | (HILUNIT(dev) << 4);
142653923Shibler return(newdev);
142753923Shibler }
142853923Shibler #endif
142953923Shibler
143053923Shibler /*
143141480Smckusick * Low level routines which actually talk to the 8042 chip.
143241480Smckusick */
143341480Smckusick
143441480Smckusick /*
143541480Smckusick * Send a command to the 8042 with zero or more bytes of data.
143641480Smckusick * If rdata is non-null, wait for and return a byte of data.
143741480Smckusick * We run at splimp() to make the transaction as atomic as
143841480Smckusick * possible without blocking the clock (is this necessary?)
143941480Smckusick */
send_hil_cmd(hildevice,cmd,data,dlen,rdata)144041480Smckusick send_hil_cmd(hildevice, cmd, data, dlen, rdata)
144141480Smckusick register struct hil_dev *hildevice;
144241480Smckusick u_char cmd, *data, dlen;
144341480Smckusick u_char *rdata;
144441480Smckusick {
144541480Smckusick u_char status;
144641480Smckusick int s = splimp();
144741480Smckusick
144841480Smckusick HILWAIT(hildevice);
144953923Shibler WRITEHILCMD(hildevice, cmd);
145041480Smckusick while (dlen--) {
145141480Smckusick HILWAIT(hildevice);
145253923Shibler WRITEHILDATA(hildevice, *data++);
145341480Smckusick }
145441480Smckusick if (rdata) {
145541480Smckusick do {
145641480Smckusick HILDATAWAIT(hildevice);
145753923Shibler status = READHILSTAT(hildevice);
145853923Shibler *rdata = READHILDATA(hildevice);
145941480Smckusick } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
146041480Smckusick }
146141480Smckusick splx(s);
146241480Smckusick }
146341480Smckusick
146441480Smckusick /*
146541480Smckusick * Send a command to a device on the loop.
146641480Smckusick * Since only one command can be active on the loop at any time,
146741480Smckusick * we must ensure that we are not interrupted during this process.
146841480Smckusick * Hence we mask interrupts to prevent potential access from most
146941480Smckusick * interrupt routines and turn off auto-polling to disable the
147041480Smckusick * internally generated poll commands.
147141480Smckusick *
147241480Smckusick * splhigh is extremely conservative but insures atomic operation,
147341480Smckusick * splimp (clock only interrupts) seems to be good enough in practice.
147441480Smckusick */
send_hildev_cmd(hilp,device,cmd)147541480Smckusick send_hildev_cmd(hilp, device, cmd)
147641480Smckusick register struct hilloop *hilp;
147741480Smckusick char device, cmd;
147841480Smckusick {
147941480Smckusick register struct hil_dev *hildevice = hilp->hl_addr;
148041480Smckusick u_char status, c;
148141480Smckusick int s = splimp();
148241480Smckusick
148341480Smckusick polloff(hildevice);
148441480Smckusick
148541480Smckusick /*
148641480Smckusick * Transfer the command and device info to the chip
148741480Smckusick */
148841480Smckusick HILWAIT(hildevice);
148953923Shibler WRITEHILCMD(hildevice, HIL_STARTCMD);
149041480Smckusick HILWAIT(hildevice);
149153923Shibler WRITEHILDATA(hildevice, 8 + device);
149241480Smckusick HILWAIT(hildevice);
149353923Shibler WRITEHILDATA(hildevice, cmd);
149441480Smckusick HILWAIT(hildevice);
149553923Shibler WRITEHILDATA(hildevice, HIL_TIMEOUT);
149641480Smckusick /*
149741480Smckusick * Trigger the command and wait for completion
149841480Smckusick */
149941480Smckusick HILWAIT(hildevice);
150053923Shibler WRITEHILCMD(hildevice, HIL_TRIGGER);
150141480Smckusick hilp->hl_cmddone = FALSE;
150241480Smckusick do {
150341480Smckusick HILDATAWAIT(hildevice);
150453923Shibler status = READHILSTAT(hildevice);
150553923Shibler c = READHILDATA(hildevice);
150653923Shibler hil_process_int(hilp, status, c);
150741480Smckusick } while (!hilp->hl_cmddone);
150841480Smckusick
150941480Smckusick pollon(hildevice);
151041480Smckusick splx(s);
151141480Smckusick }
151241480Smckusick
151341480Smckusick /*
151441480Smckusick * Turn auto-polling off and on.
151541480Smckusick * Also disables and enable auto-repeat. Why?
151641480Smckusick */
polloff(hildevice)151741480Smckusick polloff(hildevice)
151841480Smckusick register struct hil_dev *hildevice;
151941480Smckusick {
152041480Smckusick register char db;
152141480Smckusick
152241480Smckusick /*
152341480Smckusick * Turn off auto repeat
152441480Smckusick */
152541480Smckusick HILWAIT(hildevice);
152653923Shibler WRITEHILCMD(hildevice, HIL_SETARR);
152741480Smckusick HILWAIT(hildevice);
152853923Shibler WRITEHILDATA(hildevice, 0);
152941480Smckusick /*
153041480Smckusick * Turn off auto-polling
153141480Smckusick */
153241480Smckusick HILWAIT(hildevice);
153353923Shibler WRITEHILCMD(hildevice, HIL_READLPCTRL);
153441480Smckusick HILDATAWAIT(hildevice);
153553923Shibler db = READHILDATA(hildevice);
153641480Smckusick db &= ~LPC_AUTOPOLL;
153741480Smckusick HILWAIT(hildevice);
153853923Shibler WRITEHILCMD(hildevice, HIL_WRITELPCTRL);
153941480Smckusick HILWAIT(hildevice);
154053923Shibler WRITEHILDATA(hildevice, db);
154141480Smckusick /*
154241480Smckusick * Must wait til polling is really stopped
154341480Smckusick */
154441480Smckusick do {
154541480Smckusick HILWAIT(hildevice);
154653923Shibler WRITEHILCMD(hildevice, HIL_READBUSY);
154741480Smckusick HILDATAWAIT(hildevice);
154853923Shibler db = READHILDATA(hildevice);
154941480Smckusick } while (db & BSY_LOOPBUSY);
155041480Smckusick }
155141480Smckusick
pollon(hildevice)155241480Smckusick pollon(hildevice)
155341480Smckusick register struct hil_dev *hildevice;
155441480Smckusick {
155541480Smckusick register char db;
155641480Smckusick
155741480Smckusick /*
155841480Smckusick * Turn on auto polling
155941480Smckusick */
156041480Smckusick HILWAIT(hildevice);
156153923Shibler WRITEHILCMD(hildevice, HIL_READLPCTRL);
156241480Smckusick HILDATAWAIT(hildevice);
156353923Shibler db = READHILDATA(hildevice);
156441480Smckusick db |= LPC_AUTOPOLL;
156541480Smckusick HILWAIT(hildevice);
156653923Shibler WRITEHILCMD(hildevice, HIL_WRITELPCTRL);
156741480Smckusick HILWAIT(hildevice);
156853923Shibler WRITEHILDATA(hildevice, db);
156941480Smckusick /*
157041480Smckusick * Turn on auto repeat
157141480Smckusick */
157241480Smckusick HILWAIT(hildevice);
157353923Shibler WRITEHILCMD(hildevice, HIL_SETARR);
157441480Smckusick HILWAIT(hildevice);
157553923Shibler WRITEHILDATA(hildevice, ar_format(KBD_ARR));
157641480Smckusick }
157741480Smckusick
157841480Smckusick #ifdef DEBUG
printhilpollbuf(hilp)157941480Smckusick printhilpollbuf(hilp)
158041480Smckusick register struct hilloop *hilp;
158141480Smckusick {
158241480Smckusick register u_char *cp;
158341480Smckusick register int i, len;
158441480Smckusick
158541480Smckusick cp = hilp->hl_pollbuf;
158641480Smckusick len = hilp->hl_pollbp - cp;
158741480Smckusick for (i = 0; i < len; i++)
158841480Smckusick printf("%x ", hilp->hl_pollbuf[i]);
158941480Smckusick printf("\n");
159041480Smckusick }
159141480Smckusick
printhilcmdbuf(hilp)159241480Smckusick printhilcmdbuf(hilp)
159341480Smckusick register struct hilloop *hilp;
159441480Smckusick {
159541480Smckusick register u_char *cp;
159641480Smckusick register int i, len;
159741480Smckusick
159841480Smckusick cp = hilp->hl_cmdbuf;
159941480Smckusick len = hilp->hl_cmdbp - cp;
160041480Smckusick for (i = 0; i < len; i++)
160141480Smckusick printf("%x ", hilp->hl_cmdbuf[i]);
160241480Smckusick printf("\n");
160341480Smckusick }
160441480Smckusick
hilreport(hilp)160541480Smckusick hilreport(hilp)
160641480Smckusick register struct hilloop *hilp;
160741480Smckusick {
160841480Smckusick register int i, len;
160941480Smckusick int s = splhil();
161041480Smckusick
161141480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) {
161241480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
161341480Smckusick hilp->hl_cmddev = i;
161441480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY);
161541480Smckusick printf("hil%d: id: ", i);
161641480Smckusick printhilcmdbuf(hilp);
161741480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
161841480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) {
161941480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
162041480Smckusick hilp->hl_cmddev = i;
162141480Smckusick send_hildev_cmd(hilp, i, HILSECURITY);
162241480Smckusick printf("hil%d: sc: ", i);
162341480Smckusick printhilcmdbuf(hilp);
162441480Smckusick }
162541480Smckusick }
162641480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf;
162741480Smckusick hilp->hl_cmddev = 0;
162841480Smckusick splx(s);
162941480Smckusick }
163041480Smckusick #endif
1631