kern_conf.c revision 37153
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.24 1998/06/07 17:11:32 dfr 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 NUMBDEV 128
43#define NUMCDEV 256
44#define bdevsw_ALLOCSTART	(NUMBDEV/2)
45#define cdevsw_ALLOCSTART	(NUMCDEV/2)
46
47struct bdevsw 	*bdevsw[NUMBDEV];
48int	nblkdev = NUMBDEV;
49struct cdevsw 	*cdevsw[NUMCDEV];
50int	nchrdev = NUMCDEV;
51
52static void	cdevsw_make __P((struct bdevsw *from));
53static int	isdisk __P((dev_t dev, int type));
54
55/*
56 * Routine to determine if a device is a disk.
57 *
58 * KLUDGE XXX add flags to cdevsw entries for disks XXX
59 * A minimal stub routine can always return 0.
60 */
61static int
62isdisk(dev, type)
63	dev_t dev;
64	int type;
65{
66
67	switch (major(dev)) {
68	case 15:		/* VBLK: vn, VCHR: cd */
69		return (1);
70	case 0:			/* wd */
71	case 2:			/* fd */
72	case 4:			/* sd */
73	case 6:			/* cd */
74	case 7:			/* mcd */
75	case 16:		/* scd */
76	case 17:		/* matcd */
77	case 18:		/* ata */
78	case 19:		/* wcd */
79	case 20:		/* od */
80	case 22:		/* gd */
81		if (type == VBLK)
82			return (1);
83		return (0);
84	case 3:			/* wd */
85	case 9:			/* fd */
86	case 13:		/* sd */
87	case 29:		/* mcd */
88	case 43:		/* vn */
89	case 45:		/* scd */
90	case 46:		/* matcd */
91	case 69:		/* wcd */
92	case 70:		/* od */
93	case 78:		/* gd */
94		if (type == VCHR)
95			return (1);
96		/* fall through */
97	default:
98		return (0);
99	}
100	/* NOTREACHED */
101}
102
103
104/*
105 * Routine to convert from character to block device number.
106 *
107 * A minimal stub routine can always return NODEV.
108 */
109dev_t
110chrtoblk(dev_t dev)
111{
112	struct bdevsw *bd;
113	struct cdevsw *cd;
114
115	if(cd = cdevsw[major(dev)]) {
116          if ( (bd = cd->d_bdev) )
117	    return(makedev(bd->d_maj,minor(dev)));
118	}
119	return(NODEV);
120}
121
122/*
123 * (re)place an entry in the bdevsw or cdevsw table
124 * return the slot used in major(*descrip)
125 */
126#define ADDENTRY(TTYPE,NXXXDEV,ALLOCSTART) \
127int TTYPE##_add(dev_t *descrip,						\
128		struct TTYPE *newentry,					\
129		struct TTYPE **oldentry)				\
130{									\
131	int i ;								\
132	if ( (int)*descrip == NODEV) {	/* auto (0 is valid) */		\
133		/*							\
134		 * Search the table looking for a slot...		\
135		 */							\
136		for (i = ALLOCSTART; i < NXXXDEV; i++)			\
137			if (TTYPE[i] == NULL)				\
138				break;		/* found one! */	\
139		/* out of allocable slots? */				\
140		if (i >= NXXXDEV) {					\
141			return ENFILE;					\
142		}							\
143	} else {				/* assign */		\
144		i = major(*descrip);					\
145		if (i < 0 || i >= NXXXDEV) {				\
146			return EINVAL;					\
147		}							\
148	}								\
149									\
150	/* maybe save old */						\
151        if (oldentry) {							\
152		*oldentry = TTYPE[i];					\
153	}								\
154	if (newentry)							\
155		newentry->d_maj = i;					\
156	/* replace with new */						\
157	TTYPE[i] = newentry;						\
158									\
159	/* done!  let them know where we put it */			\
160	*descrip = makedev(i,0);					\
161	return 0;							\
162} \
163
164static ADDENTRY(bdevsw, nblkdev,bdevsw_ALLOCSTART)
165ADDENTRY(cdevsw, nchrdev,cdevsw_ALLOCSTART)
166
167/*
168 * Since the bdevsw struct for a disk contains all the information
169 * needed to create a cdevsw entry, these two routines do that, rather
170 * than specifying it by hand.
171 */
172
173static void
174cdevsw_make(struct bdevsw *from)
175{
176	struct cdevsw *to = from->d_cdev;
177
178	if (!to)
179		panic("No target cdevsw in bdevsw");
180	to->d_open = from->d_open;
181	to->d_close = from->d_close;
182	to->d_read = rawread;
183	to->d_write = rawwrite;
184	to->d_ioctl = from->d_ioctl;
185	to->d_stop = nostop;
186	to->d_reset = nullreset;
187	to->d_devtotty = nodevtotty;
188	to->d_poll = seltrue;
189	to->d_mmap = nommap;
190	to->d_strategy = from->d_strategy;
191	to->d_name = from->d_name;
192	to->d_bdev = from;
193	to->d_maj = -1;
194	to->d_bmaj = from->d_maj;
195	to->d_maxio = from->d_maxio;
196	to->d_dump = from->d_dump;
197	to->d_psize = from->d_psize;
198	to->d_flags = from->d_flags;
199}
200
201void
202bdevsw_add_generic(int bdev, int cdev, struct bdevsw *bdevsw)
203{
204	dev_t dev;
205	/*
206	 * XXX hack alert.
207	 */
208	if (isdisk(makedev(bdev, 0), VBLK) &&
209	    (bdevsw->d_flags & D_TYPEMASK) != D_DISK) {
210	    printf("bdevsw_add_generic: adding D_DISK flag for device %d\n",
211		   bdev);
212	    bdevsw->d_flags &= ~D_TYPEMASK;
213	    bdevsw->d_flags |= D_DISK;
214	}
215	cdevsw_make(bdevsw);
216	dev = makedev(cdev, 0);
217	cdevsw_add(&dev, bdevsw->d_cdev, NULL);
218	dev = makedev(bdev, 0);
219	bdevsw_add(&dev, bdevsw        , NULL);
220}
221
222int
223cdevsw_module_handler(module_t mod, modeventtype_t what, void* arg)
224{
225	struct cdevsw_module_data* data = (struct cdevsw_module_data*) arg;
226	int error;
227
228	switch (what) {
229	case MOD_LOAD:
230		if (error = cdevsw_add(&data->dev, data->cdevsw, NULL))
231			return error;
232		break;
233
234	case MOD_UNLOAD:
235		if (error = cdevsw_add(&data->dev, NULL, NULL))
236			return error;
237		break;
238	}
239
240	if (data->chainevh)
241		return data->chainevh(mod, what, data->chainarg);
242	else
243		return 0;
244}
245
246int
247bdevsw_module_handler(module_t mod, modeventtype_t what, void* arg)
248{
249	struct bdevsw_module_data* data = (struct bdevsw_module_data*) arg;
250	int error;
251
252	switch (what) {
253	case MOD_LOAD:
254		/*
255		 * XXX hack alert.
256		 */
257		if (isdisk(data->bdev, VBLK) && data->bdevsw->d_flags != D_DISK) {
258			printf("bdevsw_module_handler: adding D_DISK flag for device %d\n",
259			       major(data->bdev));
260			data->bdevsw->d_flags = D_DISK;
261		}
262		cdevsw_make(data->bdevsw);
263		if (error = cdevsw_add(&data->cdev, data->bdevsw->d_cdev, NULL))
264			return error;
265		if (error = bdevsw_add(&data->bdev, data->bdevsw, NULL))
266			return error;
267		break;
268
269	case MOD_UNLOAD:
270		if (error = cdevsw_add(&data->cdev, NULL, NULL))
271			return error;
272		if (error = cdevsw_add(&data->bdev, NULL, NULL))
273			return error;
274		break;
275	}
276
277	if (data->chainevh)
278		return data->chainevh(mod, what, data->chainarg);
279	else
280		return 0;
281}
282