예제 #1
0
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);
}
예제 #2
0
파일: pckbc.c 프로젝트: ajinkya93/OpenBSD
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);
}
예제 #3
0
파일: pckbc.c 프로젝트: ajinkya93/OpenBSD
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);
}
예제 #4
0
파일: pckbc.c 프로젝트: ajinkya93/OpenBSD
/*
 * 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);
}