diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2000-04-10 07:06:18 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2000-04-10 07:06:18 +0000 |
commit | e3aaffb5c351fad2a905355ac8b0703721d089f4 (patch) | |
tree | 216624a980f5dd72047f1268a7b668f042ebd4ef /sys/dev/ata | |
parent | fd15ab77cff7d1685f86a25686c91e518b748a35 (diff) |
Added support for wd detach (merge from NetBSD). Support for
SCSI/ATAPI detach is not here yet.
Minor cleanup of wdc. Downgrade to UDMA mode 1 before going further.
Want to stay in UDMA modes because they're more error-resilient due to
a CRC.
Got rid of some of the ridiculous amount of softc sharing going on.
Hopefully, this will make the life of whoever goes in and fixes the
ref-counting to be correct easier.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/ata_wdc.c | 40 | ||||
-rw-r--r-- | sys/dev/ata/atavar.h | 8 | ||||
-rw-r--r-- | sys/dev/ata/wd.c | 285 | ||||
-rw-r--r-- | sys/dev/ata/wdvar.h | 4 |
4 files changed, 224 insertions, 113 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c index b9f075f1a01..32147d4ecfa 100644 --- a/sys/dev/ata/ata_wdc.c +++ b/sys/dev/ata/ata_wdc.c @@ -95,6 +95,7 @@ #define DEBUG_STATUS 0x04 #define DEBUG_FUNCS 0x08 #define DEBUG_PROBE 0x10 + #ifdef WDCDEBUG int wdcdebug_wd_mask = 0; #define WDCDEBUG_PRINT(args, level) \ @@ -115,6 +116,7 @@ struct cfdriver wdc_cd = { void wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *)); void _wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *)); int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *, int)); +void wdc_ata_bio_kill_xfer __P((struct channel_softc *,struct wdc_xfer *)); void wdc_ata_bio_done __P((struct channel_softc *, struct wdc_xfer *)); int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *, int)); int wdc_ata_err __P((struct ata_drive_datas *, struct ata_bio *)); @@ -148,6 +150,7 @@ wdc_ata_bio(drvp, ata_bio) xfer->c_bcount = ata_bio->bcount; xfer->c_start = wdc_ata_bio_start; xfer->c_intr = wdc_ata_bio_intr; + xfer->c_kill_xfer = wdc_ata_bio_kill_xfer; wdc_exec_xfer(chp, xfer); return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED; } @@ -222,7 +225,7 @@ _wdc_ata_bio_start(chp, xfer) ata_delay = ATA_DELAY; else ata_delay = ATA_DELAY; -again: + again: /* * * When starting a multi-sector transfer, or doing single-sector @@ -238,7 +241,7 @@ again: long blkdiff; int i; for (i = 0; (blkdiff = ata_bio->badsect[i]) != -1; - i++) { + i++) { blkdiff -= ata_bio->blkno; if (blkdiff < 0) continue; @@ -255,7 +258,7 @@ again: } break; } - /* Transfer is okay now. */ + /* Transfer is okay now. */ } if (ata_bio->flags & ATA_LBA) { sect = (ata_bio->blkno >> 0) & 0xff; @@ -322,8 +325,8 @@ again: /* The number of blocks in the last stretch may be smaller. */ nblks = xfer->c_bcount / ata_bio->lp->d_secsize; if (ata_bio->nblks > nblks) { - ata_bio->nblks = nblks; - ata_bio->nbytes = xfer->c_bcount; + ata_bio->nblks = nblks; + ata_bio->nbytes = xfer->c_bcount; } } /* If this was a write and not using DMA, push the data. */ @@ -346,7 +349,7 @@ again: ata_bio->nbytes); } -intr: /* Wait for IRQ (either real or polled) */ + intr: /* Wait for IRQ (either real or polled) */ if ((ata_bio->flags & ATA_POLL) == 0) { chp->ch_flags |= WDCF_IRQ_WAIT; } else { @@ -357,7 +360,7 @@ intr: /* Wait for IRQ (either real or polled) */ goto again; } return; -timeout: + timeout: printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n", chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, chp->ch_status, chp->ch_error); @@ -506,6 +509,27 @@ end: return 1; } + +void +wdc_ata_bio_kill_xfer(chp, xfer) + struct channel_softc *chp; + struct wdc_xfer *xfer; +{ + struct ata_bio *ata_bio = xfer->cmd; + + untimeout(wdctimeout, chp); + /* remove this command from xfer queue */ + wdc_free_xfer(chp, xfer); + + ata_bio->flags |= ATA_ITSDONE; + ata_bio->error = ERR_NODEV; + ata_bio->r_error = WDCE_ABRT; + if ((ata_bio->flags & ATA_POLL) == 0) { + WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS); + wddone(ata_bio->wd); + } +} + void wdc_ata_bio_done(chp, xfer) struct channel_softc *chp; @@ -536,7 +560,7 @@ wdc_ata_bio_done(chp, xfer) ata_bio->flags |= ATA_ITSDONE; if ((ata_bio->flags & ATA_POLL) == 0) { WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS); - wddone(chp->ch_drive[drive].drv_softc); + wddone(ata_bio->wd); } WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n", chp->ch_flags), DEBUG_XFERS); diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h index 859f76aa311..8448949adcd 100644 --- a/sys/dev/ata/atavar.h +++ b/sys/dev/ata/atavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atavar.h,v 1.4 1999/10/09 03:42:03 csapuntz Exp $ */ +/* $OpenBSD: atavar.h,v 1.5 2000/04/10 07:06:16 csapuntz Exp $ */ /* $NetBSD: atavar.h,v 1.13 1999/03/10 13:11:43 bouyer Exp $ */ /* @@ -55,6 +55,7 @@ struct ata_drive_datas { #define DRIVE_DMAERR 0x0100 /* Udma transfer had crc error, don't try DMA */ #define DRIVE_DSCBA 0x0200 /* DSC in buffer availability mode */ #define DRIVE_DSCWAIT 0x0400 /* In wait for DSC to be asserted */ + /* * Current setting of drive's PIO, DMA and UDMA modes. * Is initialised by the disks drivers at attach time, and may be @@ -83,7 +84,8 @@ struct ata_drive_datas { /* downgrade mode after this many successive errors */ #define NERRS_MAX 2 - struct device *drv_softc; /* ATA/PI drive's softc, can be NULL */ + char drive_name[31]; + int cf_flags; void *chnl_softc; /* channel softc */ }; @@ -151,6 +153,8 @@ struct wdc_command { void *callback_arg; /* argument passed to *callback() */ }; +extern int at_poll; + int wdc_exec_command __P((struct ata_drive_datas *, struct wdc_command*)); #define WDC_COMPLETE 0x01 #define WDC_QUEUED 0x02 diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index 5f14d80a80e..6aa3eb0d250 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wd.c,v 1.11 2000/04/07 09:12:44 niklas Exp $ */ +/* $OpenBSD: wd.c,v 1.12 2000/04/10 07:06:16 csapuntz Exp $ */ /* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */ /* @@ -88,6 +88,7 @@ #if NRND > 0 #include <sys/rnd.h> #endif +#include <sys/vnode.h> #include <vm/vm.h> @@ -110,6 +111,7 @@ #define WDUNIT(dev) DISKUNIT(dev) #define WDPART(dev) DISKPART(dev) +#define WDMINOR(unit, part) DISKMINOR(unit, part) #define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) #define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART)) @@ -136,7 +138,6 @@ struct wd_softc { /* IDE disk soft states */ struct ata_bio sc_wdc_bio; /* current transfer */ struct buf *sc_bp; /* buf being transfered */ - void *wdc_softc; /* pointer to our parent */ struct ata_drive_datas *drvp; /* Our controller's infos */ int openings; struct ataparams sc_params;/* drive characteistics found */ @@ -152,6 +153,7 @@ struct wd_softc { #define WDF_LOADED 0x10 /* parameters loaded */ #define WDF_WAIT 0x20 /* waiting for resources */ #define WDF_LBA 0x40 /* using LBA mode */ + int sc_capacity; int cyl; /* actual drive parameters */ int heads; @@ -160,6 +162,7 @@ struct wd_softc { #if NRND > 0 rndsource_element_t rnd_source; #endif + void *sc_sdhook; }; #define sc_drive sc_wdc_bio.drive @@ -173,10 +176,14 @@ int wdprobe __P((struct device *, struct cfdata *, void *)); int wdprobe __P((struct device *, void *, void *)); #endif void wdattach __P((struct device *, struct device *, void *)); +int wddetach __P((struct device *, int)); +int wdactivate __P((struct device *, enum devact)); +void wdzeroref __P((struct device *)); int wdprint __P((void *, char *)); struct cfattach wd_ca = { - sizeof(struct wd_softc), wdprobe, wdattach + sizeof(struct wd_softc), wdprobe, wdattach, + wddetach, wdactivate, wdzeroref }; #ifdef __OpenBSD__ @@ -228,8 +235,11 @@ bdev_decl(wd); #ifdef DKBAD void bad144intern __P((struct wd_softc *)); #endif -int wdlock __P((struct wd_softc *)); -void wdunlock __P((struct wd_softc *)); + +#define wdlock(wd) disk_lock(&(wd)->sc_dk) +#define wdunlock(wd) disk_unlock(&(wd)->sc_dk) +#define wdlookup(unit) (struct wd_softc *)device_lookup(&wd_cd, (unit)) + int wdprobe(parent, match_, aux) @@ -282,13 +292,14 @@ wdattach(parent, self, aux) WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); wd->openings = aa_link->aa_openings; - wd->drvp = aa_link->aa_drv_data;; - wd->wdc_softc = parent; - /* give back our softc to our caller */ - wd->drvp->drv_softc = &wd->sc_dev; + wd->drvp = aa_link->aa_drv_data; + + strncpy(wd->drvp->drive_name, wd->sc_dev.dv_xname, + sizeof(wd->drvp->drive_name) - 1); + wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags; /* read our drive info */ - if (wd_get_params(wd, AT_POLL, &wd->sc_params) != 0) { + if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) { printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname); return; } @@ -364,7 +375,8 @@ wdattach(parent, self, aux) wd->sc_dk.dk_name = wd->sc_dev.dv_xname; disk_attach(&wd->sc_dk); wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; - if (shutdownhook_establish(wd_shutdown, wd) == NULL) + wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd); + if (wd->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", wd->sc_dev.dv_xname); #if NRND > 0 @@ -373,6 +385,79 @@ wdattach(parent, self, aux) #endif } +int +wdactivate(self, act) + struct device *self; + enum devact act; +{ + int rv = 0; + + switch (act) { + case DVACT_ACTIVATE: + break; + + case DVACT_DEACTIVATE: + /* + * Nothing to do; we key off the device's DVF_ACTIVATE. + */ + break; + } + return (rv); +} + + +int +wddetach(self, flags) + struct device *self; + int flags; +{ + struct wd_softc *sc = (struct wd_softc *)self; + struct buf *dp, *bp; + int s, bmaj, cmaj, mn; + + /* Remove unprocessed buffers from queue */ + s = splbio(); + for (dp = &sc->sc_q; (bp = dp->b_actf) != NULL; ) { + dp->b_actf = bp->b_actf; + + bp->b_error = ENXIO; + bp->b_flags |= B_ERROR; + biodone(bp); + } + splx(s); + + /* locate the major number */ + mn = WDMINOR(self->dv_unit, 0); + + for (bmaj = 0; bmaj < nblkdev; bmaj++) + if (bdevsw[bmaj].d_open == wdopen) + vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK); + for (cmaj = 0; cmaj < nchrdev; cmaj++) + if (cdevsw[cmaj].d_open == wdopen) + vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR); + + /* Get rid of the shutdown hook. */ + if (sc->sc_sdhook != NULL) + shutdownhook_disestablish(sc->sc_sdhook); + +#if NRND > 0 + /* Unhook the entropy source. */ + rnd_detach_source(&sc->rnd_source); +#endif + + return (0); +} + +void +wdzeroref(self) + struct device *self; +{ + struct wd_softc *sc = (struct wd_softc *)self; + + /* Detach disk. */ + disk_detach(&sc->sc_dk); +} + /* * Read/write routine for a buffer. Validates the arguments and schedules the * transfer. Does not wait for the transfer to complete. @@ -381,8 +466,15 @@ void wdstrategy(bp) struct buf *bp; { - struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)]; + struct wd_softc *wd; int s; + + wd = wdlookup(WDUNIT(bp->b_dev)); + if (wd == NULL) { + bp->b_error = ENXIO; + goto bad; + } + WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname), DEBUG_XFERS); @@ -417,6 +509,7 @@ wdstrategy(bp) disksort(&wd->sc_q, bp); wdstart(wd); splx(s); + device_unref(&wd->sc_dev); return; bad: bp->b_flags |= B_ERROR; @@ -424,6 +517,8 @@ done: /* Toss transfer; we're done early. */ bp->b_resid = bp->b_bcount; biodone(bp); + if (wd != NULL) + device_unref(&wd->sc_dev); } /* @@ -486,6 +581,7 @@ __wdstart(wd, bp) wd->sc_wdc_bio.flags |= ATA_READ; wd->sc_wdc_bio.bcount = bp->b_bcount; wd->sc_wdc_bio.databuf = bp->b_data; + wd->sc_wdc_bio.wd = wd; /* Instrumentation. */ disk_busy(&wd->sc_dk); switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) { @@ -515,6 +611,10 @@ wddone(v) bp->b_resid = wd->sc_wdc_bio.bcount; errbuf[0] = '\0'; switch (wd->sc_wdc_bio.error) { + case ERR_NODEV: + bp->b_flags |= B_ERROR; + bp->b_error = ENXIO; + break; case ERR_DMA: errbuf = "DMA error"; goto retry; @@ -530,7 +630,8 @@ wddone(v) (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0) goto noerror; ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf); -retry: /* Just reset and retry. Can we do more ? */ +retry: + /* Just reset and retry. Can we do more ? */ wdc_reset_channel(wd->drvp); diskerr(bp, "wd", errbuf, LOG_PRINTF, wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label); @@ -594,53 +695,6 @@ wdwrite(dev, uio, flags) return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio)); } -/* - * Wait interruptibly for an exclusive lock. - * - * XXX - * Several drivers do this; it should be abstracted and made MP-safe. - */ -int -wdlock(wd) - struct wd_softc *wd; -{ - int error; - int s; - - WDCDEBUG_PRINT(("wdlock\n"), DEBUG_FUNCS); - - s = splbio(); - - while ((wd->sc_flags & WDF_LOCKED) != 0) { - wd->sc_flags |= WDF_WANTED; - if ((error = tsleep(wd, PRIBIO | PCATCH, - "wdlck", 0)) != 0) { - splx(s); - return error; - } - } - wd->sc_flags |= WDF_LOCKED; - splx(s); - return 0; -} - -/* - * Unlock and wake up any waiters. - */ -void -wdunlock(wd) - struct wd_softc *wd; -{ - - WDCDEBUG_PRINT(("wdunlock\n"), DEBUG_FUNCS); - - wd->sc_flags &= ~WDF_LOCKED; - if ((wd->sc_flags & WDF_WANTED) != 0) { - wd->sc_flags &= ~WDF_WANTED; - wakeup(wd); - } -} - int wdopen(dev, flag, fmt, p) dev_t dev; @@ -652,10 +706,9 @@ wdopen(dev, flag, fmt, p) int error; WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS); + unit = WDUNIT(dev); - if (unit >= wd_cd.cd_ndevs) - return ENXIO; - wd = wd_cd.cd_devs[unit]; + wd = wdlookup(unit); if (wd == NULL) return ENXIO; @@ -717,6 +770,7 @@ wdopen(dev, flag, fmt, p) wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; wdunlock(wd); + device_unref(&wd->sc_dev); return 0; bad: @@ -730,6 +784,7 @@ bad4: if (wd->sc_dk.dk_openmask == 0) wdc_ata_delref(wd->drvp); #endif + device_unref(&wd->sc_dev); return error; } @@ -739,13 +794,17 @@ wdclose(dev, flag, fmt, p) int flag, fmt; struct proc *p; { - struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)]; + struct wd_softc *wd; int part = WDPART(dev); - int error; + int error = 0; + + wd = wdlookup(WDUNIT(dev)); + if (wd == NULL) + return ENXIO; WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS); if ((error = wdlock(wd)) != 0) - return error; + goto exit; switch (fmt) { case S_IFCHR: @@ -767,7 +826,10 @@ wdclose(dev, flag, fmt, p) } wdunlock(wd); - return 0; + + exit: + device_unref(&wd->sc_dev); + return (error); } void @@ -775,7 +837,6 @@ wdgetdefaultlabel(wd, lp) struct wd_softc *wd; struct disklabel *lp; { - WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS); bzero(lp, sizeof(struct disklabel)); @@ -867,13 +928,19 @@ wdioctl(dev, xfer, addr, flag, p) int flag; struct proc *p; { - struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)]; - int error; + struct wd_softc *wd; + int error = 0; WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS); - if ((wd->sc_flags & WDF_LOADED) == 0) - return EIO; + wd = wdlookup(WDUNIT(dev)); + if (wd == NULL) + return ENXIO; + + if ((wd->sc_flags & WDF_LOADED) == 0) { + error = EIO; + goto exit; + } switch (xfer) { #ifdef DKBAD @@ -883,38 +950,40 @@ wdioctl(dev, xfer, addr, flag, p) DKBAD(wd->sc_dk.dk_cpulabel) = *(struct dkbad *)addr; wd->sc_dk.dk_label->d_flags |= D_BADSECT; bad144intern(wd); - return 0; + goto exit; #endif case DIOCRLDINFO: wdgetdisklabel(dev, wd, wd->sc_dk.dk_label, wd->sc_dk.dk_cpulabel, 0); - return 0; + goto exit; case DIOCGPDINFO: { struct cpu_disklabel osdep; wdgetdisklabel(dev, wd, (struct disklabel *)addr, &osdep, 1); - return 0; + goto exit; } case DIOCGDINFO: *(struct disklabel *)addr = *(wd->sc_dk.dk_label); - return 0; + goto exit; case DIOCGPART: ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; ((struct partinfo *)addr)->part = &wd->sc_dk.dk_label->d_partitions[WDPART(dev)]; - return 0; + goto exit; case DIOCWDINFO: case DIOCSDINFO: - if ((flag & FWRITE) == 0) - return EBADF; + if ((flag & FWRITE) == 0) { + error = EBADF; + goto exit; + } if ((error = wdlock(wd)) != 0) - return error; + goto exit; wd->sc_flags |= WDF_LABELLING; error = setdisklabel(wd->sc_dk.dk_label, @@ -931,21 +1000,24 @@ wdioctl(dev, xfer, addr, flag, p) wd->sc_flags &= ~WDF_LABELLING; wdunlock(wd); - return error; + goto exit; case DIOCWLABEL: - if ((flag & FWRITE) == 0) - return EBADF; + if ((flag & FWRITE) == 0) { + error = EBADF; + goto exit; + } + if (*(int *)addr) wd->sc_flags |= WDF_WLABEL; else wd->sc_flags &= ~WDF_WLABEL; - return 0; + goto exit; #ifndef __OpenBSD__ case DIOCGDEFLABEL: wdgetdefaultlabel(wd, (struct disklabel *)addr); - return 0; + goto exit; #endif #ifdef notyet @@ -972,7 +1044,7 @@ wdioctl(dev, xfer, addr, flag, p) fop->df_count -= auio.uio_resid; fop->df_reg[0] = wdc->sc_status; fop->df_reg[1] = wdc->sc_error; - return error; + goto exit; } #endif @@ -981,8 +1053,10 @@ wdioctl(dev, xfer, addr, flag, p) * Make sure this command is (relatively) safe first */ if ((((atareq_t *) addr)->flags & ATACMD_READ) == 0 && - (flag & FWRITE) == 0) - return (EBADF); + (flag & FWRITE) == 0) { + error = EBADF; + goto exit; + } { struct wd_ioctl *wi; atareq_t *atareq = (atareq_t *) addr; @@ -1020,16 +1094,21 @@ wdioctl(dev, xfer, addr, flag, p) } *atareq = wi->wi_atareq; wi_free(wi); - return(error); + goto exit; } default: - return ENOTTY; + error = ENOTTY; + goto exit; } #ifdef DIAGNOSTIC panic("wdioctl: impossible"); #endif + + exit: + device_unref(&wd->sc_dev); + return (error); } #ifdef B_FORMAT @@ -1047,30 +1126,33 @@ wdsize(dev) dev_t dev; { struct wd_softc *wd; - int part, unit, omask; + int part, omask; int size; WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS); - unit = WDUNIT(dev); - if (unit >= wd_cd.cd_ndevs) - return (-1); - wd = wd_cd.cd_devs[unit]; + wd = wdlookup(WDUNIT(dev)); if (wd == NULL) return (-1); part = WDPART(dev); omask = wd->sc_dk.dk_openmask & (1 << part); - if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) - return (-1); + if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) { + size = -1; + goto exit; + } + if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) size = -1; else size = wd->sc_dk.dk_label->d_partitions[part].p_size * (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0) - return (-1); + size = -1; + + exit: + device_unref(&wd->sc_dev); return (size); } @@ -1103,10 +1185,8 @@ wddump(dev, blkno, va, size) wddoingadump = 1; unit = WDUNIT(dev); - if (unit >= wd_cd.cd_ndevs) - return ENXIO; - wd = wd_cd.cd_devs[unit]; - if (wd == (struct wd_softc *)0) + wd = wdlookup(unit); + if (wd == NULL) return ENXIO; part = WDPART(dev); @@ -1147,6 +1227,7 @@ again: wd->sc_wdc_bio.bcount = min(nblks, wddumpmulti) * lp->d_secsize; wd->sc_wdc_bio.databuf = va; + wd->sc_wdc_bio.wd = wd; #ifndef WD_DUMP_NOT_TRUSTED switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) { case WDC_TRY_AGAIN: diff --git a/sys/dev/ata/wdvar.h b/sys/dev/ata/wdvar.h index 46fb4ee0c18..5dc67ffedbe 100644 --- a/sys/dev/ata/wdvar.h +++ b/sys/dev/ata/wdvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wdvar.h,v 1.1 1999/07/18 21:25:18 csapuntz Exp $ */ +/* $OpenBSD: wdvar.h,v 1.2 2000/04/10 07:06:16 csapuntz Exp $ */ /* $NetBSD: wdvar.h,v 1.3 1998/11/11 19:38:27 bouyer Exp $ */ /* @@ -58,8 +58,10 @@ struct ata_bio { #define ERR_DF 2 /* Drive fault */ #define ERR_DMA 3 /* DMA error */ #define TIMEOUT 4 /* device timed out */ +#define ERR_NODEV 5 /* device bas been detached */ u_int8_t r_error; /* copy of error register */ daddr_t badsect[127]; /* 126 plus trailing -1 marker */ + struct wd_softc *wd; }; /* drive states stored in ata_drive_datas */ |