1 /* $NetBSD: bio.c,v 1.8 2008/04/09 05:47:19 cegger Exp $ */
2 /* $OpenBSD: bio.c,v 1.9 2007/03/20 02:35:55 marco Exp $ */
5 * Copyright (c) 2002 Niklas Hallqvist. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 /* A device controller ioctl tunnelling device. */
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: bio.c,v 1.8 2008/04/09 05:47:19 cegger Exp $");
33 #include "opt_compat_netbsd.h"
35 #include <sys/param.h>
37 #include <sys/device.h>
38 #include <sys/event.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
42 #include <sys/systm.h>
43 #include <sys/mutex.h>
45 #include <sys/kauth.h>
47 #include <dev/biovar.h>
50 LIST_ENTRY(bio_mapping
) bm_link
;
52 int (*bm_ioctl
)(device_t
, u_long
, void *);
55 static LIST_HEAD(, bio_mapping
) bios
= LIST_HEAD_INITIALIZER(bios
);
56 static kmutex_t bio_lock
;
57 static bool bio_lock_initialized
= false;
59 static void bio_initialize(void);
60 static int bioclose(dev_t
, int, int, struct lwp
*);
61 static int bioioctl(dev_t
, u_long
, void *, int, struct lwp
*);
62 static int bioopen(dev_t
, int, int, struct lwp
*);
64 static int bio_delegate_ioctl(void *, u_long
, void *);
65 static struct bio_mapping
*bio_lookup(char *);
66 static int bio_validate(void *);
70 const struct cdevsw bio_cdevsw
= {
71 bioopen
, bioclose
, noread
, nowrite
, bioioctl
,
72 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_OTHER
| D_MPSAFE
79 if (bio_lock_initialized
)
82 mutex_init(&bio_lock
, MUTEX_DEFAULT
, IPL_VM
);
83 bio_lock_initialized
= true;
89 if (!bio_lock_initialized
)
94 bioopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
100 bioclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
106 bioioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
108 struct bio_locate
*locate
;
109 struct bio_common
*common
;
123 error
= kauth_authorize_device_passthru(l
->l_cred
, dev
,
124 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF
, addr
);
131 error
= kauth_authorize_device_passthru(l
->l_cred
, dev
,
132 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF
, addr
);
137 struct bioc_alarm
*alarm
= (struct bioc_alarm
*)addr
;
138 switch (alarm
->ba_opcode
) {
143 error
= kauth_authorize_device_passthru(l
->l_cred
, dev
,
144 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF
, addr
);
149 error
= kauth_authorize_device_passthru(l
->l_cred
, dev
,
150 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF
, addr
);
166 error
= copyinstr(locate
->bl_name
, name
, sizeof(name
), NULL
);
169 locate
->bl_cookie
= bio_lookup(name
);
170 if (locate
->bl_cookie
== NULL
)
176 mutex_enter(&bio_lock
);
177 if (!bio_validate(common
->bc_cookie
)) {
178 mutex_exit(&bio_lock
);
181 mutex_exit(&bio_lock
);
185 struct bioc_disk
*bd
=
186 malloc(sizeof(*bd
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
188 (void)memcpy(bd
, addr
, sizeof(struct obioc_disk
));
189 error
= bio_delegate_ioctl(common
->bc_cookie
,
196 (void)memcpy(addr
, bd
, sizeof(struct obioc_disk
));
201 struct bioc_vol
*bv
=
202 malloc(sizeof(*bv
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
204 (void)memcpy(bv
, addr
, sizeof(struct obioc_vol
));
205 error
= bio_delegate_ioctl(common
->bc_cookie
,
212 (void)memcpy(addr
, bv
, sizeof(struct obioc_vol
));
218 error
= bio_delegate_ioctl(common
->bc_cookie
, cmd
, addr
);
225 bio_register(device_t dev
, int (*ioctl
)(device_t
, u_long
, void *))
227 struct bio_mapping
*bm
;
229 if (!bio_lock_initialized
)
232 bm
= malloc(sizeof(*bm
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
236 bm
->bm_ioctl
= ioctl
;
237 mutex_enter(&bio_lock
);
238 LIST_INSERT_HEAD(&bios
, bm
, bm_link
);
239 mutex_exit(&bio_lock
);
244 bio_unregister(device_t dev
)
246 struct bio_mapping
*bm
, *next
;
248 mutex_enter(&bio_lock
);
249 for (bm
= LIST_FIRST(&bios
); bm
!= NULL
; bm
= next
) {
250 next
= LIST_NEXT(bm
, bm_link
);
252 if (dev
== bm
->bm_dev
) {
253 LIST_REMOVE(bm
, bm_link
);
257 mutex_exit(&bio_lock
);
260 static struct bio_mapping
*
261 bio_lookup(char *name
)
263 struct bio_mapping
*bm
;
265 mutex_enter(&bio_lock
);
266 LIST_FOREACH(bm
, &bios
, bm_link
) {
267 if (strcmp(name
, device_xname(bm
->bm_dev
)) == 0) {
268 mutex_exit(&bio_lock
);
272 mutex_exit(&bio_lock
);
277 bio_validate(void *cookie
)
279 struct bio_mapping
*bm
;
281 LIST_FOREACH(bm
, &bios
, bm_link
)
289 bio_delegate_ioctl(void *cookie
, u_long cmd
, void *addr
)
291 struct bio_mapping
*bm
= cookie
;
293 return bm
->bm_ioctl(bm
->bm_dev
, cmd
, addr
);