summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1998-04-19 23:32:49 +0000
committerjulian <julian@FreeBSD.org>1998-04-19 23:32:49 +0000
commit0796a5c56ed9d1eaf2c8691327b581fcfa3cd05b (patch)
tree9c3ff4ea4ec1cc8aeb30628a4e4452193f1d12cb
parent64e2dfa0bb7dd8d4a7affdfbf920764d02d2b02c (diff)
downloadFreeBSD-src-0796a5c56ed9d1eaf2c8691327b581fcfa3cd05b.zip
FreeBSD-src-0796a5c56ed9d1eaf2c8691327b581fcfa3cd05b.tar.gz
Add changes and code to implement a functional DEVFS.
This code will be turned on with the TWO options DEVFS and SLICE. (see LINT) Two labels PRE_DEVFS_SLICE and POST_DEVFS_SLICE will deliniate these changes. /dev will be automatically mounted by init (thanks phk) on bootup. See /sys/dev/slice/slice.4 for more info. All code should act the same without these options enabled. Mike Smith, Poul Henning Kamp, Soeren, and a few dozen others This code does not support the following: bad144 handling. Persistance. (My head is still hurting from the last time we discussed this) ATAPI flopies are not handled by the SLICE code yet. When this code is running, all major numbers are arbitrary and COULD be dynamically assigned. (this is not done, for POLA only) Minor numbers for disk slices ARE arbitray and dynamically assigned.
-rw-r--r--sys/amd64/amd64/autoconf.c31
-rw-r--r--sys/conf/NOTES6
-rw-r--r--sys/conf/files4
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/dev/fdc/fdc.c286
-rw-r--r--sys/dev/slice/disklabel.c827
-rw-r--r--sys/dev/slice/mbr.c837
-rw-r--r--sys/dev/slice/slice.4152
-rw-r--r--sys/dev/slice/slice.h195
-rw-r--r--sys/dev/slice/slice_base.c671
-rw-r--r--sys/dev/slice/slice_device.c388
-rw-r--r--sys/dev/slice/slices.thought124
-rw-r--r--sys/dev/vn/vn.c349
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c13
-rw-r--r--sys/fs/specfs/spec_vnops.c11
-rw-r--r--sys/i386/conf/LINT6
-rw-r--r--sys/i386/conf/NOTES6
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/i386/i386/autoconf.c31
-rw-r--r--sys/i386/i386/mountroot.c359
-rw-r--r--sys/i386/isa/fd.c286
-rw-r--r--sys/i386/isa/wd.c289
-rw-r--r--sys/isa/fd.c286
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c13
-rw-r--r--sys/kern/init_main.c4
-rw-r--r--sys/kern/subr_diskslice.c5
-rw-r--r--sys/kern/vfs_conf.c7
-rw-r--r--sys/kern/vfs_export.c31
-rw-r--r--sys/kern/vfs_mount.c7
-rw-r--r--sys/kern/vfs_subr.c31
-rw-r--r--sys/miscfs/devfs/devfs_tree.c160
-rw-r--r--sys/miscfs/devfs/devfs_vfsops.c3
-rw-r--r--sys/miscfs/devfs/devfs_vnops.c40
-rw-r--r--sys/miscfs/devfs/devfsdefs.h3
-rw-r--r--sys/miscfs/specfs/spec_vnops.c11
-rw-r--r--sys/miscfs/specfs/specdev.h6
-rw-r--r--sys/scsi/sd.c213
-rw-r--r--sys/sys/devfsext.h32
-rw-r--r--sys/sys/sliceio.h37
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c25
40 files changed, 5588 insertions, 203 deletions
diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c
index 6d96c0c..1aeef1c 100644
--- a/sys/amd64/amd64/autoconf.c
+++ b/sys/amd64/amd64/autoconf.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
- * $Id: autoconf.c,v 1.91 1998/03/16 12:07:54 msmith Exp $
+ * $Id: autoconf.c,v 1.92 1998/03/17 00:28:02 msmith Exp $
*/
/*
@@ -107,6 +107,7 @@ SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
static void configure_finish __P((void));
static void configure_start __P((void));
static int setdumpdev __P((dev_t dev));
+#ifndef SLICE
static void setroot __P((void));
#ifdef CD9660
@@ -135,6 +136,7 @@ static struct {
static int find_cdrom_root __P((void));
+
static int
find_cdrom_root()
{
@@ -170,6 +172,7 @@ find_cdrom_root()
return EINVAL;
}
#endif /* CD9660 */
+#endif /* !SLICE */
static void
configure_start()
@@ -300,6 +303,8 @@ configure(dummy)
cold = 0;
}
+#ifndef SLICE
+
void
cpu_rootconf()
{
@@ -370,6 +375,24 @@ cpu_rootconf()
}
#endif
+#if defined(LFS) || defined(LFS_ROOT)
+ if (!mountrootfsname) {
+ if (bootverbose)
+ printf("Considering LFS root f/s.\n");
+ mountrootfsname = "lfs";
+ /*
+ * Ignore the -a flag if this kernel isn't compiled
+ * with a generic root/swap configuration: if we skip
+ * setroot() and we aren't a generic kernel, chaos
+ * will ensue because setconf() will be a no-op.
+ * (rootdev is always initialized to NODEV in a
+ * generic configuration, so we test for that.)
+ */
+ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
+ setroot();
+ }
+#endif
+
if (!mountrootfsname) {
panic("Nobody wants to mount my root for me");
}
@@ -377,6 +400,8 @@ cpu_rootconf()
setconf();
}
+#endif
+
void
cpu_dumpconf()
{
@@ -420,6 +445,8 @@ setdumpdev(dev)
return (0);
}
+#ifndef SLICE
+
u_long bootdev = 0; /* not a dev_t - encoding is different */
/* Name lookup for bootable majors XXX extend me */
@@ -484,6 +511,8 @@ setroot()
printf("changing root device to %s%s\n", sname, partname);
}
+#endif
+
static int
sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
{
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 21bf3c4..b41d6ac 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.424 1998/04/09 22:28:57 sos Exp $
+# $Id: LINT,v 1.425 1998/04/18 04:58:00 ahasty Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -470,8 +470,10 @@ options UNION #Union filesystem
options "CD9660_ROOT" #CD-ROM usable as root device
options FFS_ROOT #FFS usable as root device
options NFS_ROOT #NFS usable as root device
-# This DEVFS is experimental but seems to work
+# DEVFS and SLICE are experimental but seems to work.
+# SLICE disables too much old code so enabling it in LINT would be bad
options DEVFS #devices filesystem
+#options SLICE #devfs based disk handling
# Allow the FFS to use Softupdates technology.
# To do this you need to fetch the two files
diff --git a/sys/conf/files b/sys/conf/files
index 6f77e75..19dd181 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -53,6 +53,10 @@ dev/ppbus/ppbconf.c optional ppbus
dev/ppbus/ppi.c optional ppi
dev/ppbus/pps.c optional pps
dev/ppbus/vpo.c optional vpo
+dev/slice/slice_base.c optional slice
+dev/slice/slice_device.c optional slice
+dev/slice/mbr.c optional slice
+dev/slice/disklabel.c optional slice
dev/vn/vn.c optional vn
dev/vx/if_vx.c optional vx device-driver
gnu/ext2fs/ext2_alloc.c optional ext2fs
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index a08df9d..f0a9e71 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.195 1998/03/23 16:44:22 peter Exp $
+# $Id: files.i386,v 1.196 1998/04/06 15:49:35 peter Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -36,6 +36,7 @@ i386/eisa/eisaconf.c optional eisa
i386/eisa/if_vx_eisa.c optional vx device-driver
i386/eisa/if_fea.c optional fea device-driver
i386/i386/autoconf.c standard device-driver
+i386/i386/mountroot.c optional slice
i386/i386/bios.c standard
i386/i386/bioscall.s standard
i386/i386/busdma_machdep.c standard
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index d09b927..abc2634 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -43,7 +43,7 @@
* SUCH DAMAGE.
*
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
- * $Id: fd.c,v 1.107 1998/01/24 02:54:18 eivind Exp $
+ * $Id: fd.c,v 1.108 1998/04/17 22:36:31 des Exp $
*
*/
@@ -82,9 +82,13 @@
#include <sys/ftape.h>
#include <i386/isa/ftreg.h>
#endif
-#ifdef DEVFS
+#ifdef DEVFS
#include <sys/devfsext.h>
-#endif
+#ifdef SLICE
+#include <sys/device.h>
+#include <dev/slice/slice.h>
+#endif /* SLICE */
+#endif /* DEVFS */
/* misuse a flag to identify format operation */
#define B_FORMAT B_XXX
@@ -180,8 +184,21 @@ static struct fd_data {
struct callout_handle toffhandle;
struct callout_handle tohandle;
#ifdef DEVFS
+#ifdef SLICE
+ int unit; /* as in fd0 */
+ void *bdevs[MAXPARTITIONS];
+ void *cdevs[MAXPARTITIONS];
+ struct subdev{
+ struct slice *slice;
+ int minor;
+ struct fd_data *drive;
+ struct slicelimits limit;
+ }subdevs[16];
+ struct intr_config_hook ich;
+#else /* SLICE */
void *bdevs[1 + NUMDENS + MAXPARTITIONS];
void *cdevs[1 + NUMDENS + MAXPARTITIONS];
+#endif /* SLICE */
#endif
} fd_data[NFD];
@@ -227,7 +244,9 @@ static timeout_t fd_timeout;
static timeout_t fd_pseudointr;
static int fdstate(fdcu_t, fdc_p);
static int retrier(fdcu_t);
+#ifndef SLICE
static int fdformat(dev_t, struct fd_formb *, struct proc *);
+#endif
static int enable_fifo(fdc_p fdc);
@@ -284,6 +303,7 @@ static d_close_t fdclose;
static d_ioctl_t fdioctl;
static d_strategy_t fdstrategy;
+/* even if SLICE defined, these are needed for the ft support. */
#define CDEV_MAJOR 9
#define BDEV_MAJOR 2
static struct cdevsw fd_cdevsw;
@@ -294,6 +314,30 @@ static struct bdevsw fd_bdevsw =
static struct isa_device *fdcdevs[NFDC];
+#ifdef SLICE
+static sl_h_IO_req_t fdsIOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t fdsioctl; /* ioctl req downward (to device) */
+static sl_h_open_t fdsopen; /* downwards travelling open */
+static sl_h_close_t fdsclose; /* downwards travelling close */
+static void fdsinit(void *);
+
+static struct slice_handler slicetype = {
+ "floppy",
+ 0,
+ NULL,
+ 0,
+ NULL, /* constructor */
+ &fdsIOreq,
+ &fdsioctl,
+ &fdsopen,
+ &fdsclose,
+ NULL, /* revoke */
+ NULL, /* claim */
+ NULL, /* verify */
+ NULL /* upconfig */
+};
+#endif /* SLICE */
+
static int
fdc_err(fdcu_t fdcu, const char *s)
{
@@ -529,8 +573,12 @@ fdattach(struct isa_device *dev)
struct isa_device *fdup;
int ic_type = 0;
#ifdef DEVFS
+#ifdef SLICE
+ char namebuf[64];
+#else
int mynor;
int typemynor;
+#endif /* SLICE */
int typesize;
#endif
@@ -682,6 +730,9 @@ fdattach(struct isa_device *dev)
continue;
fd->track = FD_NO_TRACK;
+#ifdef SLICE
+ fd->unit = fdu;
+#endif
fd->fdc = fdc;
fd->fdsu = fdsu;
fd->options = 0;
@@ -721,6 +772,30 @@ fdattach(struct isa_device *dev)
continue;
}
#ifdef DEVFS
+#ifdef SLICE
+ sprintf(namebuf,"fd%d",fdu);
+ fd->subdevs[0].minor = 0;
+ fd->subdevs[0].drive = fd;
+ fd->subdevs[0].limit.blksize =
+ 128 << (fd_types[fd->type - 1].secsize);
+ fd->subdevs[0].limit.slicesize =
+ fd_types[fd->type - 1].size
+ * fd->subdevs[0].limit.blksize;
+ fd->ft = fd_types + (fd->type - 1); /* default value */
+ sl_make_slice(&slicetype,
+ &fd->subdevs[0],
+ &fd->subdevs[0].limit,
+ &fd->subdevs[0].slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ fd->subdevs[0].slice->probeinfo.typespecific = NULL;
+ fd->subdevs[0].slice->probeinfo.type = NULL;
+
+ fd->ich.ich_func = fdsinit;
+ fd->ich.ich_arg = &fd->subdevs[0];
+ config_intrhook_establish(&fd->ich);
+#else /* SLICE */
mynor = fdu << 6;
fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -728,6 +803,7 @@ fdattach(struct isa_device *dev)
fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR,
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d", fdu);
+#endif /* SLICE */
for (i = 1; i < 1 + NUMDENS; i++) {
/*
* XXX this and the lookup in Fdopen() should be
@@ -755,7 +831,6 @@ fdattach(struct isa_device *dev)
continue;
break;
}
- typemynor = mynor | i;
typesize = fd_types[i - 1].size / 2;
/*
* XXX all these conversions give bloated code and
@@ -765,6 +840,27 @@ fdattach(struct isa_device *dev)
typesize = 1480;
if (typesize == 1722)
typesize = 1720;
+#ifdef SLICE
+ sprintf(namebuf,"fd%d.%d",fdu,typesize);
+ fd->subdevs[i].minor = i;
+ fd->subdevs[i].drive = fd;
+ fd->subdevs[i].limit.blksize =
+ 128 << (fd_types[i - 1].secsize);
+ fd->subdevs[i].limit.slicesize =
+ fd_types[i - 1].size
+ * fd->subdevs[i].limit.blksize;
+ sl_make_slice(&slicetype,
+ &fd->subdevs[i],
+ &fd->subdevs[i].limit,
+ &fd->subdevs[i].slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ fd->subdevs[i].slice->probeinfo.typespecific = NULL;
+ fd->subdevs[i].slice->probeinfo.type = NO_SUBPART;
+ }
+#else /* SLICE */
+ typemynor = mynor | i;
fd->bdevs[i] =
devfs_add_devswf(&fd_bdevsw, typemynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -774,14 +870,15 @@ fdattach(struct isa_device *dev)
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d.%d", fdu, typesize);
}
+
for (i = 0; i < MAXPARTITIONS; i++) {
- fd->bdevs[1 + NUMDENS + i] =
- devfs_link(fd->bdevs[0],
+ fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0],
"fd%d%c", fdu, 'a' + i);
fd->cdevs[1 + NUMDENS + i] =
devfs_link(fd->cdevs[0],
"rfd%d%c", fdu, 'a' + i);
}
+#endif /* SLICE */
#endif /* DEVFS */
#ifdef notyet
if (dk_ndrive < DK_NDRIVE) {
@@ -800,6 +897,22 @@ fdattach(struct isa_device *dev)
return (1);
}
+
+#ifdef SLICE
+
+static void
+fdsinit(void *arg)
+{
+ struct subdev *sd = arg;
+ sh_p tp;
+
+ if ((tp = slice_probeall(sd->slice)) != NULL) {
+ (*tp->constructor)(sd->slice);
+ }
+ config_intrhook_disestablish(&sd->drive->ich);
+}
+#endif /* SLICE */
+
/****************************************************************************/
/* motor control stuff */
/* remember to not deselect the drive we're working on */
@@ -1022,6 +1135,10 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p)
if (type == 0)
type = fd_data[fdu].type;
else {
+ /*
+ * For each type of basic drive, make sure we are trying
+ * to open a type it can do,
+ */
if (type != fd_data[fdu].type) {
switch (fd_data[fdu].type) {
case FD_360:
@@ -1182,6 +1299,49 @@ bad:
biodone(bp);
}
+#ifdef SLICE
+/****************************************************************************/
+/* fdsIOreq */
+/****************************************************************************/
+static void
+fdsIOreq(void *private ,struct buf *bp)
+{
+ unsigned nblocks, blknum, cando;
+ int s;
+ fdcu_t fdcu;
+ fdu_t fdu;
+ fdc_p fdc;
+ fd_p fd;
+ size_t fdblk;
+ struct subdev *sd;
+
+ sd = private;
+ fd = sd->drive;
+ fdu = fd->unit;
+ fdc = fd->fdc;
+ fdcu = fdc->fdcu;
+
+ /* check for controller already busy with tape */
+ if (fdc->flags & FDC_TAPE_BUSY) {
+ bp->b_error = EBUSY;
+ bp->b_flags |= B_ERROR;
+ goto bad;
+ }
+ bp->b_driver1 = sd; /* squirrel away which device.. */
+ bp->b_resid = 0;
+ s = splbio();
+ bufqdisksort(&fdc->head, bp);
+ untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */
+ fdstart(fdcu);
+ splx(s);
+ return;
+
+bad:
+ biodone(bp);
+ return;
+}
+#endif /* SLICE */
+
/***************************************************************\
* fdstart *
* We have just queued something.. if the controller is not busy *
@@ -1292,6 +1452,7 @@ fdintr(fdcu_t fdcu)
static int
fdstate(fdcu_t fdcu, fdc_p fdc)
{
+ struct subdev *sd;
int read, format, head, sec = 0, sectrac, st0, cyl, st3;
unsigned blknum = 0, b_cylinder = 0;
fdu_t fdu = fdc->fdu;
@@ -1317,8 +1478,14 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
TRACE1("[fdc%d IDLE]", fdcu);
return(0);
}
+#ifdef SLICE
+ sd = bp->b_driver1;
+ fd = sd->drive;
+ fdu = fd->unit;
+#else
fdu = FDUNIT(minor(bp->b_dev));
fd = fd_data + fdu;
+#endif
fdblk = 128 << fd->ft->secsize;
if (fdc->fd && (fd != fdc->fd))
{
@@ -1332,7 +1499,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
- (char *)finfo;
}
if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) {
- blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk +
+ blknum = (unsigned) bp->b_pblkno * DEV_BSIZE/fdblk +
fd->skip/fdblk;
b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
}
@@ -1704,13 +1871,26 @@ static int
retrier(fdcu)
fdcu_t fdcu;
{
+ struct subdev *sd;
fdc_p fdc = fdc_data + fdcu;
register struct buf *bp;
+#ifdef SLICE
+ struct fd_data *fd;
+ int fdu;
+#endif
bp = bufq_first(&fdc->head);
+#ifdef SLICE
+ sd = bp->b_driver1;
+ fd = sd->drive;
+ fdu = fd->unit;
+ if(fd->options & FDOPT_NORETRY)
+ goto fail;
+#else
if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY)
goto fail;
+#endif
switch(fdc->retry)
{
case 0: case 1: case 2:
@@ -1727,14 +1907,19 @@ retrier(fdcu)
default:
fail:
{
+#ifdef SLICE
+ printf("fd%d: hard error, block %d ", fdu,
+ fd->skip / DEV_BSIZE);
+#else
dev_t sav_b_dev = bp->b_dev;
/* Trick diskerr */
bp->b_dev = makedev(major(bp->b_dev),
- (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
+ (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
diskerr(bp, "fd", "hard error", LOG_PRINTF,
fdc->fd->skip / DEV_BSIZE,
(struct disklabel *)NULL);
bp->b_dev = sav_b_dev;
+#endif /* !SLICE */
if (fdc->flags & FDC_STAT_VALID)
{
printf(
@@ -1764,11 +1949,16 @@ retrier(fdcu)
return(1);
}
+#ifdef SLICE
+static int
+fdformat( struct subdev *sd, struct fd_formb *finfo, struct proc *p)
+#else /* !SLICE */
static int
fdformat(dev, finfo, p)
dev_t dev;
struct fd_formb *finfo;
struct proc *p;
+#endif /* !SLICE */
{
fdu_t fdu;
fd_p fd;
@@ -1777,8 +1967,13 @@ fdformat(dev, finfo, p)
int rv = 0, s;
size_t fdblk;
- fdu = FDUNIT(minor(dev));
- fd = &fd_data[fdu];
+#ifdef SLICE
+ fd = sd->drive;
+ fdu = fd->unit;
+#else
+ fdu = FDUNIT(minor(dev));
+ fd = &fd_data[fdu];
+#endif
fdblk = 128 << fd->ft->secsize;
/* set up a buffer header for fdstrategy() */
@@ -1792,7 +1987,6 @@ fdformat(dev, finfo, p)
bzero((void *)bp, sizeof(struct buf));
bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
bp->b_proc = p;
- bp->b_dev = dev;
/*
* calculate a fake blkno, so fdstrategy() would initiate a
@@ -1805,7 +1999,13 @@ fdformat(dev, finfo, p)
bp->b_data = (caddr_t)finfo;
/* now do the format */
+#ifdef SLICE
+ bp->b_driver1 = sd;
+ fdsIOreq(sd, bp);
+#else /* !SLICE */
+ bp->b_dev = dev;
fdstrategy(bp);
+#endif /* !SLICE */
/* ...and wait for it to complete */
s = splbio();
@@ -1836,7 +2036,7 @@ fdformat(dev, finfo, p)
* TODO: don't allocate buffer on stack.
*/
-int
+static int
fdioctl(dev, cmd, addr, flag, p)
dev_t dev;
int cmd;
@@ -1861,10 +2061,33 @@ fdioctl(dev, cmd, addr, flag, p)
return ftioctl(dev, cmd, addr, flag, p);
#endif
+#ifdef SLICE
+ /*
+ * if SLICE is defined then only ft accesses come here
+ * so break the rest off to another function for SLICE access.
+ */
+ return (ENOTTY);
+}
+
+/*
+ * Slice ioctls come here
+ */
+static int
+fdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct subdev *sd = private;
+ fd_p fd = sd->drive;
+ fdu_t fdu = fd->unit;
+ fdc_p fdc = fd->fdc;
+ fdcu_t fdcu = fdc->fdcu;
+ size_t fdblk;
+ int error = 0;
+#endif /* SLICE */
fdblk = 128 << fd->ft->secsize;
switch (cmd)
{
+#ifndef SLICE
case DIOCGDINFO:
bzero(buffer, sizeof (buffer));
dl = (struct disklabel *)buffer;
@@ -1908,7 +2131,7 @@ fdioctl(dev, cmd, addr, flag, p)
error = writedisklabel(dev, fdstrategy,
(struct disklabel *)buffer);
break;
-
+#endif /* !SLICE */
case FD_FORM:
if((flag & FWRITE) == 0)
error = EBADF; /* must be opened for writing */
@@ -1916,26 +2139,30 @@ fdioctl(dev, cmd, addr, flag, p)
FD_FORMAT_VERSION)
error = EINVAL; /* wrong version of formatting prog */
else
+#ifdef SLICE
+ error = fdformat(sd, (struct fd_formb *)addr, p);
+#else
error = fdformat(dev, (struct fd_formb *)addr, p);
+#endif
break;
case FD_GTYPE: /* get drive type */
- *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft;
+ *(struct fd_type *)addr = *fd->ft;
break;
case FD_STYPE: /* set drive type */
/* this is considered harmful; only allow for superuser */
if(suser(p->p_ucred, &p->p_acflag) != 0)
return EPERM;
- *fd_data[FDUNIT(minor(dev))].ft = *(struct fd_type *)addr;
+ *fd->ft = *(struct fd_type *)addr;
break;
case FD_GOPTS: /* get drive options */
- *(int *)addr = fd_data[FDUNIT(minor(dev))].options;
+ *(int *)addr = fd->options;
break;
case FD_SOPTS: /* set drive options */
- fd_data[FDUNIT(minor(dev))].options = *(int *)addr;
+ fd->options = *(int *)addr;
break;
default:
@@ -1959,7 +2186,32 @@ static void fd_drvinit(void *notused )
SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL)
+
+#ifdef SLICE
+static int
+fdsopen(void *private, int flags, int mode, struct proc *p)
+{
+ struct subdev *sd;
+
+ sd = private;
+
+ return(Fdopen(makedev(0,sd->minor), 0 , 0, p));
+}
+
+static void
+fdsclose(void *private, int flags, int mode, struct proc *p)
+{
+ struct subdev *sd;
+
+ sd = private;
+
+ fdclose(makedev(0,sd->minor), 0 , 0, p);
+ return ;
+}
+
+#endif /* SLICE */
#endif
+
/*
* Hello emacs, these are the
* Local Variables:
diff --git a/sys/dev/slice/disklabel.c b/sys/dev/slice/disklabel.c
new file mode 100644
index 0000000..cb2119b
--- /dev/null
+++ b/sys/dev/slice/disklabel.c
@@ -0,0 +1,827 @@
+/*-
+ * Copyright (C) 1997,1998 Julian Elischer. All rights reserved.
+ * julian@freebsd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+#include <sys/dkstat.h>
+#include <sys/malloc.h>
+#include <dev/slice/slice.h>
+
+#include <sys/conf.h>
+#include <sys/sliceio.h>
+#include <sys/syslog.h>
+
+
+struct private_data {
+ u_int32_t flags;
+ u_int8_t rflags;
+ u_int8_t wflags;
+ int savedoflags;
+ struct slice *slice_down;
+ struct disklabel disklabel;
+ struct subdev {
+ int part;
+ struct slice *slice;
+ struct slicelimits limit;
+ struct private_data *pd;
+ u_int32_t offset; /* all disklabel supports */
+ } subdevs[MAXPARTITIONS];
+};
+
+static sl_h_constructor_t dkl_constructor; /* constructor (from device) */
+static sl_h_IO_req_t dkl_IOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t dkl_ioctl; /* ioctl req downward (to device) */
+static sl_h_open_t dkl_open; /* downwards travelling open */
+static sl_h_close_t dkl_close; /* downwards travelling close */
+static sl_h_claim_t dkl_claim; /* upwards travelling claim */
+static sl_h_revoke_t dkl_revoke;/* upwards travelling revokation */
+static sl_h_verify_t dkl_verify;/* things changed, are we stil valid? */
+static sl_h_upconfig_t dkl_upconfig;/* config requests from below */
+
+static struct slice_handler slicetype = {
+ "disklabel",
+ 0,
+ NULL,
+ 0,
+ &dkl_constructor, /* constructor */
+ &dkl_IOreq,
+ &dkl_ioctl,
+ &dkl_open,
+ &dkl_close,
+ &dkl_revoke, /* revoke */
+ &dkl_claim, /* claim */
+ &dkl_verify, /* verify */
+ &dkl_upconfig /* subslice manipulation */
+};
+
+static void
+sd_drvinit(void *unused)
+{
+ sl_newtype(&slicetype);
+}
+
+SYSINIT(sddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sd_drvinit, NULL);
+
+/*-
+ * Given a slice, extract out our table of information
+ */
+/*-
+ * Attempt to read a disk label from a slice.
+ * The label must be partly set up before this: secpercyl, secsize
+ * and anything required in the strategy routine (e.g., dummy bounds for the
+ * partition containing the label) must be filled in before calling us.
+ * Returns NULL on success and an error string on failure.
+ */
+static int
+dkl_extract_table(sl_p slice, struct disklabel * lp)
+{
+ int error = EINVAL;
+ struct buf *bp;
+ struct disklabel *dlp;
+ struct partition *dp;
+ int part;
+ int slice_offset; /* XXX */
+
+ RR;
+ /* start off with a known result */
+ bzero(lp, sizeof(*lp));
+ if (error = slice_readblock(slice, LABELSECTOR, &bp))
+ return (error);
+ /*
+ * Step through the block looking for the label.
+ * It may not be at the front (Though I have never seen this).
+ * When found, copy it to the destination supplied.
+ */
+ error = EINVAL;
+ for (dlp = (struct disklabel *) bp->b_data;
+ dlp <= (struct disklabel *) ((char *) bp->b_data
+ + slice->limits.blksize
+ - sizeof(*dlp));
+ dlp = (struct disklabel *) ((char *) dlp + sizeof(long))) {
+ if ((dlp->d_magic != DISKMAGIC) ||
+ (dlp->d_magic2 != DISKMAGIC) ||
+ (dlp->d_npartitions > MAXPARTITIONS) ||
+ dkcksum(dlp))
+ continue;
+ error = 0;
+ bcopy(dlp, lp, sizeof(*lp));
+ /*
+ * disklabels are done relative to the base of the disk,
+ * rather than the local partition, (DUH!)
+ * so use partition 2 (c) to get the base,
+ * and subtract it from all non-0 offsets.
+ */
+ dp = lp->d_partitions;
+ slice_offset = dp[2].p_offset;
+ for (part = 0; part < MAXPARTITIONS; part++, dp++) {
+ /*
+ * We could be reloading, in which case skip
+ * entries already set up.
+ */
+ if (dp->p_size == 0)
+ continue;
+ if( dp->p_offset < slice_offset ) {
+ printf("slice before 'c'\n");
+ dp->p_size = 0;
+ continue;
+ }
+ dp->p_offset -= slice_offset;
+ }
+ break;
+ }
+
+done:
+ bp->b_flags |= B_INVAL | B_AGE;
+ brelse(bp);
+ return (error);
+}
+/*
+ * given a table, write it to disk.
+ */
+static int
+dkl_insert_table(sl_p slice, struct disklabel * lp)
+{
+ int error = EINVAL;
+ struct buf *bp;
+ struct disklabel *dlp;
+ struct partition *dp;
+ int part;
+ int slice_offset; /* XXX */
+
+ RR;
+ /* start off with a known result */
+ if (error = slice_readblock(slice, LABELSECTOR, &bp))
+ return (error);
+ /*
+ * Step through the block looking for the label.
+ * It may not be at the front (Though I have never seen this).
+ * When found, replace it witht he new one.
+ */
+ error = EINVAL;
+ for (dlp = (struct disklabel *) bp->b_data;
+ dlp <= (struct disklabel *) ((char *) bp->b_data
+ + slice->limits.blksize
+ - sizeof(*dlp));
+ dlp = (struct disklabel *) ((char *) dlp + sizeof(long))) {
+ if ((dlp->d_magic != DISKMAGIC) ||
+ (dlp->d_magic2 != DISKMAGIC) ||
+ (dlp->d_npartitions > MAXPARTITIONS) ||
+ dkcksum(dlp))
+ continue;
+ error = 0;
+ }
+ if (error) {
+ /*
+ * We didn't find one..
+ * so clear the block and place the new disklabel
+ * at the start.
+ */
+ bzero(bp->b_data, slice->limits.blksize);
+ dlp = (struct disklabel *) bp->b_data;
+ }
+ /*
+ * old disklabels are done relative to the base of the disk,
+ * rather than the local partition, (DUH!)
+ * so use partition 2 (c) to get the base,
+ * and subtract it from all non-0 offsets.
+ */
+ dp = dlp->d_partitions;
+ slice_offset = dp[2].p_offset;
+ bcopy(lp, dlp, sizeof(*lp));
+ slice_offset -= dp[2].p_offset; /* size we adjust by? */
+ for (part = 0; part < MAXPARTITIONS; part++, dp++) {
+ if (dp->p_size == 0)
+ continue;
+ dp->p_offset += slice_offset;
+ }
+ error = slice_writeblock(slice, LABELSECTOR, bp);
+quit:
+ bp->b_flags |= B_INVAL | B_AGE;
+ brelse(bp);
+ return (error);
+}
+
+
+
+/*-
+ * look at a slice and figure out if we should be interested in it. (Is it
+ * ours?)
+ */
+static int
+dkl_claim(struct slice * slice, struct slice * lower, void *ID)
+{
+ struct disklabel disklabel;
+ struct disklabel *dl, *dl0;
+ int error;
+ RR;
+
+ /*-
+ * Try load a valid disklabel table.
+ * This is 90% of what we need to check.
+ */
+ if ((error = dkl_extract_table(slice, &disklabel)) != 0) {
+ return (error);
+ }
+ /*-
+ * If there is no geometry info, extract it from the label
+ * as some drivers need this.
+ */
+ /* XXX */
+
+ /*-
+ * well, it looks like one of ours.
+ */
+ return (0);
+}
+
+/*-
+ * This is a special HACK function for the IDE driver.
+ * It is here because everything it need is in scope here,
+ * but it is not really part of the SLICE code.
+ * Because old ESDI drives could not tell their geometry, They need
+ * to get it from the MBR or the disklabel. This is the disklabel bit.
+ */
+int
+dkl_geom_hack(struct slice * slice, struct ide_geom *geom)
+{
+ struct disklabel disklabel;
+ struct disklabel *dl, *dl0;
+ int error;
+ RR;
+
+ /* first check it's a disklabel*/
+ if ((error = dkl_claim (slice, NULL, 0)))
+ return (error);
+ /*-
+ * Try load a valid disklabel table.
+ * This is wasteful but never called on new (< 5 YO ) drives.
+ */
+ if ((error = dkl_extract_table(slice, &disklabel)) != 0) {
+ return (error);
+ }
+ geom->secpertrack = disklabel. d_nsectors;
+ geom->trackpercyl = disklabel.d_ntracks;
+ geom->cyls = disklabel.d_ncylinders;
+ return (0);
+}
+
+/*-
+ * look at a slice we know to be ours and decide what the #$%^ to do with it.
+ */
+static int
+dkl_constructor(sl_p slice)
+{
+ int i;
+ u_int64_t disksize = slice->limits.slicesize;
+ struct private_data *pd;
+ struct partition *dp, *dp0;
+ struct disklabel *dl;
+ sh_p tp;
+ char name[64];
+
+ int part;
+ int error = 0;
+ u_long dkl_offset;
+
+ RR;
+ /*-
+ * If we are being called to re-load a slice,
+ * then don't reallocate resources.
+ */
+ if ((pd = slice->private_up) == NULL) {
+ if (slice->name == NULL) {
+ printf("name is NULL\n");
+ return (EINVAL);
+ }
+ if (strlen(slice->name) > 58) {
+ printf("slice: name %s too long\n", slice->name);
+ return (ENAMETOOLONG);
+ }
+ pd = malloc(sizeof(*pd), M_DEVBUF, M_NOWAIT);
+ if (pd == NULL) {
+ printf("fdisk: failed malloc\n");
+ return (ENOMEM);
+ }
+ bzero(pd, sizeof(*pd));
+ pd->slice_down = slice;
+ if ((error = dkl_extract_table(slice, &pd->disklabel)) != 0) {
+ struct partinfo data;
+ /*
+ * If it's just that there is no disklabel there,
+ * Then we fake one up and write it. if this were
+ * not ok, then we would have not been called.
+ * (as probe will have failed). If it's
+ * a physical error, then that's reason to fail.
+ */
+ if (error != EINVAL) {
+ free(pd, M_DEVBUF);
+ return (error);
+ }
+ dkl_dummy_ioctl(slice, DIOCGPART,
+ (caddr_t) &data, 0, NULL);
+ bcopy(data.disklab, &pd->disklabel,
+ sizeof(pd->disklabel));
+ if ((error = dkl_insert_table(slice, &pd->disklabel))) {
+ free(pd, M_DEVBUF);
+ return (error);
+ }
+ }
+ slice->refs++;
+ slice->handler_up = &slicetype;
+ slice->private_up = pd;
+ slicetype.refs++;
+ }
+ dl = &pd->disklabel;
+ dp0 = dl->d_partitions;
+
+ /*-
+ * Handle each of the partitions.
+ * We should check that each makes sence and is legal.
+ * 1/ it should not already have a slice.
+ * 2/ should not be 0 length.
+ * 3/ should not go past end of our slice.
+ * 4/ should not overlap other slices.
+ * It can include sector 0 (unfortunatly)
+ */
+ dp = dp0;
+ for (part = 0; part < MAXPARTITIONS; part++, dp++) {
+ int i;
+ if ( part == 2 )
+ continue; /* XXX skip the 'c' partition */
+ /*
+ * We could be reloading, in which case skip
+ * entries already set up.
+ */
+ if (pd->subdevs[part].slice != NULL)
+ breakout: continue;
+ /*
+ * also skip partitions not present
+ */
+ if (dp->p_size == 0)
+ continue;
+printf(" part %d, start=%d, size=%d\n", part, dp->p_offset, dp->p_size);
+
+ if ((dp->p_offset + dp->p_size) >
+ (slice->limits.slicesize / slice->limits.blksize)) {
+ printf("dkl: slice %d too big ", part);
+ printf("(%x > %x:%x )\n",
+ (dp->p_offset + dp->p_size),
+ (slice->limits.slicesize / slice->limits.blksize) );
+ continue;
+ }
+ /* check for overlaps with existing slices */
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ /*
+ * Don't bother if that slice was not made.
+ * This handles the (i == part) case.
+ */
+ if (pd->subdevs[i].slice == NULL)
+ continue;
+ if ((dp0[i].p_offset < (dp->p_offset + dp->p_size))
+ && ((dp0[i].p_offset + dp0[i].p_size) > dp->p_offset)) {
+ printf("dkl: slice %d overlaps slice %d\n",
+ part, i);
+ goto breakout;
+ }
+ }
+ /*-
+ * the slice seems to make sense. Use it.
+ */
+ pd->subdevs[part].part = part;
+ pd->subdevs[part].pd = pd;
+ pd->subdevs[part].offset = dp->p_offset;
+ pd->subdevs[part].limit.blksize
+ = slice->limits.blksize;
+ pd->subdevs[part].limit.slicesize
+ = (slice->limits.blksize * (u_int64_t)dp->p_size);
+
+ sprintf(name, "%s%c", slice->name, (char )('a' + part));
+ sl_make_slice(&slicetype,
+ &pd->subdevs[part],
+ &pd->subdevs[part].limit,
+ &pd->subdevs[part].slice,
+ NULL,
+ name);
+ pd->subdevs[part].slice->probeinfo.typespecific = &dp->p_fstype;
+ switch (dp->p_fstype) {
+ case FS_UNUSED:
+ /* allow unuseed to be further split */
+ pd->subdevs[part].slice->probeinfo.type = NULL;
+ break;
+ case FS_V6:
+ case FS_V7:
+ case FS_SYSV:
+ case FS_V71K:
+ case FS_V8:
+ case FS_MSDOS:
+ case FS_BSDLFS:
+ case FS_OTHER:
+ case FS_HPFS:
+ case FS_ISO9660:
+ case FS_BOOT :
+#if 0
+ printf("%s: type %d. Leaving\n",
+ pd->subdevs[part].slice->name,
+ (u_int)dp->p_fstype);
+#endif
+ case FS_SWAP:
+ case FS_BSDFFS:
+ pd->subdevs[part].slice->probeinfo.type = NO_SUBPART;
+ break;
+ default:
+ pd->subdevs[part].slice->probeinfo.type = NULL;
+ }
+ /*
+ * Dont allow further breakup of slices that
+ * cover our disklabel
+ */
+ if (dp->p_offset < 16) {
+#if 0
+ printf("%s: covers disklabel. Leaving\n",
+ pd->subdevs[part].slice->name);
+#endif
+ pd->subdevs[part].slice->probeinfo.type = NO_SUBPART;
+ }
+ if ((tp = slice_probeall(pd->subdevs[part].slice)) != NULL) {
+ (*tp->constructor)(pd->subdevs[part].slice);
+ }
+ }
+ return (error);
+}
+
+/*-
+ * look at a slice that USED to be ours.
+ * decide if any sub-slices need to be revoked.
+ * If not then at least ask them to verify themselves.
+ */
+static int
+dkl_verify(sl_p slice)
+{
+ register struct private_data *pd;
+ struct disklabel label;
+ struct partition *dp, *dp2;
+ struct disklabel *dl;
+ int part;
+ int error;
+ /* register struct slice *slice; */
+
+ RR;
+ pd = slice->private_up;
+ /* slice = pd->slice_down; */
+ bzero(&label, sizeof(label));
+ /*
+ * Try load a valid disklabel. This is 90% of what we need to check.
+ */
+ if (((error = dkl_extract_table(slice, &label)) != 0)
+ || (slice->limits.blksize != 512)) {
+ /*-
+ * Oh oh, we need to invalidate all the subslices.
+ * and relinquish this slice.
+ */
+ return (dkl_revoke(pd));
+ }
+ dl = &(pd->disklabel);
+ dp = dl->d_partitions;
+ dp2 = label.d_partitions;
+ for (part = 0; part < MAXPARTITIONS; part++, dp++, dp2++) {
+ if (pd->subdevs[part].slice) {
+ if ((dp2->p_offset != dp->p_offset)
+ || (dp2->p_size != dp->p_size)) {
+ sl_rmslice(pd->subdevs[part].slice);
+ pd->subdevs[part].slice = NULL;
+ } else if (pd->subdevs[part].slice->handler_up) {
+ (*pd->subdevs[part].slice->handler_up->verify)
+ (pd->subdevs[part].slice);
+ }
+ }
+ }
+ /*- having got rid of changing slices, replace
+ * the old table with the new one, and
+ * handle any new slices by calling the constructor.
+ */
+ bcopy(&label, dl, sizeof(label));
+ error = dkl_constructor(slice);
+done:
+ return (error);
+}
+
+/*-
+ * Invalidate all subslices, and free resources for this handler instance.
+ */
+static int
+dkl_revoke(void *private)
+{
+ register struct private_data *pd;
+ register struct slice *slice;
+ int part;
+
+ RR;
+ pd = private;
+ slice = pd->slice_down;
+ for (part = 0; part < MAXPARTITIONS; part++) {
+ if (pd->subdevs[part].slice) {
+ sl_rmslice(pd->subdevs[part].slice);
+ }
+ }
+ /*-
+ * remove ourself as a handler
+ */
+ slice->handler_up = NULL;
+ slice->private_up = NULL;
+ slicetype.refs--;
+ free(pd, M_DEVBUF);
+ sl_unref(slice);
+ return (0);
+}
+
+/*-
+ * shift the appropriate IO by the offset for that slice.
+ */
+static void
+dkl_IOreq(void *private, struct buf * bp)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+
+RR;
+ sdp = private;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+ bp->b_pblkno += sdp->offset; /* add the offset for that slice */
+ sliceio(slice, bp, SLW_ABOVE);
+}
+
+/*
+ * shift the appropriate IO by the offset for that slice.
+ */
+static void
+mbr_IOreq(void *private, struct buf * bp)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+
+RR;
+ sdp = private;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+ bp->b_pblkno += sdp->offset; /* add the offset for that slice */
+ sliceio(slice, bp, SLW_ABOVE);
+}
+
+static int
+dkl_open(void *private, int flags, int mode, struct proc * p)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+ int error;
+ u_int8_t newrflags = 0;
+ u_int8_t newwflags = 0;
+ int newoflags;
+ int part;
+ u_int8_t partbit;
+
+RR;
+ sdp = private;
+ part = sdp->part;
+ partbit = (1 << part);
+ pd = sdp->pd;
+ slice = pd->slice_down;
+
+ /*
+ * Calculate the change to to over-all picture here.
+ * Notice that this might result in LESS open bits
+ * if that was what was passed from above.
+ * (Prelude to 'mode-change' instead of open/close.)
+ */
+ /* work out what our stored flags will be if this succeeds */
+ newwflags &= ~ (partbit);
+ newrflags &= ~ (partbit);
+ newwflags |= (flags & FWRITE) ? (partbit) : 0;
+ newrflags |= (flags & FREAD) ? (partbit) : 0;
+
+ /* work out what we want to pass down this time */
+ newoflags = newwflags ? FWRITE : 0;
+ newoflags |= newrflags ? FREAD : 0;
+
+ /*
+ * If the agregate flags we used last time are the same as
+ * the agregate flags we would use this time, then don't
+ * bother re-doing the command.
+ */
+ if (newoflags != pd->savedoflags) {
+ if (error = sliceopen(slice, newoflags, mode, p, SLW_ABOVE)) {
+ return (error);
+ }
+ }
+
+ /*
+ * Now that we know it succeeded, commit, by replacing the old
+ * flags with the new ones.
+ */
+ pd->rflags = newrflags;
+ pd->wflags = newwflags;
+ pd->savedoflags = newoflags;
+ return (0);
+}
+
+static void
+dkl_close(void *private, int flags, int mode, struct proc * p)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+ u_int8_t newrflags = 0;
+ u_int8_t newwflags = 0;
+ int newoflags;
+ int part;
+ u_int8_t partbit;
+
+RR;
+ sdp = private;
+ part = sdp->part;
+ partbit = (1 << part);
+ pd = sdp->pd;
+ slice = pd->slice_down;
+
+ if ((pd->rflags == 0) && (pd->wflags == 0))
+ return;
+
+ /* work out what our stored flags will be if this succeeds */
+ newwflags &= ~ (partbit);
+ newrflags &= ~ (partbit);
+ newwflags |= (flags & FWRITE) ? (partbit) : 0;
+ newrflags |= (flags & FREAD) ? (partbit) : 0;
+
+ /* work out what we want to pass down this time */
+ newoflags = newwflags ? FWRITE : 0;
+ newoflags |= newrflags ? FREAD : 0;
+
+ /*
+ * If this was the last open slice above, then release our own open
+ */
+ if ((pd->rflags == 0) && (pd->wflags == 0)) {
+ sliceclose(slice, newoflags, mode, p, SLW_ABOVE);
+ }
+ pd->rflags = newrflags;
+ pd->wflags = newwflags;
+ pd->savedoflags = newoflags;
+ return ;
+}
+
+static int
+dkl_ioctl(void *private, int cmd, caddr_t addr, int flag, struct proc * p)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+ struct disklabel *lp;
+ int error;
+
+ RR;
+ sdp = private;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+ lp = &pd->disklabel;
+ switch (cmd) {
+ case DIOCGDINFO:
+ *(struct disklabel *)addr = *lp;
+ return (0);
+
+ case DIOCGPART:
+ if (lp == NULL)
+ return (EINVAL);
+ ((struct partinfo *)addr)->disklab = lp;
+ ((struct partinfo *)addr)->part = lp->d_partitions + sdp->part;
+ return (0);
+
+/* These don't really make sense. keep the headers for a reminder */
+ case DIOCSDINFO:
+ case DIOCSYNCSLICEINFO:
+ case DIOCWDINFO:
+ case DIOCWLABEL:
+ return (ENOIOCTL);
+ }
+
+ return ((*slice->handler_down->ioctl) (slice->private_down,
+ cmd, addr, flag, p));
+}
+
+static int
+dkl_upconfig(struct slice *slice, int cmd, caddr_t addr, int flag, struct proc * p)
+{
+ RR;
+ switch (cmd) {
+ case SLCIOCRESET:
+ return (0);
+
+/* These don't really make sense. keep the headers for a reminder */
+ default:
+ return (ENOIOCTL);
+ }
+ return (0);
+}
+
+static struct disklabel static_label;
+/*
+ * This is a hack routine called from the slice generic code to produce a dummy
+ * disklabel when given a slice descriptor. It's in here because this code
+ * knows about disklabels.
+ */
+int
+dkl_dummy_ioctl(struct slice *slice, int cmd, caddr_t addr,
+ int flag, struct proc * p)
+{
+ struct disklabel *lp = &static_label;
+
+ switch (cmd) {
+ case DIOCGDINFO:
+ case DIOCGPART:
+ bzero(lp, sizeof(static_label));
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_secsize = slice->limits.blksize;
+ lp->d_nsectors = 1;
+ lp->d_ntracks = 1;
+ lp->d_secpercyl = 1;
+ lp->d_ncylinders =
+ lp->d_secperunit = slice->limits.slicesize
+ / slice->limits.blksize;
+ lp->d_npartitions = RAW_PART + 1;
+ lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
+ lp->d_partitions[RAW_PART].p_offset = 0;
+ break;
+ default:
+ return (ENOIOCTL);
+ }
+ lp->d_checksum = dkcksum(lp);
+
+ switch (cmd) {
+ case DIOCGDINFO:
+ *(struct disklabel *)addr = *lp;
+ break;
+ case DIOCGPART:
+ /* XXX hack alert.
+ * This is a hack as this information is consumed immediatly
+ * otherwise the use of a static buffer would be dangerous.
+ */
+ ((struct partinfo *)addr)->disklab = lp;
+ ((struct partinfo *)addr)->part = lp->d_partitions + RAW_PART;
+ }
+
+ return (0);
+
+}
+
+#if 0 /* use the existing one for now */
+/*-
+ * Compute checksum for disk label.
+ */
+u_int
+dkcksum(lp)
+ register struct disklabel *lp;
+{
+ register u_short *start, *end;
+ register u_short sum = 0;
+
+ start = (u_short *) lp;
+ end = (u_short *) & lp->d_partitions[lp->d_npartitions];
+ while (start < end)
+ sum ^= *start++;
+ return (sum);
+}
+#endif /* 0 */
+
diff --git a/sys/dev/slice/mbr.c b/sys/dev/slice/mbr.c
new file mode 100644
index 0000000..7babfc9
--- /dev/null
+++ b/sys/dev/slice/mbr.c
@@ -0,0 +1,837 @@
+/*-
+ * Copyright (C) 1997,1998 Julian Elischer. All rights reserved.
+ * julian@freebsd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/malloc.h>
+#include <sys/sliceio.h>
+#include <dev/slice/slice.h>
+
+
+struct private_data {
+ u_int32_t flags;
+ struct slice *slice_down;
+ int savedoflags;
+ struct dos_partition dos_table[NDOSPART];
+ struct subdev {
+ int part;
+ struct slice *slice;
+ struct slicelimits limit;
+ struct private_data *pd;
+ u_int32_t offset; /* Fdisk only has 32 bits */
+ } subdevs[NDOSPART];
+};
+/*
+ * Bits in the mbr private data flag word
+ */
+#define MBRF_OPEN_RBIT 0x01
+#define MBRF_S1_OPEN_RD 0x01
+#define MBRF_S2_OPEN_RD 0x02
+#define MBRF_S3_OPEN_RD 0x04
+#define MBRF_S4_OPEN_RD 0x08
+#define MBRF_MSK_RD 0x0F
+#define MBRF_OPEN_WBIT 0x10
+#define MBRF_S1_OPEN_WR 0x10
+#define MBRF_S2_OPEN_WR 0x20
+#define MBRF_S3_OPEN_WR 0x40
+#define MBRF_S4_OPEN_WR 0x80
+#define MBRF_MSK_WR 0xF0
+#define MBRF_MSK_OPEN 0xFF
+
+static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ {0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000,},
+};
+#define DOSPTYP_ONTRACK 84
+
+static sl_h_constructor_t mbr_constructor; /* constructor (from device) */
+static sl_h_IO_req_t mbr_IOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t mbr_ioctl; /* ioctl req downward (to device) */
+static sl_h_open_t mbr_open; /* downwards travelling open */
+static sl_h_close_t mbr_close; /* downwards travelling close */
+static sl_h_claim_t mbr_claim; /* upwards travelling claim */
+static sl_h_revoke_t mbr_revoke;/* upwards travelling revokation */
+static sl_h_verify_t mbr_verify;/* things changed, are we stil valid? */
+static sl_h_upconfig_t mbr_upconfig;/* config request from below */
+
+static struct slice_handler slicetype = {
+ "MBR",
+ 0,
+ NULL,
+ 0,
+ &mbr_constructor, /* constructor */
+ &mbr_IOreq,
+ &mbr_ioctl,
+ &mbr_open,
+ &mbr_close,
+ &mbr_revoke, /* revoke */
+ &mbr_claim, /* claim */
+ &mbr_verify, /* verify */
+ &mbr_upconfig /* config from below */
+};
+
+static void
+sd_drvinit(void *unused)
+{
+ sl_newtype(&slicetype);
+}
+
+SYSINIT(sddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sd_drvinit, NULL);
+
+/*
+ * Given a slice, extract out our table of information
+ */
+static int
+mbr_find_table(sl_p slice, struct buf **bpp, int *blknum)
+{
+ int ontrack_offset = 0;
+ int error;
+ u_int8_t *cp;
+ struct dos_partition *dp0, *dp;
+ int part;
+ int redone = 0;
+ struct buf *bp;
+
+RR;
+ *bpp = NULL;
+reread:
+ if (error = slice_readblock(slice, ontrack_offset, &bp))
+ return (error);
+ cp = bp->b_data;
+ if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
+ error = EINVAL;
+ goto done;
+ }
+ dp0 = (struct dos_partition *) (cp + DOSPARTOFF);
+
+ /*
+ * Check for "Ontrack Diskmanager". Note that if the geometry is
+ * still needed then we probably won't be able to read a DiskManager
+ * MBR because we will fail to read sector 63. The very act of
+ * finding a Disk Manager might however have given us the info we
+ * need if the disk manager set's its partition up correctly.
+ */
+ if (!redone) {
+ for (part = 0, dp = dp0;
+ part < NDOSPART; part++, dp++) {
+ if (dp->dp_typ == DOSPTYP_ONTRACK) {
+#ifdef MAYBE
+ /*
+ * It's not known if this should always 63 or
+ * if this is just the start of the 2nd
+ * track.
+ */
+ ontrack_offset = dp->dp_start;
+#else
+ ontrack_offset = 63;
+#endif
+ if (bootverbose)
+ printf("Found \"Ontrack Disk Manager\"\n");
+ bp->b_flags |= B_INVAL | B_AGE;
+ brelse(bp);
+ redone++;
+ goto reread;
+ }
+ }
+ }
+done:
+ if (blknum)
+ *blknum = ontrack_offset;
+ *bpp = bp;
+ return (error);
+}
+
+/*
+ * Given a slice, extract out our table of information
+ */
+static int
+mbr_extract_table(sl_p slice, struct dos_partition *table)
+{
+ int error;
+ struct buf *bp;
+
+RR;
+ /* start off with a known result */
+ bzero(table, sizeof(*table) * NDOSPART);
+ error = mbr_find_table(slice, &bp, NULL);
+ if (!error)
+ bcopy((bp->b_data + DOSPARTOFF), table,
+ sizeof(*table) * NDOSPART);
+done:
+ if (bp) {
+ bp->b_flags |= B_INVAL | B_AGE;
+ brelse(bp);
+ }
+ return (error);
+}
+
+/*
+ * read the block and replace the mbr table with that given.
+ * If there isn't one, clear the rest of the block.
+ */
+static int
+mbr_insert_table(sl_p slice, struct dos_partition *table)
+{
+ int blknum = 0;
+ int error;
+ struct buf *bp;
+
+RR;
+ error = mbr_find_table(slice, &bp, &blknum);
+ if ( error == EINVAL) {
+ /*
+ * The block was read, but there was no table there.
+ * just clear out the cruft for now.
+ */
+ bzero(bp->b_data, slice->limits.blksize);
+ } else if (error == 0) {
+ bcopy( table, (bp->b_data + DOSPARTOFF),
+ sizeof(*table) * NDOSPART);
+ bp->b_data[0x1FE] = 0x55;
+ bp->b_data[0x1FF] = 0xAA;
+ /* XXX Somehow we should get boot code in there too. */
+ /* for now leave it to the tool */
+ error = slice_writeblock(slice, blknum, bp);
+ }
+done:
+ if (bp) {
+ bp->b_flags |= B_INVAL | B_AGE;
+ brelse(bp);
+ }
+ return (error);
+}
+
+/*
+ * look at a slice and figure out if we should be interested in it. (Is it
+ * ours?)
+ */
+static int
+mbr_claim(struct slice * slice, struct slice * lower, void *ID)
+{
+ struct dos_partition table[NDOSPART];
+ struct dos_partition *dp, *dp0;
+ int part;
+ int error;
+ int max_ncyls;
+ int max_nsectors;
+ int max_ntracks;
+ u_int32_t secpercyl;
+ int numactive = 0;
+RR;
+
+ /*
+ * Don't even BOTHER if it's not 512 byte sectors
+ */
+ if (slice->limits.blksize != 512)
+ return (EINVAL);
+ /*
+ * Try load a valid MBR table. This is 90% of what we need to check.
+ */
+ if ((error = mbr_extract_table(slice, table)) != 0) {
+ return (error);
+ }
+ dp0 = table;
+ /*
+ * The first block of the dos code is marked like a valid MBR.
+ * Try to distinguish this case byt doing a sanity check on the table.
+ * Check:
+ * Flag byte can only be 0 or 0x80.
+ * At most one active partition.
+ * -Other tests to be added here-
+ */
+ for (part = 0, dp = dp0; part < NDOSPART; part++, dp++) {
+ if (dp->dp_flag & 0x7f) {
+ printf ("rejected.. bad flag ");
+ return(EINVAL); /* must be either 0 or 0x80 */
+ }
+ if ((dp->dp_typ) && (dp->dp_size) && (dp->dp_start == 0)) {
+ printf("rejected.. Slice includes MBR ");
+ return (EINVAL);
+ }
+ if (dp->dp_flag == 0x80)
+ numactive++;
+ }
+ if (numactive > 1) {
+ printf ("rejected.. multiple active ");
+ return (EINVAL);
+ }
+ /*
+ * If it's the MBR that comes with the disklabel then we should just
+ * give up and let the disklabel handler take control of this slice.
+ */
+ if (bcmp(dp0, historical_bogus_partition_table,
+ sizeof historical_bogus_partition_table) == 0) {
+ printf("rejecting disklabel table ");
+ return (EINVAL);
+ }
+ /*
+ * well, it looks like one of ours.
+ */
+ return (0);
+}
+
+/*
+ * This routine tries to guess the geometry for
+ * old disk drivers that need the MBR code to set it. Bits taken from
+ * diskslice_machdep.c which itself evolved from earlier code.
+ * This is not part of the SLICE code per-se, but just a convenient place to
+ * put this HACK because everything is in scope. Only called by the IDE driver.
+ */
+int
+mbr_geom_hack(struct slice * slice, struct ide_geom *geom)
+{
+ struct dos_partition table[NDOSPART];
+ struct dos_partition *dp, *dp0;
+ int part;
+ int error;
+ int max_ncyls;
+ int max_nsectors;
+ int max_ntracks;
+ u_int32_t secpercyl;
+RR;
+
+ /*
+ * Don't even BOTHER if it's not claimable by us.
+ */
+ if ((error = mbr_claim(slice,NULL,0)))
+ return (error);
+ /*
+ * Load the mbr.
+ */
+ if ((error = mbr_extract_table(slice, table)) != 0) {
+ return (error);
+ }
+ dp0 = table;
+ /*
+ * Guess the geometry. For some old drives (ESDI, st506) the
+ * driver below us may not yet know the geometry, but needs
+ * to before it can access blocks out of the first track.
+ * This hack is to use information in the MBR to "deduce"
+ * this information and pass it back.
+ */
+ max_ncyls = 0;
+ max_nsectors = 0;
+ max_ntracks = 0;
+ for (part = 0, dp = dp0; part < NDOSPART; part++, dp++) {
+ int ncyls;
+ int nsectors;
+ int ntracks;
+
+ if (dp->dp_size == 0)
+ continue;
+ ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
+ if (max_ncyls < ncyls)
+ max_ncyls = ncyls;
+ nsectors = DPSECT(dp->dp_esect);
+ if (max_nsectors < nsectors)
+ max_nsectors = nsectors;
+ ntracks = dp->dp_ehd + 1;
+ if (max_ntracks < ntracks)
+ max_ntracks = ntracks;
+ }
+ if ((max_ncyls == 0)
+ && (max_nsectors == 0)
+ && (max_ntracks == 0)) {
+ /* we've gained nought, so just return */
+ return (EINVAL);
+ }
+ secpercyl = (u_long) max_nsectors *max_ntracks;
+ printf("s=%d, h=%d, c=%d\n", max_nsectors, max_ntracks, max_ncyls);
+ /*
+ * Check that we have guessed the geometry right by checking
+ * the partition entries.
+ */
+ error = 0;
+ for (part = 0, dp = dp0; part < NDOSPART; part++, dp++) {
+ int cyl;
+ int sector;
+ int track;
+ int secpercyl;
+
+ if (dp->dp_size == 0)
+ continue;
+ cyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
+ track = dp->dp_shd;
+ sector = DPSECT(dp->dp_ssect) - 1;
+ secpercyl = max_nsectors * max_ntracks;
+ /*
+ * If the geometry doesn't work for any partition
+ * start then don't accept it.
+ */
+ if (((((dp->dp_start / secpercyl) % 1024) != cyl)
+ && (cyl != 1023))
+ || (((dp->dp_start % secpercyl)
+ / max_nsectors) != track)
+ || (((dp->dp_start % secpercyl)
+ % max_nsectors) != sector)) {
+ printf("Can't get disk geometry from MBR\n");
+ return (EINVAL);
+ }
+ if ((dp->dp_start / secpercyl) > 1023) {
+ printf("part %d above BIOS reach\n", part);
+ }
+ }
+
+ /*
+ * Set our newely hypothesised numbers into the geometry
+ * slots in the supplied SLICE.
+ */
+ geom->secpertrack = max_nsectors;
+ geom->trackpercyl = max_ntracks;
+ geom->cyls = max_ncyls;
+ return (0);
+}
+
+/*
+ * look at a slice we know to be ours and decide what the #$%^ to do with it.
+ * We presume the driver already did the geometry hack if needed.
+ */
+static int
+mbr_constructor(sl_p slice)
+{
+ int i;
+ u_int64_t disksize = slice->limits.slicesize;
+ struct private_data *pd;
+ struct dos_partition *dp, *dp0;
+ int redone = 0;
+ int ontrack_offset = 0;
+ char name[64];
+ sh_p tp;
+
+ int part;
+ int error = 0;
+
+RR;
+ /*
+ * If we are being called to re-load a slice,
+ * then don't reallocate resources.
+ */
+ if ( (pd = slice->private_up) == NULL) {
+ if (slice->name == NULL) {
+ printf("name is NULL\n");
+ return (EINVAL);
+ }
+ if (strlen(slice->name) > 58) {
+ printf("slice: name %s too long\n", slice->name);
+ return (ENAMETOOLONG);
+ }
+ pd = malloc(sizeof(*pd), M_DEVBUF, M_NOWAIT);
+ if (pd == NULL) {
+ printf("fdisk: failed malloc\n");
+ return (ENOMEM);
+ }
+ bzero(pd, sizeof(*pd));
+ pd->slice_down = slice;
+ if ((error = mbr_extract_table(slice, pd->dos_table)) != 0) {
+ /*
+ * If it's just that there is no table there,
+ * Then we fake an empty one up and write it. if
+ * this were not ok, then we would have not been
+ * called. (as probe will have failed). If it's
+ * a physical error, then that's reason to fail.
+ */
+ if (error != EINVAL) {
+ free(pd, M_DEVBUF);
+ return (error);
+ }
+ bzero(pd->dos_table, sizeof(pd->dos_table));
+ if ((error = mbr_insert_table(slice, pd->dos_table))) {
+ free(pd, M_DEVBUF);
+ return (error);
+ }
+
+ }
+ slice->refs++;
+ slice->handler_up = &slicetype;
+ slice->private_up = pd;
+ slicetype.refs++;
+ }
+
+ dp0 = pd->dos_table;
+
+ /*
+ * Handle each of the partitions.
+ * We should check that each makes sence and is legal.
+ * 1/ it should not already have a slice.
+ * 2/ should not be 0 length.
+ * 3/ should not go past end of our slice.
+ * 4/ should not include sector 0.
+ * 5/ should not overlap other slices.
+ */
+ dp = dp0;
+ for (part = 0; part < NDOSPART; part++, dp++) {
+ int i;
+ if (pd->subdevs[part].slice != NULL)
+breakout: continue;
+ if (dp->dp_size == 0)
+ continue;
+ if (dp->dp_start < 1)
+ continue;
+ if ((dp->dp_start + dp->dp_size) >
+ (slice->limits.slicesize/slice->limits.blksize))
+ continue;
+ /* check for overlaps with existing slices */
+ for (i = 0; i < NDOSPART; i++) {
+ /* skip empty slots (including this one) */
+ if(pd->subdevs[i].slice == NULL )
+ continue;
+ if ((dp0[i].dp_start < (dp->dp_start + dp->dp_size))
+ && ((dp0[i].dp_start + dp0[i].dp_size) > dp->dp_start))
+ {
+ printf("mbr: new slice %d overlaps slice %d\n",
+ part, i);
+ goto breakout;
+ }
+ }
+ /*
+ * the slice seems to make sense. Use it.
+ */
+ pd->subdevs[part].part = part;
+ pd->subdevs[part].pd = pd;
+ pd->subdevs[part].offset = dp->dp_start;
+ pd->subdevs[part].limit.blksize
+ = slice->limits.blksize;
+ pd->subdevs[part].limit.slicesize
+ = (slice->limits.blksize * (u_int64_t)dp->dp_size);
+
+ sprintf(name, "%ss%d", slice->name, part + 1);
+ sl_make_slice(&slicetype,
+ &pd->subdevs[part],
+ &pd->subdevs[part].limit,
+ &pd->subdevs[part].slice,
+ NULL,
+ name);
+ pd->subdevs[part].slice->probeinfo.typespecific = &dp->dp_typ;
+ switch (dp->dp_typ) { /* list stolen from fdisk */
+ case 0x00: /* "unused" */
+ case 0x01: /* "Primary DOS with 12 bit FAT" */
+ case 0x02: /* "XENIX / filesystem" */
+ case 0x03: /* "XENIX /usr filesystem" */
+ case 0x04: /* "Primary DOS with 16 bit FAT" */
+ case 0x05: /* "Extended DOS" */
+ case 0x06: /* "Primary 'big' DOS (> 32MB)" */
+ case 0x07: /* "OS/2 HPFS, QNX or Advanced UNIX" */
+ case 0x08: /* "AIX filesystem" */
+ case 0x09: /* "AIX boot partition or Coherent" */
+ case 0x0A: /* "OS/2 Boot Manager or OPUS" */
+ case 0x10: /* "OPUS" */
+ case 0x40: /* "VENIX 286" */
+ case 0x50: /* "DM" */
+ case 0x51: /* "DM" */
+ case 0x52: /* "CP/M or Microport SysV/AT" */
+ case 0x56: /* "GB" */
+ case 0x61: /* "Speed" */
+ case 0x63: /* "ISC UNIX, System V/386, GNU HURD or Mach" */
+ case 0x64: /* "Novell Netware 2.xx" */
+ case 0x65: /* "Novell Netware 3.xx" */
+ case 0x75: /* "PCIX" */
+ case 0x80: /* "Minix 1.1 ... 1.4a" */
+ case 0x81: /* "Minix 1.4b ... 1.5.10" */
+ case 0x82: /* "Linux swap" */
+ case 0x83: /* "Linux filesystem" */
+ case 0x93: /* "Amoeba filesystem" */
+ case 0x94: /* "Amoeba bad block table" */
+ case 0xA6: /* "OpenBSD" */
+ case 0xA7: /* "NEXTSTEP" */
+ case 0xB7: /* "BSDI BSD/386 filesystem" */
+ case 0xB8: /* "BSDI BSD/386 swap" */
+ case 0xDB: /* "Concurrent CPM or C.DOS or CTOS" */
+ case 0xE1: /* "Speed" */
+ case 0xE3: /* "Speed" */
+ case 0xE4: /* "Speed" */
+ case 0xF1: /* "Speed" */
+ case 0xF2: /* "DOS 3.3+ Secondary" */
+ case 0xF4: /* "Speed" */
+ case 0xFF: /* "BBT (Bad Blocks Table)" */
+ printf("%s: type %d. Leaving\n",
+ pd->subdevs[part].slice->name,
+ (u_int)dp->dp_typ);
+ pd->subdevs[part].slice->probeinfo.type = NO_SUBPART;
+ break;
+ case DOSPTYP_386BSD: /* 0xA5 "FreeBSD/NetBSD/386BSD" */
+ pd->subdevs[part].slice->probeinfo.type = "disklabel";
+ break;
+ default:
+ pd->subdevs[part].slice->probeinfo.type = NULL;
+ }
+ if ((tp = slice_probeall(pd->subdevs[part].slice)) != NULL) {
+ (*tp->constructor)(pd->subdevs[part].slice);
+ }
+ }
+ return (error);
+}
+
+/*
+ * look at a slice that USED to be ours.
+ * decide if any sub-slices need to be revoked.
+ * If not then at least ask them to verify themselves.
+ * Note, arg 'slice' is not strictly needed
+ */
+static int
+mbr_verify(sl_p slice)
+{
+ register struct private_data *pd;
+ struct dos_partition table[NDOSPART];
+ struct dos_partition *dp, *dp0;
+ int part;
+ int error;
+ /* register struct slice *slice; */
+
+RR;
+ pd = slice->private_up;
+ /* slice = pd->slice_down; */
+ bzero(table, sizeof(table));
+ /*
+ * Try load a valid MBR table. This is 90% of what we need to check.
+ */
+ if ((slice->limits.blksize != 512)
+ || ((error = mbr_extract_table(slice, table)) != 0)) {
+ /*
+ * Oh oh, we need to invalidate all the subslices.
+ * and relinquish this slice.
+ */
+ return(mbr_revoke(pd));
+ }
+ /*
+ * For each existing subslice, check that the basic size
+ * and position has not changed. Also check the TYPE.
+ * It is possible we should allow a slice to grow.
+ */
+ dp = dp0 = pd->dos_table;
+ for (part = 0, dp = dp0; part < NDOSPART; part++, dp++) {
+ if (pd->subdevs[part].slice) {
+ if ((table[part].dp_start != dp->dp_start)
+ || (table[part].dp_size != dp->dp_size)
+ || (table[part].dp_typ != dp->dp_typ) ) {
+ sl_rmslice(pd->subdevs[part].slice);
+ pd->subdevs[part].slice = NULL;
+ } else if ( pd->subdevs[part].slice->handler_up) {
+ (*pd->subdevs[part].slice->handler_up->verify)
+ (pd->subdevs[part].slice);
+ }
+ }
+ }
+ /*
+ * Having got rid of changing slices, replace
+ * the old table with the new one, and
+ * Handle any new slices by calling the constructor.
+ * This way, if we are in 'promiscuous' mode,
+ * (e.g. repartitionning a disk we are running on from
+ * Single user mode, the unchanged slices can remain open and active
+ * through the process. If you change an open slice,
+ * the vnodes will be changed to deadfs so a crash is probably
+ * nearby. XXX too late. It's written to disk.. (we COULD reverse it,
+ * but....)
+ */
+ bcopy( table, dp0, sizeof(table));
+ error = mbr_constructor(slice);
+ return (error);
+}
+
+/*
+ * Invalidate all subslices, and free resources for this handler instance.
+ */
+static int
+mbr_revoke(void *private)
+{
+ register struct private_data *pd;
+ register struct slice *slice;
+ int part;
+
+RR;
+ pd = private;
+ slice = pd->slice_down;
+ for (part = 0; part < NDOSPART; part++) {
+ if (pd->subdevs[part].slice) {
+ sl_rmslice(pd->subdevs[part].slice);
+ }
+ }
+ /*
+ * remove ourself as a handler
+ */
+ slice->handler_up = NULL;
+ slice->private_up = NULL;
+ slicetype.refs--;
+ free(pd,M_DEVBUF);
+ sl_unref(slice);
+ return (0);
+}
+
+/*
+ * shift the appropriate IO by the offset for that slice.
+ */
+static void
+mbr_IOreq(void *private, struct buf * bp)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+
+RR;
+ sdp = private;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+ bp->b_pblkno += sdp->offset; /* add the offset for that slice */
+ sliceio(slice, bp, SLW_ABOVE);
+}
+
+static int
+mbr_open(void *private, int flags, int mode, struct proc * p)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+ int part;
+ int error;
+ int newflags = 0;
+ int oldoflags = 0;
+ int newoflags = 0;
+
+RR;
+ sdp = private;
+ part = sdp->part;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+
+ /*
+ * Calculate the change to to over-all picture here.
+ * Notice that this might result in LESS open bits
+ * if that was what was passed from above.
+ * (Prelude to 'mode-change' instead of open/close.)
+ */
+ /* work out what our stored flags will be if this succeeds */
+ newflags = pd->flags & ~((MBRF_OPEN_WBIT|MBRF_OPEN_RBIT) << part);
+ newflags |= (flags & FWRITE) ? (MBRF_OPEN_WBIT << part) : 0;
+ newflags |= (flags & FREAD) ? (MBRF_OPEN_RBIT << part) : 0;
+
+ /* work out what we want to pass down this time */
+ newoflags = (newflags & MBRF_MSK_WR) ? FWRITE : 0;
+ newoflags |= (newflags & MBRF_MSK_RD) ? FREAD : 0;
+
+ /*
+ * If the agregate flags we used last time are the same as
+ * the agregate flags we would use this time, then don't
+ * bother re-doing the command.
+ */
+ if (newoflags != pd->savedoflags) {
+ if (error = sliceopen(slice, newoflags, mode, p, SLW_ABOVE)) {
+ return (error);
+ }
+ }
+
+ /*
+ * Now that we know it succeeded, commit, by replacing the old
+ * flags with the new ones.
+ */
+ pd->flags &= ~MBRF_MSK_OPEN;
+ pd->flags |= newflags;
+ pd->savedoflags = newoflags;
+ return (0);
+}
+
+static void
+mbr_close(void *private, int flags, int mode, struct proc * p)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+ int newflags;
+ int newoflags;
+ int part;
+
+RR;
+ sdp = private;
+ part = sdp->part;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+
+ if ((pd->flags & MBRF_MSK_OPEN) == 0)
+ return;
+
+ /* work out what our stored flags will be if this succeeds */
+ newflags = pd->flags & ~((MBRF_OPEN_WBIT|MBRF_OPEN_RBIT) << part);
+ newflags |= (flags & FWRITE) ? (MBRF_OPEN_WBIT << part) : 0;
+ newflags |= (flags & FREAD) ? (MBRF_OPEN_RBIT << part) : 0;
+
+ /* work out what we want to pass down this time */
+ newoflags = (newflags & MBRF_MSK_WR) ? FWRITE : 0;
+ newoflags |= (newflags & MBRF_MSK_RD) ? FREAD : 0;
+
+ /*
+ * If this was the last open slice above, then release our own open
+ */
+ pd->flags &= ~((MBRF_OPEN_RBIT|MBRF_OPEN_WBIT) << part);
+ if (pd->flags & MBRF_MSK_OPEN) {
+ sliceclose(slice, newoflags, mode, p, SLW_ABOVE);
+ }
+ pd->flags &= ~MBRF_MSK_OPEN;
+ pd->flags |= newflags;
+ pd->savedoflags = newoflags;
+ return ;
+}
+
+static int
+mbr_ioctl(void *private, int cmd, caddr_t addr, int flag, struct proc * p)
+{
+ register struct private_data *pd;
+ struct subdev *sdp;
+ register struct slice *slice;
+ int error;
+
+RR;
+ sdp = private;
+ pd = sdp->pd;
+ slice = pd->slice_down;
+
+ return ((*slice->handler_down->ioctl) (slice->private_down,
+ cmd, addr, flag, p));
+}
+
+static int
+mbr_upconfig(struct slice *slice, int cmd, caddr_t addr,
+ int flag, struct proc * p)
+{
+ RR;
+ switch (cmd) {
+ case SLCIOCRESET:
+ return (0);
+
+/* These don't really make sense. keep the headers for a reminder */
+ default:
+ return (ENOIOCTL);
+ }
+ return (0);
+}
+
diff --git a/sys/dev/slice/slice.4 b/sys/dev/slice/slice.4
new file mode 100644
index 0000000..2fffdb3
--- /dev/null
+++ b/sys/dev/slice/slice.4
@@ -0,0 +1,152 @@
+yes I know this is not in mandoc format..
+
+The slices are stackable..
+With alternating layers of handler(driver)/slice/handler/slice/handler/slice
+The "Slice" is implemented as a common structure shared between three
+pieces of code. Each slice in the stack can be thought of in OO terms as
+an instance of the 'slice' object. Methods include all the 'device' node
+methods exported via the cdevsw[], bdevsw[] and devfs interfaces. Thus
+whenever a handler exports a slice object, a unique node is made available
+to the users via the device system, to access that slice, as if it were a
+disk in it's own right. Since the interface is implemented by the same
+code no matter where in the stack it occurs, all partitions and devices
+which are exported by the slice code, exhibit almost identical behavior.
+Theoretically, it should be possible to treat a partition of a device, as
+if it were a separate device, as it should exhibit the same behavior as
+the device itself (except for size).
+
+The diagram below exhibits the form of one layer of the stack. Each handler
+can decide how many slices to export on the upper side, and
+how many slices to connect to on the lower side. If A slice can not be
+further subdivided, there may not be an upper handler.
+
+ [upper handler] (optional)
+ ^
+ |
+ |
+ v |------ raw (char) device
+[common slice information]<---------->[slice device]
+ ^ |------ block device
+ |
+ |
+ v
+ [lower handler] (may be a device driver)
+
+Each of these 3 items share some knowledge of the internal structure and
+contents of the slice structure. They also know each other's published
+interfaces. This may change as the design settles down and it becomes more
+obvious which parts can be hidden.
+
+The slices are created bottom up.
+When the driver decides that there is media that should be made available,
+it creates a 'slice' object to represent it. This slice object comes with a
+set of methods for exporting and implementing a device. The action of creating
+a slice therefor creates the interface through which a user can access that
+device. A driver might even export such slice before the media is present,
+in order to make a device node available to the user. (e.g. the floppy
+driver would make /dev/rfd0 available even if there was no media present,
+simply because it has no way of detecting that the media has been added.
+Attempts to open or access that node would result in the usual EIO
+errors.
+
+i.e. the device probes, and creates a static 'slice' that is associated with
+the device.. The static slice can't be removed unless the driver does so,
+thought if the media is changed the size of the slice may change.
+
+
+Some time after the media has been detected, or deduced to be present,
+the driver would ask the system to try interpret the contents of the
+media. It does this by passing the slice to the generic code. The generic
+code will ask all the possible handlers to see if that slice (or virtual
+disk) has the structure it requires. Sometimes the driver (or lower handler,
+for that is what the driver is from the point of view of the slice) Will 'seed'
+the slice with a 'hint' which will make the generic code narrow it's requests
+to a particular handler, or group of handlers.
+
+When a slice object attaches an handler to one of it's slices, that handler
+might elect to further export more slices, each representing some different
+view of the slice. This could result on a multi layer stack of slices and
+handlers, depending on the contents of the device. Whether a handler will
+elect to further divide a slice given to it is solely up to that handler. No
+other code has jurisdiction over that decision.
+
+Because a device may need to know that it is being used, it is important
+that open() events be cascaded down towards the device. Handlers that
+export multiple slices upwards must pass down the union of all the open
+states of those slices.
+
+A lower level handler can decide that the slices it has exported are no
+longer valid. This can occur for several reasons. For example a write to a
+low level slice might change the structures defining a higher level slice,
+or a driver (the lowest level handler) might notice that the media on which
+a slice is based, has been removed, or in some other way become
+unavailable. The handler must be able to invalidate the slice(es) affected,
+and know that the system will cascade that invalidation upwards as needed.
+A higher handler may decide to no pass on the invalidation if it calculates
+that higher level services can still be provided without the particular
+lower slice being present, (e.g. a RAID handler).
+
+Access to various layers is controlled by a strict protocol to avoid
+accidental system damage. There is a single sysctl variable that can
+disable the enforcement of this protocol, however it should ony be used
+in special (e.g. system instalation) circumstances. The basic protocol
+is that a higher level device cannot be opened while one of it's lower
+layers is open for writing. Similarly, a lower layer cannot be openned for
+writing while an upper layer is open at all. Two devices at different
+layers can be openned at the same time if there is no direct
+decendancy between the two. In an analogue, we might say that 'cousins'
+can be openned independantly, but anscestors and descendents cannot.
+The sysctl variable kern.slicexclusive has 3 values.
+0 disables the checks metioned above. 1 enables them, and 2
+enables eve more draconian rules in which even READ opens are disabled.
+
+Further rules govern the interaction of the block and raw versions of a
+slice. For example, if a block device is open for read/write, it's raw
+device can not be written to (in mode 1)
+
+[think about upwards permission inherritance for subslices]
+
+
+[setting up new configurations]
+A disk exports simply a raw slice. It has no preference as to what goes on it..
+(preferences are stored in the slice's probehints structure.)
+To slice it into fdisk type:
+1/ set the hints to "mbr", through an ioctl on that device. (e.g. rsd0)
+2/ Run the "mbr" code's constructor. this will initialise the slice.
+ The "mbr" code will actually write an mbr to the slice,
+ with default values. (so it will recognise it in the future).
+ (this is why the claim is separate from the constructor). The claim()
+ is nondestructive. The constructor KNOWS it owns the slice.
+3/ Send ioctls to the device that are redirected UP to the new handler.
+ These ioctls allow "type specific templates" and manipulation
+ of slice tables. Each hander interprets these to suit it's own table
+ format. This uses the sl_h_upconfig() method, which is basically an
+ ioctl entrypoint, but which is not automatically cascaded up.
+
+
+rc should have the following added to it to make the system 'safe'
+when multi-user mode is entered.
+
+*** /etc/rc.orig Sat Apr 18 14:34:48 1998
+--- /etc/rc Sat Apr 18 14:38:32 1998
+***************
+*** 82,87 ****
+--- 82,96 ----
+ exit 1
+ fi
+
++ ###DEVFS
++ # put the storage slices into safe mode.
++ # 0 == unsafe. One char, one blk and one subslice can all be openned R/W.
++ # 1 = readonly. If a subslice is open, a blk and chr can be openned R/O.
++ # If a slice is open R/W, subslices cannot be openned.
++ # 2 = exclusive. If a subslice is open, a blk or chr cannot be openned.
++ # and visa versa.
++ sysctl -w kern.slicexclusive=1
++
+ # If there is a global system configuration file, suck it in.
+ if [ -f /etc/rc.conf ]; then
+ . /etc/rc.conf
+
+
+
diff --git a/sys/dev/slice/slice.h b/sys/dev/slice/slice.h
new file mode 100644
index 0000000..553bdb5
--- /dev/null
+++ b/sys/dev/slice/slice.h
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (C) 1997,1998 Julian Elischer. All rights reserved.
+ * julian@freebsd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+typedef struct slice_handler *sh_p;
+typedef struct slice *sl_p;
+
+struct slicelimits {
+ u_int32_t blksize; /* IN BYTES */
+ u_int64_t slicesize; /* IN BYTES */
+};
+typedef struct slicelimits *slmt_p;
+
+/*
+ * This struct is only used by the IDE geometry guessing hack in
+ * the MBR and disklabel code, when talked to by the IDE driver with a VERY
+ * OLD DISK
+ */
+struct ide_geom {
+ u_int32_t secpertrack; /* set to 0 if geom not known */
+ u_int16_t trackpercyl;
+ u_int32_t cyls;
+};
+
+/*
+ * The probehints are set by the lower handler, to give direction as to
+ * what handler is probably required above. If a slice is repartitioned,
+ * these may change e.g. mbr may set 165 meaning "FreeBSD slice" or 4 "DOS".
+ * -type: a string for the type that should be used.
+ * if it's a null string ("") then don't even try find a sub handler.
+ * defined as NO_SUBPART
+ * if it's a NULL pointer (NULL) then probe all known types.
+ * -typespecific: A pointer to SOMETHING that teh lower handler thinks
+ * may be of interest to the higher hamdlers. The "something" is dependent
+ * on the type of the lower handler so the upper handler must know of
+ * this in advance. The type of this should be specified in an
+ * include file associated with the lower type. This is probably rarely
+ * needed.
+ */
+struct probehints {
+ char *type; /* don't probe, just use this type */
+ void *typespecific; /* the lower layer specifies this */
+};
+#define NO_SUBPART ""
+/*
+ * The common slice structure with data, methods and linkages.
+ */
+struct slice {
+ /* Per slice data */
+ char *name; /* e.g. sd0 wd0s1, wd0s1a ?? */
+ struct probehints probeinfo; /* how we should probe this */
+ u_int32_t flags; /* this device open, etc. */
+ u_int16_t refs; /* active references, free if 1->0 */
+ u_int16_t opencount; /* actual count of opens if allowed */
+ struct slicelimits limits; /* limits on this slice */
+ sh_p handler_up; /* type methods etc. */
+ void *private_up; /* data for the slice type */
+ sh_p handler_down; /* type methods etc. */
+ void *private_down; /* data for the slice type */
+ /*------- fields for the slice device driver -------*/
+ LIST_ENTRY(slice) hash_list; /* next slice in this bucket */
+ u_int32_t minor; /* the key for finding us */
+ void *devfs_btoken;
+ void *devfs_ctoken;
+};
+
+/* bit definitions for the slice flags */
+#define SLF_CLOSED 0x00000000 /* slice not open */
+#define SLF_OPEN_BLK_RD 0x00000001 /* blk slice readable */
+#define SLF_OPEN_BLK_WR 0x00000002 /* blk slice writeable */
+#define SLF_OPEN_BLK (SLF_OPEN_BLK_RD|SLF_OPEN_BLK_WR)
+#define SLF_OPEN_CHR_RD 0x00000004 /* raw slice readable */
+#define SLF_OPEN_CHR_WR 0x00000008 /* raw slice writeable */
+#define SLF_OPEN_CHR (SLF_OPEN_CHR_RD|SLF_OPEN_CHR_WR)
+#define SLF_OPEN_DEV_RD (SLF_OPEN_CHR_RD|SLF_OPEN_BLK_RD)
+#define SLF_OPEN_DEV_WR (SLF_OPEN_CHR_WR|SLF_OPEN_BLK_WR)
+#define SLF_OPEN_DEV (SLF_OPEN_DEV_RD|SLF_OPEN_DEV_WR)
+#define SLF_OPEN_UP_RD 0x00000010 /* upper layer is readable */
+#define SLF_OPEN_UP_WR 0x00000020 /* upper layer is writable */
+#define SLF_OPEN_UP 0x00000030 /* upper layer is open */
+#define SLF_OPEN_WR (SLF_OPEN_UP_WR|SLF_OPEN_DEV_WR)
+#define SLF_OPEN_RD (SLF_OPEN_UP_RD|SLF_OPEN_DEV_RD)
+#define SLF_OPEN_STATE (SLF_OPEN_WR|SLF_OPEN_RD) /* Mask open state */
+
+#define SLF_INVALID 0x00000100 /* Everything aborts */
+#define SLF_LOCKED 0x00000200 /* Hold off, It's busy */
+#define SLF_WANTED 0x00000400 /* I held off, wake me up */
+
+/*
+ * prototypes for slice methods
+ */
+typedef void sl_h_IO_req_t(void *private, struct buf * buf);
+typedef int sl_h_ioctl_t(void *private, int cmd, caddr_t data,
+ int fflag, struct proc * p);
+typedef int sl_h_constructor_t(sl_p slice);
+typedef int sl_h_open_t(void *private, int flags, int mode, struct proc * p);
+typedef void sl_h_close_t(void *private, int flags, int mode, struct proc * p);
+typedef int sl_h_revoke_t(void *private);
+typedef int sl_h_claim_t(struct slice * slice, struct slice * lower,
+ void *ID); /* eg ID=165 for BSD */
+typedef int sl_h_verify_t(struct slice *slice);
+typedef int sl_h_upconfig_t(struct slice *slice, int cmd, caddr_t data,
+ int fflag, struct proc *p);
+
+struct slice_handler {
+ char *name;
+ int version;/* the version of this handler */
+ struct slice_handler *next; /* next registered type */
+ int refs; /* references to this type */
+ sl_h_constructor_t *constructor; /* make new instantiation */
+ sl_h_IO_req_t *IOreq; /* IO req downward (to device) */
+ sl_h_ioctl_t *ioctl; /* ioctl downward (to device) */
+ sl_h_open_t *open; /* downwards travelling open */
+ sl_h_close_t *close; /* downwards travelling close */
+ sl_h_revoke_t *revoke; /* revoke upwards (towards user ) */
+ sl_h_claim_t *claim; /* claim a new slice */
+ sl_h_verify_t *verify; /* verify that a slice as it was before */
+ sl_h_upconfig_t *upconf; /* config requests from slice below */
+};
+
+/*
+ * general routines that handlers need.
+ */
+int sl_make_slice(sh_p handler_down, void *private_down,
+ struct slicelimits *limits,
+ sl_p *slicepp, char *type, char *name);
+void sl_rmslice(sl_p slice);
+int sl_newtype(sh_p tp);
+sh_p sl_findtype(char *type);
+sh_p slice_probeall(sl_p slice);
+int lockslice(sl_p slice);
+int unlockslice(sl_p slice);
+int slice_readblock(struct slice *slice, int blkno, struct buf **bpp);
+int slice_writeblock(struct slice *slice, int blkno, struct buf *bp);
+
+/*
+ * Definitions for "SLICE" utilities. (handler or device acting on a slice).
+ */
+enum slc_who { SLW_ABOVE, SLW_DEVICE }; /* helps to know who's calling */
+
+void sliceio(sl_p slice, struct buf * bp, enum slc_who who);
+int sliceopen(sl_p slice, int flags, int mode,
+ struct proc * p, enum slc_who who);
+void sliceclose(sl_p slice, int flags, int mode,
+ struct proc * p, enum slc_who who);
+
+void sl_unref(sl_p slice);
+void slice_add_device(sl_p slice);
+void slice_remove_device(sl_p slice);
+
+/*
+ * The geometry guessing HACK functions
+ */
+int mbr_geom_hack(struct slice * slice, struct ide_geom *geom);
+int dkl_geom_hack(struct slice * slice, struct ide_geom *geom);
+/*
+ * The routine to produce a dummy disklabel from a slice.
+ * Lives in disklabel.c because that's where everyhting is in scope,
+ * but is used in slice_device.c. XXX hack.
+ */
+int dkl_dummy_ioctl(struct slice *slice, int cmd, caddr_t addr,
+ int flag, struct proc * p);
+
+/*
+ * debugging
+ */
+#if 0
+#define RR printf(__FUNCTION__ " called\n")
+#else
+#define RR /* nothing */
+#endif
diff --git a/sys/dev/slice/slice_base.c b/sys/dev/slice/slice_base.c
new file mode 100644
index 0000000..558720b
--- /dev/null
+++ b/sys/dev/slice/slice_base.c
@@ -0,0 +1,671 @@
+/*-
+ * Copyright (C) 1997,1998 Julian Elischer. All rights reserved.
+ * julian@freebsd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h> /* SYSINIT stuff */
+#include <sys/fcntl.h> /* FREAD/FWRITE */
+#include <sys/conf.h> /* cdevsw stuff */
+#include <sys/malloc.h> /* malloc region definitions */
+#include <sys/buf.h> /* buffers for IO */
+#include <sys/queue.h> /* linked lists etc. */
+#include <sys/stat.h> /* S_IFCHR, S_IFBLK */
+#include <sys/sysctl.h> /* the sysctl for shooting self in foot */
+/*#include <sys/devfsext.h> */ /* DEVFS defintitions */
+#include <dev/slice/slice.h> /* temporary location */
+
+#define SLICESPL() splbio()
+
+
+static int slicexclusive = 0; /* default value == "foot shootable" */
+
+/*
+ * Make a new type available. Just link it in, but first make sure there is
+ * no name collision.
+ */
+
+static sh_p types;
+
+int
+sl_newtype(sh_p tp)
+{
+ if (sl_findtype(tp->name)) {
+ return (EEXIST);
+ }
+ tp->next = types;
+ types = tp;
+ return (0);
+}
+
+/*
+ * Look for a type of the name given.
+ */
+sh_p
+sl_findtype(char *type)
+{
+ sh_p tp;
+
+ tp = types;
+ while (tp) {
+ if (strcmp(tp->name, type) == 0)
+ return (tp);
+ tp = tp->next;
+ }
+ return (NULL);
+}
+
+/*
+ * Ask all known handler types if a given slice is handled by them.
+ * If the slice specifies a type, then just find that.
+ */
+sh_p
+slice_probeall(sl_p slice)
+{
+ sh_p tp = types;
+ if (slice->probeinfo.type == NULL) {
+ while (tp) {
+ printf("%s: probing for %s.. ",slice->name, tp->name);
+ if ((*tp->claim) (slice, NULL, NULL) == 0) {
+ printf("yep\n");
+ return (tp);
+ }
+ printf("nope\n");
+ tp = tp->next;
+ }
+ /*
+ * Null string ("") means "don't even try". Caller probably should
+ * pre-trap such cases but we'll check here too.
+ */
+ } else if (slice->probeinfo.type[0]) {
+ tp = sl_findtype(slice->probeinfo.type);
+ if ((tp) && ((*tp->claim) (slice, NULL, NULL) == 0)) {
+ printf("%s: attaching %s..\n",slice->name, tp->name);
+ return (tp);
+ }
+ }
+ /*printf("%s: Leaving as raw device\n", slice->name); */
+ return (NULL);
+}
+
+
+
+/*
+ * Make a handler instantiation of the requested type.
+ *
+ */
+static int
+sl_make_handler(char *type, sl_p slice)
+{
+ sh_p handler_up;
+ void *private_up;
+ int errval;
+
+ /*
+ * check that the type makes sense.
+ */
+ if (type == NULL) {
+ return (EINVAL);
+ }
+ handler_up = sl_findtype(type);
+ if (handler_up == NULL) {
+ return (ENXIO);
+ }
+ /*
+ * and call the constructor
+ */
+ if (handler_up->constructor != NULL) {
+ errval = (*handler_up->constructor) (slice);
+ return (errval);
+ } else {
+ printf("slice handler %s has no constructor\n",
+ handler_up->name);
+ return (EINVAL);
+ }
+}
+
+/*
+ * lock and unlock Slices while doing operations such as open().
+ * gets a reference on the slice..
+ * XXX This doesn't work for SMP.
+ */
+int
+lockslice(struct slice *slice)
+{
+ int s = SLICESPL();
+ slice->refs++;
+ while ( slice->flags & (SLF_LOCKED | SLF_INVALID)) {
+ if (slice->flags & SLF_INVALID) {
+ sl_unref(slice);
+ splx(s);
+ return (ENXIO);
+ }
+ slice->flags |= SLF_WANTED;
+ tsleep(slice, PRIBIO, "lockslice", 0);
+ }
+ slice->flags |= SLF_LOCKED;
+ splx(s);
+ return (0);
+}
+
+/*
+ * Releases a slice
+ * Assumes that if we had it locked, no-one else could invalidate it.
+ * We can still hold a reference on it.
+ */
+int
+unlockslice(struct slice *slice)
+{
+ int s = SLICESPL();
+ slice->flags &= ~SLF_LOCKED;
+ if ( slice->flags & SLF_WANTED) {
+ slice->flags &= ~SLF_WANTED;
+ wakeup(slice);
+ }
+ splx(s);
+ return (0);
+}
+
+/*
+ * create a new slice. Link it into the structures. don't yet find and call
+ * it's type handler. That's done later
+ */
+int
+sl_make_slice(sh_p handler_down, void *private_down,
+ struct slicelimits * limits,
+ sl_p * slicepp, char *type, char *name)
+{
+ sl_p slice;
+
+ /*
+ * Allocate storage for this instance .
+ */
+ slice = malloc(sizeof(*slice), M_DEVBUF, M_NOWAIT);
+ if (slice == NULL) {
+ printf("slice failed to allocate driver storage\n");
+ return (ENOMEM);
+ }
+ bzero(slice, sizeof(*slice));
+ if (name) {
+ slice->name = malloc(strlen(name) + 1, M_DEVBUF, M_NOWAIT);
+ if (slice->name == NULL) {
+ printf("slice failed name storage\n");
+ free(slice, M_DEVBUF);
+ return (ENOMEM);
+ }
+ strcpy(slice->name, name);
+ }
+ slice->handler_down = handler_down;
+ slice->private_down = private_down;
+ handler_down->refs++;
+ slice->limits = *limits;
+ slice_add_device(slice);
+ slice->refs = 1; /* one for our downward creator */
+ *slicepp = slice;
+ if (type) {
+ slice->refs++; /* don't go away *//* probably not needed */
+ sl_make_handler(type, slice);
+ sl_unref(slice);
+ }
+ return (0);
+}
+
+/*
+ * Forceably start a shutdown process on a slice. Either call it's shutdown
+ * method, or do the default shutdown if there is no type-specific method.
+ * XXX Really should say who called us.
+ */
+void
+sl_rmslice(sl_p slice)
+{
+RR;
+ /*
+ * An extra reference so it doesn't go away while we are not looking.
+ */
+ slice->refs++;
+
+ if (slice->flags & SLF_INVALID) {
+ /*
+ * If it's already shutting down, let it die without further
+ * taunting. "go away or I'll taunt you a second time, you
+ * silly eenglish pig-dog"
+ */
+ sl_unref(slice);/* possibly the last reference */
+ return;
+ }
+
+ /*
+ * Mark it as invalid so any newcomers know not to try use it.
+ * No real need to LOCK it.
+ */
+ slice->flags &= ~SLF_OPEN_STATE;
+ slice->flags |= SLF_INVALID;
+
+ /*
+ * remove the device appendages.
+ * Any open vnodes SHOULD go to deadfs.
+ */
+ slice_remove_device(slice);
+
+ /*
+ * Propogate the damage upwards.
+ * Note that the revoke method is not optional.
+ * The upper handler releases it's reference so refs--.
+ */
+ if (slice->handler_up) {
+ (*slice->handler_up->revoke) (slice->private_up);
+ }
+ sl_unref(slice); /* One for the lower handler that called us */
+ sl_unref(slice); /* possibly the last reference */
+}
+
+
+
+void
+sl_unref(sl_p slice)
+{
+ if ((--(slice->refs)) == 0) {
+ FREE(slice, M_DEVBUF);
+ }
+}
+
+/*
+ * Read a block on behalf of a handler.
+ * This is not a bulk IO routine but meant for probes etc.
+ * I think that perhaps it should attempt to do sliceopen()
+ * calls on the slice first. (XXX?)
+ */
+int
+slice_readblock(struct slice * slice, int blkno, struct buf ** bpp)
+{
+ struct buf *bp;
+ int error = 0;
+
+ /*
+ * posibly attempt to open device?
+ */
+ /* --not yet-- */
+ /*
+ * Now that it is open, get the buffer and set in the parameters.
+ */
+ bp = geteblk((int) slice->limits.blksize);
+ if (bp == NULL) {
+ return (ENOMEM);
+ }
+ bp->b_pblkno = bp->b_blkno = blkno;
+ bp->b_bcount = slice->limits.blksize;
+ bp->b_flags |= B_BUSY | B_READ;
+ sliceio(slice, bp, SLW_ABOVE);
+ if (biowait(bp) != 0) {
+ printf("failure reading device block\n");
+ error = EIO;
+ bp->b_flags |= B_INVAL | B_AGE;
+ brelse(bp);
+ bp = NULL;
+ }
+ *bpp = bp;
+ return (error);
+}
+
+/*
+ * Read a block on behalf of a handler.
+ * This is not a bulk IO routine but meant for probes etc.
+ * I think that perhaps it should attempt to do sliceopen()
+ * calls on the slice first. (XXX?)
+ */
+int
+slice_writeblock(struct slice * slice, int blkno, struct buf * bp)
+{
+ int error = 0;
+
+ if (bp == NULL) {
+ return (ENOMEM);
+ }
+ bp->b_pblkno = bp->b_blkno = blkno;
+ bp->b_bcount = slice->limits.blksize;
+ bp->b_flags |= B_BUSY | B_WRITE;
+ sliceio(slice, bp, SLW_ABOVE);
+ if (biowait(bp) != 0) {
+ printf("failure reading device block\n");
+ error = EIO;
+ }
+ return (error);
+}
+
+/*
+ * functions that are used to call the next level down.
+ */
+void
+sliceio(sl_p slice, struct buf * bp, enum slc_who who)
+{
+ /* XXX do shortcuts here */
+
+ if (slice->flags & SLF_INVALID) {
+ bp->b_error = ENXIO;
+ goto bad;
+ }
+ /*
+ * if it's from above, assume it hasn't
+ * broken it's agreement about read/write.
+ * A higher level slice would have caught it.
+ * Make no such assumption if it's this device.
+ */
+ if (who == SLW_DEVICE) {
+ if (((slice->flags & SLF_OPEN_DEV_WR) == 0) &&
+ ( (bp->b_flags & B_READ) == B_WRITE )) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+ }
+ (*slice->handler_down->IOreq) (slice->private_down, bp);
+ return;
+bad:
+ bp->b_flags |= B_ERROR;
+ /* toss transfer, we're done early */
+ biodone(bp);
+ return;
+}
+
+/*
+ * Try open a slice.
+ * don't forget to say if we are above (1) or the dev (0).
+ *
+ * We really need to add a lot of support for CHANGING
+ * what we have openned.. i.e if we have ABOVE open R/W
+ * and DEVICE open R/O, then closing the device
+ * should downgrade our open to those items below us to R/O.
+ * This would need support in both open and close routines in both
+ * slice and handler code.
+ *
+ * ((*) == Illegal state.. (how did we get here?))
+ * (must have been in "shoot foot mode").
+ * A bit already set can be set again. (may represent part of an upgrade)
+ * This may not hold true if we are in an 'illegal state'.
+ * Some such opens will fail in an attempt to revert to a legal state.
+ * success = ((request & allowed[state]) == request)
+ */
+#define UP_RDWR SLF_OPEN_UP
+#define CHR_RDWR SLF_OPEN_CHR
+#define CHR_RD SLF_OPEN_CHR_RD
+#define BLK_RDWR SLF_OPEN_BLK
+#define BLK_RD SLF_OPEN_BLK_RD
+static u_char allowed[64] = {
+/* Present state | requested states allowed */
+/* UP CHR BLK | UP CHR BLK */
+/* R W R W R W | R W R W R W */
+/* 0 0 0 0 0 0 1 1 1 1 1 1 */( UP_RDWR|CHR_RDWR|BLK_RDWR ),
+/* 0 0 0 0 0 1 0 0 1 0 1 1 */( CHR_RD|BLK_RDWR ),
+/* 0 0 0 0 1 0 1 1 1 1 1 1 */( UP_RDWR|CHR_RDWR|BLK_RDWR ),
+/* 0 0 0 0 1 1 0 0 1 0 1 1 */( CHR_RD|BLK_RDWR ),
+/* 0 0 0 1 0 0 0 0 1 1 1 0 */( CHR_RDWR|BLK_RD ),
+/* 0 0 0 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 0 0 1 1 0 0 0 1 1 1 0 */( CHR_RDWR|BLK_RD ),
+/* 0 0 0 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 0 1 0 0 0 1 1 1 1 1 1 */( UP_RDWR|CHR_RDWR|BLK_RDWR ),
+/* 0 0 1 0 0 1 0 0 1 0 1 1 */( CHR_RD|BLK_RDWR ),
+/* 0 0 1 0 1 0 1 1 1 1 1 1 */( UP_RDWR|CHR_RDWR|BLK_RDWR ),
+/* 0 0 1 0 1 1 0 0 1 0 1 1 */( CHR_RD|BLK_RDWR ),
+/* 0 0 1 1 0 0 0 0 1 1 1 0 */( CHR_RDWR|BLK_RD ),
+/* 0 0 1 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 0 1 1 1 0 0 0 1 1 1 0 */( CHR_RDWR|BLK_RD ),
+/* 0 0 1 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 0 0 0 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 0 1 0 0 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 0 0 1 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 0 1 0 0 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 0 1 0 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 0 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 0 1 1 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 0 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 1 0 0 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 0 1 1 0 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 1 0 1 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 0 1 1 0 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 1 1 0 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 1 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 1 1 1 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 0 1 1 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 0 0 0 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 0 0 0 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 0 0 1 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 0 0 0 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 0 1 0 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 0 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 0 1 1 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 0 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 1 0 0 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 0 1 0 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 1 0 1 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 0 1 0 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 1 1 0 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 1 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 1 1 1 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 0 1 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 0 0 0 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 1 0 0 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 0 0 1 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 1 0 0 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 0 1 0 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 0 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 0 1 1 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 0 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 1 0 0 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 1 1 0 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 1 0 1 0 1 1 1 0 1 0 */( UP_RDWR|CHR_RD|BLK_RD ),
+/* 1 1 1 0 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 1 1 0 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 1 1 0 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 1 1 1 0 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ),
+/* 1 1 1 1 1 1 0 0 1 0 1 0 (*) */( CHR_RD|BLK_RD ) };
+
+int
+sliceopen(struct slice *slice, int flags, int mode,
+ struct proc * p, enum slc_who who)
+{
+ int s;
+ int error;
+ int sl_flags = slice->flags & SLF_OPEN_STATE;
+ int or_flags;
+ int and_flags;
+ int dn_flags;
+ int odn_flags;
+
+
+ if (slice->flags & SLF_INVALID)
+ return (ENXIO);
+ /*
+ * Firstly, don't allow re-opens of what is already open
+ */
+ if (error = lockslice(slice))
+ return (error);
+ error = EBUSY; /* default answer */
+ switch (who) {
+ case SLW_ABOVE:
+ or_flags = ((flags & FREAD) ? SLF_OPEN_UP_RD : 0);
+ or_flags |= ((flags & FWRITE) ? SLF_OPEN_UP_WR : 0);
+ and_flags = ~SLF_OPEN_UP;
+ break;
+ case SLW_DEVICE:
+ switch (mode & S_IFMT) {
+ case S_IFCHR:
+ or_flags = ((flags & FREAD) ? SLF_OPEN_CHR_RD : 0);
+ or_flags |= ((flags & FWRITE) ? SLF_OPEN_CHR_WR : 0);
+ and_flags = ~SLF_OPEN_CHR;
+ break;
+ case S_IFBLK:
+ or_flags = ((flags & FREAD) ? SLF_OPEN_BLK_RD : 0);
+ or_flags |= ((flags & FWRITE) ? SLF_OPEN_BLK_WR : 0);
+ and_flags = ~SLF_OPEN_BLK;
+ break;
+ default:
+ panic("slice: bad open type");
+ }
+ break;
+ default:
+ panic("slice: bad request source");
+ }
+ /*
+ * Be appropriatly paranoid depending on the system mode.
+ * This is also probably wrong XXX
+ */
+ switch(slicexclusive) {
+ case 2:
+ /*
+ * if any one path has it open, we forbid any other
+ * paths. Only allow an upgrade/downgrade from
+ * the same source as the present openner.
+ */
+ if ( sl_flags & and_flags)
+ goto reject;
+ case 1: /*
+ * The behaviour is encoded into the state array given above.
+ */
+ if ((or_flags & allowed[sl_flags]) != or_flags)
+ goto reject;
+ break;
+ case 0: /*
+ * Permission is granted to shoot self in foot.
+ * All three of UPPER, CHAR and BLK can be open at once.
+ */
+ break;
+ }
+ /*
+ * Get the old open mode and the new open mode.
+ * If we already have it open in this way, don't do it again.
+ *
+ * XXX More thought needed for the locking and open-flags.
+ * For now ignore the existance of flags other than FWRITE & FREAD.
+ */
+ odn_flags = (sl_flags & SLF_OPEN_WR) ? FWRITE : 0;
+ odn_flags |= (sl_flags & SLF_OPEN_RD) ? FREAD : 0;
+ sl_flags &= and_flags;
+ sl_flags |= or_flags;
+ dn_flags = (sl_flags & SLF_OPEN_WR) ? FWRITE : 0;
+ dn_flags |= (sl_flags & SLF_OPEN_RD) ? FREAD : 0;
+ error = 0;
+ if (dn_flags != odn_flags) {
+ if ((error = (*slice->handler_down->open) (slice->private_down,
+ dn_flags, mode, p)) != 0) {
+ goto reject;
+ }
+ }
+ slice->flags &= ~SLF_OPEN_STATE;
+ slice->flags |= sl_flags;
+reject:
+ unlockslice(slice);
+ sl_unref(slice); /* lockslice gave us a ref.*/
+ return (error);
+}
+
+void
+sliceclose(struct slice *slice, int flags, int mode,
+ struct proc * p, enum slc_who who)
+{
+ sh_p tp;
+
+ if (slice->flags & SLF_INVALID)
+ return ;
+ if (lockslice(slice))
+ return ;
+ switch (who) {
+ case SLW_ABOVE:
+ slice->flags &= ~SLF_OPEN_UP;
+ break;
+ case SLW_DEVICE:
+ switch (mode & S_IFMT) {
+ case S_IFCHR:
+ slice->flags &= ~SLF_OPEN_CHR;
+ break;
+ case S_IFBLK:
+ slice->flags &= ~SLF_OPEN_BLK;
+ break;
+ default:
+ panic("slice: bad open type");
+ }
+ /*
+ * If we had an upper handler, ask it to check if it's still
+ * valid. it may decide to self destruct.
+ */
+ if (slice->handler_up) {
+ (*slice->handler_up->verify)(slice);
+ }
+ /*
+ * If we don't have an upper handler, check if
+ * maybe there is now a suitable environment for one.
+ * We may end up with a different handler
+ * from what we had above. Maybe we should clear the hint?
+ * Maybe we should ask the lower one to re-issue the request?
+ */
+ if (slice->handler_up == NULL) {
+ if ((tp = slice_probeall(slice)) != NULL) {
+ (*tp->constructor)(slice);
+ }
+ }
+ break;
+ }
+ /*
+ * Last-close semantics strike again
+ * This may refine to a downgrade if we closed (say) the last writer
+ * but there are still readers.
+ * probably open/close should merge to one 'mode-change' function.
+ * (except for a vnode reference with no mode)
+ */
+ if ( (slice->flags & SLF_OPEN_STATE) == 0)
+ (*slice->handler_down->close) (slice->private_down,
+ flags, mode, p);
+ unlockslice(slice);
+ sl_unref(slice);
+ return ;
+}
+
+
+/*
+ * control behaviour of slices WRT sharing:
+ * 2 = no sharing
+ * 1 = read on a device already mounted (or parent of) is ok. No writes.
+ * 0 = go ahead.. shoot yourself in the foot.
+ */
+static int
+sysctl_kern_slicexclusive SYSCTL_HANDLER_ARGS
+{
+ int error;
+ int new_val = slicexclusive;
+
+ error = sysctl_handle_int(oidp, &new_val, 0, req);
+ if (error == 0) {
+ if ((new_val >= 0) && (new_val < 3)) {
+ slicexclusive = new_val;
+ } else {
+ error = EINVAL;
+ }
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, slicexclusive, CTLTYPE_INT|CTLFLAG_RW,
+ 0, sizeof slicexclusive, sysctl_kern_slicexclusive, "I", "");
+
diff --git a/sys/dev/slice/slice_device.c b/sys/dev/slice/slice_device.c
new file mode 100644
index 0000000..4b7f86b
--- /dev/null
+++ b/sys/dev/slice/slice_device.c
@@ -0,0 +1,388 @@
+/*-
+ * Copyright (C) 1997,1998 Julian Elischer. All rights reserved.
+ * julian@freebsd.org
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h> /* SYSINIT stuff */
+#include <sys/conf.h> /* cdevsw stuff */
+#include <sys/malloc.h> /* malloc region definitions */
+#include <sys/buf.h> /* bufs for describing IO */
+#include <sys/fcntl.h> /* file open modes etc. */
+#include <sys/queue.h> /* standard queue macros */
+#include <sys/stat.h> /* S_IFBLK, S_IFMT etc. */
+#include <sys/devfsext.h> /* DEVFS defintitions */
+#include <dev/slice/slice.h> /* temporary location */
+
+
+
+/* Function prototypes (these should all be static except for slicenew()) */
+static d_open_t slcdevopen;
+static d_close_t slcdevclose;
+static d_ioctl_t slcdevioctl;
+static d_dump_t slcdevdump;
+static d_psize_t slcdevsize;
+static d_strategy_t slcdevstrategy;
+
+#define BDEV_MAJOR 14
+#define CDEV_MAJOR 20
+
+static struct cdevsw slice_cdevsw;
+static struct bdevsw slice_bdevsw = {
+ slcdevopen,
+ slcdevclose,
+ slcdevstrategy,
+ slcdevioctl,
+ slcdevdump,
+ slcdevsize,
+ D_DISK,
+ "slice",
+ &slice_cdevsw,
+ -1
+};
+
+static dev_t cdevnum, bdevnum;
+
+#define UNIT_HASH_SIZE 64
+LIST_HEAD(slice_bucket, slice) hash_table[UNIT_HASH_SIZE - 1];
+
+/*
+ * Now for some driver initialisation. Occurs ONCE during boot (very early).
+ */
+static void
+slice_drvinit(void *unused)
+{
+ int i;
+
+ /*
+ * add bdevsw and cdevsw entries
+ */
+ bdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &slice_bdevsw);
+
+ /*
+ * clear out the hash table
+ */
+ for (i = 0; i < UNIT_HASH_SIZE; i++) {
+ LIST_INIT(hash_table + i);
+ }
+}
+
+SYSINIT(slicedev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR,
+ slice_drvinit, NULL);
+
+static int nextunit = 0;
+
+void
+slice_add_device(sl_p slice)
+{
+ int unit = nextunit++;
+ char *name = slice->name;
+RR;
+ slice->minor = makedev(0,
+ (((unit << 8) & 0xffff0000) | (unit & 0x000000ff)));
+ /*
+ * put it on the hash chain for it's bucket so we can find it again
+ * later.
+ */
+ LIST_INSERT_HEAD(hash_table + (slice->minor % UNIT_HASH_SIZE),
+ slice, hash_list);
+ /*
+ * Add an entry in the devfs for it. Possibly should happen later.
+ */
+ slice->devfs_ctoken = devfs_add_devswf(&slice_cdevsw, unit, DV_CHR,
+ UID_ROOT, GID_KMEM, 0600, "r%s", name ? name : "-");
+ slice->devfs_btoken = devfs_add_devswf(&slice_bdevsw, unit, DV_BLK,
+ UID_ROOT, GID_KMEM, 0600, "%s", name ? name : "-");
+ /* XXX link this node into upper list of caller */
+}
+
+/*
+ * Given a minor number, find the slice which the operations are destined.
+ * When DEVFS DDEV devices are enabled this is bypassed entirely.
+ */
+static struct slice *
+minor_to_slice(unsigned int minor)
+{
+ int hash = minor % UNIT_HASH_SIZE;
+ struct slice *slice;
+
+ slice = (hash_table + hash)->lh_first;
+ while (slice) {
+ if (slice->minor == minor) {
+ return (slice);
+ }
+ slice = slice->hash_list.le_next;
+ }
+ return (NULL);
+}
+
+/*
+ * Macro to check that the unit number is valid Often this isn't needed as
+ * once the open() is performed, the unit number is pretty much safe.. The
+ * exception would be if we implemented devices that could "go away". in
+ * which case all these routines would be wise to check the number,
+ * DIAGNOSTIC or not.
+ */
+#define CHECKUNIT() \
+do { /* the do-while is a safe way to do this grouping */ \
+ if (slice == NULL) { \
+ printf( __FUNCTION__ ": unit not attached\n", unit); \
+ panic ("slice"); \
+ } \
+} while (0)
+
+#ifdef DIAGNOSTIC
+#define CHECKUNIT_DIAG() CHECKUNIT()
+#else /* DIAGNOSTIC */
+#define CHECKUNIT_DIAG()
+#endif /* DIAGNOSTIC */
+
+int
+slcdevioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc * p)
+{
+ sl_p slice = minor_to_slice(minor(dev));
+ int error = 0;
+
+ CHECKUNIT_DIAG();
+RR;
+
+ /*
+ * Look for only some generic "inherrited" ioctls that apply to all
+ * disk-like devices otherwise pass it down to the previous handler
+ */
+
+ switch (cmd) {
+ /*
+ * At present there are none, but eventually there would be
+ * something that returns the basic partition parameters.
+ * Whether this would be in the form of a disklabel or
+ * similar I have not yet decided.
+ */
+ default:
+ if (slice->handler_down->ioctl) {
+ error = (*slice->handler_down->ioctl)
+ (slice->private_down, cmd, data, flag, p);
+ } else {
+ error = ENOTTY;
+ }
+ if (error) {
+ /*
+ * If no disklabel was returned, let's make
+ * up something that will satisfy the system's
+ * need for a disklabel to mount an ffs on.
+ * Don't overwrite error unless we get a dummy.
+ * let the called routine decide
+ * if it can handle any ioctl.
+ */
+ if (dkl_dummy_ioctl(slice, cmd, data, flag, p) == 0) {
+ error = 0;
+ }
+ }
+ break;
+ }
+ return (error);
+}
+
+/*
+ * You also need read, write, open, close routines. This should get you
+ * started.
+ * The open MIGHT allow the caller to proceed if it is a READ
+ * mode, and it is open at a higher layer.
+ * All Accesses would have to be checked for READ
+ * as the system doesn't enforce this at this time.
+ */
+static int
+slcdevopen(dev_t dev, int flags, int mode, struct proc * p)
+{
+ sl_p slice = minor_to_slice(minor(dev));
+ int error;
+
+RR;
+ if (slice == NULL)
+ return (ENXIO);
+#if 1 /* the hack */
+ if ((mode & S_IFMT) == S_IFBLK) {
+ /*
+ * XXX Because a mount -u does not re-open the device
+ * The hack here, is to always open block devices
+ * in full read/write mode. Eventually, if DEVFS
+ * becomes ubiquitous, VOP to do a file upgrade
+ * might be implemented. Other Filesystems need
+ * not implement it..
+ * THIS SHOULD BE DONE IN slice_device.c
+ */
+ flags |= FWRITE;
+ }
+#endif /* the hack */
+ return (sliceopen(slice, flags, mode, p, SLW_DEVICE));
+}
+
+static int
+slcdevclose(dev_t dev, int flags, int mode, struct proc * p)
+{
+ sl_p slice = minor_to_slice(minor(dev));
+RR;
+ CHECKUNIT_DIAG();
+ sliceclose(slice, flags, mode, p, SLW_DEVICE);
+ return(0);
+}
+
+static int
+slcdevsize(dev_t dev)
+{
+ sl_p slice = minor_to_slice(minor(dev));
+
+RR;
+ if (slice == NULL)
+ return (-1);
+
+#if 0
+ return (slice->limits.slicesize / slice->limits.blksize);
+#else
+ return (slice->limits.slicesize / 512);
+#endif
+}
+
+
+/*
+ * Read/write routine for a buffer. Finds the proper unit, range checks
+ * arguments, and schedules the transfer. Does not wait for the transfer to
+ * complete. Multi-page transfers are supported. All I/O requests must be a
+ * multiple of a sector in length.
+ */
+void
+slcdevstrategy(struct buf * bp)
+{
+ sl_p slice = minor_to_slice(minor(bp->b_dev));
+ u_int64_t start, end;
+ u_int32_t blksize;
+ daddr_t blkno;
+ int s;
+
+RR;
+ if (slice == NULL) {
+ bp->b_error = ENXIO;
+ goto bad;
+ }
+ blksize = slice->limits.blksize;
+ /* Check we are going to be able to do this kind of transfer */
+ /* Check the start point too if DEV_BSIZE != reallity */
+ if (bp->b_blkno < 0) {
+ Debugger("Slice code got negative blocknumber");
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ start = (u_int64_t)bp->b_blkno * DEV_BSIZE;
+ if (blksize != DEV_BSIZE) {
+ if ((start % blksize) != 0) {
+ Debugger("slice: request not on block boundary.");
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ blkno = start / blksize;
+ } else {
+ blkno = bp->b_blkno;
+ }
+
+ if ((bp->b_bcount % blksize) != 0) {
+ printf("bcount = %d, blksize= %d(%d)\n",
+ bp->b_bcount, blksize,
+ slice->limits.blksize);
+ Debugger("slice: request not multile of blocksize.");
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ /*
+ * Do bounds checking, adjust transfer, and set b_pblkno.
+ */
+ bp->b_pblkno = blkno;
+ end = start + (u_int64_t)bp->b_bcount; /* first byte BEYOND the IO */
+
+ /*
+ * Handle the cases near or beyond the end of the slice. Assumes IO
+ * is < 2^63 bytes long. (pretty safe)
+ */
+ if (end > slice->limits.slicesize) {
+ int64_t size;
+ size = slice->limits.slicesize - start;
+ /*
+ * if exactly on end of slice, return EOF
+ */
+ if ((size == 0) && (bp->b_flags & B_READ)) {
+ printf("slice: at end of slice.");
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ if (size <= 0) {
+ printf("slice: beyond end of slice.");
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ bp->b_bcount = size;
+ }
+ sliceio(slice, bp, SLW_DEVICE);
+ return;
+
+done:
+ s = splbio();
+ /* toss transfer, we're done early */
+ biodone(bp);
+ splx(s);
+ return;
+bad:
+ bp->b_flags |= B_ERROR;
+ goto done;
+
+}
+
+void
+slice_remove_device(sl_p slice)
+{
+ /*
+ * Remove the devfs entry, which revokes the vnode etc. XXX if
+ * handler has madde more, we should tell it too. e.g. floppy driver
+ * does this.
+ */
+RR;
+ devfs_remove_dev(slice->devfs_btoken);
+ devfs_remove_dev(slice->devfs_ctoken);
+
+ /*
+ * Remove it from the hashtable.
+ */
+ LIST_REMOVE(slice, hash_list);
+}
+
+static int
+slcdevdump(dev_t dev)
+{
+ sl_p slice = minor_to_slice(minor(dev));
+RR;
+ if (slice == NULL)
+ return (ENXIO);
+ return (0);
+}
diff --git a/sys/dev/slice/slices.thought b/sys/dev/slice/slices.thought
new file mode 100644
index 0000000..654f250
--- /dev/null
+++ b/sys/dev/slice/slices.thought
@@ -0,0 +1,124 @@
+Original notes on how this might be implememented.. may not reflect
+the final code very much.
+======================================================[JRE]
+
+the slices are 'kinda' stackable..
+With alternating layers of handler(driver)/slice/handler/slice/handler/slice
+The "Slice" is a common structure shared between three pieces of code.
+1/ the lower handler
+2/ the upper handler
+3/ the generic slice code, which implements the device nodes etc.
+Each of these 3 items share a knowledge of the internal struture and
+contents of the slice structure. they also know each other's published
+interfaces.
+
+Each layer is much like the previous..
+Each layer has similar characteristics..
+The slices are created bottom up..
+i.e. the device probes, and creates a static 'slice' that is
+assiciated with the device.. The static slice
+can't be altered, unless the media is changed..
+
+A translation method, which might be NULL, in which case
+it is a simple case of offset addition.
+Possibly the offset might be already added..
+possibly this might be achieved by specifying a default method set.
+
+Each disk slice has a structure associated with it..
+When a slice is 'loaded' there must be some way of deciding if it has
+a subslice structure. if it does, then that structure must
+be loaded to create mode slices..
+this is recursive.
+
+The structuring must be such that it can recognise an attempt to change
+higer level structuring..
+This suggests a recursive 'open' count.. for open subslices.
+
+The idea would be to pass the following operations through methods.
+
+ translation to (possibly more than one) io operation
+ open count passing..
+ interpretation of subslicing and other slicing operations.
+ possibly there might be permissions inherritance.
+ open a slice...
+ create a slice.. methods are supplied by the disk driver..
+
+ upward methods:
+ force close
+
+ identify slice type.. slice type modules each asked
+ to identify..
+
+to do IO
+
+1/ find apropriate slice (hash)
+LIST_HEAD(slice_bucket, slice) hash_table[UNIT_HASH_SIZE - 1];
+
+in the init,
+for ( i = 0; i < UNIT_HASH_SIZE; i++) {
+ LIST_INIT(hash_table + i)
+}
+
+struct slice *minor_to_slice(unsigned int minor)
+{
+ int hash = minor % UNIT_HASH_SIZE;
+ struct slice *slice;
+
+ slice = (hash_table + hash)->lh_first;
+ while (slice) {
+ if (slice->minor == minor) {
+ return (slice);
+ }
+ slice = slice->hashlist.le_next
+ }
+ return (NULL);
+}
+2/
+ if IO method,
+ do IO method..
+ return
+ check bounds
+ adjust offset
+ follow slice-parent link and loop to top
+IO methods are supplied by drivers
+drivers including concatination drivers etc.
+
+concatination must be seen as a slice type
+
+once all parts of a concatinated slice are created, then
+the new 'concatinated slice' appears in the devfs.
+a concatinated slice has a 'label' that identifies it's volume
+and it's part (e.g. part 3 out of 5)
+'slice's in ram are either Primary or slave slices in a concatinated slice..
+
+
+to set up a slice call slice_add() which:
+1/ If (slice type not known)
+ Identify the type (call all type probe routines in turn)
+2/ call the succeeding type attach routine
+3/ the attach routine calls slice_add() for each sub slice
+The probe and attach may merge.
+
+
+the type of a slice must be detirmined taking into account the type of the
+parent slice.. It is conceivable that the parent slice
+might TELL the slice_add() routine what to make the slice..
+Possibly the parent set's a CONTEXT which might be helpful
+in identifying a slice
+
+
+disk:
+set up Method struct:
+IO points to disk strategy
+set size to whole disk
+set offset to 0
+set context to RAW
+call slice_add
+
+
+slice_add()
+called when we know about a slice..possibly we should fill out a slice
+struct before calling it.
+The slice struct is all that is needed to be able to do IO
+to the slice. slice_add, will then link the slice into
+the system as needed.
diff --git a/sys/dev/vn/vn.c b/sys/dev/vn/vn.c
index 8439c52..664014a 100644
--- a/sys/dev/vn/vn.c
+++ b/sys/dev/vn/vn.c
@@ -38,7 +38,7 @@
* from: Utah Hdr: vn.c 1.13 94/04/02
*
* from: @(#)vn.c 8.6 (Berkeley) 4/1/94
- * $Id: vn.c,v 1.54 1998/02/09 06:07:59 eivind Exp $
+ * $Id: vn.c,v 1.55 1998/02/20 13:27:36 bde Exp $
*/
/*
@@ -84,17 +84,19 @@
#include <sys/diskslice.h>
#include <sys/stat.h>
#include <sys/conf.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
+#ifdef SLICE
+#include <sys/device.h>
+#include <dev/slice/slice.h>
+#endif /* SLICE */
#include <miscfs/specfs/specdev.h>
#include <sys/vnioctl.h>
+static d_ioctl_t vnioctl;
+#ifndef SLICE
static d_open_t vnopen;
static d_close_t vnclose;
-static d_ioctl_t vnioctl;
static d_dump_t vndump;
static d_psize_t vnsize;
static d_strategy_t vnstrategy;
@@ -106,6 +108,30 @@ static struct bdevsw vn_bdevsw =
{ vnopen, vnclose, vnstrategy, vnioctl, /*15*/
vndump, vnsize, D_DISK | D_NOCLUSTERRW, "vn", &vn_cdevsw, -1 };
+#else /* SLICE */
+
+static sl_h_IO_req_t nvsIOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t nvsioctl; /* ioctl req downward (to device) */
+static sl_h_open_t nvsopen; /* downwards travelling open */
+static sl_h_close_t nvsclose; /* downwards travelling close */
+
+static struct slice_handler slicetype = {
+ "vn",
+ 0,
+ NULL,
+ 0,
+ NULL, /* constructor */
+ &nvsIOreq,
+ &nvsioctl,
+ &nvsopen,
+ &nvsclose,
+ NULL, /* revoke */
+ NULL, /* claim */
+ NULL, /* verify */
+ NULL /* upconfig */
+};
+#endif
+
#define vnunit(dev) dkunit(dev)
#define getvnbuf() \
@@ -117,16 +143,19 @@ static struct bdevsw vn_bdevsw =
struct vn_softc {
int sc_flags; /* flags */
size_t sc_size; /* size of vn */
-#if defined(DEVFS) && defined(notyet)
- void *sc_bdev; /* devfs token for whole disk */
- void *sc_cdev; /* devfs token for raw whole disk */
-#endif
+#ifdef SLICE
+ struct slice *slice;
+ struct slicelimits limit;
+ int mynor;
+ int unit;
+#else
+ struct diskslices *sc_slices;
+#endif /* SLICE */
struct vnode *sc_vp; /* vnode */
struct ucred *sc_cred; /* credentials */
int sc_maxactive; /* max # of active requests */
struct buf sc_tab; /* transfer queue */
u_long sc_options; /* options */
- struct diskslices *sc_slices;
};
/* sc_flags */
@@ -142,6 +171,7 @@ static int vnsetcred (struct vn_softc *vn, struct ucred *cred);
static void vnshutdown (int, void *);
static void vnclear (struct vn_softc *vn);
+#ifndef SLICE
static int
vnclose(dev_t dev, int flags, int mode, struct proc *p)
{
@@ -393,6 +423,170 @@ vnstrategy(struct buf *bp)
}
}
+#else /* SLICE */
+static void
+nvsIOreq(void *private ,struct buf *bp)
+{
+ struct vn_softc *vn = private;
+ u_int32_t unit = vn->unit;
+ register daddr_t bn;
+ int error;
+ int isvplocked = 0;
+ long sz;
+ struct uio auio;
+ struct iovec aiov;
+
+ IFOPT(vn, VN_DEBUG)
+ printf("vnstrategy(%p): unit %d\n", bp, unit);
+
+ if ((vn->sc_flags & VNF_INITED) == 0) {
+ bp->b_error = ENXIO;
+ bp->b_flags |= B_ERROR;
+ biodone(bp);
+ return;
+ }
+ bn = bp->b_pblkno;
+ bp->b_resid = bp->b_bcount;/* XXX best place to set this? */
+ sz = howmany(bp->b_bcount, DEV_BSIZE);
+
+ if( (bp->b_flags & B_PAGING) == 0) {
+ aiov.iov_base = bp->b_data;
+ aiov.iov_len = bp->b_bcount;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = dbtob(bn);
+ auio.uio_segflg = UIO_SYSSPACE;
+ if( bp->b_flags & B_READ)
+ auio.uio_rw = UIO_READ;
+ else
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_resid = bp->b_bcount;
+ auio.uio_procp = curproc;
+ if (!VOP_ISLOCKED(vn->sc_vp)) {
+ isvplocked = 1;
+ vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
+ }
+ if( bp->b_flags & B_READ)
+ error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
+ else
+ error = VOP_WRITE(vn->sc_vp, &auio, 0, vn->sc_cred);
+ if (isvplocked) {
+ VOP_UNLOCK(vn->sc_vp, 0, curproc);
+ isvplocked = 0;
+ }
+ bp->b_resid = auio.uio_resid;
+
+ if( error )
+ bp->b_flags |= B_ERROR;
+ biodone(bp);
+ } else {
+ long bsize, resid;
+ off_t byten;
+ int flags;
+ caddr_t addr;
+ struct buf *nbp;
+
+ nbp = getvnbuf();
+ byten = dbtob(bn);
+ /* This is probably the only time this is RIGHT */
+ bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
+ addr = bp->b_data;
+ flags = bp->b_flags | B_CALL;
+ for (resid = bp->b_resid; resid; ) {
+ struct vnode *vp;
+ daddr_t nbn;
+ int off, s, nra;
+
+ nra = 0;
+ if (!VOP_ISLOCKED(vn->sc_vp)) {
+ isvplocked = 1;
+ vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
+ }
+ error = VOP_BMAP(vn->sc_vp, (daddr_t)(byten / bsize),
+ &vp, &nbn, &nra, NULL);
+ if (isvplocked) {
+ VOP_UNLOCK(vn->sc_vp, 0, curproc);
+ isvplocked = 0;
+ }
+ if (error == 0 && nbn == -1)
+ error = EIO;
+
+ IFOPT(vn, VN_DONTCLUSTER)
+ nra = 0;
+
+ off = byten % bsize;
+ if (off)
+ sz = bsize - off;
+ else
+ sz = (1 + nra) * bsize;
+ if (resid < sz)
+ sz = resid;
+
+ if (error) {
+ bp->b_resid -= (resid - sz);
+ bp->b_flags |= B_ERROR;
+ biodone(bp);
+ putvnbuf(nbp);
+ return;
+ }
+
+ IFOPT(vn,VN_IO)
+ printf(
+ /* XXX no %qx in kernel. Synthesize it. */
+ "vnstrategy: vp %p/%p bn 0x%lx%08lx/0x%lx sz 0x%x\n",
+ vn->sc_vp, vp, (long)(byten >> 32),
+ (u_long)byten, nbn, sz);
+
+ nbp->b_flags = flags;
+ nbp->b_bcount = sz;
+ nbp->b_bufsize = sz;
+ nbp->b_error = 0;
+ if (vp->v_type == VBLK || vp->v_type == VCHR)
+ nbp->b_dev = vp->v_rdev;
+ else
+ nbp->b_dev = NODEV;
+ nbp->b_data = addr;
+ nbp->b_blkno = nbn + btodb(off);
+ nbp->b_proc = bp->b_proc;
+ nbp->b_iodone = vniodone;
+ nbp->b_vp = vp;
+ nbp->b_rcred = vn->sc_cred; /* XXX crdup? */
+ nbp->b_wcred = vn->sc_cred; /* XXX crdup? */
+ nbp->b_dirtyoff = bp->b_dirtyoff;
+ nbp->b_dirtyend = bp->b_dirtyend;
+ nbp->b_validoff = bp->b_validoff;
+ nbp->b_validend = bp->b_validend;
+
+ if ((nbp->b_flags & B_READ) == 0)
+ nbp->b_vp->v_numoutput++;
+
+ VOP_STRATEGY(nbp);
+
+ s = splbio();
+ while ((nbp->b_flags & B_DONE) == 0) {
+ nbp->b_flags |= B_WANTED;
+ tsleep(nbp, PRIBIO, "vnwait", 0);
+ }
+ splx(s);
+
+ if( nbp->b_flags & B_ERROR) {
+ bp->b_flags |= B_ERROR;
+ bp->b_resid -= (resid - sz);
+ biodone(bp);
+ putvnbuf(nbp);
+ return;
+ }
+
+ byten += sz;
+ addr += sz;
+ resid -= sz;
+ }
+ biodone(bp);
+ putvnbuf(nbp);
+ }
+}
+#endif /* SLICE */
+
void
vniodone( struct buf *bp) {
bp->b_flags |= B_DONE;
@@ -409,6 +603,9 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
struct nameidata nd;
int error;
u_long *f;
+#ifdef SLICE
+ sh_p tp;
+#endif
IFOPT(vn,VN_FOLLOW)
@@ -424,6 +621,7 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
case VNIOCUCLEAR:
goto vn_specific;
}
+#ifndef SLICE
IFOPT(vn,VN_LABELS) {
if (vn->sc_slices != NULL) {
@@ -438,6 +636,7 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
return (ENOTTY);
}
+#endif
vn_specific:
error = suser(p->p_ucred, &p->p_acflag);
@@ -477,6 +676,28 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
}
vio->vn_size = dbtob(vn->sc_size);
vn->sc_flags |= VNF_INITED;
+#ifdef SLICE
+/*
+ * XXX The filesystem blocksize will say 1024
+ * for a 8K filesystem. don't know yet how to deal with this,
+ * so lie for now.. say 512.
+ */
+#if 0
+ vn->limit.blksize = vn->sc_vp->v_mount->mnt_stat.f_bsize;
+#else
+ vn->limit.blksize = DEV_BSIZE;
+#endif
+ vn->slice->limits.blksize = vn->limit.blksize;
+ vn->limit.slicesize = vattr.va_size;
+ vn->slice->limits.slicesize = vattr.va_size;
+ /*
+ * We have a media to read/write.
+ * Try identify it.
+ */
+ if ((tp = slice_probeall(vn->slice)) != NULL) {
+ (*tp->constructor)(vn->slice);
+ }
+#else
IFOPT(vn, VN_LABELS) {
/*
* Reopen so that `ds' knows which devices are open.
@@ -489,6 +710,7 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
if (error)
vnclear(vn);
}
+#endif
IFOPT(vn, VN_FOLLOW)
printf("vnioctl: SET vp %p size %x\n",
vn->sc_vp, vn->sc_size);
@@ -588,6 +810,14 @@ vnclear(struct vn_softc *vn)
IFOPT(vn, VN_FOLLOW)
printf("vnclear(%p): vp=%p\n", vn, vp);
+#ifdef SLICE
+ if (vn->slice->handler_up) {
+ (*(vn->slice->handler_up->revoke)) (vn->slice->private_up);
+ }
+#else /* SLICE */
+ if (vn->sc_slices != NULL)
+ dsgone(&vn->sc_slices);
+#endif
vn->sc_flags &= ~VNF_INITED;
if (vp == (struct vnode *)0)
panic("vnclear: null vp");
@@ -596,10 +826,9 @@ vnclear(struct vn_softc *vn)
vn->sc_vp = (struct vnode *)0;
vn->sc_cred = (struct ucred *)0;
vn->sc_size = 0;
- if (vn->sc_slices != NULL)
- dsgone(&vn->sc_slices);
}
+#ifndef SLICE
static int
vnsize(dev_t dev)
{
@@ -617,44 +846,94 @@ vndump(dev_t dev)
return (ENODEV);
}
-static int vn_devsw_installed;
+static vn_devsw_installed = 0;
+#endif /* !SLICE */
static void
vn_drvinit(void *unused)
{
-#ifdef DEVFS
- int mynor;
- int unit;
- struct vn_softc *vn;
-#endif
-
+#ifndef SLICE
if( ! vn_devsw_installed ) {
if (at_shutdown(&vnshutdown, NULL, SHUTDOWN_POST_SYNC)) {
printf("vn: could not install shutdown hook\n");
return;
}
bdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &vn_bdevsw);
-#ifdef DEVFS
- for (unit = 0; unit < NVN; unit++) {
- vn = vn_softc[unit];
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- /*
- * XXX not saving tokens yet. The vn devices don't
- * exist until after they have been opened :-).
- */
- devfs_add_devswf(&vn_bdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "vn%d", unit);
- devfs_add_devswf(&vn_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rvn%d", unit);
- }
-#endif
vn_devsw_installed = 1;
}
+#else /* SLICE */
+ int mynor;
+ int unit;
+ struct vn_softc *vn;
+ char namebuf[64];
+ if (at_shutdown(&vnshutdown, NULL, SHUTDOWN_POST_SYNC)) {
+ printf("vn: could not install shutdown hook\n");
+ return;
+ }
+ for (unit = 0; unit < NVN; unit++) {
+ vn = malloc(sizeof *vn, M_DEVBUF, M_NOWAIT);
+ if (!vn)
+ return;
+ bzero(vn, sizeof *vn);
+ vn_softc[unit] = vn;
+ vn->unit = unit;
+ sprintf(namebuf,"vn%d",vn->unit);
+ vn->mynor = dkmakeminor(unit, WHOLE_DISK_SLICE,
+ RAW_PART);
+ vn->limit.blksize = DEV_BSIZE;
+ vn->limit.slicesize = ((u_int64_t)vn->sc_size * DEV_BSIZE);
+ sl_make_slice(&slicetype,
+ vn,
+ &vn->limit,
+ &vn->slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ vn->slice->probeinfo.typespecific = NULL;
+ vn->slice->probeinfo.type = NULL;
+ }
+#define CDEV_MAJOR 20 /* not really needed */
+#endif /* SLICE */
}
SYSINIT(vndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,vn_drvinit,NULL)
+#ifdef SLICE
+
+static int
+nvsopen(void *private, int flags, int mode, struct proc *p)
+{
+ struct vn_softc *vn;
+
+ vn = private;
+
+ IFOPT(vn, VN_FOLLOW)
+ printf("vnopen(0x%lx, 0x%x, 0x%x, %p)\n",
+ makedev(0,vn->mynor) , flags, mode, p);
+ return (0);
+}
+static void
+nvsclose(void *private, int flags, int mode, struct proc *p)
+{
+ struct vn_softc *vn;
+
+ vn = private;
+ IFOPT(vn, VN_FOLLOW)
+ printf("vnclose(0x%lx, 0x%x, 0x%x, %p)\n",
+ makedev(0,vn->mynor) , flags, mode, p);
+ return;
+}
+
+static int
+nvsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct vn_softc *vn;
+
+ vn = private;
+
+ return(vnioctl(makedev(0,vn->mynor), cmd, addr, flag, p));
+}
+
+#endif
#endif
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 1431b19..c4a4a57 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
- * $Id: cd9660_vfsops.c,v 1.34 1998/03/01 22:46:00 msmith Exp $
+ * $Id: cd9660_vfsops.c,v 1.35 1998/03/08 09:56:41 julian Exp $
*/
#include <sys/param.h>
@@ -143,6 +143,9 @@ iso_get_ssector(dev, p)
return ntohl(t.entry.addr.lba);
}
+#ifdef SLICE
+extern struct vnode *root_device_vnode;
+#endif
static int
iso_mountroot(mp, p)
@@ -152,10 +155,18 @@ iso_mountroot(mp, p)
struct iso_args args;
int error;
+#ifdef SLICE
+ rootvp = root_device_vnode;
+ if (rootvp == NULL) {
+ printf("cd9660_mountroot: rootvp not set");
+ return (EINVAL);
+ }
+#else
if ((error = bdevvp(rootdev, &rootvp))) {
printf("iso_mountroot: can't find rootvp");
return (error);
}
+#endif
args.flags = ISOFSMNT_ROOT;
args.ssector = iso_get_ssector(rootdev, p);
if (bootverbose)
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 666322f..82f001d 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
- * $Id: spec_vnops.c,v 1.59 1998/03/08 08:46:18 dyson Exp $
+ * $Id: spec_vnops.c,v 1.60 1998/03/08 09:57:36 julian Exp $
*/
#include <sys/param.h>
@@ -761,8 +761,15 @@ spec_getpages(ap)
* Round up physical size for real devices, use the
* fundamental blocksize of the fs if possible.
*/
- if (vp && vp->v_mount)
+ if (vp && vp->v_mount) {
+ if (vp->v_type != VBLK) {
+ vprint("Non VBLK", vp);
+ }
blksiz = vp->v_mount->mnt_stat.f_bsize;
+ if (blksiz < DEV_BSIZE) {
+ blksiz = DEV_BSIZE;
+ }
+ }
else
blksiz = DEV_BSIZE;
size = (ap->a_count + blksiz - 1) & ~(blksiz - 1);
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index 21bf3c4..b41d6ac 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.424 1998/04/09 22:28:57 sos Exp $
+# $Id: LINT,v 1.425 1998/04/18 04:58:00 ahasty Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -470,8 +470,10 @@ options UNION #Union filesystem
options "CD9660_ROOT" #CD-ROM usable as root device
options FFS_ROOT #FFS usable as root device
options NFS_ROOT #NFS usable as root device
-# This DEVFS is experimental but seems to work
+# DEVFS and SLICE are experimental but seems to work.
+# SLICE disables too much old code so enabling it in LINT would be bad
options DEVFS #devices filesystem
+#options SLICE #devfs based disk handling
# Allow the FFS to use Softupdates technology.
# To do this you need to fetch the two files
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 21bf3c4..b41d6ac 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.424 1998/04/09 22:28:57 sos Exp $
+# $Id: LINT,v 1.425 1998/04/18 04:58:00 ahasty Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -470,8 +470,10 @@ options UNION #Union filesystem
options "CD9660_ROOT" #CD-ROM usable as root device
options FFS_ROOT #FFS usable as root device
options NFS_ROOT #NFS usable as root device
-# This DEVFS is experimental but seems to work
+# DEVFS and SLICE are experimental but seems to work.
+# SLICE disables too much old code so enabling it in LINT would be bad
options DEVFS #devices filesystem
+#options SLICE #devfs based disk handling
# Allow the FFS to use Softupdates technology.
# To do this you need to fetch the two files
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index a08df9d..f0a9e71 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.195 1998/03/23 16:44:22 peter Exp $
+# $Id: files.i386,v 1.196 1998/04/06 15:49:35 peter Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -36,6 +36,7 @@ i386/eisa/eisaconf.c optional eisa
i386/eisa/if_vx_eisa.c optional vx device-driver
i386/eisa/if_fea.c optional fea device-driver
i386/i386/autoconf.c standard device-driver
+i386/i386/mountroot.c optional slice
i386/i386/bios.c standard
i386/i386/bioscall.s standard
i386/i386/busdma_machdep.c standard
diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c
index 6d96c0c..1aeef1c 100644
--- a/sys/i386/i386/autoconf.c
+++ b/sys/i386/i386/autoconf.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
- * $Id: autoconf.c,v 1.91 1998/03/16 12:07:54 msmith Exp $
+ * $Id: autoconf.c,v 1.92 1998/03/17 00:28:02 msmith Exp $
*/
/*
@@ -107,6 +107,7 @@ SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
static void configure_finish __P((void));
static void configure_start __P((void));
static int setdumpdev __P((dev_t dev));
+#ifndef SLICE
static void setroot __P((void));
#ifdef CD9660
@@ -135,6 +136,7 @@ static struct {
static int find_cdrom_root __P((void));
+
static int
find_cdrom_root()
{
@@ -170,6 +172,7 @@ find_cdrom_root()
return EINVAL;
}
#endif /* CD9660 */
+#endif /* !SLICE */
static void
configure_start()
@@ -300,6 +303,8 @@ configure(dummy)
cold = 0;
}
+#ifndef SLICE
+
void
cpu_rootconf()
{
@@ -370,6 +375,24 @@ cpu_rootconf()
}
#endif
+#if defined(LFS) || defined(LFS_ROOT)
+ if (!mountrootfsname) {
+ if (bootverbose)
+ printf("Considering LFS root f/s.\n");
+ mountrootfsname = "lfs";
+ /*
+ * Ignore the -a flag if this kernel isn't compiled
+ * with a generic root/swap configuration: if we skip
+ * setroot() and we aren't a generic kernel, chaos
+ * will ensue because setconf() will be a no-op.
+ * (rootdev is always initialized to NODEV in a
+ * generic configuration, so we test for that.)
+ */
+ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
+ setroot();
+ }
+#endif
+
if (!mountrootfsname) {
panic("Nobody wants to mount my root for me");
}
@@ -377,6 +400,8 @@ cpu_rootconf()
setconf();
}
+#endif
+
void
cpu_dumpconf()
{
@@ -420,6 +445,8 @@ setdumpdev(dev)
return (0);
}
+#ifndef SLICE
+
u_long bootdev = 0; /* not a dev_t - encoding is different */
/* Name lookup for bootable majors XXX extend me */
@@ -484,6 +511,8 @@ setroot()
printf("changing root device to %s%s\n", sname, partname);
}
+#endif
+
static int
sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
{
diff --git a/sys/i386/i386/mountroot.c b/sys/i386/i386/mountroot.c
new file mode 100644
index 0000000..4dfbb83
--- /dev/null
+++ b/sys/i386/i386/mountroot.c
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
+ * $Id: autoconf.c,v 1.82 1997/11/21 18:27:08 bde Exp $
+ */
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time and initializes the vba
+ * device tables and the memory controller monitoring. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+#include "opt_cd9660.h"
+#include "opt_ffs.h"
+#include "opt_nfs.h"
+#include "opt_mfs.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/devfsext.h>
+#include <sys/disklabel.h>
+#include <sys/reboot.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <machine/bootinfo.h>
+#include <machine/md_var.h>
+
+u_long bootdev = 0; /* from bootblocks: not dev_t - encoding is different */
+struct vnode *root_device_vnode = NULL;
+char root_device_name[64];
+
+
+/*#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <machine/clock.h> */
+
+struct major_hack {
+ int major;
+ char *name;
+} hack_major[] = {
+{0, "wd"}, /* ST506 disk controller (with IDE extensions) */
+{2, "fd"}, /* floppy disk */
+{3, "wt"}, /* QIC-02/36 tape */
+{4, "sd"}, /* SCSI "disk" type */
+{5, "st"}, /* SCSI "tape" type */
+{6, "cd"}, /* SCSI "cdrom" type */
+{7, "mcd"}, /* Mitsumi CDROM interface */
+{15, "vn"}, /* vnode disk device */
+{16, "scd"}, /* Sony CDROM interface */
+{17, "matcd"}, /* Matsushita/Panasonic/Creative(SB) CDROM interface */
+{18, "ata"}, /* "device independent" ATA/IDE driver */
+{19, "wcdb"}, /* ATAPI CDROM client of "ata" */
+{20, "od"}, /* SCSI "magneto-optical" disk */
+{21, "ccd"}, /* concatenated disk */
+{22, "gd"}, /* Geometry disk. */
+{23, "worm"}, /* SCSI "worm type" */
+{0, NULL}
+};
+
+static struct {
+ char *name;
+ int major;
+} try_cdrom[] = {
+ { "cd", 6 },
+ { "mcd", 7 },
+ { "scd", 16 },
+ { "matcd", 17 },
+ { "wcd", 19 },
+ { 0, 0}
+};
+
+#ifdef CD9660
+/*
+ * XXX All this CD-ROM root stuff is fairly messy. Ick.
+ * We need to look for a cdrom that we can open.
+ * Of course we don't KNOW which, so just try them all in
+ * an arbitrary order.
+ * If we find one, we open it and put it's vnode into the right place.
+ * (and the name)
+ */
+static int
+find_cdrom_root(void)
+{
+ int i, j, error;
+ struct bdevsw *bd;
+ char buf[32];
+ struct vnode *vn;
+
+#if CD9660_ROOTDELAY > 0
+ DELAY(CD9660_ROOTDELAY * 1000000);
+#endif
+ for (i = 0 ; i < 2; i++) {
+ for (j = 0 ; try_cdrom[j].name ; j++) {
+ if (try_cdrom[j].major >= nblkdev)
+ continue;
+ /*if (bootverbose)*/
+ printf("trying %s%d as rootdev\n",
+ try_cdrom[j].name, i);
+ sprintf(buf, "\%s%d", try_cdrom[j].name, i);
+ vn = devfs_open_device(buf, DV_BLK);
+ if (vn) {
+ root_device_vnode = vn;
+ strcpy(root_device_name, buf);
+ rootdev = makedev(try_cdrom[j].major, i * 8);
+ return 0;
+ }
+ }
+ }
+ return EINVAL;
+}
+#endif /* CD9660 */
+
+
+/*
+ * Open a standard 386BSD compatible disk, according to the
+ * old rules (sd0a is the a part of the first BSD slice on sd0.)
+ */
+static int
+open_root_by_major(dev_t dev)
+{
+ /*
+ * given a dev_t (from god-only knows where)
+ * turn it into a sane device name.
+ */
+ int maj = major(dev);
+ int min = minor(dev);
+ int unit = (min >> 3) & 0x0f;
+ int part = (min & 0x07);
+ int i = 0;
+ struct major_hack *mp;
+ struct vnode *vn;
+ char buf[32];
+
+ mp = hack_major;
+ while (mp->name) {
+ if ( mp->major == maj)
+ break;
+ mp++;
+ }
+ if (mp->name == NULL) {
+ return (EINVAL);
+ }
+
+ /* try see if we have old style partitions */
+ sprintf(buf,"/%s%d%c", mp->name, unit, 'a'+ part);
+ printf ("WOULD SELECT %s ", buf);
+ if ((vn = devfs_open_device(buf, DV_BLK))) {
+ printf("And it exists\n");
+ } else {
+ printf("but it doesn't exist\n");
+ for ( i = 1; i < 5; i++ ) {
+ sprintf(buf,"/%s%ds%d%c", mp->name, unit, i, 'a'+ part);
+ if ((vn = devfs_open_device(buf, DV_BLK))) {
+ printf("%s exists, I'll use that\n", buf);
+ break;
+ } else {
+ printf ("%s didn't work\n", buf);
+ }
+ }
+ if (i == 5) {
+ return (EINVAL);
+ }
+ }
+ if (vn) {
+ root_device_vnode = vn;
+ strcpy(root_device_name, buf);
+ rootdev = devfs_vntodev(vn);
+ return (0);
+ }
+ return (EINVAL);
+}
+
+/*
+ * Attempt to find the device from which we were booted.
+ * If we can do so, and not instructed not to do so,
+ * change rootdev to correspond to the load device.
+ */
+static void
+setroot(void)
+{
+ int majdev, mindev, unit, part, adaptor;
+ dev_t newrootdev;
+ struct vnode *vn;
+ char buf[32];
+
+/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
+ /*
+ * If bootdev is screwy, just open the default device
+ * that was compiled in.
+ */
+ if (boothowto & RB_DFLTROOT ||
+ (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) {
+ open_root_by_major(rootdev);
+ return;
+ }
+ majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
+ unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
+ part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+
+ /*
+ * We have two choices.. do it by hand
+ * or use the major/minor we were given
+ */
+ switch (majdev) {
+ case 2: /*fd*/
+ sprintf(buf,"/fd%d", unit);
+ if ((vn = devfs_open_device(buf, DV_BLK))) {
+ root_device_vnode = vn;
+ strcpy(root_device_name, buf);
+ rootdev = devfs_vntodev(vn);
+ }
+ break;
+ case 0: /*wd*/
+ case 4: /*sd*/
+ newrootdev = makedev(majdev,(unit * 8)+part);
+ open_root_by_major(newrootdev);
+ break;
+ default: /* try something different.. you never know.. */
+ open_root_by_major(rootdev);
+ return;
+ }
+ if ( root_device_vnode == NULL) {
+ panic("can't mount root");
+ }
+}
+
+void
+cpu_rootconf()
+{
+ /*
+ * XXX NetBSD has a much cleaner approach to finding root.
+ * XXX We should adopt their code.
+ */
+#ifdef CD9660
+ if ((boothowto & RB_CDROM)) {
+ if (bootverbose)
+ printf("Considering CD-ROM root f/s.\n");
+ /* NB: find_cdrom_root() sets rootdev if successful. */
+ if (find_cdrom_root() == 0)
+ mountrootfsname = "cd9660";
+ else if (bootverbose)
+ printf("No CD-ROM available as root f/s.\n");
+ }
+#endif /* CD9660 */
+
+#ifdef MFS_ROOT
+ if (!mountrootfsname) {
+ if (bootverbose)
+ printf("Considering MFS root f/s.\n");
+ mountrootfsname = "mfs";
+ /*
+ * Ignore the -a flag if this kernel isn't compiled
+ * with a generic root/swap configuration: if we skip
+ * setroot() and we aren't a generic kernel, chaos
+ * will ensue because setconf() will be a no-op.
+ * (rootdev is always initialized to NODEV in a
+ * generic configuration, so we test for that.)
+ */
+ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
+ setroot();
+ }
+#endif
+
+#ifdef BOOTP_NFSROOT
+ if (!mountrootfsname && !nfs_diskless_valid) {
+ if (bootverbose)
+ printf("Considering BOOTP NFS root f/s.\n");
+ mountrootfsname = "nfs";
+ }
+#endif /* BOOTP_NFSROOT */
+#ifdef NFS
+ if (!mountrootfsname && nfs_diskless_valid) {
+ if (bootverbose)
+ printf("Considering NFS root f/s.\n");
+ mountrootfsname = "nfs";
+ }
+#endif /* NFS */
+
+#ifdef FFS
+ if (!mountrootfsname) {
+ mountrootfsname = "ufs";
+ if (bootverbose)
+ printf("Considering FFS root f/s.\n");
+ /*
+ * Ignore the -a flag if this kernel isn't compiled
+ * with a generic root/swap configuration: if we skip
+ * setroot() and we aren't a generic kernel, chaos
+ * will ensue because setconf() will be a no-op.
+ * (rootdev is always initialized to NODEV in a
+ * generic configuration, so we test for that.)
+ */
+ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
+ setroot();
+ }
+#endif
+
+#ifdef LFS
+ if (!mountrootfsname) {
+ if (bootverbose)
+ printf("Considering LFS root f/s.\n");
+ mountrootfsname = "lfs";
+ /*
+ * Ignore the -a flag if this kernel isn't compiled
+ * with a generic root/swap configuration: if we skip
+ * setroot() and we aren't a generic kernel, chaos
+ * will ensue because setconf() will be a no-op.
+ * (rootdev is always initialized to NODEV in a
+ * generic configuration, so we test for that.)
+ */
+ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
+ setroot();
+ }
+#endif
+
+ if (!mountrootfsname) {
+ panic("Nobody wants to mount my root for me");
+ }
+
+ setconf();
+}
+
diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c
index d09b927..abc2634 100644
--- a/sys/i386/isa/fd.c
+++ b/sys/i386/isa/fd.c
@@ -43,7 +43,7 @@
* SUCH DAMAGE.
*
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
- * $Id: fd.c,v 1.107 1998/01/24 02:54:18 eivind Exp $
+ * $Id: fd.c,v 1.108 1998/04/17 22:36:31 des Exp $
*
*/
@@ -82,9 +82,13 @@
#include <sys/ftape.h>
#include <i386/isa/ftreg.h>
#endif
-#ifdef DEVFS
+#ifdef DEVFS
#include <sys/devfsext.h>
-#endif
+#ifdef SLICE
+#include <sys/device.h>
+#include <dev/slice/slice.h>
+#endif /* SLICE */
+#endif /* DEVFS */
/* misuse a flag to identify format operation */
#define B_FORMAT B_XXX
@@ -180,8 +184,21 @@ static struct fd_data {
struct callout_handle toffhandle;
struct callout_handle tohandle;
#ifdef DEVFS
+#ifdef SLICE
+ int unit; /* as in fd0 */
+ void *bdevs[MAXPARTITIONS];
+ void *cdevs[MAXPARTITIONS];
+ struct subdev{
+ struct slice *slice;
+ int minor;
+ struct fd_data *drive;
+ struct slicelimits limit;
+ }subdevs[16];
+ struct intr_config_hook ich;
+#else /* SLICE */
void *bdevs[1 + NUMDENS + MAXPARTITIONS];
void *cdevs[1 + NUMDENS + MAXPARTITIONS];
+#endif /* SLICE */
#endif
} fd_data[NFD];
@@ -227,7 +244,9 @@ static timeout_t fd_timeout;
static timeout_t fd_pseudointr;
static int fdstate(fdcu_t, fdc_p);
static int retrier(fdcu_t);
+#ifndef SLICE
static int fdformat(dev_t, struct fd_formb *, struct proc *);
+#endif
static int enable_fifo(fdc_p fdc);
@@ -284,6 +303,7 @@ static d_close_t fdclose;
static d_ioctl_t fdioctl;
static d_strategy_t fdstrategy;
+/* even if SLICE defined, these are needed for the ft support. */
#define CDEV_MAJOR 9
#define BDEV_MAJOR 2
static struct cdevsw fd_cdevsw;
@@ -294,6 +314,30 @@ static struct bdevsw fd_bdevsw =
static struct isa_device *fdcdevs[NFDC];
+#ifdef SLICE
+static sl_h_IO_req_t fdsIOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t fdsioctl; /* ioctl req downward (to device) */
+static sl_h_open_t fdsopen; /* downwards travelling open */
+static sl_h_close_t fdsclose; /* downwards travelling close */
+static void fdsinit(void *);
+
+static struct slice_handler slicetype = {
+ "floppy",
+ 0,
+ NULL,
+ 0,
+ NULL, /* constructor */
+ &fdsIOreq,
+ &fdsioctl,
+ &fdsopen,
+ &fdsclose,
+ NULL, /* revoke */
+ NULL, /* claim */
+ NULL, /* verify */
+ NULL /* upconfig */
+};
+#endif /* SLICE */
+
static int
fdc_err(fdcu_t fdcu, const char *s)
{
@@ -529,8 +573,12 @@ fdattach(struct isa_device *dev)
struct isa_device *fdup;
int ic_type = 0;
#ifdef DEVFS
+#ifdef SLICE
+ char namebuf[64];
+#else
int mynor;
int typemynor;
+#endif /* SLICE */
int typesize;
#endif
@@ -682,6 +730,9 @@ fdattach(struct isa_device *dev)
continue;
fd->track = FD_NO_TRACK;
+#ifdef SLICE
+ fd->unit = fdu;
+#endif
fd->fdc = fdc;
fd->fdsu = fdsu;
fd->options = 0;
@@ -721,6 +772,30 @@ fdattach(struct isa_device *dev)
continue;
}
#ifdef DEVFS
+#ifdef SLICE
+ sprintf(namebuf,"fd%d",fdu);
+ fd->subdevs[0].minor = 0;
+ fd->subdevs[0].drive = fd;
+ fd->subdevs[0].limit.blksize =
+ 128 << (fd_types[fd->type - 1].secsize);
+ fd->subdevs[0].limit.slicesize =
+ fd_types[fd->type - 1].size
+ * fd->subdevs[0].limit.blksize;
+ fd->ft = fd_types + (fd->type - 1); /* default value */
+ sl_make_slice(&slicetype,
+ &fd->subdevs[0],
+ &fd->subdevs[0].limit,
+ &fd->subdevs[0].slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ fd->subdevs[0].slice->probeinfo.typespecific = NULL;
+ fd->subdevs[0].slice->probeinfo.type = NULL;
+
+ fd->ich.ich_func = fdsinit;
+ fd->ich.ich_arg = &fd->subdevs[0];
+ config_intrhook_establish(&fd->ich);
+#else /* SLICE */
mynor = fdu << 6;
fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -728,6 +803,7 @@ fdattach(struct isa_device *dev)
fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR,
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d", fdu);
+#endif /* SLICE */
for (i = 1; i < 1 + NUMDENS; i++) {
/*
* XXX this and the lookup in Fdopen() should be
@@ -755,7 +831,6 @@ fdattach(struct isa_device *dev)
continue;
break;
}
- typemynor = mynor | i;
typesize = fd_types[i - 1].size / 2;
/*
* XXX all these conversions give bloated code and
@@ -765,6 +840,27 @@ fdattach(struct isa_device *dev)
typesize = 1480;
if (typesize == 1722)
typesize = 1720;
+#ifdef SLICE
+ sprintf(namebuf,"fd%d.%d",fdu,typesize);
+ fd->subdevs[i].minor = i;
+ fd->subdevs[i].drive = fd;
+ fd->subdevs[i].limit.blksize =
+ 128 << (fd_types[i - 1].secsize);
+ fd->subdevs[i].limit.slicesize =
+ fd_types[i - 1].size
+ * fd->subdevs[i].limit.blksize;
+ sl_make_slice(&slicetype,
+ &fd->subdevs[i],
+ &fd->subdevs[i].limit,
+ &fd->subdevs[i].slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ fd->subdevs[i].slice->probeinfo.typespecific = NULL;
+ fd->subdevs[i].slice->probeinfo.type = NO_SUBPART;
+ }
+#else /* SLICE */
+ typemynor = mynor | i;
fd->bdevs[i] =
devfs_add_devswf(&fd_bdevsw, typemynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -774,14 +870,15 @@ fdattach(struct isa_device *dev)
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d.%d", fdu, typesize);
}
+
for (i = 0; i < MAXPARTITIONS; i++) {
- fd->bdevs[1 + NUMDENS + i] =
- devfs_link(fd->bdevs[0],
+ fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0],
"fd%d%c", fdu, 'a' + i);
fd->cdevs[1 + NUMDENS + i] =
devfs_link(fd->cdevs[0],
"rfd%d%c", fdu, 'a' + i);
}
+#endif /* SLICE */
#endif /* DEVFS */
#ifdef notyet
if (dk_ndrive < DK_NDRIVE) {
@@ -800,6 +897,22 @@ fdattach(struct isa_device *dev)
return (1);
}
+
+#ifdef SLICE
+
+static void
+fdsinit(void *arg)
+{
+ struct subdev *sd = arg;
+ sh_p tp;
+
+ if ((tp = slice_probeall(sd->slice)) != NULL) {
+ (*tp->constructor)(sd->slice);
+ }
+ config_intrhook_disestablish(&sd->drive->ich);
+}
+#endif /* SLICE */
+
/****************************************************************************/
/* motor control stuff */
/* remember to not deselect the drive we're working on */
@@ -1022,6 +1135,10 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p)
if (type == 0)
type = fd_data[fdu].type;
else {
+ /*
+ * For each type of basic drive, make sure we are trying
+ * to open a type it can do,
+ */
if (type != fd_data[fdu].type) {
switch (fd_data[fdu].type) {
case FD_360:
@@ -1182,6 +1299,49 @@ bad:
biodone(bp);
}
+#ifdef SLICE
+/****************************************************************************/
+/* fdsIOreq */
+/****************************************************************************/
+static void
+fdsIOreq(void *private ,struct buf *bp)
+{
+ unsigned nblocks, blknum, cando;
+ int s;
+ fdcu_t fdcu;
+ fdu_t fdu;
+ fdc_p fdc;
+ fd_p fd;
+ size_t fdblk;
+ struct subdev *sd;
+
+ sd = private;
+ fd = sd->drive;
+ fdu = fd->unit;
+ fdc = fd->fdc;
+ fdcu = fdc->fdcu;
+
+ /* check for controller already busy with tape */
+ if (fdc->flags & FDC_TAPE_BUSY) {
+ bp->b_error = EBUSY;
+ bp->b_flags |= B_ERROR;
+ goto bad;
+ }
+ bp->b_driver1 = sd; /* squirrel away which device.. */
+ bp->b_resid = 0;
+ s = splbio();
+ bufqdisksort(&fdc->head, bp);
+ untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */
+ fdstart(fdcu);
+ splx(s);
+ return;
+
+bad:
+ biodone(bp);
+ return;
+}
+#endif /* SLICE */
+
/***************************************************************\
* fdstart *
* We have just queued something.. if the controller is not busy *
@@ -1292,6 +1452,7 @@ fdintr(fdcu_t fdcu)
static int
fdstate(fdcu_t fdcu, fdc_p fdc)
{
+ struct subdev *sd;
int read, format, head, sec = 0, sectrac, st0, cyl, st3;
unsigned blknum = 0, b_cylinder = 0;
fdu_t fdu = fdc->fdu;
@@ -1317,8 +1478,14 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
TRACE1("[fdc%d IDLE]", fdcu);
return(0);
}
+#ifdef SLICE
+ sd = bp->b_driver1;
+ fd = sd->drive;
+ fdu = fd->unit;
+#else
fdu = FDUNIT(minor(bp->b_dev));
fd = fd_data + fdu;
+#endif
fdblk = 128 << fd->ft->secsize;
if (fdc->fd && (fd != fdc->fd))
{
@@ -1332,7 +1499,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
- (char *)finfo;
}
if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) {
- blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk +
+ blknum = (unsigned) bp->b_pblkno * DEV_BSIZE/fdblk +
fd->skip/fdblk;
b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
}
@@ -1704,13 +1871,26 @@ static int
retrier(fdcu)
fdcu_t fdcu;
{
+ struct subdev *sd;
fdc_p fdc = fdc_data + fdcu;
register struct buf *bp;
+#ifdef SLICE
+ struct fd_data *fd;
+ int fdu;
+#endif
bp = bufq_first(&fdc->head);
+#ifdef SLICE
+ sd = bp->b_driver1;
+ fd = sd->drive;
+ fdu = fd->unit;
+ if(fd->options & FDOPT_NORETRY)
+ goto fail;
+#else
if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY)
goto fail;
+#endif
switch(fdc->retry)
{
case 0: case 1: case 2:
@@ -1727,14 +1907,19 @@ retrier(fdcu)
default:
fail:
{
+#ifdef SLICE
+ printf("fd%d: hard error, block %d ", fdu,
+ fd->skip / DEV_BSIZE);
+#else
dev_t sav_b_dev = bp->b_dev;
/* Trick diskerr */
bp->b_dev = makedev(major(bp->b_dev),
- (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
+ (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
diskerr(bp, "fd", "hard error", LOG_PRINTF,
fdc->fd->skip / DEV_BSIZE,
(struct disklabel *)NULL);
bp->b_dev = sav_b_dev;
+#endif /* !SLICE */
if (fdc->flags & FDC_STAT_VALID)
{
printf(
@@ -1764,11 +1949,16 @@ retrier(fdcu)
return(1);
}
+#ifdef SLICE
+static int
+fdformat( struct subdev *sd, struct fd_formb *finfo, struct proc *p)
+#else /* !SLICE */
static int
fdformat(dev, finfo, p)
dev_t dev;
struct fd_formb *finfo;
struct proc *p;
+#endif /* !SLICE */
{
fdu_t fdu;
fd_p fd;
@@ -1777,8 +1967,13 @@ fdformat(dev, finfo, p)
int rv = 0, s;
size_t fdblk;
- fdu = FDUNIT(minor(dev));
- fd = &fd_data[fdu];
+#ifdef SLICE
+ fd = sd->drive;
+ fdu = fd->unit;
+#else
+ fdu = FDUNIT(minor(dev));
+ fd = &fd_data[fdu];
+#endif
fdblk = 128 << fd->ft->secsize;
/* set up a buffer header for fdstrategy() */
@@ -1792,7 +1987,6 @@ fdformat(dev, finfo, p)
bzero((void *)bp, sizeof(struct buf));
bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
bp->b_proc = p;
- bp->b_dev = dev;
/*
* calculate a fake blkno, so fdstrategy() would initiate a
@@ -1805,7 +1999,13 @@ fdformat(dev, finfo, p)
bp->b_data = (caddr_t)finfo;
/* now do the format */
+#ifdef SLICE
+ bp->b_driver1 = sd;
+ fdsIOreq(sd, bp);
+#else /* !SLICE */
+ bp->b_dev = dev;
fdstrategy(bp);
+#endif /* !SLICE */
/* ...and wait for it to complete */
s = splbio();
@@ -1836,7 +2036,7 @@ fdformat(dev, finfo, p)
* TODO: don't allocate buffer on stack.
*/
-int
+static int
fdioctl(dev, cmd, addr, flag, p)
dev_t dev;
int cmd;
@@ -1861,10 +2061,33 @@ fdioctl(dev, cmd, addr, flag, p)
return ftioctl(dev, cmd, addr, flag, p);
#endif
+#ifdef SLICE
+ /*
+ * if SLICE is defined then only ft accesses come here
+ * so break the rest off to another function for SLICE access.
+ */
+ return (ENOTTY);
+}
+
+/*
+ * Slice ioctls come here
+ */
+static int
+fdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct subdev *sd = private;
+ fd_p fd = sd->drive;
+ fdu_t fdu = fd->unit;
+ fdc_p fdc = fd->fdc;
+ fdcu_t fdcu = fdc->fdcu;
+ size_t fdblk;
+ int error = 0;
+#endif /* SLICE */
fdblk = 128 << fd->ft->secsize;
switch (cmd)
{
+#ifndef SLICE
case DIOCGDINFO:
bzero(buffer, sizeof (buffer));
dl = (struct disklabel *)buffer;
@@ -1908,7 +2131,7 @@ fdioctl(dev, cmd, addr, flag, p)
error = writedisklabel(dev, fdstrategy,
(struct disklabel *)buffer);
break;
-
+#endif /* !SLICE */
case FD_FORM:
if((flag & FWRITE) == 0)
error = EBADF; /* must be opened for writing */
@@ -1916,26 +2139,30 @@ fdioctl(dev, cmd, addr, flag, p)
FD_FORMAT_VERSION)
error = EINVAL; /* wrong version of formatting prog */
else
+#ifdef SLICE
+ error = fdformat(sd, (struct fd_formb *)addr, p);
+#else
error = fdformat(dev, (struct fd_formb *)addr, p);
+#endif
break;
case FD_GTYPE: /* get drive type */
- *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft;
+ *(struct fd_type *)addr = *fd->ft;
break;
case FD_STYPE: /* set drive type */
/* this is considered harmful; only allow for superuser */
if(suser(p->p_ucred, &p->p_acflag) != 0)
return EPERM;
- *fd_data[FDUNIT(minor(dev))].ft = *(struct fd_type *)addr;
+ *fd->ft = *(struct fd_type *)addr;
break;
case FD_GOPTS: /* get drive options */
- *(int *)addr = fd_data[FDUNIT(minor(dev))].options;
+ *(int *)addr = fd->options;
break;
case FD_SOPTS: /* set drive options */
- fd_data[FDUNIT(minor(dev))].options = *(int *)addr;
+ fd->options = *(int *)addr;
break;
default:
@@ -1959,7 +2186,32 @@ static void fd_drvinit(void *notused )
SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL)
+
+#ifdef SLICE
+static int
+fdsopen(void *private, int flags, int mode, struct proc *p)
+{
+ struct subdev *sd;
+
+ sd = private;
+
+ return(Fdopen(makedev(0,sd->minor), 0 , 0, p));
+}
+
+static void
+fdsclose(void *private, int flags, int mode, struct proc *p)
+{
+ struct subdev *sd;
+
+ sd = private;
+
+ fdclose(makedev(0,sd->minor), 0 , 0, p);
+ return ;
+}
+
+#endif /* SLICE */
#endif
+
/*
* Hello emacs, these are the
* Local Variables:
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 26b3832..92a6a08 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
- * $Id: wd.c,v 1.157 1998/04/18 13:25:49 obrien Exp $
+ * $Id: wd.c,v 1.158 1998/04/19 03:26:05 peter Exp $
*/
/* TODO:
@@ -80,7 +80,12 @@
#include <sys/buf.h>
#include <sys/malloc.h>
#ifdef DEVFS
+#ifdef SLICE
+#include <sys/device.h>
+#include <dev/slice/slice.h>
+#else
#include <sys/devfsext.h>
+#endif /*SLICE*/
#endif /*DEVFS*/
#include <machine/bootinfo.h>
#include <machine/clock.h>
@@ -170,9 +175,16 @@ struct disk {
int dk_port; /* i/o port base */
int dk_altport; /* altstatus port base */
#ifdef DEVFS
+#ifdef SLICE
+ struct slice *slice;
+ int minor;
+ struct slicelimits limit;
+ struct intr_config_hook ich;
+#else
void *dk_bdev; /* devfs token for whole disk */
void *dk_cdev; /* devfs token for raw whole disk */
-#endif
+#endif /* SLICE */
+#endif /* DEVFS */
u_long cfg_flags; /* configured characteristics */
short dk_flags; /* drive characteristics found */
#define DKFL_SINGLE 0x00004 /* sector at a time mode */
@@ -243,6 +255,33 @@ struct isa_driver wdcdriver = {
wdprobe, wdattach, "wdc",
};
+#ifdef SLICE
+
+static sl_h_IO_req_t wdsIOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t wdsioctl; /* ioctl req downward (to device) */
+static sl_h_open_t wdsopen; /* downwards travelling open */
+static sl_h_close_t wdsclose; /* downwards travelling close */
+static void wds_init(void*);
+
+static struct slice_handler slicetype = {
+ "IDE",
+ 0,
+ NULL,
+ 0,
+ NULL, /* constructor */
+ &wdsIOreq,
+ &wdsioctl,
+ &wdsopen,
+ &wdsclose,
+ NULL, /* revoke */
+ NULL, /* claim */
+ NULL, /* verify */
+ NULL /* upconfig */
+};
+#endif
+
+#ifndef SLICE
+
static d_open_t wdopen;
static d_close_t wdclose;
static d_strategy_t wdstrategy;
@@ -256,6 +295,7 @@ static struct cdevsw wd_cdevsw;
static struct bdevsw wd_bdevsw =
{ wdopen, wdclose, wdstrategy, wdioctl, /*0*/
wddump, wdsize, D_DISK, "wd", &wd_cdevsw, -1 };
+#endif /* !SLICE */
#ifdef CMD640
static int atapictrlr;
@@ -404,7 +444,7 @@ nodevice:
static int
wdattach(struct isa_device *dvp)
{
-#ifdef DEVFS
+#if defined(DEVFS) && ! defined(SLICE)
int mynor;
#endif
int unit, lunit;
@@ -485,12 +525,18 @@ wdattach(struct isa_device *dvp)
if (du->cfg_flags & WDOPT_SLEEPHACK)
printf(", sleep-hack");
printf("\n");
+#ifdef SLICE
+/*
+ * Here we somehow schedule the geometry HACK fro later and print
+ * something meaningful.
+ */
+#endif
if (du->dk_params.wdp_heads == 0)
printf("wd%d: size unknown, using %s values\n",
lunit, du->dk_dd.d_secperunit > 17
? "BIOS" : "fake");
- printf(
-"wd%d: %luMB (%lu sectors), %lu cyls, %lu heads, %lu S/T, %lu B/S\n",
+ printf( "wd%d: %luMB (%lu sectors), "
+ "%lu cyls, %lu heads, %lu S/T, %lu B/S\n",
lunit,
du->dk_dd.d_secperunit
/ ((1024L * 1024L) / du->dk_dd.d_secsize),
@@ -502,8 +548,9 @@ wdattach(struct isa_device *dvp)
if (bootverbose) {
wp = &du->dk_params;
- printf(
-"wd%d: ATA INQUIRE valid = %04x, dmamword = %04x, apio = %04x, udma = %04x\n",
+ printf( "wd%d: ATA INQUIRE valid = %04x, "
+ "dmamword = %04x, apio = %04x, "
+ "udma = %04x\n",
du->dk_lunit,
wp->wdp_atavalid,
wp->wdp_dmamword,
@@ -518,6 +565,36 @@ wdattach(struct isa_device *dvp)
wdtimeout(du);
#ifdef DEVFS
+#ifdef SLICE
+ {
+ char namebuf[64];
+ sprintf(namebuf,"wd%d",lunit);
+ du->minor = dkmakeminor(lunit,
+ WHOLE_DISK_SLICE, RAW_PART);
+ du->limit.blksize = du->dk_dd.d_secsize;
+ du->limit.slicesize =
+ (u_int64_t)du->dk_dd.d_secsize *
+ du->dk_dd.d_secperunit;
+ /*
+ * Fill in the 3 geometry entries
+ * to tell the mbr code
+ * we already know it, so that it
+ * doesn't try deduce it.
+ */
+ sl_make_slice(&slicetype,
+ du,
+ &du->limit,
+ &du->slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ du->slice->probeinfo.typespecific = NULL;
+ du->slice->probeinfo.type = NULL;
+ }
+ du->ich.ich_func = wds_init;
+ du->ich.ich_arg = du;
+ config_intrhook_establish(&du->ich);
+#else
mynor = dkmakeminor(lunit, WHOLE_DISK_SLICE, RAW_PART);
du->dk_bdev = devfs_add_devswf(&wd_bdevsw, mynor,
DV_BLK, UID_ROOT,
@@ -528,6 +605,7 @@ wdattach(struct isa_device *dvp)
GID_OPERATOR, 0640,
"rwd%d", lunit);
#endif
+#endif
if (dk_ndrive < DK_NDRIVE) {
sprintf(dk_names[dk_ndrive], "wd%d", lunit);
@@ -583,6 +661,47 @@ next: ;
return (1);
}
+#ifdef SLICE
+extern struct proc *curproc;
+static void
+wds_init(void *arg)
+{
+ struct disk *du = arg;
+ sh_p tp;
+ int err = 0;
+ struct ide_geom geom;
+
+ if ((err = wdsopen(du, 0, 0, curproc))) {
+ printf("wd open failed with %d", err);
+ return;
+ }
+ /*
+ * If we still don't have geometry,
+ * Then call the IDE geometry HACK functions.
+ */
+#if 0
+ if ( ?? ) { /* how do we know? */
+ bzero (&geom, sizeof(geom));
+ if (mbr_geom_hack(du->slice)) && (dkl_geom_hack(du->slice)) {
+ printf("We really have no geometry\n");
+ } else {
+ du->dk_dd.d_secperunit = (geom.cyls *
+ geom.trackpercyl * geom.secpertrack);
+ du->dk_dd.d_ncylinders = geom.cyls;
+ du->dk_dd.d_ntracks = geom.trackpercyl;
+ du->dk_dd.d_nsectors = geom.secpertrack;
+ }
+ }
+#endif
+ if ((tp = slice_probeall(du->slice)) != NULL) {
+ (*tp->constructor)(du->slice);
+ }
+ config_intrhook_disestablish(&du->ich);
+ wdsclose(du, 0, 0, curproc);
+}
+#endif
+
+#ifndef SLICE
/* Read/write routine for a buffer. Finds the proper unit, range checks
* arguments, and schedules the transfer. Does not wait for the transfer
* to complete. Multi-page transfers are supported. All I/O requests must
@@ -695,6 +814,7 @@ wdstrategy1(struct buf *bp)
*/
wdstrategy(bp);
}
+#endif /* !SLICE */
/*
* Routine to queue a command to the controller. The unit's
@@ -720,6 +840,11 @@ wdustart(register struct disk *du)
if (bp == NULL) { /* yes, an assign */
return;
}
+ /*
+ * store away which device we came from.
+ */
+ bp->b_driver1 = du;
+
bufq_remove(&drive_queue[du->dk_lunit], bp);
/* link onto controller queue */
@@ -727,6 +852,7 @@ wdustart(register struct disk *du)
/* mark the drive unit as busy */
wdutab[du->dk_lunit].b_active = 1;
+
}
/*
@@ -781,8 +907,13 @@ wdstart(int ctrlr)
}
/* obtain controller and drive information */
+#ifdef SLICE
+ du = bp->b_driver1;
+ lunit = du->dk_lunit;
+#else /* !SLICE */
lunit = dkunit(bp->b_dev);
du = wddrives[lunit];
+#endif /* !SLICE */
/* if not really a transfer, do control operations specially */
if (du->dk_state < OPEN) {
@@ -822,6 +953,7 @@ wdstart(int ctrlr)
du->dk_flags |= DKFL_SINGLE;
}
+#ifndef SLICE
if (du->dk_flags & DKFL_SINGLE
&& dsgetbad(bp->b_dev, du->dk_slices) != NULL) {
/* XXX */
@@ -831,6 +963,7 @@ wdstart(int ctrlr)
blknum = transbad144(dsgetbad(bp->b_dev, du->dk_slices),
blknum - ds_offset) + ds_offset;
}
+#endif
wdtab[ctrlr].b_active = 1; /* mark controller active */
@@ -1077,7 +1210,11 @@ wdintr(int unit)
}
#endif
bp = bufq_first(&wdtab[unit].controller_queue);
+#ifdef SLICE
+ du = bp->b_driver1;
+#else /* !SLICE */
du = wddrives[dkunit(bp->b_dev)];
+#endif /* !SLICE */
/* finish off DMA */
if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) {
@@ -1284,6 +1421,7 @@ done: ;
wdstart(unit);
}
+#ifndef SLICE
/*
* Initialize a drive.
*/
@@ -1460,6 +1598,7 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
return (0);
#endif
}
+#endif /* !SLICE */
/*
* Implement operations other than read/write.
@@ -1473,7 +1612,11 @@ wdcontrol(register struct buf *bp)
register struct disk *du;
int ctrlr;
+#ifdef SLICE
+ du = bp->b_driver1;
+#else /* !SLICE */
du = wddrives[dkunit(bp->b_dev)];
+#endif /* !SLICE */
#ifdef CMD640
ctrlr = du->dk_ctrlr_cmd640;
#else
@@ -1953,6 +2096,7 @@ failed:
return (0);
}
+#ifndef SLICE
int
wdclose(dev_t dev, int flags, int fmt, struct proc *p)
{
@@ -1974,11 +2118,12 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
du = wddrives[lunit];
wdsleep(du->dk_ctrlr, "wdioct");
+#ifndef SLICE
error = dsioctl("wd", dev, cmd, addr, flags, &du->dk_slices,
wdstrategy1, (ds_setgeom_t *)NULL);
if (error != ENOIOCTL)
return (error);
-
+#endif /* SLICE */
switch (cmd) {
case DIOCSBADSCAN:
if (*(int *)addr)
@@ -2240,15 +2385,20 @@ out:
}
return (0);
}
+#endif /* !SLICE */
static void
wderror(struct buf *bp, struct disk *du, char *mesg)
{
+#ifndef SLICE
+ printf("wd%d: %s:\n", du->dk_lunit, mesg);
+#else /* !SLICE */
if (bp == NULL)
printf("wd%d: %s:\n", du->dk_lunit, mesg);
else
diskerr(bp, "wd", mesg, LOG_PRINTF, du->dk_skip,
dsgetlabel(bp->b_dev, du->dk_slices));
+#endif /* !SLICE */
printf("wd%d: status %b error %b\n", du->dk_lunit,
du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS);
}
@@ -2471,6 +2621,7 @@ wdwait(struct disk *du, u_char bits_wanted, int timeout)
return (-1);
}
+#ifndef SLICE
static wd_devsw_installed = 0;
static void wd_drvinit(void *unused)
@@ -2485,6 +2636,128 @@ static void wd_drvinit(void *unused)
}
SYSINIT(wddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,wd_drvinit,NULL)
+#endif /* !SLICE */
+
+
+
+#ifdef SLICE
+/*
+ * Read/write routine for a buffer. Finds the proper unit, range checks
+ * arguments, and schedules the transfer. Does not wait for the transfer
+ * to complete. Multi-page transfers are supported. All I/O requests must
+ * be a multiple of a sector in length.
+ */
+static void
+wdsIOreq(void *private ,struct buf *bp)
+{
+ struct disk *du = private;
+ int s;
+ int lunit = du->dk_lunit;
+
+ /* queue transfer on drive, activate drive and controller if idle */
+ s = splbio();
+
+ bufqdisksort(&drive_queue[lunit], bp);
+
+ /*
+ * Move the head of the drive queue to the controller queue.
+ */
+ if (wdutab[lunit].b_active == 0)
+ wdustart(du);
+
+ /*
+ * Kick off the controller if there is anything for IT to do.
+ */
+#ifdef CMD640
+ if (wdtab[du->dk_ctrlr_cmd640].b_active == 0)
+#else
+ if (wdtab[du->dk_ctrlr].b_active == 0)
+#endif
+ wdstart(du->dk_ctrlr); /* start controller */
+
+ splx(s);
+ return;
+
+}
+
+/*
+ * Initialize a drive.
+ */
+static int
+wdsopen(void *private, int flags, int mode, struct proc *p)
+{
+ register struct disk *du;
+ register unsigned int lunit;
+ int error = 0;
+
+ du = private;
+
+ /* Finish flushing IRQs left over from wdattach(). */
+#ifdef CMD640
+ if (wdtab[du->dk_ctrlr_cmd640].b_active == 2)
+ wdtab[du->dk_ctrlr_cmd640].b_active = 0;
+#else
+ if (wdtab[du->dk_ctrlr].b_active == 2)
+ wdtab[du->dk_ctrlr].b_active = 0;
+#endif
+
+ du->dk_state = OPEN;
+ du->dk_flags &= ~DKFL_BADSCAN;
+
+ return (error);
+}
+
+static void
+wdsclose(void *private, int flags, int mode, struct proc *p)
+{
+ register struct disk *du;
+
+ du = private;
+ du->dk_state = CLOSED;
+ return;
+}
+
+static int
+wdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ register struct disk *du;
+ int error;
+ du = private;
+ wdsleep(du->dk_ctrlr, "wdioct");
+ switch (cmd) {
+ case DIOCSBADSCAN:
+ if (*(int *)addr)
+ du->dk_flags |= DKFL_BADSCAN;
+ else
+ du->dk_flags &= ~DKFL_BADSCAN;
+ return (0);
+#ifdef notyet
+ case DIOCWFORMAT:
+ if (!(flag & FWRITE))
+ return (EBADF);
+ fop = (struct format_op *)addr;
+ aiov.iov_base = fop->df_buf;
+ aiov.iov_len = fop->df_count;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = fop->df_count;
+ auio.uio_segflg = 0;
+ auio.uio_offset = fop->df_startblk * du->dk_dd.d_secsize;
+#error /* XXX the 386BSD interface is different */
+ error = physio(wdformat, &rwdbuf[lunit], 0, dev, B_WRITE,
+ minphys, &auio);
+ fop->df_count -= auio.uio_resid;
+ fop->df_reg[0] = du->dk_status;
+ fop->df_reg[1] = du->dk_error;
+ return (error);
+#endif
+
+ default:
+ return (ENOTTY);
+ }
+}
+
+#endif /* NWDC > 0 */
#endif /* NWDC > 0 */
diff --git a/sys/isa/fd.c b/sys/isa/fd.c
index d09b927..abc2634 100644
--- a/sys/isa/fd.c
+++ b/sys/isa/fd.c
@@ -43,7 +43,7 @@
* SUCH DAMAGE.
*
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91
- * $Id: fd.c,v 1.107 1998/01/24 02:54:18 eivind Exp $
+ * $Id: fd.c,v 1.108 1998/04/17 22:36:31 des Exp $
*
*/
@@ -82,9 +82,13 @@
#include <sys/ftape.h>
#include <i386/isa/ftreg.h>
#endif
-#ifdef DEVFS
+#ifdef DEVFS
#include <sys/devfsext.h>
-#endif
+#ifdef SLICE
+#include <sys/device.h>
+#include <dev/slice/slice.h>
+#endif /* SLICE */
+#endif /* DEVFS */
/* misuse a flag to identify format operation */
#define B_FORMAT B_XXX
@@ -180,8 +184,21 @@ static struct fd_data {
struct callout_handle toffhandle;
struct callout_handle tohandle;
#ifdef DEVFS
+#ifdef SLICE
+ int unit; /* as in fd0 */
+ void *bdevs[MAXPARTITIONS];
+ void *cdevs[MAXPARTITIONS];
+ struct subdev{
+ struct slice *slice;
+ int minor;
+ struct fd_data *drive;
+ struct slicelimits limit;
+ }subdevs[16];
+ struct intr_config_hook ich;
+#else /* SLICE */
void *bdevs[1 + NUMDENS + MAXPARTITIONS];
void *cdevs[1 + NUMDENS + MAXPARTITIONS];
+#endif /* SLICE */
#endif
} fd_data[NFD];
@@ -227,7 +244,9 @@ static timeout_t fd_timeout;
static timeout_t fd_pseudointr;
static int fdstate(fdcu_t, fdc_p);
static int retrier(fdcu_t);
+#ifndef SLICE
static int fdformat(dev_t, struct fd_formb *, struct proc *);
+#endif
static int enable_fifo(fdc_p fdc);
@@ -284,6 +303,7 @@ static d_close_t fdclose;
static d_ioctl_t fdioctl;
static d_strategy_t fdstrategy;
+/* even if SLICE defined, these are needed for the ft support. */
#define CDEV_MAJOR 9
#define BDEV_MAJOR 2
static struct cdevsw fd_cdevsw;
@@ -294,6 +314,30 @@ static struct bdevsw fd_bdevsw =
static struct isa_device *fdcdevs[NFDC];
+#ifdef SLICE
+static sl_h_IO_req_t fdsIOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t fdsioctl; /* ioctl req downward (to device) */
+static sl_h_open_t fdsopen; /* downwards travelling open */
+static sl_h_close_t fdsclose; /* downwards travelling close */
+static void fdsinit(void *);
+
+static struct slice_handler slicetype = {
+ "floppy",
+ 0,
+ NULL,
+ 0,
+ NULL, /* constructor */
+ &fdsIOreq,
+ &fdsioctl,
+ &fdsopen,
+ &fdsclose,
+ NULL, /* revoke */
+ NULL, /* claim */
+ NULL, /* verify */
+ NULL /* upconfig */
+};
+#endif /* SLICE */
+
static int
fdc_err(fdcu_t fdcu, const char *s)
{
@@ -529,8 +573,12 @@ fdattach(struct isa_device *dev)
struct isa_device *fdup;
int ic_type = 0;
#ifdef DEVFS
+#ifdef SLICE
+ char namebuf[64];
+#else
int mynor;
int typemynor;
+#endif /* SLICE */
int typesize;
#endif
@@ -682,6 +730,9 @@ fdattach(struct isa_device *dev)
continue;
fd->track = FD_NO_TRACK;
+#ifdef SLICE
+ fd->unit = fdu;
+#endif
fd->fdc = fdc;
fd->fdsu = fdsu;
fd->options = 0;
@@ -721,6 +772,30 @@ fdattach(struct isa_device *dev)
continue;
}
#ifdef DEVFS
+#ifdef SLICE
+ sprintf(namebuf,"fd%d",fdu);
+ fd->subdevs[0].minor = 0;
+ fd->subdevs[0].drive = fd;
+ fd->subdevs[0].limit.blksize =
+ 128 << (fd_types[fd->type - 1].secsize);
+ fd->subdevs[0].limit.slicesize =
+ fd_types[fd->type - 1].size
+ * fd->subdevs[0].limit.blksize;
+ fd->ft = fd_types + (fd->type - 1); /* default value */
+ sl_make_slice(&slicetype,
+ &fd->subdevs[0],
+ &fd->subdevs[0].limit,
+ &fd->subdevs[0].slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ fd->subdevs[0].slice->probeinfo.typespecific = NULL;
+ fd->subdevs[0].slice->probeinfo.type = NULL;
+
+ fd->ich.ich_func = fdsinit;
+ fd->ich.ich_arg = &fd->subdevs[0];
+ config_intrhook_establish(&fd->ich);
+#else /* SLICE */
mynor = fdu << 6;
fd->bdevs[0] = devfs_add_devswf(&fd_bdevsw, mynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -728,6 +803,7 @@ fdattach(struct isa_device *dev)
fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR,
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d", fdu);
+#endif /* SLICE */
for (i = 1; i < 1 + NUMDENS; i++) {
/*
* XXX this and the lookup in Fdopen() should be
@@ -755,7 +831,6 @@ fdattach(struct isa_device *dev)
continue;
break;
}
- typemynor = mynor | i;
typesize = fd_types[i - 1].size / 2;
/*
* XXX all these conversions give bloated code and
@@ -765,6 +840,27 @@ fdattach(struct isa_device *dev)
typesize = 1480;
if (typesize == 1722)
typesize = 1720;
+#ifdef SLICE
+ sprintf(namebuf,"fd%d.%d",fdu,typesize);
+ fd->subdevs[i].minor = i;
+ fd->subdevs[i].drive = fd;
+ fd->subdevs[i].limit.blksize =
+ 128 << (fd_types[i - 1].secsize);
+ fd->subdevs[i].limit.slicesize =
+ fd_types[i - 1].size
+ * fd->subdevs[i].limit.blksize;
+ sl_make_slice(&slicetype,
+ &fd->subdevs[i],
+ &fd->subdevs[i].limit,
+ &fd->subdevs[i].slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ fd->subdevs[i].slice->probeinfo.typespecific = NULL;
+ fd->subdevs[i].slice->probeinfo.type = NO_SUBPART;
+ }
+#else /* SLICE */
+ typemynor = mynor | i;
fd->bdevs[i] =
devfs_add_devswf(&fd_bdevsw, typemynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -774,14 +870,15 @@ fdattach(struct isa_device *dev)
UID_ROOT, GID_OPERATOR, 0640,
"rfd%d.%d", fdu, typesize);
}
+
for (i = 0; i < MAXPARTITIONS; i++) {
- fd->bdevs[1 + NUMDENS + i] =
- devfs_link(fd->bdevs[0],
+ fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0],
"fd%d%c", fdu, 'a' + i);
fd->cdevs[1 + NUMDENS + i] =
devfs_link(fd->cdevs[0],
"rfd%d%c", fdu, 'a' + i);
}
+#endif /* SLICE */
#endif /* DEVFS */
#ifdef notyet
if (dk_ndrive < DK_NDRIVE) {
@@ -800,6 +897,22 @@ fdattach(struct isa_device *dev)
return (1);
}
+
+#ifdef SLICE
+
+static void
+fdsinit(void *arg)
+{
+ struct subdev *sd = arg;
+ sh_p tp;
+
+ if ((tp = slice_probeall(sd->slice)) != NULL) {
+ (*tp->constructor)(sd->slice);
+ }
+ config_intrhook_disestablish(&sd->drive->ich);
+}
+#endif /* SLICE */
+
/****************************************************************************/
/* motor control stuff */
/* remember to not deselect the drive we're working on */
@@ -1022,6 +1135,10 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p)
if (type == 0)
type = fd_data[fdu].type;
else {
+ /*
+ * For each type of basic drive, make sure we are trying
+ * to open a type it can do,
+ */
if (type != fd_data[fdu].type) {
switch (fd_data[fdu].type) {
case FD_360:
@@ -1182,6 +1299,49 @@ bad:
biodone(bp);
}
+#ifdef SLICE
+/****************************************************************************/
+/* fdsIOreq */
+/****************************************************************************/
+static void
+fdsIOreq(void *private ,struct buf *bp)
+{
+ unsigned nblocks, blknum, cando;
+ int s;
+ fdcu_t fdcu;
+ fdu_t fdu;
+ fdc_p fdc;
+ fd_p fd;
+ size_t fdblk;
+ struct subdev *sd;
+
+ sd = private;
+ fd = sd->drive;
+ fdu = fd->unit;
+ fdc = fd->fdc;
+ fdcu = fdc->fdcu;
+
+ /* check for controller already busy with tape */
+ if (fdc->flags & FDC_TAPE_BUSY) {
+ bp->b_error = EBUSY;
+ bp->b_flags |= B_ERROR;
+ goto bad;
+ }
+ bp->b_driver1 = sd; /* squirrel away which device.. */
+ bp->b_resid = 0;
+ s = splbio();
+ bufqdisksort(&fdc->head, bp);
+ untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */
+ fdstart(fdcu);
+ splx(s);
+ return;
+
+bad:
+ biodone(bp);
+ return;
+}
+#endif /* SLICE */
+
/***************************************************************\
* fdstart *
* We have just queued something.. if the controller is not busy *
@@ -1292,6 +1452,7 @@ fdintr(fdcu_t fdcu)
static int
fdstate(fdcu_t fdcu, fdc_p fdc)
{
+ struct subdev *sd;
int read, format, head, sec = 0, sectrac, st0, cyl, st3;
unsigned blknum = 0, b_cylinder = 0;
fdu_t fdu = fdc->fdu;
@@ -1317,8 +1478,14 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
TRACE1("[fdc%d IDLE]", fdcu);
return(0);
}
+#ifdef SLICE
+ sd = bp->b_driver1;
+ fd = sd->drive;
+ fdu = fd->unit;
+#else
fdu = FDUNIT(minor(bp->b_dev));
fd = fd_data + fdu;
+#endif
fdblk = 128 << fd->ft->secsize;
if (fdc->fd && (fd != fdc->fd))
{
@@ -1332,7 +1499,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
- (char *)finfo;
}
if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) {
- blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk +
+ blknum = (unsigned) bp->b_pblkno * DEV_BSIZE/fdblk +
fd->skip/fdblk;
b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
}
@@ -1704,13 +1871,26 @@ static int
retrier(fdcu)
fdcu_t fdcu;
{
+ struct subdev *sd;
fdc_p fdc = fdc_data + fdcu;
register struct buf *bp;
+#ifdef SLICE
+ struct fd_data *fd;
+ int fdu;
+#endif
bp = bufq_first(&fdc->head);
+#ifdef SLICE
+ sd = bp->b_driver1;
+ fd = sd->drive;
+ fdu = fd->unit;
+ if(fd->options & FDOPT_NORETRY)
+ goto fail;
+#else
if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY)
goto fail;
+#endif
switch(fdc->retry)
{
case 0: case 1: case 2:
@@ -1727,14 +1907,19 @@ retrier(fdcu)
default:
fail:
{
+#ifdef SLICE
+ printf("fd%d: hard error, block %d ", fdu,
+ fd->skip / DEV_BSIZE);
+#else
dev_t sav_b_dev = bp->b_dev;
/* Trick diskerr */
bp->b_dev = makedev(major(bp->b_dev),
- (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
+ (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
diskerr(bp, "fd", "hard error", LOG_PRINTF,
fdc->fd->skip / DEV_BSIZE,
(struct disklabel *)NULL);
bp->b_dev = sav_b_dev;
+#endif /* !SLICE */
if (fdc->flags & FDC_STAT_VALID)
{
printf(
@@ -1764,11 +1949,16 @@ retrier(fdcu)
return(1);
}
+#ifdef SLICE
+static int
+fdformat( struct subdev *sd, struct fd_formb *finfo, struct proc *p)
+#else /* !SLICE */
static int
fdformat(dev, finfo, p)
dev_t dev;
struct fd_formb *finfo;
struct proc *p;
+#endif /* !SLICE */
{
fdu_t fdu;
fd_p fd;
@@ -1777,8 +1967,13 @@ fdformat(dev, finfo, p)
int rv = 0, s;
size_t fdblk;
- fdu = FDUNIT(minor(dev));
- fd = &fd_data[fdu];
+#ifdef SLICE
+ fd = sd->drive;
+ fdu = fd->unit;
+#else
+ fdu = FDUNIT(minor(dev));
+ fd = &fd_data[fdu];
+#endif
fdblk = 128 << fd->ft->secsize;
/* set up a buffer header for fdstrategy() */
@@ -1792,7 +1987,6 @@ fdformat(dev, finfo, p)
bzero((void *)bp, sizeof(struct buf));
bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
bp->b_proc = p;
- bp->b_dev = dev;
/*
* calculate a fake blkno, so fdstrategy() would initiate a
@@ -1805,7 +1999,13 @@ fdformat(dev, finfo, p)
bp->b_data = (caddr_t)finfo;
/* now do the format */
+#ifdef SLICE
+ bp->b_driver1 = sd;
+ fdsIOreq(sd, bp);
+#else /* !SLICE */
+ bp->b_dev = dev;
fdstrategy(bp);
+#endif /* !SLICE */
/* ...and wait for it to complete */
s = splbio();
@@ -1836,7 +2036,7 @@ fdformat(dev, finfo, p)
* TODO: don't allocate buffer on stack.
*/
-int
+static int
fdioctl(dev, cmd, addr, flag, p)
dev_t dev;
int cmd;
@@ -1861,10 +2061,33 @@ fdioctl(dev, cmd, addr, flag, p)
return ftioctl(dev, cmd, addr, flag, p);
#endif
+#ifdef SLICE
+ /*
+ * if SLICE is defined then only ft accesses come here
+ * so break the rest off to another function for SLICE access.
+ */
+ return (ENOTTY);
+}
+
+/*
+ * Slice ioctls come here
+ */
+static int
+fdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct subdev *sd = private;
+ fd_p fd = sd->drive;
+ fdu_t fdu = fd->unit;
+ fdc_p fdc = fd->fdc;
+ fdcu_t fdcu = fdc->fdcu;
+ size_t fdblk;
+ int error = 0;
+#endif /* SLICE */
fdblk = 128 << fd->ft->secsize;
switch (cmd)
{
+#ifndef SLICE
case DIOCGDINFO:
bzero(buffer, sizeof (buffer));
dl = (struct disklabel *)buffer;
@@ -1908,7 +2131,7 @@ fdioctl(dev, cmd, addr, flag, p)
error = writedisklabel(dev, fdstrategy,
(struct disklabel *)buffer);
break;
-
+#endif /* !SLICE */
case FD_FORM:
if((flag & FWRITE) == 0)
error = EBADF; /* must be opened for writing */
@@ -1916,26 +2139,30 @@ fdioctl(dev, cmd, addr, flag, p)
FD_FORMAT_VERSION)
error = EINVAL; /* wrong version of formatting prog */
else
+#ifdef SLICE
+ error = fdformat(sd, (struct fd_formb *)addr, p);
+#else
error = fdformat(dev, (struct fd_formb *)addr, p);
+#endif
break;
case FD_GTYPE: /* get drive type */
- *(struct fd_type *)addr = *fd_data[FDUNIT(minor(dev))].ft;
+ *(struct fd_type *)addr = *fd->ft;
break;
case FD_STYPE: /* set drive type */
/* this is considered harmful; only allow for superuser */
if(suser(p->p_ucred, &p->p_acflag) != 0)
return EPERM;
- *fd_data[FDUNIT(minor(dev))].ft = *(struct fd_type *)addr;
+ *fd->ft = *(struct fd_type *)addr;
break;
case FD_GOPTS: /* get drive options */
- *(int *)addr = fd_data[FDUNIT(minor(dev))].options;
+ *(int *)addr = fd->options;
break;
case FD_SOPTS: /* set drive options */
- fd_data[FDUNIT(minor(dev))].options = *(int *)addr;
+ fd->options = *(int *)addr;
break;
default:
@@ -1959,7 +2186,32 @@ static void fd_drvinit(void *notused )
SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL)
+
+#ifdef SLICE
+static int
+fdsopen(void *private, int flags, int mode, struct proc *p)
+{
+ struct subdev *sd;
+
+ sd = private;
+
+ return(Fdopen(makedev(0,sd->minor), 0 , 0, p));
+}
+
+static void
+fdsclose(void *private, int flags, int mode, struct proc *p)
+{
+ struct subdev *sd;
+
+ sd = private;
+
+ fdclose(makedev(0,sd->minor), 0 , 0, p);
+ return ;
+}
+
+#endif /* SLICE */
#endif
+
/*
* Hello emacs, these are the
* Local Variables:
diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c
index 1431b19..c4a4a57 100644
--- a/sys/isofs/cd9660/cd9660_vfsops.c
+++ b/sys/isofs/cd9660/cd9660_vfsops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
- * $Id: cd9660_vfsops.c,v 1.34 1998/03/01 22:46:00 msmith Exp $
+ * $Id: cd9660_vfsops.c,v 1.35 1998/03/08 09:56:41 julian Exp $
*/
#include <sys/param.h>
@@ -143,6 +143,9 @@ iso_get_ssector(dev, p)
return ntohl(t.entry.addr.lba);
}
+#ifdef SLICE
+extern struct vnode *root_device_vnode;
+#endif
static int
iso_mountroot(mp, p)
@@ -152,10 +155,18 @@ iso_mountroot(mp, p)
struct iso_args args;
int error;
+#ifdef SLICE
+ rootvp = root_device_vnode;
+ if (rootvp == NULL) {
+ printf("cd9660_mountroot: rootvp not set");
+ return (EINVAL);
+ }
+#else
if ((error = bdevvp(rootdev, &rootvp))) {
printf("iso_mountroot: can't find rootvp");
return (error);
}
+#endif
args.flags = ISOFSMNT_ROOT;
args.ssector = iso_get_ssector(rootdev, p);
if (bootverbose)
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 3de881d..c6659bf 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -39,7 +39,7 @@
* SUCH DAMAGE.
*
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
- * $Id: init_main.c,v 1.89 1998/04/11 17:24:06 phk Exp $
+ * $Id: init_main.c,v 1.90 1998/04/17 22:36:49 des Exp $
*/
#include "opt_devfs.h"
@@ -582,7 +582,7 @@ start_init(p)
options = 1;
#endif
-#if defined(DEVFS) && defined(DEVFS_ROOT)
+#if defined(DEVFS) && defined(SLICE)
(void)subyte(--ucp, 'd');
options = 1;
#endif
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c
index 5ffb5db..4b11dc6 100644
--- a/sys/kern/subr_diskslice.c
+++ b/sys/kern/subr_diskslice.c
@@ -1,3 +1,6 @@
+#ifdef SLICE
+#undef DEVFS
+#endif
/*-
* Copyright (c) 1994 Bruce D. Evans.
* All rights reserved.
@@ -43,7 +46,7 @@
* from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
* from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
* from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
- * $Id: subr_diskslice.c,v 1.41 1998/01/24 02:54:34 eivind Exp $
+ * $Id: subr_diskslice.c,v 1.42 1998/02/15 05:41:31 bde Exp $
*/
#include "opt_devfs.h"
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index a42a89a..ffe86ce 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_conf.c 8.8 (Berkeley) 3/31/94
- * $Id: vfs_conf.c,v 1.21 1998/02/09 06:09:32 eivind Exp $
+ * $Id: vfs_conf.c,v 1.22 1998/03/11 00:10:31 msmith Exp $
*/
/*
@@ -73,9 +73,12 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct");
static struct mount *rootfs;
struct vnode *rootvnode;
char *mountrootfsname;
+#ifdef SLICE
+char rootdevice[32];
+#endif /* SLICE */
#ifdef BOOTP
extern void bootpc_init __P((void));
-#endif
+#endif /* BOOTP */
/*
* vfs_init() will set maxvfsconf
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 8e6c9dc..5e6386e 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
- * $Id: vfs_subr.c,v 1.150 1998/04/16 03:31:26 peter Exp $
+ * $Id: vfs_subr.c,v 1.151 1998/04/18 06:26:16 peter Exp $
*/
/*
@@ -71,6 +71,9 @@
#include <vm/vm_zone.h>
#include <sys/sysctl.h>
+#if defined(DEVFS)
+#include <sys/devfsext.h>
+#endif /* DEVFS */
#include <miscfs/specfs/specdev.h>
static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
@@ -1090,7 +1093,7 @@ reassignbuf(bp, newvp)
splx(s);
}
-#ifndef DEVFS_ROOT
+#ifndef SLICE
/*
* Create a vnode for a block device.
* Used for mounting the root file system.
@@ -1120,7 +1123,7 @@ bdevvp(dev, vpp)
*vpp = vp;
return (0);
}
-#endif /* !DEVFS_ROOT */
+#endif /* !SLICE */
/*
* Check to see if the new vnode represents a special device
@@ -1151,6 +1154,8 @@ loop:
continue;
/*
* Alias, but not in use, so flush it out.
+ * Only alias active device nodes.
+ * Not sure why we don't re-use this like we do below.
*/
simple_lock(&vp->v_interlock);
if (vp->v_usecount == 0) {
@@ -1159,12 +1164,26 @@ loop:
goto loop;
}
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
+ /*
+ * It dissappeared, and we may have slept.
+ * Restart from the beginning
+ */
simple_unlock(&spechash_slock);
goto loop;
}
break;
}
+ /*
+ * It would be a lot clearer what is going on here if
+ * this had been expressed as:
+ * if ( vp && (vp->v_tag == VT_NULL))
+ * and the clauses had been swapped.
+ */
if (vp == NULL || vp->v_tag != VT_NON) {
+ /*
+ * Put the new vnode into the hash chain.
+ * and if there was an alias, connect them.
+ */
MALLOC(nvp->v_specinfo, struct specinfo *,
sizeof(struct specinfo), M_VNODE, M_WAITOK);
nvp->v_rdev = nvp_rdev;
@@ -1180,6 +1199,12 @@ loop:
}
return (NULLVP);
}
+ /*
+ * if ( vp && (vp->v_tag == VT_NULL))
+ * We have a vnode alias, but it is a trashed.
+ * Make it look like it's newley allocated. (by getnewvnode())
+ * The caller should use this instead.
+ */
simple_unlock(&spechash_slock);
VOP_UNLOCK(vp, 0, p);
simple_lock(&vp->v_interlock);
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index a42a89a..ffe86ce 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_conf.c 8.8 (Berkeley) 3/31/94
- * $Id: vfs_conf.c,v 1.21 1998/02/09 06:09:32 eivind Exp $
+ * $Id: vfs_conf.c,v 1.22 1998/03/11 00:10:31 msmith Exp $
*/
/*
@@ -73,9 +73,12 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct");
static struct mount *rootfs;
struct vnode *rootvnode;
char *mountrootfsname;
+#ifdef SLICE
+char rootdevice[32];
+#endif /* SLICE */
#ifdef BOOTP
extern void bootpc_init __P((void));
-#endif
+#endif /* BOOTP */
/*
* vfs_init() will set maxvfsconf
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 8e6c9dc..5e6386e 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
- * $Id: vfs_subr.c,v 1.150 1998/04/16 03:31:26 peter Exp $
+ * $Id: vfs_subr.c,v 1.151 1998/04/18 06:26:16 peter Exp $
*/
/*
@@ -71,6 +71,9 @@
#include <vm/vm_zone.h>
#include <sys/sysctl.h>
+#if defined(DEVFS)
+#include <sys/devfsext.h>
+#endif /* DEVFS */
#include <miscfs/specfs/specdev.h>
static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
@@ -1090,7 +1093,7 @@ reassignbuf(bp, newvp)
splx(s);
}
-#ifndef DEVFS_ROOT
+#ifndef SLICE
/*
* Create a vnode for a block device.
* Used for mounting the root file system.
@@ -1120,7 +1123,7 @@ bdevvp(dev, vpp)
*vpp = vp;
return (0);
}
-#endif /* !DEVFS_ROOT */
+#endif /* !SLICE */
/*
* Check to see if the new vnode represents a special device
@@ -1151,6 +1154,8 @@ loop:
continue;
/*
* Alias, but not in use, so flush it out.
+ * Only alias active device nodes.
+ * Not sure why we don't re-use this like we do below.
*/
simple_lock(&vp->v_interlock);
if (vp->v_usecount == 0) {
@@ -1159,12 +1164,26 @@ loop:
goto loop;
}
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
+ /*
+ * It dissappeared, and we may have slept.
+ * Restart from the beginning
+ */
simple_unlock(&spechash_slock);
goto loop;
}
break;
}
+ /*
+ * It would be a lot clearer what is going on here if
+ * this had been expressed as:
+ * if ( vp && (vp->v_tag == VT_NULL))
+ * and the clauses had been swapped.
+ */
if (vp == NULL || vp->v_tag != VT_NON) {
+ /*
+ * Put the new vnode into the hash chain.
+ * and if there was an alias, connect them.
+ */
MALLOC(nvp->v_specinfo, struct specinfo *,
sizeof(struct specinfo), M_VNODE, M_WAITOK);
nvp->v_rdev = nvp_rdev;
@@ -1180,6 +1199,12 @@ loop:
}
return (NULLVP);
}
+ /*
+ * if ( vp && (vp->v_tag == VT_NULL))
+ * We have a vnode alias, but it is a trashed.
+ * Make it look like it's newley allocated. (by getnewvnode())
+ * The caller should use this instead.
+ */
simple_unlock(&spechash_slock);
VOP_UNLOCK(vp, 0, p);
simple_lock(&vp->v_interlock);
diff --git a/sys/miscfs/devfs/devfs_tree.c b/sys/miscfs/devfs/devfs_tree.c
index c7c561e..6d03fa6 100644
--- a/sys/miscfs/devfs/devfs_tree.c
+++ b/sys/miscfs/devfs/devfs_tree.c
@@ -1,4 +1,4 @@
-/*#define SPLIT_DEVS 1*/
+
/*
* Copyright 1997,1998 Julian Elischer. All rights reserved.
* julian@freebsd.org
@@ -24,15 +24,20 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: devfs_tree.c,v 1.50 1998/03/26 20:52:05 phk Exp $
+ * $Id: devfs_tree.c,v 1.51 1998/04/17 22:36:53 des Exp $
*/
+
+#define SPLIT_DEVS 1
+/*#define SPLIT_DEVS 1*/
+
#include "opt_devfs.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>
+#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/proc.h>
@@ -894,44 +899,6 @@ DBPRINT((" vntodn "));
return(0);
}
-#ifdef DEVFS_ROOT
-static dn_p
-findbdev(dev_t dev, dn_p dir)
-{
- devnm_p newfp;
- dn_p dnp;
-
- for(newfp = dir->by.Dir.dirlist;newfp;newfp=newfp->next) {
- dnp = newfp->dnp;
- if (dnp->type == DEV_BDEV && dnp->by.Bdev.dev == dev) {
- return (dnp);
- }
- if (dnp->type == DEV_DIR) {
- if (dnp = findbdev(dev, dnp))
- return dnp;
- }
- }
- return (0);
-}
-
-/*
- * Create a vnode for a block device.
- * Used for mounting the root file system.
- */
-int
-bdevvp(dev_t dev, struct vnode **vpp)
-{
- dn_p dnp = 0;
-
- if (dev == NODEV)
- return(0);
- dnp= findbdev(dev, dev_root->dnp);
- if (!dnp)
- return (ENOENT);
- return (devfs_dntovn(dnp, vpp));
-}
-#endif /* DEVFS_ROOT */
-
/***************************************************************\
* given a dev_node, find the appropriate vnode if one is already*
* associated, or get a new one an associate it with the dev_node*
@@ -1207,3 +1174,116 @@ devfs_link(void *original, char *fmt, ...)
return new_dev;
}
+/*
+ * internal kernel call to open a device. Return either 0 or an open vnode.
+ */
+struct vnode *
+devfs_open_device(char *path, int type)
+{
+ register char *lastslash;
+ char *nextpart;
+ devnm_p nm_p;
+ dn_p dirnode;
+ struct vnode *vn;
+
+ /*
+ * If the caller didn't supply a full path, ignore and be
+ * noisy about it.
+ */
+ if (*path != '/') {
+ printf (__FUNCTION__ ": caller supplied bad path\n");
+ return (NULL);
+ }
+
+ /*
+ * find the last '/'. Unfortunatly rindex() while being in
+ * libkern source, is not being compiled.. do it by hand.
+ * lastslash = strrchr(path,(int)'c');
+ * There will be at LEAST one '/'.
+ */
+ {
+ register char *p = path; /* don't destroy path */
+
+ for (lastslash = NULL;*p; ++p) {
+ if (*p == '/')
+ lastslash = p;
+ }
+ }
+ dirnode = dev_root->dnp;
+ if(lastslash != path) {
+ /* find the directory we need */
+ *lastslash = '\0';
+ if (dev_finddir(path, dirnode, NULL, &dirnode) != 0) {
+ *lastslash = '/';
+ return (NULL);
+ }
+ /* ok we found the directory, put the slash back */
+ *lastslash = '/';
+ }
+ nextpart = ++lastslash;
+ if (*nextpart == '\0')
+ return (NULL);
+ /*
+ * Now only return true if it exists and is the right type.
+ */
+ if ((nm_p = dev_findname(dirnode, nextpart)) == NULL) {
+ return (NULL);
+ }
+ switch(type) {
+ case DV_BLK:
+ if( nm_p->dnp->type != DEV_BDEV)
+ return (NULL);
+ break;
+ case DV_CHR:
+ if( nm_p->dnp->type != DEV_CDEV)
+ return (NULL);
+ break;
+ }
+
+ if ( devfs_dntovn(nm_p->dnp, &vn))
+ return (NULL);
+
+#if 0
+ if ( VOP_OPEN(vn, FREAD, proc0.p_cred->pc_ucred, &proc0)) {
+ vput(vn);
+ return (NULL);
+ }
+#endif
+ return (vn);
+}
+
+/*
+ * internal kernel call to close a devfs device.
+ * It should have been openned by th ecall above.
+ * try not mix it with user-openned vnodes.
+ * Frees the vnode.
+ */
+void
+devfs_close_device(struct vnode *vn)
+{
+#if 0
+ VOP_CLOSE(vn, 0, proc0.p_cred->pc_ucred, &proc0) ;
+#endif
+ vput(vn);
+}
+
+/*
+ * Little utility routine for compatibilty.
+ * Returns the dev_t that a devfs vnode represents.
+ * should go away after dev_t go away :).
+ */
+dev_t
+devfs_vntodev(struct vnode *vn)
+{
+ register dn_p dnp;
+ dnp = (dn_p)vn->v_data;
+ switch (dnp->type) {
+ case DEV_BDEV:
+ return (dnp->by.Bdev.dev);
+ break;
+ case DEV_CDEV:
+ return (dnp->by.Cdev.dev);
+ break;
+ }
+ panic ("bad devfs DEVICE vnode");
+}
diff --git a/sys/miscfs/devfs/devfs_vfsops.c b/sys/miscfs/devfs/devfs_vfsops.c
index 442dc1b..c87ec56 100644
--- a/sys/miscfs/devfs/devfs_vfsops.c
+++ b/sys/miscfs/devfs/devfs_vfsops.c
@@ -23,10 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: devfs_vfsops.c,v 1.27 1998/03/01 22:46:08 msmith Exp $
+ * $Id: devfs_vfsops.c,v 1.28 1998/04/17 22:36:53 des Exp $
*
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
diff --git a/sys/miscfs/devfs/devfs_vnops.c b/sys/miscfs/devfs/devfs_vnops.c
index 773d903..6c9bae7 100644
--- a/sys/miscfs/devfs/devfs_vnops.c
+++ b/sys/miscfs/devfs/devfs_vnops.c
@@ -1,3 +1,4 @@
+
/*
* Copyright 1997,1998 Julian Elischer. All rights reserved.
* julian@freebsd.org
@@ -23,9 +24,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: devfs_vnops.c,v 1.52 1998/03/10 09:12:19 julian Exp $
+ * $Id: devfs_vnops.c,v 1.53 1998/03/26 20:52:12 phk Exp $
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
@@ -482,33 +484,23 @@ DBPRINT(("getattr\n"));
vap->va_fileid = (long)file_node;
vap->va_size = file_node->len; /* now a u_quad_t */
vap->va_blocksize = 512;
- if(file_node->ctime.tv_sec)
- {
- vap->va_ctime = file_node->ctime;
- }
- else
- {
- TIMEVAL_TO_TIMESPEC(&boottime,&(vap->va_ctime));
- }
- if(file_node->mtime.tv_sec)
- {
- vap->va_mtime = file_node->mtime;
- }
- else
- {
- TIMEVAL_TO_TIMESPEC(&boottime,&(vap->va_mtime));
- }
- if(file_node->atime.tv_sec)
- {
- vap->va_atime = file_node->atime;
- }
- else
+ /*
+ * XXX If the node times are in Jan 1, 1970, then
+ * update them to the boot time.
+ * When we made the node, the date/time was not yet known.
+ */
+ if(file_node->ctime.tv_sec < (24 * 3600))
{
- TIMEVAL_TO_TIMESPEC(&boottime,&(vap->va_atime));
+ TIMEVAL_TO_TIMESPEC(&boottime,&(file_node->ctime));
+ TIMEVAL_TO_TIMESPEC(&boottime,&(file_node->mtime));
+ TIMEVAL_TO_TIMESPEC(&boottime,&(file_node->atime));
}
+ vap->va_ctime = file_node->ctime;
+ vap->va_mtime = file_node->mtime;
+ vap->va_atime = file_node->atime;
vap->va_gen = 0;
vap->va_flags = 0;
- vap->va_bytes = file_node->len; /* u_quad_t */
+ vap->va_bytes = file_node->len; /* u_quad_t */
vap->va_filerev = 0; /* XXX */ /* u_quad_t */
vap->va_vaflags = 0; /* XXX */
return 0;
diff --git a/sys/miscfs/devfs/devfsdefs.h b/sys/miscfs/devfs/devfsdefs.h
index b475e22..ef31dd9 100644
--- a/sys/miscfs/devfs/devfsdefs.h
+++ b/sys/miscfs/devfs/devfsdefs.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: devfsdefs.h,v 1.12 1997/10/11 18:31:29 phk Exp $
+ * $Id: devfsdefs.h,v 1.13 1998/01/02 07:31:07 julian Exp $
*/
#ifdef DEVFS_DEBUG
#define DBPRINT(A) printf(A)
@@ -31,7 +31,6 @@
#define DBPRINT(A)
#endif
-
/* first a couple of defines for compatibility with inodes */
#define ISUID 04000 /* set user identifier when exec'ing */
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index 666322f..82f001d 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
- * $Id: spec_vnops.c,v 1.59 1998/03/08 08:46:18 dyson Exp $
+ * $Id: spec_vnops.c,v 1.60 1998/03/08 09:57:36 julian Exp $
*/
#include <sys/param.h>
@@ -761,8 +761,15 @@ spec_getpages(ap)
* Round up physical size for real devices, use the
* fundamental blocksize of the fs if possible.
*/
- if (vp && vp->v_mount)
+ if (vp && vp->v_mount) {
+ if (vp->v_type != VBLK) {
+ vprint("Non VBLK", vp);
+ }
blksiz = vp->v_mount->mnt_stat.f_bsize;
+ if (blksiz < DEV_BSIZE) {
+ blksiz = DEV_BSIZE;
+ }
+ }
else
blksiz = DEV_BSIZE;
size = (ap->a_count + blksiz - 1) & ~(blksiz - 1);
diff --git a/sys/miscfs/specfs/specdev.h b/sys/miscfs/specfs/specdev.h
index b4c6f77..9c225a3 100644
--- a/sys/miscfs/specfs/specdev.h
+++ b/sys/miscfs/specfs/specdev.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)specdev.h 8.6 (Berkeley) 5/21/95
- * $Id: specdev.h,v 1.13 1997/10/15 13:23:21 phk Exp $
+ * $Id: specdev.h,v 1.14 1998/03/08 09:57:40 julian Exp $
*/
/*
@@ -43,7 +43,8 @@ struct specinfo {
struct vnode **si_hashchain;
struct vnode *si_specnext;
struct mount *si_mountpoint;
- dev_t si_rdev;
+ dev_t si_rdev;
+ unsigned long si_blksize; /* smallest IO unit */
};
/*
* Exported shorthand
@@ -52,6 +53,7 @@ struct specinfo {
#define v_hashchain v_specinfo->si_hashchain
#define v_specnext v_specinfo->si_specnext
#define v_specmountpoint v_specinfo->si_mountpoint
+#define v_blksize v_specinfo->si_blksize
/*
* Special device management
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
index bbc83ae..a5d6236 100644
--- a/sys/scsi/sd.c
+++ b/sys/scsi/sd.c
@@ -1,4 +1,3 @@
-
/*
* Written by Julian Elischer (julian@dialix.oz.au)
* for TRW Financial Systems for use under the MACH(2.5) operating system.
@@ -15,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
*
- * $Id: sd.c,v 1.122 1998/04/15 17:47:21 bde Exp $
+ * $Id: sd.c,v 1.123 1998/04/17 22:37:10 des Exp $
*/
#include "opt_bounce.h"
@@ -35,7 +34,11 @@
#include <sys/conf.h>
#ifdef DEVFS
#include <sys/devfsext.h>
-#endif /*DEVFS*/
+#ifdef SLICE
+#include <sys/device.h>
+#include <dev/slice/slice.h>
+#endif /* SLICE */
+#endif /* DEVFS */
#include <scsi/scsi_disk.h>
#include <scsi/scsiconf.h>
@@ -93,8 +96,17 @@ struct scsi_data {
struct buf_queue_head buf_queue;
int dkunit; /* disk stats unit number */
#ifdef DEVFS
+#ifdef SLICE
+ struct slice *slice;
+ int mynor;
+ struct slicelimits limit;
+ struct scsi_link *sc_link;
+ int unit;
+ struct intr_config_hook ich;
+#else /* SLICE */
void *b_devfs_token;
void *c_devfs_token;
+#endif /* SLICE */
void *ctl_devfs_token;
#endif
};
@@ -119,10 +131,35 @@ static d_strategy_t sdstrategy;
#define CDEV_MAJOR 13
#define BDEV_MAJOR 4
+#ifndef SLICE
static struct cdevsw sd_cdevsw;
static struct bdevsw sd_bdevsw =
{ sdopen, sdclose, sdstrategy, sdioctl, /*4*/
sddump, sdsize, D_DISK, "sd", &sd_cdevsw, -1 };
+#else /* ! SLICE */
+
+static sl_h_IO_req_t sdsIOreq; /* IO req downward (to device) */
+static sl_h_ioctl_t sdsioctl; /* ioctl req downward (to device) */
+static sl_h_open_t sdsopen; /* downwards travelling open */
+static sl_h_close_t sdsclose; /* downwards travelling close */
+static void sds_init (void *arg);
+
+static struct slice_handler slicetype = {
+ "scsidisk",
+ 0,
+ NULL,
+ 0,
+ NULL, /* constructor */
+ &sdsIOreq,
+ &sdsioctl,
+ &sdsopen,
+ &sdsclose,
+ NULL, /* revoke */
+ NULL, /* claim */
+ NULL, /* verify */
+ NULL /* upconfig */
+};
+#endif
@@ -148,7 +185,11 @@ static struct scsi_device sd_switch =
sd_open,
sd_ioctl,
sd_close,
+#ifndef SLICE
sd_strategy,
+#else
+ NULL,
+#endif
};
static struct scsi_xfer sx;
@@ -227,6 +268,31 @@ sdattach(struct scsi_link *sc_link)
sd_registerdev(unit);
#ifdef DEVFS
+#ifdef SLICE
+ {
+ char namebuf[64];
+ sd->unit = unit;
+ sd->sc_link = sc_link;
+ sprintf(namebuf,"sd%d",sd->unit);
+ sd->mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
+ sd->limit.blksize = sd->params.secsiz;
+ /* need to cast to avoid overflow! */
+ sd->limit.slicesize =
+ (u_int64_t)sd->params.secsiz * sd->params.disksize;
+ sl_make_slice(&slicetype,
+ sd,
+ &sd->limit,
+ &sd->slice,
+ NULL,
+ namebuf);
+ /* Allow full probing */
+ sd->slice->probeinfo.typespecific = NULL;
+ sd->slice->probeinfo.type = NULL;
+ }
+ sd->ich.ich_func = sds_init;
+ sd->ich.ich_arg = sd;
+ config_intrhook_establish(&sd->ich);
+#else /* SLICE */
mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
sd->b_devfs_token = devfs_add_devswf(&sd_bdevsw, mynor, DV_BLK,
UID_ROOT, GID_OPERATOR, 0640,
@@ -240,11 +306,26 @@ sdattach(struct scsi_link *sc_link)
DV_CHR,
UID_ROOT, GID_WHEEL, 0600,
"rsd%d.ctl", unit);
+#endif /* SLICE */
#endif
-
return 0;
}
+#ifdef SLICE
+/* run a LOT later */
+static void
+sds_init(void *arg)
+{
+ struct scsi_data *sd = arg;
+ sh_p tp;
+
+ if ((tp = slice_probeall(sd->slice)) != NULL) {
+ (*tp->constructor)(sd->slice);
+ }
+ config_intrhook_disestablish(&sd->ich);
+}
+#endif /* SLICE */
+
/*
* open the device. Make sure the partition info is a up-to-date as can be.
*/
@@ -295,6 +376,7 @@ sd_open(dev, mode, fmt, p, sc_link)
*/
sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
if (!(sc_link->flags & SDEV_MEDIA_LOADED) && sd->dk_slices != NULL) {
+#ifndef SLICE
/*
* If somebody still has it open, then forbid re-entry.
*/
@@ -304,6 +386,7 @@ sd_open(dev, mode, fmt, p, sc_link)
}
dsgone(&sd->dk_slices);
+#endif /* !SLICE */
}
/*
@@ -339,11 +422,13 @@ sd_open(dev, mode, fmt, p, sc_link)
/* XXX as long as it's not 0 - readdisklabel divides by it (?) */
label.d_secperunit = sd->params.disksize;
+#ifndef SLICE
/* Initialize slice tables. */
errcode = dsopen("sd", dev, fmt, &sd->dk_slices, &label, sdstrategy1,
(ds_setgeom_t *)NULL, &sd_bdevsw, &sd_cdevsw);
if (errcode != 0)
goto bad;
+#endif /* !SLICE */
SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
SC_DEBUG(sc_link, SDEV_DB3, ("open %ld %ld\n", sdstrats, sdqueues));
@@ -379,15 +464,18 @@ sd_close(dev, fflag, fmt, p, sc_link)
errcode = scsi_device_lock(sc_link);
if (errcode)
return errcode;
+#ifndef SLICE
dsclose(dev, fmt, sd->dk_slices);
if (!dsisopen(sd->dk_slices)) {
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
sc_link->flags &= ~SDEV_OPEN;
}
+#endif /* ! SLICE */
scsi_device_unlock(sc_link);
return (0);
}
+#ifndef SLICE
/*
* Actually translate the requested transfer into one the physical driver
* can understand. The transfer is described by a buf and will include
@@ -518,6 +606,7 @@ sdstrategy1(struct buf *bp)
sdstrategy(bp);
}
+#endif /* ! SLICE */
/*
* sdstart looks to see if there is a buf waiting for the device
* and that the device is not already busy. If both are true,
@@ -650,7 +739,7 @@ sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
#if 0
/* Wait until we have exclusive access to the device. */
/* XXX this is how wd does it. How did we work without this? */
- wdsleep(du->dk_ctrlr, "wdioct");
+ sdsleep(du->dk_ctrlr, "wdioct");
#endif
/*
@@ -662,10 +751,10 @@ sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
if (cmd == DIOCSBAD)
return (EINVAL); /* XXX */
+#ifndef SLICE
error = scsi_device_lock(sc_link);
if (error)
return error;
-
error = dsioctl("sd", dev, cmd, addr, flag, &sd->dk_slices,
sdstrategy1, (ds_setgeom_t *)NULL);
scsi_device_unlock(sc_link);
@@ -673,6 +762,7 @@ sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
return (error);
if (PARTITION(dev) != RAW_PART)
return (ENOTTY);
+#endif /* ! SLICE */ /* really only take this from the ctl device XXX */
return (scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link));
}
@@ -888,6 +978,7 @@ sd_get_parms(int unit, int flags)
return (error);
}
+#ifndef SLICE
static int
sdsize(dev_t dev)
{
@@ -899,6 +990,7 @@ sdsize(dev_t dev)
return (dssize(dev, &sd->dk_slices, sdopen, sdclose));
}
+#endif /* ! SLICE */
/*
* sense handler: Called to determine what to do when the
* device returns a CHECK CONDITION.
@@ -952,6 +1044,7 @@ sd_sense_handler(struct scsi_xfer *xs)
return SCSIRET_DO_RETRY;
}
+#ifndef SLICE
/*
* dump all of physical memory into the partition specified, starting
* at offset 'dumplo' into the partition.
@@ -1092,7 +1185,9 @@ sddump(dev_t dev)
}
return (0);
}
+#endif /* !SLICE */
+#ifndef SLICE
static sd_devsw_installed = 0;
static void sd_drvinit(void *unused)
@@ -1106,3 +1201,109 @@ static void sd_drvinit(void *unused)
SYSINIT(sddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sd_drvinit,NULL)
+#endif /* !SLICE */
+#ifdef SLICE
+
+/*
+ * Read/write routine for a buffer. Finds the proper unit, range checks
+ * arguments, and schedules the transfer. Does not wait for the transfer
+ * to complete. Multi-page transfers are supported. All I/O requests must
+ * be a multiple of a sector in length.
+scsi_strategy(bp, &sd_switch);
+ */
+static void
+sdsIOreq(void *private ,struct buf *bp)
+{
+ struct scsi_data *sd = private;
+ u_int32_t opri;
+ u_int32_t unit = sd->unit;
+ struct scsi_link *sc_link = sd->sc_link;
+
+ SC_DEBUG(sc_link, SDEV_DB2, ("sdIOreq\n"));
+ SC_DEBUG(sc_link, SDEV_DB1, ("%ld bytes @ blk%ld\n",
+ bp->b_bcount, bp->b_pblkno));
+
+ bp->b_resid = 0;
+ bp->b_error = 0;
+
+ (*sc_link->adapter->scsi_minphys)(bp);
+
+ sdstrats++;
+ /*
+ * If the device has been made invalid, error out
+ */
+ if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
+ bp->b_error = EIO;
+ goto bad;
+ }
+
+ /*
+ * check it's not too big a transfer for our adapter
+ */
+ /*scsi_minphys(bp,&sd_switch);*/
+
+ opri = SPLSD();
+ /*
+ * Use a bounce buffer if necessary
+ */
+#ifdef BOUNCE_BUFFERS
+ if (sc_link->flags & SDEV_BOUNCE)
+ vm_bounce_alloc(bp);
+#endif
+
+ /*
+ * Place it in the queue of disk activities for this disk
+ */
+#ifdef SDDISKSORT
+ bufq_disksort(&sd->buf_queue, bp);
+#else
+ bufq_insert_tail(&sd->buf_queue, bp);
+#endif
+
+ /*
+ * Tell the device to get going on the transfer if it's
+ * not doing anything, otherwise just wait for completion
+ */
+ sdstart(unit, 0);
+
+ splx(opri);
+ return;
+bad:
+ bp->b_flags |= B_ERROR;
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+ return;
+}
+
+
+static int
+sdsopen(void *private, int flags, int mode, struct proc *p)
+{
+ struct scsi_data *sd;
+
+ sd = private;
+
+ return(sdopen(makedev(0,sd->mynor), 0 , 0, p));
+}
+
+static void
+sdsclose(void *private, int flags, int mode, struct proc *p)
+{
+ struct scsi_data *sd;
+
+ sd = private;
+
+ sdclose(makedev(0,sd->mynor), 0 , 0, p);
+ return;
+}
+static int
+sdsioctl( void *private, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct scsi_data *sd;
+
+ sd = private;
+
+ return(sdioctl(makedev(0,sd->mynor), cmd, addr, flag, p));
+}
+
+#endif
diff --git a/sys/sys/devfsext.h b/sys/sys/devfsext.h
index 1cbf003..47842e0 100644
--- a/sys/sys/devfsext.h
+++ b/sys/sys/devfsext.h
@@ -1,17 +1,47 @@
/* usual BSD style copyright here */
/* Written by Julian Elischer (julian@dialix.oz.au)*/
/*
- * $Id: devfsext.h,v 1.15 1997/02/22 09:44:59 peter Exp $
+ * $Id: devfsext.h,v 1.16 1997/09/16 14:23:35 bde Exp $
*/
#ifndef _SYS_DEVFSECT_H_
#define _SYS_DEVFSECT_H_
+/*
+ * Make a device at a path, and get a cookie for it in return.
+ * Specify the type, the minor number and the devsw entry to use,
+ * and the initial default perms/ownerships.
+ */
void *devfs_add_devswf __P((void *devsw, int minor, int chrblk, uid_t uid,
gid_t gid, int perms, char *fmt, ...));
+/*
+ * Make a link to a device you already made, and have the cookie for
+ * We get another cookie, but for now, it can be discarded, as
+ * at the moment there is nothing you can do with it that you couldn't do
+ * with the original cookie. ( XXX this might be something I should change )
+ */
void *devfs_link __P((void *original, char *fmt, ...));
+
+/*
+ * Remove all instances of a device you have made. INCLUDING LINKS.
+ * I.e. either the cookie from the original device or the cookie
+ * from a link will have the effect of removing both entries.
+ * Removing with BOTH an original cookie and one from a link is
+ * likely to cause a panic.
+ */
void devfs_remove_dev __P((void *devnmp));
+/*
+ * Check if a device exists and is the type you need. Returns NULL or a
+ * cookie that can be used to try 'open' the device. XXX This is a bit
+ * of a duplication of devfs_lookup(). I might one day try merge them a bit.
+ * Used for mountroot under DEVFS. Path is relative to the base of the devfs.
+ */
+struct vnode *devfs_open_device __P((char *path, int devtype));
+void devfs_close_device __P((struct vnode *vn));
+
+dev_t devfs_vntodev __P((struct vnode *vn)); /* extract dev_t from devfs vn */
+
#define DV_CHR 0
#define DV_BLK 1
#define DV_DEV 2
diff --git a/sys/sys/sliceio.h b/sys/sys/sliceio.h
new file mode 100644
index 0000000..a5d3cae
--- /dev/null
+++ b/sys/sys/sliceio.h
@@ -0,0 +1,37 @@
+/*
+ * $Id: mtio.h,v 1.10 1997/02/22 09:45:37 peter Exp $
+ */
+
+#ifndef _SYS_SLICEIO_H_
+#define _SYS_SLICEIO_H_
+
+#ifndef KERNEL
+#include <sys/types.h>
+#endif
+#include <sys/ioccom.h>
+#define SLCTYPE_SIZE 16
+#define SLCNAME_SIZE 32
+
+struct sliceinfo {
+ u_int64_t size;
+ u_int32_t blocksize;
+ char type[SLCTYPE_SIZE]; /* e.g. sd or raw*/
+ char hint[SLCTYPE_SIZE]; /* e.g. mbr or ""*/
+ char handler[SLCTYPE_SIZE]; /* e.g. mbr or "" */
+ char devicename[SLCNAME_SIZE]; /* e.g. sd0s1a */
+};
+
+struct subsliceinfo {
+ struct sliceinfo wholesliceinfo; /* size of the whole slice */
+ int slicenumber; /* which subslice we are on */
+ u_int64_t offset; /* where that subslice starts */
+ struct sliceinfo subsliceinfo; /* info about that subslice */
+};
+
+#define SLCIOCRESET _IO('S', 0) /* reset and reprobe. */
+#define SLCIOCINQ _IOR('S', 2, struct sliceinfo) /* info on container */
+#define SLCIOCMOD _IOW('S', 3, struct sliceinfo) /* force container */
+#define SLCIOCGETSUB _IOWR('S', 4, struct subsliceinfo) /* get sub info */
+#define SLCIOCSETSUB _IOWR('S', 5, struct subsliceinfo) /* set sub info */
+
+#endif /* !_SYS_SLICEIO_H_ */
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 9b4753c..c07d845 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
- * $Id: ffs_vfsops.c,v 1.77 1998/03/27 14:20:57 peter Exp $
+ * $Id: ffs_vfsops.c,v 1.78 1998/03/30 09:56:00 phk Exp $
*/
#include "opt_quota.h"
@@ -128,6 +128,9 @@ VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0);
* system call will fail with EFAULT in copyinstr in
* namei() if it is a genuine NULL from the user.
*/
+#ifdef SLICE
+extern struct vnode *root_device_vnode;
+#endif
static int
ffs_mount( mp, path, data, ndp, p)
struct mount *mp; /* mount struct pointer*/
@@ -156,6 +159,13 @@ ffs_mount( mp, path, data, ndp, p)
***
*/
+#ifdef SLICE
+ rootvp = root_device_vnode;
+ if (rootvp == NULL) {
+ printf("ffs_mountroot: rootvp not set");
+ return (EINVAL);
+ }
+#else /* !SLICE */
if ((err = bdevvp(rootdev, &rootvp))) {
printf("ffs_mountroot: can't find rootvp");
return (err);
@@ -165,6 +175,7 @@ ffs_mount( mp, path, data, ndp, p)
mp->mnt_flag |= MNT_NOCLUSTERR;
if (bdevsw[major(rootdev)]->d_flags & D_NOCLUSTERW)
mp->mnt_flag |= MNT_NOCLUSTERW;
+#endif /* !SLICE */
if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) {
/* fs specific cleanup (if any)*/
goto error_1;
@@ -307,12 +318,18 @@ ffs_mount( mp, path, data, ndp, p)
/*
********************
* UPDATE
+ * If it's not the same vnode, or at least the same device
+ * then it's not correct.
********************
*/
- if (devvp != ump->um_devvp)
- err = EINVAL; /* needs translation */
- else
+ if (devvp != ump->um_devvp) {
+ if ( devvp->v_rdev == ump->um_devvp->v_rdev) {
+ vrele(devvp);
+ } else {
+ err = EINVAL; /* needs translation */
+ }
+ } else
vrele(devvp);
/*
* Update device name only on success
OpenPOWER on IntegriCloud