xref: /openbsd-src/sys/dev/bio.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: bio.c,v 1.12 2010/01/22 21:56:04 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 2002 Niklas Hallqvist.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /* A device controller ioctl tunnelling device.  */
28 
29 #include <sys/param.h>
30 #include <sys/device.h>
31 #include <sys/ioctl.h>
32 #include <sys/malloc.h>
33 #include <sys/queue.h>
34 #include <sys/systm.h>
35 
36 #include <dev/biovar.h>
37 
38 struct bio_mapping {
39 	LIST_ENTRY(bio_mapping) bm_link;
40 	struct device *bm_dev;
41 	int (*bm_ioctl)(struct device *, u_long, caddr_t);
42 };
43 
44 LIST_HEAD(, bio_mapping) bios = LIST_HEAD_INITIALIZER(bios);
45 
46 void	bioattach(int);
47 int	bioclose(dev_t, int, int, struct proc *);
48 int	bioioctl(dev_t, u_long, caddr_t, int, struct proc *);
49 int	bioopen(dev_t, int, int, struct proc *);
50 
51 int	bio_delegate_ioctl(struct bio_mapping *, u_long, caddr_t);
52 struct	bio_mapping *bio_lookup(char *);
53 int	bio_validate(void *);
54 
55 void
56 bioattach(int nunits)
57 {
58 }
59 
60 int
61 bioopen(dev_t dev, int flags, int mode, struct proc *p)
62 {
63 	return (0);
64 }
65 
66 int
67 bioclose(dev_t dev, int flags, int mode, struct proc *p)
68 {
69 	return (0);
70 }
71 
72 int
73 bioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
74 {
75 	struct bio_locate *locate;
76 	struct bio_common *common;
77 	char name[16];
78 	int error;
79 
80 	switch (cmd) {
81 	case BIOCLOCATE:
82 		locate = (struct bio_locate *)addr;
83 		error = copyinstr(locate->bl_name, name, sizeof name, NULL);
84 		if (error != 0)
85 			return (error);
86 		locate->bl_cookie = bio_lookup(name);
87 		if (locate->bl_cookie == NULL)
88 			return (ENOENT);
89 		break;
90 
91 	case BIOCINQ:
92 	case BIOCDISK:
93 	case BIOCVOL:
94 	case BIOCALARM:
95 	case BIOCBLINK:
96 	case BIOCSETSTATE:
97 	case BIOCCREATERAID:
98 	case BIOCDELETERAID:
99 	case BIOCDISCIPLINE:
100 		common = (struct bio_common *)addr;
101 		if (!bio_validate(common->bc_cookie))
102 			return (ENOENT);
103 		return (bio_delegate_ioctl(
104 		    (struct bio_mapping *)common->bc_cookie, cmd, addr));
105 
106 	default:
107 		return (ENXIO);
108 	}
109 	return (0);
110 }
111 
112 int
113 bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, caddr_t))
114 {
115 	struct bio_mapping *bm;
116 
117 	bm = malloc(sizeof *bm, M_DEVBUF, M_NOWAIT);
118 	if (bm == NULL)
119 		return (ENOMEM);
120 	bm->bm_dev = dev;
121 	bm->bm_ioctl = ioctl;
122 	LIST_INSERT_HEAD(&bios, bm, bm_link);
123 	return (0);
124 }
125 
126 void
127 bio_unregister(struct device *dev)
128 {
129 	struct bio_mapping *bm, *next;
130 
131 	for (bm = LIST_FIRST(&bios); bm != NULL; bm = next) {
132 		next = LIST_NEXT(bm, bm_link);
133 
134 		if (dev == bm->bm_dev) {
135 			LIST_REMOVE(bm, bm_link);
136 			free(bm, M_DEVBUF);
137 		}
138 	}
139 }
140 
141 struct bio_mapping *
142 bio_lookup(char *name)
143 {
144 	struct bio_mapping *bm;
145 
146 	LIST_FOREACH(bm, &bios, bm_link)
147 		if (strcmp(name, bm->bm_dev->dv_xname) == 0)
148 			return (bm);
149 	return (NULL);
150 }
151 
152 int
153 bio_validate(void *cookie)
154 {
155 	struct bio_mapping *bm;
156 
157 	LIST_FOREACH(bm, &bios, bm_link)
158 		if (bm == cookie)
159 			return (1);
160 	return (0);
161 }
162 
163 int
164 bio_delegate_ioctl(struct bio_mapping *bm, u_long cmd, caddr_t addr)
165 {
166 	return (bm->bm_ioctl(bm->bm_dev, cmd, addr));
167 }
168