📄 hil.c
字号:
case HILRN: case HILRS: case HILED: case HILP1: case HILP2: case HILP3: case HILP4: case HILP5: case HILP6: case HILP7: case HILP: case HILA1: case HILA2: case HILA3: case HILA4: case HILA5: case HILA6: case HILA7: case HILA: send_hildev_cmd(hilp, device, (cmd & 0xFF)); bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf); break; case HILDKR: case HILER1: case HILER2: if (hilp->hl_kbddev) { hilp->hl_cmddev = hilp->hl_kbddev; send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF)); hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2); if (cmd == HILIOCAR1) hilp->hl_kbdflags |= KBD_AR1; else if (cmd == HILIOCAR2) hilp->hl_kbdflags |= KBD_AR2; } break; case EFTSBP: /* Send four data bytes to the tone gererator. */ send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); /* Send the trigger beeper command to the 8042. */ send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); break; case EFTRRT: /* Transfer the real time to the 8042 data buffer */ send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL); /* Read each byte of the real time */ for (i = 0; i < 5; i++) { send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL, 0, &hold); data[4-i] = hold; } break; case EFTRT: for (i = 0; i < 4; i++) { send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i, NULL, 0, &hold); data[i] = hold; } break; case EFTRLC: case EFTRCC: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold); *data = hold; break; case EFTSRPG: case EFTSRD: case EFTSRR: send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL); break; case EFTSBI:#ifdef hp800 /* XXX big magic */ hold = 7 - (*(u_char *)data >> 5); *(int *)data = 0x84069008 | (hold << 8); send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL); send_hil_cmd(hilp->hl_addr, 0xC4, NULL, 0, NULL); break;#else hilbeep(hilp, (struct _hilbell *)data);#endif break; case FIONBIO: dptr = &hilp->hl_device[device]; if (*(int *)data) dptr->hd_flags |= HIL_NOBLOCK; else dptr->hd_flags &= ~HIL_NOBLOCK; break; case FIOASYNC: break; default: hilp->hl_cmddev = 0; return(EINVAL); } hilp->hl_cmddev = 0; return(0);}#endif/* ARGSUSED */hilmap(dev, off, prot) dev_t dev; int off, prot;{}/*ARGSUSED*/hilselect(dev, rw, p) dev_t dev; int rw; struct proc *p;{ register struct hilloop *hilp = &hilloop[HILLOOP(dev)]; register struct hilloopdev *dptr; register struct hiliqueue *qp; register int mask; int s, device; if (rw == FWRITE) return (1); device = HILUNIT(dev); /* * Read interface. * Return 1 if there is something in the queue, 0 ow. */ dptr = &hilp->hl_device[device]; if (dptr->hd_flags & HIL_READIN) { s = splhil(); if (dptr->hd_queue.c_cc) { splx(s); return (1); } selrecord(p, &dptr->hd_selr); splx(s); return (0); } /* * Make sure device is alive and real (or the loop device). * Note that we do not do this for the read interface. * This is primarily to be consistant with HP-UX. */ if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE) return (1); /* * Select on loop device is special. * Check to see if there are any data for any loop device * provided it is associated with a queue belonging to this user. */ if (device == 0) mask = -1; else mask = hildevmask(device); /* * Must check everybody with interrupts blocked to prevent races. */ s = splhil(); for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++) if (qp->hq_procp == p && (mask & qp->hq_devmask) && qp->hq_eventqueue->hil_evqueue.head != qp->hq_eventqueue->hil_evqueue.tail) { splx(s); return (1); } selrecord(p, &dptr->hd_selr); splx(s); return (0);}/*ARGSUSED*/hilint(unit) int unit;{#ifdef hp300 struct hilloop *hilp = &hilloop[0]; /* XXX how do we know on 300? */#else struct hilloop *hilp = &hilloop[unit];#endif register struct hil_dev *hildevice = hilp->hl_addr; u_char c, stat; stat = READHILSTAT(hildevice); c = READHILDATA(hildevice); /* clears interrupt */ hil_process_int(hilp, stat, c);}#include "ite.h"hil_process_int(hilp, stat, c) register struct hilloop *hilp; register u_char stat, c;{#ifdef DEBUG if (hildebug & HDB_EVENTS) printf("hilint: %x %x\n", stat, c);#endif /* the shift enables the compiler to generate a jump table */ switch ((stat>>HIL_SSHIFT) & HIL_SMASK) {#if NITE > 0 case HIL_KEY: case HIL_SHIFT: case HIL_CTRL: case HIL_CTRLSHIFT: itefilter(stat, c); return;#endif case HIL_STATUS: /* The status info. */ if (c & HIL_ERROR) { hilp->hl_cmddone = TRUE; if (c == HIL_RECONFIG) hilconfig(hilp); break; } if (c & HIL_COMMAND) { if (c & HIL_POLLDATA) /* End of data */ hilevent(hilp); else /* End of command */ hilp->hl_cmdending = TRUE; hilp->hl_actdev = 0; } else { if (c & HIL_POLLDATA) { /* Start of polled data */ if (hilp->hl_actdev != 0) hilevent(hilp); hilp->hl_actdev = (c & HIL_DEVMASK); hilp->hl_pollbp = hilp->hl_pollbuf; } else { /* Start of command */ if (hilp->hl_cmddev == (c & HIL_DEVMASK)) { hilp->hl_cmdbp = hilp->hl_cmdbuf; hilp->hl_actdev = 0; } } } return; case HIL_DATA: if (hilp->hl_actdev != 0) /* Collecting poll data */ *hilp->hl_pollbp++ = c; else if (hilp->hl_cmddev != 0) /* Collecting cmd data */ if (hilp->hl_cmdending) { hilp->hl_cmddone = TRUE; hilp->hl_cmdending = FALSE; } else *hilp->hl_cmdbp++ = c; return; case 0: /* force full jump table */ default: return; }}#if defined(DEBUG) && !defined(PANICBUTTON)#define PANICBUTTON#endif/* * Optimized macro to compute: * eq->head == (eq->tail + 1) % eq->size * i.e. has tail caught up with head. We do this because 32 bit long * remaidering is expensive (a function call with our compiler). */#define HQFULL(eq) (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1)#define HQVALID(eq) \ ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE)hilevent(hilp) struct hilloop *hilp;{ register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev]; register int len, mask, qnum; register u_char *cp, *pp; register HILQ *hq; struct timeval ourtime; hil_packet *proto; int s, len0; long tenths;#ifdef PANICBUTTON static int first; extern int panicbutton; cp = hilp->hl_pollbuf; if (panicbutton && (*cp & HIL_KBDDATA)) { if (*++cp == 0x4E) first = 1; else if (first && *cp == 0x46 && !panicstr) panic("are we having fun yet?"); else first = 0; }#endif#ifdef DEBUG if (hildebug & HDB_EVENTS) { printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev); printhilpollbuf(hilp); printf("\n"); }#endif /* * Note that HIL_READIN effectively "shuts off" any queues * that may have been in use at the time of an HILIOCHPUX call. */ if (dptr->hd_flags & HIL_READIN) { hpuxhilevent(hilp, dptr); return; } /* * If this device isn't on any queue or there are no data * in the packet (can this happen?) do nothing. */ if (dptr->hd_qmask == 0 || (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0) return; /* * Everybody gets the same time stamp */ s = splclock(); ourtime = time; splx(s); tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); proto = NULL; mask = dptr->hd_qmask; for (qnum = 0; mask; qnum++) { if ((mask & hilqmask(qnum)) == 0) continue; mask &= ~hilqmask(qnum); hq = hilp->hl_queue[qnum].hq_eventqueue; /* * Ensure that queue fields that we rely on are valid * and that there is space in the queue. If either * test fails, we just skip this queue. */ if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue)) continue; /* * Copy data to queue. * If this is the first queue we construct the packet * with length, timestamp and poll buffer data. * For second and sucessive packets we just duplicate * the first packet. */ pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail]; if (proto == NULL) { proto = (hil_packet *)pp; cp = hilp->hl_pollbuf; len = len0; *pp++ = len + 6; *pp++ = hilp->hl_actdev; *(long *)pp = tenths; pp += sizeof(long); do *pp++ = *cp++; while (--len); } else *(hil_packet *)pp = *proto; if (++hq->hil_evqueue.tail == hq->hil_evqueue.size) hq->hil_evqueue.tail = 0; } /* * Wake up anyone selecting on this device or the loop itself */ selwakeup(&dptr->hd_selr); dptr = &hilp->hl_device[HILLOOPDEV]; selwakeup(&dptr->hd_selr);}#undef HQFULLhpuxhilevent(hilp, dptr) register struct hilloop *hilp; register struct hilloopdev *dptr;{ register int len; struct timeval ourtime; long tstamp; int s; /* * Everybody gets the same time stamp */ s = splclock(); ourtime = time; splx(s); tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000); /* * Each packet that goes into the buffer must be preceded by the * number of bytes in the packet, and the timestamp of the packet. * This adds 5 bytes to the packet size. Make sure there is enough * room in the buffer for it, and if not, toss the packet. */ len = hilp->hl_pollbp - hilp->hl_pollbuf; if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) { putc(len+5, &dptr->hd_queue); (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue); (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue); } /* * Wake up any one blocked on a read or select */ if (dptr->hd_flags & HIL_ASLEEP) { dptr->hd_flags &= ~HIL_ASLEEP; wakeup((caddr_t)dptr); } selwakeup(&dptr->hd_selr);}/* * Shared queue manipulation routines */hilqalloc(hilp, qip) register struct hilloop *hilp; struct hilqinfo *qip;{ struct proc *p = curproc; /* XXX */#ifdef DEBUG if (hildebug & HDB_FOLLOW) printf("hilqalloc(%d): addr %x\n", p->p_pid, qip->addr);#endif return(EINVAL);}hilqfree(hilp, qnum) register struct hilloop *hilp; register int qnum;{ struct proc *p = curproc; /* XXX */#ifdef DEBUG if (hildebug & HDB_FOLLOW) printf("hilqfree(%d): qnum %d\n", p->p_pid, qnum);#endif return(EINVAL);}hilqmap(hilp, qnum, device) register struct hilloop *hilp; register int qnum, device;{ struct proc *p = curproc; /* XXX */ register struct hilloopdev *dptr = &hilp->hl_device[device]; int s;#ifdef DEBUG if (hildebug & HDB_FOLLOW) printf("hilqmap(%d): qnum %d device %x\n", p->p_pid, qnum, device);#endif if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) return(EINVAL); if ((dptr->hd_flags & HIL_QUEUEIN) == 0) return(EINVAL); if (dptr->hd_qmask && p->p_ucred->cr_uid && p->p_ucred->cr_uid != dptr->hd_uid) return(EPERM); hilp->hl_queue[qnum].hq_devmask |= hildevmask(device); if (dptr->hd_qmask == 0) dptr->hd_uid = p->p_ucred->cr_uid; s = splhil(); dptr->hd_qmask |= hilqmask(qnum); splx(s);#ifdef DEBUG if (hildebug & HDB_MASK) printf("hilqmap(%d): devmask %x qmask %x\n", p->p_pid, hilp->hl_queue[qnum].hq_devmask, dptr->hd_qmask);#endif return(0);}hilqunmap(hilp, qnum, device) register struct hilloop *hilp; register int qnum, device;{ struct proc *p = curproc; /* XXX */ int s;#ifdef DEBUG if (hildebug & HDB_FOLLOW) printf("hilqunmap(%d): qnum %d device %x\n", p->p_pid, qnum, device);#endif if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p) return(EINVAL); hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device); s = splhil(); hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum); splx(s);#ifdef DEBUG if (hildebug & HDB_MASK) printf("hilqunmap(%d): devmask %x qmask %x\n", p->p_pid, hilp->hl_queue[qnum].hq_devmask, hilp->hl_device[device].hd_qmask);#endif return(0);}/* * Cooked keyboard functions for ite driver. * There is only one "cooked" ITE keyboard (the first keyboard found) * per loop. There may be other keyboards, but they will always be "raw". */kbdbell(unit) int unit;{ struct hilloop *hilp = &hilloop[unit]; hilbeep(hilp, &default_bell);}kbdenable(unit) int unit;{ struct hilloop *hilp = &hilloop[unit]; register struct hil_dev *hildevice = hilp->hl_addr; char db; /* Set the autorepeat rate register */ db = ar_format(KBD_ARR); send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL); /* Set the autorepeat delay register */ db = ar_format(KBD_ARD); send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -