kern_conf.c revision 49982
111126Sjulian/*-
211126Sjulian * Parts Copyright (c) 1995 Terrence R. Lambert
311126Sjulian * Copyright (c) 1995 Julian R. Elischer
411126Sjulian * All rights reserved.
511126Sjulian *
611126Sjulian * Redistribution and use in source and binary forms, with or without
711126Sjulian * modification, are permitted provided that the following conditions
811126Sjulian * are met:
911126Sjulian * 1. Redistributions of source code must retain the above copyright
1011126Sjulian *    notice, this list of conditions and the following disclaimer.
1111126Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1211126Sjulian *    notice, this list of conditions and the following disclaimer in the
1311126Sjulian *    documentation and/or other materials provided with the distribution.
1411126Sjulian * 3. All advertising materials mentioning features or use of this software
1511126Sjulian *    must display the following acknowledgement:
1611126Sjulian *      This product includes software developed by Terrence R. Lambert.
1711126Sjulian * 4. The name Terrence R. Lambert may not be used to endorse or promote
1811126Sjulian *    products derived from this software without specific prior written
1911126Sjulian *    permission.
2011126Sjulian *
2111126Sjulian * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY
2211126Sjulian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311126Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411126Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
2511126Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2611126Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2711126Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2811126Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2911126Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3011126Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3111126Sjulian * SUCH DAMAGE.
3211126Sjulian *
3349982Sbillf * $Id: kern_conf.c,v 1.57 1999/08/15 09:32:47 phk Exp $
3411126Sjulian */
3511126Sjulian
3611126Sjulian#include <sys/param.h>
3748936Sphk#include <sys/kernel.h>
3811127Sjulian#include <sys/systm.h>
3936735Sdfr#include <sys/module.h>
4048936Sphk#include <sys/malloc.h>
4111126Sjulian#include <sys/conf.h>
4212954Sjulian#include <sys/vnode.h>
4348936Sphk#include <sys/queue.h>
4449535Sphk#include <machine/stdarg.h>
4511126Sjulian
4647640Sphk#define cdevsw_ALLOCSTART	(NUMCDEVSW/2)
4712954Sjulian
4847640Sphkstruct cdevsw 	*cdevsw[NUMCDEVSW];
4912954Sjulian
5048936Sphkstatic int	bmaj2cmaj[NUMCDEVSW];
5146635Sphk
5248936SphkMALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage");
5348936Sphk
5448936Sphk#define DEVT_HASH 83
5548936Sphk#define DEVT_STASH 50
5648936Sphk
5748936Sphkstatic struct specinfo devt_stash[DEVT_STASH];
5848936Sphk
5948936Sphkstatic SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH];
6048936Sphk
6111126Sjulian/*
6212954Sjulian * Routine to convert from character to block device number.
6312954Sjulian *
6412954Sjulian * A minimal stub routine can always return NODEV.
6512954Sjulian */
6612954Sjuliandev_t
6712954Sjulianchrtoblk(dev_t dev)
6812954Sjulian{
6912954Sjulian	struct cdevsw *cd;
7012954Sjulian
7146676Sphk	if((cd = devsw(dev)) != NULL) {
7237389Sjulian          if (cd->d_bmaj != -1)
7348864Sphk	    return(makebdev(cd->d_bmaj,minor(dev)));
7412954Sjulian	}
7512954Sjulian	return(NODEV);
7612954Sjulian}
7712954Sjulian
7847640Sphkstruct cdevsw *
7947640Sphkdevsw(dev_t dev)
8047640Sphk{
8149679Sphk	if (dev->si_devsw)
8249679Sphk		return (dev->si_devsw);
8347640Sphk        return(cdevsw[major(dev)]);
8447640Sphk}
8547640Sphk
8647640Sphk/*
8747640Sphk *  Add a cdevsw entry
8847640Sphk */
8947640Sphk
9037389Sjulianint
9147640Sphkcdevsw_add(struct cdevsw *newentry)
9217264Sphk{
9347028Sphk	int i;
9447028Sphk	static int setup;
9517264Sphk
9647028Sphk	if (!setup) {
9747640Sphk		for (i = 0; i < NUMCDEVSW; i++)
9847028Sphk			if (!bmaj2cmaj[i])
9948936Sphk				bmaj2cmaj[i] = 254;
10047028Sphk		setup++;
10147028Sphk	}
10247028Sphk
10347640Sphk	if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) {
10447640Sphk		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
10547640Sphk		    newentry->d_name, newentry->d_maj);
10647640Sphk		return EINVAL;
10737389Sjulian	}
10817264Sphk
10948510Sphk	if (cdevsw[newentry->d_maj]) {
11048510Sphk		printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n",
11148510Sphk		    newentry->d_name, cdevsw[newentry->d_maj]->d_name);
11248510Sphk	}
11347640Sphk	cdevsw[newentry->d_maj] = newentry;
11437389Sjulian
11548510Sphk	if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) {
11648936Sphk		if (bmaj2cmaj[newentry->d_bmaj] != 254) {
11748510Sphk			printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n",
11848510Sphk			    newentry->d_name,
11948510Sphk			    cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name);
12048510Sphk		}
12147640Sphk		bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj;
12248510Sphk	}
12347640Sphk
12437389Sjulian	return 0;
12537389Sjulian}
12637389Sjulian
12748211Sgrog/*
12848211Sgrog *  Remove a cdevsw entry
12948211Sgrog */
13048211Sgrog
13136735Sdfrint
13248211Sgrogcdevsw_remove(struct cdevsw *oldentry)
13348211Sgrog{
13448211Sgrog	if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) {
13548211Sgrog		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
13648211Sgrog		    oldentry->d_name, oldentry->d_maj);
13748211Sgrog		return EINVAL;
13848211Sgrog	}
13948211Sgrog
14048211Sgrog	cdevsw[oldentry->d_maj] = NULL;
14148211Sgrog
14248211Sgrog	if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW)
14349504Sgrog		bmaj2cmaj[oldentry->d_bmaj] = 254;
14448211Sgrog
14548211Sgrog	return 0;
14648211Sgrog}
14748211Sgrog
14848211Sgrogint
14946635Sphkdevsw_module_handler(module_t mod, int what, void* arg)
15036735Sdfr{
15146635Sphk	struct devsw_module_data* data = (struct devsw_module_data*) arg;
15248240Sdfr	int error = 0;
15336735Sdfr
15436735Sdfr	switch (what) {
15536735Sdfr	case MOD_LOAD:
15647640Sphk		error = cdevsw_add(data->cdevsw);
15744975Sdfr		if (!error && data->chainevh)
15844975Sdfr			error = data->chainevh(mod, what, data->chainarg);
15944975Sdfr		return error;
16036735Sdfr
16136735Sdfr	case MOD_UNLOAD:
16244975Sdfr		if (data->chainevh) {
16344975Sdfr			error = data->chainevh(mod, what, data->chainarg);
16444975Sdfr			if (error)
16544975Sdfr				return error;
16644975Sdfr		}
16748240Sdfr		cdevsw_remove(data->cdevsw);
16844975Sdfr		return error;
16936735Sdfr	}
17036735Sdfr
17136735Sdfr	if (data->chainevh)
17236735Sdfr		return data->chainevh(mod, what, data->chainarg);
17336735Sdfr	else
17436735Sdfr		return 0;
17536735Sdfr}
17647028Sphk
17747028Sphk/*
17847028Sphk * dev_t and u_dev_t primitives
17947028Sphk */
18047028Sphk
18147028Sphkint
18247028Sphkmajor(dev_t x)
18347028Sphk{
18448936Sphk	if (x == NODEV)
18548936Sphk		return NOUDEV;
18648936Sphk	return((x->si_udev >> 8) & 0xff);
18747028Sphk}
18847028Sphk
18947028Sphkint
19047028Sphkminor(dev_t x)
19147028Sphk{
19248936Sphk	if (x == NODEV)
19348936Sphk		return NOUDEV;
19448936Sphk	return(x->si_udev & 0xffff00ff);
19547028Sphk}
19647028Sphk
19749826Sphkint
19849826Sphklminor(dev_t x)
19949826Sphk{
20049826Sphk	int i;
20149826Sphk
20249826Sphk	if (x == NODEV)
20349826Sphk		return NOUDEV;
20449826Sphk	i = minor(x);
20549826Sphk	return ((i & 0xff) | (i >> 8));
20649826Sphk}
20749826Sphk
20847028Sphkdev_t
20947680Sphkmakebdev(int x, int y)
21047680Sphk{
21148892Sphk	return (makedev(bmaj2cmaj[x], y));
21247680Sphk}
21347680Sphk
21447680Sphkdev_t
21547028Sphkmakedev(int x, int y)
21647028Sphk{
21748936Sphk	struct specinfo *si;
21848936Sphk	udev_t	udev;
21948936Sphk	int hash;
22048936Sphk	static int stashed;
22148936Sphk
22248936Sphk	udev = (x << 8) | y;
22348936Sphk	hash = udev % DEVT_HASH;
22448936Sphk	SLIST_FOREACH(si, &dev_hash[hash], si_hash) {
22548936Sphk		if (si->si_udev == udev)
22648936Sphk			return (si);
22748936Sphk	}
22848936Sphk	if (stashed >= DEVT_STASH) {
22948936Sphk		MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT,
23048936Sphk		    M_USE_RESERVE);
23148936Sphk	} else {
23248936Sphk		si = devt_stash + stashed++;
23348936Sphk	}
23448936Sphk	bzero(si, sizeof(*si));
23548936Sphk	si->si_udev = udev;
23648936Sphk	si->si_bsize_phys = DEV_BSIZE;
23748936Sphk	si->si_bsize_best = BLKDEV_IOSIZE;
23848936Sphk	si->si_bsize_max = MAXBSIZE;
23949535Sphk	if (y > 256)
24049535Sphk		sprintf(si->si_name, "#%d/0x%x", x, y);
24149535Sphk	else
24249535Sphk		sprintf(si->si_name, "#%d/%d", x, y);
24348936Sphk	SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
24448936Sphk        return (si);
24547028Sphk}
24647028Sphk
24747028Sphkudev_t
24847028Sphkdev2udev(dev_t x)
24947028Sphk{
25048936Sphk	if (x == NODEV)
25148936Sphk		return NOUDEV;
25248936Sphk	return (x->si_udev);
25347028Sphk}
25447028Sphk
25548948Sgreenudev_t
25648948Sgreendev2budev(dev_t x)
25748948Sgreen{
25848949Sgreen	if (x == NODEV)
25948948Sgreen		return NOUDEV;
26048948Sgreen	else
26148948Sgreen		return makeudev(devsw(x)->d_bmaj, minor(x));
26248948Sgreen}
26348948Sgreen
26447028Sphkdev_t
26547028Sphkudev2dev(udev_t x, int b)
26647028Sphk{
26748864Sphk	switch (b) {
26848864Sphk		case 0:
26948864Sphk			return makedev(umajor(x), uminor(x));
27048864Sphk		case 1:
27148864Sphk			return makebdev(umajor(x), uminor(x));
27248864Sphk		default:
27348864Sphk			Debugger("udev2dev(...,X)");
27448864Sphk			return NODEV;
27548864Sphk	}
27647028Sphk}
27747028Sphk
27847028Sphkint
27947028Sphkuminor(udev_t dev)
28047028Sphk{
28147028Sphk	return(dev & 0xffff00ff);
28247028Sphk}
28347028Sphk
28447028Sphkint
28547028Sphkumajor(udev_t dev)
28647028Sphk{
28747028Sphk	return((dev & 0xff00) >> 8);
28847028Sphk}
28947028Sphk
29047028Sphkudev_t
29148859Sphkmakeudev(int x, int y)
29247028Sphk{
29347028Sphk        return ((x << 8) | y);
29447028Sphk}
29547028Sphk
29649535Sphkdev_t
29749535Sphkmake_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...)
29849535Sphk{
29949535Sphk	dev_t	dev;
30049535Sphk	va_list ap;
30149535Sphk	int i;
30249535Sphk
30349535Sphk	dev = makedev(devsw->d_maj, minor);
30449535Sphk	va_start(ap, fmt);
30549535Sphk	i = kvprintf(fmt, NULL, dev->si_name, 32, ap);
30649535Sphk	dev->si_name[i] = '\0';
30749535Sphk	va_end(ap);
30849535Sphk	dev->si_devsw = devsw;
30949535Sphk	return (dev);
31049535Sphk}
31149535Sphk
31249982Sbillfchar *
31349982Sbillfdevtoname(dev_t dev)
31449982Sbillf{
31549982Sbillf
31649982Sbillf	return (dev->si_name);
31749982Sbillf}
31849982Sbillf
319