1 /* $NetBSD: cir.c,v 1.25 2009/05/12 14:29:42 cegger Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cir.c,v 1.25 2009/05/12 14:29:42 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/ioctl.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
42 #include <sys/select.h>
43 #include <sys/vnode.h>
45 #include <dev/ir/ir.h>
46 #include <dev/ir/cirio.h>
47 #include <dev/ir/cirvar.h>
49 dev_type_open(ciropen
);
50 dev_type_close(circlose
);
51 dev_type_read(cirread
);
52 dev_type_write(cirwrite
);
53 dev_type_ioctl(cirioctl
);
54 dev_type_poll(cirpoll
);
56 const struct cdevsw cir_cdevsw
= {
57 ciropen
, circlose
, cirread
, cirwrite
, cirioctl
,
58 nostop
, notty
, cirpoll
, nommap
, nokqfilter
,
62 int cir_match(device_t parent
, cfdata_t match
, void *aux
);
63 void cir_attach(device_t parent
, device_t self
, void *aux
);
64 int cir_detach(device_t self
, int flags
);
66 CFATTACH_DECL(cir
, sizeof(struct cir_softc
),
67 cir_match
, cir_attach
, cir_detach
, NULL
);
69 extern struct cfdriver cir_cd
;
71 #define CIRUNIT(dev) (minor(dev))
74 cir_match(device_t parent
, cfdata_t match
, void *aux
)
76 struct ir_attach_args
*ia
= aux
;
78 return (ia
->ia_type
== IR_TYPE_CIR
);
82 cir_attach(device_t parent
, device_t self
, void *aux
)
84 struct cir_softc
*sc
= device_private(self
);
85 struct ir_attach_args
*ia
= aux
;
87 selinit(&sc
->sc_rdsel
);
88 sc
->sc_methods
= ia
->ia_methods
;
89 sc
->sc_handle
= ia
->ia_handle
;
92 if (sc
->sc_methods
->im_read
== NULL
||
93 sc
->sc_methods
->im_write
== NULL
||
94 sc
->sc_methods
->im_setparams
== NULL
)
95 panic("%s: missing methods", device_xname(&sc
->sc_dev
));
101 cir_detach(device_t self
, int flags
)
103 struct cir_softc
*sc
= device_private(self
);
106 /* locate the major number */
107 maj
= cdevsw_lookup_major(&cir_cdevsw
);
109 /* Nuke the vnodes for any open instances (calls close). */
110 mn
= device_unit(self
);
111 vdevgone(maj
, mn
, mn
, VCHR
);
113 seldestroy(&sc
->sc_rdsel
);
119 ciropen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
121 struct cir_softc
*sc
;
124 sc
= device_lookup_private(&cir_cd
, CIRUNIT(dev
));
127 if (!device_is_active(&sc
->sc_dev
))
133 if (sc
->sc_methods
->im_open
!= NULL
) {
134 error
= sc
->sc_methods
->im_open(sc
->sc_handle
, flag
, mode
,
144 circlose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
146 struct cir_softc
*sc
;
149 sc
= device_lookup_private(&cir_cd
, CIRUNIT(dev
));
152 if (sc
->sc_methods
->im_close
!= NULL
)
153 error
= sc
->sc_methods
->im_close(sc
->sc_handle
, flag
, mode
,
162 cirread(dev_t dev
, struct uio
*uio
, int flag
)
164 struct cir_softc
*sc
;
166 sc
= device_lookup_private(&cir_cd
, CIRUNIT(dev
));
169 if (!device_is_active(&sc
->sc_dev
))
171 return (sc
->sc_methods
->im_read(sc
->sc_handle
, uio
, flag
));
175 cirwrite(dev_t dev
, struct uio
*uio
, int flag
)
177 struct cir_softc
*sc
;
179 sc
= device_lookup_private(&cir_cd
, CIRUNIT(dev
));
182 if (!device_is_active(&sc
->sc_dev
))
184 return (sc
->sc_methods
->im_write(sc
->sc_handle
, uio
, flag
));
188 cirioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
190 struct cir_softc
*sc
;
193 sc
= device_lookup_private(&cir_cd
, CIRUNIT(dev
));
196 if (!device_is_active(&sc
->sc_dev
))
201 /* All handled in the upper FS layer. */
205 *(struct cir_params
*)addr
= sc
->sc_params
;
209 error
= sc
->sc_methods
->im_setparams(sc
->sc_handle
,
210 (struct cir_params
*)addr
);
212 sc
->sc_params
= *(struct cir_params
*)addr
;
222 cirpoll(dev_t dev
, int events
, struct lwp
*l
)
224 struct cir_softc
*sc
;
228 sc
= device_lookup_private(&cir_cd
, CIRUNIT(dev
));
231 if (!device_is_active(&sc
->sc_dev
))
236 if (events
& (POLLIN
| POLLRDNORM
))
237 if (sc
->sc_rdframes
> 0)
238 revents
|= events
& (POLLIN
| POLLRDNORM
);
241 /* How about write? */
242 if (events
& (POLLOUT
| POLLWRNORM
))
244 revents
|= events
& (POLLOUT
| POLLWRNORM
);
248 if (events
& (POLLIN
| POLLRDNORM
))
249 selrecord(l
, &sc
->sc_rdsel
);
252 if (events
& (POLLOUT
| POLLWRNORM
))
253 selrecord(p
, &sc
->sc_wrsel
);