xref: /netbsd-src/sys/dev/ir/cir.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: cir.c,v 1.9 2003/07/14 15:47:14 lukem Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Lennart Augustsson (lennart@augustsson.net).
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: cir.c,v 1.9 2003/07/14 15:47:14 lukem Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/ioctl.h>
45 #include <sys/kernel.h>
46 #include <sys/device.h>
47 #include <sys/conf.h>
48 #include <sys/poll.h>
49 #include <sys/select.h>
50 #include <sys/vnode.h>
51 
52 #include <dev/ir/ir.h>
53 #include <dev/ir/cirio.h>
54 #include <dev/ir/cirvar.h>
55 
56 dev_type_open(ciropen);
57 dev_type_close(circlose);
58 dev_type_read(cirread);
59 dev_type_write(cirwrite);
60 dev_type_ioctl(cirioctl);
61 dev_type_poll(cirpoll);
62 dev_type_kqfilter(cirkqfilter);
63 
64 const struct cdevsw cir_cdevsw = {
65 	ciropen, circlose, cirread, cirwrite, cirioctl,
66 	nostop, notty, cirpoll, nommap, cirkqfilter,
67 };
68 
69 int cir_match(struct device *parent, struct cfdata *match, void *aux);
70 void cir_attach(struct device *parent, struct device *self, void *aux);
71 int cir_activate(struct device *self, enum devact act);
72 int cir_detach(struct device *self, int flags);
73 
74 CFATTACH_DECL(cir, sizeof(struct cir_softc),
75     cir_match, cir_attach, cir_detach, cir_activate);
76 
77 extern struct cfdriver cir_cd;
78 
79 #define CIRUNIT(dev) (minor(dev))
80 
81 int
82 cir_match(struct device *parent, struct cfdata *match, void *aux)
83 {
84 	struct ir_attach_args *ia = aux;
85 
86 	return (ia->ia_type == IR_TYPE_CIR);
87 }
88 
89 void
90 cir_attach(struct device *parent, struct device *self, void *aux)
91 {
92 	struct cir_softc *sc = (struct cir_softc *)self;
93 	struct ir_attach_args *ia = aux;
94 
95 	sc->sc_methods = ia->ia_methods;
96 	sc->sc_handle = ia->ia_handle;
97 
98 #ifdef DIAGNOSTIC
99 	if (sc->sc_methods->im_read == NULL ||
100 	    sc->sc_methods->im_write == NULL ||
101 	    sc->sc_methods->im_setparams == NULL)
102 		panic("%s: missing methods", sc->sc_dev.dv_xname);
103 #endif
104 	printf("\n");
105 }
106 
107 int
108 cir_activate(struct device *self, enum devact act)
109 {
110 	/*struct cir_softc *sc = (struct cir_softc *)self;*/
111 
112 	switch (act) {
113 	case DVACT_ACTIVATE:
114 		return (EOPNOTSUPP);
115 		break;
116 
117 	case DVACT_DEACTIVATE:
118 		break;
119 	}
120 	return (0);
121 }
122 
123 int
124 cir_detach(struct device *self, int flags)
125 {
126 	/*struct cir_softc *sc = (struct cir_softc *)self;*/
127 	int maj, mn;
128 
129 	/* locate the major number */
130 	maj = cdevsw_lookup_major(&cir_cdevsw);
131 
132 	/* Nuke the vnodes for any open instances (calls close). */
133 	mn = self->dv_unit;
134 	vdevgone(maj, mn, mn, VCHR);
135 
136 	return (0);
137 }
138 
139 int
140 ciropen(dev_t dev, int flag, int mode, struct proc *p)
141 {
142 	struct cir_softc *sc;
143 	int error;
144 
145 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
146 	if (sc == NULL)
147 		return (ENXIO);
148 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
149 		return (EIO);
150 	if (sc->sc_open)
151 		return (EBUSY);
152 	if (sc->sc_methods->im_open != NULL) {
153 		error = sc->sc_methods->im_open(sc->sc_handle, flag, mode, p);
154 		if (error)
155 			return (error);
156 	}
157 	sc->sc_open = 1;
158 	return (0);
159 }
160 
161 int
162 circlose(dev_t dev, int flag, int mode, struct proc *p)
163 {
164 	struct cir_softc *sc;
165 	int error;
166 
167 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
168 	if (sc == NULL)
169 		return (ENXIO);
170 	if (sc->sc_methods->im_close != NULL)
171 		error = sc->sc_methods->im_close(sc->sc_handle, flag, mode, p);
172 	else
173 		error = 0;
174 	sc->sc_open = 0;
175 	return (error);
176 }
177 
178 int
179 cirread(dev_t dev, struct uio *uio, int flag)
180 {
181 	struct cir_softc *sc;
182 
183 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
184 	if (sc == NULL)
185 		return (ENXIO);
186 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
187 		return (EIO);
188 	return (sc->sc_methods->im_read(sc->sc_handle, uio, flag));
189 }
190 
191 int
192 cirwrite(dev_t dev, struct uio *uio, int flag)
193 {
194 	struct cir_softc *sc;
195 
196 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
197 	if (sc == NULL)
198 		return (ENXIO);
199 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
200 		return (EIO);
201 	return (sc->sc_methods->im_write(sc->sc_handle, uio, flag));
202 }
203 
204 int
205 cirioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
206 {
207 	struct cir_softc *sc;
208 	int error;
209 
210 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
211 	if (sc == NULL)
212 		return (ENXIO);
213 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
214 		return (EIO);
215 
216 	switch (cmd) {
217 	case FIONBIO:
218 		/* All handled in the upper FS layer. */
219 		error = 0;
220 		break;
221 	case CIR_GET_PARAMS:
222 		*(struct cir_params *)addr = sc->sc_params;
223 		break;
224 	case CIR_SET_PARAMS:
225 		error = sc->sc_methods->im_setparams(sc->sc_handle,
226 			    (struct cir_params *)addr);
227 		if (!error)
228 			sc->sc_params = *(struct cir_params *)addr;
229 		break;
230 	default:
231 		error = EINVAL;
232 		break;
233 	}
234 	return (error);
235 }
236 
237 int
238 cirpoll(dev_t dev, int events, struct proc *p)
239 {
240 	struct cir_softc *sc;
241 	int revents;
242 	int s;
243 
244 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
245 	if (sc == NULL)
246 		return (ENXIO);
247 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
248 		return (EIO);
249 
250 	revents = 0;
251 	s = splir();
252 #if 0
253 	if (events & (POLLIN | POLLRDNORM))
254 		if (sc->sc_rdframes > 0)
255 			revents |= events & (POLLIN | POLLRDNORM);
256 #endif
257 
258 #if 0
259 	/* How about write? */
260 	if (events & (POLLOUT | POLLWRNORM))
261 		if (???)
262 			revents |= events & (POLLOUT | POLLWRNORM);
263 #endif
264 
265 	if (revents == 0) {
266 		if (events & (POLLIN | POLLRDNORM))
267 			selrecord(p, &sc->sc_rdsel);
268 
269 #if 0
270 		if (events & (POLLOUT | POLLWRNORM))
271 			selrecord(p, &sc->sc_wrsel);
272 #endif
273 	}
274 
275 	splx(s);
276 	return (revents);
277 }
278