summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1998-04-22 19:27:54 +0000
committerjulian <julian@FreeBSD.org>1998-04-22 19:27:54 +0000
commited0da47a02390b289c84b8d8bdda2caa48d1bf6a (patch)
tree51208643ece97c62db9703d39b4119a87de1e87c /sys
parentefb500c7ac711f70e1f1fdbbaf8bb2ff7eac24f5 (diff)
downloadFreeBSD-src-ed0da47a02390b289c84b8d8bdda2caa48d1bf6a.zip
FreeBSD-src-ed0da47a02390b289c84b8d8bdda2caa48d1bf6a.tar.gz
Bad144 support for the slice system (!)
Submitted by: luoqi@watermarkgroup.com (Luoqi Chen) I'm amazed by this. Slice has only been checked in for 2 days..
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/slice/disklabel.c129
-rw-r--r--sys/dev/slice/mbr.c33
-rw-r--r--sys/dev/slice/slice_device.c4
-rw-r--r--sys/i386/isa/wd.c12
-rw-r--r--sys/sys/sliceio.h3
5 files changed, 154 insertions, 27 deletions
diff --git a/sys/dev/slice/disklabel.c b/sys/dev/slice/disklabel.c
index 513d11f..ff8c6f6 100644
--- a/sys/dev/slice/disklabel.c
+++ b/sys/dev/slice/disklabel.c
@@ -23,9 +23,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: disklabel.c,v 1.1 1998/04/19 23:31:03 julian Exp $
+ * $Id: disklabel.c,v 1.2 1998/04/22 10:25:09 julian Exp $
*/
-
+#define BAD144
#include <sys/param.h>
#include <sys/kernel.h>
@@ -35,6 +35,9 @@
#include <sys/disklabel.h>
#include <sys/diskslice.h>
#include <sys/dkstat.h>
+#ifdef BAD144
+#include <sys/dkbad.h>
+#endif
#include <sys/malloc.h>
#include <dev/slice/slice.h>
@@ -57,6 +60,9 @@ struct private_data {
struct private_data *pd;
u_int32_t offset; /* all disklabel supports */
} subdevs[MAXPARTITIONS];
+#ifdef BAD144
+ struct dkbad_intern *bad;
+#endif
};
static sl_h_constructor_t dkl_constructor; /* constructor (from device) */
@@ -232,7 +238,78 @@ quit:
return (error);
}
+#ifdef BAD144
+static int
+dkl_internbad144(struct private_data *pd, struct dkbad *btp, int flag)
+{
+ struct disklabel *lp = &pd->disklabel;
+ struct dkbad_intern *bip = pd->bad;
+ int i;
+
+ if (bip == NULL) {
+ bip = malloc(sizeof *bip, M_DEVBUF, flag);
+ if (bip == NULL)
+ return (ENOMEM);
+ pd->bad = bip;
+ }
+ /*
+ * Spare sectors are allocated beginning with the last sector of
+ * the second last track of the disk (the last track is used for
+ * the bad sector list).
+ */
+ bip->bi_maxspare = lp->d_secperunit - lp->d_nsectors - 1;
+ bip->bi_nbad = DKBAD_MAXBAD;
+ for (i=0; i < DKBAD_MAXBAD && btp->bt_bad[i].bt_cyl != DKBAD_NOCYL; i++)
+ bip->bi_bad[i] = btp->bt_bad[i].bt_cyl * lp->d_secpercyl
+ + (btp->bt_bad[i].bt_trksec >> 8)
+ * lp->d_nsectors
+ + (btp->bt_bad[i].bt_trksec & 0x00ff);
+ bip->bi_bad[i] = -1;
+#if 1
+ for (i = 0; i < DKBAD_MAXBAD && bip->bi_bad[i] != -1; i++)
+ printf(" %8d => %8d\n", bip->bi_bad[i],
+ bip->bi_maxspare - i);
+#endif
+ return (0);
+}
+
+static int
+dkl_readbad144(struct private_data *pd)
+{
+ sl_p slice = pd->slice_down;
+ struct disklabel *lp = &pd->disklabel;
+ struct dkbad *db;
+ struct buf *bp;
+ int blkno, i, error;
+
+ for (i = 0; i < min(10, lp->d_nsectors); i += 2) {
+ blkno = lp->d_secperunit - lp->d_nsectors + i;
+ if (lp->d_secsize > slice->limits.blksize)
+ blkno *= lp->d_secsize / slice->limits.blksize;
+ else
+ blkno /= slice->limits.blksize / lp->d_secsize;
+ error = slice_readblock(slice, blkno, &bp);
+ if (error)
+ return (error);
+ bp->b_flags |= B_INVAL | B_AGE;
+ db = (struct dkbad *)bp->b_data;
+ if (db->bt_mbz == 0 && db->bt_flag == DKBAD_MAGIC) {
+ printf(" bad144 table found at block %d\n", blkno);
+ error = dkl_internbad144(pd, db, M_NOWAIT);
+ brelse(bp);
+ return (error);
+ }
+ brelse(bp);
+ }
+ return (EINVAL);
+}
+static __inline daddr_t
+dkl_transbad144(struct private_data *pd, daddr_t blkno)
+{
+ return transbad144(pd->bad, blkno);
+}
+#endif
/*-
* look at a slice and figure out if we should be interested in it. (Is it
@@ -357,6 +434,14 @@ dkl_constructor(sl_p slice)
return (error);
}
}
+#ifdef BAD144
+ if (pd->disklabel.d_flags & D_BADSECT) {
+ if ((error = dkl_readbad144(pd))) {
+ free(pd, M_DEVBUF);
+ return (error);
+ }
+ }
+#endif
slice->refs++;
slice->handler_up = &slicetype;
slice->private_up = pd;
@@ -560,6 +645,10 @@ dkl_revoke(void *private)
slice->handler_up = NULL;
slice->private_up = NULL;
slicetype.refs--;
+#ifdef BAD144
+ if (pd->bad)
+ free(pd->bad, M_DEVBUF);
+#endif
free(pd, M_DEVBUF);
sl_unref(slice);
return (0);
@@ -583,24 +672,6 @@ RR;
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)
{
@@ -730,6 +801,13 @@ dkl_ioctl(void *private, int cmd, caddr_t addr, int flag, struct proc * p)
((struct partinfo *)addr)->part = lp->d_partitions + sdp->part;
return (0);
+#ifdef BAD144
+ case DIOCSBAD:
+ if (!(flag & FWRITE))
+ return (EBADF);
+ return (dkl_internbad144(pd, (struct dkbad *)addr, M_WAITOK));
+#endif
+
/* These don't really make sense. keep the headers for a reminder */
case DIOCSDINFO:
case DIOCSYNCSLICEINFO:
@@ -750,6 +828,17 @@ dkl_upconfig(struct slice *slice, int cmd, caddr_t addr, int flag, struct proc *
case SLCIOCRESET:
return (0);
+ case SLCIOCTRANSBAD:
+ {
+ struct private_data *pd;
+ daddr_t blkno;
+
+ pd = slice->private_up;
+ if (pd->bad)
+ *(daddr_t*)addr = dkl_transbad144(pd, *(daddr_t*)addr);
+ return (0);
+ }
+
/* These don't really make sense. keep the headers for a reminder */
default:
return (ENOIOCTL);
diff --git a/sys/dev/slice/mbr.c b/sys/dev/slice/mbr.c
index 29e8b01..5558775 100644
--- a/sys/dev/slice/mbr.c
+++ b/sys/dev/slice/mbr.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mbr.c,v 1.1 1998/04/19 23:31:05 julian Exp $
+ * $Id: mbr.c,v 1.2 1998/04/22 10:25:09 julian Exp $
*/
#include <sys/param.h>
@@ -825,11 +825,42 @@ static int
mbr_upconfig(struct slice *slice, int cmd, caddr_t addr,
int flag, struct proc * p)
{
+ int error;
+
RR;
switch (cmd) {
case SLCIOCRESET:
return (0);
+ case SLCIOCTRANSBAD:
+ {
+ struct private_data *pd;
+ struct subdev *sdp;
+ daddr_t blkno;
+ int part;
+
+ blkno = *(daddr_t *)addr;
+ pd = slice->private_up;
+ sdp = pd->subdevs;
+ for (part = 0; part < NDOSPART; part++, sdp++) {
+ if (!sdp->slice)
+ continue;
+ if (blkno < sdp->offset)
+ continue;
+ if (blkno >= sdp->offset +
+ sdp->limit.slicesize / sdp->limit.blksize)
+ continue;
+ blkno -= sdp->offset;
+ slice = sdp->slice;
+ error = (*slice->handler_up->upconf)(slice, cmd,
+ (caddr_t)&blkno, flag, p);
+ if (!error)
+ *(daddr_t *)addr = blkno + sdp->offset;
+ return (error);
+ }
+ return (0);
+ }
+
/* These don't really make sense. keep the headers for a reminder */
default:
return (ENOIOCTL);
diff --git a/sys/dev/slice/slice_device.c b/sys/dev/slice/slice_device.c
index 783a862..30bb309 100644
--- a/sys/dev/slice/slice_device.c
+++ b/sys/dev/slice/slice_device.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: slice_device.c,v 1.1 1998/04/19 23:31:14 julian Exp $
+ * $Id: slice_device.c,v 1.2 1998/04/22 10:25:10 julian Exp $
*/
#define DIAGNOSTIC 1
@@ -227,7 +227,7 @@ slcdevclose(dev_t dev, int flags, int mode, struct proc * p)
{
sl_p slice = minor_to_slice(minor(dev));
RR;
-#ifdef DIAGNOSTIC
+#ifdef DIAGNOSTICX
if ((flags & (FWRITE | FREAD)) != 0) {
printf("sliceclose called with non 0 flags\n");
}
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 88dc731..ef1181a 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.159 1998/04/19 23:31:44 julian Exp $
+ * $Id: wd.c,v 1.160 1998/04/22 10:25:17 julian Exp $
*/
/* TODO:
@@ -83,6 +83,7 @@
#ifdef SLICE
#include <sys/device.h>
#include <sys/fcntl.h>
+#include <sys/sliceio.h>
#include <dev/slice/slice.h>
#else
#include <sys/devfsext.h>
@@ -968,6 +969,11 @@ wdstart(int ctrlr)
blknum = transbad144(dsgetbad(bp->b_dev, du->dk_slices),
blknum - ds_offset) + ds_offset;
}
+#else
+ if (du->dk_flags & DKFL_SINGLE) {
+ (void) (*du->slice->handler_up->upconf)(du->slice,
+ SLCIOCTRANSBAD, (caddr_t)&blknum, 0, 0);
+ }
#endif
wdtab[ctrlr].b_active = 1; /* mark controller active */
@@ -2395,7 +2401,7 @@ out:
static void
wderror(struct buf *bp, struct disk *du, char *mesg)
{
-#ifndef SLICE
+#ifdef SLICE
printf("wd%d: %s:\n", du->dk_lunit, mesg);
#else /* !SLICE */
if (bp == NULL)
@@ -2653,7 +2659,7 @@ SYSINIT(wddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,wd_drvinit,NULL)
* be a multiple of a sector in length.
*/
static void
-wdsIOreq(void *private ,struct buf *bp)
+wdsIOreq(void *private, struct buf *bp)
{
struct disk *du = private;
int s;
diff --git a/sys/sys/sliceio.h b/sys/sys/sliceio.h
index a5d3cae..2a519af 100644
--- a/sys/sys/sliceio.h
+++ b/sys/sys/sliceio.h
@@ -1,5 +1,5 @@
/*
- * $Id: mtio.h,v 1.10 1997/02/22 09:45:37 peter Exp $
+ * $Id: sliceio.h,v 1.1 1998/04/19 23:32:43 julian Exp $
*/
#ifndef _SYS_SLICEIO_H_
@@ -33,5 +33,6 @@ struct subsliceinfo {
#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 */
+#define SLCIOCTRANSBAD _IOWR('S', 6, daddr_t) /* map bad144 sector */
#endif /* !_SYS_SLICEIO_H_ */
OpenPOWER on IntegriCloud