Subject: Re: dynamic configuration (was Re: PR#4094)
To: None <soda@sra.co.jp, tech-kern@netbsd.org>
From: Chris Torek <torek@BSDI.COM>
List: tech-kern
Date: 08/21/2000 11:06:15
I would like to recommend (again :-) ) eliminating the distinction
between "bdevsw" and "cdevsw" at the driver level.  In BSD/OS, a
given dev_t can be opened as a "block device" if it has a strategy
routine; otherwise, it is character-only.  All block devices are
also character devices (strict superset), so the only significant
feature of a block device is that it has a function that operates
on a "struct buf *".

Merging the switch tables is also an ideal time for adjusting the
the way bits in a dev_t split up (since you need compat code to handle
the old numbering, and that can map "old block 17, old character 32"
to "new merged 12" or whatever).

Note that this does not affect the drivers themselves in any way --
they still get opened with S_IFBLK or S_IFCHR as usual.  In BSD/OS,
the key code is in spec_open:

	struct devsw *ds;
	...
	if ((u_int)maj >= ndevsw || (ds = devsw[maj]) == NULL)
		return (ENXIO);

	switch (vp->v_type) {

	case VCHR:
		... eventually (if all checks pass) open as character dev:
		error = ds->d_open(dev, mode, S_IFCHR, p);
		...

	case VBLK:
		if (ds->d_strategy == NULL)
			return (ENOTBLK);
		... eventually open as block dev:
		error = ds->d_open(dev, mode, S_IFBLK, p);
		...
	}

The actual "struct devsw" for each device driver should be defined
in that driver's C source file(s).  The lookup table (devsw[]) has
type "array N of pointer to struct devsw", or "pointer to pointer
to struct devsw" if it is dynamically allocated.  (If you want to
make a list of "devsw" structures for other purposes, you could
then eliminate the array, but an array of pointers makes for easy
major-number-to-"devsw *" lookup.)

Chris