155104Storek /* 255104Storek * Copyright (c) 1992 The Regents of the University of California. 355104Storek * 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 1255499Sbostic * California, Lawrence Berkeley Laboratories. 1355499Sbostic * 1455104Storek * %sccs.include.redist.c% 1555104Storek * 16*56536Sbostic * @(#)event.c 7.3 (Berkeley) 10/11/92 1755104Storek * 1855104Storek * from: $Header: event.c,v 1.4 92/06/17 05:35:45 torek Exp $ (LBL) 1955104Storek */ 2055104Storek 2155104Storek /* 2255104Storek * Internal `Firm_event' interface for the keyboard and mouse drivers. 2355104Storek */ 2455104Storek 25*56536Sbostic #include <sys/param.h> 26*56536Sbostic #include <sys/fcntl.h> 27*56536Sbostic #include <sys/malloc.h> 28*56536Sbostic #include <sys/proc.h> 29*56536Sbostic #include <sys/systm.h> 30*56536Sbostic #include <sys/vnode.h> 3155104Storek 32*56536Sbostic #include <sparc/dev/vuid_event.h> 33*56536Sbostic #include <sparc/dev/event_var.h> 3455104Storek 3555104Storek /* 3655104Storek * Initialize a firm_event queue. 3755104Storek */ 3855104Storek void 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 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 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 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