int pckbcintr_hard(void *vsc) { struct pckbc_softc *sc = (struct pckbc_softc *)vsc; struct pckbc_internal *t = sc->id; u_char stat; pckbc_slot_t slot; struct pckbc_slotdata *q; int served = 0, data, next, s; for(;;) { stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0); if (!(stat & KBS_DIB)) break; served = 1; slot = (t->t_haveaux && (stat & 0x20)) ? PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; q = t->t_slotdata[slot]; if (!q) { /* XXX do something for live insertion? */ printf("pckbc: no dev for slot %d\n", slot); KBD_DELAY; (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0); continue; } KBD_DELAY; data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0); rnd_add_uint32(&q->rnd_source, (stat<<8)|data); if (q->polling) { q->poll_data = data; q->poll_stat = stat; break; /* pckbc_poll_data() will get it */ } #if 0 /* XXXBJH */ if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data)) continue; #endif s = splhigh(); next = (t->rbuf_write+1) % PCKBC_RBUF_SIZE; if (next == t->rbuf_read) { splx(s); break; } t->rbuf[t->rbuf_write].data = data; t->rbuf[t->rbuf_write].slot = slot; t->rbuf_write = next; splx(s); } return (served); }
int pckbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc) { u_char stat; pckbc_slot_t slot; struct pckbc_slotdata *q; int served = 0, data; /* reschedule timeout further into the idle times */ if (timeout_pending(&t->t_poll)) timeout_add_sec(&t->t_poll, 1); for(;;) { stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0); if (!(stat & KBS_DIB)) break; served = 1; slot = (t->t_haveaux && (stat & KBS_AUXDATA)) ? PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; q = t->t_slotdata[slot]; if (!q) { /* XXX do something for live insertion? */ #ifdef PCKBCDEBUG printf("pckbcintr: no dev for slot %d\n", slot); #endif KBD_DELAY; (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0); continue; } if (q->polling) break; /* pckbc_poll_data() will get it */ KBD_DELAY; data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0); if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data)) continue; if (sc != NULL) { if (sc->inputhandler[slot]) (*sc->inputhandler[slot])(sc->inputarg[slot], data); #ifdef PCKBCDEBUG else printf("pckbcintr: slot %d lost %d\n", slot, data); #endif } } return (served); }
int pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot) { struct pckbc_internal *t = self; struct pckbc_slotdata *q = t->t_slotdata[slot]; int c; c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, slot, t->t_haveaux); if (c != -1 && q && CMD_IN_QUEUE(q)) { /* we jumped into a running command - try to deliver the response */ if (pckbc_cmdresponse(t, slot, c)) return (-1); } return (c); }
/* * Put command into the device's command queue, return zero or errno. */ int pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, int responselen, int sync, u_char *respbuf) { struct pckbc_internal *t = self; struct pckbc_slotdata *q = t->t_slotdata[slot]; struct pckbc_devcmd *nc; int s, isactive, res = 0; if ((len > 4) || (responselen > 4)) return (EINVAL); s = spltty(); nc = TAILQ_FIRST(&q->freequeue); if (nc) { TAILQ_REMOVE(&q->freequeue, nc, next); } splx(s); if (!nc) return (ENOMEM); bzero(nc, sizeof(*nc)); memcpy(nc->cmd, cmd, len); nc->cmdlen = len; nc->responselen = responselen; nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0); s = spltty(); if (q->polling && sync) { /* * XXX We should poll until the queue is empty. * But we don't come here normally, so make * it simple and throw away everything. */ pckbc_cleanqueue(q); } isactive = CMD_IN_QUEUE(q); TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next); if (!isactive) pckbc_start(t, slot); if (q->polling) res = (sync ? nc->status : 0); else if (sync) { if ((res = tsleep(nc, 0, "kbccmd", 1*hz))) { TAILQ_REMOVE(&q->cmdqueue, nc, next); pckbc_cleanup(t); } else { TAILQ_REMOVE(&q->cmdqueue, nc, next); res = nc->status; } } else timeout_add_sec(&t->t_cleanup, 1); if (sync) { if (respbuf) memcpy(respbuf, nc->response, responselen); TAILQ_INSERT_TAIL(&q->freequeue, nc, next); } splx(s); return (res); }