1*41480Smckusick /* 2*41480Smckusick * Copyright (c) 1988 University of Utah. 3*41480Smckusick * Copyright (c) 1990 The Regents of the University of California. 4*41480Smckusick * All rights reserved. 5*41480Smckusick * 6*41480Smckusick * This code is derived from software contributed to Berkeley by 7*41480Smckusick * the Systems Programming Group of the University of Utah Computer 8*41480Smckusick * Science Department. 9*41480Smckusick * 10*41480Smckusick * %sccs.include.redist.c% 11*41480Smckusick * 12*41480Smckusick * from: Utah $Hdr: hil.c 1.33 89/12/22$ 13*41480Smckusick * 14*41480Smckusick * @(#)hil.c 7.1 (Berkeley) 05/08/90 15*41480Smckusick */ 16*41480Smckusick 17*41480Smckusick #include "param.h" 18*41480Smckusick #include "conf.h" 19*41480Smckusick #include "user.h" 20*41480Smckusick #include "proc.h" 21*41480Smckusick #include "ioctl.h" 22*41480Smckusick #include "file.h" 23*41480Smckusick #include "tty.h" 24*41480Smckusick #include "systm.h" 25*41480Smckusick #include "uio.h" 26*41480Smckusick #include "kernel.h" 27*41480Smckusick #include "mapmem.h" 28*41480Smckusick 29*41480Smckusick #include "hilreg.h" 30*41480Smckusick #include "hilioctl.h" 31*41480Smckusick #include "hilvar.h" 32*41480Smckusick #include "kbdmap.h" 33*41480Smckusick 34*41480Smckusick #include "machine/cpu.h" 35*41480Smckusick 36*41480Smckusick struct hilloop hil0; 37*41480Smckusick struct _hilbell default_bell = { BELLDUR, BELLFREQ }; 38*41480Smckusick 39*41480Smckusick #ifdef MAPMEM 40*41480Smckusick int hilqfork(), hilqvfork(), hilqexit(); 41*41480Smckusick struct mapmemops hilqops = { hilqfork, hilqvfork, hilqexit, hilqexit }; 42*41480Smckusick #endif 43*41480Smckusick 44*41480Smckusick #ifdef DEBUG 45*41480Smckusick int hildebug = 0; 46*41480Smckusick #define HDB_FOLLOW 0x01 47*41480Smckusick #define HDB_MMAP 0x02 48*41480Smckusick #define HDB_MASK 0x04 49*41480Smckusick #define HDB_CONFIG 0x08 50*41480Smckusick #define HDB_KEYBOARD 0x10 51*41480Smckusick #define HDB_IDMODULE 0x20 52*41480Smckusick #define HDB_EVENTS 0x80 53*41480Smckusick #endif 54*41480Smckusick 55*41480Smckusick hilinit() 56*41480Smckusick { 57*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 58*41480Smckusick register int i; 59*41480Smckusick 60*41480Smckusick /* 61*41480Smckusick * Initialize loop information 62*41480Smckusick */ 63*41480Smckusick hilp->hl_addr = HILADDR; 64*41480Smckusick hilp->hl_cmdending = FALSE; 65*41480Smckusick hilp->hl_actdev = hilp->hl_cmddev = 0; 66*41480Smckusick hilp->hl_cmddone = FALSE; 67*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 68*41480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf; 69*41480Smckusick hilp->hl_kbddev = 0; 70*41480Smckusick hilp->hl_kbdlang = KBD_DEFAULT; 71*41480Smckusick hilp->hl_kbdflags = 0; 72*41480Smckusick /* 73*41480Smckusick * Clear all queues and device associations with queues 74*41480Smckusick */ 75*41480Smckusick for (i = 0; i < NHILQ; i++) { 76*41480Smckusick hilp->hl_queue[i].hq_eventqueue = NULL; 77*41480Smckusick hilp->hl_queue[i].hq_procp = NULL; 78*41480Smckusick hilp->hl_queue[i].hq_devmask = 0; 79*41480Smckusick } 80*41480Smckusick for (i = 0; i < NHILD; i++) 81*41480Smckusick hilp->hl_device[i].hd_qmask = 0; 82*41480Smckusick hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO); 83*41480Smckusick /* 84*41480Smckusick * Reset the loop hardware, and collect keyboard/id info 85*41480Smckusick */ 86*41480Smckusick hilreset(hilp); 87*41480Smckusick hilinfo(hilp); 88*41480Smckusick kbdenable(); 89*41480Smckusick } 90*41480Smckusick 91*41480Smckusick hilopen(dev, flags) 92*41480Smckusick dev_t dev; 93*41480Smckusick { 94*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 95*41480Smckusick register struct hilloopdev *dptr; 96*41480Smckusick u_char device = HILUNIT(dev); 97*41480Smckusick 98*41480Smckusick #ifdef DEBUG 99*41480Smckusick if (hildebug & HDB_FOLLOW) 100*41480Smckusick printf("hilopen(%d): device %x\n", u.u_procp->p_pid, device); 101*41480Smckusick #endif 102*41480Smckusick 103*41480Smckusick if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0) 104*41480Smckusick return(ENXIO); 105*41480Smckusick 106*41480Smckusick dptr = &hilp->hl_device[device]; 107*41480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0) 108*41480Smckusick return(ENODEV); 109*41480Smckusick 110*41480Smckusick /* 111*41480Smckusick * Pseudo-devices cannot be read, nothing more to do. 112*41480Smckusick */ 113*41480Smckusick if (dptr->hd_flags & HIL_PSEUDO) 114*41480Smckusick return(0); 115*41480Smckusick 116*41480Smckusick /* 117*41480Smckusick * Open semantics: 118*41480Smckusick * 1. Open devices have only one of HIL_READIN/HIL_QUEUEIN. 119*41480Smckusick * 2. HPUX processes always get read syscall interface and 120*41480Smckusick * must have exclusive use of the device. 121*41480Smckusick * 3. BSD processes default to shared queue interface. 122*41480Smckusick * Multiple processes can open the device. 123*41480Smckusick */ 124*41480Smckusick if (u.u_procp->p_flag & SHPUX) { 125*41480Smckusick if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN)) 126*41480Smckusick return(EBUSY); 127*41480Smckusick dptr->hd_flags |= HIL_READIN; 128*41480Smckusick } else { 129*41480Smckusick if (dptr->hd_flags & HIL_READIN) 130*41480Smckusick return(EBUSY); 131*41480Smckusick dptr->hd_flags |= HIL_QUEUEIN; 132*41480Smckusick } 133*41480Smckusick if (flags & FNDELAY) 134*41480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 135*41480Smckusick /* 136*41480Smckusick * It is safe to flush the read buffer as we are guarenteed 137*41480Smckusick * that no one else is using it. 138*41480Smckusick */ 139*41480Smckusick ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); 140*41480Smckusick 141*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL); 142*41480Smckusick /* 143*41480Smckusick * Opened the keyboard, put in raw mode. 144*41480Smckusick */ 145*41480Smckusick (void) splhil(); 146*41480Smckusick if (device == hilp->hl_kbddev) { 147*41480Smckusick u_char mask = 0; 148*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); 149*41480Smckusick hilp->hl_kbdflags |= KBD_RAW; 150*41480Smckusick #ifdef DEBUG 151*41480Smckusick if (hildebug & HDB_KEYBOARD) 152*41480Smckusick printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev); 153*41480Smckusick #endif 154*41480Smckusick } 155*41480Smckusick (void) spl0(); 156*41480Smckusick return (0); 157*41480Smckusick } 158*41480Smckusick 159*41480Smckusick /* ARGSUSED */ 160*41480Smckusick hilclose(dev, flags) 161*41480Smckusick dev_t dev; 162*41480Smckusick { 163*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 164*41480Smckusick register struct hilloopdev *dptr; 165*41480Smckusick register int i; 166*41480Smckusick u_char device = HILUNIT(dev); 167*41480Smckusick char mask, lpctrl; 168*41480Smckusick 169*41480Smckusick #ifdef DEBUG 170*41480Smckusick if (hildebug & HDB_FOLLOW) 171*41480Smckusick printf("hilclose(%d): device %x\n", u.u_procp->p_pid, device); 172*41480Smckusick #endif 173*41480Smckusick 174*41480Smckusick dptr = &hilp->hl_device[device]; 175*41480Smckusick if (device && (dptr->hd_flags & HIL_PSEUDO)) 176*41480Smckusick return (0); 177*41480Smckusick 178*41480Smckusick if ((u.u_procp->p_flag & SHPUX) == 0) { 179*41480Smckusick /* 180*41480Smckusick * If this is the loop device, 181*41480Smckusick * free up all queues belonging to this process. 182*41480Smckusick */ 183*41480Smckusick if (device == 0) { 184*41480Smckusick for (i = 0; i < NHILQ; i++) 185*41480Smckusick if (hilp->hl_queue[i].hq_procp == u.u_procp) 186*41480Smckusick (void) hilqfree(i); 187*41480Smckusick } else { 188*41480Smckusick mask = ~hildevmask(device); 189*41480Smckusick (void) splhil(); 190*41480Smckusick for (i = 0; i < NHILQ; i++) 191*41480Smckusick if (hilp->hl_queue[i].hq_procp == u.u_procp) { 192*41480Smckusick dptr->hd_qmask &= ~hilqmask(i); 193*41480Smckusick hilp->hl_queue[i].hq_devmask &= mask; 194*41480Smckusick } 195*41480Smckusick (void) spl0(); 196*41480Smckusick } 197*41480Smckusick } 198*41480Smckusick /* 199*41480Smckusick * Always flush the read buffer 200*41480Smckusick */ 201*41480Smckusick dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK); 202*41480Smckusick ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc); 203*41480Smckusick /* 204*41480Smckusick * Set keyboard back to cooked mode when closed. 205*41480Smckusick */ 206*41480Smckusick (void) splhil(); 207*41480Smckusick if (device && device == hilp->hl_kbddev) { 208*41480Smckusick mask = 1 << (hilp->hl_kbddev - 1); 209*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL); 210*41480Smckusick hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2); 211*41480Smckusick /* 212*41480Smckusick * XXX: We have had trouble with keyboards remaining raw 213*41480Smckusick * after close due to the LPC_KBDCOOK bit getting cleared 214*41480Smckusick * somewhere along the line. Hence we check and reset 215*41480Smckusick * LPCTRL if necessary. 216*41480Smckusick */ 217*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl); 218*41480Smckusick if ((lpctrl & LPC_KBDCOOK) == 0) { 219*41480Smckusick printf("hilclose: bad LPCTRL %x, reset to %x\n", 220*41480Smckusick lpctrl, lpctrl|LPC_KBDCOOK); 221*41480Smckusick lpctrl |= LPC_KBDCOOK; 222*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL, 223*41480Smckusick &lpctrl, 1, NULL); 224*41480Smckusick } 225*41480Smckusick #ifdef DEBUG 226*41480Smckusick if (hildebug & HDB_KEYBOARD) 227*41480Smckusick printf("hilclose: keyboard %d cooked\n", 228*41480Smckusick hilp->hl_kbddev); 229*41480Smckusick #endif 230*41480Smckusick kbdenable(); 231*41480Smckusick } 232*41480Smckusick (void) spl0(); 233*41480Smckusick return (0); 234*41480Smckusick } 235*41480Smckusick 236*41480Smckusick /* 237*41480Smckusick * Read interface to HIL device. 238*41480Smckusick */ 239*41480Smckusick hilread(dev, uio) 240*41480Smckusick dev_t dev; 241*41480Smckusick register struct uio *uio; 242*41480Smckusick { 243*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 244*41480Smckusick register struct hilloopdev *dptr; 245*41480Smckusick register int cc; 246*41480Smckusick u_char device = HILUNIT(dev); 247*41480Smckusick char buf[HILBUFSIZE]; 248*41480Smckusick int error; 249*41480Smckusick 250*41480Smckusick #if 0 251*41480Smckusick /* 252*41480Smckusick * XXX: Don't do this since HP-UX doesn't. 253*41480Smckusick * 254*41480Smckusick * Check device number. 255*41480Smckusick * This check is necessary since loop can reconfigure. 256*41480Smckusick */ 257*41480Smckusick if (device > hilp->hl_maxdev) 258*41480Smckusick return(ENODEV); 259*41480Smckusick #endif 260*41480Smckusick 261*41480Smckusick dptr = &hilp->hl_device[device]; 262*41480Smckusick if ((dptr->hd_flags & HIL_READIN) == 0) 263*41480Smckusick return(ENODEV); 264*41480Smckusick 265*41480Smckusick (void) splhil(); 266*41480Smckusick while (dptr->hd_queue.c_cc == 0) { 267*41480Smckusick if (dptr->hd_flags & HIL_NOBLOCK) { 268*41480Smckusick spl0(); 269*41480Smckusick return(EWOULDBLOCK); 270*41480Smckusick } 271*41480Smckusick dptr->hd_flags |= HIL_ASLEEP; 272*41480Smckusick sleep((caddr_t)dptr, TTIPRI); 273*41480Smckusick } 274*41480Smckusick (void) spl0(); 275*41480Smckusick 276*41480Smckusick error = 0; 277*41480Smckusick while (uio->uio_resid > 0 && error == 0) { 278*41480Smckusick cc = hilq_to_b(&dptr->hd_queue, buf, 279*41480Smckusick MIN(uio->uio_resid, HILBUFSIZE)); 280*41480Smckusick if (cc <= 0) 281*41480Smckusick break; 282*41480Smckusick error = uiomove(buf, cc, uio); 283*41480Smckusick } 284*41480Smckusick return(error); 285*41480Smckusick } 286*41480Smckusick 287*41480Smckusick hilioctl(dev, cmd, data, flag) 288*41480Smckusick dev_t dev; 289*41480Smckusick caddr_t data; 290*41480Smckusick { 291*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 292*41480Smckusick char device = HILUNIT(dev); 293*41480Smckusick struct hilloopdev *dptr; 294*41480Smckusick register int i; 295*41480Smckusick u_char hold; 296*41480Smckusick int error; 297*41480Smckusick 298*41480Smckusick #ifdef DEBUG 299*41480Smckusick if (hildebug & HDB_FOLLOW) 300*41480Smckusick printf("hilioctl(%d): dev %x cmd %x\n", 301*41480Smckusick u.u_procp->p_pid, device, cmd); 302*41480Smckusick #endif 303*41480Smckusick 304*41480Smckusick dptr = &hilp->hl_device[device]; 305*41480Smckusick if ((dptr->hd_flags & HIL_ALIVE) == 0) 306*41480Smckusick return (ENODEV); 307*41480Smckusick 308*41480Smckusick /* 309*41480Smckusick * Don't allow hardware ioctls on virtual devices. 310*41480Smckusick * Note that though these are the BSD names, they have the same 311*41480Smckusick * values as the HP-UX equivalents so we catch them as well. 312*41480Smckusick */ 313*41480Smckusick if (dptr->hd_flags & HIL_PSEUDO) { 314*41480Smckusick switch (cmd) { 315*41480Smckusick case HILIOCSC: 316*41480Smckusick case HILIOCID: 317*41480Smckusick case HILIOCRN: 318*41480Smckusick case HILIOCRS: 319*41480Smckusick case HILIOCED: 320*41480Smckusick return(ENODEV); 321*41480Smckusick 322*41480Smckusick /* 323*41480Smckusick * XXX: should also return ENODEV but HP-UX compat 324*41480Smckusick * breaks if we do. They work ok right now because 325*41480Smckusick * we only recognize one keyboard on the loop. This 326*41480Smckusick * will have to change if we remove that restriction. 327*41480Smckusick */ 328*41480Smckusick case HILIOCAROFF: 329*41480Smckusick case HILIOCAR1: 330*41480Smckusick case HILIOCAR2: 331*41480Smckusick break; 332*41480Smckusick 333*41480Smckusick default: 334*41480Smckusick break; 335*41480Smckusick } 336*41480Smckusick } 337*41480Smckusick 338*41480Smckusick #ifdef HPUXCOMPAT 339*41480Smckusick if (u.u_procp->p_flag & SHPUX) 340*41480Smckusick return(hpuxhilioctl(dev, cmd, data, flag)); 341*41480Smckusick #endif 342*41480Smckusick 343*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 344*41480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); 345*41480Smckusick hilp->hl_cmddev = device; 346*41480Smckusick error = 0; 347*41480Smckusick switch (cmd) { 348*41480Smckusick 349*41480Smckusick case HILIOCSBP: 350*41480Smckusick /* Send four data bytes to the tone gererator. */ 351*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); 352*41480Smckusick /* Send the trigger beeper command to the 8042. */ 353*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 354*41480Smckusick break; 355*41480Smckusick 356*41480Smckusick case HILIOCRRT: 357*41480Smckusick /* Transfer the real time to the 8042 data buffer */ 358*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 359*41480Smckusick /* Read each byte of the real time */ 360*41480Smckusick for (i = 0; i < 5; i++) { 361*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 362*41480Smckusick 0, &hold); 363*41480Smckusick data[4-i] = hold; 364*41480Smckusick } 365*41480Smckusick break; 366*41480Smckusick 367*41480Smckusick case HILIOCRT: 368*41480Smckusick for (i = 0; i < 4; i++) { 369*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, 370*41480Smckusick NULL, 0, &hold); 371*41480Smckusick data[i] = hold; 372*41480Smckusick } 373*41480Smckusick break; 374*41480Smckusick 375*41480Smckusick case HILIOCID: 376*41480Smckusick case HILIOCSC: 377*41480Smckusick case HILIOCRN: 378*41480Smckusick case HILIOCRS: 379*41480Smckusick case HILIOCED: 380*41480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF)); 381*41480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); 382*41480Smckusick break; 383*41480Smckusick 384*41480Smckusick case HILIOCAROFF: 385*41480Smckusick case HILIOCAR1: 386*41480Smckusick case HILIOCAR2: 387*41480Smckusick if (hilp->hl_kbddev) { 388*41480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 389*41480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); 390*41480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); 391*41480Smckusick if (cmd == HILIOCAR1) 392*41480Smckusick hilp->hl_kbdflags |= KBD_AR1; 393*41480Smckusick else if (cmd == HILIOCAR2) 394*41480Smckusick hilp->hl_kbdflags |= KBD_AR2; 395*41480Smckusick } 396*41480Smckusick break; 397*41480Smckusick 398*41480Smckusick case HILIOCBEEP: 399*41480Smckusick hilbeep(hilp, (struct _hilbell *)data); 400*41480Smckusick break; 401*41480Smckusick 402*41480Smckusick case FIONBIO: 403*41480Smckusick dptr = &hilp->hl_device[device]; 404*41480Smckusick if (*(int *)data) 405*41480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 406*41480Smckusick else 407*41480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK; 408*41480Smckusick break; 409*41480Smckusick 410*41480Smckusick /* 411*41480Smckusick * FIOASYNC must be present for FIONBIO above to work! 412*41480Smckusick * (See fcntl in kern_descrip.c). 413*41480Smckusick */ 414*41480Smckusick case FIOASYNC: 415*41480Smckusick break; 416*41480Smckusick 417*41480Smckusick case HILIOCALLOCQ: 418*41480Smckusick error = hilqalloc((struct hilqinfo *)data); 419*41480Smckusick break; 420*41480Smckusick 421*41480Smckusick case HILIOCFREEQ: 422*41480Smckusick error = hilqfree(((struct hilqinfo *)data)->qid); 423*41480Smckusick break; 424*41480Smckusick 425*41480Smckusick case HILIOCMAPQ: 426*41480Smckusick error = hilqmap(*(int *)data, device); 427*41480Smckusick break; 428*41480Smckusick 429*41480Smckusick case HILIOCUNMAPQ: 430*41480Smckusick error = hilqunmap(*(int *)data, device); 431*41480Smckusick break; 432*41480Smckusick 433*41480Smckusick case HILIOCHPUX: 434*41480Smckusick dptr = &hilp->hl_device[device]; 435*41480Smckusick dptr->hd_flags |= HIL_READIN; 436*41480Smckusick dptr->hd_flags &= ~HIL_QUEUEIN; 437*41480Smckusick break; 438*41480Smckusick 439*41480Smckusick case HILIOCRESET: 440*41480Smckusick hilreset(hilp); 441*41480Smckusick break; 442*41480Smckusick 443*41480Smckusick #ifdef DEBUG 444*41480Smckusick case HILIOCTEST: 445*41480Smckusick hildebug = *(int *) data; 446*41480Smckusick break; 447*41480Smckusick #endif 448*41480Smckusick 449*41480Smckusick default: 450*41480Smckusick error = EINVAL; 451*41480Smckusick break; 452*41480Smckusick 453*41480Smckusick } 454*41480Smckusick hilp->hl_cmddev = 0; 455*41480Smckusick return(error); 456*41480Smckusick } 457*41480Smckusick 458*41480Smckusick #ifdef HPUXCOMPAT 459*41480Smckusick /* ARGSUSED */ 460*41480Smckusick hpuxhilioctl(dev, cmd, data, flag) 461*41480Smckusick dev_t dev; 462*41480Smckusick caddr_t data; 463*41480Smckusick { 464*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 465*41480Smckusick char device = HILUNIT(dev); 466*41480Smckusick struct hilloopdev *dptr; 467*41480Smckusick register int i; 468*41480Smckusick u_char hold; 469*41480Smckusick 470*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 471*41480Smckusick bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE); 472*41480Smckusick hilp->hl_cmddev = device; 473*41480Smckusick switch (cmd) { 474*41480Smckusick 475*41480Smckusick case HILSC: 476*41480Smckusick case HILID: 477*41480Smckusick case HILRN: 478*41480Smckusick case HILRS: 479*41480Smckusick case HILED: 480*41480Smckusick case HILP1: 481*41480Smckusick case HILP2: 482*41480Smckusick case HILP3: 483*41480Smckusick case HILP4: 484*41480Smckusick case HILP5: 485*41480Smckusick case HILP6: 486*41480Smckusick case HILP7: 487*41480Smckusick case HILP: 488*41480Smckusick case HILA1: 489*41480Smckusick case HILA2: 490*41480Smckusick case HILA3: 491*41480Smckusick case HILA4: 492*41480Smckusick case HILA5: 493*41480Smckusick case HILA6: 494*41480Smckusick case HILA7: 495*41480Smckusick case HILA: 496*41480Smckusick send_hildev_cmd(hilp, device, (cmd & 0xFF)); 497*41480Smckusick bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); 498*41480Smckusick break; 499*41480Smckusick 500*41480Smckusick case HILDKR: 501*41480Smckusick case HILER1: 502*41480Smckusick case HILER2: 503*41480Smckusick if (hilp->hl_kbddev) { 504*41480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 505*41480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); 506*41480Smckusick hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); 507*41480Smckusick if (cmd == HILIOCAR1) 508*41480Smckusick hilp->hl_kbdflags |= KBD_AR1; 509*41480Smckusick else if (cmd == HILIOCAR2) 510*41480Smckusick hilp->hl_kbdflags |= KBD_AR2; 511*41480Smckusick } 512*41480Smckusick break; 513*41480Smckusick 514*41480Smckusick case EFTSBP: 515*41480Smckusick /* Send four data bytes to the tone gererator. */ 516*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); 517*41480Smckusick /* Send the trigger beeper command to the 8042. */ 518*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 519*41480Smckusick break; 520*41480Smckusick 521*41480Smckusick case EFTRRT: 522*41480Smckusick /* Transfer the real time to the 8042 data buffer */ 523*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); 524*41480Smckusick /* Read each byte of the real time */ 525*41480Smckusick for (i = 0; i < 5; i++) { 526*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 527*41480Smckusick 0, &hold); 528*41480Smckusick data[4-i] = hold; 529*41480Smckusick } 530*41480Smckusick break; 531*41480Smckusick 532*41480Smckusick case EFTRT: 533*41480Smckusick for (i = 0; i < 4; i++) { 534*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, 535*41480Smckusick NULL, 0, &hold); 536*41480Smckusick data[i] = hold; 537*41480Smckusick } 538*41480Smckusick break; 539*41480Smckusick 540*41480Smckusick case EFTRLC: 541*41480Smckusick case EFTRCC: 542*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold); 543*41480Smckusick *data = hold; 544*41480Smckusick break; 545*41480Smckusick 546*41480Smckusick case EFTSRPG: 547*41480Smckusick case EFTSRD: 548*41480Smckusick case EFTSRR: 549*41480Smckusick send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL); 550*41480Smckusick break; 551*41480Smckusick 552*41480Smckusick case EFTSBI: 553*41480Smckusick hilbeep(hilp, (struct _hilbell *)data); 554*41480Smckusick break; 555*41480Smckusick 556*41480Smckusick case FIONBIO: 557*41480Smckusick dptr = &hilp->hl_device[device]; 558*41480Smckusick if (*(int *)data) 559*41480Smckusick dptr->hd_flags |= HIL_NOBLOCK; 560*41480Smckusick else 561*41480Smckusick dptr->hd_flags &= ~HIL_NOBLOCK; 562*41480Smckusick break; 563*41480Smckusick 564*41480Smckusick case FIOASYNC: 565*41480Smckusick break; 566*41480Smckusick 567*41480Smckusick default: 568*41480Smckusick hilp->hl_cmddev = 0; 569*41480Smckusick return(EINVAL); 570*41480Smckusick } 571*41480Smckusick hilp->hl_cmddev = 0; 572*41480Smckusick return(0); 573*41480Smckusick } 574*41480Smckusick #endif 575*41480Smckusick 576*41480Smckusick /* 577*41480Smckusick * XXX: the mmap inteface for HIL devices should be rethought. 578*41480Smckusick * We used it only briefly in conjuntion with shared queues 579*41480Smckusick * (instead of HILIOCMAPQ ioctl). Perhaps mmap()ing a device 580*41480Smckusick * should give a single queue per process. 581*41480Smckusick */ 582*41480Smckusick /* ARGSUSED */ 583*41480Smckusick hilmap(dev, off, prot) 584*41480Smckusick dev_t dev; 585*41480Smckusick register int off; 586*41480Smckusick { 587*41480Smckusick #ifdef MMAP 588*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 589*41480Smckusick register struct hiliqueue *qp; 590*41480Smckusick register int qnum; 591*41480Smckusick 592*41480Smckusick /* 593*41480Smckusick * Only allow mmap() on loop device 594*41480Smckusick */ 595*41480Smckusick if (HILUNIT(dev) != 0 || off >= NHILQ*sizeof(HILQ)) 596*41480Smckusick return(-1); 597*41480Smckusick /* 598*41480Smckusick * Determine which queue we want based on the offset. 599*41480Smckusick * Queue must belong to calling process. 600*41480Smckusick */ 601*41480Smckusick qp = &hilp->hl_queue[off / sizeof(HILQ)]; 602*41480Smckusick if (qp->hq_procp != u.u_procp) 603*41480Smckusick return(-1); 604*41480Smckusick 605*41480Smckusick off %= sizeof(HILQ); 606*41480Smckusick return(kvtop((u_int)qp->hq_eventqueue + off) >> PGSHIFT); 607*41480Smckusick #endif 608*41480Smckusick } 609*41480Smckusick 610*41480Smckusick /*ARGSUSED*/ 611*41480Smckusick hilselect(dev, rw) 612*41480Smckusick dev_t dev; 613*41480Smckusick { 614*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 615*41480Smckusick register struct hilloopdev *dptr; 616*41480Smckusick register struct hiliqueue *qp; 617*41480Smckusick register int mask; 618*41480Smckusick int s, device; 619*41480Smckusick 620*41480Smckusick if (rw == FWRITE) 621*41480Smckusick return (1); 622*41480Smckusick device = HILUNIT(dev); 623*41480Smckusick 624*41480Smckusick /* 625*41480Smckusick * Read interface. 626*41480Smckusick * Return 1 if there is something in the queue, 0 ow. 627*41480Smckusick */ 628*41480Smckusick dptr = &hilp->hl_device[device]; 629*41480Smckusick if (dptr->hd_flags & HIL_READIN) { 630*41480Smckusick s = splhil(); 631*41480Smckusick if (dptr->hd_queue.c_cc) { 632*41480Smckusick splx(s); 633*41480Smckusick return (1); 634*41480Smckusick } 635*41480Smckusick if (dptr->hd_selr && 636*41480Smckusick dptr->hd_selr->p_wchan == (caddr_t)&selwait) 637*41480Smckusick dptr->hd_flags |= HIL_SELCOLL; 638*41480Smckusick else 639*41480Smckusick dptr->hd_selr = u.u_procp; 640*41480Smckusick splx(s); 641*41480Smckusick return (0); 642*41480Smckusick } 643*41480Smckusick 644*41480Smckusick /* 645*41480Smckusick * Make sure device is alive and real (or the loop device). 646*41480Smckusick * Note that we do not do this for the read interface. 647*41480Smckusick * This is primarily to be consistant with HP-UX. 648*41480Smckusick */ 649*41480Smckusick if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE) 650*41480Smckusick return (1); 651*41480Smckusick 652*41480Smckusick /* 653*41480Smckusick * Select on loop device is special. 654*41480Smckusick * Check to see if there are any data for any loop device 655*41480Smckusick * provided it is associated with a queue belonging to this user. 656*41480Smckusick */ 657*41480Smckusick if (device == 0) 658*41480Smckusick mask = -1; 659*41480Smckusick else 660*41480Smckusick mask = hildevmask(device); 661*41480Smckusick /* 662*41480Smckusick * Must check everybody with interrupts blocked to prevent races. 663*41480Smckusick */ 664*41480Smckusick s = splhil(); 665*41480Smckusick for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++) 666*41480Smckusick if (qp->hq_procp == u.u_procp && (mask & qp->hq_devmask) && 667*41480Smckusick qp->hq_eventqueue->hil_evqueue.head != 668*41480Smckusick qp->hq_eventqueue->hil_evqueue.tail) { 669*41480Smckusick splx(s); 670*41480Smckusick return (1); 671*41480Smckusick } 672*41480Smckusick 673*41480Smckusick if (dptr->hd_selr && dptr->hd_selr->p_wchan == (caddr_t)&selwait) 674*41480Smckusick dptr->hd_flags |= HIL_SELCOLL; 675*41480Smckusick else 676*41480Smckusick dptr->hd_selr = u.u_procp; 677*41480Smckusick splx(s); 678*41480Smckusick return (0); 679*41480Smckusick } 680*41480Smckusick 681*41480Smckusick hilint() 682*41480Smckusick { 683*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 684*41480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 685*41480Smckusick u_char c, stat; 686*41480Smckusick 687*41480Smckusick stat = hildevice->hil_stat; 688*41480Smckusick c = hildevice->hil_data; /* clears interrupt */ 689*41480Smckusick hil_process_int(stat, c); 690*41480Smckusick } 691*41480Smckusick 692*41480Smckusick #include "ite.h" 693*41480Smckusick 694*41480Smckusick hil_process_int(stat, c) 695*41480Smckusick register u_char stat, c; 696*41480Smckusick { 697*41480Smckusick register struct hilloop *hilp; 698*41480Smckusick 699*41480Smckusick #ifdef DEBUG 700*41480Smckusick if (hildebug & HDB_EVENTS) 701*41480Smckusick printf("hilint: %x %x\n", stat, c); 702*41480Smckusick #endif 703*41480Smckusick 704*41480Smckusick /* the shift enables the compiler to generate a jump table */ 705*41480Smckusick switch ((stat>>HIL_SSHIFT) & HIL_SMASK) { 706*41480Smckusick 707*41480Smckusick #if NITE > 0 708*41480Smckusick case HIL_KEY: 709*41480Smckusick case HIL_SHIFT: 710*41480Smckusick case HIL_CTRL: 711*41480Smckusick case HIL_CTRLSHIFT: 712*41480Smckusick itefilter(stat, c); 713*41480Smckusick return; 714*41480Smckusick #endif 715*41480Smckusick 716*41480Smckusick case HIL_STATUS: /* The status info. */ 717*41480Smckusick hilp = &hil0; /* XXX */ 718*41480Smckusick if (c & HIL_ERROR) { 719*41480Smckusick hilp->hl_cmddone = TRUE; 720*41480Smckusick if (c == HIL_RECONFIG) 721*41480Smckusick hilconfig(hilp); 722*41480Smckusick break; 723*41480Smckusick } 724*41480Smckusick if (c & HIL_COMMAND) { 725*41480Smckusick if (c & HIL_POLLDATA) /* End of data */ 726*41480Smckusick hilevent(hilp); 727*41480Smckusick else /* End of command */ 728*41480Smckusick hilp->hl_cmdending = TRUE; 729*41480Smckusick hilp->hl_actdev = 0; 730*41480Smckusick } else { 731*41480Smckusick if (c & HIL_POLLDATA) { /* Start of polled data */ 732*41480Smckusick if (hilp->hl_actdev != 0) 733*41480Smckusick hilevent(hilp); 734*41480Smckusick hilp->hl_actdev = (c & HIL_DEVMASK); 735*41480Smckusick hilp->hl_pollbp = hilp->hl_pollbuf; 736*41480Smckusick } else { /* Start of command */ 737*41480Smckusick if (hilp->hl_cmddev == (c & HIL_DEVMASK)) { 738*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 739*41480Smckusick hilp->hl_actdev = 0; 740*41480Smckusick } 741*41480Smckusick } 742*41480Smckusick } 743*41480Smckusick return; 744*41480Smckusick 745*41480Smckusick case HIL_DATA: 746*41480Smckusick hilp = &hil0; /* XXX */ 747*41480Smckusick if (hilp->hl_actdev != 0) /* Collecting poll data */ 748*41480Smckusick *hilp->hl_pollbp++ = c; 749*41480Smckusick else if (hilp->hl_cmddev != 0) /* Collecting cmd data */ 750*41480Smckusick if (hilp->hl_cmdending) { 751*41480Smckusick hilp->hl_cmddone = TRUE; 752*41480Smckusick hilp->hl_cmdending = FALSE; 753*41480Smckusick } else 754*41480Smckusick *hilp->hl_cmdbp++ = c; 755*41480Smckusick return; 756*41480Smckusick 757*41480Smckusick case 0: /* force full jump table */ 758*41480Smckusick default: 759*41480Smckusick return; 760*41480Smckusick } 761*41480Smckusick } 762*41480Smckusick 763*41480Smckusick #if defined(DEBUG) && !defined(PANICBUTTON) 764*41480Smckusick #define PANICBUTTON 765*41480Smckusick #endif 766*41480Smckusick 767*41480Smckusick /* 768*41480Smckusick * Optimized macro to compute: 769*41480Smckusick * eq->head == (eq->tail + 1) % eq->size 770*41480Smckusick * i.e. has tail caught up with head. We do this because 32 bit long 771*41480Smckusick * remaidering is expensive (a function call with our compiler). 772*41480Smckusick */ 773*41480Smckusick #define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1) 774*41480Smckusick #define HQVALID(eq) \ 775*41480Smckusick ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE) 776*41480Smckusick 777*41480Smckusick hilevent(hilp) 778*41480Smckusick struct hilloop *hilp; 779*41480Smckusick { 780*41480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev]; 781*41480Smckusick register int len, mask, qnum; 782*41480Smckusick register u_char *cp, *pp; 783*41480Smckusick register HILQ *hq; 784*41480Smckusick struct timeval ourtime; 785*41480Smckusick hil_packet *proto; 786*41480Smckusick int s, len0; 787*41480Smckusick long tenths; 788*41480Smckusick 789*41480Smckusick #ifdef PANICBUTTON 790*41480Smckusick static int first; 791*41480Smckusick extern int panicbutton; 792*41480Smckusick 793*41480Smckusick cp = hilp->hl_pollbuf; 794*41480Smckusick if (panicbutton && (*cp & HIL_KBDDATA)) { 795*41480Smckusick if (*++cp == 0x4E) 796*41480Smckusick first = 1; 797*41480Smckusick else if (first && *cp == 0x46 && !panicstr) 798*41480Smckusick panic("are we having fun yet?"); 799*41480Smckusick else 800*41480Smckusick first = 0; 801*41480Smckusick } 802*41480Smckusick #endif 803*41480Smckusick #ifdef DEBUG 804*41480Smckusick if (hildebug & HDB_EVENTS) { 805*41480Smckusick printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev); 806*41480Smckusick printhilpollbuf(hilp); 807*41480Smckusick printf("\n"); 808*41480Smckusick } 809*41480Smckusick #endif 810*41480Smckusick 811*41480Smckusick /* 812*41480Smckusick * Note that HIL_READIN effectively "shuts off" any queues 813*41480Smckusick * that may have been in use at the time of an HILIOCHPUX call. 814*41480Smckusick */ 815*41480Smckusick if (dptr->hd_flags & HIL_READIN) { 816*41480Smckusick hpuxhilevent(hilp, dptr); 817*41480Smckusick return; 818*41480Smckusick } 819*41480Smckusick 820*41480Smckusick /* 821*41480Smckusick * If this device isn't on any queue or there are no data 822*41480Smckusick * in the packet (can this happen?) do nothing. 823*41480Smckusick */ 824*41480Smckusick if (dptr->hd_qmask == 0 || 825*41480Smckusick (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0) 826*41480Smckusick return; 827*41480Smckusick 828*41480Smckusick /* 829*41480Smckusick * Everybody gets the same time stamp 830*41480Smckusick */ 831*41480Smckusick s = splclock(); 832*41480Smckusick ourtime = time; 833*41480Smckusick splx(s); 834*41480Smckusick tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 835*41480Smckusick 836*41480Smckusick proto = NULL; 837*41480Smckusick mask = dptr->hd_qmask; 838*41480Smckusick for (qnum = 0; mask; qnum++) { 839*41480Smckusick if ((mask & hilqmask(qnum)) == 0) 840*41480Smckusick continue; 841*41480Smckusick mask &= ~hilqmask(qnum); 842*41480Smckusick hq = hilp->hl_queue[qnum].hq_eventqueue; 843*41480Smckusick 844*41480Smckusick /* 845*41480Smckusick * Ensure that queue fields that we rely on are valid 846*41480Smckusick * and that there is space in the queue. If either 847*41480Smckusick * test fails, we just skip this queue. 848*41480Smckusick */ 849*41480Smckusick if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue)) 850*41480Smckusick continue; 851*41480Smckusick 852*41480Smckusick /* 853*41480Smckusick * Copy data to queue. 854*41480Smckusick * If this is the first queue we construct the packet 855*41480Smckusick * with length, timestamp and poll buffer data. 856*41480Smckusick * For second and sucessive packets we just duplicate 857*41480Smckusick * the first packet. 858*41480Smckusick */ 859*41480Smckusick pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail]; 860*41480Smckusick if (proto == NULL) { 861*41480Smckusick proto = (hil_packet *)pp; 862*41480Smckusick cp = hilp->hl_pollbuf; 863*41480Smckusick len = len0; 864*41480Smckusick *pp++ = len + 6; 865*41480Smckusick *pp++ = hilp->hl_actdev; 866*41480Smckusick *(long *)pp = tenths; 867*41480Smckusick pp += sizeof(long); 868*41480Smckusick do *pp++ = *cp++; while (--len); 869*41480Smckusick } else 870*41480Smckusick *(hil_packet *)pp = *proto; 871*41480Smckusick 872*41480Smckusick if (++hq->hil_evqueue.tail == hq->hil_evqueue.size) 873*41480Smckusick hq->hil_evqueue.tail = 0; 874*41480Smckusick } 875*41480Smckusick 876*41480Smckusick /* 877*41480Smckusick * Wake up anyone selecting on this device or the loop itself 878*41480Smckusick */ 879*41480Smckusick if (dptr->hd_selr) { 880*41480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 881*41480Smckusick dptr->hd_selr = NULL; 882*41480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 883*41480Smckusick } 884*41480Smckusick dptr = &hilp->hl_device[HILLOOPDEV]; 885*41480Smckusick if (dptr->hd_selr) { 886*41480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 887*41480Smckusick dptr->hd_selr = NULL; 888*41480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 889*41480Smckusick } 890*41480Smckusick } 891*41480Smckusick 892*41480Smckusick #undef HQFULL 893*41480Smckusick 894*41480Smckusick hpuxhilevent(hilp, dptr) 895*41480Smckusick register struct hilloop *hilp; 896*41480Smckusick register struct hilloopdev *dptr; 897*41480Smckusick { 898*41480Smckusick register int len; 899*41480Smckusick struct timeval ourtime; 900*41480Smckusick long tstamp; 901*41480Smckusick int s; 902*41480Smckusick 903*41480Smckusick /* 904*41480Smckusick * Everybody gets the same time stamp 905*41480Smckusick */ 906*41480Smckusick s = splclock(); 907*41480Smckusick ourtime = time; 908*41480Smckusick splx(s); 909*41480Smckusick tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); 910*41480Smckusick 911*41480Smckusick /* 912*41480Smckusick * Each packet that goes into the buffer must be preceded by the 913*41480Smckusick * number of bytes in the packet, and the timestamp of the packet. 914*41480Smckusick * This adds 5 bytes to the packet size. Make sure there is enough 915*41480Smckusick * room in the buffer for it, and if not, toss the packet. 916*41480Smckusick */ 917*41480Smckusick len = hilp->hl_pollbp - hilp->hl_pollbuf; 918*41480Smckusick if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) { 919*41480Smckusick putc(len+5, &dptr->hd_queue); 920*41480Smckusick (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue); 921*41480Smckusick (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue); 922*41480Smckusick } 923*41480Smckusick 924*41480Smckusick /* 925*41480Smckusick * Wake up any one blocked on a read or select 926*41480Smckusick */ 927*41480Smckusick if (dptr->hd_flags & HIL_ASLEEP) { 928*41480Smckusick dptr->hd_flags &= ~HIL_ASLEEP; 929*41480Smckusick wakeup((caddr_t)dptr); 930*41480Smckusick } 931*41480Smckusick if (dptr->hd_selr) { 932*41480Smckusick selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL); 933*41480Smckusick dptr->hd_selr = NULL; 934*41480Smckusick dptr->hd_flags &= ~HIL_SELCOLL; 935*41480Smckusick } 936*41480Smckusick } 937*41480Smckusick 938*41480Smckusick /* 939*41480Smckusick * Shared queue manipulation routines 940*41480Smckusick */ 941*41480Smckusick 942*41480Smckusick hilqalloc(qip) 943*41480Smckusick struct hilqinfo *qip; 944*41480Smckusick { 945*41480Smckusick #ifdef MAPMEM 946*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 947*41480Smckusick register HILQ *hq; 948*41480Smckusick register int qnum; 949*41480Smckusick struct mapmem *mp; 950*41480Smckusick int hilqmapin(); 951*41480Smckusick 952*41480Smckusick #ifdef DEBUG 953*41480Smckusick if (hildebug & HDB_FOLLOW) 954*41480Smckusick printf("hilqalloc(%d): addr %x\n", 955*41480Smckusick u.u_procp->p_pid, qip->addr); 956*41480Smckusick #endif 957*41480Smckusick /* 958*41480Smckusick * Find a free queue 959*41480Smckusick */ 960*41480Smckusick for (qnum = 0; qnum < NHILQ; qnum++) 961*41480Smckusick if (hilp->hl_queue[qnum].hq_procp == NULL) 962*41480Smckusick break; 963*41480Smckusick if (qnum == NHILQ) 964*41480Smckusick return(EMFILE); 965*41480Smckusick 966*41480Smckusick /* 967*41480Smckusick * Allocate and clear memory for the queue 968*41480Smckusick */ 969*41480Smckusick if (hilp->hl_queue[qnum].hq_eventqueue) 970*41480Smckusick panic("hilqalloc"); 971*41480Smckusick hq = (HILQ *) cialloc(sizeof(HILQ)); 972*41480Smckusick if (hq == NULL) 973*41480Smckusick return(ENOMEM); 974*41480Smckusick bzero((caddr_t)hq, sizeof(HILQ)); 975*41480Smckusick hilp->hl_queue[qnum].hq_eventqueue = hq; 976*41480Smckusick hq->hil_evqueue.size = HEVQSIZE; 977*41480Smckusick 978*41480Smckusick /* 979*41480Smckusick * Map queue into user address space as instructed 980*41480Smckusick */ 981*41480Smckusick mp = mmalloc(qnum, &qip->addr, sizeof(HILQ), MM_RW|MM_CI, &hilqops); 982*41480Smckusick if (mp == MMNIL) { 983*41480Smckusick cifree((caddr_t)hq, sizeof(HILQ)); 984*41480Smckusick hilp->hl_queue[qnum].hq_eventqueue = NULL; 985*41480Smckusick return(u.u_error); 986*41480Smckusick } 987*41480Smckusick qip->qid = qnum; 988*41480Smckusick if (!mmmapin(mp, hilqmapin)) { 989*41480Smckusick mmfree(mp); 990*41480Smckusick cifree((caddr_t)hq, sizeof(HILQ)); 991*41480Smckusick hilp->hl_queue[qnum].hq_eventqueue = NULL; 992*41480Smckusick return(u.u_error); 993*41480Smckusick } 994*41480Smckusick hilp->hl_queue[qnum].hq_procp = u.u_procp; 995*41480Smckusick hilp->hl_queue[qnum].hq_devmask = 0; 996*41480Smckusick return(0); 997*41480Smckusick #else 998*41480Smckusick return(EINVAL); 999*41480Smckusick #endif 1000*41480Smckusick } 1001*41480Smckusick 1002*41480Smckusick hilqfree(qnum) 1003*41480Smckusick register int qnum; 1004*41480Smckusick { 1005*41480Smckusick #ifdef MAPMEM 1006*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 1007*41480Smckusick register struct mapmem *mp; 1008*41480Smckusick 1009*41480Smckusick #ifdef DEBUG 1010*41480Smckusick if (hildebug & HDB_FOLLOW) 1011*41480Smckusick printf("hilqfree(%d): qnum %d\n", 1012*41480Smckusick u.u_procp->p_pid, qnum); 1013*41480Smckusick #endif 1014*41480Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != u.u_procp) 1015*41480Smckusick return(EINVAL); 1016*41480Smckusick for (mp = u.u_mmap; mp; mp = mp->mm_next) 1017*41480Smckusick if (qnum == mp->mm_id && mp->mm_ops == &hilqops) { 1018*41480Smckusick hilqexit(mp); 1019*41480Smckusick return(0); 1020*41480Smckusick } 1021*41480Smckusick panic("hilqfree"); 1022*41480Smckusick /* NOTREACHED */ 1023*41480Smckusick #else 1024*41480Smckusick return(EINVAL); 1025*41480Smckusick #endif 1026*41480Smckusick } 1027*41480Smckusick 1028*41480Smckusick hilqmap(qnum, device) 1029*41480Smckusick register int qnum, device; 1030*41480Smckusick { 1031*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 1032*41480Smckusick register struct hilloopdev *dptr = &hilp->hl_device[device]; 1033*41480Smckusick int s; 1034*41480Smckusick 1035*41480Smckusick #ifdef DEBUG 1036*41480Smckusick if (hildebug & HDB_FOLLOW) 1037*41480Smckusick printf("hilqmap(%d): qnum %d device %x\n", 1038*41480Smckusick u.u_procp->p_pid, qnum, device); 1039*41480Smckusick #endif 1040*41480Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != u.u_procp) 1041*41480Smckusick return(EINVAL); 1042*41480Smckusick if ((dptr->hd_flags & HIL_QUEUEIN) == 0) 1043*41480Smckusick return(EINVAL); 1044*41480Smckusick if (dptr->hd_qmask && u.u_uid && u.u_uid != dptr->hd_uid) 1045*41480Smckusick return(EPERM); 1046*41480Smckusick 1047*41480Smckusick hilp->hl_queue[qnum].hq_devmask |= hildevmask(device); 1048*41480Smckusick if (dptr->hd_qmask == 0) 1049*41480Smckusick dptr->hd_uid = u.u_uid; 1050*41480Smckusick s = splhil(); 1051*41480Smckusick dptr->hd_qmask |= hilqmask(qnum); 1052*41480Smckusick splx(s); 1053*41480Smckusick #ifdef DEBUG 1054*41480Smckusick if (hildebug & HDB_MASK) 1055*41480Smckusick printf("hilqmap(%d): devmask %x qmask %x\n", 1056*41480Smckusick u.u_procp->p_pid, hilp->hl_queue[qnum].hq_devmask, 1057*41480Smckusick dptr->hd_qmask); 1058*41480Smckusick #endif 1059*41480Smckusick return(0); 1060*41480Smckusick } 1061*41480Smckusick 1062*41480Smckusick hilqunmap(qnum, device) 1063*41480Smckusick register int qnum, device; 1064*41480Smckusick { 1065*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 1066*41480Smckusick int s; 1067*41480Smckusick 1068*41480Smckusick #ifdef DEBUG 1069*41480Smckusick if (hildebug & HDB_FOLLOW) 1070*41480Smckusick printf("hilqunmap(%d): qnum %d device %x\n", 1071*41480Smckusick u.u_procp->p_pid, qnum, device); 1072*41480Smckusick #endif 1073*41480Smckusick 1074*41480Smckusick if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != u.u_procp) 1075*41480Smckusick return(EINVAL); 1076*41480Smckusick 1077*41480Smckusick hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device); 1078*41480Smckusick s = splhil(); 1079*41480Smckusick hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum); 1080*41480Smckusick splx(s); 1081*41480Smckusick #ifdef DEBUG 1082*41480Smckusick if (hildebug & HDB_MASK) 1083*41480Smckusick printf("hilqunmap(%d): devmask %x qmask %x\n", 1084*41480Smckusick u.u_procp->p_pid, hilp->hl_queue[qnum].hq_devmask, 1085*41480Smckusick hilp->hl_device[device].hd_qmask); 1086*41480Smckusick #endif 1087*41480Smckusick return(0); 1088*41480Smckusick } 1089*41480Smckusick 1090*41480Smckusick #ifdef MAPMEM 1091*41480Smckusick hilqmapin(mp, off) 1092*41480Smckusick struct mapmem *mp; 1093*41480Smckusick { 1094*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 1095*41480Smckusick register HILQ *hq = hilp->hl_queue[mp->mm_id].hq_eventqueue; 1096*41480Smckusick 1097*41480Smckusick if (hq == NULL || off >= sizeof(HILQ)) 1098*41480Smckusick return(-1); 1099*41480Smckusick return(kvtop((u_int)hq + off) >> PGSHIFT); 1100*41480Smckusick } 1101*41480Smckusick 1102*41480Smckusick /* 1103*41480Smckusick * Fork hook. 1104*41480Smckusick * Unmap queue from child's address space 1105*41480Smckusick */ 1106*41480Smckusick hilqfork(mp, ischild) 1107*41480Smckusick struct mapmem *mp; 1108*41480Smckusick { 1109*41480Smckusick #ifdef DEBUG 1110*41480Smckusick if (hildebug & HDB_MMAP) 1111*41480Smckusick printf("hilqfork(%d): %s qnum %d\n", u.u_procp->p_pid, 1112*41480Smckusick ischild ? "child" : "parent", mp->mm_id); 1113*41480Smckusick #endif 1114*41480Smckusick if (ischild) { 1115*41480Smckusick mmmapout(mp); 1116*41480Smckusick mmfree(mp); 1117*41480Smckusick } 1118*41480Smckusick } 1119*41480Smckusick 1120*41480Smckusick /* 1121*41480Smckusick * Vfork hook. 1122*41480Smckusick * Associate queue with child when VM resources are passed. 1123*41480Smckusick */ 1124*41480Smckusick hilqvfork(mp, fup, tup) 1125*41480Smckusick struct mapmem *mp; 1126*41480Smckusick struct user *fup, *tup; 1127*41480Smckusick { 1128*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 1129*41480Smckusick register struct hiliqueue *qp = &hilp->hl_queue[mp->mm_id]; 1130*41480Smckusick 1131*41480Smckusick #ifdef DEBUG 1132*41480Smckusick if (hildebug & HDB_MMAP) 1133*41480Smckusick printf("hilqvfork(%d): from %x to %x qnum %d, qprocp %x\n", 1134*41480Smckusick u.u_procp->p_pid, fup->u_procp, tup->u_procp, 1135*41480Smckusick mp->mm_id, qp->hq_procp); 1136*41480Smckusick #endif 1137*41480Smckusick if (qp->hq_procp == fup->u_procp) 1138*41480Smckusick qp->hq_procp = tup->u_procp; 1139*41480Smckusick } 1140*41480Smckusick 1141*41480Smckusick /* 1142*41480Smckusick * Exit hook. 1143*41480Smckusick * Unmap all devices and free all queues. 1144*41480Smckusick */ 1145*41480Smckusick hilqexit(mp) 1146*41480Smckusick struct mapmem *mp; 1147*41480Smckusick { 1148*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 1149*41480Smckusick register int mask, i; 1150*41480Smckusick int s; 1151*41480Smckusick 1152*41480Smckusick #ifdef DEBUG 1153*41480Smckusick if (hildebug & HDB_MMAP) 1154*41480Smckusick printf("hilqexit(%d): qnum %d\n", u.u_procp->p_pid, mp->mm_id); 1155*41480Smckusick #endif 1156*41480Smckusick /* 1157*41480Smckusick * Atomically take all devices off the queue 1158*41480Smckusick */ 1159*41480Smckusick mask = ~hilqmask(mp->mm_id); 1160*41480Smckusick s = splhil(); 1161*41480Smckusick for (i = 0; i < NHILD; i++) 1162*41480Smckusick hilp->hl_device[i].hd_qmask &= mask; 1163*41480Smckusick splx(s); 1164*41480Smckusick /* 1165*41480Smckusick * Now unmap from user address space and free queue 1166*41480Smckusick */ 1167*41480Smckusick i = mp->mm_id; 1168*41480Smckusick cifree((caddr_t)hilp->hl_queue[i].hq_eventqueue, sizeof(HILQ)); 1169*41480Smckusick hilp->hl_queue[i].hq_eventqueue = NULL; 1170*41480Smckusick hilp->hl_queue[i].hq_procp = NULL; 1171*41480Smckusick mmfree(mp); 1172*41480Smckusick } 1173*41480Smckusick #endif 1174*41480Smckusick 1175*41480Smckusick #include "clist.h" 1176*41480Smckusick 1177*41480Smckusick /* 1178*41480Smckusick * This is just a copy of the virgin q_to_b routine with minor 1179*41480Smckusick * optimizations for HIL use. It is used for two reasons: 1180*41480Smckusick * 1. If we have PAGE mode defined, the normal q_to_b processes 1181*41480Smckusick * chars one at a time and breaks on newlines. 1182*41480Smckusick * 2. We don't have to raise the priority to spltty() for most 1183*41480Smckusick * of the clist manipulations. 1184*41480Smckusick */ 1185*41480Smckusick hilq_to_b(q, cp, cc) 1186*41480Smckusick register struct clist *q; 1187*41480Smckusick register char *cp; 1188*41480Smckusick { 1189*41480Smckusick register struct cblock *bp; 1190*41480Smckusick register int nc; 1191*41480Smckusick char *acp; 1192*41480Smckusick int s; 1193*41480Smckusick extern char cwaiting; 1194*41480Smckusick 1195*41480Smckusick if (cc <= 0) 1196*41480Smckusick return (0); 1197*41480Smckusick s = splhil(); 1198*41480Smckusick if (q->c_cc <= 0) { 1199*41480Smckusick q->c_cc = 0; 1200*41480Smckusick q->c_cf = q->c_cl = NULL; 1201*41480Smckusick splx(s); 1202*41480Smckusick return (0); 1203*41480Smckusick } 1204*41480Smckusick acp = cp; 1205*41480Smckusick 1206*41480Smckusick while (cc) { 1207*41480Smckusick nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 1208*41480Smckusick nc = MIN(nc, cc); 1209*41480Smckusick nc = MIN(nc, q->c_cc); 1210*41480Smckusick (void) bcopy(q->c_cf, cp, (unsigned)nc); 1211*41480Smckusick q->c_cf += nc; 1212*41480Smckusick q->c_cc -= nc; 1213*41480Smckusick cc -= nc; 1214*41480Smckusick cp += nc; 1215*41480Smckusick if (q->c_cc <= 0) { 1216*41480Smckusick bp = (struct cblock *)(q->c_cf - 1); 1217*41480Smckusick bp = (struct cblock *)((int)bp & ~CROUND); 1218*41480Smckusick q->c_cf = q->c_cl = NULL; 1219*41480Smckusick spltty(); 1220*41480Smckusick bp->c_next = cfreelist; 1221*41480Smckusick cfreelist = bp; 1222*41480Smckusick cfreecount += CBSIZE; 1223*41480Smckusick if (cwaiting) { 1224*41480Smckusick wakeup(&cwaiting); 1225*41480Smckusick cwaiting = 0; 1226*41480Smckusick } 1227*41480Smckusick break; 1228*41480Smckusick } 1229*41480Smckusick if (((int)q->c_cf & CROUND) == 0) { 1230*41480Smckusick bp = (struct cblock *)(q->c_cf); 1231*41480Smckusick bp--; 1232*41480Smckusick q->c_cf = bp->c_next->c_info; 1233*41480Smckusick spltty(); 1234*41480Smckusick bp->c_next = cfreelist; 1235*41480Smckusick cfreelist = bp; 1236*41480Smckusick cfreecount += CBSIZE; 1237*41480Smckusick if (cwaiting) { 1238*41480Smckusick wakeup(&cwaiting); 1239*41480Smckusick cwaiting = 0; 1240*41480Smckusick } 1241*41480Smckusick splhil(); 1242*41480Smckusick } 1243*41480Smckusick } 1244*41480Smckusick splx(s); 1245*41480Smckusick return (cp-acp); 1246*41480Smckusick } 1247*41480Smckusick 1248*41480Smckusick /* 1249*41480Smckusick * Cooked keyboard functions for ite driver. 1250*41480Smckusick * There is only one "cooked" ITE keyboard (the first keyboard found) 1251*41480Smckusick * per loop. There may be other keyboards, but they will always be "raw". 1252*41480Smckusick */ 1253*41480Smckusick 1254*41480Smckusick kbdbell() 1255*41480Smckusick { 1256*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 1257*41480Smckusick 1258*41480Smckusick hilbeep(hilp, &default_bell); 1259*41480Smckusick } 1260*41480Smckusick 1261*41480Smckusick kbdenable() 1262*41480Smckusick { 1263*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 1264*41480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 1265*41480Smckusick char db; 1266*41480Smckusick 1267*41480Smckusick /* Set the autorepeat rate register */ 1268*41480Smckusick db = ar_format(KBD_ARR); 1269*41480Smckusick send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL); 1270*41480Smckusick 1271*41480Smckusick /* Set the autorepeat delay register */ 1272*41480Smckusick db = ar_format(KBD_ARD); 1273*41480Smckusick send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL); 1274*41480Smckusick 1275*41480Smckusick /* Enable interrupts */ 1276*41480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); 1277*41480Smckusick } 1278*41480Smckusick 1279*41480Smckusick kbddisable() 1280*41480Smckusick { 1281*41480Smckusick } 1282*41480Smckusick 1283*41480Smckusick /* 1284*41480Smckusick * XXX: read keyboard directly and return code. 1285*41480Smckusick * Used by console getchar routine. Could really screw up anybody 1286*41480Smckusick * reading from the keyboard in the normal, interrupt driven fashion. 1287*41480Smckusick */ 1288*41480Smckusick kbdgetc(statp) 1289*41480Smckusick int *statp; 1290*41480Smckusick { 1291*41480Smckusick struct hilloop *hilp = &hil0; /* XXX */ 1292*41480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 1293*41480Smckusick register int c, stat; 1294*41480Smckusick int s; 1295*41480Smckusick 1296*41480Smckusick s = splhil(); 1297*41480Smckusick while (((stat = hildevice->hil_stat) & HIL_DATA_RDY) == 0) 1298*41480Smckusick ; 1299*41480Smckusick c = hildevice->hil_data; 1300*41480Smckusick splx(s); 1301*41480Smckusick *statp = stat; 1302*41480Smckusick return(c); 1303*41480Smckusick } 1304*41480Smckusick 1305*41480Smckusick /* 1306*41480Smckusick * Recoginize and clear keyboard generated NMIs. 1307*41480Smckusick * Returns 1 if it was ours, 0 otherwise. Note that we cannot use 1308*41480Smckusick * send_hil_cmd() to issue the clear NMI command as that would actually 1309*41480Smckusick * lower the priority to splimp() and it doesn't wait for the completion 1310*41480Smckusick * of the command. Either of these conditions could result in the 1311*41480Smckusick * interrupt reoccuring. Note that we issue the CNMT command twice. 1312*41480Smckusick * This seems to be needed, once is not always enough!?! 1313*41480Smckusick */ 1314*41480Smckusick kbdnmi() 1315*41480Smckusick { 1316*41480Smckusick register struct hilloop *hilp = &hil0; /* XXX */ 1317*41480Smckusick 1318*41480Smckusick if ((*KBDNMISTAT & KBDNMI) == 0) 1319*41480Smckusick return(0); 1320*41480Smckusick HILWAIT(hilp->hl_addr); 1321*41480Smckusick hilp->hl_addr->hil_cmd = HIL_CNMT; 1322*41480Smckusick HILWAIT(hilp->hl_addr); 1323*41480Smckusick hilp->hl_addr->hil_cmd = HIL_CNMT; 1324*41480Smckusick HILWAIT(hilp->hl_addr); 1325*41480Smckusick return(1); 1326*41480Smckusick } 1327*41480Smckusick 1328*41480Smckusick #define HILSECURITY 0x33 1329*41480Smckusick #define HILIDENTIFY 0x03 1330*41480Smckusick #define HILSCBIT 0x04 1331*41480Smckusick 1332*41480Smckusick /* 1333*41480Smckusick * Called at boot time to print out info about interesting devices 1334*41480Smckusick */ 1335*41480Smckusick hilinfo(hilp) 1336*41480Smckusick register struct hilloop *hilp; 1337*41480Smckusick { 1338*41480Smckusick register int id, len; 1339*41480Smckusick register struct kbdmap *km; 1340*41480Smckusick 1341*41480Smckusick /* 1342*41480Smckusick * Keyboard info. 1343*41480Smckusick */ 1344*41480Smckusick if (hilp->hl_kbddev) { 1345*41480Smckusick printf("hil%d: ", hilp->hl_kbddev); 1346*41480Smckusick for (km = kbd_map; km->kbd_code; km++) 1347*41480Smckusick if (km->kbd_code == hilp->hl_kbdlang) { 1348*41480Smckusick printf("%s ", km->kbd_desc); 1349*41480Smckusick break; 1350*41480Smckusick } 1351*41480Smckusick printf("keyboard\n"); 1352*41480Smckusick } 1353*41480Smckusick /* 1354*41480Smckusick * ID module. 1355*41480Smckusick * Attempt to locate the first ID module and print out its 1356*41480Smckusick * security code. Is this a good idea?? 1357*41480Smckusick */ 1358*41480Smckusick id = hiliddev(hilp); 1359*41480Smckusick if (id) { 1360*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1361*41480Smckusick hilp->hl_cmddev = id; 1362*41480Smckusick send_hildev_cmd(hilp, id, HILSECURITY); 1363*41480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 1364*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1365*41480Smckusick hilp->hl_cmddev = 0; 1366*41480Smckusick printf("hil%d: security code", id); 1367*41480Smckusick for (id = 0; id < len; id++) 1368*41480Smckusick printf(" %x", hilp->hl_cmdbuf[id]); 1369*41480Smckusick while (id++ < 16) 1370*41480Smckusick printf(" 0"); 1371*41480Smckusick printf("\n"); 1372*41480Smckusick } 1373*41480Smckusick } 1374*41480Smckusick 1375*41480Smckusick #define HILAR1 0x3E 1376*41480Smckusick #define HILAR2 0x3F 1377*41480Smckusick 1378*41480Smckusick /* 1379*41480Smckusick * Called after the loop has reconfigured. Here we need to: 1380*41480Smckusick * - determine how many devices are on the loop 1381*41480Smckusick * (some may have been added or removed) 1382*41480Smckusick * - locate the ITE keyboard (if any) and ensure 1383*41480Smckusick * that it is in the proper state (raw or cooked) 1384*41480Smckusick * and is set to use the proper language mapping table 1385*41480Smckusick * - ensure all other keyboards are raw 1386*41480Smckusick * Note that our device state is now potentially invalid as 1387*41480Smckusick * devices may no longer be where they were. What we should 1388*41480Smckusick * do here is either track where the devices went and move 1389*41480Smckusick * state around accordingly or, more simply, just mark all 1390*41480Smckusick * devices as HIL_DERROR and don't allow any further use until 1391*41480Smckusick * they are closed. This is a little too brutal for my tastes, 1392*41480Smckusick * we prefer to just assume people won't move things around. 1393*41480Smckusick */ 1394*41480Smckusick hilconfig(hilp) 1395*41480Smckusick register struct hilloop *hilp; 1396*41480Smckusick { 1397*41480Smckusick u_char db; 1398*41480Smckusick int s; 1399*41480Smckusick 1400*41480Smckusick s = splhil(); 1401*41480Smckusick #ifdef DEBUG 1402*41480Smckusick if (hildebug & HDB_CONFIG) { 1403*41480Smckusick printf("hilconfig: reconfigured: "); 1404*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); 1405*41480Smckusick printf("LPSTAT %x, ", db); 1406*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db); 1407*41480Smckusick printf("LPCTRL %x, ", db); 1408*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); 1409*41480Smckusick printf("KBDSADR %x\n", db); 1410*41480Smckusick hilreport(hilp); 1411*41480Smckusick } 1412*41480Smckusick #endif 1413*41480Smckusick /* 1414*41480Smckusick * Determine how many devices are on the loop. 1415*41480Smckusick * Mark those as alive and real, all others as dead. 1416*41480Smckusick */ 1417*41480Smckusick db = 0; 1418*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db); 1419*41480Smckusick hilp->hl_maxdev = db & LPS_DEVMASK; 1420*41480Smckusick for (db = 1; db < NHILD; db++) { 1421*41480Smckusick if (db <= hilp->hl_maxdev) 1422*41480Smckusick hilp->hl_device[db].hd_flags |= HIL_ALIVE; 1423*41480Smckusick else 1424*41480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_ALIVE; 1425*41480Smckusick hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO; 1426*41480Smckusick } 1427*41480Smckusick #ifdef DEBUG 1428*41480Smckusick if (hildebug & (HDB_CONFIG|HDB_KEYBOARD)) 1429*41480Smckusick printf("hilconfig: max device %d\n", hilp->hl_maxdev); 1430*41480Smckusick #endif 1431*41480Smckusick if (hilp->hl_maxdev == 0) { 1432*41480Smckusick hilp->hl_kbddev = 0; 1433*41480Smckusick splx(s); 1434*41480Smckusick return; 1435*41480Smckusick } 1436*41480Smckusick /* 1437*41480Smckusick * Find out where the keyboards are and record the ITE keyboard 1438*41480Smckusick * (first one found). If no keyboards found, we are all done. 1439*41480Smckusick */ 1440*41480Smckusick db = 0; 1441*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db); 1442*41480Smckusick #ifdef DEBUG 1443*41480Smckusick if (hildebug & HDB_KEYBOARD) 1444*41480Smckusick printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n", 1445*41480Smckusick db, hilp->hl_kbddev, ffs((int)db)); 1446*41480Smckusick #endif 1447*41480Smckusick hilp->hl_kbddev = ffs((int)db); 1448*41480Smckusick if (hilp->hl_kbddev == 0) { 1449*41480Smckusick splx(s); 1450*41480Smckusick return; 1451*41480Smckusick } 1452*41480Smckusick /* 1453*41480Smckusick * Determine if the keyboard should be cooked or raw and configure it. 1454*41480Smckusick */ 1455*41480Smckusick db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1); 1456*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL); 1457*41480Smckusick /* 1458*41480Smckusick * Re-enable autorepeat in raw mode, cooked mode AR is not affected. 1459*41480Smckusick */ 1460*41480Smckusick if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) { 1461*41480Smckusick db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2; 1462*41480Smckusick hilp->hl_cmddev = hilp->hl_kbddev; 1463*41480Smckusick send_hildev_cmd(hilp, hilp->hl_kbddev, db); 1464*41480Smckusick hilp->hl_cmddev = 0; 1465*41480Smckusick } 1466*41480Smckusick /* 1467*41480Smckusick * Determine the keyboard language configuration, but don't 1468*41480Smckusick * override a user-specified setting. 1469*41480Smckusick */ 1470*41480Smckusick db = 0; 1471*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db); 1472*41480Smckusick #ifdef DEBUG 1473*41480Smckusick if (hildebug & HDB_KEYBOARD) 1474*41480Smckusick printf("hilconfig: language: old %x new %x\n", 1475*41480Smckusick hilp->hl_kbdlang, db); 1476*41480Smckusick #endif 1477*41480Smckusick if (hilp->hl_kbdlang != KBD_SPECIAL) { 1478*41480Smckusick struct kbdmap *km; 1479*41480Smckusick 1480*41480Smckusick for (km = kbd_map; km->kbd_code; km++) 1481*41480Smckusick if (km->kbd_code == db) { 1482*41480Smckusick hilp->hl_kbdlang = db; 1483*41480Smckusick /* XXX */ 1484*41480Smckusick kbd_keymap = km->kbd_keymap; 1485*41480Smckusick kbd_shiftmap = km->kbd_shiftmap; 1486*41480Smckusick kbd_ctrlmap = km->kbd_ctrlmap; 1487*41480Smckusick kbd_ctrlshiftmap = km->kbd_ctrlshiftmap; 1488*41480Smckusick kbd_stringmap = km->kbd_stringmap; 1489*41480Smckusick } 1490*41480Smckusick } 1491*41480Smckusick splx(s); 1492*41480Smckusick } 1493*41480Smckusick 1494*41480Smckusick hilreset(hilp) 1495*41480Smckusick struct hilloop *hilp; 1496*41480Smckusick { 1497*41480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 1498*41480Smckusick u_char db; 1499*41480Smckusick 1500*41480Smckusick /* 1501*41480Smckusick * Initialize the loop: reconfigure, don't report errors, 1502*41480Smckusick * cook keyboards, and enable autopolling. 1503*41480Smckusick */ 1504*41480Smckusick db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL; 1505*41480Smckusick send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL); 1506*41480Smckusick /* 1507*41480Smckusick * Delay one second for reconfiguration and then read the the 1508*41480Smckusick * data register to clear the interrupt (if the loop reconfigured). 1509*41480Smckusick */ 1510*41480Smckusick DELAY(1000000); 1511*41480Smckusick if (hildevice->hil_stat & HIL_DATA_RDY) 1512*41480Smckusick db = hildevice->hil_data; 1513*41480Smckusick /* 1514*41480Smckusick * The HIL loop may have reconfigured. If so we proceed on, 1515*41480Smckusick * if not we loop until a successful reconfiguration is reported 1516*41480Smckusick * back to us. The HIL loop will continue to attempt forever. 1517*41480Smckusick * Probably not very smart. 1518*41480Smckusick */ 1519*41480Smckusick do { 1520*41480Smckusick send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db); 1521*41480Smckusick } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0); 1522*41480Smckusick /* 1523*41480Smckusick * At this point, the loop should have reconfigured. 1524*41480Smckusick * The reconfiguration interrupt has already called hilconfig() 1525*41480Smckusick * so the keyboard has been determined. All that is left is 1526*41480Smckusick * 1527*41480Smckusick */ 1528*41480Smckusick #if 0 1529*41480Smckusick hilconfig(hilp); 1530*41480Smckusick #endif 1531*41480Smckusick send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL); 1532*41480Smckusick } 1533*41480Smckusick 1534*41480Smckusick hilbeep(hilp, bp) 1535*41480Smckusick struct hilloop *hilp; 1536*41480Smckusick register struct _hilbell *bp; 1537*41480Smckusick { 1538*41480Smckusick u_char buf[2]; 1539*41480Smckusick 1540*41480Smckusick buf[0] = ~((bp->duration - 10) / 10); 1541*41480Smckusick buf[1] = bp->frequency; 1542*41480Smckusick send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL); 1543*41480Smckusick } 1544*41480Smckusick 1545*41480Smckusick /* 1546*41480Smckusick * Locate and return the address of the first ID module, 0 if none present. 1547*41480Smckusick */ 1548*41480Smckusick hiliddev(hilp) 1549*41480Smckusick register struct hilloop *hilp; 1550*41480Smckusick { 1551*41480Smckusick register int i, len; 1552*41480Smckusick 1553*41480Smckusick #ifdef DEBUG 1554*41480Smckusick if (hildebug & HDB_IDMODULE) 1555*41480Smckusick printf("hiliddev(%x): looking for idmodule...", hilp); 1556*41480Smckusick #endif 1557*41480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) { 1558*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1559*41480Smckusick hilp->hl_cmddev = i; 1560*41480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY); 1561*41480Smckusick /* 1562*41480Smckusick * XXX: the final condition checks to ensure that the 1563*41480Smckusick * device ID byte is in the range of the ID module (0x30-0x3F) 1564*41480Smckusick */ 1565*41480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 1566*41480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) && 1567*41480Smckusick (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) { 1568*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1569*41480Smckusick hilp->hl_cmddev = i; 1570*41480Smckusick send_hildev_cmd(hilp, i, HILSECURITY); 1571*41480Smckusick break; 1572*41480Smckusick } 1573*41480Smckusick } 1574*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1575*41480Smckusick hilp->hl_cmddev = 0; 1576*41480Smckusick #ifdef DEBUG 1577*41480Smckusick if (hildebug & HDB_IDMODULE) 1578*41480Smckusick if (i <= hilp->hl_maxdev) 1579*41480Smckusick printf("found at %d\n", i); 1580*41480Smckusick else 1581*41480Smckusick printf("not found\n"); 1582*41480Smckusick #endif 1583*41480Smckusick return(i <= hilp->hl_maxdev ? i : 0); 1584*41480Smckusick } 1585*41480Smckusick 1586*41480Smckusick /* 1587*41480Smckusick * Low level routines which actually talk to the 8042 chip. 1588*41480Smckusick */ 1589*41480Smckusick 1590*41480Smckusick /* 1591*41480Smckusick * Send a command to the 8042 with zero or more bytes of data. 1592*41480Smckusick * If rdata is non-null, wait for and return a byte of data. 1593*41480Smckusick * We run at splimp() to make the transaction as atomic as 1594*41480Smckusick * possible without blocking the clock (is this necessary?) 1595*41480Smckusick */ 1596*41480Smckusick send_hil_cmd(hildevice, cmd, data, dlen, rdata) 1597*41480Smckusick register struct hil_dev *hildevice; 1598*41480Smckusick u_char cmd, *data, dlen; 1599*41480Smckusick u_char *rdata; 1600*41480Smckusick { 1601*41480Smckusick u_char status; 1602*41480Smckusick int s = splimp(); 1603*41480Smckusick 1604*41480Smckusick HILWAIT(hildevice); 1605*41480Smckusick hildevice->hil_cmd = cmd; 1606*41480Smckusick while (dlen--) { 1607*41480Smckusick HILWAIT(hildevice); 1608*41480Smckusick hildevice->hil_data = *data++; 1609*41480Smckusick } 1610*41480Smckusick if (rdata) { 1611*41480Smckusick do { 1612*41480Smckusick HILDATAWAIT(hildevice); 1613*41480Smckusick status = hildevice->hil_stat; 1614*41480Smckusick *rdata = hildevice->hil_data; 1615*41480Smckusick } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K); 1616*41480Smckusick } 1617*41480Smckusick splx(s); 1618*41480Smckusick } 1619*41480Smckusick 1620*41480Smckusick /* 1621*41480Smckusick * Send a command to a device on the loop. 1622*41480Smckusick * Since only one command can be active on the loop at any time, 1623*41480Smckusick * we must ensure that we are not interrupted during this process. 1624*41480Smckusick * Hence we mask interrupts to prevent potential access from most 1625*41480Smckusick * interrupt routines and turn off auto-polling to disable the 1626*41480Smckusick * internally generated poll commands. 1627*41480Smckusick * 1628*41480Smckusick * splhigh is extremely conservative but insures atomic operation, 1629*41480Smckusick * splimp (clock only interrupts) seems to be good enough in practice. 1630*41480Smckusick */ 1631*41480Smckusick send_hildev_cmd(hilp, device, cmd) 1632*41480Smckusick register struct hilloop *hilp; 1633*41480Smckusick char device, cmd; 1634*41480Smckusick { 1635*41480Smckusick register struct hil_dev *hildevice = hilp->hl_addr; 1636*41480Smckusick u_char status, c; 1637*41480Smckusick int s = splimp(); 1638*41480Smckusick 1639*41480Smckusick polloff(hildevice); 1640*41480Smckusick 1641*41480Smckusick /* 1642*41480Smckusick * Transfer the command and device info to the chip 1643*41480Smckusick */ 1644*41480Smckusick HILWAIT(hildevice); 1645*41480Smckusick hildevice->hil_cmd = HIL_STARTCMD; 1646*41480Smckusick HILWAIT(hildevice); 1647*41480Smckusick hildevice->hil_data = 8 + device; 1648*41480Smckusick HILWAIT(hildevice); 1649*41480Smckusick hildevice->hil_data = cmd; 1650*41480Smckusick HILWAIT(hildevice); 1651*41480Smckusick hildevice->hil_data = HIL_TIMEOUT; 1652*41480Smckusick /* 1653*41480Smckusick * Trigger the command and wait for completion 1654*41480Smckusick */ 1655*41480Smckusick HILWAIT(hildevice); 1656*41480Smckusick hildevice->hil_cmd = HIL_TRIGGER; 1657*41480Smckusick hilp->hl_cmddone = FALSE; 1658*41480Smckusick do { 1659*41480Smckusick HILDATAWAIT(hildevice); 1660*41480Smckusick status = hildevice->hil_stat; 1661*41480Smckusick c = hildevice->hil_data; 1662*41480Smckusick hil_process_int(status, c); 1663*41480Smckusick } while (!hilp->hl_cmddone); 1664*41480Smckusick 1665*41480Smckusick pollon(hildevice); 1666*41480Smckusick splx(s); 1667*41480Smckusick } 1668*41480Smckusick 1669*41480Smckusick /* 1670*41480Smckusick * Turn auto-polling off and on. 1671*41480Smckusick * Also disables and enable auto-repeat. Why? 1672*41480Smckusick */ 1673*41480Smckusick polloff(hildevice) 1674*41480Smckusick register struct hil_dev *hildevice; 1675*41480Smckusick { 1676*41480Smckusick register char db; 1677*41480Smckusick 1678*41480Smckusick /* 1679*41480Smckusick * Turn off auto repeat 1680*41480Smckusick */ 1681*41480Smckusick HILWAIT(hildevice); 1682*41480Smckusick hildevice->hil_cmd = HIL_SETARR; 1683*41480Smckusick HILWAIT(hildevice); 1684*41480Smckusick hildevice->hil_data = 0; 1685*41480Smckusick /* 1686*41480Smckusick * Turn off auto-polling 1687*41480Smckusick */ 1688*41480Smckusick HILWAIT(hildevice); 1689*41480Smckusick hildevice->hil_cmd = HIL_READLPCTRL; 1690*41480Smckusick HILDATAWAIT(hildevice); 1691*41480Smckusick db = hildevice->hil_data; 1692*41480Smckusick db &= ~LPC_AUTOPOLL; 1693*41480Smckusick HILWAIT(hildevice); 1694*41480Smckusick hildevice->hil_cmd = HIL_WRITELPCTRL; 1695*41480Smckusick HILWAIT(hildevice); 1696*41480Smckusick hildevice->hil_data = db; 1697*41480Smckusick /* 1698*41480Smckusick * Must wait til polling is really stopped 1699*41480Smckusick */ 1700*41480Smckusick do { 1701*41480Smckusick HILWAIT(hildevice); 1702*41480Smckusick hildevice->hil_cmd = HIL_READBUSY; 1703*41480Smckusick HILDATAWAIT(hildevice); 1704*41480Smckusick db = hildevice->hil_data; 1705*41480Smckusick } while (db & BSY_LOOPBUSY); 1706*41480Smckusick } 1707*41480Smckusick 1708*41480Smckusick pollon(hildevice) 1709*41480Smckusick register struct hil_dev *hildevice; 1710*41480Smckusick { 1711*41480Smckusick register char db; 1712*41480Smckusick 1713*41480Smckusick /* 1714*41480Smckusick * Turn on auto polling 1715*41480Smckusick */ 1716*41480Smckusick HILWAIT(hildevice); 1717*41480Smckusick hildevice->hil_cmd = HIL_READLPCTRL; 1718*41480Smckusick HILDATAWAIT(hildevice); 1719*41480Smckusick db = hildevice->hil_data; 1720*41480Smckusick db |= LPC_AUTOPOLL; 1721*41480Smckusick HILWAIT(hildevice); 1722*41480Smckusick hildevice->hil_cmd = HIL_WRITELPCTRL; 1723*41480Smckusick HILWAIT(hildevice); 1724*41480Smckusick hildevice->hil_data = db; 1725*41480Smckusick /* 1726*41480Smckusick * Turn on auto repeat 1727*41480Smckusick */ 1728*41480Smckusick HILWAIT(hildevice); 1729*41480Smckusick hildevice->hil_cmd = HIL_SETARR; 1730*41480Smckusick HILWAIT(hildevice); 1731*41480Smckusick hildevice->hil_data = ar_format(KBD_ARR); 1732*41480Smckusick } 1733*41480Smckusick 1734*41480Smckusick #ifdef DEBUG 1735*41480Smckusick printhilpollbuf(hilp) 1736*41480Smckusick register struct hilloop *hilp; 1737*41480Smckusick { 1738*41480Smckusick register u_char *cp; 1739*41480Smckusick register int i, len; 1740*41480Smckusick 1741*41480Smckusick cp = hilp->hl_pollbuf; 1742*41480Smckusick len = hilp->hl_pollbp - cp; 1743*41480Smckusick for (i = 0; i < len; i++) 1744*41480Smckusick printf("%x ", hilp->hl_pollbuf[i]); 1745*41480Smckusick printf("\n"); 1746*41480Smckusick } 1747*41480Smckusick 1748*41480Smckusick printhilcmdbuf(hilp) 1749*41480Smckusick register struct hilloop *hilp; 1750*41480Smckusick { 1751*41480Smckusick register u_char *cp; 1752*41480Smckusick register int i, len; 1753*41480Smckusick 1754*41480Smckusick cp = hilp->hl_cmdbuf; 1755*41480Smckusick len = hilp->hl_cmdbp - cp; 1756*41480Smckusick for (i = 0; i < len; i++) 1757*41480Smckusick printf("%x ", hilp->hl_cmdbuf[i]); 1758*41480Smckusick printf("\n"); 1759*41480Smckusick } 1760*41480Smckusick 1761*41480Smckusick hilreport(hilp) 1762*41480Smckusick register struct hilloop *hilp; 1763*41480Smckusick { 1764*41480Smckusick register int i, len; 1765*41480Smckusick int s = splhil(); 1766*41480Smckusick 1767*41480Smckusick for (i = 1; i <= hilp->hl_maxdev; i++) { 1768*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1769*41480Smckusick hilp->hl_cmddev = i; 1770*41480Smckusick send_hildev_cmd(hilp, i, HILIDENTIFY); 1771*41480Smckusick printf("hil%d: id: ", i); 1772*41480Smckusick printhilcmdbuf(hilp); 1773*41480Smckusick len = hilp->hl_cmdbp - hilp->hl_cmdbuf; 1774*41480Smckusick if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) { 1775*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1776*41480Smckusick hilp->hl_cmddev = i; 1777*41480Smckusick send_hildev_cmd(hilp, i, HILSECURITY); 1778*41480Smckusick printf("hil%d: sc: ", i); 1779*41480Smckusick printhilcmdbuf(hilp); 1780*41480Smckusick } 1781*41480Smckusick } 1782*41480Smckusick hilp->hl_cmdbp = hilp->hl_cmdbuf; 1783*41480Smckusick hilp->hl_cmddev = 0; 1784*41480Smckusick splx(s); 1785*41480Smckusick } 1786*41480Smckusick #endif 1787