diff options
Diffstat (limited to 'sys/dev/ata')
| -rw-r--r-- | sys/dev/ata/ata_wdc.c | 23 | ||||
| -rw-r--r-- | sys/dev/ata/atavar.h | 18 | ||||
| -rw-r--r-- | sys/dev/ata/wd.c | 9 |
3 files changed, 40 insertions, 10 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c index 4a6bc577bff..02da34e06e5 100644 --- a/sys/dev/ata/ata_wdc.c +++ b/sys/dev/ata/ata_wdc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata_wdc.c,v 1.57 2004/06/22 19:20:56 mycroft Exp $ */ +/* $NetBSD: ata_wdc.c,v 1.58 2004/07/31 21:26:43 bouyer Exp $ */ /* * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.57 2004/06/22 19:20:56 mycroft Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.58 2004/07/31 21:26:43 bouyer Exp $"); #ifndef WDCDEBUG #define WDCDEBUG @@ -119,7 +119,8 @@ static void wdc_ata_bio_start(struct wdc_channel *,struct ata_xfer *); static void _wdc_ata_bio_start(struct wdc_channel *,struct ata_xfer *); static int wdc_ata_bio_intr(struct wdc_channel *, struct ata_xfer *, int); -static void wdc_ata_bio_kill_xfer(struct wdc_channel *,struct ata_xfer *); +static void wdc_ata_bio_kill_xfer(struct wdc_channel *, + struct ata_xfer *, int); static void wdc_ata_bio_done(struct wdc_channel *, struct ata_xfer *); static int wdc_ata_err(struct ata_drive_datas *, struct ata_bio *); #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */ @@ -740,7 +741,8 @@ wdc_ata_kill_pending(struct ata_drive_datas *drvp) } static void -wdc_ata_bio_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer) +wdc_ata_bio_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer, + int reason) { struct ata_bio *ata_bio = xfer->c_cmd; int drive = xfer->c_drive; @@ -750,7 +752,18 @@ wdc_ata_bio_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer) wdc_free_xfer(chp, xfer); ata_bio->flags |= ATA_ITSDONE; - ata_bio->error = ERR_NODEV; + switch (reason) { + case KILL_GONE: + ata_bio->error = ERR_NODEV; + break; + case KILL_RESET: + ata_bio->error = ERR_RESET; + break; + default: + printf("wdc_ata_bio_kill_xfer: unknown reason %d\n", + reason); + panic("wdc_ata_bio_kill_xfer"); + } ata_bio->r_error = WDCE_ABRT; WDCDEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS); (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc); diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h index ac922ca7865..0844268b652 100644 --- a/sys/dev/ata/atavar.h +++ b/sys/dev/ata/atavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: atavar.h,v 1.43 2004/06/01 19:32:30 mycroft Exp $ */ +/* $NetBSD: atavar.h,v 1.44 2004/07/31 21:26:43 bouyer Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -58,14 +58,19 @@ struct ata_xfer { /* Low-level protocol handlers. */ void (*c_start)(struct wdc_channel *, struct ata_xfer *); int (*c_intr)(struct wdc_channel *, struct ata_xfer *, int); - void (*c_kill_xfer)(struct wdc_channel *, struct ata_xfer *); + void (*c_kill_xfer)(struct wdc_channel *, struct ata_xfer *, int); }; +/* vlags in c_flags */ #define C_ATAPI 0x0001 /* xfer is ATAPI request */ #define C_TIMEOU 0x0002 /* xfer processing timed out */ #define C_POLL 0x0004 /* command is polled */ #define C_DMA 0x0008 /* command uses DMA */ +/* reasons for c_kill_xfer() */ +#define KILL_GONE 1 /* device is gone */ +#define KILL_RESET 2 /* xfer was reset */ + /* Per-channel queue of ata_xfers. May be shared by multiple channels. */ struct ata_queue { TAILQ_HEAD(, ata_xfer) queue_xfer; @@ -192,6 +197,7 @@ struct ata_bio { #define ERR_DMA 3 /* DMA error */ #define TIMEOUT 4 /* device timed out */ #define ERR_NODEV 5 /* device has been gone */ +#define ERR_RESET 6 /* command was terminated by channel reset */ u_int8_t r_error;/* copy of error register */ daddr_t badsect[127];/* 126 plus trailing -1 marker */ }; @@ -232,7 +238,9 @@ struct wdc_command { #define AT_ERROR 0x0080 /* command is done with error */ #define AT_TIMEOU 0x0100 /* command timed out */ #define AT_DF 0x0200 /* Drive fault */ -#define AT_READREG 0x0400 /* Read registers on completion */ +#define AT_RESET 0x0400 /* command terminated by channel reset */ +#define AT_GONE 0x0800 /* command terminated because device is gone */ +#define AT_READREG 0x1000 /* Read registers on completion */ int timeout; /* timeout (in ms) */ void *data; /* Data buffer address */ @@ -249,6 +257,10 @@ struct ata_bustype { int bustype_type; /* symbolic name of type */ int (*ata_bio)(struct ata_drive_datas *, struct ata_bio *); void (*ata_reset_channel)(struct ata_drive_datas *, int); +/* extra flags for ata_reset_channel(), in addition to AT_* */ +#define AT_RST_EMERG 0x10000 /* emergency - e.g. for a dump */ +#define AT_RST_NOCMD 0x20000 /* XXX has to go - temporary until we have tagged queuing */ + int (*ata_exec_command)(struct ata_drive_datas *, struct wdc_command *); diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index 7198f2ff256..a949e820e69 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.280 2004/06/22 19:20:56 mycroft Exp $ */ +/* $NetBSD: wd.c,v 1.281 2004/07/31 21:26:43 bouyer Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.280 2004/06/22 19:20:56 mycroft Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.281 2004/07/31 21:26:43 bouyer Exp $"); #ifndef WDCDEBUG #define WDCDEBUG @@ -742,6 +742,9 @@ wddone(void *v) case TIMEOUT: errmsg = "device timeout"; goto retry; + case ERR_RESET: + errmsg = "channel reset"; + goto retry2; case ERROR: /* Don't care about media change bits */ if (wd->sc_wdc_bio.r_error != 0 && @@ -751,6 +754,7 @@ wddone(void *v) do_perror = 1; retry: /* Just reset and retry. Can we do more ? */ wd->atabus->ata_reset_channel(wd->drvp, 0); +retry2: diskerr(bp, "wd", errmsg, LOG_PRINTF, wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label); if (wd->retries < WDIORETRIES) @@ -1449,6 +1453,7 @@ wddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) if (wddumprecalibrated == 0) { wddumpmulti = wd->sc_multi; wddumprecalibrated = 1; + wd->atabus->ata_reset_channel(wd->drvp, AT_POLL | AT_RST_EMERG); wd->drvp->state = RESET; } |
