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