summaryrefslogtreecommitdiff
path: root/sys/arch/hp300/dev/sd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/hp300/dev/sd.c')
-rw-r--r--sys/arch/hp300/dev/sd.c199
1 files changed, 132 insertions, 67 deletions
diff --git a/sys/arch/hp300/dev/sd.c b/sys/arch/hp300/dev/sd.c
index 75121b1b6dc..713833396f3 100644
--- a/sys/arch/hp300/dev/sd.c
+++ b/sys/arch/hp300/dev/sd.c
@@ -1,4 +1,5 @@
-/* $NetBSD: sd.c,v 1.22.4.1 1996/06/06 16:22:04 thorpej Exp $ */
+/* $OpenBSD: sd.c,v 1.6 1997/01/12 15:13:03 downsj Exp $ */
+/* $NetBSD: sd.c,v 1.28 1997/01/07 09:29:30 thorpej Exp $ */
/*
* Copyright (c) 1990, 1993
@@ -366,6 +367,9 @@ sdattach(hd)
disk_attach(&sc->sc_dkdev);
sc->sc_flags |= SDF_ALIVE;
+
+ /* XXX Set device class. */
+ hd->hp_dev.dv_class = DV_DISK;
}
void
@@ -579,7 +583,7 @@ sdopen(dev, flags, mode, p)
{
register int unit = sdunit(dev);
register struct sd_softc *sc = &sd_softc[unit];
- int error, mask;
+ int error, mask, part;
if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
return(ENXIO);
@@ -604,12 +608,27 @@ sdopen(dev, flags, mode, p)
return(error);
}
- mask = 1 << sdpart(dev);
- if (mode == S_IFCHR)
+ part = sdpart(dev);
+ mask = 1 << part;
+
+ /* Check that the partition exists. */
+ if (part != RAW_PART &&
+ (part >= sc->sc_dkdev.dk_label->d_npartitions ||
+ sc->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED))
+ return (ENXIO);
+
+ /* Ensure only one open at a time. */
+ switch (mode) {
+ case S_IFCHR:
sc->sc_dkdev.dk_copenmask |= mask;
- else
+ break;
+ case S_IFBLK:
sc->sc_dkdev.dk_bopenmask |= mask;
- sc->sc_dkdev.dk_openmask |= mask;
+ break;
+ }
+ sc->sc_dkdev.dk_openmask =
+ sc->sc_dkdev.dk_copenmask | sc->sc_dkdev.dk_bopenmask;
+
return(0);
}
@@ -760,6 +779,7 @@ sdstrategy(bp)
register struct partition *pinfo;
register daddr_t bn;
register int sz, s;
+ int offset;
if (sc->sc_format_pid >= 0) {
if (sc->sc_format_pid != curproc->p_pid) { /* XXX */
@@ -775,28 +795,40 @@ sdstrategy(bp)
bn = bp->b_blkno;
sz = howmany(bp->b_bcount, DEV_BSIZE);
pinfo = &sc->sc_dkdev.dk_label->d_partitions[sdpart(bp->b_dev)];
- if (bn < 0 || bn + sz > pinfo->p_size) {
- sz = pinfo->p_size - bn;
- if (sz == 0) {
- bp->b_resid = bp->b_bcount;
- goto done;
- }
- if (sz < 0) {
- bp->b_error = EINVAL;
- goto bad;
+
+ /* Don't perform partition translation on RAW_PART. */
+ offset = (sdpart(bp->b_dev) == RAW_PART) ? 0 : pinfo->p_offset;
+
+ if (sdpart(bp->b_dev) != RAW_PART) {
+ /*
+ * XXX This block of code belongs in
+ * XXX bounds_check_with_label()
+ */
+
+ if (bn < 0 || bn + sz > pinfo->p_size) {
+ sz = pinfo->p_size - bn;
+ if (sz == 0) {
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ if (sz < 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ bp->b_bcount = dbtob(sz);
}
- bp->b_bcount = dbtob(sz);
- }
- /*
- * Check for write to write protected label
- */
- if (bn + pinfo->p_offset <= LABELSECTOR &&
+ /*
+ * Check for write to write protected label
+ */
+ if (bn + offset <= LABELSECTOR &&
#if LABELSECTOR != 0
- bn + pinfo->p_offset + sz > LABELSECTOR &&
+ bn + offset + sz > LABELSECTOR &&
#endif
- !(bp->b_flags & B_READ) && !(sc->sc_flags & SDF_WLABEL)) {
- bp->b_error = EROFS;
- goto bad;
+ !(bp->b_flags & B_READ) &&
+ !(sc->sc_flags & SDF_WLABEL)) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
}
/*
* Non-aligned or partial-block transfers handled specially.
@@ -806,7 +838,7 @@ sdstrategy(bp)
sdlblkstrat(bp, sc->sc_blksize);
goto done;
}
- bp->b_cylin = (bn + pinfo->p_offset) >> sc->sc_bshift;
+ bp->b_cylin = (bn + offset) >> sc->sc_bshift;
}
s = splbio();
disksort(dp, bp);
@@ -1216,60 +1248,93 @@ sdsize(dev)
return (psize);
}
+static int sddoingadump; /* simple mutex */
+
/*
* Non-interrupt driven, non-dma dump routine.
*/
int
-sddump(dev)
+sddump(dev, blkno, va, size)
dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
{
- int part = sdpart(dev);
- int unit = sdunit(dev);
- register struct sd_softc *sc = &sd_softc[unit];
- register struct hp_device *hp = sc->sc_hd;
- register struct partition *pinfo;
- register daddr_t baddr;
- register int maddr;
- register int pages, i;
- int stat;
- extern int lowram, dumpsize;
-
- /* is drive ok? */
- if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
+ int sectorsize; /* size of a disk sector */
+ int nsects; /* number of sectors in partition */
+ int sectoff; /* sector offset of partition */
+ int totwrt; /* total number of sectors left to write */
+ int nwrt; /* current number of sectors to write */
+ int unit, part;
+ struct sd_softc *sc;
+ struct hp_device *hp;
+ struct disklabel *lp;
+ daddr_t baddr;
+ char stat;
+
+ /* Check for recursive dump; if so, punt. */
+ if (sddoingadump)
+ return (EFAULT);
+ sddoingadump = 1;
+
+ /* Decompose unit and partition. */
+ unit = sdunit(dev);
+ part = sdpart(dev);
+
+ /* Make sure device is ok. */
+ if (unit >= NSD)
+ return (ENXIO);
+ sc = &sd_softc[unit];
+ if ((sc->sc_flags & SDF_ALIVE) == 0)
return (ENXIO);
- pinfo = &sc->sc_dkdev.dk_label->d_partitions[part];
- /* dump parameters in range? */
- if (dumplo < 0 || dumplo >= pinfo->p_size ||
- pinfo->p_fstype != FS_SWAP)
+ hp = sc->sc_hd;
+
+ /*
+ * Convert to disk sectors. Request must be a multiple of size.
+ */
+ lp = sc->sc_dkdev.dk_label;
+ sectorsize = lp->d_secsize;
+ if ((size % sectorsize) != 0)
+ return (EFAULT);
+ totwrt = size / sectorsize;
+ blkno = dbtob(blkno) / sectorsize; /* blkno in DEV_BSIZE units */
+
+ nsects = lp->d_partitions[part].p_size;
+ sectoff = lp->d_partitions[part].p_offset;
+
+ /* Check transfer bounds against partition size. */
+ if ((blkno < 0) || (blkno + totwrt) > nsects)
return (EINVAL);
- pages = dumpsize;
- if (dumplo + ctod(pages) > pinfo->p_size)
- pages = dtoc(pinfo->p_size - dumplo);
- maddr = lowram;
- baddr = dumplo + pinfo->p_offset;
- /* scsi bus idle? */
- if (!scsireq(&sc->sc_dq)) {
- scsireset(hp->hp_ctlr);
- sdreset(sc, sc->sc_hd);
- printf("[ drive %d reset ] ", unit);
- }
- for (i = 0; i < pages; i++) {
-#define NPGMB (1024*1024/NBPG)
- /* print out how many Mbs we have dumped */
- if (i && (i % NPGMB) == 0)
- printf("%d ", i / NPGMB);
-#undef NPBMG
- pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, maddr,
- VM_PROT_READ, TRUE);
+
+ /* Offset block number to start of partition. */
+ blkno += sectoff;
+
+ while (totwrt > 0) {
+ nwrt = totwrt; /* XXX */
+#ifndef SD_DUMP_NOT_TRUSTED
+ /*
+ * Send the data. Note the `0' argument for bshift;
+ * we've done the necessary conversion above.
+ */
stat = scsi_tt_write(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,
- vmmap, NBPG, baddr, sc->sc_bshift);
+ va, nwrt * sectorsize, blkno, 0);
if (stat) {
- printf("sddump: scsi write error 0x%x\n", stat);
+ printf("\nsddump: scsi write error 0x%x\n", stat);
return (EIO);
}
- maddr += NBPG;
- baddr += ctod(1);
+#else /* SD_DUMP_NOT_TRUSTED */
+ /* Lets just talk about it first. */
+ printf("%s: dump addr %p, blk %d\n", hp->hp_xname,
+ va, blkno);
+ delay(500 * 1000); /* half a second */
+#endif /* SD_DUMP_NOT_TRUSTED */
+
+ /* update block count */
+ totwrt -= nwrt;
+ blkno += nwrt;
+ va += sectorsize * nwrt;
}
+ sddoingadump = 0;
return (0);
}
#endif