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*45750Smckusick * @(#)hil.c 7.5 (Berkeley) 12/05/90 1541480Smckusick */ 1641480Smckusick 1741480Smckusick #include "param.h" 1841480Smckusick #include "conf.h" 1941480Smckusick #include "user.h" 2041480Smckusick #include "proc.h" 2141480Smckusick #include "ioctl.h" 2241480Smckusick #include "file.h" 2341480Smckusick #include "tty.h" 2441480Smckusick #include "systm.h" 2541480Smckusick #include "uio.h" 2641480Smckusick #include "kernel.h" 2741480Smckusick 2841480Smckusick #include "hilreg.h" 2941480Smckusick #include "hilioctl.h" 3041480Smckusick #include "hilvar.h" 3141480Smckusick #include "kbdmap.h" 3241480Smckusick 3341480Smckusick #include "machine/cpu.h" 3441480Smckusick 35*45750Smckusick #include "../vm/vm_param.h" 36*45750Smckusick #include "../vm/vm_map.h" 37*45750Smckusick #include "../vm/vm_kern.h" 38*45750Smckusick #include "../vm/vm_page.h" 39*45750Smckusick #include "../vm/vm_pager.h" 40*45750Smckusick 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 9441480Smckusick hilopen(dev, flags) 9541480Smckusick dev_t dev; 9641480Smckusick { 9743316Smckusick struct proc *p = u.u_procp; /* XXX */ 9841480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 9941480Smckusick register struct hilloopdev *dptr; 10041480Smckusick u_char device = HILUNIT(dev); 10141480Smckusick 10241480Smckusick #ifdef DEBUG 10341480Smckusick if (hildebug & HDB_FOLLOW) 10443316Smckusick printf("hilopen(%d): device %x\n", p->p_pid, device); 10541480Smckusick #endif 10641480Smckusick 10741480Smckusick if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0) 10841480Smckusick return(ENXIO); 10941480Smckusick 11041480Smckusick dptr = &hilp->hl_device[device]; 11141480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0) 11241480Smckusick return(ENODEV); 11341480Smckusick 11441480Smckusick /* 11541480Smckusick * Pseudo-devices cannot be read, nothing more to do. 11641480Smckusick */ 11741480Smckusick if (dptr->hd_flags & HIL_PSEUDO) 11841480Smckusick return(0); 11941480Smckusick 12041480Smckusick /* 12141480Smckusick * Open semantics: 12241480Smckusick * 1. Open devices have only one of HIL_READIN/HIL_QUEUEIN. 12341480Smckusick * 2. HPUX processes always get read syscall interface and 12441480Smckusick * must have exclusive use of the device. 12541480Smckusick * 3. BSD processes default to shared queue interface. 12641480Smckusick * Multiple processes can open the device. 12741480Smckusick */ 12843316Smckusick if (p->p_flag & SHPUX) { 12941480Smckusick if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN)) 13041480Smckusick return(EBUSY); 13141480Smckusick dptr->hd_flags |= HIL_READIN; 13241480Smckusick } else { 13341480Smckusick if (dptr->hd_flags & HIL_READIN) 13441480Smckusick return(EBUSY); 13541480Smckusick dptr->hd_flags |= HIL_QUEUEIN; 13641480Smckusick } 13741480Smckusick if (flags & FNDELAY) 13841480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 13941480Smckusick /* 14041480Smckusick * It is safe to flush the read buffer as we are guarenteed 14141480Smckusick * that no one else is using it. 14241480Smckusick */ 14341480Smckusick ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); 14441480Smckusick 14541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL); 14641480Smckusick /* 14741480Smckusick * Opened the keyboard, put in raw mode. 14841480Smckusick */ 14941480Smckusick (void) splhil(); 15041480Smckusick if (device == hilp->hl_kbddev) { 15141480Smckusick u_char mask = 0; 15241480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); 15341480Smckusick hilp->hl_kbdflags |= KBD_RAW; 15441480Smckusick #ifdef DEBUG 15541480Smckusick if (hildebug & HDB_KEYBOARD) 15641480Smckusick printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev); 15741480Smckusick #endif 15841480Smckusick } 15941480Smckusick (void) spl0(); 16041480Smckusick return (0); 16141480Smckusick } 16241480Smckusick 16341480Smckusick /* ARGSUSED */ 16441480Smckusick hilclose(dev, flags) 16541480Smckusick dev_t dev; 16641480Smckusick { 16743316Smckusick struct proc *p = u.u_procp; /* XXX */ 16841480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 16941480Smckusick register struct hilloopdev *dptr; 17041480Smckusick register int i; 17141480Smckusick u_char device = HILUNIT(dev); 17241480Smckusick char mask, lpctrl; 17341480Smckusick 17441480Smckusick #ifdef DEBUG 17541480Smckusick if (hildebug & HDB_FOLLOW) 17643316Smckusick printf("hilclose(%d): device %x\n", p->p_pid, device); 17741480Smckusick #endif 17841480Smckusick 17941480Smckusick dptr = &hilp->hl_device[device]; 18041480Smckusick if (device && (dptr->hd_flags & HIL_PSEUDO)) 18141480Smckusick return (0); 18241480Smckusick 18343316Smckusick if ((p->p_flag & SHPUX) == 0) { 18441480Smckusick /* 18541480Smckusick * If this is the loop device, 18641480Smckusick * free up all queues belonging to this process. 18741480Smckusick */ 18841480Smckusick if (device == 0) { 18941480Smckusick for (i = 0; i < NHILQ; i++) 19043316Smckusick if (hilp->hl_queue[i].hq_procp == p) 19141480Smckusick (void) hilqfree(i); 19241480Smckusick } else { 19341480Smckusick mask = ~hildevmask(device); 19441480Smckusick (void) splhil(); 19541480Smckusick for (i = 0; i < NHILQ; i++) 19643316Smckusick if (hilp->hl_queue[i].hq_procp == p) { 19741480Smckusick dptr->hd_qmask &= ~hilqmask(i); 19841480Smckusick hilp->hl_queue[i].hq_devmask &= mask; 19941480Smckusick } 20041480Smckusick (void) spl0(); 20141480Smckusick } 20241480Smckusick } 20341480Smckusick /* 20441480Smckusick * Always flush the read buffer 20541480Smckusick */ 20641480Smckusick dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK); 20741480Smckusick ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); 20841480Smckusick /* 20941480Smckusick * Set keyboard back to cooked mode when closed. 21041480Smckusick */ 21141480Smckusick (void) splhil(); 21241480Smckusick if (device && device == hilp->hl_kbddev) { 21341480Smckusick mask = 1 << (hilp->hl_kbddev - 1); 21441480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); 21541480Smckusick hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2); 21641480Smckusick /* 21741480Smckusick * XXX: We have had trouble with keyboards remaining raw 21841480Smckusick * after close due to the LPC_KBDCOOK bit getting cleared 21941480Smckusick * somewhere along the line. Hence we check and reset 22041480Smckusick * LPCTRL if necessary. 22141480Smckusick */ 22241480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl); 22341480Smckusick if ((lpctrl & LPC_KBDCOOK) == 0) { 22441480Smckusick printf("hilclose: bad LPCTRL %x, reset to %x\n", 22541480Smckusick lpctrl, lpctrl|LPC_KBDCOOK); 22641480Smckusick lpctrl |= LPC_KBDCOOK; 22741480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL, 22841480Smckusick &lpctrl, 1, NULL); 22941480Smckusick } 23041480Smckusick #ifdef DEBUG 23141480Smckusick if (hildebug & HDB_KEYBOARD) 23241480Smckusick printf("hilclose: keyboard %d cooked\n", 23341480Smckusick hilp->hl_kbddev); 23441480Smckusick #endif 23541480Smckusick kbdenable(); 23641480Smckusick } 23741480Smckusick (void) spl0(); 23841480Smckusick return (0); 23941480Smckusick } 24041480Smckusick 24141480Smckusick /* 24241480Smckusick * Read interface to HIL device. 24341480Smckusick */ 24441480Smckusick hilread(dev, uio) 24541480Smckusick dev_t dev; 24641480Smckusick register struct uio *uio; 24741480Smckusick { 24841480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 24941480Smckusick register struct hilloopdev *dptr; 25041480Smckusick register int cc; 25141480Smckusick u_char device = HILUNIT(dev); 25241480Smckusick char buf[HILBUFSIZE]; 25341480Smckusick int error; 25441480Smckusick 25541480Smckusick #if 0 25641480Smckusick /* 25741480Smckusick * XXX: Don't do this since HP-UX doesn't. 25841480Smckusick * 25941480Smckusick * Check device number. 26041480Smckusick * This check is necessary since loop can reconfigure. 26141480Smckusick */ 26241480Smckusick if (device > hilp->hl_maxdev) 26341480Smckusick return(ENODEV); 26441480Smckusick #endif 26541480Smckusick 26641480Smckusick dptr = &hilp->hl_device[device]; 26741480Smckusick if ((dptr->hd_flags & HIL_READIN) == 0) 26841480Smckusick return(ENODEV); 26941480Smckusick 27041480Smckusick (void) splhil(); 27141480Smckusick while (dptr->hd_queue.c_cc == 0) { 27241480Smckusick if (dptr->hd_flags & HIL_NOBLOCK) { 27341480Smckusick spl0(); 27441480Smckusick return(EWOULDBLOCK); 27541480Smckusick } 27641480Smckusick dptr->hd_flags |= HIL_ASLEEP; 27742360Smckusick if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) { 27842360Smckusick (void) spl0(); 27942360Smckusick return (error); 28042360Smckusick } 28141480Smckusick } 28241480Smckusick (void) spl0(); 28341480Smckusick 28441480Smckusick error = 0; 28541480Smckusick while (uio->uio_resid > 0 && error == 0) { 28641480Smckusick cc = hilq_to_b(&dptr->hd_queue, buf, 28741480Smckusick MIN(uio->uio_resid, HILBUFSIZE)); 28841480Smckusick if (cc <= 0) 28941480Smckusick break; 29041480Smckusick error = uiomove(buf, cc, uio); 29141480Smckusick } 29241480Smckusick return(error); 29341480Smckusick } 29441480Smckusick 29541480Smckusick hilioctl(dev, cmd, data, flag) 29641480Smckusick dev_t dev; 29741480Smckusick caddr_t data; 29841480Smckusick { 29943316Smckusick struct proc *p = u.u_procp; /* XXX */ 30041480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 30141480Smckusick char device = HILUNIT(dev); 30241480Smckusick struct hilloopdev *dptr; 30341480Smckusick register int i; 30441480Smckusick u_char hold; 30541480Smckusick int error; 30641480Smckusick 30741480Smckusick #ifdef DEBUG 30841480Smckusick if (hildebug & HDB_FOLLOW) 30941480Smckusick printf("hilioctl(%d): dev %x cmd %x\n", 31043316Smckusick p->p_pid, device, cmd); 31141480Smckusick #endif 31241480Smckusick 31341480Smckusick dptr = &hilp->hl_device[device]; 31441480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0) 31541480Smckusick return (ENODEV); 31641480Smckusick 31741480Smckusick /* 31841480Smckusick * Don't allow hardware ioctls on virtual devices. 31941480Smckusick * Note that though these are the BSD names, they have the same 32041480Smckusick * values as the HP-UX equivalents so we catch them as well. 32141480Smckusick */ 32241480Smckusick if (dptr->hd_flags & HIL_PSEUDO) { 32341480Smckusick switch (cmd) { 32441480Smckusick case HILIOCSC: 32541480Smckusick case HILIOCID: 32641480Smckusick case HILIOCRN: 32741480Smckusick case HILIOCRS: 32841480Smckusick case HILIOCED: 32941480Smckusick return(ENODEV); 33041480Smckusick 33141480Smckusick /* 33241480Smckusick * XXX: should also return ENODEV but HP-UX compat 33341480Smckusick * breaks if we do. They work ok right now because 33441480Smckusick * we only recognize one keyboard on the loop. This 33541480Smckusick * will have to change if we remove that restriction. 33641480Smckusick */ 33741480Smckusick case HILIOCAROFF: 33841480Smckusick case HILIOCAR1: 33941480Smckusick case HILIOCAR2: 34041480Smckusick break; 34141480Smckusick 34241480Smckusick default: 34341480Smckusick break; 34441480Smckusick } 34541480Smckusick } 34641480Smckusick 34741480Smckusick #ifdef HPUXCOMPAT 34843316Smckusick if (p->p_flag & SHPUX) 34941480Smckusick return(hpuxhilioctl(dev, cmd, data, flag)); 35041480Smckusick #endif 35141480Smckusick 35241480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 35341480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); 35441480Smckusick hilp->hl_cmddev = device; 35541480Smckusick error = 0; 35641480Smckusick switch (cmd) { 35741480Smckusick 35841480Smckusick case HILIOCSBP: 35941480Smckusick /* Send four data bytes to the tone gererator. */ 36041480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); 36141480Smckusick /* Send the trigger beeper command to the 8042. */ 36241480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 36341480Smckusick break; 36441480Smckusick 36541480Smckusick case HILIOCRRT: 36641480Smckusick /* Transfer the real time to the 8042 data buffer */ 36741480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 36841480Smckusick /* Read each byte of the real time */ 36941480Smckusick for (i = 0; i < 5; i++) { 37041480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 37141480Smckusick 0, &hold); 37241480Smckusick data[4-i] = hold; 37341480Smckusick } 37441480Smckusick break; 37541480Smckusick 37641480Smckusick case HILIOCRT: 37741480Smckusick for (i = 0; i < 4; i++) { 37841480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, 37941480Smckusick NULL, 0, &hold); 38041480Smckusick data[i] = hold; 38141480Smckusick } 38241480Smckusick break; 38341480Smckusick 38441480Smckusick case HILIOCID: 38541480Smckusick case HILIOCSC: 38641480Smckusick case HILIOCRN: 38741480Smckusick case HILIOCRS: 38841480Smckusick case HILIOCED: 38941480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF)); 39041480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); 39141480Smckusick break; 39241480Smckusick 39341480Smckusick case HILIOCAROFF: 39441480Smckusick case HILIOCAR1: 39541480Smckusick case HILIOCAR2: 39641480Smckusick if (hilp->hl_kbddev) { 39741480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 39841480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); 39941480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); 40041480Smckusick if (cmd == HILIOCAR1) 40141480Smckusick hilp->hl_kbdflags |= KBD_AR1; 40241480Smckusick else if (cmd == HILIOCAR2) 40341480Smckusick hilp->hl_kbdflags |= KBD_AR2; 40441480Smckusick } 40541480Smckusick break; 40641480Smckusick 40741480Smckusick case HILIOCBEEP: 40841480Smckusick hilbeep(hilp, (struct _hilbell *)data); 40941480Smckusick break; 41041480Smckusick 41141480Smckusick case FIONBIO: 41241480Smckusick dptr = &hilp->hl_device[device]; 41341480Smckusick if (*(int *)data) 41441480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 41541480Smckusick else 41641480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK; 41741480Smckusick break; 41841480Smckusick 41941480Smckusick /* 42041480Smckusick * FIOASYNC must be present for FIONBIO above to work! 42141480Smckusick * (See fcntl in kern_descrip.c). 42241480Smckusick */ 42341480Smckusick case FIOASYNC: 42441480Smckusick break; 42541480Smckusick 42641480Smckusick case HILIOCALLOCQ: 42741480Smckusick error = hilqalloc((struct hilqinfo *)data); 42841480Smckusick break; 42941480Smckusick 43041480Smckusick case HILIOCFREEQ: 43141480Smckusick error = hilqfree(((struct hilqinfo *)data)->qid); 43241480Smckusick break; 43341480Smckusick 43441480Smckusick case HILIOCMAPQ: 43541480Smckusick error = hilqmap(*(int *)data, device); 43641480Smckusick break; 43741480Smckusick 43841480Smckusick case HILIOCUNMAPQ: 43941480Smckusick error = hilqunmap(*(int *)data, device); 44041480Smckusick break; 44141480Smckusick 44241480Smckusick case HILIOCHPUX: 44341480Smckusick dptr = &hilp->hl_device[device]; 44441480Smckusick dptr->hd_flags |= HIL_READIN; 44541480Smckusick dptr->hd_flags &= ~HIL_QUEUEIN; 44641480Smckusick break; 44741480Smckusick 44841480Smckusick case HILIOCRESET: 44941480Smckusick hilreset(hilp); 45041480Smckusick break; 45141480Smckusick 45241480Smckusick #ifdef DEBUG 45341480Smckusick case HILIOCTEST: 45441480Smckusick hildebug = *(int *) data; 45541480Smckusick break; 45641480Smckusick #endif 45741480Smckusick 45841480Smckusick default: 45941480Smckusick error = EINVAL; 46041480Smckusick break; 46141480Smckusick 46241480Smckusick } 46341480Smckusick hilp->hl_cmddev = 0; 46441480Smckusick return(error); 46541480Smckusick } 46641480Smckusick 46741480Smckusick #ifdef HPUXCOMPAT 46841480Smckusick /* ARGSUSED */ 46941480Smckusick hpuxhilioctl(dev, cmd, data, flag) 47041480Smckusick dev_t dev; 47141480Smckusick caddr_t data; 47241480Smckusick { 47341480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 47441480Smckusick char device = HILUNIT(dev); 47541480Smckusick struct hilloopdev *dptr; 47641480Smckusick register int i; 47741480Smckusick u_char hold; 47841480Smckusick 47941480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 48041480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); 48141480Smckusick hilp->hl_cmddev = device; 48241480Smckusick switch (cmd) { 48341480Smckusick 48441480Smckusick case HILSC: 48541480Smckusick case HILID: 48641480Smckusick case HILRN: 48741480Smckusick case HILRS: 48841480Smckusick case HILED: 48941480Smckusick case HILP1: 49041480Smckusick case HILP2: 49141480Smckusick case HILP3: 49241480Smckusick case HILP4: 49341480Smckusick case HILP5: 49441480Smckusick case HILP6: 49541480Smckusick case HILP7: 49641480Smckusick case HILP: 49741480Smckusick case HILA1: 49841480Smckusick case HILA2: 49941480Smckusick case HILA3: 50041480Smckusick case HILA4: 50141480Smckusick case HILA5: 50241480Smckusick case HILA6: 50341480Smckusick case HILA7: 50441480Smckusick case HILA: 50541480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF)); 50641480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); 50741480Smckusick break; 50841480Smckusick 50941480Smckusick case HILDKR: 51041480Smckusick case HILER1: 51141480Smckusick case HILER2: 51241480Smckusick if (hilp->hl_kbddev) { 51341480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 51441480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); 51541480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); 51641480Smckusick if (cmd == HILIOCAR1) 51741480Smckusick hilp->hl_kbdflags |= KBD_AR1; 51841480Smckusick else if (cmd == HILIOCAR2) 51941480Smckusick hilp->hl_kbdflags |= KBD_AR2; 52041480Smckusick } 52141480Smckusick break; 52241480Smckusick 52341480Smckusick case EFTSBP: 52441480Smckusick /* Send four data bytes to the tone gererator. */ 52541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); 52641480Smckusick /* Send the trigger beeper command to the 8042. */ 52741480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 52841480Smckusick break; 52941480Smckusick 53041480Smckusick case EFTRRT: 53141480Smckusick /* Transfer the real time to the 8042 data buffer */ 53241480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 53341480Smckusick /* Read each byte of the real time */ 53441480Smckusick for (i = 0; i < 5; i++) { 53541480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 53641480Smckusick 0, &hold); 53741480Smckusick data[4-i] = hold; 53841480Smckusick } 53941480Smckusick break; 54041480Smckusick 54141480Smckusick case EFTRT: 54241480Smckusick for (i = 0; i < 4; i++) { 54341480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, 54441480Smckusick NULL, 0, &hold); 54541480Smckusick data[i] = hold; 54641480Smckusick } 54741480Smckusick break; 54841480Smckusick 54941480Smckusick case EFTRLC: 55041480Smckusick case EFTRCC: 55141480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold); 55241480Smckusick *data = hold; 55341480Smckusick break; 55441480Smckusick 55541480Smckusick case EFTSRPG: 55641480Smckusick case EFTSRD: 55741480Smckusick case EFTSRR: 55841480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL); 55941480Smckusick break; 56041480Smckusick 56141480Smckusick case EFTSBI: 56241480Smckusick hilbeep(hilp, (struct _hilbell *)data); 56341480Smckusick break; 56441480Smckusick 56541480Smckusick case FIONBIO: 56641480Smckusick dptr = &hilp->hl_device[device]; 56741480Smckusick if (*(int *)data) 56841480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 56941480Smckusick else 57041480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK; 57141480Smckusick break; 57241480Smckusick 57341480Smckusick case FIOASYNC: 57441480Smckusick break; 57541480Smckusick 57641480Smckusick default: 57741480Smckusick hilp->hl_cmddev = 0; 57841480Smckusick return(EINVAL); 57941480Smckusick } 58041480Smckusick hilp->hl_cmddev = 0; 58141480Smckusick return(0); 58241480Smckusick } 58341480Smckusick #endif 58441480Smckusick 58541480Smckusick /* 58641480Smckusick * XXX: the mmap inteface for HIL devices should be rethought. 58741480Smckusick * We used it only briefly in conjuntion with shared queues 58841480Smckusick * (instead of HILIOCMAPQ ioctl). Perhaps mmap()ing a device 58941480Smckusick * should give a single queue per process. 59041480Smckusick */ 59141480Smckusick /* ARGSUSED */ 59241480Smckusick hilmap(dev, off, prot) 59341480Smckusick dev_t dev; 59441480Smckusick register int off; 59541480Smckusick { 59643411Shibler #ifdef MMAP 59743316Smckusick struct proc *p = u.u_procp; /* XXX */ 59841480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 59941480Smckusick register struct hiliqueue *qp; 60041480Smckusick register int qnum; 60141480Smckusick 60241480Smckusick /* 60341480Smckusick * Only allow mmap() on loop device 60441480Smckusick */ 60541480Smckusick if (HILUNIT(dev) != 0 || off >= NHILQ*sizeof(HILQ)) 60641480Smckusick return(-1); 60741480Smckusick /* 60841480Smckusick * Determine which queue we want based on the offset. 60941480Smckusick * Queue must belong to calling process. 61041480Smckusick */ 61141480Smckusick qp = &hilp->hl_queue[off / sizeof(HILQ)]; 61243316Smckusick if (qp->hq_procp != p) 61341480Smckusick return(-1); 61441480Smckusick 61541480Smckusick off %= sizeof(HILQ); 61641480Smckusick return(kvtop((u_int)qp->hq_eventqueue + off) >> PGSHIFT); 61741480Smckusick #endif 61841480Smckusick } 61941480Smckusick 62041480Smckusick /*ARGSUSED*/ 62141480Smckusick hilselect(dev, rw) 62241480Smckusick dev_t dev; 62341480Smckusick { 62443316Smckusick struct proc *p = u.u_procp; /* XXX */ 62541480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 62641480Smckusick register struct hilloopdev *dptr; 62741480Smckusick register struct hiliqueue *qp; 62841480Smckusick register int mask; 62941480Smckusick int s, device; 63041480Smckusick 63141480Smckusick if (rw == FWRITE) 63241480Smckusick return (1); 63341480Smckusick device = HILUNIT(dev); 63441480Smckusick 63541480Smckusick /* 63641480Smckusick * Read interface. 63741480Smckusick * Return 1 if there is something in the queue, 0 ow. 63841480Smckusick */ 63941480Smckusick dptr = &hilp->hl_device[device]; 64041480Smckusick if (dptr->hd_flags & HIL_READIN) { 64141480Smckusick s = splhil(); 64241480Smckusick if (dptr->hd_queue.c_cc) { 64341480Smckusick splx(s); 64441480Smckusick return (1); 64541480Smckusick } 64641480Smckusick if (dptr->hd_selr && 64741480Smckusick dptr->hd_selr->p_wchan == (caddr_t)&selwait) 64841480Smckusick dptr->hd_flags |= HIL_SELCOLL; 64941480Smckusick else 65043316Smckusick dptr->hd_selr = p; 65141480Smckusick splx(s); 65241480Smckusick return (0); 65341480Smckusick } 65441480Smckusick 65541480Smckusick /* 65641480Smckusick * Make sure device is alive and real (or the loop device). 65741480Smckusick * Note that we do not do this for the read interface. 65841480Smckusick * This is primarily to be consistant with HP-UX. 65941480Smckusick */ 66041480Smckusick if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE) 66141480Smckusick return (1); 66241480Smckusick 66341480Smckusick /* 66441480Smckusick * Select on loop device is special. 66541480Smckusick * Check to see if there are any data for any loop device 66641480Smckusick * provided it is associated with a queue belonging to this user. 66741480Smckusick */ 66841480Smckusick if (device == 0) 66941480Smckusick mask = -1; 67041480Smckusick else 67141480Smckusick mask = hildevmask(device); 67241480Smckusick /* 67341480Smckusick * Must check everybody with interrupts blocked to prevent races. 67441480Smckusick */ 67541480Smckusick s = splhil(); 67641480Smckusick for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++) 67743316Smckusick if (qp->hq_procp == p && (mask & qp->hq_devmask) && 67841480Smckusick qp->hq_eventqueue->hil_evqueue.head != 67941480Smckusick qp->hq_eventqueue->hil_evqueue.tail) { 68041480Smckusick splx(s); 68141480Smckusick return (1); 68241480Smckusick } 68341480Smckusick 68441480Smckusick if (dptr->hd_selr && dptr->hd_selr->p_wchan == (caddr_t)&selwait) 68541480Smckusick dptr->hd_flags |= HIL_SELCOLL; 68641480Smckusick else 68743316Smckusick dptr->hd_selr = p; 68841480Smckusick splx(s); 68941480Smckusick return (0); 69041480Smckusick } 69141480Smckusick 69241480Smckusick hilint() 69341480Smckusick { 69441480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 69541480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 69641480Smckusick u_char c, stat; 69741480Smckusick 69841480Smckusick stat = hildevice->hil_stat; 69941480Smckusick c = hildevice->hil_data; /* clears interrupt */ 70041480Smckusick hil_process_int(stat, c); 70141480Smckusick } 70241480Smckusick 70341480Smckusick #include "ite.h" 70441480Smckusick 70541480Smckusick hil_process_int(stat, c) 70641480Smckusick register u_char stat, c; 70741480Smckusick { 70841480Smckusick register struct hilloop *hilp; 70941480Smckusick 71041480Smckusick #ifdef DEBUG 71141480Smckusick if (hildebug & HDB_EVENTS) 71241480Smckusick printf("hilint: %x %x\n", stat, c); 71341480Smckusick #endif 71441480Smckusick 71541480Smckusick /* the shift enables the compiler to generate a jump table */ 71641480Smckusick switch ((stat>>HIL_SSHIFT) & HIL_SMASK) { 71741480Smckusick 71841480Smckusick #if NITE > 0 71941480Smckusick case HIL_KEY: 72041480Smckusick case HIL_SHIFT: 72141480Smckusick case HIL_CTRL: 72241480Smckusick case HIL_CTRLSHIFT: 72341480Smckusick itefilter(stat, c); 72441480Smckusick return; 72541480Smckusick #endif 72641480Smckusick 72741480Smckusick case HIL_STATUS: /* The status info. */ 72841480Smckusick hilp = &hil0; /* XXX */ 72941480Smckusick if (c & HIL_ERROR) { 73041480Smckusick hilp->hl_cmddone = TRUE; 73141480Smckusick if (c == HIL_RECONFIG) 73241480Smckusick hilconfig(hilp); 73341480Smckusick break; 73441480Smckusick } 73541480Smckusick if (c & HIL_COMMAND) { 73641480Smckusick if (c & HIL_POLLDATA) /* End of data */ 73741480Smckusick hilevent(hilp); 73841480Smckusick else /* End of command */ 73941480Smckusick hilp->hl_cmdending = TRUE; 74041480Smckusick hilp->hl_actdev = 0; 74141480Smckusick } else { 74241480Smckusick if (c & HIL_POLLDATA) { /* Start of polled data */ 74341480Smckusick if (hilp->hl_actdev != 0) 74441480Smckusick hilevent(hilp); 74541480Smckusick hilp->hl_actdev = (c & HIL_DEVMASK); 74641480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf; 74741480Smckusick } else { /* Start of command */ 74841480Smckusick if (hilp->hl_cmddev == (c & HIL_DEVMASK)) { 74941480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 75041480Smckusick hilp->hl_actdev = 0; 75141480Smckusick } 75241480Smckusick } 75341480Smckusick } 75441480Smckusick return; 75541480Smckusick 75641480Smckusick case HIL_DATA: 75741480Smckusick hilp = &hil0; /* XXX */ 75841480Smckusick if (hilp->hl_actdev != 0) /* Collecting poll data */ 75941480Smckusick *hilp->hl_pollbp++ = c; 76041480Smckusick else if (hilp->hl_cmddev != 0) /* Collecting cmd data */ 76141480Smckusick if (hilp->hl_cmdending) { 76241480Smckusick hilp->hl_cmddone = TRUE; 76341480Smckusick hilp->hl_cmdending = FALSE; 76441480Smckusick } else 76541480Smckusick *hilp->hl_cmdbp++ = c; 76641480Smckusick return; 76741480Smckusick 76841480Smckusick case 0: /* force full jump table */ 76941480Smckusick default: 77041480Smckusick return; 77141480Smckusick } 77241480Smckusick } 77341480Smckusick 77441480Smckusick #if defined(DEBUG) && !defined(PANICBUTTON) 77541480Smckusick #define PANICBUTTON 77641480Smckusick #endif 77741480Smckusick 77841480Smckusick /* 77941480Smckusick * Optimized macro to compute: 78041480Smckusick * eq->head == (eq->tail + 1) % eq->size 78141480Smckusick * i.e. has tail caught up with head. We do this because 32 bit long 78241480Smckusick * remaidering is expensive (a function call with our compiler). 78341480Smckusick */ 78441480Smckusick #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1) 78541480Smckusick #define HQVALID(eq) \ 78641480Smckusick ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE) 78741480Smckusick 78841480Smckusick hilevent(hilp) 78941480Smckusick struct hilloop *hilp; 79041480Smckusick { 79141480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev]; 79241480Smckusick register int len, mask, qnum; 79341480Smckusick register u_char *cp, *pp; 79441480Smckusick register HILQ *hq; 79541480Smckusick struct timeval ourtime; 79641480Smckusick hil_packet *proto; 79741480Smckusick int s, len0; 79841480Smckusick long tenths; 79941480Smckusick 80041480Smckusick #ifdef PANICBUTTON 80141480Smckusick static int first; 80241480Smckusick extern int panicbutton; 80341480Smckusick 80441480Smckusick cp = hilp->hl_pollbuf; 80541480Smckusick if (panicbutton && (*cp & HIL_KBDDATA)) { 80641480Smckusick if (*++cp == 0x4E) 80741480Smckusick first = 1; 80841480Smckusick else if (first && *cp == 0x46 && !panicstr) 80941480Smckusick panic("are we having fun yet?"); 81041480Smckusick else 81141480Smckusick first = 0; 81241480Smckusick } 81341480Smckusick #endif 81441480Smckusick #ifdef DEBUG 81541480Smckusick if (hildebug & HDB_EVENTS) { 81641480Smckusick printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev); 81741480Smckusick printhilpollbuf(hilp); 81841480Smckusick printf("\n"); 81941480Smckusick } 82041480Smckusick #endif 82141480Smckusick 82241480Smckusick /* 82341480Smckusick * Note that HIL_READIN effectively "shuts off" any queues 82441480Smckusick * that may have been in use at the time of an HILIOCHPUX call. 82541480Smckusick */ 82641480Smckusick if (dptr->hd_flags & HIL_READIN) { 82741480Smckusick hpuxhilevent(hilp, dptr); 82841480Smckusick return; 82941480Smckusick } 83041480Smckusick 83141480Smckusick /* 83241480Smckusick * If this device isn't on any queue or there are no data 83341480Smckusick * in the packet (can this happen?) do nothing. 83441480Smckusick */ 83541480Smckusick if (dptr->hd_qmask == 0 || 83641480Smckusick (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0) 83741480Smckusick return; 83841480Smckusick 83941480Smckusick /* 84041480Smckusick * Everybody gets the same time stamp 84141480Smckusick */ 84241480Smckusick s = splclock(); 84341480Smckusick ourtime = time; 84441480Smckusick splx(s); 84541480Smckusick tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 84641480Smckusick 84741480Smckusick proto = NULL; 84841480Smckusick mask = dptr->hd_qmask; 84941480Smckusick for (qnum = 0; mask; qnum++) { 85041480Smckusick if ((mask & hilqmask(qnum)) == 0) 85141480Smckusick continue; 85241480Smckusick mask &= ~hilqmask(qnum); 85341480Smckusick hq = hilp->hl_queue[qnum].hq_eventqueue; 85441480Smckusick 85541480Smckusick /* 85641480Smckusick * Ensure that queue fields that we rely on are valid 85741480Smckusick * and that there is space in the queue. If either 85841480Smckusick * test fails, we just skip this queue. 85941480Smckusick */ 86041480Smckusick if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue)) 86141480Smckusick continue; 86241480Smckusick 86341480Smckusick /* 86441480Smckusick * Copy data to queue. 86541480Smckusick * If this is the first queue we construct the packet 86641480Smckusick * with length, timestamp and poll buffer data. 86741480Smckusick * For second and sucessive packets we just duplicate 86841480Smckusick * the first packet. 86941480Smckusick */ 87041480Smckusick pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail]; 87141480Smckusick if (proto == NULL) { 87241480Smckusick proto = (hil_packet *)pp; 87341480Smckusick cp = hilp->hl_pollbuf; 87441480Smckusick len = len0; 87541480Smckusick *pp++ = len + 6; 87641480Smckusick *pp++ = hilp->hl_actdev; 87741480Smckusick *(long *)pp = tenths; 87841480Smckusick pp += sizeof(long); 87941480Smckusick do *pp++ = *cp++; while (--len); 88041480Smckusick } else 88141480Smckusick *(hil_packet *)pp = *proto; 88241480Smckusick 88341480Smckusick if (++hq->hil_evqueue.tail == hq->hil_evqueue.size) 88441480Smckusick hq->hil_evqueue.tail = 0; 88541480Smckusick } 88641480Smckusick 88741480Smckusick /* 88841480Smckusick * Wake up anyone selecting on this device or the loop itself 88941480Smckusick */ 89041480Smckusick if (dptr->hd_selr) { 89141480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 89241480Smckusick dptr->hd_selr = NULL; 89341480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 89441480Smckusick } 89541480Smckusick dptr = &hilp->hl_device[HILLOOPDEV]; 89641480Smckusick if (dptr->hd_selr) { 89741480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 89841480Smckusick dptr->hd_selr = NULL; 89941480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 90041480Smckusick } 90141480Smckusick } 90241480Smckusick 90341480Smckusick #undef HQFULL 90441480Smckusick 90541480Smckusick hpuxhilevent(hilp, dptr) 90641480Smckusick register struct hilloop *hilp; 90741480Smckusick register struct hilloopdev *dptr; 90841480Smckusick { 90941480Smckusick register int len; 91041480Smckusick struct timeval ourtime; 91141480Smckusick long tstamp; 91241480Smckusick int s; 91341480Smckusick 91441480Smckusick /* 91541480Smckusick * Everybody gets the same time stamp 91641480Smckusick */ 91741480Smckusick s = splclock(); 91841480Smckusick ourtime = time; 91941480Smckusick splx(s); 92041480Smckusick tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 92141480Smckusick 92241480Smckusick /* 92341480Smckusick * Each packet that goes into the buffer must be preceded by the 92441480Smckusick * number of bytes in the packet, and the timestamp of the packet. 92541480Smckusick * This adds 5 bytes to the packet size. Make sure there is enough 92641480Smckusick * room in the buffer for it, and if not, toss the packet. 92741480Smckusick */ 92841480Smckusick len = hilp->hl_pollbp - hilp->hl_pollbuf; 92941480Smckusick if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) { 93041480Smckusick putc(len+5, &dptr->hd_queue); 93141480Smckusick (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue); 93241480Smckusick (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue); 93341480Smckusick } 93441480Smckusick 93541480Smckusick /* 93641480Smckusick * Wake up any one blocked on a read or select 93741480Smckusick */ 93841480Smckusick if (dptr->hd_flags & HIL_ASLEEP) { 93941480Smckusick dptr->hd_flags &= ~HIL_ASLEEP; 94041480Smckusick wakeup((caddr_t)dptr); 94141480Smckusick } 94241480Smckusick if (dptr->hd_selr) { 94341480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 94441480Smckusick dptr->hd_selr = NULL; 94541480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 94641480Smckusick } 94741480Smckusick } 94841480Smckusick 94941480Smckusick /* 95041480Smckusick * Shared queue manipulation routines 95141480Smckusick */ 95241480Smckusick 95341480Smckusick hilqalloc(qip) 95441480Smckusick struct hilqinfo *qip; 95541480Smckusick { 95643316Smckusick struct proc *p = u.u_procp; /* XXX */ 95741480Smckusick 95841480Smckusick #ifdef DEBUG 95941480Smckusick if (hildebug & HDB_FOLLOW) 960*45750Smckusick printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr); 96141480Smckusick #endif 96241480Smckusick return(EINVAL); 96341480Smckusick } 96441480Smckusick 96541480Smckusick hilqfree(qnum) 96641480Smckusick register int qnum; 96741480Smckusick { 96843316Smckusick struct proc *p = u.u_procp; /* XXX */ 96941480Smckusick 97041480Smckusick #ifdef DEBUG 97141480Smckusick if (hildebug & HDB_FOLLOW) 972*45750Smckusick printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum); 97341480Smckusick #endif 97441480Smckusick return(EINVAL); 97541480Smckusick } 97641480Smckusick 97741480Smckusick hilqmap(qnum, device) 97841480Smckusick register int qnum, device; 97941480Smckusick { 98043316Smckusick struct proc *p = u.u_procp; /* XXX */ 98141480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 98241480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[device]; 98341480Smckusick int s; 98441480Smckusick 98541480Smckusick #ifdef DEBUG 98641480Smckusick if (hildebug & HDB_FOLLOW) 98741480Smckusick printf("hilqmap(%d): qnum %d device %x\n", 98843316Smckusick p->p_pid, qnum, device); 98941480Smckusick #endif 99043316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) 99141480Smckusick return(EINVAL); 99241480Smckusick if ((dptr->hd_flags & HIL_QUEUEIN) == 0) 99341480Smckusick return(EINVAL); 99441480Smckusick if (dptr->hd_qmask && u.u_uid && u.u_uid != dptr->hd_uid) 99541480Smckusick return(EPERM); 99641480Smckusick 99741480Smckusick hilp->hl_queue[qnum].hq_devmask |= hildevmask(device); 99841480Smckusick if (dptr->hd_qmask == 0) 99941480Smckusick dptr->hd_uid = u.u_uid; 100041480Smckusick s = splhil(); 100141480Smckusick dptr->hd_qmask |= hilqmask(qnum); 100241480Smckusick splx(s); 100341480Smckusick #ifdef DEBUG 100441480Smckusick if (hildebug & HDB_MASK) 100541480Smckusick printf("hilqmap(%d): devmask %x qmask %x\n", 100643316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask, 100741480Smckusick dptr->hd_qmask); 100841480Smckusick #endif 100941480Smckusick return(0); 101041480Smckusick } 101141480Smckusick 101241480Smckusick hilqunmap(qnum, device) 101341480Smckusick register int qnum, device; 101441480Smckusick { 101543316Smckusick struct proc *p = u.u_procp; /* XXX */ 101641480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 101741480Smckusick int s; 101841480Smckusick 101941480Smckusick #ifdef DEBUG 102041480Smckusick if (hildebug & HDB_FOLLOW) 102141480Smckusick printf("hilqunmap(%d): qnum %d device %x\n", 102243316Smckusick p->p_pid, qnum, device); 102341480Smckusick #endif 102441480Smckusick 102543316Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) 102641480Smckusick return(EINVAL); 102741480Smckusick 102841480Smckusick hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device); 102941480Smckusick s = splhil(); 103041480Smckusick hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum); 103141480Smckusick splx(s); 103241480Smckusick #ifdef DEBUG 103341480Smckusick if (hildebug & HDB_MASK) 103441480Smckusick printf("hilqunmap(%d): devmask %x qmask %x\n", 103543316Smckusick p->p_pid, hilp->hl_queue[qnum].hq_devmask, 103641480Smckusick hilp->hl_device[device].hd_qmask); 103741480Smckusick #endif 103841480Smckusick return(0); 103941480Smckusick } 104041480Smckusick 104141480Smckusick #include "clist.h" 104241480Smckusick 104341480Smckusick /* 104441480Smckusick * This is just a copy of the virgin q_to_b routine with minor 104541480Smckusick * optimizations for HIL use. It is used for two reasons: 104641480Smckusick * 1. If we have PAGE mode defined, the normal q_to_b processes 104741480Smckusick * chars one at a time and breaks on newlines. 104841480Smckusick * 2. We don't have to raise the priority to spltty() for most 104941480Smckusick * of the clist manipulations. 105041480Smckusick */ 105141480Smckusick hilq_to_b(q, cp, cc) 105241480Smckusick register struct clist *q; 105341480Smckusick register char *cp; 105441480Smckusick { 105541480Smckusick register struct cblock *bp; 105641480Smckusick register int nc; 105741480Smckusick char *acp; 105841480Smckusick int s; 105941480Smckusick extern char cwaiting; 106041480Smckusick 106141480Smckusick if (cc <= 0) 106241480Smckusick return (0); 106341480Smckusick s = splhil(); 106441480Smckusick if (q->c_cc <= 0) { 106541480Smckusick q->c_cc = 0; 106641480Smckusick q->c_cf = q->c_cl = NULL; 106741480Smckusick splx(s); 106841480Smckusick return (0); 106941480Smckusick } 107041480Smckusick acp = cp; 107141480Smckusick 107241480Smckusick while (cc) { 107341480Smckusick nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 107441480Smckusick nc = MIN(nc, cc); 107541480Smckusick nc = MIN(nc, q->c_cc); 107641480Smckusick (void) bcopy(q->c_cf, cp, (unsigned)nc); 107741480Smckusick q->c_cf += nc; 107841480Smckusick q->c_cc -= nc; 107941480Smckusick cc -= nc; 108041480Smckusick cp += nc; 108141480Smckusick if (q->c_cc <= 0) { 108241480Smckusick bp = (struct cblock *)(q->c_cf - 1); 108341480Smckusick bp = (struct cblock *)((int)bp & ~CROUND); 108441480Smckusick q->c_cf = q->c_cl = NULL; 108541480Smckusick spltty(); 108641480Smckusick bp->c_next = cfreelist; 108741480Smckusick cfreelist = bp; 108841480Smckusick cfreecount += CBSIZE; 108941480Smckusick if (cwaiting) { 109041480Smckusick wakeup(&cwaiting); 109141480Smckusick cwaiting = 0; 109241480Smckusick } 109341480Smckusick break; 109441480Smckusick } 109541480Smckusick if (((int)q->c_cf & CROUND) == 0) { 109641480Smckusick bp = (struct cblock *)(q->c_cf); 109741480Smckusick bp--; 109841480Smckusick q->c_cf = bp->c_next->c_info; 109941480Smckusick spltty(); 110041480Smckusick bp->c_next = cfreelist; 110141480Smckusick cfreelist = bp; 110241480Smckusick cfreecount += CBSIZE; 110341480Smckusick if (cwaiting) { 110441480Smckusick wakeup(&cwaiting); 110541480Smckusick cwaiting = 0; 110641480Smckusick } 110741480Smckusick splhil(); 110841480Smckusick } 110941480Smckusick } 111041480Smckusick splx(s); 111141480Smckusick 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