kern_conf.c revision 37172
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.25 1998/06/25 11:27:34 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 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));
53
54/*
55 * Routine to convert from character to block device number.
56 *
57 * A minimal stub routine can always return NODEV.
58 */
59dev_t
60chrtoblk(dev_t dev)
61{
62	struct bdevsw *bd;
63	struct cdevsw *cd;
64
65	if(cd = cdevsw[major(dev)]) {
66          if ( (bd = cd->d_bdev) )
67	    return(makedev(bd->d_maj,minor(dev)));
68	}
69	return(NODEV);
70}
71
72/*
73 * (re)place an entry in the bdevsw or cdevsw table
74 * return the slot used in major(*descrip)
75 */
76#define ADDENTRY(TTYPE,NXXXDEV,ALLOCSTART) \
77int TTYPE##_add(dev_t *descrip,						\
78		struct TTYPE *newentry,					\
79		struct TTYPE **oldentry)				\
80{									\
81	int i ;								\
82	if ( (int)*descrip == NODEV) {	/* auto (0 is valid) */		\
83		/*							\
84		 * Search the table looking for a slot...		\
85		 */							\
86		for (i = ALLOCSTART; i < NXXXDEV; i++)			\
87			if (TTYPE[i] == NULL)				\
88				break;		/* found one! */	\
89		/* out of allocable slots? */				\
90		if (i >= NXXXDEV) {					\
91			return ENFILE;					\
92		}							\
93	} else {				/* assign */		\
94		i = major(*descrip);					\
95		if (i < 0 || i >= NXXXDEV) {				\
96			return EINVAL;					\
97		}							\
98	}								\
99									\
100	/* maybe save old */						\
101        if (oldentry) {							\
102		*oldentry = TTYPE[i];					\
103	}								\
104	if (newentry)							\
105		newentry->d_maj = i;					\
106	/* replace with new */						\
107	TTYPE[i] = newentry;						\
108									\
109	/* done!  let them know where we put it */			\
110	*descrip = makedev(i,0);					\
111	return 0;							\
112} \
113
114static ADDENTRY(bdevsw, nblkdev,bdevsw_ALLOCSTART)
115ADDENTRY(cdevsw, nchrdev,cdevsw_ALLOCSTART)
116
117/*
118 * Since the bdevsw struct for a disk contains all the information
119 * needed to create a cdevsw entry, these two routines do that, rather
120 * than specifying it by hand.
121 */
122
123static void
124cdevsw_make(struct bdevsw *from)
125{
126	struct cdevsw *to = from->d_cdev;
127
128	if (!to)
129		panic("No target cdevsw in bdevsw");
130	to->d_open = from->d_open;
131	to->d_close = from->d_close;
132	to->d_read = rawread;
133	to->d_write = rawwrite;
134	to->d_ioctl = from->d_ioctl;
135	to->d_stop = nostop;
136	to->d_reset = nullreset;
137	to->d_devtotty = nodevtotty;
138	to->d_poll = seltrue;
139	to->d_mmap = nommap;
140	to->d_strategy = from->d_strategy;
141	to->d_name = from->d_name;
142	to->d_bdev = from;
143	to->d_maj = -1;
144	to->d_bmaj = from->d_maj;
145	to->d_maxio = from->d_maxio;
146	to->d_dump = from->d_dump;
147	to->d_psize = from->d_psize;
148	to->d_flags = from->d_flags;
149}
150
151void
152bdevsw_add_generic(int bdev, int cdev, struct bdevsw *bdevsw)
153{
154	dev_t dev;
155
156	cdevsw_make(bdevsw);
157	dev = makedev(cdev, 0);
158	cdevsw_add(&dev, bdevsw->d_cdev, NULL);
159	dev = makedev(bdev, 0);
160	bdevsw_add(&dev, bdevsw        , NULL);
161}
162
163int
164cdevsw_module_handler(module_t mod, modeventtype_t what, void* arg)
165{
166	struct cdevsw_module_data* data = (struct cdevsw_module_data*) arg;
167	int error;
168
169	switch (what) {
170	case MOD_LOAD:
171		if (error = cdevsw_add(&data->dev, data->cdevsw, NULL))
172			return error;
173		break;
174
175	case MOD_UNLOAD:
176		if (error = cdevsw_add(&data->dev, NULL, NULL))
177			return error;
178		break;
179	}
180
181	if (data->chainevh)
182		return data->chainevh(mod, what, data->chainarg);
183	else
184		return 0;
185}
186
187int
188bdevsw_module_handler(module_t mod, modeventtype_t what, void* arg)
189{
190	struct bdevsw_module_data* data = (struct bdevsw_module_data*) arg;
191	int error;
192
193	switch (what) {
194	case MOD_LOAD:
195		cdevsw_make(data->bdevsw);
196		if (error = cdevsw_add(&data->cdev, data->bdevsw->d_cdev, NULL))
197			return error;
198		if (error = bdevsw_add(&data->bdev, data->bdevsw, NULL))
199			return error;
200		break;
201
202	case MOD_UNLOAD:
203		if (error = cdevsw_add(&data->cdev, NULL, NULL))
204			return error;
205		if (error = bdevsw_add(&data->bdev, NULL, NULL))
206			return error;
207		break;
208	}
209
210	if (data->chainevh)
211		return data->chainevh(mod, what, data->chainarg);
212	else
213		return 0;
214}
215