summaryrefslogtreecommitdiff
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorbouyer <bouyer@NetBSD.org>2012-07-31 15:50:31 +0000
committerbouyer <bouyer@NetBSD.org>2012-07-31 15:50:31 +0000
commitaee187e7a26ea9ba93b45c0bbcd0fdd490c6c497 (patch)
tree934c95ddcb0012348fd3eed617f4d0cb81445f12 /sys/dev/ata
parentb2061654b40cbc50de035c4291bfd62bee95faa7 (diff)
Apply back changes that were reverted on Jul 24 and Jul 26 (general ata/wdc
cleanup and SATA PMP support), now that I'm back to fix the fallouts.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/ata.c283
-rw-r--r--sys/dev/ata/ata_wdc.c24
-rw-r--r--sys/dev/ata/atavar.h47
-rw-r--r--sys/dev/ata/files.ata5
-rw-r--r--sys/dev/ata/sata_subr.c55
-rw-r--r--sys/dev/ata/satapmpreg.h7
-rw-r--r--sys/dev/ata/satavar.h3
-rw-r--r--sys/dev/ata/wd.c40
8 files changed, 326 insertions, 138 deletions
diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c
index a83e2a0e041..d26d9cc6d93 100644
--- a/sys/dev/ata/ata.c
+++ b/sys/dev/ata/ata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.123 2012/07/29 21:10:50 jakllsch Exp $ */
+/* $NetBSD: ata.c,v 1.124 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.123 2012/07/29 21:10:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.124 2012/07/31 15:50:34 bouyer Exp $");
#include "opt_ata.h"
@@ -55,10 +55,15 @@ __KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.123 2012/07/29 21:10:50 jakllsch Exp $");
#include "atapibus.h"
#include "ataraid.h"
+#include "sata_pmp.h"
#if NATARAID > 0
#include <dev/ata/ata_raidvar.h>
#endif
+#if NSATA_PMP > 0
+#include <dev/ata/satapmpvar.h>
+#endif
+#include <dev/ata/satapmpreg.h>
#define DEBUG_FUNCS 0x08
#define DEBUG_PROBE 0x10
@@ -199,13 +204,19 @@ atabusconfig(struct atabus_softc *atabus_sc)
chp->ch_flags |= ATACH_TH_RUN;
splx(s);
- /* Probe for the drives. */
+ /*
+ * Probe for the drives attached to controller, unless a PMP
+ * is already known
+ */
/* XXX for SATA devices we will power up all drives at once */
- (*atac->atac_probe)(chp);
+ if (chp->ch_satapmp_nports == 0)
+ (*atac->atac_probe)(chp);
- ATADEBUG_PRINT(("atabusattach: ch_drive_flags 0x%x 0x%x\n",
- chp->ch_drive[0].drive_flags, chp->ch_drive[1].drive_flags),
- DEBUG_PROBE);
+ if (chp->ch_drive != NULL && chp->ch_ndrives >= 2) {
+ ATADEBUG_PRINT(("atabusattach: ch_drive_type 0x%x 0x%x\n",
+ chp->ch_drive[0].drive_type, chp->ch_drive[1].drive_type),
+ DEBUG_PROBE);
+ }
/* next operations will occurs in a separate thread */
s = splbio();
@@ -223,17 +234,19 @@ atabusconfig(struct atabus_softc *atabus_sc)
mutex_exit(&atabus_qlock);
/* If no drives, abort here */
- for (i = 0; i < chp->ch_ndrive; i++)
- if ((chp->ch_drive[i].drive_flags & DRIVE) != 0)
+ if (chp->ch_drive == NULL)
+ goto out;
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (i = 0; i < chp->ch_ndrives; i++)
+ if (chp->ch_drive[i].drive_type != ATA_DRIVET_NONE)
break;
- if (i == chp->ch_ndrive)
+ if (i == chp->ch_ndrives)
goto out;
/* Shortcut in case we've been shutdown */
if (chp->ch_flags & ATACH_SHUTDOWN)
goto out;
-
if ((error = kthread_create(PRI_NONE, 0, NULL, atabusconfig_thread,
atabus_sc, &atabus_cfg_lwp,
"%scnf", device_xname(atac->atac_dev))) != 0)
@@ -274,10 +287,25 @@ atabusconfig_thread(void *arg)
mutex_exit(&atabus_qlock);
/*
+ * First look for a port multiplier
+ */
+ if (chp->ch_ndrives == PMP_MAX_DRIVES &&
+ chp->ch_drive[PMP_PORT_CTL].drive_type == ATA_DRIVET_PM) {
+#if NSATA_PMP > 0
+ satapmp_attach(chp);
+#else
+ aprint_error_dev(atabus_sc->sc_dev,
+ "SATA port multiplier not supported\n");
+ /* no problems going on, all drives are ATA_DRIVET_NONE */
+#endif
+ }
+
+ /*
* Attach an ATAPI bus, if needed.
*/
- for (i = 0; i < chp->ch_ndrive; i++) {
- if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) {
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (i = 0; i < chp->ch_ndrives && chp->atapibus == NULL; i++) {
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATAPI) {
#if NATAPIBUS > 0
(*atac->atac_atapibus_attach)(atabus_sc);
#else
@@ -288,34 +316,36 @@ atabusconfig_thread(void *arg)
device_xname(atac->atac_dev));
chp->atapibus = NULL;
s = splbio();
- for (i = 0; i < chp->ch_ndrive; i++)
- chp->ch_drive[i].drive_flags &= ~DRIVE_ATAPI;
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATAPI)
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
+ }
splx(s);
#endif
break;
}
}
- for (i = 0; i < chp->ch_ndrive; i++) {
+ for (i = 0; i < chp->ch_ndrives; i++) {
struct ata_device adev;
- if ((chp->ch_drive[i].drive_flags &
- (DRIVE_ATA | DRIVE_OLD)) == 0) {
+ if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATA &&
+ chp->ch_drive[i].drive_type != ATA_DRIVET_OLD) {
continue;
}
+ if (chp->ch_drive[i].drv_softc != NULL)
+ continue;
memset(&adev, 0, sizeof(struct ata_device));
adev.adev_bustype = atac->atac_bustype_ata;
adev.adev_channel = chp->ch_channel;
adev.adev_openings = 1;
adev.adev_drv_data = &chp->ch_drive[i];
- KASSERT(chp->ch_drive[i].drv_softc == NULL);
chp->ch_drive[i].drv_softc = config_found_ia(atabus_sc->sc_dev,
"ata_hl", &adev, ataprint);
- if (chp->ch_drive[i].drv_softc != NULL)
+ if (chp->ch_drive[i].drv_softc != NULL) {
ata_probe_caps(&chp->ch_drive[i]);
- else {
+ } else {
s = splbio();
- chp->ch_drive[i].drive_flags &=
- ~(DRIVE_ATA | DRIVE_OLD);
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
splx(s);
}
}
@@ -327,9 +357,8 @@ atabusconfig_thread(void *arg)
}
#if NATARAID > 0
if (atac->atac_cap & ATAC_CAP_RAID) {
- for (i = 0; i < chp->ch_ndrive; i++) {
- if ((chp->ch_drive[i].drv_softc != NULL) &&
- (chp->ch_drive[i].drive_flags & DRIVE_ATA)) {
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATA) {
ata_raid_check_component(
chp->ch_drive[i].drv_softc);
}
@@ -342,10 +371,13 @@ atabusconfig_thread(void *arg)
* ones
*/
s = splbio();
- for (i = 0; i < chp->ch_ndrive; i++) {
- if (chp->ch_drive[i].drv_softc == NULL)
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_PM)
+ continue;
+ if (chp->ch_drive[i].drv_softc == NULL) {
chp->ch_drive[i].drive_flags = 0;
- else
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
+ } else
chp->ch_drive[i].state = 0;
}
splx(s);
@@ -380,13 +412,16 @@ atabus_thread(void *arg)
chp->ch_flags |= ATACH_TH_RUN;
/*
- * Probe the drives. Reset all flags to 0 to indicate to controllers
+ * Probe the drives. Reset type to indicate to controllers
* that can re-probe that all drives must be probed..
*
- * Note: ch_ndrive may be changed during the probe.
+ * Note: ch_ndrives may be changed during the probe.
*/
- for (i = 0; i < ATA_MAXDRIVES; i++)
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (i = 0; i < chp->ch_ndrives; i++) {
chp->ch_drive[i].drive_flags = 0;
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
+ }
splx(s);
atabusconfig(sc);
@@ -528,12 +563,16 @@ atabus_detach(device_t self, int flags)
KASSERT(chp->atapibus == NULL);
}
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+
/*
* Detach our other children.
*/
- for (i = 0; i < chp->ch_ndrive; i++) {
- if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI)
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATAPI)
continue;
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_PM)
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
if ((dev = chp->ch_drive[i].drv_softc) != NULL) {
ATADEBUG_PRINT(("%s.%d: %s: detaching %s\n", __func__,
__LINE__, device_xname(self), device_xname(dev)),
@@ -542,9 +581,10 @@ atabus_detach(device_t self, int flags)
if (error)
goto out;
KASSERT(chp->ch_drive[i].drv_softc == NULL);
- KASSERT((chp->ch_drive[i].drive_flags & DRIVE) == 0);
+ KASSERT(chp->ch_drive[i].drive_type == 0);
}
}
+ atabus_free_drives(chp);
out:
#ifdef ATADEBUG
@@ -565,23 +605,35 @@ atabus_childdetached(device_t self, device_t child)
struct ata_channel *chp = sc->sc_chan;
int i;
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
/*
* atapibus detached.
*/
if (child == chp->atapibus) {
chp->atapibus = NULL;
found = true;
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATAPI)
+ continue;
+ KASSERT(chp->ch_drive[i].drv_softc != NULL);
+ chp->ch_drive[i].drv_softc = NULL;
+ chp->ch_drive[i].drive_flags = 0;
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
+ }
}
/*
* Detach our other children.
*/
- for (i = 0; i < chp->ch_ndrive; i++) {
- if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI)
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATAPI)
continue;
if (child == chp->ch_drive[i].drv_softc) {
chp->ch_drive[i].drv_softc = NULL;
chp->ch_drive[i].drive_flags = 0;
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_PM)
+ chp->ch_satapmp_nports = 0;
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
found = true;
}
}
@@ -599,6 +651,64 @@ CFATTACH_DECL3_NEW(atabus, sizeof(struct atabus_softc),
* Common ATA bus operations.
*****************************************************************************/
+/* allocate/free the channel's ch_drive[] array */
+int
+atabus_alloc_drives(struct ata_channel *chp, int ndrives)
+{
+ int i;
+ if (chp->ch_ndrives != ndrives)
+ atabus_free_drives(chp);
+ if (chp->ch_drive == NULL) {
+ chp->ch_drive = malloc(
+ sizeof(struct ata_drive_datas) * ndrives,
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ }
+ if (chp->ch_drive == NULL) {
+ aprint_error_dev(chp->ch_atac->atac_dev,
+ "can't alloc drive array\n");
+ chp->ch_ndrives = 0;
+ return ENOMEM;
+ };
+ for (i = 0; i < ndrives; i++) {
+ chp->ch_drive[i].chnl_softc = chp;
+ chp->ch_drive[i].drive = i;
+ }
+ chp->ch_ndrives = ndrives;
+ return 0;
+}
+
+void
+atabus_free_drives(struct ata_channel *chp)
+{
+#ifdef DIAGNOSTIC
+ int i;
+ int dopanic = 0;
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type != ATA_DRIVET_NONE) {
+ printf("%s: ch_drive[%d] type %d != ATA_DRIVET_NONE\n",
+ device_xname(chp->atabus), i,
+ chp->ch_drive[i].drive_type);
+ dopanic = 1;
+ }
+ if (chp->ch_drive[i].drv_softc != NULL) {
+ printf("%s: ch_drive[%d] attached to %s\n",
+ device_xname(chp->atabus), i,
+ device_xname(chp->ch_drive[i].drv_softc));
+ dopanic = 1;
+ }
+ }
+ if (dopanic)
+ panic("atabus_free_drives");
+#endif
+
+ if (chp->ch_drive == NULL)
+ return;
+ chp->ch_ndrives = 0;
+ free(chp->ch_drive, M_DEVBUF);
+ chp->ch_drive = NULL;
+}
+
/* Get the disk's parameters */
int
ata_get_params(struct ata_drive_datas *drvp, u_int8_t flags,
@@ -617,12 +727,12 @@ ata_get_params(struct ata_drive_datas *drvp, u_int8_t flags,
memset(prms, 0, sizeof(struct ataparams));
memset(&ata_c, 0, sizeof(struct ata_command));
- if (drvp->drive_flags & DRIVE_ATA) {
+ if (drvp->drive_type == ATA_DRIVET_ATA) {
ata_c.r_command = WDCC_IDENTIFY;
ata_c.r_st_bmask = WDCS_DRDY;
ata_c.r_st_pmask = WDCS_DRQ;
ata_c.timeout = 3000; /* 3s */
- } else if (drvp->drive_flags & DRIVE_ATAPI) {
+ } else if (drvp->drive_type == ATA_DRIVET_ATAPI) {
ata_c.r_command = ATAPI_IDENTIFY_DEVICE;
ata_c.r_st_bmask = 0;
ata_c.r_st_pmask = WDCS_DRQ;
@@ -673,7 +783,7 @@ ata_get_params(struct ata_drive_datas *drvp, u_int8_t flags,
#if BYTE_ORDER == BIG_ENDIAN
!
#endif
- ((drvp->drive_flags & DRIVE_ATAPI) ?
+ ((drvp->drive_type == ATA_DRIVET_ATAPI) ?
((M(0) == 'N' && M(1) == 'E') ||
(M(0) == 'F' && M(1) == 'X') ||
(M(0) == 'P' && M(1) == 'i')) :
@@ -869,8 +979,8 @@ atastart(struct ata_channel *chp)
ATADEBUG_PRINT(("atastart: xfer %p channel %d drive %d\n", xfer,
chp->ch_channel, xfer->c_drive), DEBUG_XFERS);
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_RESET) {
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_RESET;
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_RESET) {
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_RESET;
chp->ch_drive[xfer->c_drive].state = 0;
}
chp->ch_queue->active_xfer = xfer;
@@ -952,7 +1062,7 @@ ata_kill_pending(struct ata_drive_datas *drvp)
while ((xfer = chp->ch_queue->active_xfer) != NULL) {
if (xfer->c_chp == chp && xfer->c_drive == drvp->drive) {
- drvp->drive_flags |= DRIVE_WAITDRAIN;
+ drvp->drive_flags |= ATA_DRIVE_WAITDRAIN;
(void) tsleep(&chp->ch_queue->active_xfer,
PRIBIO, "atdrn", 0);
} else {
@@ -1011,7 +1121,8 @@ ata_reset_channel(struct ata_channel *chp, int flags)
(*atac->atac_bustype_ata->ata_reset_channel)(chp, flags);
- for (drive = 0; drive < chp->ch_ndrive; drive++)
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (drive = 0; drive < chp->ch_ndrives; drive++)
chp->ch_drive[drive].state = 0;
chp->ch_flags &= ~ATACH_TH_RESET;
@@ -1065,19 +1176,21 @@ ata_print_modes(struct ata_channel *chp)
int drive;
struct ata_drive_datas *drvp;
- for (drive = 0; drive < chp->ch_ndrive; drive++) {
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (drive = 0; drive < chp->ch_ndrives; drive++) {
drvp = &chp->ch_drive[drive];
- if ((drvp->drive_flags & DRIVE) == 0 || drvp->drv_softc == NULL)
+ if (drvp->drive_type == ATA_DRIVET_NONE ||
+ drvp->drv_softc == NULL)
continue;
aprint_verbose("%s(%s:%d:%d): using PIO mode %d",
device_xname(drvp->drv_softc),
device_xname(atac->atac_dev),
chp->ch_channel, drvp->drive, drvp->PIO_mode);
#if NATA_DMA
- if (drvp->drive_flags & DRIVE_DMA)
+ if (drvp->drive_flags & ATA_DRIVE_DMA)
aprint_verbose(", DMA mode %d", drvp->DMA_mode);
#if NATA_UDMA
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
aprint_verbose(", Ultra-DMA mode %d", drvp->UDMA_mode);
if (drvp->UDMA_mode == 2)
aprint_verbose(" (Ultra/33)");
@@ -1093,7 +1206,7 @@ ata_print_modes(struct ata_channel *chp)
#if NATA_DMA || NATA_PIOBM
if (0
#if NATA_DMA
- || (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA))
+ || (drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA))
#endif
#if NATA_PIOBM
/* PIOBM capable controllers use DMA for PIO commands */
@@ -1122,7 +1235,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags)
int cf_flags = device_cfdata(drv_dev)->cf_flags;
/* if drive or controller don't know its mode, we can't do much */
- if ((drvp->drive_flags & DRIVE_MODE) == 0 ||
+ if ((drvp->drive_flags & ATA_DRIVE_MODE) == 0 ||
(atac->atac_set_modes == NULL))
return 0;
/* current drive mode was set by a config flag, let it this way */
@@ -1135,7 +1248,7 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags)
/*
* If we were using Ultra-DMA mode, downgrade to the next lower mode.
*/
- if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) {
+ if ((drvp->drive_flags & ATA_DRIVE_UDMA) && drvp->UDMA_mode >= 2) {
drvp->UDMA_mode--;
aprint_error_dev(drv_dev,
"transfer error, downgrading to Ultra-DMA mode %d\n",
@@ -1146,8 +1259,8 @@ ata_downgrade_mode(struct ata_drive_datas *drvp, int flags)
/*
* If we were using ultra-DMA, don't downgrade to multiword DMA.
*/
- else if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
- drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
+ else if (drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) {
+ drvp->drive_flags &= ~(ATA_DRIVE_DMA | ATA_DRIVE_UDMA);
drvp->PIO_mode = drvp->PIO_cap;
aprint_error_dev(drv_dev,
"transfer error, downgrading to PIO mode %d\n",
@@ -1190,13 +1303,13 @@ ata_probe_caps(struct ata_drive_datas *drvp)
* and compare results.
*/
s = splbio();
- drvp->drive_flags |= DRIVE_CAP32;
+ drvp->drive_flags |= ATA_DRIVE_CAP32;
splx(s);
ata_get_params(drvp, AT_WAIT, &params2);
if (memcmp(&params, &params2, sizeof(struct ataparams)) != 0) {
/* Not good. fall back to 16bits */
s = splbio();
- drvp->drive_flags &= ~DRIVE_CAP32;
+ drvp->drive_flags &= ~ATA_DRIVE_CAP32;
splx(s);
} else {
aprint_verbose_dev(drv_dev, "32-bit data port\n");
@@ -1217,7 +1330,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
#endif
/* An ATAPI device is at last PIO mode 3 */
- if (drvp->drive_flags & DRIVE_ATAPI)
+ if (drvp->drive_type == ATA_DRIVET_ATAPI)
drvp->PIO_mode = 3;
/*
@@ -1277,7 +1390,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
return;
}
s = splbio();
- drvp->drive_flags |= DRIVE_MODE;
+ drvp->drive_flags |= ATA_DRIVE_MODE;
splx(s);
printed = 0;
for (i = 7; i >= 0; i--) {
@@ -1303,7 +1416,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
drvp->DMA_mode = i;
drvp->DMA_cap = i;
s = splbio();
- drvp->drive_flags |= DRIVE_DMA;
+ drvp->drive_flags |= ATA_DRIVE_DMA;
splx(s);
}
#endif
@@ -1344,7 +1457,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
drvp->UDMA_mode = i;
drvp->UDMA_cap = i;
s = splbio();
- drvp->drive_flags |= DRIVE_UDMA;
+ drvp->drive_flags |= ATA_DRIVE_UDMA;
splx(s);
}
#endif
@@ -1355,20 +1468,20 @@ ata_probe_caps(struct ata_drive_datas *drvp)
}
s = splbio();
- drvp->drive_flags &= ~DRIVE_NOSTREAM;
- if (drvp->drive_flags & DRIVE_ATAPI) {
+ drvp->drive_flags &= ~ATA_DRIVE_NOSTREAM;
+ if (drvp->drive_type == ATA_DRIVET_ATAPI) {
if (atac->atac_cap & ATAC_CAP_ATAPI_NOSTREAM)
- drvp->drive_flags |= DRIVE_NOSTREAM;
+ drvp->drive_flags |= ATA_DRIVE_NOSTREAM;
} else {
if (atac->atac_cap & ATAC_CAP_ATA_NOSTREAM)
- drvp->drive_flags |= DRIVE_NOSTREAM;
+ drvp->drive_flags |= ATA_DRIVE_NOSTREAM;
}
splx(s);
/* Try to guess ATA version here, if it didn't get reported */
if (drvp->ata_vers == 0) {
#if NATA_UDMA
- if (drvp->drive_flags & DRIVE_UDMA)
+ if (drvp->drive_flags & ATA_DRIVE_UDMA)
drvp->ata_vers = 4; /* should be at last ATA-4 */
else
#endif
@@ -1380,7 +1493,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
s = splbio();
drvp->PIO_mode =
(cf_flags & ATA_CONFIG_PIO_MODES) >> ATA_CONFIG_PIO_OFF;
- drvp->drive_flags |= DRIVE_MODE;
+ drvp->drive_flags |= ATA_DRIVE_MODE;
splx(s);
}
#if NATA_DMA
@@ -1392,11 +1505,11 @@ ata_probe_caps(struct ata_drive_datas *drvp)
s = splbio();
if ((cf_flags & ATA_CONFIG_DMA_MODES) ==
ATA_CONFIG_DMA_DISABLE) {
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
} else {
drvp->DMA_mode = (cf_flags & ATA_CONFIG_DMA_MODES) >>
ATA_CONFIG_DMA_OFF;
- drvp->drive_flags |= DRIVE_DMA | DRIVE_MODE;
+ drvp->drive_flags |= ATA_DRIVE_DMA | ATA_DRIVE_MODE;
}
splx(s);
}
@@ -1409,11 +1522,11 @@ ata_probe_caps(struct ata_drive_datas *drvp)
s = splbio();
if ((cf_flags & ATA_CONFIG_UDMA_MODES) ==
ATA_CONFIG_UDMA_DISABLE) {
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
} else {
drvp->UDMA_mode = (cf_flags & ATA_CONFIG_UDMA_MODES) >>
ATA_CONFIG_UDMA_OFF;
- drvp->drive_flags |= DRIVE_UDMA | DRIVE_MODE;
+ drvp->drive_flags |= ATA_DRIVE_UDMA | ATA_DRIVE_MODE;
}
splx(s);
}
@@ -1492,8 +1605,8 @@ atabusioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
struct atabusioscan_args *a=
(struct atabusioscan_args *)addr;
#endif
- if ((chp->ch_drive[0].drive_flags & DRIVE_OLD) ||
- (chp->ch_drive[1].drive_flags & DRIVE_OLD))
+ if ((chp->ch_drive[0].drive_type == ATA_DRIVET_OLD) ||
+ (chp->ch_drive[1].drive_type == ATA_DRIVET_OLD))
return (EOPNOTSUPP);
return (EOPNOTSUPP);
}
@@ -1501,8 +1614,8 @@ atabusioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
struct atabusiodetach_args *a=
(struct atabusiodetach_args *)addr;
- if ((chp->ch_drive[0].drive_flags & DRIVE_OLD) ||
- (chp->ch_drive[1].drive_flags & DRIVE_OLD))
+ if ((chp->ch_drive[0].drive_type == ATA_DRIVET_OLD) ||
+ (chp->ch_drive[1].drive_type == ATA_DRIVET_OLD))
return (EOPNOTSUPP);
switch (a->at_dev) {
case -1:
@@ -1575,23 +1688,23 @@ atabus_rescan(device_t self, const char *ifattr, const int *locators)
struct ata_channel *chp = sc->sc_chan;
struct atabus_initq *initq;
int i;
- int s;
- if (chp->atapibus != NULL) {
- return EBUSY;
- }
-
- for (i = 0; i < ATA_MAXDRIVES; i++) {
- if (chp->ch_drive[i].drv_softc != NULL) {
+ /*
+ * we can rescan a port multiplier atabus, even if some devices are
+ * still attached
+ */
+ if (chp->ch_satapmp_nports == 0) {
+ if (chp->atapibus != NULL) {
return EBUSY;
}
- }
- s = splbio();
- for (i = 0; i < ATA_MAXDRIVES; i++) {
- chp->ch_drive[i].drive_flags = 0;
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drv_softc != NULL) {
+ return EBUSY;
+ }
+ }
}
- splx(s);
initq = malloc(sizeof(*initq), M_DEVBUF, M_WAITOK);
initq->atabus_sc = sc;
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c
index af4f9635d68..8ae353cfe6d 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.100 2012/07/26 20:49:47 jakllsch Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.101 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
@@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.100 2012/07/26 20:49:47 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.101 2012/07/31 15:50:34 bouyer Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -149,7 +149,7 @@ wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
if (ata_bio->flags & ATA_POLL)
xfer->c_flags |= C_POLL;
#if NATA_DMA
- if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
+ if ((drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) &&
(ata_bio->flags & ATA_SINGLE) == 0)
xfer->c_flags |= C_DMA;
#endif
@@ -187,8 +187,10 @@ wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
#endif
- ATADEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
- device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive),
+ ATADEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d state %d drive_flags 0x%x "
+ "c_flags 0x%x ch_flags 0x%x\n",
+ device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive,
+ drvp->state, drvp->drive_flags, xfer->c_flags, chp->ch_flags),
DEBUG_XFERS);
/* Do control operations specially. */
@@ -231,7 +233,7 @@ wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
if (atac->atac_set_modes == NULL)
goto geometry;
/* Also don't try if the drive didn't report its mode */
- if ((drvp->drive_flags & DRIVE_MODE) == 0)
+ if ((drvp->drive_flags & ATA_DRIVE_MODE) == 0)
goto geometry;
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
0x08 | drvp->PIO_mode, WDSF_SET_MODE);
@@ -242,12 +244,12 @@ wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
goto ctrlerror;
#if NATA_DMA
#if NATA_UDMA
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
} else
#endif
- if (drvp->drive_flags & DRIVE_DMA) {
+ if (drvp->drive_flags & ATA_DRIVE_DMA) {
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
} else {
@@ -780,7 +782,7 @@ wdc_ata_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer,
panic("wdc_ata_bio_kill_xfer");
}
ata_bio->r_error = WDCE_ABRT;
- ATADEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS);
+ ATADEBUG_PRINT(("wdc_ata_bio_kill_xfer: drv_done\n"), DEBUG_XFERS);
(*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
}
@@ -804,9 +806,9 @@ wdc_ata_bio_done(struct ata_channel *chp, struct ata_xfer *xfer)
chp->ch_queue->active_xfer = NULL;
ata_free_xfer(chp, xfer);
- if (chp->ch_drive[drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
ata_bio->error = ERR_NODEV;
- chp->ch_drive[drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
}
ata_bio->flags |= ATA_ITSDONE;
diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h
index 24878f34af9..5b45d0da107 100644
--- a/sys/dev/ata/atavar.h
+++ b/sys/dev/ata/atavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.89 2012/07/29 21:10:50 jakllsch Exp $ */
+/* $NetBSD: atavar.h,v 1.90 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -37,11 +37,6 @@
#include <dev/scsipi/atapiconf.h>
/*
- * Max number of drives per channel.
- */
-#define ATA_MAXDRIVES 2
-
-/*
* Description of a command to be handled by an ATA controller. These
* commands are queued in a list.
*/
@@ -116,19 +111,21 @@ struct ata_drive_datas {
u_int8_t drive; /* drive number */
int8_t ata_vers; /* ATA version supported */
u_int16_t drive_flags; /* bitmask for drives present/absent and cap */
-
-#define DRIVE_ATA 0x0001
-#define DRIVE_ATAPI 0x0002
-#define DRIVE_OLD 0x0004
-#define DRIVE (DRIVE_ATA|DRIVE_ATAPI|DRIVE_OLD)
-#define DRIVE_CAP32 0x0008
-#define DRIVE_DMA 0x0010
-#define DRIVE_UDMA 0x0020
-#define DRIVE_MODE 0x0040 /* the drive reported its mode */
-#define DRIVE_RESET 0x0080 /* reset the drive state at next xfer */
-#define DRIVE_WAITDRAIN 0x0100 /* device is waiting for the queue to drain */
-#define DRIVE_ATAPIST 0x0200 /* device is an ATAPI tape drive */
-#define DRIVE_NOSTREAM 0x0400 /* no stream methods on this drive */
+#define ATA_DRIVE_CAP32 0x0001
+#define ATA_DRIVE_DMA 0x0002
+#define ATA_DRIVE_UDMA 0x0004
+#define ATA_DRIVE_MODE 0x0008 /* the drive reported its mode */
+#define ATA_DRIVE_RESET 0x0010 /* reset the drive state at next xfer */
+#define ATA_DRIVE_WAITDRAIN 0x0020 /* device is waiting for the queue to drain */
+#define ATA_DRIVE_NOSTREAM 0x0040 /* no stream methods on this drive */
+#define ATA_DRIVE_ATAPIDSCW 0x0080 /* needs to wait for DSC in phase_complete */
+
+ uint8_t drive_type;
+#define ATA_DRIVET_NONE 0
+#define ATA_DRIVET_ATA 1
+#define ATA_DRIVET_ATAPI 2
+#define ATA_DRIVET_OLD 3
+#define ATA_DRIVET_PM 4
/*
* Current setting of drive's PIO, DMA and UDMA modes.
@@ -286,7 +283,7 @@ struct ata_command {
struct ata_bustype {
int bustype_type; /* symbolic name of type */
int (*ata_bio)(struct ata_drive_datas *, struct ata_bio *);
- void (*ata_reset_drive)(struct ata_drive_datas *, int);
+ void (*ata_reset_drive)(struct ata_drive_datas *, int, uint32_t *);
void (*ata_reset_channel)(struct ata_channel *, int);
/* extra flags for ata_reset_*(), in addition to AT_* */
#define AT_RST_EMERG 0x10000 /* emergency - e.g. for a dump */
@@ -347,8 +344,8 @@ struct ata_channel {
int ch_reset_flags;
/* per-drive info */
- int ch_ndrive;
- struct ata_drive_datas ch_drive[ATA_MAXDRIVES];
+ int ch_ndrives; /* number of entries in ch_drive[] */
+ struct ata_drive_datas *ch_drive; /* array of ata_drive_datas */
device_t atabus; /* self */
@@ -364,6 +361,9 @@ struct ata_channel {
/* The channel kernel thread */
struct lwp *ch_thread;
+
+ /* Number of sata PMP ports, if any */
+ int ch_satapmp_nports;
};
/*
@@ -431,6 +431,9 @@ void ata_channel_attach(struct ata_channel *);
int atabusprint(void *aux, const char *);
int ataprint(void *aux, const char *);
+int atabus_alloc_drives(struct ata_channel *, int);
+void atabus_free_drives(struct ata_channel *);
+
struct ataparams;
int ata_get_params(struct ata_drive_datas *, u_int8_t, struct ataparams *);
int ata_set_mode(struct ata_drive_datas *, u_int8_t, u_int8_t);
diff --git a/sys/dev/ata/files.ata b/sys/dev/ata/files.ata
index 195b65c8be1..7183c5bfdc4 100644
--- a/sys/dev/ata/files.ata
+++ b/sys/dev/ata/files.ata
@@ -1,4 +1,4 @@
-# $NetBSD: files.ata,v 1.23 2012/07/26 20:49:47 jakllsch Exp $
+# $NetBSD: files.ata,v 1.24 2012/07/31 15:50:34 bouyer Exp $
#
# Config file and device description for machine-independent devices
# which attach to ATA busses. Included by ports that need it. Ports
@@ -34,3 +34,6 @@ file dev/ata/sata_subr.c sata needs-flag
# Common SATA FIS subroutines
file dev/ata/satafis_subr.c sata_fis
+
+# SATA port multiplier support
+file dev/ata/satapmp_subr.c sata_pmp needs-flag
diff --git a/sys/dev/ata/sata_subr.c b/sys/dev/ata/sata_subr.c
index c1053ef2fb2..6945f3d864f 100644
--- a/sys/dev/ata/sata_subr.c
+++ b/sys/dev/ata/sata_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sata_subr.c,v 1.19 2012/07/26 20:49:47 jakllsch Exp $ */
+/* $NetBSD: sata_subr.c,v 1.20 2012/07/31 15:50:34 bouyer Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
* Common functions for Serial ATA.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.19 2012/07/26 20:49:47 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.20 2012/07/31 15:50:34 bouyer Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.19 2012/07/26 20:49:47 jakllsch Exp
#include <dev/ata/satareg.h>
#include <dev/ata/satavar.h>
+#include <dev/ata/satapmpreg.h>
/*
* sata_speed:
@@ -146,3 +147,53 @@ sata_reset_interface(struct ata_channel *chp, bus_space_tag_t sata_t,
}
return(sstatus & SStatus_DET_mask);
}
+
+void
+sata_interpret_sig(struct ata_channel *chp, int port, uint32_t sig)
+{
+ int err;
+ int s;
+
+ /* some ATAPI devices have bogus lower two bytes, sigh */
+ if ((sig & 0xffff0000) == 0xeb140000) {
+ sig &= 0xffff0000;
+ sig |= 0x00000101;
+ }
+ if (chp->ch_drive == NULL) {
+ if (sig == 0x96690101)
+ err = atabus_alloc_drives(chp, PMP_MAX_DRIVES);
+ else
+ err = atabus_alloc_drives(chp, 1);
+ if (err)
+ return;
+ }
+ KASSERT(port < chp->ch_ndrives);
+
+ s = splbio();
+ switch(sig) {
+ case 0x96690101:
+ KASSERT(port == 0 || port == PMP_PORT_CTL);
+ chp->ch_drive[PMP_PORT_CTL].drive_type = ATA_DRIVET_PM;
+ break;
+ case 0xc33c0101:
+ aprint_verbose_dev(chp->atabus, "port %d is SEMB, ignored\n",
+ port);
+ break;
+ case 0xeb140101:
+ chp->ch_drive[port].drive_type = ATA_DRIVET_ATAPI;
+ break;
+ case 0x00000101:
+ chp->ch_drive[port].drive_type = ATA_DRIVET_ATA;
+ break;
+ case 0xffffffff:
+ /* COMRESET time out */
+ break;
+ default:
+ chp->ch_drive[port].drive_type = ATA_DRIVET_ATA;
+ aprint_verbose_dev(chp->atabus,
+ "Unrecognized signature 0x%08x on port %d. "
+ "Assuming it's a disk.\n", sig, port);
+ break;
+ }
+ splx(s);
+}
diff --git a/sys/dev/ata/satapmpreg.h b/sys/dev/ata/satapmpreg.h
index 8bb9b85bd98..a5fdc4beec0 100644
--- a/sys/dev/ata/satapmpreg.h
+++ b/sys/dev/ata/satapmpreg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: satapmpreg.h,v 1.5 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: satapmpreg.h,v 1.6 2012/07/31 15:50:34 bouyer Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#define PMP_GSCR_ID 0x00 /* product and vendor id */
-#define PMP_ID_DEV(x) ((x) << 16)
+#define PMP_ID_DEV(x) ((x) >> 16)
#define PMP_ID_VEND(x) ((x) & 0xffff)
#define PMP_GSCR_REV 0x01 /* revision */
#define PMP_REV_SPEC_10 0x02
@@ -79,4 +79,7 @@
#define PMPC_READ_PORT 0xe4
#define PMPC_WRITE_PORT 0xe8
+/* max number of drives (last one being the PM itself */
+#define PMP_MAX_DRIVES 16
+
#endif /* _DEV_ATA_SATAPMPREG_H_ */
diff --git a/sys/dev/ata/satavar.h b/sys/dev/ata/satavar.h
index 4764801f9bd..5e0d20e5699 100644
--- a/sys/dev/ata/satavar.h
+++ b/sys/dev/ata/satavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: satavar.h,v 1.7 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: satavar.h,v 1.8 2012/07/31 15:50:34 bouyer Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -42,5 +42,6 @@
const char *sata_speed(uint32_t);
uint32_t sata_reset_interface(struct ata_channel *, bus_space_tag_t,
bus_space_handle_t, bus_space_handle_t);
+void sata_interpret_sig(struct ata_channel *, int, uint32_t);
#endif /* _DEV_ATA_SATAVAR_H_ */
diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c
index df7ee54988e..1e381bebe7b 100644
--- a/sys/dev/ata/wd.c
+++ b/sys/dev/ata/wd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.399 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: wd.c,v 1.400 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.399 2012/07/26 20:49:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.400 2012/07/31 15:50:34 bouyer Exp $");
#include "opt_ata.h"
@@ -283,7 +283,8 @@ wdattach(device_t parent, device_t self, void *aux)
wd->drvp = adev->adev_drv_data;
wd->drvp->drv_done = wddone;
- wd->drvp->drv_softc = wd->sc_dev;
+ wd->drvp->drv_softc = wd->sc_dev; /* done in atabusconfig_thread()
+ but too late */
aprint_naive("\n");
aprint_normal("\n");
@@ -291,7 +292,7 @@ wdattach(device_t parent, device_t self, void *aux)
/* read our drive info */
if (wd_get_params(wd, AT_WAIT, &wd->sc_params) != 0) {
aprint_error_dev(self, "IDENTIFY failed\n");
- return;
+ goto out;
}
for (blank = 0, p = wd->sc_params.atap_model, q = tbuf, i = 0;
@@ -380,6 +381,7 @@ wdattach(device_t parent, device_t self, void *aux)
ATADEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
device_xname(self), wd->sc_params.atap_dmatiming_mimi,
wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
+out:
/*
* Initialize and attach the disk structure.
*/
@@ -461,7 +463,8 @@ wddetach(device_t self, int flags)
callout_destroy(&sc->sc_restart_ch);
- sc->drvp->drive_flags = 0; /* no drive any more here */
+ sc->drvp->drive_type = ATA_DRIVET_NONE; /* no drive any more here */
+ sc->drvp->drive_flags = 0;
return (0);
}
@@ -772,7 +775,7 @@ wddone(void *v)
errmsg = "error";
do_perror = 1;
retry: /* Just reset and retry. Can we do more ? */
- (*wd->atabus->ata_reset_drive)(wd->drvp, AT_RST_NOCMD);
+ (*wd->atabus->ata_reset_drive)(wd->drvp, AT_RST_NOCMD, NULL);
retry2:
diskerr(bp, "wd", errmsg, LOG_PRINTF,
wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label);
@@ -896,6 +899,9 @@ wdopen(dev_t dev, int flag, int fmt, struct lwp *l)
if (! device_is_active(wd->sc_dev))
return (ENODEV);
+ if (wd->sc_capacity == 0)
+ return (ENODEV);
+
part = WDPART(dev);
mutex_enter(&wd->sc_dk.dk_openlock);
@@ -928,11 +934,15 @@ wdopen(dev_t dev, int flag, int fmt, struct lwp *l)
}
} else {
if ((wd->sc_flags & WDF_LOADED) == 0) {
- wd->sc_flags |= WDF_LOADED;
/* Load the physical device parameters. */
- wd_get_params(wd, AT_WAIT, &wd->sc_params);
-
+ if (wd_get_params(wd, AT_WAIT, &wd->sc_params) != 0) {
+ aprint_error_dev(wd->sc_dev,
+ "IDENTIFY failed\n");
+ error = EIO;
+ goto bad2;
+ }
+ wd->sc_flags |= WDF_LOADED;
/* Load the partition info if not already loaded. */
wdgetdisklabel(wd);
}
@@ -1077,7 +1087,7 @@ wdgetdisklabel(struct wd_softc *wd)
if (wd->drvp->state > RESET) {
s = splbio();
- wd->drvp->drive_flags |= DRIVE_RESET;
+ wd->drvp->drive_flags |= ATA_DRIVE_RESET;
splx(s);
}
errstring = readdisklabel(MAKEWDDEV(0, device_unit(wd->sc_dev),
@@ -1092,7 +1102,7 @@ wdgetdisklabel(struct wd_softc *wd)
*/
if (wd->drvp->state > RESET) {
s = splbio();
- wd->drvp->drive_flags |= DRIVE_RESET;
+ wd->drvp->drive_flags |= ATA_DRIVE_RESET;
splx(s);
}
errstring = readdisklabel(MAKEWDDEV(0, device_unit(wd->sc_dev),
@@ -1105,7 +1115,7 @@ wdgetdisklabel(struct wd_softc *wd)
if (wd->drvp->state > RESET) {
s = splbio();
- wd->drvp->drive_flags |= DRIVE_RESET;
+ wd->drvp->drive_flags |= ATA_DRIVE_RESET;
splx(s);
}
#ifdef HAS_BAD144_HANDLING
@@ -1293,7 +1303,7 @@ wdioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
if (error == 0) {
if (wd->drvp->state > RESET) {
s = splbio();
- wd->drvp->drive_flags |= DRIVE_RESET;
+ wd->drvp->drive_flags |= ATA_DRIVE_RESET;
splx(s);
}
if (xfer == DIOCWDINFO
@@ -1607,7 +1617,7 @@ wddump(dev_t dev, daddr_t blkno, void *va, size_t size)
if (wddumprecalibrated == 0) {
wddumprecalibrated = 1;
(*wd->atabus->ata_reset_drive)(wd->drvp,
- AT_POLL | AT_RST_EMERG);
+ AT_POLL | AT_RST_EMERG, NULL);
wd->drvp->state = RESET;
}
@@ -1762,6 +1772,8 @@ wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params)
case CMD_AGAIN:
return 1;
case CMD_ERR:
+ if (wd->drvp->drive_type != ATA_DRIVET_OLD)
+ return 1;
/*
* We `know' there's a drive here; just assume it's old.
* This geometry is only used to read the MBR and print a