xref: /csrg-svn/sys/sparc/dev/event.c (revision 63318)
155104Storek /*
2*63318Sbostic  * Copyright (c) 1992, 1993
3*63318Sbostic  *	The Regents of the University of California.  All rights reserved.
455104Storek  *
555104Storek  * This software was developed by the Computer Systems Engineering group
655104Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
755104Storek  * contributed to Berkeley.
855104Storek  *
955499Sbostic  * All advertising materials mentioning features or use of this software
1055499Sbostic  * must display the following acknowledgement:
1155499Sbostic  *	This product includes software developed by the University of
1259186Storek  *	California, Lawrence Berkeley Laboratory.
1355499Sbostic  *
1455104Storek  * %sccs.include.redist.c%
1555104Storek  *
16*63318Sbostic  *	@(#)event.c	8.1 (Berkeley) 06/11/93
1755104Storek  *
1859186Storek  * from: $Header: event.c,v 1.5 92/11/26 01:10:44 torek Exp $ (LBL)
1955104Storek  */
2055104Storek 
2155104Storek /*
2255104Storek  * Internal `Firm_event' interface for the keyboard and mouse drivers.
2355104Storek  */
2455104Storek 
2556536Sbostic #include <sys/param.h>
2656536Sbostic #include <sys/fcntl.h>
2756536Sbostic #include <sys/malloc.h>
2856536Sbostic #include <sys/proc.h>
2956536Sbostic #include <sys/systm.h>
3056536Sbostic #include <sys/vnode.h>
3155104Storek 
3256536Sbostic #include <sparc/dev/vuid_event.h>
3356536Sbostic #include <sparc/dev/event_var.h>
3455104Storek 
3555104Storek /*
3655104Storek  * Initialize a firm_event queue.
3755104Storek  */
3855104Storek void
ev_init(ev)3955104Storek ev_init(ev)
4055104Storek 	register struct evvar *ev;
4155104Storek {
4255104Storek 
4355104Storek 	ev->ev_get = ev->ev_put = 0;
4455104Storek 	ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event),
4555104Storek 	    M_DEVBUF, M_WAITOK);
4655104Storek 	bzero((caddr_t)ev->ev_q, EV_QSIZE * sizeof(struct firm_event));
4755104Storek }
4855104Storek 
4955104Storek /*
5055104Storek  * Tear down a firm_event queue.
5155104Storek  */
5255104Storek void
ev_fini(ev)5355104Storek ev_fini(ev)
5455104Storek 	register struct evvar *ev;
5555104Storek {
5655104Storek 
5755104Storek 	free(ev->ev_q, M_DEVBUF);
5855104Storek }
5955104Storek 
6055104Storek /*
6155104Storek  * User-level interface: read, select.
6255104Storek  * (User cannot write an event queue.)
6355104Storek  */
6455104Storek int
ev_read(ev,uio,flags)6555104Storek ev_read(ev, uio, flags)
6655104Storek 	register struct evvar *ev;
6755104Storek 	struct uio *uio;
6855104Storek 	int flags;
6955104Storek {
7055104Storek 	int s, n, cnt, error;
7155104Storek 
7255104Storek 	/*
7355104Storek 	 * Make sure we can return at least 1.
7455104Storek 	 */
7555104Storek 	if (uio->uio_resid < sizeof(struct firm_event))
7655104Storek 		return (EMSGSIZE);	/* ??? */
7755104Storek 	s = splev();
7855104Storek 	while (ev->ev_get == ev->ev_put) {
7955104Storek 		if (flags & IO_NDELAY) {
8055104Storek 			splx(s);
8155104Storek 			return (EWOULDBLOCK);
8255104Storek 		}
8355104Storek 		ev->ev_wanted = 1;
8455104Storek 		error = tsleep((caddr_t)ev, PEVENT | PCATCH, "firm_event", 0);
8555104Storek 		if (error) {
8655104Storek 			splx(s);
8755104Storek 			return (error);
8855104Storek 		}
8955104Storek 	}
9055104Storek 	/*
9155104Storek 	 * Move firm_events from tail end of queue (there is at least one
9255104Storek 	 * there).
9355104Storek 	 */
9455104Storek 	if (ev->ev_put < ev->ev_get)
9555104Storek 		cnt = EV_QSIZE - ev->ev_get;	/* events in [get..QSIZE) */
9655104Storek 	else
9755104Storek 		cnt = ev->ev_put - ev->ev_get;	/* events in [get..put) */
9855104Storek 	splx(s);
9955104Storek 	n = howmany(uio->uio_resid, sizeof(struct firm_event));
10055104Storek 	if (cnt > n)
10155104Storek 		cnt = n;
10255104Storek 	error = uiomove((caddr_t)&ev->ev_q[ev->ev_get],
10355104Storek 	    cnt * sizeof(struct firm_event), uio);
10455104Storek 	n -= cnt;
10555104Storek 	/*
10655104Storek 	 * If we do not wrap to 0, used up all our space, or had an error,
10755104Storek 	 * stop.  Otherwise move from front of queue to put index, if there
10855104Storek 	 * is anything there to move.
10955104Storek 	 */
11055104Storek 	if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 ||
11155104Storek 	    n == 0 || error || (cnt = ev->ev_put) == 0)
11255104Storek 		return (error);
11355104Storek 	if (cnt > n)
11455104Storek 		cnt = n;
11555104Storek 	error = uiomove((caddr_t)&ev->ev_q[0],
11655104Storek 	    cnt * sizeof(struct firm_event), uio);
11755104Storek 	ev->ev_get = cnt;
11855104Storek 	return (error);
11955104Storek }
12055104Storek 
12155104Storek int
ev_select(ev,rw,p)12255104Storek ev_select(ev, rw, p)
12355104Storek 	register struct evvar *ev;
12455104Storek 	int rw;
12555104Storek 	struct proc *p;
12655104Storek {
12755104Storek 	int s = splev();
12855104Storek 
12955104Storek 	switch (rw) {
13055104Storek 
13155104Storek 	case FREAD:
13255104Storek 		/* succeed if there is something to read */
13355104Storek 		if (ev->ev_get != ev->ev_put) {
13455104Storek 			splx(s);
13555104Storek 			return (1);
13655104Storek 		}
13755104Storek 		selrecord(p, &ev->ev_sel);
13855104Storek 		break;
13955104Storek 
14055104Storek 	case FWRITE:
14155104Storek 		return (1);	/* always fails => never blocks */
14255104Storek 	}
14355104Storek 	splx(s);
14455104Storek 	return (0);
14555104Storek }
146