xref: /csrg-svn/sys/sparc/dev/event.c (revision 55104)
1*55104Storek /*
2*55104Storek  * Copyright (c) 1992 The Regents of the University of California.
3*55104Storek  * All rights reserved.
4*55104Storek  *
5*55104Storek  * This software was developed by the Computer Systems Engineering group
6*55104Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*55104Storek  * contributed to Berkeley.
8*55104Storek  *
9*55104Storek  * %sccs.include.redist.c%
10*55104Storek  *
11*55104Storek  *	@(#)event.c	7.1 (Berkeley) 07/13/92
12*55104Storek  *
13*55104Storek  * from: $Header: event.c,v 1.4 92/06/17 05:35:45 torek Exp $ (LBL)
14*55104Storek  */
15*55104Storek 
16*55104Storek /*
17*55104Storek  * Internal `Firm_event' interface for the keyboard and mouse drivers.
18*55104Storek  */
19*55104Storek 
20*55104Storek #include "sys/param.h"
21*55104Storek #include "sys/fcntl.h"
22*55104Storek #include "sys/malloc.h"
23*55104Storek #include "sys/proc.h"
24*55104Storek #include "sys/systm.h"
25*55104Storek #include "sys/vnode.h"
26*55104Storek 
27*55104Storek #include "vuid_event.h"
28*55104Storek #include "event_var.h"
29*55104Storek 
30*55104Storek /*
31*55104Storek  * Initialize a firm_event queue.
32*55104Storek  */
33*55104Storek void
34*55104Storek ev_init(ev)
35*55104Storek 	register struct evvar *ev;
36*55104Storek {
37*55104Storek 
38*55104Storek 	ev->ev_get = ev->ev_put = 0;
39*55104Storek 	ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event),
40*55104Storek 	    M_DEVBUF, M_WAITOK);
41*55104Storek 	bzero((caddr_t)ev->ev_q, EV_QSIZE * sizeof(struct firm_event));
42*55104Storek }
43*55104Storek 
44*55104Storek /*
45*55104Storek  * Tear down a firm_event queue.
46*55104Storek  */
47*55104Storek void
48*55104Storek ev_fini(ev)
49*55104Storek 	register struct evvar *ev;
50*55104Storek {
51*55104Storek 
52*55104Storek 	free(ev->ev_q, M_DEVBUF);
53*55104Storek }
54*55104Storek 
55*55104Storek /*
56*55104Storek  * User-level interface: read, select.
57*55104Storek  * (User cannot write an event queue.)
58*55104Storek  */
59*55104Storek int
60*55104Storek ev_read(ev, uio, flags)
61*55104Storek 	register struct evvar *ev;
62*55104Storek 	struct uio *uio;
63*55104Storek 	int flags;
64*55104Storek {
65*55104Storek 	int s, n, cnt, error;
66*55104Storek 
67*55104Storek 	/*
68*55104Storek 	 * Make sure we can return at least 1.
69*55104Storek 	 */
70*55104Storek 	if (uio->uio_resid < sizeof(struct firm_event))
71*55104Storek 		return (EMSGSIZE);	/* ??? */
72*55104Storek 	s = splev();
73*55104Storek 	while (ev->ev_get == ev->ev_put) {
74*55104Storek 		if (flags & IO_NDELAY) {
75*55104Storek 			splx(s);
76*55104Storek 			return (EWOULDBLOCK);
77*55104Storek 		}
78*55104Storek 		ev->ev_wanted = 1;
79*55104Storek 		error = tsleep((caddr_t)ev, PEVENT | PCATCH, "firm_event", 0);
80*55104Storek 		if (error) {
81*55104Storek 			splx(s);
82*55104Storek 			return (error);
83*55104Storek 		}
84*55104Storek 	}
85*55104Storek 	/*
86*55104Storek 	 * Move firm_events from tail end of queue (there is at least one
87*55104Storek 	 * there).
88*55104Storek 	 */
89*55104Storek 	if (ev->ev_put < ev->ev_get)
90*55104Storek 		cnt = EV_QSIZE - ev->ev_get;	/* events in [get..QSIZE) */
91*55104Storek 	else
92*55104Storek 		cnt = ev->ev_put - ev->ev_get;	/* events in [get..put) */
93*55104Storek 	splx(s);
94*55104Storek 	n = howmany(uio->uio_resid, sizeof(struct firm_event));
95*55104Storek 	if (cnt > n)
96*55104Storek 		cnt = n;
97*55104Storek 	error = uiomove((caddr_t)&ev->ev_q[ev->ev_get],
98*55104Storek 	    cnt * sizeof(struct firm_event), uio);
99*55104Storek 	n -= cnt;
100*55104Storek 	/*
101*55104Storek 	 * If we do not wrap to 0, used up all our space, or had an error,
102*55104Storek 	 * stop.  Otherwise move from front of queue to put index, if there
103*55104Storek 	 * is anything there to move.
104*55104Storek 	 */
105*55104Storek 	if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 ||
106*55104Storek 	    n == 0 || error || (cnt = ev->ev_put) == 0)
107*55104Storek 		return (error);
108*55104Storek 	if (cnt > n)
109*55104Storek 		cnt = n;
110*55104Storek 	error = uiomove((caddr_t)&ev->ev_q[0],
111*55104Storek 	    cnt * sizeof(struct firm_event), uio);
112*55104Storek 	ev->ev_get = cnt;
113*55104Storek 	return (error);
114*55104Storek }
115*55104Storek 
116*55104Storek int
117*55104Storek ev_select(ev, rw, p)
118*55104Storek 	register struct evvar *ev;
119*55104Storek 	int rw;
120*55104Storek 	struct proc *p;
121*55104Storek {
122*55104Storek 	int s = splev();
123*55104Storek 
124*55104Storek 	switch (rw) {
125*55104Storek 
126*55104Storek 	case FREAD:
127*55104Storek 		/* succeed if there is something to read */
128*55104Storek 		if (ev->ev_get != ev->ev_put) {
129*55104Storek 			splx(s);
130*55104Storek 			return (1);
131*55104Storek 		}
132*55104Storek 		selrecord(p, &ev->ev_sel);
133*55104Storek 		break;
134*55104Storek 
135*55104Storek 	case FWRITE:
136*55104Storek 		return (1);	/* always fails => never blocks */
137*55104Storek 	}
138*55104Storek 	splx(s);
139*55104Storek 	return (0);
140*55104Storek }
141