141480Smckusick /* 241480Smckusick * Copyright (c) 1988 University of Utah. 341480Smckusick * Copyright (c) 1990 The Regents of the University of California. 441480Smckusick * 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 * 1241480Smckusick * from: Utah $Hdr: hil.c 1.33 89/12/22$ 1341480Smckusick * 14*50254Skarels * @(#)hil.c 7.9 (Berkeley) 06/28/91 1541480Smckusick */ 1641480Smckusick 1745788Sbostic #include "sys/param.h" 1845788Sbostic #include "sys/conf.h" 1949132Skarels #include "sys/proc.h" 2045788Sbostic #include "sys/user.h" 2145788Sbostic #include "sys/ioctl.h" 2245788Sbostic #include "sys/file.h" 2345788Sbostic #include "sys/tty.h" 2445788Sbostic #include "sys/systm.h" 2545788Sbostic #include "sys/uio.h" 2645788Sbostic #include "sys/kernel.h" 2741480Smckusick 2841480Smckusick #include "hilreg.h" 2941480Smckusick #include "hilioctl.h" 3041480Smckusick #include "hilvar.h" 3141480Smckusick #include "kbdmap.h" 3241480Smckusick 3349132Skarels #include "machine/cpu.h" 3441480Smckusick 3545788Sbostic #include "vm/vm_param.h" 3645788Sbostic #include "vm/vm_map.h" 3745788Sbostic #include "vm/vm_kern.h" 3845788Sbostic #include "vm/vm_page.h" 3945788Sbostic #include "vm/vm_pager.h" 4045750Smckusick 4141480Smckusick struct hilloop hil0; 4241480Smckusick struct _hilbell default_bell = { BELLDUR, BELLFREQ }; 4341480Smckusick 4441480Smckusick #ifdef DEBUG 4541480Smckusick int hildebug = 0; 4641480Smckusick #define HDB_FOLLOW 0x01 4741480Smckusick #define HDB_MMAP 0x02 4841480Smckusick #define HDB_MASK 0x04 4941480Smckusick #define HDB_CONFIG 0x08 5041480Smckusick #define HDB_KEYBOARD 0x10 5141480Smckusick #define HDB_IDMODULE 0x20 5241480Smckusick #define HDB_EVENTS 0x80 5341480Smckusick #endif 5441480Smckusick 5542360Smckusick /* symbolic sleep message strings */ 5642360Smckusick char hilin[] = "hilin"; 5742360Smckusick 5841480Smckusick hilinit() 5941480Smckusick { 6041480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 6141480Smckusick register int i; 6241480Smckusick 6341480Smckusick /* 6441480Smckusick * Initialize loop information 6541480Smckusick */ 6641480Smckusick hilp->hl_addr = HILADDR; 6741480Smckusick hilp->hl_cmdending = FALSE; 6841480Smckusick hilp->hl_actdev = hilp->hl_cmddev = 0; 6941480Smckusick hilp->hl_cmddone = FALSE; 7041480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 7141480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf; 7241480Smckusick hilp->hl_kbddev = 0; 7341480Smckusick hilp->hl_kbdlang = KBD_DEFAULT; 7441480Smckusick hilp->hl_kbdflags = 0; 7541480Smckusick /* 7641480Smckusick * Clear all queues and device associations with queues 7741480Smckusick */ 7841480Smckusick for (i = 0; i < NHILQ; i++) { 7941480Smckusick hilp->hl_queue[i].hq_eventqueue = NULL; 8041480Smckusick hilp->hl_queue[i].hq_procp = NULL; 8141480Smckusick hilp->hl_queue[i].hq_devmask = 0; 8241480Smckusick } 8341480Smckusick for (i = 0; i < NHILD; i++) 8441480Smckusick hilp->hl_device[i].hd_qmask = 0; 8541480Smckusick hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO); 8641480Smckusick /* 8741480Smckusick * Reset the loop hardware, and collect keyboard/id info 8841480Smckusick */ 8941480Smckusick hilreset(hilp); 9041480Smckusick hilinfo(hilp); 9141480Smckusick kbdenable(); 9241480Smckusick } 9341480Smckusick 9449132Skarels /* ARGSUSED */ 9549132Skarels hilopen(dev, flags, mode, p) 9641480Smckusick dev_t dev; 9749132Skarels int flags, mode; 9849132Skarels struct proc *p; 9941480Smckusick { 10041480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 10141480Smckusick register struct hilloopdev *dptr; 10241480Smckusick u_char device = HILUNIT(dev); 10341480Smckusick 10441480Smckusick #ifdef DEBUG 10541480Smckusick if (hildebug & HDB_FOLLOW) 10643316Smckusick printf("hilopen(%d): device %x\n", p->p_pid, device); 10741480Smckusick #endif 10841480Smckusick 10941480Smckusick if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0) 11041480Smckusick return(ENXIO); 11141480Smckusick 11241480Smckusick dptr = &hilp->hl_device[device]; 11341480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0) 11441480Smckusick return(ENODEV); 11541480Smckusick 11641480Smckusick /* 11741480Smckusick * Pseudo-devices cannot be read, nothing more to do. 11841480Smckusick */ 11941480Smckusick if (dptr->hd_flags & HIL_PSEUDO) 12041480Smckusick return(0); 12141480Smckusick 12241480Smckusick /* 12341480Smckusick * Open semantics: 12441480Smckusick * 1. Open devices have only one of HIL_READIN/HIL_QUEUEIN. 12541480Smckusick * 2. HPUX processes always get read syscall interface and 12641480Smckusick * must have exclusive use of the device. 12741480Smckusick * 3. BSD processes default to shared queue interface. 12841480Smckusick * Multiple processes can open the device. 12941480Smckusick */ 13043316Smckusick if (p->p_flag & SHPUX) { 13141480Smckusick if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN)) 13241480Smckusick return(EBUSY); 13341480Smckusick dptr->hd_flags |= HIL_READIN; 13441480Smckusick } else { 13541480Smckusick if (dptr->hd_flags & HIL_READIN) 13641480Smckusick return(EBUSY); 13741480Smckusick dptr->hd_flags |= HIL_QUEUEIN; 13841480Smckusick } 13949947Smckusick if (flags & FNONBLOCK) 14041480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 14141480Smckusick /* 14241480Smckusick * It is safe to flush the read buffer as we are guarenteed 14341480Smckusick * that no one else is using it. 14441480Smckusick */ 14541480Smckusick ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); 14641480Smckusick 14741480Smckusick send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL); 14841480Smckusick /* 14941480Smckusick * Opened the keyboard, put in raw mode. 15041480Smckusick */ 15141480Smckusick (void) splhil(); 15241480Smckusick if (device == hilp->hl_kbddev) { 15341480Smckusick u_char mask = 0; 15441480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); 15541480Smckusick hilp->hl_kbdflags |= KBD_RAW; 15641480Smckusick #ifdef DEBUG 15741480Smckusick if (hildebug & HDB_KEYBOARD) 15841480Smckusick printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev); 15941480Smckusick #endif 16041480Smckusick } 16141480Smckusick (void) spl0(); 16241480Smckusick return (0); 16341480Smckusick } 16441480Smckusick 16541480Smckusick /* ARGSUSED */ 16641480Smckusick hilclose(dev, flags) 16741480Smckusick dev_t dev; 16841480Smckusick { 16949132Skarels struct proc *p = curproc; /* XXX */ 17041480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 17141480Smckusick register struct hilloopdev *dptr; 17241480Smckusick register int i; 17341480Smckusick u_char device = HILUNIT(dev); 17441480Smckusick char mask, lpctrl; 17541480Smckusick 17641480Smckusick #ifdef DEBUG 17741480Smckusick if (hildebug & HDB_FOLLOW) 17843316Smckusick printf("hilclose(%d): device %x\n", p->p_pid, device); 17941480Smckusick #endif 18041480Smckusick 18141480Smckusick dptr = &hilp->hl_device[device]; 18241480Smckusick if (device && (dptr->hd_flags & HIL_PSEUDO)) 18341480Smckusick return (0); 18441480Smckusick 18543316Smckusick if ((p->p_flag & SHPUX) == 0) { 18641480Smckusick /* 18741480Smckusick * If this is the loop device, 18841480Smckusick * free up all queues belonging to this process. 18941480Smckusick */ 19041480Smckusick if (device == 0) { 19141480Smckusick for (i = 0; i < NHILQ; i++) 19243316Smckusick if (hilp->hl_queue[i].hq_procp == p) 19341480Smckusick (void) hilqfree(i); 19441480Smckusick } else { 19541480Smckusick mask = ~hildevmask(device); 19641480Smckusick (void) splhil(); 19741480Smckusick for (i = 0; i < NHILQ; i++) 19843316Smckusick if (hilp->hl_queue[i].hq_procp == p) { 19941480Smckusick dptr->hd_qmask &= ~hilqmask(i); 20041480Smckusick hilp->hl_queue[i].hq_devmask &= mask; 20141480Smckusick } 20241480Smckusick (void) spl0(); 20341480Smckusick } 20441480Smckusick } 20541480Smckusick /* 20641480Smckusick * Always flush the read buffer 20741480Smckusick */ 20841480Smckusick dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK); 20941480Smckusick ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); 21041480Smckusick /* 21141480Smckusick * Set keyboard back to cooked mode when closed. 21241480Smckusick */ 21341480Smckusick (void) splhil(); 21441480Smckusick if (device && device == hilp->hl_kbddev) { 21541480Smckusick mask = 1 << (hilp->hl_kbddev - 1); 21641480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); 21741480Smckusick hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2); 21841480Smckusick /* 21941480Smckusick * XXX: We have had trouble with keyboards remaining raw 22041480Smckusick * after close due to the LPC_KBDCOOK bit getting cleared 22141480Smckusick * somewhere along the line. Hence we check and reset 22241480Smckusick * LPCTRL if necessary. 22341480Smckusick */ 22441480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl); 22541480Smckusick if ((lpctrl & LPC_KBDCOOK) == 0) { 22641480Smckusick printf("hilclose: bad LPCTRL %x, reset to %x\n", 22741480Smckusick lpctrl, lpctrl|LPC_KBDCOOK); 22841480Smckusick lpctrl |= LPC_KBDCOOK; 22941480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL, 23041480Smckusick &lpctrl, 1, NULL); 23141480Smckusick } 23241480Smckusick #ifdef DEBUG 23341480Smckusick if (hildebug & HDB_KEYBOARD) 23441480Smckusick printf("hilclose: keyboard %d cooked\n", 23541480Smckusick hilp->hl_kbddev); 23641480Smckusick #endif 23741480Smckusick kbdenable(); 23841480Smckusick } 23941480Smckusick (void) spl0(); 24041480Smckusick return (0); 24141480Smckusick } 24241480Smckusick 24341480Smckusick /* 24441480Smckusick * Read interface to HIL device. 24541480Smckusick */ 24641480Smckusick hilread(dev, uio) 24741480Smckusick dev_t dev; 24841480Smckusick register struct uio *uio; 24941480Smckusick { 25041480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 25141480Smckusick register struct hilloopdev *dptr; 25241480Smckusick register int cc; 25341480Smckusick u_char device = HILUNIT(dev); 25441480Smckusick char buf[HILBUFSIZE]; 25541480Smckusick int error; 25641480Smckusick 25741480Smckusick #if 0 25841480Smckusick /* 25941480Smckusick * XXX: Don't do this since HP-UX doesn't. 26041480Smckusick * 26141480Smckusick * Check device number. 26241480Smckusick * This check is necessary since loop can reconfigure. 26341480Smckusick */ 26441480Smckusick if (device > hilp->hl_maxdev) 26541480Smckusick return(ENODEV); 26641480Smckusick #endif 26741480Smckusick 26841480Smckusick dptr = &hilp->hl_device[device]; 26941480Smckusick if ((dptr->hd_flags & HIL_READIN) == 0) 27041480Smckusick return(ENODEV); 27141480Smckusick 27241480Smckusick (void) splhil(); 27341480Smckusick while (dptr->hd_queue.c_cc == 0) { 27441480Smckusick if (dptr->hd_flags & HIL_NOBLOCK) { 27541480Smckusick spl0(); 27641480Smckusick return(EWOULDBLOCK); 27741480Smckusick } 27841480Smckusick dptr->hd_flags |= HIL_ASLEEP; 27942360Smckusick if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) { 28042360Smckusick (void) spl0(); 28142360Smckusick return (error); 28242360Smckusick } 28341480Smckusick } 28441480Smckusick (void) spl0(); 28541480Smckusick 28641480Smckusick error = 0; 28741480Smckusick while (uio->uio_resid > 0 && error == 0) { 28841480Smckusick cc = hilq_to_b(&dptr->hd_queue, buf, 28941480Smckusick MIN(uio->uio_resid, HILBUFSIZE)); 29041480Smckusick if (cc <= 0) 29141480Smckusick break; 29241480Smckusick error = uiomove(buf, cc, uio); 29341480Smckusick } 29441480Smckusick return(error); 29541480Smckusick } 29641480Smckusick 29749132Skarels hilioctl(dev, cmd, data, flag, p) 29841480Smckusick dev_t dev; 29941480Smckusick caddr_t data; 30049132Skarels struct proc *p; 30141480Smckusick { 30241480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 30341480Smckusick char device = HILUNIT(dev); 30441480Smckusick struct hilloopdev *dptr; 30541480Smckusick register int i; 30641480Smckusick u_char hold; 30741480Smckusick int error; 30841480Smckusick 30941480Smckusick #ifdef DEBUG 31041480Smckusick if (hildebug & HDB_FOLLOW) 31141480Smckusick printf("hilioctl(%d): dev %x cmd %x\n", 31243316Smckusick p->p_pid, device, cmd); 31341480Smckusick #endif 31441480Smckusick 31541480Smckusick dptr = &hilp->hl_device[device]; 31641480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0) 31741480Smckusick return (ENODEV); 31841480Smckusick 31941480Smckusick /* 32041480Smckusick * Don't allow hardware ioctls on virtual devices. 32141480Smckusick * Note that though these are the BSD names, they have the same 32241480Smckusick * values as the HP-UX equivalents so we catch them as well. 32341480Smckusick */ 32441480Smckusick if (dptr->hd_flags & HIL_PSEUDO) { 32541480Smckusick switch (cmd) { 32641480Smckusick case HILIOCSC: 32741480Smckusick case HILIOCID: 32841480Smckusick case HILIOCRN: 32941480Smckusick case HILIOCRS: 33041480Smckusick case HILIOCED: 33141480Smckusick return(ENODEV); 33241480Smckusick 33341480Smckusick /* 33441480Smckusick * XXX: should also return ENODEV but HP-UX compat 33541480Smckusick * breaks if we do. They work ok right now because 33641480Smckusick * we only recognize one keyboard on the loop. This 33741480Smckusick * will have to change if we remove that restriction. 33841480Smckusick */ 33941480Smckusick case HILIOCAROFF: 34041480Smckusick case HILIOCAR1: 34141480Smckusick case HILIOCAR2: 34241480Smckusick break; 34341480Smckusick 34441480Smckusick default: 34541480Smckusick break; 34641480Smckusick } 34741480Smckusick } 34841480Smckusick 34941480Smckusick #ifdef HPUXCOMPAT 35043316Smckusick if (p->p_flag & SHPUX) 35141480Smckusick return(hpuxhilioctl(dev, cmd, data, flag)); 35241480Smckusick #endif 35341480Smckusick 35441480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 35541480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); 35641480Smckusick hilp->hl_cmddev = device; 35741480Smckusick error = 0; 35841480Smckusick switch (cmd) { 35941480Smckusick 36041480Smckusick case HILIOCSBP: 36141480Smckusick /* Send four data bytes to the tone gererator. */ 36241480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); 36341480Smckusick /* Send the trigger beeper command to the 8042. */ 36441480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 36541480Smckusick break; 36641480Smckusick 36741480Smckusick case HILIOCRRT: 36841480Smckusick /* Transfer the real time to the 8042 data buffer */ 36941480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 37041480Smckusick /* Read each byte of the real time */ 37141480Smckusick for (i = 0; i < 5; i++) { 37241480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 37341480Smckusick 0, &hold); 37441480Smckusick data[4-i] = hold; 37541480Smckusick } 37641480Smckusick break; 37741480Smckusick 37841480Smckusick case HILIOCRT: 37941480Smckusick for (i = 0; i < 4; i++) { 38041480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, 38141480Smckusick NULL, 0, &hold); 38241480Smckusick data[i] = hold; 38341480Smckusick } 38441480Smckusick break; 38541480Smckusick 38641480Smckusick case HILIOCID: 38741480Smckusick case HILIOCSC: 38841480Smckusick case HILIOCRN: 38941480Smckusick case HILIOCRS: 39041480Smckusick case HILIOCED: 39141480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF)); 39241480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); 39341480Smckusick break; 39441480Smckusick 39541480Smckusick case HILIOCAROFF: 39641480Smckusick case HILIOCAR1: 39741480Smckusick case HILIOCAR2: 39841480Smckusick if (hilp->hl_kbddev) { 39941480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 40041480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); 40141480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); 40241480Smckusick if (cmd == HILIOCAR1) 40341480Smckusick hilp->hl_kbdflags |= KBD_AR1; 40441480Smckusick else if (cmd == HILIOCAR2) 40541480Smckusick hilp->hl_kbdflags |= KBD_AR2; 40641480Smckusick } 40741480Smckusick break; 40841480Smckusick 40941480Smckusick case HILIOCBEEP: 41041480Smckusick hilbeep(hilp, (struct _hilbell *)data); 41141480Smckusick break; 41241480Smckusick 41341480Smckusick case FIONBIO: 41441480Smckusick dptr = &hilp->hl_device[device]; 41541480Smckusick if (*(int *)data) 41641480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 41741480Smckusick else 41841480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK; 41941480Smckusick break; 42041480Smckusick 42141480Smckusick /* 42241480Smckusick * FIOASYNC must be present for FIONBIO above to work! 42341480Smckusick * (See fcntl in kern_descrip.c). 42441480Smckusick */ 42541480Smckusick case FIOASYNC: 42641480Smckusick break; 42741480Smckusick 42841480Smckusick case HILIOCALLOCQ: 42941480Smckusick error = hilqalloc((struct hilqinfo *)data); 43041480Smckusick break; 43141480Smckusick 43241480Smckusick case HILIOCFREEQ: 43341480Smckusick error = hilqfree(((struct hilqinfo *)data)->qid); 43441480Smckusick break; 43541480Smckusick 43641480Smckusick case HILIOCMAPQ: 43741480Smckusick error = hilqmap(*(int *)data, device); 43841480Smckusick break; 43941480Smckusick 44041480Smckusick case HILIOCUNMAPQ: 44141480Smckusick error = hilqunmap(*(int *)data, device); 44241480Smckusick break; 44341480Smckusick 44441480Smckusick case HILIOCHPUX: 44541480Smckusick dptr = &hilp->hl_device[device]; 44641480Smckusick dptr->hd_flags |= HIL_READIN; 44741480Smckusick dptr->hd_flags &= ~HIL_QUEUEIN; 44841480Smckusick break; 44941480Smckusick 45041480Smckusick case HILIOCRESET: 45141480Smckusick hilreset(hilp); 45241480Smckusick break; 45341480Smckusick 45441480Smckusick #ifdef DEBUG 45541480Smckusick case HILIOCTEST: 45641480Smckusick hildebug = *(int *) data; 45741480Smckusick break; 45841480Smckusick #endif 45941480Smckusick 46041480Smckusick default: 46141480Smckusick error = EINVAL; 46241480Smckusick break; 46341480Smckusick 46441480Smckusick } 46541480Smckusick hilp->hl_cmddev = 0; 46641480Smckusick return(error); 46741480Smckusick } 46841480Smckusick 46941480Smckusick #ifdef HPUXCOMPAT 47041480Smckusick /* ARGSUSED */ 47141480Smckusick hpuxhilioctl(dev, cmd, data, flag) 47241480Smckusick dev_t dev; 47341480Smckusick caddr_t data; 47441480Smckusick { 47541480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 47641480Smckusick char device = HILUNIT(dev); 47741480Smckusick struct hilloopdev *dptr; 47841480Smckusick register int i; 47941480Smckusick u_char hold; 48041480Smckusick 48141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 48241480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); 48341480Smckusick hilp->hl_cmddev = device; 48441480Smckusick switch (cmd) { 48541480Smckusick 48641480Smckusick case HILSC: 48741480Smckusick case HILID: 48841480Smckusick case HILRN: 48941480Smckusick case HILRS: 49041480Smckusick case HILED: 49141480Smckusick case HILP1: 49241480Smckusick case HILP2: 49341480Smckusick case HILP3: 49441480Smckusick case HILP4: 49541480Smckusick case HILP5: 49641480Smckusick case HILP6: 49741480Smckusick case HILP7: 49841480Smckusick case HILP: 49941480Smckusick case HILA1: 50041480Smckusick case HILA2: 50141480Smckusick case HILA3: 50241480Smckusick case HILA4: 50341480Smckusick case HILA5: 50441480Smckusick case HILA6: 50541480Smckusick case HILA7: 50641480Smckusick case HILA: 50741480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF)); 50841480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); 50941480Smckusick break; 51041480Smckusick 51141480Smckusick case HILDKR: 51241480Smckusick case HILER1: 51341480Smckusick case HILER2: 51441480Smckusick if (hilp->hl_kbddev) { 51541480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 51641480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); 51741480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); 51841480Smckusick if (cmd == HILIOCAR1) 51941480Smckusick hilp->hl_kbdflags |= KBD_AR1; 52041480Smckusick else if (cmd == HILIOCAR2) 52141480Smckusick hilp->hl_kbdflags |= KBD_AR2; 52241480Smckusick } 52341480Smckusick break; 52441480Smckusick 52541480Smckusick case EFTSBP: 52641480Smckusick /* Send four data bytes to the tone gererator. */ 52741480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); 52841480Smckusick /* Send the trigger beeper command to the 8042. */ 52941480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 53041480Smckusick break; 53141480Smckusick 53241480Smckusick case EFTRRT: 53341480Smckusick /* Transfer the real time to the 8042 data buffer */ 53441480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 53541480Smckusick /* Read each byte of the real time */ 53641480Smckusick for (i = 0; i < 5; i++) { 53741480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 53841480Smckusick 0, &hold); 53941480Smckusick data[4-i] = hold; 54041480Smckusick } 54141480Smckusick break; 54241480Smckusick 54341480Smckusick case EFTRT: 54441480Smckusick for (i = 0; i < 4; i++) { 54541480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, 54641480Smckusick NULL, 0, &hold); 54741480Smckusick data[i] = hold; 54841480Smckusick } 54941480Smckusick break; 55041480Smckusick 55141480Smckusick case EFTRLC: 55241480Smckusick case EFTRCC: 55341480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold); 55441480Smckusick *data = hold; 55541480Smckusick break; 55641480Smckusick 55741480Smckusick case EFTSRPG: 55841480Smckusick case EFTSRD: 55941480Smckusick case EFTSRR: 56041480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL); 56141480Smckusick break; 56241480Smckusick 56341480Smckusick case EFTSBI: 56441480Smckusick hilbeep(hilp, (struct _hilbell *)data); 56541480Smckusick break; 56641480Smckusick 56741480Smckusick case FIONBIO: 56841480Smckusick dptr = &hilp->hl_device[device]; 56941480Smckusick if (*(int *)data) 57041480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 57141480Smckusick else 57241480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK; 57341480Smckusick break; 57441480Smckusick 57541480Smckusick case FIOASYNC: 57641480Smckusick break; 57741480Smckusick 57841480Smckusick default: 57941480Smckusick hilp->hl_cmddev = 0; 58041480Smckusick return(EINVAL); 58141480Smckusick } 58241480Smckusick hilp->hl_cmddev = 0; 58341480Smckusick return(0); 58441480Smckusick } 58541480Smckusick #endif 58641480Smckusick 58741480Smckusick /* 58849132Skarels * XXX: the mmap interface for HIL devices should be rethought. 58941480Smckusick * We used it only briefly in conjuntion with shared queues 59041480Smckusick * (instead of HILIOCMAPQ ioctl). Perhaps mmap()ing a device 59141480Smckusick * should give a single queue per process. 59241480Smckusick */ 59341480Smckusick /* ARGSUSED */ 59441480Smckusick hilmap(dev, off, prot) 59541480Smckusick dev_t dev; 59641480Smckusick register int off; 59741480Smckusick { 59843411Shibler #ifdef MMAP 59949132Skarels struct proc *p = curproc; /* XXX */ 60041480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 60141480Smckusick register struct hiliqueue *qp; 60241480Smckusick register int qnum; 60341480Smckusick 60441480Smckusick /* 60541480Smckusick * Only allow mmap() on loop device 60641480Smckusick */ 60741480Smckusick if (HILUNIT(dev) != 0 || off >= NHILQ*sizeof(HILQ)) 60841480Smckusick return(-1); 60941480Smckusick /* 61041480Smckusick * Determine which queue we want based on the offset. 61141480Smckusick * Queue must belong to calling process. 61241480Smckusick */ 61341480Smckusick qp = &hilp->hl_queue[off / sizeof(HILQ)]; 61443316Smckusick if (qp->hq_procp != p) 61541480Smckusick return(-1); 61641480Smckusick 61741480Smckusick off %= sizeof(HILQ); 61841480Smckusick return(kvtop((u_int)qp->hq_eventqueue + off) >> PGSHIFT); 61941480Smckusick #endif 62041480Smckusick } 62141480Smckusick 62241480Smckusick /*ARGSUSED*/ 62349132Skarels hilselect(dev, rw, p) 62441480Smckusick dev_t dev; 62549132Skarels struct proc *p; 62641480Smckusick { 62741480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 62841480Smckusick register struct hilloopdev *dptr; 62941480Smckusick register struct hiliqueue *qp; 63041480Smckusick register int mask; 63141480Smckusick int s, device; 63241480Smckusick 63341480Smckusick if (rw == FWRITE) 63441480Smckusick return (1); 63541480Smckusick device = HILUNIT(dev); 63641480Smckusick 63741480Smckusick /* 63841480Smckusick * Read interface. 63941480Smckusick * Return 1 if there is something in the queue, 0 ow. 64041480Smckusick */ 64141480Smckusick dptr = &hilp->hl_device[device]; 64241480Smckusick if (dptr->hd_flags & HIL_READIN) { 64341480Smckusick s = splhil(); 64441480Smckusick if (dptr->hd_queue.c_cc) { 64541480Smckusick splx(s); 64641480Smckusick return (1); 64741480Smckusick } 64841480Smckusick if (dptr->hd_selr && 64941480Smckusick dptr->hd_selr->p_wchan == (caddr_t)&selwait) 65041480Smckusick dptr->hd_flags |= HIL_SELCOLL; 65141480Smckusick else 65243316Smckusick dptr->hd_selr = p; 65341480Smckusick splx(s); 65441480Smckusick return (0); 65541480Smckusick } 65641480Smckusick 65741480Smckusick /* 65841480Smckusick * Make sure device is alive and real (or the loop device). 65941480Smckusick * Note that we do not do this for the read interface. 66041480Smckusick * This is primarily to be consistant with HP-UX. 66141480Smckusick */ 66241480Smckusick if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE) 66341480Smckusick return (1); 66441480Smckusick 66541480Smckusick /* 66641480Smckusick * Select on loop device is special. 66741480Smckusick * Check to see if there are any data for any loop device 66841480Smckusick * provided it is associated with a queue belonging to this user. 66941480Smckusick */ 67041480Smckusick if (device == 0) 67141480Smckusick mask = -1; 67241480Smckusick else 67341480Smckusick mask = hildevmask(device); 67441480Smckusick /* 67541480Smckusick * Must check everybody with interrupts blocked to prevent races. 67641480Smckusick */ 67741480Smckusick s = splhil(); 67841480Smckusick for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++) 67943316Smckusick if (qp->hq_procp == p && (mask & qp->hq_devmask) && 68041480Smckusick qp->hq_eventqueue->hil_evqueue.head != 68141480Smckusick qp->hq_eventqueue->hil_evqueue.tail) { 68241480Smckusick splx(s); 68341480Smckusick return (1); 68441480Smckusick } 68541480Smckusick 68641480Smckusick if (dptr->hd_selr && dptr->hd_selr->p_wchan == (caddr_t)&selwait) 68741480Smckusick dptr->hd_flags |= HIL_SELCOLL; 68841480Smckusick else 68943316Smckusick dptr->hd_selr = p; 69041480Smckusick splx(s); 69141480Smckusick return (0); 69241480Smckusick } 69341480Smckusick 69441480Smckusick hilint() 69541480Smckusick { 69641480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 69741480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 69841480Smckusick u_char c, stat; 69941480Smckusick 70041480Smckusick stat = hildevice->hil_stat; 70141480Smckusick c = hildevice->hil_data; /* clears interrupt */ 70241480Smckusick hil_process_int(stat, c); 70341480Smckusick } 70441480Smckusick 70541480Smckusick #include "ite.h" 70641480Smckusick 70741480Smckusick hil_process_int(stat, c) 70841480Smckusick register u_char stat, c; 70941480Smckusick { 71041480Smckusick register struct hilloop *hilp; 71141480Smckusick 71241480Smckusick #ifdef DEBUG 71341480Smckusick if (hildebug & HDB_EVENTS) 71441480Smckusick printf("hilint: %x %x\n", stat, c); 71541480Smckusick #endif 71641480Smckusick 71741480Smckusick /* the shift enables the compiler to generate a jump table */ 71841480Smckusick switch ((stat>>HIL_SSHIFT) & HIL_SMASK) { 71941480Smckusick 72041480Smckusick #if NITE > 0 72141480Smckusick case HIL_KEY: 72241480Smckusick case HIL_SHIFT: 72341480Smckusick case HIL_CTRL: 72441480Smckusick case HIL_CTRLSHIFT: 72541480Smckusick itefilter(stat, c); 72641480Smckusick return; 72741480Smckusick #endif 72841480Smckusick 72941480Smckusick case HIL_STATUS: /* The status info. */ 73041480Smckusick hilp = &hil0; /* XXX */ 73141480Smckusick if (c & HIL_ERROR) { 73241480Smckusick hilp->hl_cmddone = TRUE; 73341480Smckusick if (c == HIL_RECONFIG) 73441480Smckusick hilconfig(hilp); 73541480Smckusick break; 73641480Smckusick } 73741480Smckusick if (c & HIL_COMMAND) { 73841480Smckusick if (c & HIL_POLLDATA) /* End of data */ 73941480Smckusick hilevent(hilp); 74041480Smckusick else /* End of command */ 74141480Smckusick hilp->hl_cmdending = TRUE; 74241480Smckusick hilp->hl_actdev = 0; 74341480Smckusick } else { 74441480Smckusick if (c & HIL_POLLDATA) { /* Start of polled data */ 74541480Smckusick if (hilp->hl_actdev != 0) 74641480Smckusick hilevent(hilp); 74741480Smckusick hilp->hl_actdev = (c & HIL_DEVMASK); 74841480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf; 74941480Smckusick } else { /* Start of command */ 75041480Smckusick if (hilp->hl_cmddev == (c & HIL_DEVMASK)) { 75141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 75241480Smckusick hilp->hl_actdev = 0; 75341480Smckusick } 75441480Smckusick } 75541480Smckusick } 75641480Smckusick return; 75741480Smckusick 75841480Smckusick case HIL_DATA: 75941480Smckusick hilp = &hil0; /* XXX */ 76041480Smckusick if (hilp->hl_actdev != 0) /* Collecting poll data */ 76141480Smckusick *hilp->hl_pollbp++ = c; 76241480Smckusick else if (hilp->hl_cmddev != 0) /* Collecting cmd data */ 76341480Smckusick if (hilp->hl_cmdending) { 76441480Smckusick hilp->hl_cmddone = TRUE; 76541480Smckusick hilp->hl_cmdending = FALSE; 76641480Smckusick } else 76741480Smckusick *hilp->hl_cmdbp++ = c; 76841480Smckusick return; 76941480Smckusick 77041480Smckusick case 0: /* force full jump table */ 77141480Smckusick default: 77241480Smckusick return; 77341480Smckusick } 77441480Smckusick } 77541480Smckusick 77641480Smckusick #if defined(DEBUG) && !defined(PANICBUTTON) 77741480Smckusick #define PANICBUTTON 77841480Smckusick #endif 77941480Smckusick 78041480Smckusick /* 78141480Smckusick * Optimized macro to compute: 78241480Smckusick * eq->head == (eq->tail + 1) % eq->size 78341480Smckusick * i.e. has tail caught up with head. We do this because 32 bit long 78441480Smckusick * remaidering is expensive (a function call with our compiler). 78541480Smckusick */ 78641480Smckusick #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1) 78741480Smckusick #define HQVALID(eq) \ 78841480Smckusick ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE) 78941480Smckusick 79041480Smckusick hilevent(hilp) 79141480Smckusick struct hilloop *hilp; 79241480Smckusick { 79341480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev]; 79441480Smckusick register int len, mask, qnum; 79541480Smckusick register u_char *cp, *pp; 79641480Smckusick register HILQ *hq; 79741480Smckusick struct timeval ourtime; 79841480Smckusick hil_packet *proto; 79941480Smckusick int s, len0; 80041480Smckusick long tenths; 80141480Smckusick 80241480Smckusick #ifdef PANICBUTTON 80341480Smckusick static int first; 80441480Smckusick extern int panicbutton; 80541480Smckusick 80641480Smckusick cp = hilp->hl_pollbuf; 80741480Smckusick if (panicbutton && (*cp & HIL_KBDDATA)) { 80841480Smckusick if (*++cp == 0x4E) 80941480Smckusick first = 1; 81041480Smckusick else if (first && *cp == 0x46 && !panicstr) 81141480Smckusick panic("are we having fun yet?"); 81241480Smckusick else 81341480Smckusick first = 0; 81441480Smckusick } 81541480Smckusick #endif 81641480Smckusick #ifdef DEBUG 81741480Smckusick if (hildebug & HDB_EVENTS) { 81841480Smckusick printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev); 81941480Smckusick printhilpollbuf(hilp); 82041480Smckusick printf("\n"); 82141480Smckusick } 82241480Smckusick #endif 82341480Smckusick 82441480Smckusick /* 82541480Smckusick * Note that HIL_READIN effectively "shuts off" any queues 82641480Smckusick * that may have been in use at the time of an HILIOCHPUX call. 82741480Smckusick */ 82841480Smckusick if (dptr->hd_flags & HIL_READIN) { 82941480Smckusick hpuxhilevent(hilp, dptr); 83041480Smckusick return; 83141480Smckusick } 83241480Smckusick 83341480Smckusick /* 83441480Smckusick * If this device isn't on any queue or there are no data 83541480Smckusick * in the packet (can this happen?) do nothing. 83641480Smckusick */ 83741480Smckusick if (dptr->hd_qmask == 0 || 83841480Smckusick (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0) 83941480Smckusick return; 84041480Smckusick 84141480Smckusick /* 84241480Smckusick * Everybody gets the same time stamp 84341480Smckusick */ 84441480Smckusick s = splclock(); 84541480Smckusick ourtime = time; 84641480Smckusick splx(s); 84741480Smckusick tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 84841480Smckusick 84941480Smckusick proto = NULL; 85041480Smckusick mask = dptr->hd_qmask; 85141480Smckusick for (qnum = 0; mask; qnum++) { 85241480Smckusick if ((mask & hilqmask(qnum)) == 0) 85341480Smckusick continue; 85441480Smckusick mask &= ~hilqmask(qnum); 85541480Smckusick hq = hilp->hl_queue[qnum].hq_eventqueue; 85641480Smckusick 85741480Smckusick /* 85841480Smckusick * Ensure that queue fields that we rely on are valid 85941480Smckusick * and that there is space in the queue. If either 86041480Smckusick * test fails, we just skip this queue. 86141480Smckusick */ 86241480Smckusick if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue)) 86341480Smckusick continue; 86441480Smckusick 86541480Smckusick /* 86641480Smckusick * Copy data to queue. 86741480Smckusick * If this is the first queue we construct the packet 86841480Smckusick * with length, timestamp and poll buffer data. 86941480Smckusick * For second and sucessive packets we just duplicate 87041480Smckusick * the first packet. 87141480Smckusick */ 87241480Smckusick pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail]; 87341480Smckusick if (proto == NULL) { 87441480Smckusick proto = (hil_packet *)pp; 87541480Smckusick cp = hilp->hl_pollbuf; 87641480Smckusick len = len0; 87741480Smckusick *pp++ = len + 6; 87841480Smckusick *pp++ = hilp->hl_actdev; 87941480Smckusick *(long *)pp = tenths; 88041480Smckusick pp += sizeof(long); 88141480Smckusick do *pp++ = *cp++; while (--len); 88241480Smckusick } else 88341480Smckusick *(hil_packet *)pp = *proto; 88441480Smckusick 88541480Smckusick if (++hq->hil_evqueue.tail == hq->hil_evqueue.size) 88641480Smckusick hq->hil_evqueue.tail = 0; 88741480Smckusick } 88841480Smckusick 88941480Smckusick /* 89041480Smckusick * Wake up anyone selecting on this device or the loop itself 89141480Smckusick */ 89241480Smckusick if (dptr->hd_selr) { 89341480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 89441480Smckusick dptr->hd_selr = NULL; 89541480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 89641480Smckusick } 89741480Smckusick dptr = &hilp->hl_device[HILLOOPDEV]; 89841480Smckusick if (dptr->hd_selr) { 89941480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 90041480Smckusick dptr->hd_selr = NULL; 90141480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 90241480Smckusick } 90341480Smckusick } 90441480Smckusick 90541480Smckusick #undef HQFULL 90641480Smckusick 90741480Smckusick hpuxhilevent(hilp, dptr) 90841480Smckusick register struct hilloop *hilp; 90941480Smckusick register struct hilloopdev *dptr; 91041480Smckusick { 91141480Smckusick register int len; 91241480Smckusick struct timeval ourtime; 91341480Smckusick long tstamp; 91441480Smckusick int s; 91541480Smckusick 91641480Smckusick /* 91741480Smckusick * Everybody gets the same time stamp 91841480Smckusick */ 91941480Smckusick s = splclock(); 92041480Smckusick ourtime = time; 92141480Smckusick splx(s); 92241480Smckusick tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 92341480Smckusick 92441480Smckusick /* 92541480Smckusick * Each packet that goes into the buffer must be preceded by the 92641480Smckusick * number of bytes in the packet, and the timestamp of the packet. 92741480Smckusick * This adds 5 bytes to the packet size. Make sure there is enough 92841480Smckusick * room in the buffer for it, and if not, toss the packet. 92941480Smckusick */ 93041480Smckusick len = hilp->hl_pollbp - hilp->hl_pollbuf; 93141480Smckusick if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) { 93241480Smckusick putc(len+5, &dptr->hd_queue); 93341480Smckusick (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue); 93441480Smckusick (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue); 93541480Smckusick } 93641480Smckusick 93741480Smckusick /* 93841480Smckusick * Wake up any one blocked on a read or select 93941480Smckusick */ 94041480Smckusick if (dptr->hd_flags & HIL_ASLEEP) { 94141480Smckusick dptr->hd_flags &= ~HIL_ASLEEP; 94241480Smckusick wakeup((caddr_t)dptr); 94341480Smckusick } 94441480Smckusick if (dptr->hd_selr) { 94541480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 94641480Smckusick dptr->hd_selr = NULL; 94741480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 94841480Smckusick } 94941480Smckusick } 95041480Smckusick 95141480Smckusick /* 95241480Smckusick * Shared queue manipulation routines 95341480Smckusick */ 95441480Smckusick 95541480Smckusick hilqalloc(qip) 95641480Smckusick struct hilqinfo *qip; 95741480Smckusick { 95849132Skarels struct proc *p = curproc; /* XXX */ 95941480Smckusick 96041480Smckusick #ifdef DEBUG 96141480Smckusick if (hildebug & HDB_FOLLOW) 96245750Smckusick printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr); 96341480Smckusick #endif 96441480Smckusick return(EINVAL); 96541480Smckusick } 96641480Smckusick 96741480Smckusick hilqfree(qnum) 96841480Smckusick register int qnum; 96941480Smckusick { 97049132Skarels struct proc *p = curproc; /* XXX */ 97141480Smckusick 97241480Smckusick #ifdef DEBUG 97341480Smckusick if (hildebug & HDB_FOLLOW) 97445750Smckusick printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum); 97541480Smckusick #endif 97641480Smckusick return(EINVAL); 97741480Smckusick } 97841480Smckusick 97941480Smckusick hilqmap(qnum, device) 98041480Smckusick register int qnum, device; 98141480Smckusick { 98249132Skarels struct proc *p = curproc; /* XXX */ 98341480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 98441480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[device]; 98541480Smckusick int s; 98641480Smckusick 98741480Smckusick #ifdef DEBUG 98841480Smckusick if (hildebug & HDB_FOLLOW) 98941480Smckusick printf("hilqmap(%d): qnum %d device %x\n", 99043316Smckusick p->p_pid, qnum, device); 99141480Smckusick #endif 99243316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) 99341480Smckusick return(EINVAL); 99441480Smckusick if ((dptr->hd_flags & HIL_QUEUEIN) == 0) 99541480Smckusick return(EINVAL); 99649132Skarels if (dptr->hd_qmask && p->p_ucred->cr_uid && 99749132Skarels p->p_ucred->cr_uid != dptr->hd_uid) 99841480Smckusick return(EPERM); 99941480Smckusick 100041480Smckusick hilp->hl_queue[qnum].hq_devmask |= hildevmask(device); 100141480Smckusick if (dptr->hd_qmask == 0) 100249132Skarels dptr->hd_uid = p->p_ucred->cr_uid; 100341480Smckusick s = splhil(); 100441480Smckusick dptr->hd_qmask |= hilqmask(qnum); 100541480Smckusick splx(s); 100641480Smckusick #ifdef DEBUG 100741480Smckusick if (hildebug & HDB_MASK) 100841480Smckusick printf("hilqmap(%d): devmask %x qmask %x\n", 100943316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask, 101041480Smckusick dptr->hd_qmask); 101141480Smckusick #endif 101241480Smckusick return(0); 101341480Smckusick } 101441480Smckusick 101541480Smckusick hilqunmap(qnum, device) 101641480Smckusick register int qnum, device; 101741480Smckusick { 101849132Skarels struct proc *p = curproc; /* XXX */ 101941480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 102041480Smckusick int s; 102141480Smckusick 102241480Smckusick #ifdef DEBUG 102341480Smckusick if (hildebug & HDB_FOLLOW) 102441480Smckusick printf("hilqunmap(%d): qnum %d device %x\n", 102543316Smckusick p->p_pid, qnum, device); 102641480Smckusick #endif 102741480Smckusick 102843316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) 102941480Smckusick return(EINVAL); 103041480Smckusick 103141480Smckusick hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device); 103241480Smckusick s = splhil(); 103341480Smckusick hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum); 103441480Smckusick splx(s); 103541480Smckusick #ifdef DEBUG 103641480Smckusick if (hildebug & HDB_MASK) 103741480Smckusick printf("hilqunmap(%d): devmask %x qmask %x\n", 103843316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask, 103941480Smckusick hilp->hl_device[device].hd_qmask); 104041480Smckusick #endif 104141480Smckusick return(0); 104241480Smckusick } 104341480Smckusick 104445788Sbostic #include "sys/clist.h" 104541480Smckusick 104641480Smckusick /* 104741480Smckusick * This is just a copy of the virgin q_to_b routine with minor 104850253Skarels * optimizations for HIL use. It is used because we don't have 104950253Skarels * to raise the priority to spltty() for most of the clist manipulations. 105041480Smckusick */ 105141480Smckusick hilq_to_b(q, cp, cc) 105241480Smckusick register struct clist *q; 105341480Smckusick register char *cp; 105441480Smckusick { 1055*50254Skarels register struct cblock *bp; 1056*50254Skarels register int nc; 1057*50254Skarels char *acp; 1058*50254Skarels int s; 1059*50254Skarels extern char cwaiting; 106041480Smckusick 1061*50254Skarels if (cc <= 0) 1062*50254Skarels return (0); 1063*50254Skarels s = splhil(); 1064*50254Skarels if (q->c_cc <= 0) { 1065*50254Skarels q->c_cc = 0; 1066*50254Skarels q->c_cf = q->c_cl = NULL; 1067*50254Skarels splx(s); 1068*50254Skarels return (0); 1069*50254Skarels } 1070*50254Skarels acp = cp; 1071*50254Skarels 1072*50254Skarels while (cc) { 1073*50254Skarels nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 1074*50254Skarels nc = MIN(nc, cc); 1075*50254Skarels nc = MIN(nc, q->c_cc); 1076*50254Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 1077*50254Skarels q->c_cf += nc; 1078*50254Skarels q->c_cc -= nc; 1079*50254Skarels cc -= nc; 1080*50254Skarels cp += nc; 1081*50254Skarels if (q->c_cc <= 0) { 1082*50254Skarels bp = (struct cblock *)(q->c_cf - 1); 1083*50254Skarels bp = (struct cblock *)((int)bp & ~CROUND); 1084*50254Skarels q->c_cf = q->c_cl = NULL; 1085*50254Skarels spltty(); 1086*50254Skarels bp->c_next = cfreelist; 1087*50254Skarels cfreelist = bp; 1088*50254Skarels cfreecount += CBSIZE; 1089*50254Skarels if (cwaiting) { 1090*50254Skarels wakeup(&cwaiting); 1091*50254Skarels cwaiting = 0; 1092*50254Skarels } 1093*50254Skarels break; 1094*50254Skarels } 1095*50254Skarels if (((int)q->c_cf & CROUND) == 0) { 1096*50254Skarels bp = (struct cblock *)(q->c_cf); 1097*50254Skarels bp--; 1098*50254Skarels q->c_cf = bp->c_next->c_info; 1099*50254Skarels spltty(); 1100*50254Skarels bp->c_next = cfreelist; 1101*50254Skarels cfreelist = bp; 1102*50254Skarels cfreecount += CBSIZE; 1103*50254Skarels if (cwaiting) { 1104*50254Skarels wakeup(&cwaiting); 1105*50254Skarels cwaiting = 0; 1106*50254Skarels } 1107*50254Skarels splhil(); 1108*50254Skarels } 1109*50254Skarels } 1110*50254Skarels splx(s); 1111*50254Skarels return (cp-acp); 111241480Smckusick } 111341480Smckusick 111441480Smckusick /* 111541480Smckusick * Cooked keyboard functions for ite driver. 111641480Smckusick * There is only one "cooked" ITE keyboard (the first keyboard found) 111741480Smckusick * per loop. There may be other keyboards, but they will always be "raw". 111841480Smckusick */ 111941480Smckusick 112041480Smckusick kbdbell() 112141480Smckusick { 112241480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 112341480Smckusick 112441480Smckusick hilbeep(hilp, &default_bell); 112541480Smckusick } 112641480Smckusick 112741480Smckusick kbdenable() 112841480Smckusick { 112941480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 113041480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 113141480Smckusick char db; 113241480Smckusick 113341480Smckusick /* Set the autorepeat rate register */ 113441480Smckusick db = ar_format(KBD_ARR); 113541480Smckusick send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL); 113641480Smckusick 113741480Smckusick /* Set the autorepeat delay register */ 113841480Smckusick db = ar_format(KBD_ARD); 113941480Smckusick send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL); 114041480Smckusick 114141480Smckusick /* Enable interrupts */ 114241480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); 114341480Smckusick } 114441480Smckusick 114541480Smckusick kbddisable() 114641480Smckusick { 114741480Smckusick } 114841480Smckusick 114941480Smckusick /* 115041480Smckusick * XXX: read keyboard directly and return code. 115141480Smckusick * Used by console getchar routine. Could really screw up anybody 115241480Smckusick * reading from the keyboard in the normal, interrupt driven fashion. 115341480Smckusick */ 115441480Smckusick kbdgetc(statp) 115541480Smckusick int *statp; 115641480Smckusick { 115741480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 115841480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 115941480Smckusick register int c, stat; 116041480Smckusick int s; 116141480Smckusick 116241480Smckusick s = splhil(); 116341480Smckusick while (((stat = hildevice->hil_stat) & HIL_DATA_RDY) == 0) 116441480Smckusick ; 116541480Smckusick c = hildevice->hil_data; 116641480Smckusick splx(s); 116741480Smckusick *statp = stat; 116841480Smckusick return(c); 116941480Smckusick } 117041480Smckusick 117141480Smckusick /* 117241480Smckusick * Recoginize and clear keyboard generated NMIs. 117341480Smckusick * Returns 1 if it was ours, 0 otherwise. Note that we cannot use 117441480Smckusick * send_hil_cmd() to issue the clear NMI command as that would actually 117541480Smckusick * lower the priority to splimp() and it doesn't wait for the completion 117641480Smckusick * of the command. Either of these conditions could result in the 117741480Smckusick * interrupt reoccuring. Note that we issue the CNMT command twice. 117841480Smckusick * This seems to be needed, once is not always enough!?! 117941480Smckusick */ 118041480Smckusick kbdnmi() 118141480Smckusick { 118241480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 118341480Smckusick 118441480Smckusick if ((*KBDNMISTAT & KBDNMI) == 0) 118541480Smckusick return(0); 118641480Smckusick HILWAIT(hilp->hl_addr); 118741480Smckusick hilp->hl_addr->hil_cmd = HIL_CNMT; 118841480Smckusick HILWAIT(hilp->hl_addr); 118941480Smckusick hilp->hl_addr->hil_cmd = HIL_CNMT; 119041480Smckusick HILWAIT(hilp->hl_addr); 119141480Smckusick return(1); 119241480Smckusick } 119341480Smckusick 119441480Smckusick #define HILSECURITY 0x33 119541480Smckusick #define HILIDENTIFY 0x03 119641480Smckusick #define HILSCBIT 0x04 119741480Smckusick 119841480Smckusick /* 119941480Smckusick * Called at boot time to print out info about interesting devices 120041480Smckusick */ 120141480Smckusick hilinfo(hilp) 120241480Smckusick register struct hilloop *hilp; 120341480Smckusick { 120441480Smckusick register int id, len; 120541480Smckusick register struct kbdmap *km; 120641480Smckusick 120741480Smckusick /* 120841480Smckusick * Keyboard info. 120941480Smckusick */ 121041480Smckusick if (hilp->hl_kbddev) { 121141480Smckusick printf("hil%d: ", hilp->hl_kbddev); 121241480Smckusick for (km = kbd_map; km->kbd_code; km++) 121341480Smckusick if (km->kbd_code == hilp->hl_kbdlang) { 121441480Smckusick printf("%s ", km->kbd_desc); 121541480Smckusick break; 121641480Smckusick } 121741480Smckusick printf("keyboard\n"); 121841480Smckusick } 121941480Smckusick /* 122041480Smckusick * ID module. 122141480Smckusick * Attempt to locate the first ID module and print out its 122241480Smckusick * security code. Is this a good idea?? 122341480Smckusick */ 122441480Smckusick id = hiliddev(hilp); 122541480Smckusick if (id) { 122641480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 122741480Smckusick hilp->hl_cmddev = id; 122841480Smckusick send_hildev_cmd(hilp, id, HILSECURITY); 122941480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 123041480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 123141480Smckusick hilp->hl_cmddev = 0; 123241480Smckusick printf("hil%d: security code", id); 123341480Smckusick for (id = 0; id < len; id++) 123441480Smckusick printf(" %x", hilp->hl_cmdbuf[id]); 123541480Smckusick while (id++ < 16) 123641480Smckusick printf(" 0"); 123741480Smckusick printf("\n"); 123841480Smckusick } 123941480Smckusick } 124041480Smckusick 124141480Smckusick #define HILAR1 0x3E 124241480Smckusick #define HILAR2 0x3F 124341480Smckusick 124441480Smckusick /* 124541480Smckusick * Called after the loop has reconfigured. Here we need to: 124641480Smckusick * - determine how many devices are on the loop 124741480Smckusick * (some may have been added or removed) 124841480Smckusick * - locate the ITE keyboard (if any) and ensure 124941480Smckusick * that it is in the proper state (raw or cooked) 125041480Smckusick * and is set to use the proper language mapping table 125141480Smckusick * - ensure all other keyboards are raw 125241480Smckusick * Note that our device state is now potentially invalid as 125341480Smckusick * devices may no longer be where they were. What we should 125441480Smckusick * do here is either track where the devices went and move 125541480Smckusick * state around accordingly or, more simply, just mark all 125641480Smckusick * devices as HIL_DERROR and don't allow any further use until 125741480Smckusick * they are closed. This is a little too brutal for my tastes, 125841480Smckusick * we prefer to just assume people won't move things around. 125941480Smckusick */ 126041480Smckusick hilconfig(hilp) 126141480Smckusick register struct hilloop *hilp; 126241480Smckusick { 126341480Smckusick u_char db; 126441480Smckusick int s; 126541480Smckusick 126641480Smckusick s = splhil(); 126741480Smckusick #ifdef DEBUG 126841480Smckusick if (hildebug & HDB_CONFIG) { 126941480Smckusick printf("hilconfig: reconfigured: "); 127041480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); 127141480Smckusick printf("LPSTAT %x, ", db); 127241480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db); 127341480Smckusick printf("LPCTRL %x, ", db); 127441480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); 127541480Smckusick printf("KBDSADR %x\n", db); 127641480Smckusick hilreport(hilp); 127741480Smckusick } 127841480Smckusick #endif 127941480Smckusick /* 128041480Smckusick * Determine how many devices are on the loop. 128141480Smckusick * Mark those as alive and real, all others as dead. 128241480Smckusick */ 128341480Smckusick db = 0; 128441480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); 128541480Smckusick hilp->hl_maxdev = db & LPS_DEVMASK; 128641480Smckusick for (db = 1; db < NHILD; db++) { 128741480Smckusick if (db <= hilp->hl_maxdev) 128841480Smckusick hilp->hl_device[db].hd_flags |= HIL_ALIVE; 128941480Smckusick else 129041480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_ALIVE; 129141480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO; 129241480Smckusick } 129341480Smckusick #ifdef DEBUG 129441480Smckusick if (hildebug & (HDB_CONFIG|HDB_KEYBOARD)) 129541480Smckusick printf("hilconfig: max device %d\n", hilp->hl_maxdev); 129641480Smckusick #endif 129741480Smckusick if (hilp->hl_maxdev == 0) { 129841480Smckusick hilp->hl_kbddev = 0; 129941480Smckusick splx(s); 130041480Smckusick return; 130141480Smckusick } 130241480Smckusick /* 130341480Smckusick * Find out where the keyboards are and record the ITE keyboard 130441480Smckusick * (first one found). If no keyboards found, we are all done. 130541480Smckusick */ 130641480Smckusick db = 0; 130741480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); 130841480Smckusick #ifdef DEBUG 130941480Smckusick if (hildebug & HDB_KEYBOARD) 131041480Smckusick printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n", 131141480Smckusick db, hilp->hl_kbddev, ffs((int)db)); 131241480Smckusick #endif 131341480Smckusick hilp->hl_kbddev = ffs((int)db); 131441480Smckusick if (hilp->hl_kbddev == 0) { 131541480Smckusick splx(s); 131641480Smckusick return; 131741480Smckusick } 131841480Smckusick /* 131941480Smckusick * Determine if the keyboard should be cooked or raw and configure it. 132041480Smckusick */ 132141480Smckusick db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1); 132241480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL); 132341480Smckusick /* 132441480Smckusick * Re-enable autorepeat in raw mode, cooked mode AR is not affected. 132541480Smckusick */ 132641480Smckusick if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) { 132741480Smckusick db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2; 132841480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 132941480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, db); 133041480Smckusick hilp->hl_cmddev = 0; 133141480Smckusick } 133241480Smckusick /* 133341480Smckusick * Determine the keyboard language configuration, but don't 133441480Smckusick * override a user-specified setting. 133541480Smckusick */ 133641480Smckusick db = 0; 133741480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db); 133841480Smckusick #ifdef DEBUG 133941480Smckusick if (hildebug & HDB_KEYBOARD) 134041480Smckusick printf("hilconfig: language: old %x new %x\n", 134141480Smckusick hilp->hl_kbdlang, db); 134241480Smckusick #endif 134341480Smckusick if (hilp->hl_kbdlang != KBD_SPECIAL) { 134441480Smckusick struct kbdmap *km; 134541480Smckusick 134641480Smckusick for (km = kbd_map; km->kbd_code; km++) 134741480Smckusick if (km->kbd_code == db) { 134841480Smckusick hilp->hl_kbdlang = db; 134941480Smckusick /* XXX */ 135041480Smckusick kbd_keymap = km->kbd_keymap; 135141480Smckusick kbd_shiftmap = km->kbd_shiftmap; 135241480Smckusick kbd_ctrlmap = km->kbd_ctrlmap; 135341480Smckusick kbd_ctrlshiftmap = km->kbd_ctrlshiftmap; 135441480Smckusick kbd_stringmap = km->kbd_stringmap; 135541480Smckusick } 135641480Smckusick } 135741480Smckusick splx(s); 135841480Smckusick } 135941480Smckusick 136041480Smckusick hilreset(hilp) 136141480Smckusick struct hilloop *hilp; 136241480Smckusick { 136341480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 136441480Smckusick u_char db; 136541480Smckusick 136641480Smckusick /* 136741480Smckusick * Initialize the loop: reconfigure, don't report errors, 136841480Smckusick * cook keyboards, and enable autopolling. 136941480Smckusick */ 137041480Smckusick db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL; 137141480Smckusick send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL); 137241480Smckusick /* 137341480Smckusick * Delay one second for reconfiguration and then read the the 137441480Smckusick * data register to clear the interrupt (if the loop reconfigured). 137541480Smckusick */ 137641480Smckusick DELAY(1000000); 137741480Smckusick if (hildevice->hil_stat & HIL_DATA_RDY) 137841480Smckusick db = hildevice->hil_data; 137941480Smckusick /* 138041480Smckusick * The HIL loop may have reconfigured. If so we proceed on, 138141480Smckusick * if not we loop until a successful reconfiguration is reported 138241480Smckusick * back to us. The HIL loop will continue to attempt forever. 138341480Smckusick * Probably not very smart. 138441480Smckusick */ 138541480Smckusick do { 138641480Smckusick send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db); 138741480Smckusick } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0); 138841480Smckusick /* 138941480Smckusick * At this point, the loop should have reconfigured. 139041480Smckusick * The reconfiguration interrupt has already called hilconfig() 139143411Shibler * so the keyboard has been determined. 139241480Smckusick */ 139341480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); 139441480Smckusick } 139541480Smckusick 139641480Smckusick hilbeep(hilp, bp) 139741480Smckusick struct hilloop *hilp; 139841480Smckusick register struct _hilbell *bp; 139941480Smckusick { 140041480Smckusick u_char buf[2]; 140141480Smckusick 140241480Smckusick buf[0] = ~((bp->duration - 10) / 10); 140341480Smckusick buf[1] = bp->frequency; 140441480Smckusick send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL); 140541480Smckusick } 140641480Smckusick 140741480Smckusick /* 140841480Smckusick * Locate and return the address of the first ID module, 0 if none present. 140941480Smckusick */ 141041480Smckusick hiliddev(hilp) 141141480Smckusick register struct hilloop *hilp; 141241480Smckusick { 141341480Smckusick register int i, len; 141441480Smckusick 141541480Smckusick #ifdef DEBUG 141641480Smckusick if (hildebug & HDB_IDMODULE) 141741480Smckusick printf("hiliddev(%x): looking for idmodule...", hilp); 141841480Smckusick #endif 141941480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) { 142041480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 142141480Smckusick hilp->hl_cmddev = i; 142241480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY); 142341480Smckusick /* 142441480Smckusick * XXX: the final condition checks to ensure that the 142541480Smckusick * device ID byte is in the range of the ID module (0x30-0x3F) 142641480Smckusick */ 142741480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 142841480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) && 142941480Smckusick (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) { 143041480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 143141480Smckusick hilp->hl_cmddev = i; 143241480Smckusick send_hildev_cmd(hilp, i, HILSECURITY); 143341480Smckusick break; 143441480Smckusick } 143541480Smckusick } 143641480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 143741480Smckusick hilp->hl_cmddev = 0; 143841480Smckusick #ifdef DEBUG 143941480Smckusick if (hildebug & HDB_IDMODULE) 144041480Smckusick if (i <= hilp->hl_maxdev) 144141480Smckusick printf("found at %d\n", i); 144241480Smckusick else 144341480Smckusick printf("not found\n"); 144441480Smckusick #endif 144541480Smckusick return(i <= hilp->hl_maxdev ? i : 0); 144641480Smckusick } 144741480Smckusick 144841480Smckusick /* 144941480Smckusick * Low level routines which actually talk to the 8042 chip. 145041480Smckusick */ 145141480Smckusick 145241480Smckusick /* 145341480Smckusick * Send a command to the 8042 with zero or more bytes of data. 145441480Smckusick * If rdata is non-null, wait for and return a byte of data. 145541480Smckusick * We run at splimp() to make the transaction as atomic as 145641480Smckusick * possible without blocking the clock (is this necessary?) 145741480Smckusick */ 145841480Smckusick send_hil_cmd(hildevice, cmd, data, dlen, rdata) 145941480Smckusick register struct hil_dev *hildevice; 146041480Smckusick u_char cmd, *data, dlen; 146141480Smckusick u_char *rdata; 146241480Smckusick { 146341480Smckusick u_char status; 146441480Smckusick int s = splimp(); 146541480Smckusick 146641480Smckusick HILWAIT(hildevice); 146741480Smckusick hildevice->hil_cmd = cmd; 146841480Smckusick while (dlen--) { 146941480Smckusick HILWAIT(hildevice); 147041480Smckusick hildevice->hil_data = *data++; 147141480Smckusick } 147241480Smckusick if (rdata) { 147341480Smckusick do { 147441480Smckusick HILDATAWAIT(hildevice); 147541480Smckusick status = hildevice->hil_stat; 147641480Smckusick *rdata = hildevice->hil_data; 147741480Smckusick } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K); 147841480Smckusick } 147941480Smckusick splx(s); 148041480Smckusick } 148141480Smckusick 148241480Smckusick /* 148341480Smckusick * Send a command to a device on the loop. 148441480Smckusick * Since only one command can be active on the loop at any time, 148541480Smckusick * we must ensure that we are not interrupted during this process. 148641480Smckusick * Hence we mask interrupts to prevent potential access from most 148741480Smckusick * interrupt routines and turn off auto-polling to disable the 148841480Smckusick * internally generated poll commands. 148941480Smckusick * 149041480Smckusick * splhigh is extremely conservative but insures atomic operation, 149141480Smckusick * splimp (clock only interrupts) seems to be good enough in practice. 149241480Smckusick */ 149341480Smckusick send_hildev_cmd(hilp, device, cmd) 149441480Smckusick register struct hilloop *hilp; 149541480Smckusick char device, cmd; 149641480Smckusick { 149741480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 149841480Smckusick u_char status, c; 149941480Smckusick int s = splimp(); 150041480Smckusick 150141480Smckusick polloff(hildevice); 150241480Smckusick 150341480Smckusick /* 150441480Smckusick * Transfer the command and device info to the chip 150541480Smckusick */ 150641480Smckusick HILWAIT(hildevice); 150741480Smckusick hildevice->hil_cmd = HIL_STARTCMD; 150841480Smckusick HILWAIT(hildevice); 150941480Smckusick hildevice->hil_data = 8 + device; 151041480Smckusick HILWAIT(hildevice); 151141480Smckusick hildevice->hil_data = cmd; 151241480Smckusick HILWAIT(hildevice); 151341480Smckusick hildevice->hil_data = HIL_TIMEOUT; 151441480Smckusick /* 151541480Smckusick * Trigger the command and wait for completion 151641480Smckusick */ 151741480Smckusick HILWAIT(hildevice); 151841480Smckusick hildevice->hil_cmd = HIL_TRIGGER; 151941480Smckusick hilp->hl_cmddone = FALSE; 152041480Smckusick do { 152141480Smckusick HILDATAWAIT(hildevice); 152241480Smckusick status = hildevice->hil_stat; 152341480Smckusick c = hildevice->hil_data; 152441480Smckusick hil_process_int(status, c); 152541480Smckusick } while (!hilp->hl_cmddone); 152641480Smckusick 152741480Smckusick pollon(hildevice); 152841480Smckusick splx(s); 152941480Smckusick } 153041480Smckusick 153141480Smckusick /* 153241480Smckusick * Turn auto-polling off and on. 153341480Smckusick * Also disables and enable auto-repeat. Why? 153441480Smckusick */ 153541480Smckusick polloff(hildevice) 153641480Smckusick register struct hil_dev *hildevice; 153741480Smckusick { 153841480Smckusick register char db; 153941480Smckusick 154041480Smckusick /* 154141480Smckusick * Turn off auto repeat 154241480Smckusick */ 154341480Smckusick HILWAIT(hildevice); 154441480Smckusick hildevice->hil_cmd = HIL_SETARR; 154541480Smckusick HILWAIT(hildevice); 154641480Smckusick hildevice->hil_data = 0; 154741480Smckusick /* 154841480Smckusick * Turn off auto-polling 154941480Smckusick */ 155041480Smckusick HILWAIT(hildevice); 155141480Smckusick hildevice->hil_cmd = HIL_READLPCTRL; 155241480Smckusick HILDATAWAIT(hildevice); 155341480Smckusick db = hildevice->hil_data; 155441480Smckusick db &= ~LPC_AUTOPOLL; 155541480Smckusick HILWAIT(hildevice); 155641480Smckusick hildevice->hil_cmd = HIL_WRITELPCTRL; 155741480Smckusick HILWAIT(hildevice); 155841480Smckusick hildevice->hil_data = db; 155941480Smckusick /* 156041480Smckusick * Must wait til polling is really stopped 156141480Smckusick */ 156241480Smckusick do { 156341480Smckusick HILWAIT(hildevice); 156441480Smckusick hildevice->hil_cmd = HIL_READBUSY; 156541480Smckusick HILDATAWAIT(hildevice); 156641480Smckusick db = hildevice->hil_data; 156741480Smckusick } while (db & BSY_LOOPBUSY); 156841480Smckusick } 156941480Smckusick 157041480Smckusick pollon(hildevice) 157141480Smckusick register struct hil_dev *hildevice; 157241480Smckusick { 157341480Smckusick register char db; 157441480Smckusick 157541480Smckusick /* 157641480Smckusick * Turn on auto polling 157741480Smckusick */ 157841480Smckusick HILWAIT(hildevice); 157941480Smckusick hildevice->hil_cmd = HIL_READLPCTRL; 158041480Smckusick HILDATAWAIT(hildevice); 158141480Smckusick db = hildevice->hil_data; 158241480Smckusick db |= LPC_AUTOPOLL; 158341480Smckusick HILWAIT(hildevice); 158441480Smckusick hildevice->hil_cmd = HIL_WRITELPCTRL; 158541480Smckusick HILWAIT(hildevice); 158641480Smckusick hildevice->hil_data = db; 158741480Smckusick /* 158841480Smckusick * Turn on auto repeat 158941480Smckusick */ 159041480Smckusick HILWAIT(hildevice); 159141480Smckusick hildevice->hil_cmd = HIL_SETARR; 159241480Smckusick HILWAIT(hildevice); 159341480Smckusick hildevice->hil_data = ar_format(KBD_ARR); 159441480Smckusick } 159541480Smckusick 159641480Smckusick #ifdef DEBUG 159741480Smckusick printhilpollbuf(hilp) 159841480Smckusick register struct hilloop *hilp; 159941480Smckusick { 160041480Smckusick register u_char *cp; 160141480Smckusick register int i, len; 160241480Smckusick 160341480Smckusick cp = hilp->hl_pollbuf; 160441480Smckusick len = hilp->hl_pollbp - cp; 160541480Smckusick for (i = 0; i < len; i++) 160641480Smckusick printf("%x ", hilp->hl_pollbuf[i]); 160741480Smckusick printf("\n"); 160841480Smckusick } 160941480Smckusick 161041480Smckusick printhilcmdbuf(hilp) 161141480Smckusick register struct hilloop *hilp; 161241480Smckusick { 161341480Smckusick register u_char *cp; 161441480Smckusick register int i, len; 161541480Smckusick 161641480Smckusick cp = hilp->hl_cmdbuf; 161741480Smckusick len = hilp->hl_cmdbp - cp; 161841480Smckusick for (i = 0; i < len; i++) 161941480Smckusick printf("%x ", hilp->hl_cmdbuf[i]); 162041480Smckusick printf("\n"); 162141480Smckusick } 162241480Smckusick 162341480Smckusick hilreport(hilp) 162441480Smckusick register struct hilloop *hilp; 162541480Smckusick { 162641480Smckusick register int i, len; 162741480Smckusick int s = splhil(); 162841480Smckusick 162941480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) { 163041480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 163141480Smckusick hilp->hl_cmddev = i; 163241480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY); 163341480Smckusick printf("hil%d: id: ", i); 163441480Smckusick printhilcmdbuf(hilp); 163541480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 163641480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) { 163741480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 163841480Smckusick hilp->hl_cmddev = i; 163941480Smckusick send_hildev_cmd(hilp, i, HILSECURITY); 164041480Smckusick printf("hil%d: sc: ", i); 164141480Smckusick printhilcmdbuf(hilp); 164241480Smckusick } 164341480Smckusick } 164441480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 164541480Smckusick hilp->hl_cmddev = 0; 164641480Smckusick splx(s); 164741480Smckusick } 164841480Smckusick #endif 1649