xref: /netbsd-src/sys/dev/ir/cir.c (revision 220b5c059a84c51ea44107ea8951a57ffaecdc8c)
1 /*	$NetBSD: cir.c,v 1.1 2001/12/02 10:44:43 augustss 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/param.h>
40 #include <sys/systm.h>
41 #include <sys/ioctl.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44 #include <sys/conf.h>
45 #include <sys/poll.h>
46 #include <sys/select.h>
47 #include <sys/vnode.h>
48 
49 #include <dev/ir/cirvar.h>
50 #include <dev/ir/ir.h>
51 
52 cdev_decl(cir);
53 
54 int cir_match(struct device *parent, struct cfdata *match, void *aux);
55 void cir_attach(struct device *parent, struct device *self, void *aux);
56 int cir_activate(struct device *self, enum devact act);
57 int cir_detach(struct device *self, int flags);
58 
59 struct cfattach cir_ca = {
60 	sizeof(struct cir_softc), cir_match, cir_attach,
61 	cir_detach, cir_activate
62 };
63 
64 extern struct cfdriver cir_cd;
65 
66 #define CIRUNIT(dev) (minor(dev))
67 
68 int
69 cir_match(struct device *parent, struct cfdata *match, void *aux)
70 {
71 	struct ir_attach_args *ia = aux;
72 
73 	return (ia->ia_type == IR_TYPE_CIR);
74 }
75 
76 void
77 cir_attach(struct device *parent, struct device *self, void *aux)
78 {
79 	struct cir_softc *sc = (struct cir_softc *)self;
80 	struct ir_attach_args *ia = aux;
81 
82 	sc->sc_methods = ia->ia_methods;
83 	sc->sc_handle = ia->ia_handle;
84 
85 #ifdef DIAGNOSTIC
86 	if (sc->sc_methods->im_read == NULL ||
87 	    sc->sc_methods->im_write == NULL)
88 		panic("%s: missing methods\n", sc->sc_dev.dv_xname);
89 #endif
90 	printf("\n");
91 }
92 
93 int
94 cir_activate(struct device *self, enum devact act)
95 {
96 	/*struct cir_softc *sc = (struct cir_softc *)self;*/
97 
98 	switch (act) {
99 	case DVACT_ACTIVATE:
100 		return (EOPNOTSUPP);
101 		break;
102 
103 	case DVACT_DEACTIVATE:
104 		break;
105 	}
106 	return (0);
107 }
108 
109 int
110 cir_detach(struct device *self, int flags)
111 {
112 	/*struct cir_softc *sc = (struct cir_softc *)self;*/
113 	int maj, mn;
114 
115 	/* locate the major number */
116 	for (maj = 0; maj < nchrdev; maj++)
117 		if (cdevsw[maj].d_open == ciropen)
118 			break;
119 
120 	/* Nuke the vnodes for any open instances (calls close). */
121 	mn = self->dv_unit;
122 	vdevgone(maj, mn, mn, VCHR);
123 
124 	return (0);
125 }
126 
127 int
128 ciropen(dev_t dev, int flag, int mode, struct proc *p)
129 {
130 	struct cir_softc *sc;
131 	int error;
132 
133 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
134 	if (sc == NULL)
135 		return (ENXIO);
136 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
137 		return (EIO);
138 	if (sc->sc_open)
139 		return (EBUSY);
140 	if (sc->sc_methods->im_open != NULL) {
141 		error = sc->sc_methods->im_open(sc->sc_handle, flag, mode, p);
142 		if (error)
143 			return (error);
144 	}
145 	sc->sc_open = 1;
146 	return (0);
147 }
148 
149 int
150 circlose(dev_t dev, int flag, int mode, struct proc *p)
151 {
152 	struct cir_softc *sc;
153 	int error;
154 
155 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
156 	if (sc == NULL)
157 		return (ENXIO);
158 	if (sc->sc_methods->im_close != NULL)
159 		error = sc->sc_methods->im_close(sc->sc_handle, flag, mode, p);
160 	else
161 		error = 0;
162 	sc->sc_open = 0;
163 	return (error);
164 }
165 
166 int
167 cirread(dev_t dev, struct uio *uio, int flag)
168 {
169 	struct cir_softc *sc;
170 
171 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
172 	if (sc == NULL)
173 		return (ENXIO);
174 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
175 		return (EIO);
176 	return (sc->sc_methods->im_read(sc->sc_handle, uio, flag));
177 }
178 
179 int
180 cirwrite(dev_t dev, struct uio *uio, int flag)
181 {
182 	struct cir_softc *sc;
183 
184 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
185 	if (sc == NULL)
186 		return (ENXIO);
187 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
188 		return (EIO);
189 	return (sc->sc_methods->im_write(sc->sc_handle, uio, flag));
190 }
191 
192 int
193 cirioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
194 {
195 	struct cir_softc *sc;
196 	int error;
197 
198 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
199 	if (sc == NULL)
200 		return (ENXIO);
201 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
202 		return (EIO);
203 
204 	switch (cmd) {
205 	case FIONBIO:
206 		/* All handled in the upper FS layer. */
207 		error = 0;
208 		break;
209 	default:
210 		error = EINVAL;
211 		break;
212 	}
213 	return (error);
214 }
215 
216 int
217 cirpoll(dev_t dev, int events, struct proc *p)
218 {
219 	struct cir_softc *sc;
220 	int revents;
221 	int s;
222 
223 	sc = device_lookup(&cir_cd, CIRUNIT(dev));
224 	if (sc == NULL)
225 		return (ENXIO);
226 	if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
227 		return (EIO);
228 
229 	revents = 0;
230 	s = splir();
231 #if 0
232 	if (events & (POLLIN | POLLRDNORM))
233 		if (sc->sc_rdframes > 0)
234 			revents |= events & (POLLIN | POLLRDNORM);
235 #endif
236 
237 #if 0
238 	/* How about write? */
239 	if (events & (POLLOUT | POLLWRNORM))
240 		if (???)
241 			revents |= events & (POLLOUT | POLLWRNORM);
242 #endif
243 
244 	if (revents == 0) {
245 		if (events & (POLLIN | POLLRDNORM))
246 			selrecord(p, &sc->sc_rdsel);
247 
248 #if 0
249 		if (events & (POLLOUT | POLLWRNORM))
250 			selrecord(p, &sc->sc_wrsel);
251 #endif
252 	}
253 
254 	splx(s);
255 	return (revents);
256 }
257