xref: /freebsd/sys/kern/kern_conf.c (revision 6e8394b8baa7d5d9153ab90de6824bcd19b3b4e1)
1 /*-
2  * Parts Copyright (c) 1995 Terrence R. Lambert
3  * Copyright (c) 1995 Julian R. Elischer
4  * 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  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Terrence R. Lambert.
17  * 4. The name Terrence R. Lambert may not be used to endorse or promote
18  *    products derived from this software without specific prior written
19  *    permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $Id: kern_conf.c,v 1.42 1999/06/01 18:56:24 phk Exp $
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/module.h>
39 #include <sys/conf.h>
40 #include <sys/vnode.h>
41 
42 #define cdevsw_ALLOCSTART	(NUMCDEVSW/2)
43 
44 struct cdevsw 	*cdevsw[NUMCDEVSW];
45 
46 int	bmaj2cmaj[NUMCDEVSW];
47 
48 /*
49  * Routine to convert from character to block device number.
50  *
51  * A minimal stub routine can always return NODEV.
52  */
53 dev_t
54 chrtoblk(dev_t dev)
55 {
56 	struct cdevsw *cd;
57 
58 	if((cd = devsw(dev)) != NULL) {
59           if (cd->d_bmaj != -1)
60 	    return(makedev(cd->d_bmaj,minor(dev)));
61 	}
62 	return(NODEV);
63 }
64 
65 struct cdevsw *
66 devsw(dev_t dev)
67 {
68         return(cdevsw[major(dev)]);
69 }
70 
71 struct cdevsw *
72 bdevsw(dev_t dev)
73 {
74         struct cdevsw *c;
75         int i = major(dev);
76 
77         if (bmaj2cmaj[i] == 254)
78                 return 0;
79 
80         c = cdevsw[bmaj2cmaj[major(dev)]];
81         if (!c) {
82                 printf("bogus bdev dev_t %p, no cdev\n", (void *)dev);
83                 Debugger("Bummer");
84                 return 0;
85         }
86         /* CMAJ zero is the console, which has no strategy so this works */
87         if (c->d_strategy)
88                 return (c);
89         return (0);
90 }
91 
92 /*
93  *  Add a cdevsw entry
94  */
95 
96 int
97 cdevsw_add(struct cdevsw *newentry)
98 {
99 	int i;
100 	static int setup;
101 
102 	if (!setup) {
103 		for (i = 0; i < NUMCDEVSW; i++)
104 			if (!bmaj2cmaj[i])
105 				bmaj2cmaj[i] = 254;
106 		setup++;
107 	}
108 
109 	if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) {
110 		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
111 		    newentry->d_name, newentry->d_maj);
112 		return EINVAL;
113 	}
114 
115 	cdevsw[newentry->d_maj] = newentry;
116 
117 	if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW)
118 		bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj;
119 
120 	return 0;
121 }
122 
123 int
124 devsw_module_handler(module_t mod, int what, void* arg)
125 {
126 	struct devsw_module_data* data = (struct devsw_module_data*) arg;
127 	int error;
128 
129 	if (data->cmaj == NOMAJ)
130 		data->cdev = NODEV;
131 	else
132 		data->cdev = makedev(data->cmaj, 0);
133 	switch (what) {
134 	case MOD_LOAD:
135 		error = cdevsw_add(data->cdevsw);
136 		if (!error && data->cdevsw->d_strategy != nostrategy) {
137 			if (data->bmaj == NOMAJ) {
138 				data->bdev = data->cdev;
139 				data->bmaj = data->cmaj;
140 			} else {
141 				data->bdev = makedev(data->bmaj, 0);
142 			}
143 			data->cdevsw->d_maj = data->bmaj;
144 			bmaj2cmaj[major(data->bdev)] = major(data->cdev);
145 		}
146 		if (!error && data->chainevh)
147 			error = data->chainevh(mod, what, data->chainarg);
148 		return error;
149 
150 	case MOD_UNLOAD:
151 		if (data->chainevh) {
152 			error = data->chainevh(mod, what, data->chainarg);
153 			if (error)
154 				return error;
155 		}
156 		if (data->cdevsw->d_strategy != nostrategy)
157 			bmaj2cmaj[major(data->bdev)] = 0;
158 		return error;
159 	}
160 
161 	if (data->chainevh)
162 		return data->chainevh(mod, what, data->chainarg);
163 	else
164 		return 0;
165 }
166 
167 /*
168  * dev_t and u_dev_t primitives
169  */
170 
171 #define DEVT_FASCIST 1
172 
173 int
174 major(dev_t x)
175 {
176 	uintptr_t i = (uintptr_t)x;
177 
178 #ifdef DEVT_FASCIST
179 	return(255 - ((i >> 8) & 0xff));
180 #else
181 	return((i >> 8) & 0xff);
182 #endif
183 }
184 
185 int
186 minor(dev_t x)
187 {
188 	uintptr_t i = (uintptr_t)x;
189 
190 	return(i & 0xffff00ff);
191 }
192 
193 dev_t
194 makebdev(int x, int y)
195 {
196 	return (makedev(x, y));
197 }
198 
199 dev_t
200 makedev(int x, int y)
201 {
202 #ifdef DEVT_FASCIST
203         return ((dev_t) (((255 - x) << 8) | y));
204 #else
205         return ((dev_t) ((x << 8) | y));
206 #endif
207 }
208 
209 udev_t
210 dev2udev(dev_t x)
211 {
212 	return umakedev(major(x), minor(x));
213 }
214 
215 dev_t
216 udev2dev(udev_t x, int b)
217 {
218 	return makedev(umajor(x), uminor(x));
219 }
220 
221 int
222 uminor(udev_t dev)
223 {
224 	return(dev & 0xffff00ff);
225 }
226 
227 int
228 umajor(udev_t dev)
229 {
230 	return((dev & 0xff00) >> 8);
231 }
232 
233 udev_t
234 umakedev(int x, int y)
235 {
236         return ((x << 8) | y);
237 }
238 
239