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*52533Smckusick * @(#)hil.c 7.11 (Berkeley) 02/15/92 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 */ 16652532Skarels hilclose(dev, flags, mode, p) 16741480Smckusick dev_t dev; 16852532Skarels struct proc *p; 16941480Smckusick { 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 18552532Skarels if (p && (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 } 648*52533Smckusick selrecord(p, &dptr->hd_selr); 64941480Smckusick splx(s); 65041480Smckusick return (0); 65141480Smckusick } 65241480Smckusick 65341480Smckusick /* 65441480Smckusick * Make sure device is alive and real (or the loop device). 65541480Smckusick * Note that we do not do this for the read interface. 65641480Smckusick * This is primarily to be consistant with HP-UX. 65741480Smckusick */ 65841480Smckusick if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE) 65941480Smckusick return (1); 66041480Smckusick 66141480Smckusick /* 66241480Smckusick * Select on loop device is special. 66341480Smckusick * Check to see if there are any data for any loop device 66441480Smckusick * provided it is associated with a queue belonging to this user. 66541480Smckusick */ 66641480Smckusick if (device == 0) 66741480Smckusick mask = -1; 66841480Smckusick else 66941480Smckusick mask = hildevmask(device); 67041480Smckusick /* 67141480Smckusick * Must check everybody with interrupts blocked to prevent races. 67241480Smckusick */ 67341480Smckusick s = splhil(); 67441480Smckusick for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++) 67543316Smckusick if (qp->hq_procp == p && (mask & qp->hq_devmask) && 67641480Smckusick qp->hq_eventqueue->hil_evqueue.head != 67741480Smckusick qp->hq_eventqueue->hil_evqueue.tail) { 67841480Smckusick splx(s); 67941480Smckusick return (1); 68041480Smckusick } 68141480Smckusick 682*52533Smckusick selrecord(p, &dptr->hd_selr); 68341480Smckusick splx(s); 68441480Smckusick return (0); 68541480Smckusick } 68641480Smckusick 68741480Smckusick hilint() 68841480Smckusick { 68941480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 69041480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 69141480Smckusick u_char c, stat; 69241480Smckusick 69341480Smckusick stat = hildevice->hil_stat; 69441480Smckusick c = hildevice->hil_data; /* clears interrupt */ 69541480Smckusick hil_process_int(stat, c); 69641480Smckusick } 69741480Smckusick 69841480Smckusick #include "ite.h" 69941480Smckusick 70041480Smckusick hil_process_int(stat, c) 70141480Smckusick register u_char stat, c; 70241480Smckusick { 70341480Smckusick register struct hilloop *hilp; 70441480Smckusick 70541480Smckusick #ifdef DEBUG 70641480Smckusick if (hildebug & HDB_EVENTS) 70741480Smckusick printf("hilint: %x %x\n", stat, c); 70841480Smckusick #endif 70941480Smckusick 71041480Smckusick /* the shift enables the compiler to generate a jump table */ 71141480Smckusick switch ((stat>>HIL_SSHIFT) & HIL_SMASK) { 71241480Smckusick 71341480Smckusick #if NITE > 0 71441480Smckusick case HIL_KEY: 71541480Smckusick case HIL_SHIFT: 71641480Smckusick case HIL_CTRL: 71741480Smckusick case HIL_CTRLSHIFT: 71841480Smckusick itefilter(stat, c); 71941480Smckusick return; 72041480Smckusick #endif 72141480Smckusick 72241480Smckusick case HIL_STATUS: /* The status info. */ 72341480Smckusick hilp = &hil0; /* XXX */ 72441480Smckusick if (c & HIL_ERROR) { 72541480Smckusick hilp->hl_cmddone = TRUE; 72641480Smckusick if (c == HIL_RECONFIG) 72741480Smckusick hilconfig(hilp); 72841480Smckusick break; 72941480Smckusick } 73041480Smckusick if (c & HIL_COMMAND) { 73141480Smckusick if (c & HIL_POLLDATA) /* End of data */ 73241480Smckusick hilevent(hilp); 73341480Smckusick else /* End of command */ 73441480Smckusick hilp->hl_cmdending = TRUE; 73541480Smckusick hilp->hl_actdev = 0; 73641480Smckusick } else { 73741480Smckusick if (c & HIL_POLLDATA) { /* Start of polled data */ 73841480Smckusick if (hilp->hl_actdev != 0) 73941480Smckusick hilevent(hilp); 74041480Smckusick hilp->hl_actdev = (c & HIL_DEVMASK); 74141480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf; 74241480Smckusick } else { /* Start of command */ 74341480Smckusick if (hilp->hl_cmddev == (c & HIL_DEVMASK)) { 74441480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 74541480Smckusick hilp->hl_actdev = 0; 74641480Smckusick } 74741480Smckusick } 74841480Smckusick } 74941480Smckusick return; 75041480Smckusick 75141480Smckusick case HIL_DATA: 75241480Smckusick hilp = &hil0; /* XXX */ 75341480Smckusick if (hilp->hl_actdev != 0) /* Collecting poll data */ 75441480Smckusick *hilp->hl_pollbp++ = c; 75541480Smckusick else if (hilp->hl_cmddev != 0) /* Collecting cmd data */ 75641480Smckusick if (hilp->hl_cmdending) { 75741480Smckusick hilp->hl_cmddone = TRUE; 75841480Smckusick hilp->hl_cmdending = FALSE; 75941480Smckusick } else 76041480Smckusick *hilp->hl_cmdbp++ = c; 76141480Smckusick return; 76241480Smckusick 76341480Smckusick case 0: /* force full jump table */ 76441480Smckusick default: 76541480Smckusick return; 76641480Smckusick } 76741480Smckusick } 76841480Smckusick 76941480Smckusick #if defined(DEBUG) && !defined(PANICBUTTON) 77041480Smckusick #define PANICBUTTON 77141480Smckusick #endif 77241480Smckusick 77341480Smckusick /* 77441480Smckusick * Optimized macro to compute: 77541480Smckusick * eq->head == (eq->tail + 1) % eq->size 77641480Smckusick * i.e. has tail caught up with head. We do this because 32 bit long 77741480Smckusick * remaidering is expensive (a function call with our compiler). 77841480Smckusick */ 77941480Smckusick #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1) 78041480Smckusick #define HQVALID(eq) \ 78141480Smckusick ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE) 78241480Smckusick 78341480Smckusick hilevent(hilp) 78441480Smckusick struct hilloop *hilp; 78541480Smckusick { 78641480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev]; 78741480Smckusick register int len, mask, qnum; 78841480Smckusick register u_char *cp, *pp; 78941480Smckusick register HILQ *hq; 79041480Smckusick struct timeval ourtime; 79141480Smckusick hil_packet *proto; 79241480Smckusick int s, len0; 79341480Smckusick long tenths; 79441480Smckusick 79541480Smckusick #ifdef PANICBUTTON 79641480Smckusick static int first; 79741480Smckusick extern int panicbutton; 79841480Smckusick 79941480Smckusick cp = hilp->hl_pollbuf; 80041480Smckusick if (panicbutton && (*cp & HIL_KBDDATA)) { 80141480Smckusick if (*++cp == 0x4E) 80241480Smckusick first = 1; 80341480Smckusick else if (first && *cp == 0x46 && !panicstr) 80441480Smckusick panic("are we having fun yet?"); 80541480Smckusick else 80641480Smckusick first = 0; 80741480Smckusick } 80841480Smckusick #endif 80941480Smckusick #ifdef DEBUG 81041480Smckusick if (hildebug & HDB_EVENTS) { 81141480Smckusick printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev); 81241480Smckusick printhilpollbuf(hilp); 81341480Smckusick printf("\n"); 81441480Smckusick } 81541480Smckusick #endif 81641480Smckusick 81741480Smckusick /* 81841480Smckusick * Note that HIL_READIN effectively "shuts off" any queues 81941480Smckusick * that may have been in use at the time of an HILIOCHPUX call. 82041480Smckusick */ 82141480Smckusick if (dptr->hd_flags & HIL_READIN) { 82241480Smckusick hpuxhilevent(hilp, dptr); 82341480Smckusick return; 82441480Smckusick } 82541480Smckusick 82641480Smckusick /* 82741480Smckusick * If this device isn't on any queue or there are no data 82841480Smckusick * in the packet (can this happen?) do nothing. 82941480Smckusick */ 83041480Smckusick if (dptr->hd_qmask == 0 || 83141480Smckusick (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0) 83241480Smckusick return; 83341480Smckusick 83441480Smckusick /* 83541480Smckusick * Everybody gets the same time stamp 83641480Smckusick */ 83741480Smckusick s = splclock(); 83841480Smckusick ourtime = time; 83941480Smckusick splx(s); 84041480Smckusick tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 84141480Smckusick 84241480Smckusick proto = NULL; 84341480Smckusick mask = dptr->hd_qmask; 84441480Smckusick for (qnum = 0; mask; qnum++) { 84541480Smckusick if ((mask & hilqmask(qnum)) == 0) 84641480Smckusick continue; 84741480Smckusick mask &= ~hilqmask(qnum); 84841480Smckusick hq = hilp->hl_queue[qnum].hq_eventqueue; 84941480Smckusick 85041480Smckusick /* 85141480Smckusick * Ensure that queue fields that we rely on are valid 85241480Smckusick * and that there is space in the queue. If either 85341480Smckusick * test fails, we just skip this queue. 85441480Smckusick */ 85541480Smckusick if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue)) 85641480Smckusick continue; 85741480Smckusick 85841480Smckusick /* 85941480Smckusick * Copy data to queue. 86041480Smckusick * If this is the first queue we construct the packet 86141480Smckusick * with length, timestamp and poll buffer data. 86241480Smckusick * For second and sucessive packets we just duplicate 86341480Smckusick * the first packet. 86441480Smckusick */ 86541480Smckusick pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail]; 86641480Smckusick if (proto == NULL) { 86741480Smckusick proto = (hil_packet *)pp; 86841480Smckusick cp = hilp->hl_pollbuf; 86941480Smckusick len = len0; 87041480Smckusick *pp++ = len + 6; 87141480Smckusick *pp++ = hilp->hl_actdev; 87241480Smckusick *(long *)pp = tenths; 87341480Smckusick pp += sizeof(long); 87441480Smckusick do *pp++ = *cp++; while (--len); 87541480Smckusick } else 87641480Smckusick *(hil_packet *)pp = *proto; 87741480Smckusick 87841480Smckusick if (++hq->hil_evqueue.tail == hq->hil_evqueue.size) 87941480Smckusick hq->hil_evqueue.tail = 0; 88041480Smckusick } 88141480Smckusick 88241480Smckusick /* 88341480Smckusick * Wake up anyone selecting on this device or the loop itself 88441480Smckusick */ 885*52533Smckusick selwakeup(&dptr->hd_selr); 88641480Smckusick dptr = &hilp->hl_device[HILLOOPDEV]; 887*52533Smckusick selwakeup(&dptr->hd_selr); 88841480Smckusick } 88941480Smckusick 89041480Smckusick #undef HQFULL 89141480Smckusick 89241480Smckusick hpuxhilevent(hilp, dptr) 89341480Smckusick register struct hilloop *hilp; 89441480Smckusick register struct hilloopdev *dptr; 89541480Smckusick { 89641480Smckusick register int len; 89741480Smckusick struct timeval ourtime; 89841480Smckusick long tstamp; 89941480Smckusick int s; 90041480Smckusick 90141480Smckusick /* 90241480Smckusick * Everybody gets the same time stamp 90341480Smckusick */ 90441480Smckusick s = splclock(); 90541480Smckusick ourtime = time; 90641480Smckusick splx(s); 90741480Smckusick tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 90841480Smckusick 90941480Smckusick /* 91041480Smckusick * Each packet that goes into the buffer must be preceded by the 91141480Smckusick * number of bytes in the packet, and the timestamp of the packet. 91241480Smckusick * This adds 5 bytes to the packet size. Make sure there is enough 91341480Smckusick * room in the buffer for it, and if not, toss the packet. 91441480Smckusick */ 91541480Smckusick len = hilp->hl_pollbp - hilp->hl_pollbuf; 91641480Smckusick if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) { 91741480Smckusick putc(len+5, &dptr->hd_queue); 91841480Smckusick (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue); 91941480Smckusick (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue); 92041480Smckusick } 92141480Smckusick 92241480Smckusick /* 92341480Smckusick * Wake up any one blocked on a read or select 92441480Smckusick */ 92541480Smckusick if (dptr->hd_flags & HIL_ASLEEP) { 92641480Smckusick dptr->hd_flags &= ~HIL_ASLEEP; 92741480Smckusick wakeup((caddr_t)dptr); 92841480Smckusick } 929*52533Smckusick selwakeup(&dptr->hd_selr); 93041480Smckusick } 93141480Smckusick 93241480Smckusick /* 93341480Smckusick * Shared queue manipulation routines 93441480Smckusick */ 93541480Smckusick 93641480Smckusick hilqalloc(qip) 93741480Smckusick struct hilqinfo *qip; 93841480Smckusick { 93949132Skarels struct proc *p = curproc; /* XXX */ 94041480Smckusick 94141480Smckusick #ifdef DEBUG 94241480Smckusick if (hildebug & HDB_FOLLOW) 94345750Smckusick printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr); 94441480Smckusick #endif 94541480Smckusick return(EINVAL); 94641480Smckusick } 94741480Smckusick 94841480Smckusick hilqfree(qnum) 94941480Smckusick register int qnum; 95041480Smckusick { 95149132Skarels struct proc *p = curproc; /* XXX */ 95241480Smckusick 95341480Smckusick #ifdef DEBUG 95441480Smckusick if (hildebug & HDB_FOLLOW) 95545750Smckusick printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum); 95641480Smckusick #endif 95741480Smckusick return(EINVAL); 95841480Smckusick } 95941480Smckusick 96041480Smckusick hilqmap(qnum, device) 96141480Smckusick register int qnum, device; 96241480Smckusick { 96349132Skarels struct proc *p = curproc; /* XXX */ 96441480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 96541480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[device]; 96641480Smckusick int s; 96741480Smckusick 96841480Smckusick #ifdef DEBUG 96941480Smckusick if (hildebug & HDB_FOLLOW) 97041480Smckusick printf("hilqmap(%d): qnum %d device %x\n", 97143316Smckusick p->p_pid, qnum, device); 97241480Smckusick #endif 97343316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) 97441480Smckusick return(EINVAL); 97541480Smckusick if ((dptr->hd_flags & HIL_QUEUEIN) == 0) 97641480Smckusick return(EINVAL); 97749132Skarels if (dptr->hd_qmask && p->p_ucred->cr_uid && 97849132Skarels p->p_ucred->cr_uid != dptr->hd_uid) 97941480Smckusick return(EPERM); 98041480Smckusick 98141480Smckusick hilp->hl_queue[qnum].hq_devmask |= hildevmask(device); 98241480Smckusick if (dptr->hd_qmask == 0) 98349132Skarels dptr->hd_uid = p->p_ucred->cr_uid; 98441480Smckusick s = splhil(); 98541480Smckusick dptr->hd_qmask |= hilqmask(qnum); 98641480Smckusick splx(s); 98741480Smckusick #ifdef DEBUG 98841480Smckusick if (hildebug & HDB_MASK) 98941480Smckusick printf("hilqmap(%d): devmask %x qmask %x\n", 99043316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask, 99141480Smckusick dptr->hd_qmask); 99241480Smckusick #endif 99341480Smckusick return(0); 99441480Smckusick } 99541480Smckusick 99641480Smckusick hilqunmap(qnum, device) 99741480Smckusick register int qnum, device; 99841480Smckusick { 99949132Skarels struct proc *p = curproc; /* XXX */ 100041480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 100141480Smckusick int s; 100241480Smckusick 100341480Smckusick #ifdef DEBUG 100441480Smckusick if (hildebug & HDB_FOLLOW) 100541480Smckusick printf("hilqunmap(%d): qnum %d device %x\n", 100643316Smckusick p->p_pid, qnum, device); 100741480Smckusick #endif 100841480Smckusick 100943316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) 101041480Smckusick return(EINVAL); 101141480Smckusick 101241480Smckusick hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device); 101341480Smckusick s = splhil(); 101441480Smckusick hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum); 101541480Smckusick splx(s); 101641480Smckusick #ifdef DEBUG 101741480Smckusick if (hildebug & HDB_MASK) 101841480Smckusick printf("hilqunmap(%d): devmask %x qmask %x\n", 101943316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask, 102041480Smckusick hilp->hl_device[device].hd_qmask); 102141480Smckusick #endif 102241480Smckusick return(0); 102341480Smckusick } 102441480Smckusick 102545788Sbostic #include "sys/clist.h" 102641480Smckusick 102741480Smckusick /* 102841480Smckusick * This is just a copy of the virgin q_to_b routine with minor 102950253Skarels * optimizations for HIL use. It is used because we don't have 103050253Skarels * to raise the priority to spltty() for most of the clist manipulations. 103141480Smckusick */ 103241480Smckusick hilq_to_b(q, cp, cc) 103341480Smckusick register struct clist *q; 103441480Smckusick register char *cp; 103541480Smckusick { 103650254Skarels register struct cblock *bp; 103750254Skarels register int nc; 103850254Skarels char *acp; 103950254Skarels int s; 104050254Skarels extern char cwaiting; 104141480Smckusick 104250254Skarels if (cc <= 0) 104350254Skarels return (0); 104450254Skarels s = splhil(); 104550254Skarels if (q->c_cc <= 0) { 104650254Skarels q->c_cc = 0; 104750254Skarels q->c_cf = q->c_cl = NULL; 104850254Skarels splx(s); 104950254Skarels return (0); 105050254Skarels } 105150254Skarels acp = cp; 105250254Skarels 105350254Skarels while (cc) { 105450254Skarels nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 105550254Skarels nc = MIN(nc, cc); 105650254Skarels nc = MIN(nc, q->c_cc); 105750254Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 105850254Skarels q->c_cf += nc; 105950254Skarels q->c_cc -= nc; 106050254Skarels cc -= nc; 106150254Skarels cp += nc; 106250254Skarels if (q->c_cc <= 0) { 106350254Skarels bp = (struct cblock *)(q->c_cf - 1); 106450254Skarels bp = (struct cblock *)((int)bp & ~CROUND); 106550254Skarels q->c_cf = q->c_cl = NULL; 106650254Skarels spltty(); 106750254Skarels bp->c_next = cfreelist; 106850254Skarels cfreelist = bp; 106950254Skarels cfreecount += CBSIZE; 107050254Skarels if (cwaiting) { 107150254Skarels wakeup(&cwaiting); 107250254Skarels cwaiting = 0; 107350254Skarels } 107450254Skarels break; 107550254Skarels } 107650254Skarels if (((int)q->c_cf & CROUND) == 0) { 107750254Skarels bp = (struct cblock *)(q->c_cf); 107850254Skarels bp--; 107950254Skarels q->c_cf = bp->c_next->c_info; 108050254Skarels spltty(); 108150254Skarels bp->c_next = cfreelist; 108250254Skarels cfreelist = bp; 108350254Skarels cfreecount += CBSIZE; 108450254Skarels if (cwaiting) { 108550254Skarels wakeup(&cwaiting); 108650254Skarels cwaiting = 0; 108750254Skarels } 108850254Skarels splhil(); 108950254Skarels } 109050254Skarels } 109150254Skarels splx(s); 109250254Skarels return (cp-acp); 109341480Smckusick } 109441480Smckusick 109541480Smckusick /* 109641480Smckusick * Cooked keyboard functions for ite driver. 109741480Smckusick * There is only one "cooked" ITE keyboard (the first keyboard found) 109841480Smckusick * per loop. There may be other keyboards, but they will always be "raw". 109941480Smckusick */ 110041480Smckusick 110141480Smckusick kbdbell() 110241480Smckusick { 110341480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 110441480Smckusick 110541480Smckusick hilbeep(hilp, &default_bell); 110641480Smckusick } 110741480Smckusick 110841480Smckusick kbdenable() 110941480Smckusick { 111041480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 111141480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 111241480Smckusick char db; 111341480Smckusick 111441480Smckusick /* Set the autorepeat rate register */ 111541480Smckusick db = ar_format(KBD_ARR); 111641480Smckusick send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL); 111741480Smckusick 111841480Smckusick /* Set the autorepeat delay register */ 111941480Smckusick db = ar_format(KBD_ARD); 112041480Smckusick send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL); 112141480Smckusick 112241480Smckusick /* Enable interrupts */ 112341480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); 112441480Smckusick } 112541480Smckusick 112641480Smckusick kbddisable() 112741480Smckusick { 112841480Smckusick } 112941480Smckusick 113041480Smckusick /* 113141480Smckusick * XXX: read keyboard directly and return code. 113241480Smckusick * Used by console getchar routine. Could really screw up anybody 113341480Smckusick * reading from the keyboard in the normal, interrupt driven fashion. 113441480Smckusick */ 113541480Smckusick kbdgetc(statp) 113641480Smckusick int *statp; 113741480Smckusick { 113841480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 113941480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 114041480Smckusick register int c, stat; 114141480Smckusick int s; 114241480Smckusick 114341480Smckusick s = splhil(); 114441480Smckusick while (((stat = hildevice->hil_stat) & HIL_DATA_RDY) == 0) 114541480Smckusick ; 114641480Smckusick c = hildevice->hil_data; 114741480Smckusick splx(s); 114841480Smckusick *statp = stat; 114941480Smckusick return(c); 115041480Smckusick } 115141480Smckusick 115241480Smckusick /* 115341480Smckusick * Recoginize and clear keyboard generated NMIs. 115441480Smckusick * Returns 1 if it was ours, 0 otherwise. Note that we cannot use 115541480Smckusick * send_hil_cmd() to issue the clear NMI command as that would actually 115641480Smckusick * lower the priority to splimp() and it doesn't wait for the completion 115741480Smckusick * of the command. Either of these conditions could result in the 115841480Smckusick * interrupt reoccuring. Note that we issue the CNMT command twice. 115941480Smckusick * This seems to be needed, once is not always enough!?! 116041480Smckusick */ 116141480Smckusick kbdnmi() 116241480Smckusick { 116341480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 116441480Smckusick 116541480Smckusick if ((*KBDNMISTAT & KBDNMI) == 0) 116641480Smckusick return(0); 116741480Smckusick HILWAIT(hilp->hl_addr); 116841480Smckusick hilp->hl_addr->hil_cmd = HIL_CNMT; 116941480Smckusick HILWAIT(hilp->hl_addr); 117041480Smckusick hilp->hl_addr->hil_cmd = HIL_CNMT; 117141480Smckusick HILWAIT(hilp->hl_addr); 117241480Smckusick return(1); 117341480Smckusick } 117441480Smckusick 117541480Smckusick #define HILSECURITY 0x33 117641480Smckusick #define HILIDENTIFY 0x03 117741480Smckusick #define HILSCBIT 0x04 117841480Smckusick 117941480Smckusick /* 118041480Smckusick * Called at boot time to print out info about interesting devices 118141480Smckusick */ 118241480Smckusick hilinfo(hilp) 118341480Smckusick register struct hilloop *hilp; 118441480Smckusick { 118541480Smckusick register int id, len; 118641480Smckusick register struct kbdmap *km; 118741480Smckusick 118841480Smckusick /* 118941480Smckusick * Keyboard info. 119041480Smckusick */ 119141480Smckusick if (hilp->hl_kbddev) { 119241480Smckusick printf("hil%d: ", hilp->hl_kbddev); 119341480Smckusick for (km = kbd_map; km->kbd_code; km++) 119441480Smckusick if (km->kbd_code == hilp->hl_kbdlang) { 119541480Smckusick printf("%s ", km->kbd_desc); 119641480Smckusick break; 119741480Smckusick } 119841480Smckusick printf("keyboard\n"); 119941480Smckusick } 120041480Smckusick /* 120141480Smckusick * ID module. 120241480Smckusick * Attempt to locate the first ID module and print out its 120341480Smckusick * security code. Is this a good idea?? 120441480Smckusick */ 120541480Smckusick id = hiliddev(hilp); 120641480Smckusick if (id) { 120741480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 120841480Smckusick hilp->hl_cmddev = id; 120941480Smckusick send_hildev_cmd(hilp, id, HILSECURITY); 121041480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 121141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 121241480Smckusick hilp->hl_cmddev = 0; 121341480Smckusick printf("hil%d: security code", id); 121441480Smckusick for (id = 0; id < len; id++) 121541480Smckusick printf(" %x", hilp->hl_cmdbuf[id]); 121641480Smckusick while (id++ < 16) 121741480Smckusick printf(" 0"); 121841480Smckusick printf("\n"); 121941480Smckusick } 122041480Smckusick } 122141480Smckusick 122241480Smckusick #define HILAR1 0x3E 122341480Smckusick #define HILAR2 0x3F 122441480Smckusick 122541480Smckusick /* 122641480Smckusick * Called after the loop has reconfigured. Here we need to: 122741480Smckusick * - determine how many devices are on the loop 122841480Smckusick * (some may have been added or removed) 122941480Smckusick * - locate the ITE keyboard (if any) and ensure 123041480Smckusick * that it is in the proper state (raw or cooked) 123141480Smckusick * and is set to use the proper language mapping table 123241480Smckusick * - ensure all other keyboards are raw 123341480Smckusick * Note that our device state is now potentially invalid as 123441480Smckusick * devices may no longer be where they were. What we should 123541480Smckusick * do here is either track where the devices went and move 123641480Smckusick * state around accordingly or, more simply, just mark all 123741480Smckusick * devices as HIL_DERROR and don't allow any further use until 123841480Smckusick * they are closed. This is a little too brutal for my tastes, 123941480Smckusick * we prefer to just assume people won't move things around. 124041480Smckusick */ 124141480Smckusick hilconfig(hilp) 124241480Smckusick register struct hilloop *hilp; 124341480Smckusick { 124441480Smckusick u_char db; 124541480Smckusick int s; 124641480Smckusick 124741480Smckusick s = splhil(); 124841480Smckusick #ifdef DEBUG 124941480Smckusick if (hildebug & HDB_CONFIG) { 125041480Smckusick printf("hilconfig: reconfigured: "); 125141480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); 125241480Smckusick printf("LPSTAT %x, ", db); 125341480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db); 125441480Smckusick printf("LPCTRL %x, ", db); 125541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); 125641480Smckusick printf("KBDSADR %x\n", db); 125741480Smckusick hilreport(hilp); 125841480Smckusick } 125941480Smckusick #endif 126041480Smckusick /* 126141480Smckusick * Determine how many devices are on the loop. 126241480Smckusick * Mark those as alive and real, all others as dead. 126341480Smckusick */ 126441480Smckusick db = 0; 126541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); 126641480Smckusick hilp->hl_maxdev = db & LPS_DEVMASK; 126741480Smckusick for (db = 1; db < NHILD; db++) { 126841480Smckusick if (db <= hilp->hl_maxdev) 126941480Smckusick hilp->hl_device[db].hd_flags |= HIL_ALIVE; 127041480Smckusick else 127141480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_ALIVE; 127241480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO; 127341480Smckusick } 127441480Smckusick #ifdef DEBUG 127541480Smckusick if (hildebug & (HDB_CONFIG|HDB_KEYBOARD)) 127641480Smckusick printf("hilconfig: max device %d\n", hilp->hl_maxdev); 127741480Smckusick #endif 127841480Smckusick if (hilp->hl_maxdev == 0) { 127941480Smckusick hilp->hl_kbddev = 0; 128041480Smckusick splx(s); 128141480Smckusick return; 128241480Smckusick } 128341480Smckusick /* 128441480Smckusick * Find out where the keyboards are and record the ITE keyboard 128541480Smckusick * (first one found). If no keyboards found, we are all done. 128641480Smckusick */ 128741480Smckusick db = 0; 128841480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); 128941480Smckusick #ifdef DEBUG 129041480Smckusick if (hildebug & HDB_KEYBOARD) 129141480Smckusick printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n", 129241480Smckusick db, hilp->hl_kbddev, ffs((int)db)); 129341480Smckusick #endif 129441480Smckusick hilp->hl_kbddev = ffs((int)db); 129541480Smckusick if (hilp->hl_kbddev == 0) { 129641480Smckusick splx(s); 129741480Smckusick return; 129841480Smckusick } 129941480Smckusick /* 130041480Smckusick * Determine if the keyboard should be cooked or raw and configure it. 130141480Smckusick */ 130241480Smckusick db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1); 130341480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL); 130441480Smckusick /* 130541480Smckusick * Re-enable autorepeat in raw mode, cooked mode AR is not affected. 130641480Smckusick */ 130741480Smckusick if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) { 130841480Smckusick db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2; 130941480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 131041480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, db); 131141480Smckusick hilp->hl_cmddev = 0; 131241480Smckusick } 131341480Smckusick /* 131441480Smckusick * Determine the keyboard language configuration, but don't 131541480Smckusick * override a user-specified setting. 131641480Smckusick */ 131741480Smckusick db = 0; 131841480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db); 131941480Smckusick #ifdef DEBUG 132041480Smckusick if (hildebug & HDB_KEYBOARD) 132141480Smckusick printf("hilconfig: language: old %x new %x\n", 132241480Smckusick hilp->hl_kbdlang, db); 132341480Smckusick #endif 132441480Smckusick if (hilp->hl_kbdlang != KBD_SPECIAL) { 132541480Smckusick struct kbdmap *km; 132641480Smckusick 132741480Smckusick for (km = kbd_map; km->kbd_code; km++) 132841480Smckusick if (km->kbd_code == db) { 132941480Smckusick hilp->hl_kbdlang = db; 133041480Smckusick /* XXX */ 133141480Smckusick kbd_keymap = km->kbd_keymap; 133241480Smckusick kbd_shiftmap = km->kbd_shiftmap; 133341480Smckusick kbd_ctrlmap = km->kbd_ctrlmap; 133441480Smckusick kbd_ctrlshiftmap = km->kbd_ctrlshiftmap; 133541480Smckusick kbd_stringmap = km->kbd_stringmap; 133641480Smckusick } 133741480Smckusick } 133841480Smckusick splx(s); 133941480Smckusick } 134041480Smckusick 134141480Smckusick hilreset(hilp) 134241480Smckusick struct hilloop *hilp; 134341480Smckusick { 134441480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 134541480Smckusick u_char db; 134641480Smckusick 134741480Smckusick /* 134841480Smckusick * Initialize the loop: reconfigure, don't report errors, 134941480Smckusick * cook keyboards, and enable autopolling. 135041480Smckusick */ 135141480Smckusick db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL; 135241480Smckusick send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL); 135341480Smckusick /* 135441480Smckusick * Delay one second for reconfiguration and then read the the 135541480Smckusick * data register to clear the interrupt (if the loop reconfigured). 135641480Smckusick */ 135741480Smckusick DELAY(1000000); 135841480Smckusick if (hildevice->hil_stat & HIL_DATA_RDY) 135941480Smckusick db = hildevice->hil_data; 136041480Smckusick /* 136141480Smckusick * The HIL loop may have reconfigured. If so we proceed on, 136241480Smckusick * if not we loop until a successful reconfiguration is reported 136341480Smckusick * back to us. The HIL loop will continue to attempt forever. 136441480Smckusick * Probably not very smart. 136541480Smckusick */ 136641480Smckusick do { 136741480Smckusick send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db); 136841480Smckusick } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0); 136941480Smckusick /* 137041480Smckusick * At this point, the loop should have reconfigured. 137141480Smckusick * The reconfiguration interrupt has already called hilconfig() 137243411Shibler * so the keyboard has been determined. 137341480Smckusick */ 137441480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); 137541480Smckusick } 137641480Smckusick 137741480Smckusick hilbeep(hilp, bp) 137841480Smckusick struct hilloop *hilp; 137941480Smckusick register struct _hilbell *bp; 138041480Smckusick { 138141480Smckusick u_char buf[2]; 138241480Smckusick 138341480Smckusick buf[0] = ~((bp->duration - 10) / 10); 138441480Smckusick buf[1] = bp->frequency; 138541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL); 138641480Smckusick } 138741480Smckusick 138841480Smckusick /* 138941480Smckusick * Locate and return the address of the first ID module, 0 if none present. 139041480Smckusick */ 139141480Smckusick hiliddev(hilp) 139241480Smckusick register struct hilloop *hilp; 139341480Smckusick { 139441480Smckusick register int i, len; 139541480Smckusick 139641480Smckusick #ifdef DEBUG 139741480Smckusick if (hildebug & HDB_IDMODULE) 139841480Smckusick printf("hiliddev(%x): looking for idmodule...", hilp); 139941480Smckusick #endif 140041480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) { 140141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 140241480Smckusick hilp->hl_cmddev = i; 140341480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY); 140441480Smckusick /* 140541480Smckusick * XXX: the final condition checks to ensure that the 140641480Smckusick * device ID byte is in the range of the ID module (0x30-0x3F) 140741480Smckusick */ 140841480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 140941480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) && 141041480Smckusick (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) { 141141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 141241480Smckusick hilp->hl_cmddev = i; 141341480Smckusick send_hildev_cmd(hilp, i, HILSECURITY); 141441480Smckusick break; 141541480Smckusick } 141641480Smckusick } 141741480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 141841480Smckusick hilp->hl_cmddev = 0; 141941480Smckusick #ifdef DEBUG 142041480Smckusick if (hildebug & HDB_IDMODULE) 142141480Smckusick if (i <= hilp->hl_maxdev) 142241480Smckusick printf("found at %d\n", i); 142341480Smckusick else 142441480Smckusick printf("not found\n"); 142541480Smckusick #endif 142641480Smckusick return(i <= hilp->hl_maxdev ? i : 0); 142741480Smckusick } 142841480Smckusick 142941480Smckusick /* 143041480Smckusick * Low level routines which actually talk to the 8042 chip. 143141480Smckusick */ 143241480Smckusick 143341480Smckusick /* 143441480Smckusick * Send a command to the 8042 with zero or more bytes of data. 143541480Smckusick * If rdata is non-null, wait for and return a byte of data. 143641480Smckusick * We run at splimp() to make the transaction as atomic as 143741480Smckusick * possible without blocking the clock (is this necessary?) 143841480Smckusick */ 143941480Smckusick send_hil_cmd(hildevice, cmd, data, dlen, rdata) 144041480Smckusick register struct hil_dev *hildevice; 144141480Smckusick u_char cmd, *data, dlen; 144241480Smckusick u_char *rdata; 144341480Smckusick { 144441480Smckusick u_char status; 144541480Smckusick int s = splimp(); 144641480Smckusick 144741480Smckusick HILWAIT(hildevice); 144841480Smckusick hildevice->hil_cmd = cmd; 144941480Smckusick while (dlen--) { 145041480Smckusick HILWAIT(hildevice); 145141480Smckusick hildevice->hil_data = *data++; 145241480Smckusick } 145341480Smckusick if (rdata) { 145441480Smckusick do { 145541480Smckusick HILDATAWAIT(hildevice); 145641480Smckusick status = hildevice->hil_stat; 145741480Smckusick *rdata = hildevice->hil_data; 145841480Smckusick } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K); 145941480Smckusick } 146041480Smckusick splx(s); 146141480Smckusick } 146241480Smckusick 146341480Smckusick /* 146441480Smckusick * Send a command to a device on the loop. 146541480Smckusick * Since only one command can be active on the loop at any time, 146641480Smckusick * we must ensure that we are not interrupted during this process. 146741480Smckusick * Hence we mask interrupts to prevent potential access from most 146841480Smckusick * interrupt routines and turn off auto-polling to disable the 146941480Smckusick * internally generated poll commands. 147041480Smckusick * 147141480Smckusick * splhigh is extremely conservative but insures atomic operation, 147241480Smckusick * splimp (clock only interrupts) seems to be good enough in practice. 147341480Smckusick */ 147441480Smckusick send_hildev_cmd(hilp, device, cmd) 147541480Smckusick register struct hilloop *hilp; 147641480Smckusick char device, cmd; 147741480Smckusick { 147841480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 147941480Smckusick u_char status, c; 148041480Smckusick int s = splimp(); 148141480Smckusick 148241480Smckusick polloff(hildevice); 148341480Smckusick 148441480Smckusick /* 148541480Smckusick * Transfer the command and device info to the chip 148641480Smckusick */ 148741480Smckusick HILWAIT(hildevice); 148841480Smckusick hildevice->hil_cmd = HIL_STARTCMD; 148941480Smckusick HILWAIT(hildevice); 149041480Smckusick hildevice->hil_data = 8 + device; 149141480Smckusick HILWAIT(hildevice); 149241480Smckusick hildevice->hil_data = cmd; 149341480Smckusick HILWAIT(hildevice); 149441480Smckusick hildevice->hil_data = HIL_TIMEOUT; 149541480Smckusick /* 149641480Smckusick * Trigger the command and wait for completion 149741480Smckusick */ 149841480Smckusick HILWAIT(hildevice); 149941480Smckusick hildevice->hil_cmd = HIL_TRIGGER; 150041480Smckusick hilp->hl_cmddone = FALSE; 150141480Smckusick do { 150241480Smckusick HILDATAWAIT(hildevice); 150341480Smckusick status = hildevice->hil_stat; 150441480Smckusick c = hildevice->hil_data; 150541480Smckusick hil_process_int(status, c); 150641480Smckusick } while (!hilp->hl_cmddone); 150741480Smckusick 150841480Smckusick pollon(hildevice); 150941480Smckusick splx(s); 151041480Smckusick } 151141480Smckusick 151241480Smckusick /* 151341480Smckusick * Turn auto-polling off and on. 151441480Smckusick * Also disables and enable auto-repeat. Why? 151541480Smckusick */ 151641480Smckusick polloff(hildevice) 151741480Smckusick register struct hil_dev *hildevice; 151841480Smckusick { 151941480Smckusick register char db; 152041480Smckusick 152141480Smckusick /* 152241480Smckusick * Turn off auto repeat 152341480Smckusick */ 152441480Smckusick HILWAIT(hildevice); 152541480Smckusick hildevice->hil_cmd = HIL_SETARR; 152641480Smckusick HILWAIT(hildevice); 152741480Smckusick hildevice->hil_data = 0; 152841480Smckusick /* 152941480Smckusick * Turn off auto-polling 153041480Smckusick */ 153141480Smckusick HILWAIT(hildevice); 153241480Smckusick hildevice->hil_cmd = HIL_READLPCTRL; 153341480Smckusick HILDATAWAIT(hildevice); 153441480Smckusick db = hildevice->hil_data; 153541480Smckusick db &= ~LPC_AUTOPOLL; 153641480Smckusick HILWAIT(hildevice); 153741480Smckusick hildevice->hil_cmd = HIL_WRITELPCTRL; 153841480Smckusick HILWAIT(hildevice); 153941480Smckusick hildevice->hil_data = db; 154041480Smckusick /* 154141480Smckusick * Must wait til polling is really stopped 154241480Smckusick */ 154341480Smckusick do { 154441480Smckusick HILWAIT(hildevice); 154541480Smckusick hildevice->hil_cmd = HIL_READBUSY; 154641480Smckusick HILDATAWAIT(hildevice); 154741480Smckusick db = hildevice->hil_data; 154841480Smckusick } while (db & BSY_LOOPBUSY); 154941480Smckusick } 155041480Smckusick 155141480Smckusick pollon(hildevice) 155241480Smckusick register struct hil_dev *hildevice; 155341480Smckusick { 155441480Smckusick register char db; 155541480Smckusick 155641480Smckusick /* 155741480Smckusick * Turn on auto polling 155841480Smckusick */ 155941480Smckusick HILWAIT(hildevice); 156041480Smckusick hildevice->hil_cmd = HIL_READLPCTRL; 156141480Smckusick HILDATAWAIT(hildevice); 156241480Smckusick db = hildevice->hil_data; 156341480Smckusick db |= LPC_AUTOPOLL; 156441480Smckusick HILWAIT(hildevice); 156541480Smckusick hildevice->hil_cmd = HIL_WRITELPCTRL; 156641480Smckusick HILWAIT(hildevice); 156741480Smckusick hildevice->hil_data = db; 156841480Smckusick /* 156941480Smckusick * Turn on auto repeat 157041480Smckusick */ 157141480Smckusick HILWAIT(hildevice); 157241480Smckusick hildevice->hil_cmd = HIL_SETARR; 157341480Smckusick HILWAIT(hildevice); 157441480Smckusick hildevice->hil_data = ar_format(KBD_ARR); 157541480Smckusick } 157641480Smckusick 157741480Smckusick #ifdef DEBUG 157841480Smckusick printhilpollbuf(hilp) 157941480Smckusick register struct hilloop *hilp; 158041480Smckusick { 158141480Smckusick register u_char *cp; 158241480Smckusick register int i, len; 158341480Smckusick 158441480Smckusick cp = hilp->hl_pollbuf; 158541480Smckusick len = hilp->hl_pollbp - cp; 158641480Smckusick for (i = 0; i < len; i++) 158741480Smckusick printf("%x ", hilp->hl_pollbuf[i]); 158841480Smckusick printf("\n"); 158941480Smckusick } 159041480Smckusick 159141480Smckusick printhilcmdbuf(hilp) 159241480Smckusick register struct hilloop *hilp; 159341480Smckusick { 159441480Smckusick register u_char *cp; 159541480Smckusick register int i, len; 159641480Smckusick 159741480Smckusick cp = hilp->hl_cmdbuf; 159841480Smckusick len = hilp->hl_cmdbp - cp; 159941480Smckusick for (i = 0; i < len; i++) 160041480Smckusick printf("%x ", hilp->hl_cmdbuf[i]); 160141480Smckusick printf("\n"); 160241480Smckusick } 160341480Smckusick 160441480Smckusick hilreport(hilp) 160541480Smckusick register struct hilloop *hilp; 160641480Smckusick { 160741480Smckusick register int i, len; 160841480Smckusick int s = splhil(); 160941480Smckusick 161041480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) { 161141480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 161241480Smckusick hilp->hl_cmddev = i; 161341480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY); 161441480Smckusick printf("hil%d: id: ", i); 161541480Smckusick printhilcmdbuf(hilp); 161641480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 161741480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) { 161841480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 161941480Smckusick hilp->hl_cmddev = i; 162041480Smckusick send_hildev_cmd(hilp, i, HILSECURITY); 162141480Smckusick printf("hil%d: sc: ", i); 162241480Smckusick printhilcmdbuf(hilp); 162341480Smckusick } 162441480Smckusick } 162541480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 162641480Smckusick hilp->hl_cmddev = 0; 162741480Smckusick splx(s); 162841480Smckusick } 162941480Smckusick #endif 1630