kern_conf.c revision 49504
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 *
3349504Sgrog * $Id: kern_conf.c,v 1.53 1999/07/20 21:51:12 green 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>
4411126Sjulian
4548936Sphk#include <miscfs/specfs/specdev.h>
4648936Sphk
4747640Sphk#define cdevsw_ALLOCSTART	(NUMCDEVSW/2)
4812954Sjulian
4947640Sphkstruct cdevsw 	*cdevsw[NUMCDEVSW];
5012954Sjulian
5148936Sphkstatic int	bmaj2cmaj[NUMCDEVSW];
5246635Sphk
5348936SphkMALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage");
5448936Sphk
5548936Sphk#define DEVT_HASH 83
5648936Sphk#define DEVT_STASH 50
5748936Sphk
5848936Sphkstatic struct specinfo devt_stash[DEVT_STASH];
5948936Sphk
6048936Sphkstatic SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH];
6148936Sphk
6211126Sjulian/*
6312954Sjulian * Routine to convert from character to block device number.
6412954Sjulian *
6512954Sjulian * A minimal stub routine can always return NODEV.
6612954Sjulian */
6712954Sjuliandev_t
6812954Sjulianchrtoblk(dev_t dev)
6912954Sjulian{
7012954Sjulian	struct cdevsw *cd;
7112954Sjulian
7246676Sphk	if((cd = devsw(dev)) != NULL) {
7337389Sjulian          if (cd->d_bmaj != -1)
7448864Sphk	    return(makebdev(cd->d_bmaj,minor(dev)));
7512954Sjulian	}
7612954Sjulian	return(NODEV);
7712954Sjulian}
7812954Sjulian
7947640Sphkstruct cdevsw *
8047640Sphkdevsw(dev_t dev)
8147640Sphk{
8247640Sphk        return(cdevsw[major(dev)]);
8347640Sphk}
8447640Sphk
8547640Sphkstruct cdevsw *
8647640Sphkbdevsw(dev_t dev)
8747640Sphk{
8848892Sphk        return(cdevsw[major(dev)]);
8947640Sphk}
9047640Sphk
9147640Sphk/*
9247640Sphk *  Add a cdevsw entry
9347640Sphk */
9447640Sphk
9537389Sjulianint
9647640Sphkcdevsw_add(struct cdevsw *newentry)
9717264Sphk{
9847028Sphk	int i;
9947028Sphk	static int setup;
10017264Sphk
10147028Sphk	if (!setup) {
10247640Sphk		for (i = 0; i < NUMCDEVSW; i++)
10347028Sphk			if (!bmaj2cmaj[i])
10448936Sphk				bmaj2cmaj[i] = 254;
10547028Sphk		setup++;
10647028Sphk	}
10747028Sphk
10847640Sphk	if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) {
10947640Sphk		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
11047640Sphk		    newentry->d_name, newentry->d_maj);
11147640Sphk		return EINVAL;
11237389Sjulian	}
11317264Sphk
11448510Sphk	if (cdevsw[newentry->d_maj]) {
11548510Sphk		printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n",
11648510Sphk		    newentry->d_name, cdevsw[newentry->d_maj]->d_name);
11748510Sphk	}
11847640Sphk	cdevsw[newentry->d_maj] = newentry;
11937389Sjulian
12048510Sphk	if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) {
12148936Sphk		if (bmaj2cmaj[newentry->d_bmaj] != 254) {
12248510Sphk			printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n",
12348510Sphk			    newentry->d_name,
12448510Sphk			    cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name);
12548510Sphk		}
12647640Sphk		bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj;
12748510Sphk	}
12847640Sphk
12937389Sjulian	return 0;
13037389Sjulian}
13137389Sjulian
13248211Sgrog/*
13348211Sgrog *  Remove a cdevsw entry
13448211Sgrog */
13548211Sgrog
13636735Sdfrint
13748211Sgrogcdevsw_remove(struct cdevsw *oldentry)
13848211Sgrog{
13948211Sgrog	if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) {
14048211Sgrog		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
14148211Sgrog		    oldentry->d_name, oldentry->d_maj);
14248211Sgrog		return EINVAL;
14348211Sgrog	}
14448211Sgrog
14548211Sgrog	cdevsw[oldentry->d_maj] = NULL;
14648211Sgrog
14748211Sgrog	if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW)
14849504Sgrog		bmaj2cmaj[oldentry->d_bmaj] = 254;
14948211Sgrog
15048211Sgrog	return 0;
15148211Sgrog}
15248211Sgrog
15348211Sgrogint
15446635Sphkdevsw_module_handler(module_t mod, int what, void* arg)
15536735Sdfr{
15646635Sphk	struct devsw_module_data* data = (struct devsw_module_data*) arg;
15748240Sdfr	int error = 0;
15836735Sdfr
15936735Sdfr	switch (what) {
16036735Sdfr	case MOD_LOAD:
16147640Sphk		error = cdevsw_add(data->cdevsw);
16244975Sdfr		if (!error && data->chainevh)
16344975Sdfr			error = data->chainevh(mod, what, data->chainarg);
16444975Sdfr		return error;
16536735Sdfr
16636735Sdfr	case MOD_UNLOAD:
16744975Sdfr		if (data->chainevh) {
16844975Sdfr			error = data->chainevh(mod, what, data->chainarg);
16944975Sdfr			if (error)
17044975Sdfr				return error;
17144975Sdfr		}
17248240Sdfr		cdevsw_remove(data->cdevsw);
17344975Sdfr		return error;
17436735Sdfr	}
17536735Sdfr
17636735Sdfr	if (data->chainevh)
17736735Sdfr		return data->chainevh(mod, what, data->chainarg);
17836735Sdfr	else
17936735Sdfr		return 0;
18036735Sdfr}
18147028Sphk
18247028Sphk/*
18347028Sphk * dev_t and u_dev_t primitives
18447028Sphk */
18547028Sphk
18647028Sphkint
18747028Sphkmajor(dev_t x)
18847028Sphk{
18948936Sphk	if (x == NODEV)
19048936Sphk		return NOUDEV;
19148936Sphk	return((x->si_udev >> 8) & 0xff);
19247028Sphk}
19347028Sphk
19447028Sphkint
19547028Sphkminor(dev_t x)
19647028Sphk{
19748936Sphk	if (x == NODEV)
19848936Sphk		return NOUDEV;
19948936Sphk	return(x->si_udev & 0xffff00ff);
20047028Sphk}
20147028Sphk
20247028Sphkdev_t
20347680Sphkmakebdev(int x, int y)
20447680Sphk{
20548892Sphk	return (makedev(bmaj2cmaj[x], y));
20647680Sphk}
20747680Sphk
20847680Sphkdev_t
20947028Sphkmakedev(int x, int y)
21047028Sphk{
21148936Sphk	struct specinfo *si;
21248936Sphk	udev_t	udev;
21348936Sphk	int hash;
21448936Sphk	static int stashed;
21548936Sphk
21648936Sphk	udev = (x << 8) | y;
21748936Sphk	hash = udev % DEVT_HASH;
21848936Sphk	SLIST_FOREACH(si, &dev_hash[hash], si_hash) {
21948936Sphk		if (si->si_udev == udev)
22048936Sphk			return (si);
22148936Sphk	}
22248936Sphk	if (stashed >= DEVT_STASH) {
22348936Sphk		MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT,
22448936Sphk		    M_USE_RESERVE);
22548936Sphk	} else {
22648936Sphk		si = devt_stash + stashed++;
22748936Sphk	}
22848936Sphk	bzero(si, sizeof(*si));
22948936Sphk	si->si_udev = udev;
23048936Sphk	si->si_bsize_phys = DEV_BSIZE;
23148936Sphk	si->si_bsize_best = BLKDEV_IOSIZE;
23248936Sphk	si->si_bsize_max = MAXBSIZE;
23348936Sphk	SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
23448936Sphk        return (si);
23547028Sphk}
23647028Sphk
23747028Sphkudev_t
23847028Sphkdev2udev(dev_t x)
23947028Sphk{
24048936Sphk	if (x == NODEV)
24148936Sphk		return NOUDEV;
24248936Sphk	return (x->si_udev);
24347028Sphk}
24447028Sphk
24548948Sgreenudev_t
24648948Sgreendev2budev(dev_t x)
24748948Sgreen{
24848949Sgreen	if (x == NODEV)
24948948Sgreen		return NOUDEV;
25048948Sgreen	else
25148948Sgreen		return makeudev(devsw(x)->d_bmaj, minor(x));
25248948Sgreen}
25348948Sgreen
25447028Sphkdev_t
25547028Sphkudev2dev(udev_t x, int b)
25647028Sphk{
25748864Sphk	switch (b) {
25848864Sphk		case 0:
25948864Sphk			return makedev(umajor(x), uminor(x));
26048864Sphk		case 1:
26148864Sphk			return makebdev(umajor(x), uminor(x));
26248864Sphk		default:
26348864Sphk			Debugger("udev2dev(...,X)");
26448864Sphk			return NODEV;
26548864Sphk	}
26647028Sphk}
26747028Sphk
26847028Sphkint
26947028Sphkuminor(udev_t dev)
27047028Sphk{
27147028Sphk	return(dev & 0xffff00ff);
27247028Sphk}
27347028Sphk
27447028Sphkint
27547028Sphkumajor(udev_t dev)
27647028Sphk{
27747028Sphk	return((dev & 0xff00) >> 8);
27847028Sphk}
27947028Sphk
28047028Sphkudev_t
28148859Sphkmakeudev(int x, int y)
28247028Sphk{
28347028Sphk        return ((x << 8) | y);
28447028Sphk}
28547028Sphk
286