summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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