summaryrefslogtreecommitdiff
path: root/sys/dev
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
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')
-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
-rw-r--r--sys/dev/ic/ahcisata_core.c309
-rw-r--r--sys/dev/ic/ahcisatavar.h3
-rw-r--r--sys/dev/ic/mvsata.c86
-rw-r--r--sys/dev/ic/ninjaata32.c14
-rw-r--r--sys/dev/ic/siisata.c164
-rw-r--r--sys/dev/ic/wdc.c152
-rw-r--r--sys/dev/ic/wdc_upc.c6
-rw-r--r--sys/dev/ic/wdcvar.h10
-rw-r--r--sys/dev/isa/wdc_isa.c6
-rw-r--r--sys/dev/isapnp/wdc_isapnp.c6
-rw-r--r--sys/dev/mca/ed_mca.c8
-rw-r--r--sys/dev/ofisa/wdc_ofisa.c6
-rw-r--r--sys/dev/pci/acardide.c19
-rw-r--r--sys/dev/pci/aceride.c17
-rw-r--r--sys/dev/pci/artsata.c6
-rw-r--r--sys/dev/pci/cmdide.c24
-rw-r--r--sys/dev/pci/cypide.c10
-rw-r--r--sys/dev/pci/geodeide.c13
-rw-r--r--sys/dev/pci/hptide.c15
-rw-r--r--sys/dev/pci/iteide.c15
-rw-r--r--sys/dev/pci/ixpide.c13
-rw-r--r--sys/dev/pci/jmide.c13
-rw-r--r--sys/dev/pci/nside.c9
-rw-r--r--sys/dev/pci/optiide.c11
-rw-r--r--sys/dev/pci/pciide_common.c35
-rw-r--r--sys/dev/pci/pciidevar.h4
-rw-r--r--sys/dev/pci/pdcide.c63
-rw-r--r--sys/dev/pci/pdcsata.c14
-rw-r--r--sys/dev/pci/piixide.c36
-rw-r--r--sys/dev/pci/rccide.c15
-rw-r--r--sys/dev/pci/rdcide.c13
-rw-r--r--sys/dev/pci/satalink.c29
-rw-r--r--sys/dev/pci/schide.c15
-rw-r--r--sys/dev/pci/siside.c24
-rw-r--r--sys/dev/pci/slide.c15
-rw-r--r--sys/dev/pci/stpcide.c13
-rw-r--r--sys/dev/pci/svwsata.c5
-rw-r--r--sys/dev/pci/toshide.c13
-rw-r--r--sys/dev/pci/viaide.c26
-rw-r--r--sys/dev/pcmcia/wdc_pcmcia.c10
-rw-r--r--sys/dev/podulebus/dtide.c6
-rw-r--r--sys/dev/podulebus/hcide.c6
-rw-r--r--sys/dev/scsipi/atapi_wdc.c28
-rw-r--r--sys/dev/usb/umass_isdata.c11
52 files changed, 1088 insertions, 692 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
diff --git a/sys/dev/ic/ahcisata_core.c b/sys/dev/ic/ahcisata_core.c
index 8387f6b8d0a..9f0713d2cbc 100644
--- a/sys/dev/ic/ahcisata_core.c
+++ b/sys/dev/ic/ahcisata_core.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.39 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.40 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.39 2012/07/26 20:49:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.40 2012/07/31 15:50:34 bouyer Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -42,21 +42,25 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.39 2012/07/26 20:49:48 jakllsch
#include <dev/ata/satareg.h>
#include <dev/ata/satafisvar.h>
#include <dev/ata/satafisreg.h>
+#include <dev/ata/satapmpreg.h>
#include <dev/ic/ahcisatavar.h>
+#include <dev/ic/wdcreg.h>
#include <dev/scsipi/scsi_all.h> /* for SCSI status */
#include "atapibus.h"
+#define AHCI_DEBUG
#ifdef AHCI_DEBUG
-int ahcidebug_mask = 0x0;
+int ahcidebug_mask = 0;
#endif
static void ahci_probe_drive(struct ata_channel *);
static void ahci_setup_channel(struct ata_channel *);
static int ahci_ata_bio(struct ata_drive_datas *, struct ata_bio *);
-static void ahci_reset_drive(struct ata_drive_datas *, int);
+static int ahci_do_reset_drive(struct ata_channel *, int, int, uint32_t *);
+static void ahci_reset_drive(struct ata_drive_datas *, int, uint32_t *);
static void ahci_reset_channel(struct ata_channel *, int);
static int ahci_exec_command(struct ata_drive_datas *, struct ata_command *);
static int ahci_ata_addref(struct ata_drive_datas *);
@@ -71,7 +75,8 @@ static void ahci_bio_start(struct ata_channel *, struct ata_xfer *);
static int ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int);
static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int);
-static void ahci_channel_start(struct ahci_softc *, struct ata_channel *);
+static void ahci_channel_start(struct ahci_softc *, struct ata_channel *,
+ int, int);
static void ahci_timeout(void *);
static int ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);
@@ -206,7 +211,7 @@ ahci_enable_intrs(struct ahci_softc *sc)
void
ahci_attach(struct ahci_softc *sc)
{
- uint32_t ahci_cap, ahci_rev, ahci_ports;
+ uint32_t ahci_rev, ahci_ports;
int i, j, port;
struct ahci_channel *achp;
struct ata_channel *chp;
@@ -219,9 +224,9 @@ ahci_attach(struct ahci_softc *sc)
if (ahci_reset(sc) != 0)
return;
- ahci_cap = AHCI_READ(sc, AHCI_CAP);
- sc->sc_atac.atac_nchannels = (ahci_cap & AHCI_CAP_NPMASK) + 1;
- sc->sc_ncmds = ((ahci_cap & AHCI_CAP_NCS) >> 8) + 1;
+ sc->sc_ahci_cap = AHCI_READ(sc, AHCI_CAP);
+ sc->sc_atac.atac_nchannels = (sc->sc_ahci_cap & AHCI_CAP_NPMASK) + 1;
+ sc->sc_ncmds = ((sc->sc_ahci_cap & AHCI_CAP_NCS) >> 8) + 1;
ahci_rev = AHCI_READ(sc, AHCI_VS);
snprintb(buf, sizeof(buf), "\177\020"
/* "f\000\005NP\0" */
@@ -248,7 +253,7 @@ ahci_attach(struct ahci_softc *sc)
"b\035SSNTF\0"
"b\036SNCQ\0"
"b\037S64A\0"
- "\0", ahci_cap);
+ "\0", sc->sc_ahci_cap);
aprint_normal_dev(sc->sc_atac.atac_dev, "AHCI revision %u.%u"
", %d ports, %d slots, CAP %s\n",
AHCI_VS_MJR(ahci_rev), AHCI_VS_MNR(ahci_rev),
@@ -394,7 +399,6 @@ ahci_attach(struct ahci_softc *sc)
}
}
ahci_setup_port(sc, i);
- chp->ch_ndrive = 1;
if (bus_space_subregion(sc->sc_ahcit, sc->sc_ahcih,
AHCI_P_SSTS(i), 4, &achp->ahcic_sstatus) != 0) {
aprint_error("%s: couldn't map channel %d "
@@ -542,11 +546,16 @@ ahci_intr_port(struct ahci_softc *sc, struct ahci_channel *achp)
chp->ch_error = WDCE_CRC;
chp->ch_status = WDCS_ERR;
}
+ if (is & AHCI_P_IX_IFS) {
+ aprint_error("%s port %d: SERR 0x%x\n",
+ AHCINAME(sc), chp->ch_channel,
+ AHCI_READ(sc, AHCI_P_SERR(chp->ch_channel)));
+ }
xfer->c_intr(chp, xfer, is);
/* if channel has not been restarted, do it now */
if ((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CR)
== 0)
- ahci_channel_start(sc, chp);
+ ahci_channel_start(sc, chp, 0, 0);
} else {
slot = 0; /* XXX */
is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel));
@@ -563,13 +572,166 @@ ahci_intr_port(struct ahci_softc *sc, struct ahci_channel *achp)
}
static void
-ahci_reset_drive(struct ata_drive_datas *drvp, int flags)
+ahci_reset_drive(struct ata_drive_datas *drvp, int flags, uint32_t *sigp)
{
struct ata_channel *chp = drvp->chnl_softc;
- ata_reset_channel(chp, flags);
+ struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
+ AHCI_WRITE(sc, AHCI_GHC,
+ AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE);
+ ahci_channel_stop(sc, chp, flags);
+ if (ahci_do_reset_drive(chp, drvp->drive, flags, sigp) != 0)
+ ata_reset_channel(chp, flags);
+ AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
return;
}
+/* return error code from ata_bio */
+static int
+ahci_exec_fis(struct ata_channel *chp, int timeout, int flags)
+{
+ struct ahci_channel *achp = (struct ahci_channel *)chp;
+ struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
+ int i;
+ uint32_t is;
+
+ timeout = timeout * 10; /* wait is 10ms */
+ AHCI_CMDH_SYNC(sc, achp, 0, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ /* start command */
+ AHCI_WRITE(sc, AHCI_P_CI(chp->ch_channel), 1 << 0);
+ for (i = 0; i < timeout; i++) {
+ if ((AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)) & 1 << 0) == 0)
+ return 0;
+ is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel));
+ if (is & (AHCI_P_IX_TFES | AHCI_P_IX_HBFS | AHCI_P_IX_IFS |
+ AHCI_P_IX_OFS | AHCI_P_IX_UFS)) {
+ if ((is & (AHCI_P_IX_DHRS|AHCI_P_IX_TFES)) ==
+ (AHCI_P_IX_DHRS|AHCI_P_IX_TFES)) {
+ /*
+ * we got the D2H FIS anyway,
+ * assume sig is valid.
+ * channel is restarted later
+ */
+ return ERROR;
+ }
+ aprint_debug("%s channel %d: error 0x%x sending FIS\n",
+ AHCINAME(sc), chp->ch_channel, is);
+ return ERR_DF;
+ }
+ if (flags & AT_WAIT)
+ tsleep(&sc, PRIBIO, "ahcifis", mstohz(10));
+ else
+ delay(10000);
+ }
+ aprint_debug("%s channel %d: timeout sending FIS\n",
+ AHCINAME(sc), chp->ch_channel);
+ return TIMEOUT;
+}
+
+static int
+ahci_do_reset_drive(struct ata_channel *chp, int drive, int flags,
+ uint32_t *sigp)
+{
+ struct ahci_channel *achp = (struct ahci_channel *)chp;
+ struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
+ struct ahci_cmd_tbl *cmd_tbl;
+ struct ahci_cmd_header *cmd_h;
+ int i;
+ uint32_t sig;
+
+ KASSERT((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CR) == 0);
+ /* clear port interrupt register */
+ AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
+ /* clear SErrors and start operations */
+ if ((sc->sc_ahci_cap & AHCI_CAP_CLO) == AHCI_CAP_CLO) {
+ /*
+ * issue a command list override to clear BSY.
+ * This is needed if there's a PMP with no drive
+ * on port 0
+ */
+ ahci_channel_start(sc, chp, flags, 1);
+ } else {
+ ahci_channel_start(sc, chp, flags, 0);
+ }
+ if (drive > 0) {
+ KASSERT(sc->sc_ahci_cap & AHCI_CAP_SPM);
+ }
+ /* polled command, assume interrupts are disabled */
+ /* use slot 0 to send reset, the channel is idle */
+ cmd_h = &achp->ahcic_cmdh[0];
+ cmd_tbl = achp->ahcic_cmd_tbl[0];
+ cmd_h->cmdh_flags = htole16(AHCI_CMDH_F_RST | AHCI_CMDH_F_CBSY |
+ RHD_FISLEN / 4 | (drive << AHCI_CMDH_F_PMP_SHIFT));
+ cmd_h->cmdh_prdbc = 0;
+ memset(cmd_tbl->cmdt_cfis, 0, 64);
+ cmd_tbl->cmdt_cfis[fis_type] = RHD_FISTYPE;
+ cmd_tbl->cmdt_cfis[rhd_c] = drive;
+ cmd_tbl->cmdt_cfis[rhd_control] = WDCTL_RST;
+ switch(ahci_exec_fis(chp, 1, flags)) {
+ case ERR_DF:
+ case TIMEOUT:
+ aprint_error("%s channel %d: setting WDCTL_RST failed "
+ "for drive %d\n", AHCINAME(sc), chp->ch_channel, drive);
+ if (sigp)
+ *sigp = 0xffffffff;
+ goto end;
+ default:
+ break;
+ }
+ cmd_h->cmdh_flags = htole16(RHD_FISLEN / 4 |
+ (drive << AHCI_CMDH_F_PMP_SHIFT));
+ cmd_h->cmdh_prdbc = 0;
+ memset(cmd_tbl->cmdt_cfis, 0, 64);
+ cmd_tbl->cmdt_cfis[fis_type] = RHD_FISTYPE;
+ cmd_tbl->cmdt_cfis[rhd_c] = drive;
+ cmd_tbl->cmdt_cfis[rhd_control] = 0;
+ switch(ahci_exec_fis(chp, 31, flags)) {
+ case ERR_DF:
+ case TIMEOUT:
+ aprint_error("%s channel %d: clearing WDCTL_RST failed "
+ "for drive %d\n", AHCINAME(sc), chp->ch_channel, drive);
+ if (sigp)
+ *sigp = 0xffffffff;
+ goto end;
+ default:
+ break;
+ }
+ /*
+ * wait 31s for BSY to clear
+ * This should not be needed, but some controllers clear the
+ * command slot before receiving the D2H FIS ...
+ */
+ for (i = 0; i <AHCI_RST_WAIT; i++) {
+ sig = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
+ if ((((sig & AHCI_P_TFD_ST) >> AHCI_P_TFD_ST_SHIFT)
+ & WDCS_BSY) == 0)
+ break;
+ tsleep(&sc, PRIBIO, "ahcid2h", mstohz(10));
+ }
+ if (i == AHCI_RST_WAIT) {
+ aprint_error("%s: BSY never cleared, TD 0x%x\n",
+ AHCINAME(sc), sig);
+ if (sigp)
+ *sigp = 0xffffffff;
+ goto end;
+ }
+ AHCIDEBUG_PRINT(("%s: BSY took %d ms\n", AHCINAME(sc), i * 10),
+ DEBUG_PROBE);
+ sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel));
+ if (sigp)
+ *sigp = sig;
+ AHCIDEBUG_PRINT(("%s: port %d: sig=0x%x CMD=0x%x\n",
+ AHCINAME(sc), chp->ch_channel, sig,
+ AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel))), DEBUG_PROBE);
+end:
+ ahci_channel_stop(sc, chp, flags);
+ tsleep(&sc, PRIBIO, "ahcirst", mstohz(500));
+ /* clear port interrupt register */
+ AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
+ ahci_channel_start(sc, chp, AT_WAIT,
+ (sc->sc_ahci_cap & AHCI_CAP_CLO) ? 1 : 0);
+ return 0;
+}
+
static void
ahci_reset_channel(struct ata_channel *chp, int flags)
{
@@ -591,7 +753,7 @@ ahci_reset_channel(struct ata_channel *chp, int flags)
/* clear port interrupt register */
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
/* clear SErrors and start operations */
- ahci_channel_start(sc, chp);
+ ahci_channel_start(sc, chp, flags, 1);
/* wait 31s for BSY to clear */
for (i = 0; i <AHCI_RST_WAIT; i++) {
tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
@@ -634,15 +796,8 @@ ahci_probe_drive(struct ata_channel *chp)
{
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
struct ahci_channel *achp = (struct ahci_channel *)chp;
- int i, s;
uint32_t sig;
- /* XXX This should be done by other code. */
- for (i = 0; i < chp->ch_ndrive; i++) {
- chp->ch_drive[i].chnl_softc = chp;
- chp->ch_drive[i].drive = i;
- }
-
/* bring interface up, accept FISs, power up and spin up device */
AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel),
AHCI_P_CMD_ICC_AC | AHCI_P_CMD_FRE |
@@ -652,39 +807,19 @@ ahci_probe_drive(struct ata_channel *chp)
achp->ahcic_sstatus)) {
case SStatus_DET_DEV:
tsleep(&sc, PRIBIO, "ahcidv", mstohz(500));
- /* clear port interrupt register */
- AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
- /* clear SErrors and start operations */
- ahci_channel_start(sc, chp);
- /* wait 31s for BSY to clear */
- for (i = 0; i <AHCI_RST_WAIT; i++) {
- sig = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
- if ((((sig & AHCI_P_TFD_ST) >> AHCI_P_TFD_ST_SHIFT)
- & WDCS_BSY) == 0)
- break;
- tsleep(&sc, PRIBIO, "ahcid2h", mstohz(10));
+ if (sc->sc_ahci_cap & AHCI_CAP_SPM) {
+ ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, &sig);
+ } else {
+ ahci_do_reset_drive(chp, 0, AT_WAIT, &sig);
}
- if (i == AHCI_RST_WAIT) {
- aprint_error("%s: BSY never cleared, TD 0x%x\n",
- AHCINAME(sc), sig);
- return;
+ sata_interpret_sig(chp, 0, sig);
+ /* if we have a PMP attached, inform the controller */
+ if (chp->ch_ndrives > PMP_PORT_CTL &&
+ chp->ch_drive[PMP_PORT_CTL].drive_type == ATA_DRIVET_PM) {
+ AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel),
+ AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) |
+ AHCI_P_CMD_PMA);
}
- AHCIDEBUG_PRINT(("%s: BSY took %d ms\n", AHCINAME(sc), i * 10),
- DEBUG_PROBE);
- sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel));
- AHCIDEBUG_PRINT(("%s: port %d: sig=0x%x CMD=0x%x\n",
- AHCINAME(sc), chp->ch_channel, sig,
- AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel))), DEBUG_PROBE);
- /*
- * scnt and sn are supposed to be 0x1 for ATAPI, but in some
- * cases we get wrong values here, so ignore it.
- */
- s = splbio();
- if ((sig & 0xffff0000) == 0xeb140000) {
- chp->ch_drive[0].drive_flags |= DRIVE_ATAPI;
- } else
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
- splx(s);
/* clear port interrupt register */
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
/* and enable interrupts */
@@ -778,6 +913,7 @@ ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
cmd_tbl), DEBUG_XFERS);
satafis_rhd_construct_cmd(ata_c, cmd_tbl->cmdt_cfis);
+ cmd_tbl->cmdt_cfis[rhd_c] |= xfer->c_drive;
cmd_h = &achp->ahcic_cmdh[slot];
AHCIDEBUG_PRINT(("%s port %d header %p\n", AHCINAME(sc),
@@ -793,7 +929,7 @@ ahci_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
}
cmd_h->cmdh_flags = htole16(
((ata_c->flags & AT_WRITE) ? AHCI_CMDH_F_WR : 0) |
- RHD_FISLEN / 4);
+ RHD_FISLEN / 4 | (xfer->c_drive << AHCI_CMDH_F_PMP_SHIFT));
cmd_h->cmdh_prdbc = 0;
AHCI_CMDH_SYNC(sc, achp, slot,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -883,9 +1019,9 @@ ahci_cmd_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)
chp->ch_queue->active_xfer = NULL;
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
ahci_cmd_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
return 0;
}
@@ -999,6 +1135,7 @@ ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
cmd_tbl), DEBUG_XFERS);
satafis_rhd_construct_bio(xfer, cmd_tbl->cmdt_cfis);
+ cmd_tbl->cmdt_cfis[rhd_c] |= xfer->c_drive;
cmd_h = &achp->ahcic_cmdh[slot];
AHCIDEBUG_PRINT(("%s port %d header %p\n", AHCINAME(sc),
@@ -1012,7 +1149,7 @@ ahci_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
}
cmd_h->cmdh_flags = htole16(
((ata_bio->flags & ATA_READ) ? 0 : AHCI_CMDH_F_WR) |
- RHD_FISLEN / 4);
+ RHD_FISLEN / 4 | (xfer->c_drive << AHCI_CMDH_F_PMP_SHIFT));
cmd_h->cmdh_prdbc = 0;
AHCI_CMDH_SYNC(sc, achp, slot,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1117,9 +1254,9 @@ ahci_bio_complete(struct ata_channel *chp, struct ata_xfer *xfer, int is)
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, achp->ahcic_datad[slot]);
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
ahci_bio_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
return 0;
}
@@ -1164,7 +1301,7 @@ ahci_channel_stop(struct ahci_softc *sc, struct ata_channel *chp, int flags)
== 0)
break;
if (flags & AT_WAIT)
- tsleep(&sc, PRIBIO, "ahcirst", mstohz(10));
+ tsleep(&sc, PRIBIO, "ahcistop", mstohz(10));
else
delay(10000);
}
@@ -1176,16 +1313,44 @@ ahci_channel_stop(struct ahci_softc *sc, struct ata_channel *chp, int flags)
}
static void
-ahci_channel_start(struct ahci_softc *sc, struct ata_channel *chp)
+ahci_channel_start(struct ahci_softc *sc, struct ata_channel *chp,
+ int flags, int clo)
{
+ int i;
+ uint32_t p_cmd;
/* clear error */
AHCI_WRITE(sc, AHCI_P_SERR(chp->ch_channel),
AHCI_READ(sc, AHCI_P_SERR(chp->ch_channel)));
+ if (clo) {
+ /* issue command list override */
+ KASSERT(sc->sc_ahci_cap & AHCI_CAP_CLO);
+ AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel),
+ AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) | AHCI_P_CMD_CLO);
+ /* wait 1s for AHCI_CAP_CLO to clear */
+ for (i = 0; i <100; i++) {
+ if ((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) &
+ AHCI_P_CMD_CLO) == 0)
+ break;
+ if (flags & AT_WAIT)
+ tsleep(&sc, PRIBIO, "ahciclo", mstohz(10));
+ else
+ delay(10000);
+ }
+ if (AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CLO) {
+ printf("%s: channel wouldn't CLO\n", AHCINAME(sc));
+ /* XXX controller reset ? */
+ return;
+ }
+ }
/* and start controller */
- AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel),
- AHCI_P_CMD_ICC_AC | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
- AHCI_P_CMD_FRE | AHCI_P_CMD_ST);
+ p_cmd = AHCI_P_CMD_ICC_AC | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
+ AHCI_P_CMD_FRE | AHCI_P_CMD_ST;
+ if (chp->ch_ndrives > PMP_PORT_CTL &&
+ chp->ch_drive[PMP_PORT_CTL].drive_type == ATA_DRIVET_PM) {
+ p_cmd |= AHCI_P_CMD_PMA;
+ }
+ AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel), p_cmd);
}
static void
@@ -1378,6 +1543,7 @@ ahci_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
cmd_tbl), DEBUG_XFERS);
satafis_rhd_construct_atapi(xfer, cmd_tbl->cmdt_cfis);
+ cmd_tbl->cmdt_cfis[rhd_c] |= xfer->c_drive;
memset(&cmd_tbl->cmdt_acmd, 0, sizeof(cmd_tbl->cmdt_acmd));
memcpy(cmd_tbl->cmdt_acmd, sc_xfer->cmd, sc_xfer->cmdlen);
@@ -1394,7 +1560,8 @@ ahci_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
}
cmd_h->cmdh_flags = htole16(
((sc_xfer->xs_control & XS_CTL_DATA_OUT) ? AHCI_CMDH_F_WR : 0) |
- RHD_FISLEN / 4 | AHCI_CMDH_F_A);
+ RHD_FISLEN / 4 | AHCI_CMDH_F_A |
+ (xfer->c_drive << AHCI_CMDH_F_PMP_SHIFT));
cmd_h->cmdh_prdbc = 0;
AHCI_CMDH_SYNC(sc, achp, slot,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1468,9 +1635,9 @@ ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, achp->ahcic_datad[slot]);
- if (chp->ch_drive[drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
ahci_atapi_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
return 0;
}
@@ -1545,7 +1712,7 @@ ahci_atapi_probe_device(struct atapibus_softc *sc, int target)
return;
/* if no ATAPI device detected at attach time, skip */
- if ((drvp->drive_flags & DRIVE_ATAPI) == 0) {
+ if (drvp->drive_type != ATA_DRIVET_ATAPI) {
AHCIDEBUG_PRINT(("ahci_atapi_probe_device: drive %d "
"not present\n", target), DEBUG_PROBE);
return;
@@ -1584,7 +1751,7 @@ ahci_atapi_probe_device(struct atapibus_softc *sc, int target)
periph->periph_flags |= PERIPH_REMOVABLE;
if (periph->periph_type == T_SEQUENTIAL) {
s = splbio();
- drvp->drive_flags |= DRIVE_ATAPIST;
+ drvp->drive_flags |= ATA_DRIVE_ATAPIDSCW;
splx(s);
}
@@ -1615,7 +1782,7 @@ ahci_atapi_probe_device(struct atapibus_softc *sc, int target)
ata_probe_caps(drvp);
else {
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
} else {
@@ -1624,7 +1791,7 @@ ahci_atapi_probe_device(struct atapibus_softc *sc, int target)
AHCINAME(ahcic), chp->ch_channel, target,
chp->ch_error), DEBUG_PROBE);
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
}
diff --git a/sys/dev/ic/ahcisatavar.h b/sys/dev/ic/ahcisatavar.h
index c70ada8f1ec..d07b428533d 100644
--- a/sys/dev/ic/ahcisatavar.h
+++ b/sys/dev/ic/ahcisatavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisatavar.h,v 1.9 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: ahcisatavar.h,v 1.10 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -55,6 +55,7 @@ struct ahci_softc {
int sc_cmd_hdr_nseg;
int sc_atac_capflags;
+ int32_t sc_ahci_cap; /* copy of AHCI_CAP */
int sc_ncmds; /* number of command slots */
struct ata_channel *sc_chanarray[AHCI_MAX_PORTS];
struct ahci_channel {
diff --git a/sys/dev/ic/mvsata.c b/sys/dev/ic/mvsata.c
index a3f0fce1e1b..86dc85c1446 100644
--- a/sys/dev/ic/mvsata.c
+++ b/sys/dev/ic/mvsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsata.c,v 1.23 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: mvsata.c,v 1.24 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
@@ -26,11 +26,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.23 2012/07/26 20:49:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.24 2012/07/31 15:50:34 bouyer Exp $");
#include "opt_mvsata.h"
-/* ATAPI implementation not finished. Also don't work shadow registers? */
+/* ATAPI implementation not finished. */
//#include "atapibus.h"
#include <sys/param.h>
@@ -76,13 +76,17 @@ __KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.23 2012/07/26 20:49:48 jakllsch Exp $")
#define MVSATA_EDMA_WRITE_4(mvport, reg, val) \
bus_space_write_4((mvport)->port_iot, (mvport)->port_ioh, (reg), (val))
#define MVSATA_WDC_READ_2(mvport, reg) \
- bus_space_read_2((mvport)->port_iot, (mvport)->port_ioh, (reg))
+ bus_space_read_2((mvport)->port_iot, (mvport)->port_ioh, \
+ SHADOW_REG_BLOCK_OFFSET + (reg))
#define MVSATA_WDC_READ_1(mvport, reg) \
- bus_space_read_1((mvport)->port_iot, (mvport)->port_ioh, (reg))
+ bus_space_read_1((mvport)->port_iot, (mvport)->port_ioh, \
+ SHADOW_REG_BLOCK_OFFSET + (reg))
#define MVSATA_WDC_WRITE_2(mvport, reg, val) \
- bus_space_write_2((mvport)->port_iot, (mvport)->port_ioh, (reg), (val))
+ bus_space_write_2((mvport)->port_iot, (mvport)->port_ioh, \
+ SHADOW_REG_BLOCK_OFFSET + (reg), (val))
#define MVSATA_WDC_WRITE_1(mvport, reg, val) \
- bus_space_write_1((mvport)->port_iot, (mvport)->port_ioh, (reg), (val))
+ bus_space_write_1((mvport)->port_iot, (mvport)->port_ioh, \
+ SHADOW_REG_BLOCK_OFFSET + (reg), (val))
#ifdef MVSATA_DEBUG
#define DPRINTF(x) if (mvsata_debug) printf x
@@ -103,7 +107,7 @@ int mvsata_debug = 2;
#ifndef MVSATA_WITHOUTDMA
static int mvsata_bio(struct ata_drive_datas *, struct ata_bio *);
-static void mvsata_reset_drive(struct ata_drive_datas *, int);
+static void mvsata_reset_drive(struct ata_drive_datas *, int, uint32_t *);
static void mvsata_reset_channel(struct ata_channel *, int);
static int mvsata_exec_command(struct ata_drive_datas *, struct ata_command *);
static int mvsata_addref(struct ata_drive_datas *);
@@ -304,6 +308,7 @@ mvsata_attach(struct mvsata_softc *sc, struct mvsata_product *product,
sc->sc_wdcdev.sc_atac.atac_atapibus_attach = mvsata_atapibus_attach;
#endif
#endif
+ sc->sc_wdcdev.wdc_maxdrives = 1; /* SATA is always 1 drive */
sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
sc->sc_wdcdev.sc_atac.atac_set_modes = mvsata_setup_channel;
@@ -504,7 +509,7 @@ mvsata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
ata_bio->flags |= ATA_POLL;
if (ata_bio->flags & ATA_POLL)
xfer->c_flags |= C_POLL;
- 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;
xfer->c_drive = drvp->drive;
@@ -519,12 +524,14 @@ mvsata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
}
static void
-mvsata_reset_drive(struct ata_drive_datas *drvp, int flags)
+mvsata_reset_drive(struct ata_drive_datas *drvp, int flags, uint32_t *sigp)
{
struct ata_channel *chp = drvp->chnl_softc;
struct mvsata_port *mvport = (struct mvsata_port *)chp;
uint32_t edma_c;
+ KASSERT(sigp == NULL);
+
edma_c = MVSATA_EDMA_READ_4(mvport, EDMA_CMD);
DPRINTF(("%s:%d: mvsata_reset_drive: drive=%d (EDMA %sactive)\n",
@@ -789,7 +796,7 @@ mvsata_atapi_probe_device(struct atapibus_softc *sc, int target)
return;
/* if no ATAPI device detected at attach time, skip */
- if ((drvp->drive_flags & DRIVE_ATAPI) == 0) {
+ if (drvp->drive_type != ATA_DRIVET_ATAPI) {
DPRINTF(("%s:%d: mvsata_atapi_probe_device:"
" drive %d not present\n",
device_xname(atac->atac_dev), chp->ch_channel, target));
@@ -830,7 +837,7 @@ mvsata_atapi_probe_device(struct atapibus_softc *sc, int target)
periph->periph_flags |= PERIPH_REMOVABLE;
if (periph->periph_type == T_SEQUENTIAL) {
s = splbio();
- drvp->drive_flags |= DRIVE_ATAPIST;
+ drvp->drive_flags |= ATA_DRIVE_ATAPIDSCW;
splx(s);
}
@@ -860,7 +867,7 @@ mvsata_atapi_probe_device(struct atapibus_softc *sc, int target)
ata_probe_caps(drvp);
else {
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
} else {
@@ -869,7 +876,7 @@ mvsata_atapi_probe_device(struct atapibus_softc *sc, int target)
device_xname(atac->atac_dev), chp->ch_channel, target,
chp->ch_error));
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
}
@@ -918,22 +925,22 @@ mvsata_setup_channel(struct ata_channel *chp)
device_xname(MVSATA_DEV2(mvport)), chp->ch_channel));
edma_mode = nodma;
- for (drive = 0; drive < chp->ch_ndrive; drive++) {
+ for (drive = 0; drive < chp->ch_ndrives; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if (!(drvp->drive_flags & DRIVE))
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
}
- if (drvp->drive_flags & (DRIVE_UDMA | DRIVE_DMA))
- if (drvp->drive_flags & DRIVE_ATA)
+ if (drvp->drive_flags & (ATA_DRIVE_UDMA | ATA_DRIVE_DMA))
+ if (drvp->drive_type == ATA_DRIVET_ATA)
edma_mode = dma;
}
@@ -978,14 +985,14 @@ no_edma:
aprint_error_dev(MVSATA_DEV2(mvport),
"channel %d: can't use EDMA\n", chp->ch_channel);
s = splbio();
- for (drive = 0; drive < chp->ch_ndrive; drive++) {
+ for (drive = 0; drive < chp->ch_ndrives; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if (!(drvp->drive_flags & DRIVE))
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA);
}
splx(s);
goto no_edma;
@@ -1397,9 +1404,9 @@ mvsata_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;
@@ -1440,7 +1447,7 @@ mvsata_bio_ready(struct mvsata_port *mvport, struct ata_bio *ata_bio, int drive,
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);
@@ -1449,10 +1456,10 @@ mvsata_bio_ready(struct mvsata_port *mvport, struct ata_bio *ata_bio, int drive,
goto ctrltimeout;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto ctrlerror;
- 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 if (drvp->drive_flags & DRIVE_DMA)
+ else if (drvp->drive_flags & ATA_DRIVE_DMA)
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
0x20 | drvp->DMA_mode, WDSF_SET_MODE);
else
@@ -1590,7 +1597,7 @@ mvsata_wdc_cmd_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
* Historically it's what we have always done so keeping it
* here ensure binary backward compatibility.
*/
- drive_flags = DRIVE_NOSTREAM |
+ drive_flags = ATA_DRIVE_NOSTREAM |
chp->ch_drive[xfer->c_drive].drive_flags;
else
/*
@@ -1736,7 +1743,7 @@ mvsata_wdc_cmd_done(struct ata_channel *chp, struct ata_xfer *xfer)
}
ata_c->r_count |=
MVSATA_WDC_READ_1(mvport, SRB_SC) << 8;
- ata_c->r_lba =
+ ata_c->r_lba |=
(uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAL) << 24;
ata_c->r_lba |=
(uint64_t)MVSATA_WDC_READ_1(mvport, SRB_LBAM) << 32;
@@ -1761,9 +1768,9 @@ mvsata_wdc_cmd_done(struct ata_channel *chp, struct ata_xfer *xfer)
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT);
delay(10); /* some drives need a little delay here */
}
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
mvsata_wdc_cmd_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
} else
mvsata_wdc_cmd_done_end(chp, xfer);
@@ -1833,7 +1840,7 @@ mvsata_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
if (atac->atac_set_modes == NULL)
goto ready;
/* 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 ready;
errstring = "unbusy";
if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags))
@@ -1860,11 +1867,11 @@ mvsata_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
} else
goto error;
}
- 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
- 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
@@ -1874,7 +1881,7 @@ mvsata_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
goto timeout;
if (chp->ch_status & WDCS_ERR) {
if (chp->ch_error == WDCE_ABRT) {
- if (drvp->drive_flags & DRIVE_UDMA)
+ if (drvp->drive_flags & ATA_DRIVE_UDMA)
goto error;
else {
/*
@@ -2248,7 +2255,7 @@ mvsata_atapi_phase_complete(struct ata_xfer *xfer)
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
/* wait for DSC if needed */
- if (drvp->drive_flags & DRIVE_ATAPIST) {
+ if (drvp->drive_flags & ATA_DRIVE_ATAPIDSCW) {
DPRINTFN(1,
("%s:%d:%d: mvsata_atapi_phase_complete: polldsc %d\n",
device_xname(atac->atac_dev), chp->ch_channel,
@@ -2333,9 +2340,9 @@ mvsata_atapi_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) {
sc_xfer->error = XS_DRIVER_STUFFUP;
- chp->ch_drive[drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
}
@@ -2823,7 +2830,6 @@ mvsata_port_init(struct mvsata_hc *mvhc, int port)
chp = &mvport->port_ata_channel;
chp->ch_channel = channel;
chp->ch_atac = &sc->sc_wdcdev.sc_atac;
- chp->ch_ndrive = 1; /* SATA is always 1 drive */
chp->ch_queue = &mvport->port_ata_queue;
sc->sc_ata_channels[channel] = chp;
diff --git a/sys/dev/ic/ninjaata32.c b/sys/dev/ic/ninjaata32.c
index edbcec9bbc4..e044c8ad246 100644
--- a/sys/dev/ic/ninjaata32.c
+++ b/sys/dev/ic/ninjaata32.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ninjaata32.c,v 1.17 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: ninjaata32.c,v 1.18 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 2006 ITOH Yasufumi.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ninjaata32.c,v 1.17 2012/07/26 20:49:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ninjaata32.c,v 1.18 2012/07/31 15:50:34 bouyer Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -192,7 +192,7 @@ njata32_attach(struct njata32_softc *sc)
sc->sc_ch[0].ch_ata_channel.ch_channel = 0;
sc->sc_ch[0].ch_ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
sc->sc_ch[0].ch_ata_channel.ch_queue = &sc->sc_wdc_chqueue;
- sc->sc_ch[0].ch_ata_channel.ch_ndrive = 2; /* max number of drives */
+ sc->sc_wdcdev.wdc_maxdrives = 2; /* max number of drives per channel */
/* map ATA registers */
for (i = 0; i < WDC_NREG; i++) {
@@ -317,20 +317,20 @@ njata32_setup_channel(struct ata_channel *chp)
int drive;
uint8_t mode;
- KASSERT(chp->ch_ndrive != 0);
+ KASSERT(chp->ch_ndrives != 0);
sc->sc_timing_pio = 0;
#if 0 /* ATA DMA is currently unused */
sc->sc_timing_dma = 0;
#endif
- for (drive = 0; drive < chp->ch_ndrive; drive++) {
+ for (drive = 0; drive < chp->ch_ndrives; drive++) {
drvp = &chp->ch_drive[drive];
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue; /* no drive */
#if 0 /* ATA DMA is currently unused */
- if ((drvp->drive_flags & DRIVE_DMA) != 0) {
+ if ((drvp->drive_flags & ATA_DRIVE_DMA) != 0) {
/*
* Multiword DMA
*/
diff --git a/sys/dev/ic/siisata.c b/sys/dev/ic/siisata.c
index 7d7f467def9..c7737200fe9 100644
--- a/sys/dev/ic/siisata.c
+++ b/sys/dev/ic/siisata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.21 2012/07/26 20:49:48 jakllsch Exp $ */
+/* $NetBSD: siisata.c,v 1.22 2012/07/31 15:50:34 bouyer Exp $ */
/* from ahcisata_core.c */
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.21 2012/07/26 20:49:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.22 2012/07/31 15:50:34 bouyer Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -96,6 +96,7 @@ __KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.21 2012/07/26 20:49:48 jakllsch Exp $"
#include <dev/ata/satareg.h>
#include <dev/ata/satafisvar.h>
#include <dev/ata/satafisreg.h>
+#include <dev/ata/satapmpreg.h>
#include <dev/ic/siisatavar.h>
#include <dev/ic/siisatareg.h>
@@ -116,7 +117,7 @@ void siisata_probe_drive(struct ata_channel *);
void siisata_setup_channel(struct ata_channel *);
int siisata_ata_bio(struct ata_drive_datas *, struct ata_bio *);
-void siisata_reset_drive(struct ata_drive_datas *, int);
+void siisata_reset_drive(struct ata_drive_datas *, int, uint32_t *);
void siisata_reset_channel(struct ata_channel *, int);
int siisata_ata_addref(struct ata_drive_datas *);
void siisata_ata_delref(struct ata_drive_datas *);
@@ -345,7 +346,6 @@ siisata_attach_port(struct siisata_softc *sc, int port)
}
}
- chp->ch_ndrive = 1;
if (bus_space_subregion(sc->sc_prt, sc->sc_prh,
PRX(chp->ch_channel, PRO_SSTATUS), 4, &schp->sch_sstatus) != 0) {
aprint_error_dev(sc->sc_atac.atac_dev,
@@ -462,23 +462,29 @@ siisata_intr_port(struct siisata_channel *schp)
xfer = chp->ch_queue->active_xfer;
slot = SIISATA_NON_NCQ_SLOT;
- SIISATA_DEBUG_PRINT(("%s: %s port %d\n",
- SIISATANAME(sc), __func__, chp->ch_channel), DEBUG_INTR);
-
pis = PRREAD(sc, PRX(chp->ch_channel, PRO_PIS));
+ SIISATA_DEBUG_PRINT(("%s: %s port %d, pis 0x%x ",
+ SIISATANAME(sc), __func__, chp->ch_channel, pis), DEBUG_INTR);
+
if (pis & PR_PIS_CMDCMPL) {
/* get slot status, clearing completion interrupt */
pss = PRREAD(sc, PRX(chp->ch_channel, PRO_PSS));
+ SIISATA_DEBUG_PRINT(("pss 0x%x\n", pss), DEBUG_INTR);
/* is this expected? */
/* XXX improve */
if ((schp->sch_active_slots & __BIT(slot)) == 0) {
- PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
- log(LOG_WARNING, "%s: unexpected command "
+ aprint_error( "%s: unexpected command "
"completion on port %d\n",
SIISATANAME(sc), chp->ch_channel);
return;
}
+ if ((~pss & __BIT(slot)) == 0) {
+ aprint_error( "%s: unknown slot "
+ "completion on port %d, pss 0x%x\n",
+ SIISATANAME(sc), chp->ch_channel, pss);
+ return;
+ }
} else if (pis & PR_PIS_CMDERRR) {
uint32_t ec;
@@ -487,8 +493,9 @@ siisata_intr_port(struct siisata_channel *schp)
chp->ch_error = WDCE_CRC;
ec = PRREAD(sc, PRX(chp->ch_channel, PRO_PCE));
+ SIISATA_DEBUG_PRINT(("ec %d\n", ec), DEBUG_INTR);
if (ec <= PR_PCE_DATAFISERROR) {
- if (ec == PR_PCE_DEVICEERROR) {
+ if (ec == PR_PCE_DEVICEERROR && xfer != NULL) {
/* read in specific information about error */
prbfis = bus_space_read_stream_4(
sc->sc_prt, sc->sc_prh,
@@ -498,9 +505,10 @@ siisata_intr_port(struct siisata_channel *schp)
}
siisata_reinit_port(chp);
} else {
- aprint_error_dev(sc->sc_atac.atac_dev,
- "fatal error %d on channel %d, resetting\n",
- ec, chp->ch_channel);
+ aprint_error_dev(sc->sc_atac.atac_dev, "fatal error %d"
+ " on channel %d (ctx 0x%x), resetting\n",
+ ec, chp->ch_channel,
+ PRREAD(sc, PRX(chp->ch_channel, PRO_PCR)));
/* okay, we have a "Fatal Error" */
siisata_device_reset(chp);
}
@@ -515,7 +523,7 @@ siisata_intr_port(struct siisata_channel *schp)
}
void
-siisata_reset_drive(struct ata_drive_datas *drvp, int flags)
+siisata_reset_drive(struct ata_drive_datas *drvp, int flags, uint32_t *sigp)
{
struct ata_channel *chp = drvp->chnl_softc;
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
@@ -532,21 +540,37 @@ siisata_reset_drive(struct ata_drive_datas *drvp, int flags)
memset(prb, 0, sizeof(struct siisata_prb));
prb->prb_control =
htole16(PRB_CF_SOFT_RESET | PRB_CF_INTERRUPT_MASK);
+ KASSERT(drvp->drive <= PMP_PORT_CTL);
+ prb->prb_fis[rhd_c] = drvp->drive;
siisata_activate_prb(schp, slot);
- for(i = 0; i < 31000; i++) {
- if (PRREAD(sc, PRX(chp->ch_channel, PRO_PSS)) &
- PR_PXSS(slot))
- DELAY(1000);
- else
+ for(i = 0; i < 3100; i++) {
+ if ((PRREAD(sc, PRX(chp->ch_channel, PRO_PSS)) &
+ PR_PXSS(slot)) == 0)
break;
+ if (flags & AT_WAIT)
+ tsleep(schp, PRIBIO, "siiprb", mstohz(10));
+ else
+ DELAY(10000);
}
siisata_deactivate_prb(schp, slot);
-
- log(LOG_DEBUG, "%s: port %d: ch_status %x ch_error %x\n",
- __func__, chp->ch_channel, chp->ch_status, chp->ch_error);
+ if (i == 3100) {
+ /* timeout */
+ siisata_device_reset(chp);
+ if (sigp)
+ *sigp = 0xffffffff;
+ } else {
+ /* read the signature out of the FIS */
+ if (sigp) {
+ *sigp = 0;
+ *sigp |= (PRREAD(sc, PRSX(chp->ch_channel, slot,
+ PRSO_FIS+0x4)) & 0x00ffffff) << 8;
+ *sigp |= PRREAD(sc, PRSX(chp->ch_channel, slot,
+ PRSO_FIS+0xc)) & 0xff;
+ }
+ }
#if 1
/* attempt to downgrade signaling in event of CRC error */
@@ -571,7 +595,6 @@ siisata_reset_drive(struct ata_drive_datas *drvp, int flags)
chp->ch_status = 0;
chp->ch_error = 0;
#endif
-
return;
}
@@ -627,7 +650,6 @@ siisata_probe_drive(struct ata_channel *chp)
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
struct siisata_channel *schp = (struct siisata_channel *)chp;
int i;
- int s;
uint32_t sig;
int slot = SIISATA_NON_NCQ_SLOT;
struct siisata_prb *prb;
@@ -636,12 +658,6 @@ siisata_probe_drive(struct ata_channel *chp)
SIISATA_DEBUG_PRINT(("%s: %s: port %d start\n", SIISATANAME(sc),
__func__, chp->ch_channel), DEBUG_FUNCS);
- /* XXX This should be done by other code. */
- for (i = 0; i < chp->ch_ndrive; i++) {
- chp->ch_drive[i].chnl_softc = chp;
- chp->ch_drive[i].drive = i;
- }
-
/*
* disable port interrupt as we're polling for PHY up and
* prb completion
@@ -661,6 +677,7 @@ siisata_probe_drive(struct ata_channel *chp)
prb = schp->sch_prb[slot];
memset(prb, 0, sizeof(struct siisata_prb));
prb->prb_control = htole16(PRB_CF_SOFT_RESET);
+ prb->prb_fis[rhd_c] = PMP_PORT_CTL;
siisata_activate_prb(schp, slot);
@@ -703,28 +720,10 @@ siisata_probe_drive(struct ata_channel *chp)
SIISATA_DEBUG_PRINT(("%s: %s: sig=0x%08x\n", SIISATANAME(sc),
__func__, sig), DEBUG_PROBE);
- /* some ATAPI devices have bogus lower two bytes, sigh */
- if ((sig & 0xffff0000) == 0xeb140000) {
- sig &= 0xffff0000;
- sig |= 0x00000101;
- }
-
- s = splbio();
- switch (sig) {
- case 0xeb140101:
- chp->ch_drive[0].drive_flags |= DRIVE_ATAPI;
- break;
- case 0x00000101:
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
- break;
- default:
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
- aprint_verbose_dev(sc->sc_atac.atac_dev,
- "Unrecognized signature 0x%08x on port %d. "
- "Assuming it's a disk.\n", sig, chp->ch_channel);
- break;
- }
- splx(s);
+ if (sig == 0x96690101)
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PCS),
+ PR_PC_PMP_ENABLE);
+ sata_interpret_sig(chp, 0, sig);
break;
default:
break;
@@ -808,8 +807,11 @@ siisata_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
struct siisata_prb *prb;
int i;
- SIISATA_DEBUG_PRINT(("%s: %s port %d, slot %d\n",
- SIISATANAME(sc), __func__, chp->ch_channel, slot), DEBUG_FUNCS);
+ SIISATA_DEBUG_PRINT(("%s: %s port %d drive %d command 0x%x, slot %d\n",
+ SIISATANAME((struct siisata_softc *)chp->ch_atac),
+ __func__, chp->ch_channel, xfer->c_drive,
+ ata_c->r_command, slot),
+ DEBUG_FUNCS|DEBUG_XFERS);
chp->ch_status = 0;
chp->ch_error = 0;
@@ -818,6 +820,8 @@ siisata_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
memset(prb, 0, sizeof(struct siisata_prb));
satafis_rhd_construct_cmd(ata_c, prb->prb_fis);
+ KASSERT(xfer->c_drive <= PMP_PORT_CTL);
+ prb->prb_fis[rhd_c] |= xfer->c_drive;
memset(prb->prb_atapi, 0, sizeof(prb->prb_atapi));
@@ -857,15 +861,14 @@ siisata_cmd_start(struct ata_channel *chp, struct ata_xfer *xfer)
}
if ((ata_c->flags & AT_DONE) == 0) {
- ata_c->flags |= AT_TIMEOU;
- siisata_cmd_complete(chp, xfer, slot);
+ siisata_timeout(chp);
}
/* reenable interrupts */
siisata_enable_port_interrupt(chp);
out:
SIISATA_DEBUG_PRINT(
- ("%s: %s: done\n", SIISATANAME(sc), __func__), DEBUG_FUNCS);
+ ("%s: %s: done\n", SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), DEBUG_FUNCS);
return;
}
@@ -899,7 +902,7 @@ siisata_cmd_complete(struct ata_channel *chp, struct ata_xfer *xfer, int slot)
#endif
SIISATA_DEBUG_PRINT(
- ("%s: %s\n", SIISATANAME(sc), __func__), DEBUG_FUNCS);
+ ("%s: %s\n", SIISATANAME(sc), __func__), DEBUG_FUNCS|DEBUG_XFERS);
chp->ch_flags &= ~ATACH_IRQ_WAIT;
if (xfer->c_flags & C_TIMEOU)
@@ -914,9 +917,9 @@ siisata_cmd_complete(struct ata_channel *chp, struct ata_xfer *xfer, int slot)
ata_c->flags |= AT_ERROR;
}
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
siisata_cmd_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
return 0;
} else
@@ -936,7 +939,8 @@ siisata_cmd_done(struct ata_channel *chp, struct ata_xfer *xfer, int slot)
int i;
SIISATA_DEBUG_PRINT(
- ("%s: %s.\n", SIISATANAME(sc), __func__), DEBUG_FUNCS);
+ ("%s: %s flags 0x%x error 0x%x\n", SIISATANAME(sc), __func__,
+ ata_c->flags, ata_c->r_error), DEBUG_FUNCS|DEBUG_XFERS);
siisata_deactivate_prb(schp, slot);
@@ -1016,7 +1020,7 @@ siisata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
SIISATA_DEBUG_PRINT(
("%s: %s port %d, slot %d\n",
- SIISATANAME(sc), __func__, chp->ch_channel, slot),
+ SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__, chp->ch_channel, slot),
DEBUG_FUNCS);
chp->ch_status = 0;
@@ -1026,6 +1030,8 @@ siisata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
memset(prb, 0, sizeof(struct siisata_prb));
satafis_rhd_construct_bio(xfer, prb->prb_fis);
+ KASSERT(xfer->c_drive <= PMP_PORT_CTL);
+ prb->prb_fis[rhd_c] |= xfer->c_drive;
memset(prb->prb_atapi, 0, sizeof(prb->prb_atapi));
@@ -1065,7 +1071,7 @@ siisata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
siisata_enable_port_interrupt(chp);
out:
SIISATA_DEBUG_PRINT(
- ("%s: %s: done\n", SIISATANAME(sc), __func__), DEBUG_FUNCS);
+ ("%s: %s: done\n", SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), DEBUG_FUNCS);
return;
}
@@ -1124,9 +1130,9 @@ siisata_bio_complete(struct ata_channel *chp, struct ata_xfer *xfer, int slot)
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, schp->sch_datad[slot]);
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
siisata_bio_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
return 0;
}
@@ -1167,6 +1173,7 @@ siisata_timeout(void *v)
int slot = SIISATA_NON_NCQ_SLOT;
int s = splbio();
SIISATA_DEBUG_PRINT(("%s: %p\n", __func__, xfer), DEBUG_INTR);
+ siisata_device_reset(chp);
if ((chp->ch_flags & ATACH_IRQ_WAIT) != 0) {
xfer->c_flags |= C_TIMEOU;
xfer->c_intr(chp, xfer, slot);
@@ -1270,6 +1277,8 @@ siisata_reinit_port(struct ata_channel *chp)
PRWRITE(sc, PRX(chp->ch_channel, PRO_PCS), PR_PC_PORT_INITIALIZE);
while (!(PRREAD(sc, PRX(chp->ch_channel, PRO_PS)) & PR_PS_PORT_READY))
DELAY(10);
+ if (chp->ch_ndrives > 1)
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PCS), PR_PC_PMP_ENABLE);
}
static void
@@ -1386,7 +1395,7 @@ siisata_atapi_probe_device(struct atapibus_softc *sc, int target)
return;
/* if no ATAPI device detected at attach time, skip */
- if ((drvp->drive_flags & DRIVE_ATAPI) == 0) {
+ if (drvp->drive_type == ATA_DRIVET_ATAPI) {
SIISATA_DEBUG_PRINT(("%s: drive %d "
"not present\n", __func__, target), DEBUG_PROBE);
return;
@@ -1424,12 +1433,6 @@ siisata_atapi_probe_device(struct atapibus_softc *sc, int target)
periph->periph_type = ATAPI_CFG_TYPE(id->atap_config);
if (id->atap_config & ATAPI_CFG_REMOV)
periph->periph_flags |= PERIPH_REMOVABLE;
- if (periph->periph_type == T_SEQUENTIAL) {
- s = splbio();
- drvp->drive_flags |= DRIVE_ATAPIST;
- splx(s);
- }
-
sa.sa_periph = periph;
sa.sa_inqbuf.type = ATAPI_CFG_TYPE(id->atap_config);
sa.sa_inqbuf.removable = id->atap_config & ATAPI_CFG_REMOV ?
@@ -1467,7 +1470,7 @@ siisata_atapi_probe_device(struct atapibus_softc *sc, int target)
ata_probe_caps(drvp);
else {
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type &= ATA_DRIVET_NONE;
splx(s);
}
} else {
@@ -1476,7 +1479,7 @@ siisata_atapi_probe_device(struct atapibus_softc *sc, int target)
__func__, SIISATANAME(siic), chp->ch_channel, target,
chp->ch_error), DEBUG_PROBE);
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type &= ATA_DRIVET_NONE;
splx(s);
}
}
@@ -1555,7 +1558,7 @@ siisata_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
int i;
SIISATA_DEBUG_PRINT( ("%s: %s:%d:%d, scsi flags 0x%x\n", __func__,
- SIISATANAME(sc), chp->ch_channel,
+ SIISATANAME((struct siisata_softc *)chp->ch_atac), chp->ch_channel,
chp->ch_drive[xfer->c_drive].drive, sc_xfer->xs_control),
DEBUG_XFERS);
@@ -1573,6 +1576,8 @@ siisata_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
prbp->prb_control |= htole16(PRB_CF_PACKET_WRITE);
satafis_rhd_construct_atapi(xfer, prbp->prb_fis);
+ KASSERT(xfer->c_drive <= PMP_PORT_CTL);
+ prbp->prb_fis[rhd_c] |= xfer->c_drive;
/* copy over ATAPI command */
memcpy(prbp->prb_atapi, sc_xfer->cmd, sc_xfer->cmdlen);
@@ -1611,14 +1616,13 @@ siisata_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
DELAY(1000);
}
if ((sc_xfer->xs_status & XS_STS_DONE) == 0) {
- sc_xfer->error = XS_TIMEOUT;
- siisata_atapi_complete(chp, xfer, slot);
+ siisata_timeout(chp);
}
/* reenable interrupts */
siisata_enable_port_interrupt(chp);
out:
SIISATA_DEBUG_PRINT(
- ("%s: %s: done\n", SIISATANAME(sc), __func__), DEBUG_FUNCS);
+ ("%s: %s: done\n", SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__), DEBUG_FUNCS);
return;
}
@@ -1649,9 +1653,9 @@ siisata_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer,
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, schp->sch_datad[slot]);
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
siisata_atapi_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
return 0; /* XXX verify */
}
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c
index 07b0d0f5fd7..7e4913c2f39 100644
--- a/sys/dev/ic/wdc.c
+++ b/sys/dev/ic/wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.273 2012/07/29 18:20:13 christos Exp $ */
+/* $NetBSD: wdc.c,v 1.274 2012/07/31 15:50:34 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.273 2012/07/29 18:20:13 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.274 2012/07/31 15:50:34 bouyer Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -208,11 +208,7 @@ wdc_sataprobe(struct ata_channel *chp)
uint8_t st = 0, sc, sn, cl, ch;
int i, s;
- /* XXX This should be done by other code. */
- for (i = 0; i < chp->ch_ndrive; i++) {
- chp->ch_drive[i].chnl_softc = chp;
- chp->ch_drive[i].drive = i;
- }
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
/* reset the PHY and bring online */
switch (sata_reset_interface(chp, wdr->sata_iot, wdr->sata_control,
@@ -244,15 +240,17 @@ wdc_sataprobe(struct ata_channel *chp)
"cl=0x%x ch=0x%x\n",
device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
sc, sn, cl, ch), DEBUG_PROBE);
+ if (atabus_alloc_drives(chp, 1) != 0)
+ return;
/*
* sc and sn are supposed to be 0x1 for ATAPI, but in some
* cases we get wrong values here, so ignore it.
*/
s = splbio();
if (cl == 0x14 && ch == 0xeb)
- chp->ch_drive[0].drive_flags |= DRIVE_ATAPI;
+ chp->ch_drive[0].drive_type = ATA_DRIVET_ATAPI;
else
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
+ chp->ch_drive[0].drive_type = ATA_DRIVET_ATA;
splx(s);
/*
@@ -260,7 +258,7 @@ wdc_sataprobe(struct ata_channel *chp)
* is up
*/
if (wdcreset(chp, RESET_SLEEP) != 0)
- chp->ch_drive[0].drive_flags = 0;
+ chp->ch_drive[0].drive_type = ATA_DRIVET_NONE;
break;
default:
@@ -294,8 +292,11 @@ wdc_drvprobe(struct ata_channel *chp)
u_int8_t st0 = 0, st1 = 0;
int i, j, error, s;
+ if (atabus_alloc_drives(chp, wdc->wdc_maxdrives) != 0)
+ return;
if (wdcprobe1(chp, 0) == 0) {
/* No drives, abort the attach here. */
+ atabus_free_drives(chp);
return;
}
@@ -306,7 +307,8 @@ wdc_drvprobe(struct ata_channel *chp)
* select drive 1 first, so that master is selected on
* exit from the loop
*/
- if (chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD)) {
+ if (chp->ch_ndrives > 1 &&
+ chp->ch_drive[1].drive_type == ATA_DRIVET_ATA) {
if (wdc->select)
wdc->select(chp,1);
bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
@@ -315,7 +317,7 @@ wdc_drvprobe(struct ata_channel *chp)
st1 = bus_space_read_1(wdr->cmd_iot,
wdr->cmd_iohs[wd_status], 0);
}
- if (chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD)) {
+ if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATA) {
if (wdc->select)
wdc->select(chp,0);
bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
@@ -326,12 +328,11 @@ wdc_drvprobe(struct ata_channel *chp)
}
- if (((chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD))
- == 0 ||
- (st0 & WDCS_DRDY)) &&
- ((chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD))
- == 0 ||
- (st1 & WDCS_DRDY)))
+ if ((chp->ch_drive[0].drive_type != ATA_DRIVET_ATA ||
+ (st0 & WDCS_DRDY)) &&
+ (chp->ch_ndrives < 2 ||
+ chp->ch_drive[1].drive_type != ATA_DRIVET_ATA ||
+ (st1 & WDCS_DRDY)))
break;
#ifdef WDC_NO_IDS
/* cannot tsleep here (can't enable IPL_BIO interrups),
@@ -342,10 +343,12 @@ wdc_drvprobe(struct ata_channel *chp)
tsleep(&params, PRIBIO, "atadrdy", 1);
#endif
}
- if ((st0 & WDCS_DRDY) == 0)
- chp->ch_drive[0].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD);
- if ((st1 & WDCS_DRDY) == 0)
- chp->ch_drive[1].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD);
+ if ((st0 & WDCS_DRDY) == 0 &&
+ chp->ch_drive[0].drive_type != ATA_DRIVET_ATAPI)
+ chp->ch_drive[0].drive_type = ATA_DRIVET_NONE;
+ if (chp->ch_ndrives > 1 && (st1 & WDCS_DRDY) == 0 &&
+ chp->ch_drive[1].drive_type != ATA_DRIVET_ATAPI)
+ chp->ch_drive[1].drive_type = ATA_DRIVET_NONE;
splx(s);
ATADEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n",
@@ -355,11 +358,7 @@ wdc_drvprobe(struct ata_channel *chp)
/* Wait a bit, some devices are weird just after a reset. */
delay(5000);
- for (i = 0; i < chp->ch_ndrive; i++) {
- /* XXX This should be done by other code. */
- chp->ch_drive[i].chnl_softc = chp;
- chp->ch_drive[i].drive = i;
-
+ for (i = 0; i < chp->ch_ndrives; i++) {
#if NATA_DMA
/*
* Init error counter so that an error withing the first xfers
@@ -372,10 +371,10 @@ wdc_drvprobe(struct ata_channel *chp)
if ((atac->atac_cap &
(ATAC_CAP_DATA16 | ATAC_CAP_DATA32)) == ATAC_CAP_DATA32) {
s = splbio();
- chp->ch_drive[i].drive_flags |= DRIVE_CAP32;
+ chp->ch_drive[i].drive_flags |= ATA_DRIVE_CAP32;
splx(s);
}
- if ((chp->ch_drive[i].drive_flags & DRIVE) == 0)
+ if (chp->ch_drive[i].drive_type == ATA_DRIVET_NONE)
continue;
/* Shortcut in case we've been shutdown */
@@ -400,22 +399,17 @@ wdc_drvprobe(struct ata_channel *chp)
error = ata_get_params(&chp->ch_drive[i],
AT_WAIT | AT_POLL, &params);
}
- if (error == CMD_OK) {
- /* If IDENTIFY succeeded, this is not an OLD ctrl */
- s = splbio();
- for (j = 0; j < chp->ch_ndrive; j++)
- chp->ch_drive[j].drive_flags &= ~DRIVE_OLD;
- splx(s);
- } else {
- s = splbio();
- chp->ch_drive[i].drive_flags &=
- ~(DRIVE_ATA | DRIVE_ATAPI);
- splx(s);
+ if (error != CMD_OK) {
ATADEBUG_PRINT(("%s:%d:%d: IDENTIFY failed (%d)\n",
device_xname(atac->atac_dev),
chp->ch_channel, i, error), DEBUG_PROBE);
- if ((chp->ch_drive[i].drive_flags & DRIVE_OLD) == 0)
+ s = splbio();
+ if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATA ||
+ (wdc->cap & WDC_CAPABILITY_PREATA) == 0) {
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
continue;
+ }
+ splx(s);
/*
* Pre-ATA drive ?
* Test registers writability (Error register not
@@ -439,7 +433,7 @@ wdc_drvprobe(struct ata_channel *chp)
device_xname(atac->atac_dev),
chp->ch_channel, i), DEBUG_PROBE);
s = splbio();
- chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
splx(s);
continue;
}
@@ -448,7 +442,7 @@ wdc_drvprobe(struct ata_channel *chp)
device_xname(atac->atac_dev),
chp->ch_channel, i), DEBUG_PROBE);
s = splbio();
- chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
splx(s);
continue;
}
@@ -460,13 +454,17 @@ wdc_drvprobe(struct ata_channel *chp)
device_xname(atac->atac_dev),
chp->ch_channel, i), DEBUG_PROBE);
s = splbio();
- chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
+ chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
splx(s);
} else {
s = splbio();
- for (j = 0; j < chp->ch_ndrive; j++)
- chp->ch_drive[j].drive_flags &=
- ~(DRIVE_ATA | DRIVE_ATAPI);
+ for (j = 0; j < chp->ch_ndrives; j++) {
+ if (chp->ch_drive[i].drive_type !=
+ ATA_DRIVET_NONE) {
+ chp->ch_drive[j].drive_type =
+ ATA_DRIVET_OLD;
+ }
+ }
splx(s);
}
}
@@ -724,7 +722,7 @@ wdcprobe1(struct ata_channel *chp, int poll)
* be something here assume it's ATA or OLD. Ghost will be killed
* later in attach routine.
*/
- for (drive = 0; drive < chp->ch_ndrive; drive++) {
+ for (drive = 0; drive < wdc->wdc_maxdrives; drive++) {
if ((ret_value & (0x01 << drive)) == 0)
continue;
if (wdc->select)
@@ -750,12 +748,12 @@ wdcprobe1(struct ata_channel *chp, int poll)
* sc & sn are supposed to be 0x1 for ATAPI but in some cases
* we get wrong values here, so ignore it.
*/
- if (cl == 0x14 && ch == 0xeb) {
- chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI;
- } else {
- chp->ch_drive[drive].drive_flags |= DRIVE_ATA;
- if ((wdc->cap & WDC_CAPABILITY_PREATA) != 0)
- chp->ch_drive[drive].drive_flags |= DRIVE_OLD;
+ if (chp->ch_drive != NULL) {
+ if (cl == 0x14 && ch == 0xeb) {
+ chp->ch_drive[drive].drive_type = ATA_DRIVET_ATAPI;
+ } else {
+ chp->ch_drive[drive].drive_type = ATA_DRIVET_ATA;
+ }
}
}
/*
@@ -778,7 +776,7 @@ wdcattach(struct ata_channel *chp)
struct atac_softc *atac = chp->ch_atac;
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
- KASSERT(chp->ch_ndrive > 0 && chp->ch_ndrive < 3);
+ KASSERT(wdc->wdc_maxdrives > 0 && wdc->wdc_maxdrives <= WDC_MAXDRIVES);
/* default data transfer methods */
if (wdc->datain_pio == NULL)
@@ -916,10 +914,12 @@ wdcintr(void *arg)
/* Put all disk in RESET state */
void
-wdc_reset_drive(struct ata_drive_datas *drvp, int flags)
+wdc_reset_drive(struct ata_drive_datas *drvp, int flags, uint32_t *sigp)
{
struct ata_channel *chp = drvp->chnl_softc;
+ KASSERT(sigp == NULL);
+
ATADEBUG_PRINT(("wdc_reset_drive %s:%d for drive %d\n",
device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
drvp->drive), DEBUG_FUNCS);
@@ -1037,8 +1037,10 @@ wdcreset(struct ata_channel *chp, int poll)
#endif
wdc->reset(chp, poll);
- drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE) ? 0x01:0x00;
- drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE) ? 0x02:0x00;
+ drv_mask1 = (chp->ch_drive[0].drive_type != ATA_DRIVET_NONE) ? 0x01:0x00;
+ if (chp->ch_ndrives > 1)
+ drv_mask1 |=
+ (chp->ch_drive[1].drive_type != ATA_DRIVET_NONE) ? 0x02:0x00;
drv_mask2 = __wdcwait_reset(chp, drv_mask1,
(poll == RESET_SLEEP) ? 0 : 1);
if (drv_mask2 != drv_mask1) {
@@ -1504,7 +1506,7 @@ __wdccommand_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
* Historically it's what we have always done so keeping it
* here ensure binary backward compatibility.
*/
- drive_flags = DRIVE_NOSTREAM |
+ drive_flags = ATA_DRIVE_NOSTREAM |
chp->ch_drive[xfer->c_drive].drive_flags;
} else {
/*
@@ -1668,9 +1670,9 @@ __wdccommand_done(struct ata_channel *chp, struct ata_xfer *xfer)
WDCTL_4BIT);
delay(10); /* some drives need a little delay here */
}
- if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
+ if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) {
__wdccommand_kill_xfer(chp, xfer, KILL_GONE);
- chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
} else
__wdccommand_done_end(chp, xfer);
@@ -1874,12 +1876,12 @@ wdc_datain_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
#ifndef __NO_STRICT_ALIGNMENT
if ((uintptr_t)bf & 1)
goto unaligned;
- if ((flags & DRIVE_CAP32) && ((uintptr_t)bf & 3))
+ if ((flags & ATA_DRIVE_CAP32) && ((uintptr_t)bf & 3))
goto unaligned;
#endif
- if (flags & DRIVE_NOSTREAM) {
- if ((flags & DRIVE_CAP32) && len > 3) {
+ if (flags & ATA_DRIVE_NOSTREAM) {
+ if ((flags & ATA_DRIVE_CAP32) && len > 3) {
bus_space_read_multi_4(wdr->data32iot,
wdr->data32ioh, 0, bf, len >> 2);
bf = (char *)bf + (len & ~3);
@@ -1892,7 +1894,7 @@ wdc_datain_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
len &= 1;
}
} else {
- if ((flags & DRIVE_CAP32) && len > 3) {
+ if ((flags & ATA_DRIVE_CAP32) && len > 3) {
bus_space_read_multi_stream_4(wdr->data32iot,
wdr->data32ioh, 0, bf, len >> 2);
bf = (char *)bf + (len & ~3);
@@ -1912,8 +1914,8 @@ wdc_datain_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
#ifndef __NO_STRICT_ALIGNMENT
unaligned:
- if (flags & DRIVE_NOSTREAM) {
- if (flags & DRIVE_CAP32) {
+ if (flags & ATA_DRIVE_NOSTREAM) {
+ if (flags & ATA_DRIVE_CAP32) {
while (len > 3) {
uint32_t val;
@@ -1934,7 +1936,7 @@ unaligned:
len -= 2;
}
} else {
- if (flags & DRIVE_CAP32) {
+ if (flags & ATA_DRIVE_CAP32) {
while (len > 3) {
uint32_t val;
@@ -1966,12 +1968,12 @@ wdc_dataout_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
#ifndef __NO_STRICT_ALIGNMENT
if ((uintptr_t)bf & 1)
goto unaligned;
- if ((flags & DRIVE_CAP32) && ((uintptr_t)bf & 3))
+ if ((flags & ATA_DRIVE_CAP32) && ((uintptr_t)bf & 3))
goto unaligned;
#endif
- if (flags & DRIVE_NOSTREAM) {
- if (flags & DRIVE_CAP32) {
+ if (flags & ATA_DRIVE_NOSTREAM) {
+ if (flags & ATA_DRIVE_CAP32) {
bus_space_write_multi_4(wdr->data32iot,
wdr->data32ioh, 0, bf, len >> 2);
bf = (char *)bf + (len & ~3);
@@ -1982,7 +1984,7 @@ wdc_dataout_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
}
} else {
- if (flags & DRIVE_CAP32) {
+ if (flags & ATA_DRIVE_CAP32) {
bus_space_write_multi_stream_4(wdr->data32iot,
wdr->data32ioh, 0, bf, len >> 2);
bf = (char *)bf + (len & ~3);
@@ -1997,8 +1999,8 @@ wdc_dataout_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
#ifndef __NO_STRICT_ALIGNMENT
unaligned:
- if (flags & DRIVE_NOSTREAM) {
- if (flags & DRIVE_CAP32) {
+ if (flags & ATA_DRIVE_NOSTREAM) {
+ if (flags & ATA_DRIVE_CAP32) {
while (len > 3) {
uint32_t val;
@@ -2019,7 +2021,7 @@ unaligned:
len -= 2;
}
} else {
- if (flags & DRIVE_CAP32) {
+ if (flags & ATA_DRIVE_CAP32) {
while (len > 3) {
uint32_t val;
diff --git a/sys/dev/ic/wdc_upc.c b/sys/dev/ic/wdc_upc.c
index 92daca8231c..5dd00ca97fa 100644
--- a/sys/dev/ic/wdc_upc.c
+++ b/sys/dev/ic/wdc_upc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_upc.c,v 1.28 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: wdc_upc.c,v 1.29 2012/07/31 15:50:35 bouyer Exp $ */
/*-
* Copyright (c) 2000 Ben Harris
* All rights reserved.
@@ -28,7 +28,7 @@
/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_upc.c,v 1.28 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_upc.c,v 1.29 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -89,7 +89,7 @@ wdc_upc_attach(device_t parent, device_t self, void *aux)
sc->sc_channel.ch_channel = 0;
sc->sc_channel.ch_atac = &sc->sc_wdc.sc_atac;
sc->sc_channel.ch_queue = &sc->sc_chqueue;
- sc->sc_channel.ch_ndrive = 2;
+ sc->sc_wdc.wdc_maxdrives = 2;
for (i = 0; i < WDC_NREG; i++) {
if (bus_space_subregion(ua->ua_iot, ua->ua_ioh, i,
i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) {
diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h
index 14e78c6cb46..f65409ac8f4 100644
--- a/sys/dev/ic/wdcvar.h
+++ b/sys/dev/ic/wdcvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: wdcvar.h,v 1.94 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: wdcvar.h,v 1.95 2012/07/31 15:50:35 bouyer Exp $ */
/*-
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -43,6 +43,8 @@
#define WDC_NREG 8 /* number of command registers */
#define WDC_NSHADOWREG 2 /* number of command "shadow" registers */
+#define WDC_MAXDRIVES 2 /* absolute max number of drives per channel */
+
struct wdc_regs {
/* Our registers */
bus_space_tag_t cmd_iot;
@@ -74,7 +76,9 @@ struct wdc_softc {
struct wdc_regs *regs; /* register array (per-channel) */
- int cap; /* controller capabilities */
+ int wdc_maxdrives; /* max number of drives per channel */
+
+ int cap; /* controller capabilities */
#define WDC_CAPABILITY_NO_EXTRA_RESETS 0x0100 /* only reset once */
#define WDC_CAPABILITY_PREATA 0x0200 /* ctrl can be a pre-ata one */
#define WDC_CAPABILITY_WIDEREGS 0x0400 /* Ctrl has wide (16bit) registers */
@@ -164,7 +168,7 @@ void wdccommandext(struct ata_channel *, u_int8_t, u_int8_t, u_int64_t,
u_int16_t, u_int16_t);
void wdccommandshort(struct ata_channel *, int, int);
void wdctimeout(void *arg);
-void wdc_reset_drive(struct ata_drive_datas *, int);
+void wdc_reset_drive(struct ata_drive_datas *, int, uint32_t *);
void wdc_reset_channel(struct ata_channel *, int);
void wdc_do_reset(struct ata_channel *, int);
diff --git a/sys/dev/isa/wdc_isa.c b/sys/dev/isa/wdc_isa.c
index ce5df302f06..14b2698c39f 100644
--- a/sys/dev/isa/wdc_isa.c
+++ b/sys/dev/isa/wdc_isa.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_isa.c,v 1.58 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: wdc_isa.c,v 1.59 2012/07/31 15:50:35 bouyer Exp $ */
/*-
* Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_isa.c,v 1.58 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_isa.c,v 1.59 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -224,10 +224,10 @@ wdc_isa_attach(device_t parent, device_t self, void *aux)
sc->wdc_chanlist[0] = &sc->ata_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanlist;
sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
sc->ata_channel.ch_channel = 0;
sc->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
sc->ata_channel.ch_queue = &sc->wdc_chqueue;
- sc->ata_channel.ch_ndrive = 2;
wdc_init_shadow_regs(&sc->ata_channel);
aprint_normal("\n");
diff --git a/sys/dev/isapnp/wdc_isapnp.c b/sys/dev/isapnp/wdc_isapnp.c
index b8998ca8060..cfcc394220b 100644
--- a/sys/dev/isapnp/wdc_isapnp.c
+++ b/sys/dev/isapnp/wdc_isapnp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_isapnp.c,v 1.41 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: wdc_isapnp.c,v 1.42 2012/07/31 15:50:35 bouyer Exp $ */
/*-
* Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_isapnp.c,v 1.41 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_isapnp.c,v 1.42 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -156,10 +156,10 @@ wdc_isapnp_attach(device_t parent, device_t self, void *aux)
sc->wdc_chanlist[0] = &sc->ata_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanlist;
sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
sc->ata_channel.ch_channel = 0;
sc->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
sc->ata_channel.ch_queue = &sc->wdc_chqueue;
- sc->ata_channel.ch_ndrive = 2;
wdc_init_shadow_regs(&sc->ata_channel);
diff --git a/sys/dev/mca/ed_mca.c b/sys/dev/mca/ed_mca.c
index ecbfdb4dd96..25f017c5f69 100644
--- a/sys/dev/mca/ed_mca.c
+++ b/sys/dev/mca/ed_mca.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ed_mca.c,v 1.51 2012/07/24 14:04:30 jakllsch Exp $ */
+/* $NetBSD: ed_mca.c,v 1.52 2012/07/31 15:50:35 bouyer Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ed_mca.c,v 1.51 2012/07/24 14:04:30 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ed_mca.c,v 1.52 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -440,7 +440,7 @@ edgetdisklabel(dev_t dev, struct ed_softc *ed)
*/
#if 0
if (wd->drvp->state > RECAL)
- wd->drvp->drive_flags |= DRIVE_RESET;
+ wd->drvp->drive_flags |= ATA_DRIVE_RESET;
#endif
errstring = readdisklabel(EDLABELDEV(dev),
edmcastrategy, lp, ed->sc_dk.dk_cpulabel);
@@ -492,7 +492,7 @@ edmcaioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
if (error == 0) {
#if 0
if (wd->drvp->state > RECAL)
- wd->drvp->drive_flags |= DRIVE_RESET;
+ wd->drvp->drive_flags |= ATA_DRIVE_RESET;
#endif
if (xfer == DIOCWDINFO)
error = writedisklabel(EDLABELDEV(dev),
diff --git a/sys/dev/ofisa/wdc_ofisa.c b/sys/dev/ofisa/wdc_ofisa.c
index 11908495fc9..09b89c1ba27 100644
--- a/sys/dev/ofisa/wdc_ofisa.c
+++ b/sys/dev/ofisa/wdc_ofisa.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_ofisa.c,v 1.32 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: wdc_ofisa.c,v 1.33 2012/07/31 15:50:35 bouyer Exp $ */
/*
* Copyright 1997, 1998
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_ofisa.c,v 1.32 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_ofisa.c,v 1.33 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -158,10 +158,10 @@ wdc_ofisa_attach(device_t parent, device_t self, void *aux)
sc->sc_chanlist[0] = &sc->sc_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->sc_chanlist;
sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
sc->sc_channel.ch_channel = 0;
sc->sc_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
sc->sc_channel.ch_queue = &sc->sc_chqueue;
- sc->sc_channel.ch_ndrive = 2;
wdc_init_shadow_regs(&sc->sc_channel);
diff --git a/sys/dev/pci/acardide.c b/sys/dev/pci/acardide.c
index 94abe88284c..65f75db2e92 100644
--- a/sys/dev/pci/acardide.c
+++ b/sys/dev/pci/acardide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: acardide.c,v 1.29 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: acardide.c,v 1.30 2012/07/31 15:50:35 bouyer Exp $ */
/*-
* Copyright (c) 2001 Izumi Tsutsui. All rights reserved.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acardide.c,v 1.29 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acardide.c,v 1.30 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -159,6 +159,7 @@ acard_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = acard_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 2;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -202,8 +203,8 @@ acard_setup_channel(struct ata_channel *chp)
udma_mode &= ~ATP860_UDMA_MASK(channel);
/* check 80 pins cable */
- if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA) ||
- (chp->ch_drive[1].drive_flags & DRIVE_UDMA)) {
+ if ((chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) ||
+ (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA)) {
if (pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
& ATP860_CTRL_80P(chp->ch_channel)) {
if (chp->ch_drive[0].UDMA_mode > 2)
@@ -220,11 +221,11 @@ acard_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if ((atac->atac_cap & ATAC_CAP_UDMA) &&
- (drvp->drive_flags & DRIVE_UDMA)) {
+ (drvp->drive_flags & ATA_DRIVE_UDMA)) {
/* use Ultra/DMA */
if (ACARD_IS_850(sc)) {
idetime |= ATP850_SETTIME(drive,
@@ -241,10 +242,10 @@ acard_setup_channel(struct ata_channel *chp)
}
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
} else if ((atac->atac_cap & ATAC_CAP_DMA) &&
- (drvp->drive_flags & DRIVE_DMA)) {
+ (drvp->drive_flags & ATA_DRIVE_DMA)) {
/* use Multiword DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
splx(s);
if (ACARD_IS_850(sc)) {
idetime |= ATP850_SETTIME(drive,
@@ -259,7 +260,7 @@ acard_setup_channel(struct ata_channel *chp)
} else {
/* PIO only */
s = splbio();
- drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA);
splx(s);
if (ACARD_IS_850(sc)) {
idetime |= ATP850_SETTIME(drive,
diff --git a/sys/dev/pci/aceride.c b/sys/dev/pci/aceride.c
index bc0f1f66a99..425a7392239 100644
--- a/sys/dev/pci/aceride.c
+++ b/sys/dev/pci/aceride.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aceride.c,v 1.34 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: aceride.c,v 1.35 2012/07/31 15:50:35 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: aceride.c,v 1.34 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: aceride.c,v 1.35 2012/07/31 15:50:35 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -152,6 +152,7 @@ acer_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = acer_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CDRC,
(pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CDRC) |
@@ -268,7 +269,7 @@ acer_setup_channel(struct ata_channel *chp)
pciide_channel_dma_setup(cp);
if ((chp->ch_drive[0].drive_flags | chp->ch_drive[1].drive_flags) &
- DRIVE_UDMA) { /* check 80 pins cable */
+ ATA_DRIVE_UDMA) { /* check 80 pins cable */
if (pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4A) &
ACER_0x4A_80PIN(chp->ch_channel)) {
if (chp->ch_drive[0].UDMA_mode > 2)
@@ -281,7 +282,7 @@ acer_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
ATADEBUG_PRINT(("acer_setup_channel: old timings reg for "
"channel %d drive %d 0x%x\n", chp->ch_channel, drive,
@@ -293,18 +294,18 @@ acer_setup_channel(struct ata_channel *chp)
ACER_UDMA_TIM(chp->ch_channel, drive, 0x7));
/* add timing values, setup DMA if needed */
- if ((drvp->drive_flags & DRIVE_DMA) == 0 &&
- (drvp->drive_flags & DRIVE_UDMA) == 0) {
+ if ((drvp->drive_flags & ATA_DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & ATA_DRIVE_UDMA) == 0) {
acer_fifo_udma |=
ACER_FTH_OPL(chp->ch_channel, drive, 0x1);
goto pio;
}
acer_fifo_udma |= ACER_FTH_OPL(chp->ch_channel, drive, 0x2);
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
acer_fifo_udma |= ACER_UDMA_EN(chp->ch_channel, drive);
acer_fifo_udma |=
diff --git a/sys/dev/pci/artsata.c b/sys/dev/pci/artsata.c
index d2399beac96..2fcbd6ab1a5 100644
--- a/sys/dev/pci/artsata.c
+++ b/sys/dev/pci/artsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: artsata.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: artsata.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: artsata.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: artsata.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $");
#include "opt_pciide.h"
@@ -233,7 +233,6 @@ artisea_chansetup(struct pciide_softc *sc, int channel,
cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
cp->ata_channel.ch_queue =
malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
- cp->ata_channel.ch_ndrive = 2;
if (cp->ata_channel.ch_queue == NULL) {
aprint_error("%s %s channel: "
"can't allocate memory for command queue",
@@ -349,6 +348,7 @@ artisea_chip_map_dpa(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = ARTISEA_NUM_CHAN;
sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
wdc_allocate_regs(&sc->sc_wdcdev);
diff --git a/sys/dev/pci/cmdide.c b/sys/dev/pci/cmdide.c
index 54ba573b1bd..d63feaa18e2 100644
--- a/sys/dev/pci/cmdide.c
+++ b/sys/dev/pci/cmdide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cmdide.c,v 1.36 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: cmdide.c,v 1.37 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.36 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.37 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -148,6 +148,7 @@ cmd_channel_map(const struct pci_attach_args *pa, struct pciide_softc *sc,
cp->name = PCIIDE_CHANNEL_NAME(channel);
cp->ata_channel.ch_channel = channel;
cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
/*
* Older CMD64X doesn't have independent channels
@@ -174,7 +175,6 @@ cmd_channel_map(const struct pci_attach_args *pa, struct pciide_softc *sc,
device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cp->name);
return;
}
- cp->ata_channel.ch_ndrive = 2;
aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
"%s channel %s to %s mode\n", cp->name,
@@ -258,6 +258,7 @@ cmd_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -378,15 +379,15 @@ cmd0643_9_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
tim = cmd0643_9_data_tim_pio[drvp->PIO_mode];
- if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* UltraDMA on a 646U2, 0648 or 0649 */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
udma_reg = pciide_pci_read(sc->sc_pc,
sc->sc_tag, CMD_UDMATIM(chp->ch_channel));
@@ -527,7 +528,6 @@ cmd680_channel_map(const struct pci_attach_args *pa, struct pciide_softc *sc,
device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cp->name);
return;
}
- cp->ata_channel.ch_ndrive = 2;
/* XXX */
reg = 0xa2 + channel * 16;
@@ -572,12 +572,12 @@ cmd680_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
mode &= ~(0x03 << (drive * 4));
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
off = 0xa0 + chp->ch_channel * 16;
if (drvp->UDMA_mode > 2 &&
@@ -599,7 +599,7 @@ cmd680_setup_channel(struct ata_channel *chp)
val |= udma_tbl[drvp->UDMA_mode];
pciide_pci_write(pc, pa, off, val);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
mode |= 0x02 << (drive * 4);
off = 0xa8 + chp->ch_channel * 16 + drive * 2;
val = dma_tbl[drvp->DMA_mode];
diff --git a/sys/dev/pci/cypide.c b/sys/dev/pci/cypide.c
index 33c9dd83756..4c551ff33af 100644
--- a/sys/dev/pci/cypide.c
+++ b/sys/dev/pci/cypide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cypide.c,v 1.28 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: cypide.c,v 1.29 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cypide.c,v 1.28 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cypide.c,v 1.29 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -139,6 +139,7 @@ cy693_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -150,7 +151,6 @@ cy693_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
cp->ata_channel.ch_queue =
malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
- cp->ata_channel.ch_ndrive = 2;
if (cp->ata_channel.ch_queue == NULL) {
aprint_error("%s primary channel: "
"can't allocate memory for command queue",
@@ -195,10 +195,10 @@ cy693_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
- if (drvp->drive_flags & DRIVE_DMA) {
+ if (drvp->drive_flags & ATA_DRIVE_DMA) {
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
/* use Multiword DMA */
if (dma_mode == -1 || dma_mode > drvp->DMA_mode)
diff --git a/sys/dev/pci/geodeide.c b/sys/dev/pci/geodeide.c
index bee3aed61f1..9714d2b8b1f 100644
--- a/sys/dev/pci/geodeide.c
+++ b/sys/dev/pci/geodeide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: geodeide.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: geodeide.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2004 Manuel Bouyer.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -136,6 +136,7 @@ geodeide_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
/*
* Soekris Engineering Issue #0003:
@@ -203,7 +204,7 @@ geodeide_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
switch (sc->sc_pp->ide_product) {
@@ -222,18 +223,18 @@ geodeide_setup_channel(struct ata_channel *chp)
}
/* add timing values, setup DMA if needed */
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* Use Ultra-DMA */
dma_timing |= geode_udma[drvp->UDMA_mode];
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
/* use Multiword DMA */
dma_timing |= geode_dma[drvp->DMA_mode];
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
} else {
/* PIO only */
s = splbio();
- drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA);
splx(s);
}
diff --git a/sys/dev/pci/hptide.c b/sys/dev/pci/hptide.c
index 7ec77a2bebf..11d374f9348 100644
--- a/sys/dev/pci/hptide.c
+++ b/sys/dev/pci/hptide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hptide.c,v 1.32 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: hptide.c,v 1.33 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hptide.c,v 1.32 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hptide.c,v 1.33 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -199,6 +199,7 @@ hpt_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
else
sc->sc_wdcdev.sc_atac.atac_udma_cap = 5;
}
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -334,26 +335,26 @@ hpt_setup_channel(struct ata_channel *chp)
}
/* Per drive settings */
- for (drive = 0; drive < chp->ch_ndrive; drive++) {
+ for (drive = 0; drive < chp->ch_ndrives; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
before = pci_conf_read(sc->sc_pc, sc->sc_tag,
HPT_IDETIM(chp->ch_channel, drive));
/* add timing values, setup DMA if needed */
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
if ((cable & HPT_CSEL_CBLID(chp->ch_channel)) != 0 &&
drvp->UDMA_mode > 2)
drvp->UDMA_mode = 2;
after = tim_udma[drvp->UDMA_mode];
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
/*
* use Multiword DMA.
* Timings will be used for both PIO and DMA, so adjust
diff --git a/sys/dev/pci/iteide.c b/sys/dev/pci/iteide.c
index ee9590b1f41..e79c62b76c8 100644
--- a/sys/dev/pci/iteide.c
+++ b/sys/dev/pci/iteide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: iteide.c,v 1.16 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: iteide.c,v 1.17 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: iteide.c,v 1.16 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: iteide.c,v 1.17 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -132,6 +132,7 @@ ite_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = ite_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -188,13 +189,13 @@ ite_setup_channel(struct ata_channel *chp)
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 &&
- (drvp->drive_flags & DRIVE_UDMA) != 0) {
+ (drvp->drive_flags & ATA_DRIVE_UDMA) != 0) {
/* Setup UltraDMA mode */
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
modectl &= ~IT_MODE_DMA(channel, drive);
#if 0
@@ -216,9 +217,9 @@ ite_setup_channel(struct ata_channel *chp)
mode = drvp->PIO_mode;
} else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 &&
- (drvp->drive_flags & DRIVE_DMA) != 0) {
+ (drvp->drive_flags & ATA_DRIVE_DMA) != 0) {
/* Setup multiword DMA mode */
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
modectl |= IT_MODE_DMA(channel, drive);
/* mode = min(pio, dma + 2) */
diff --git a/sys/dev/pci/ixpide.c b/sys/dev/pci/ixpide.c
index d420ac5be38..b7a80601dab 100644
--- a/sys/dev/pci/ixpide.c
+++ b/sys/dev/pci/ixpide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ixpide.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: ixpide.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2004 The NetBSD Foundation.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixpide.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixpide.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -120,6 +120,7 @@ ixp_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = ixp_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
interface = PCI_INTERFACE(pa->pa_class);
@@ -187,15 +188,15 @@ ixp_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
IXP_UDMA_ENABLE(udma, chp->ch_channel, drive);
IXP_SET_MODE(udma, chp->ch_channel, drive, drvp->UDMA_mode);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
IXP_UDMA_DISABLE(udma, chp->ch_channel, drive);
IXP_SET_TIMING(mdma_timing, chp->ch_channel, drive,
ixp_mdma_timings[drvp->DMA_mode]);
diff --git a/sys/dev/pci/jmide.c b/sys/dev/pci/jmide.c
index 2d54f0d09e3..cb8928f0916 100644
--- a/sys/dev/pci/jmide.c
+++ b/sys/dev/pci/jmide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: jmide.c,v 1.17 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: jmide.c,v 1.18 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2007 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: jmide.c,v 1.17 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: jmide.c,v 1.18 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -326,6 +326,7 @@ jmpata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = jmpata_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
/*
* can't rely on the PCI_CLASS_REG content if the chip was in raid
@@ -395,17 +396,17 @@ jmpata_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
if (drvp->UDMA_mode > 2 && ide80p == 0)
drvp->UDMA_mode = 2;
splx(s);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
}
}
diff --git a/sys/dev/pci/nside.c b/sys/dev/pci/nside.c
index 3ce6cae7255..94aec9ba2c3 100644
--- a/sys/dev/pci/nside.c
+++ b/sys/dev/pci/nside.c
@@ -1,4 +1,4 @@
-/* $NetBSD: nside.c,v 1.6 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: nside.c,v 1.7 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nside.c,v 1.6 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nside.c,v 1.7 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -129,6 +129,7 @@ natsemi_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = natsemi_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
interface = PCI_INTERFACE(pa->pa_class);
interface &= ~PCIIDE_CHANSTATUS_EN; /* Reserved on PC87415 */
@@ -172,12 +173,12 @@ natsemi_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
ndrives++;
/* add timing values, setup DMA if needed */
- if ((drvp->drive_flags & DRIVE_DMA) == 0) {
+ if ((drvp->drive_flags & ATA_DRIVE_DMA) == 0) {
tim = natsemi_pio_pulse[drvp->PIO_mode] |
(natsemi_pio_recover[drvp->PIO_mode] << 4);
} else {
diff --git a/sys/dev/pci/optiide.c b/sys/dev/pci/optiide.c
index 788c45ccd0e..d1a3249c05d 100644
--- a/sys/dev/pci/optiide.c
+++ b/sys/dev/pci/optiide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: optiide.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $ */
+/* $NetBSD: optiide.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: optiide.c,v 1.23 2012/07/26 20:49:49 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: optiide.c,v 1.24 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -141,6 +141,7 @@ opti_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
init_ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag,
OPTI_REG_INIT_CONTROL);
@@ -197,12 +198,12 @@ opti_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0) {
+ if (drvp->drive_type == ATA_DRIVET_NONE) {
mode[drive] = -1;
continue;
}
- if ((drvp->drive_flags & DRIVE_DMA)) {
+ if ((drvp->drive_flags & ATA_DRIVE_DMA)) {
/*
* Timings will be used for both PIO and DMA,
* so adjust DMA mode if needed
@@ -233,7 +234,7 @@ opti_setup_channel(struct ata_channel *chp)
chp->ch_drive[d].PIO_mode = chp->ch_drive[1-d].PIO_mode;
chp->ch_drive[d].DMA_mode = 0;
s = splbio();
- chp->ch_drive[d].drive_flags &= ~DRIVE_DMA;
+ chp->ch_drive[d].drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
}
}
diff --git a/sys/dev/pci/pciide_common.c b/sys/dev/pci/pciide_common.c
index ad54fd3612e..84d9eda94c7 100644
--- a/sys/dev/pci/pciide_common.c
+++ b/sys/dev/pci/pciide_common.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pciide_common.c,v 1.56 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: pciide_common.c,v 1.57 2012/07/31 15:50:36 bouyer Exp $ */
/*
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.56 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.57 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/malloc.h>
@@ -203,7 +203,7 @@ pciide_common_detach(struct pciide_softc *sc, int flags)
cp->ctl_baseioh, cp->ctl_ios);
}
- for (drive = 0; drive < cp->ata_channel.ch_ndrive; drive++) {
+ for (drive = 0; drive < sc->sc_wdcdev.wdc_maxdrives; drive++) {
#if NATA_DMA
pciide_dma_table_teardown(sc, channel, drive);
#endif
@@ -568,19 +568,19 @@ pciide_channel_dma_setup(struct pciide_channel *cp)
struct pciide_softc *sc = CHAN_TO_PCIIDE(&cp->ata_channel);
struct ata_drive_datas *drvp;
- KASSERT(cp->ata_channel.ch_ndrive != 0);
+ KASSERT(cp->ata_channel.ch_ndrives != 0);
- for (drive = 0; drive < cp->ata_channel.ch_ndrive; drive++) {
+ for (drive = 0; drive < cp->ata_channel.ch_ndrives; drive++) {
drvp = &cp->ata_channel.ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* setup DMA if needed */
- if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
- (drvp->drive_flags & DRIVE_UDMA) == 0) ||
+ if (((drvp->drive_flags & ATA_DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & ATA_DRIVE_UDMA) == 0) ||
sc->sc_dma_ok == 0) {
s = splbio();
- drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_DMA | ATA_DRIVE_UDMA);
splx(s);
continue;
}
@@ -588,7 +588,7 @@ pciide_channel_dma_setup(struct pciide_channel *cp)
drive) != 0) {
/* Abort DMA setup */
s = splbio();
- drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_DMA | ATA_DRIVE_UDMA);
splx(s);
continue;
}
@@ -875,7 +875,6 @@ pciide_chansetup(struct pciide_softc *sc, int channel, pcireg_t interface)
device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cp->name);
return 0;
}
- cp->ata_channel.ch_ndrive = 2;
aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev,
"%s channel %s to %s mode\n", cp->name,
(interface & PCIIDE_INTERFACE_SETTABLE(channel)) ?
@@ -996,6 +995,7 @@ default_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -1069,7 +1069,7 @@ next:
channel++) {
idedma_ctl = 0;
cp = &sc->pciide_channels[channel];
- for (drive = 0; drive < cp->ata_channel.ch_ndrive; drive++) {
+ for (drive = 0; drive < sc->sc_wdcdev.wdc_maxdrives; drive++) {
/*
* we have not probed the drives yet, allocate
* ressources for all of them.
@@ -1116,21 +1116,22 @@ sata_setup_channel(struct ata_channel *chp)
idedma_ctl = 0;
- for (drive = 0; drive < cp->ata_channel.ch_ndrive; drive++) {
+ KASSERT(cp->ata_channel.ch_ndrives != 0);
+ for (drive = 0; drive < cp->ata_channel.ch_ndrives; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
#if NATA_UDMA
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
} else
#endif /* NATA_UDMA */
- if (drvp->drive_flags & DRIVE_DMA) {
+ if (drvp->drive_flags & ATA_DRIVE_DMA) {
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
}
}
diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h
index 073bd341327..311c6ab7017 100644
--- a/sys/dev/pci/pciidevar.h
+++ b/sys/dev/pci/pciidevar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pciidevar.h,v 1.45 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: pciidevar.h,v 1.46 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
@@ -142,7 +142,7 @@ struct pciide_softc {
struct idedma_table *dma_table;
bus_dmamap_t dmamap_xfer;
int dma_flags;
- } dma_maps[ATA_MAXDRIVES];
+ } dma_maps[WDC_MAXDRIVES];
bus_space_handle_t dma_iohs[IDEDMA_NREGS];
/*
* Some controllers require certain bits to
diff --git a/sys/dev/pci/pdcide.c b/sys/dev/pci/pdcide.c
index 314c2752159..43ee0a0192d 100644
--- a/sys/dev/pci/pdcide.c
+++ b/sys/dev/pci/pdcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pdcide.c,v 1.33 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: pdcide.c,v 1.34 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pdcide.c,v 1.33 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pdcide.c,v 1.34 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -233,6 +233,7 @@ pdc202xx_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
pdc20268_setup_channel : pdc202xx_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -349,9 +350,9 @@ pdc202xx_setup_channel(struct ata_channel *chp)
st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE);
/* Trim UDMA mode */
if ((st & PDC262_STATE_80P(channel)) != 0 ||
- (chp->ch_drive[0].drive_flags & DRIVE_UDMA &&
+ (chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA &&
chp->ch_drive[0].UDMA_mode <= 2) ||
- (chp->ch_drive[1].drive_flags & DRIVE_UDMA &&
+ (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA &&
chp->ch_drive[1].UDMA_mode <= 2)) {
if (chp->ch_drive[0].UDMA_mode > 2)
chp->ch_drive[0].UDMA_mode = 2;
@@ -359,9 +360,9 @@ pdc202xx_setup_channel(struct ata_channel *chp)
chp->ch_drive[1].UDMA_mode = 2;
}
/* Set U66 if needed */
- if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA &&
+ if ((chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA &&
chp->ch_drive[0].UDMA_mode > 2) ||
- (chp->ch_drive[1].drive_flags & DRIVE_UDMA &&
+ (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA &&
chp->ch_drive[1].UDMA_mode > 2))
scr |= PDC262_U66_EN(channel);
else
@@ -372,14 +373,14 @@ pdc202xx_setup_channel(struct ata_channel *chp)
device_xname(sc->sc_wdcdev.sc_atac.atac_dev), channel,
bus_space_read_4(sc->sc_dma_iot, sc->sc_dma_ioh,
PDC262_ATAPI(channel))), DEBUG_PROBE);
- if (chp->ch_drive[0].drive_flags & DRIVE_ATAPI ||
- chp->ch_drive[1].drive_flags & DRIVE_ATAPI) {
- if (((chp->ch_drive[0].drive_flags & DRIVE_UDMA) &&
- !(chp->ch_drive[1].drive_flags & DRIVE_UDMA) &&
- (chp->ch_drive[1].drive_flags & DRIVE_DMA)) ||
- ((chp->ch_drive[1].drive_flags & DRIVE_UDMA) &&
- !(chp->ch_drive[0].drive_flags & DRIVE_UDMA) &&
- (chp->ch_drive[0].drive_flags & DRIVE_DMA)))
+ if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATAPI ||
+ chp->ch_drive[1].drive_type == ATA_DRIVET_ATAPI) {
+ if (((chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) &&
+ !(chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) &&
+ (chp->ch_drive[1].drive_flags & ATA_DRIVE_DMA)) ||
+ ((chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) &&
+ !(chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) &&
+ (chp->ch_drive[0].drive_flags & ATA_DRIVE_DMA)))
atapi = 0;
else
atapi = PDC262_ATAPI_UDMA;
@@ -390,20 +391,20 @@ pdc202xx_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
mode = 0;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
mode = PDC2xx_TIM_SET_MB(mode,
pdc2xx_udma_mb[drvp->UDMA_mode]);
mode = PDC2xx_TIM_SET_MC(mode,
pdc2xx_udma_mc[drvp->UDMA_mode]);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
mode = PDC2xx_TIM_SET_MB(mode,
pdc2xx_dma_mb[drvp->DMA_mode]);
mode = PDC2xx_TIM_SET_MC(mode,
@@ -417,7 +418,7 @@ pdc202xx_setup_channel(struct ata_channel *chp)
}
mode = PDC2xx_TIM_SET_PA(mode, pdc2xx_pa[drvp->PIO_mode]);
mode = PDC2xx_TIM_SET_PB(mode, pdc2xx_pb[drvp->PIO_mode]);
- if (drvp->drive_flags & DRIVE_ATA)
+ if (drvp->drive_type == ATA_DRIVET_ATA)
mode |= PDC2xx_TIM_PRE;
mode |= PDC2xx_TIM_SYNC | PDC2xx_TIM_ERRDY;
if (drvp->PIO_mode >= 3) {
@@ -468,17 +469,17 @@ pdc20268_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
if (drvp->UDMA_mode > 2 && u100 == 0)
drvp->UDMA_mode = 2;
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
}
}
@@ -594,14 +595,14 @@ pdc20262_dma_finish(void *v, int channel, int drive, int force)
if (dma_maps->dma_flags & WDC_DMA_LBA48) {
chp = sc->wdc_chanarray[channel];
atapi = 0;
- if (chp->ch_drive[0].drive_flags & DRIVE_ATAPI ||
- chp->ch_drive[1].drive_flags & DRIVE_ATAPI) {
- if ((!(chp->ch_drive[0].drive_flags & DRIVE_UDMA) ||
- (chp->ch_drive[1].drive_flags & DRIVE_UDMA) ||
- !(chp->ch_drive[1].drive_flags & DRIVE_DMA)) &&
- (!(chp->ch_drive[1].drive_flags & DRIVE_UDMA) ||
- (chp->ch_drive[0].drive_flags & DRIVE_UDMA) ||
- !(chp->ch_drive[0].drive_flags & DRIVE_DMA)))
+ if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATAPI ||
+ chp->ch_drive[1].drive_type == ATA_DRIVET_ATAPI) {
+ if ((!(chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) ||
+ (chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) ||
+ !(chp->ch_drive[1].drive_flags & ATA_DRIVE_DMA)) &&
+ (!(chp->ch_drive[1].drive_flags & ATA_DRIVE_UDMA) ||
+ (chp->ch_drive[0].drive_flags & ATA_DRIVE_UDMA) ||
+ !(chp->ch_drive[0].drive_flags & ATA_DRIVE_DMA)))
atapi = PDC262_ATAPI_UDMA;
}
bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
diff --git a/sys/dev/pci/pdcsata.c b/sys/dev/pci/pdcsata.c
index 307fad3529d..6a014e73457 100644
--- a/sys/dev/pci/pdcsata.c
+++ b/sys/dev/pci/pdcsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pdcsata.c,v 1.24 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: pdcsata.c,v 1.25 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2004, Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pdcsata.c,v 1.24 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pdcsata.c,v 1.25 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -292,6 +292,7 @@ pdcsata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
sc->sc_wdcdev.sc_atac.atac_set_modes = pdc203xx_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
sc->sc_wdcdev.reset = pdcsata_do_reset;
@@ -302,6 +303,7 @@ pdcsata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
0x00ff0033);
sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
sc->sc_wdcdev.sc_atac.atac_nchannels = PDC203xx_SATA_NCHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
break;
case PCI_PRODUCT_PROMISE_PDC20371:
case PCI_PRODUCT_PROMISE_PDC20375:
@@ -324,6 +326,7 @@ pdcsata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
0x00ff00ff);
sc->sc_wdcdev.sc_atac.atac_nchannels = PDC40718_SATA_NCHANNELS;
sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
break;
case PCI_PRODUCT_PROMISE_PDC20571:
@@ -373,7 +376,6 @@ pdcsata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
cp->ata_channel.ch_queue =
malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
- cp->ata_channel.ch_ndrive = 2;
if (cp->ata_channel.ch_queue == NULL) {
aprint_error("%s channel %d: "
"can't allocate memory for command queue\n",
@@ -496,11 +498,11 @@ pdc203xx_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
}
}
diff --git a/sys/dev/pci/piixide.c b/sys/dev/pci/piixide.c
index 441de21fea3..065f4573479 100644
--- a/sys/dev/pci/piixide.c
+++ b/sys/dev/pci/piixide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: piixide.c,v 1.62 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: piixide.c,v 1.63 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: piixide.c,v 1.62 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixide.c,v 1.63 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -486,6 +486,7 @@ piix_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = piix3_4_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
ATADEBUG_PRINT(("piix_setup_chip: old idetim=0x%x",
pci_conf_read(sc->sc_pc, sc->sc_tag, PIIX_IDETIM)),
@@ -611,8 +612,8 @@ piix_setup_channel(struct ata_channel *chp)
*/
/* If both drives supports DMA, take the lower mode */
- if ((drvp[0].drive_flags & DRIVE_DMA) &&
- (drvp[1].drive_flags & DRIVE_DMA)) {
+ if ((drvp[0].drive_flags & ATA_DRIVE_DMA) &&
+ (drvp[1].drive_flags & ATA_DRIVE_DMA)) {
mode[0] = mode[1] =
min(drvp[0].DMA_mode, drvp[1].DMA_mode);
drvp[0].DMA_mode = mode[0];
@@ -623,7 +624,7 @@ piix_setup_channel(struct ata_channel *chp)
* If only one drive supports DMA, use its mode, and
* put the other one in PIO mode 0 if mode not compatible
*/
- if (drvp[0].drive_flags & DRIVE_DMA) {
+ if (drvp[0].drive_flags & ATA_DRIVE_DMA) {
mode[0] = drvp[0].DMA_mode;
mode[1] = drvp[1].PIO_mode;
if (piix_isp_pio[mode[1]] != piix_isp_dma[mode[0]] ||
@@ -631,7 +632,7 @@ piix_setup_channel(struct ata_channel *chp)
mode[1] = drvp[1].PIO_mode = 0;
goto ok;
}
- if (drvp[1].drive_flags & DRIVE_DMA) {
+ if (drvp[1].drive_flags & ATA_DRIVE_DMA) {
mode[1] = drvp[1].DMA_mode;
mode[0] = drvp[0].PIO_mode;
if (piix_isp_pio[mode[0]] != piix_isp_dma[mode[1]] ||
@@ -657,7 +658,7 @@ piix_setup_channel(struct ata_channel *chp)
}
ok: /* The modes are setup */
for (drive = 0; drive < 2; drive++) {
- if (drvp[drive].drive_flags & DRIVE_DMA) {
+ if (drvp[drive].drive_flags & ATA_DRIVE_DMA) {
idetim |= piix_setup_idetim_timings(
mode[drive], 1, chp->ch_channel);
goto end;
@@ -676,10 +677,10 @@ end: /*
*/
for (drive = 0; drive < 2; drive++) {
/* If no drive, skip */
- if ((drvp[drive].drive_flags & DRIVE) == 0)
+ if (drvp[drive].drive_type == ATA_DRIVET_NONE)
continue;
idetim |= piix_setup_idetim_drvs(&drvp[drive]);
- if (drvp[drive].drive_flags & DRIVE_DMA)
+ if (drvp[drive].drive_flags & ATA_DRIVE_DMA)
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
}
if (idedma_ctl != 0) {
@@ -721,10 +722,10 @@ piix3_4_setup_channel(struct ata_channel *chp)
PIIX_UDMATIM_SET(0x3, channel, drive));
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
- (drvp->drive_flags & DRIVE_UDMA) == 0))
+ if (((drvp->drive_flags & ATA_DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & ATA_DRIVE_UDMA) == 0))
goto pio;
if (sc->sc_pp->ide_product == PCI_PRODUCT_INTEL_82801AA_IDE ||
@@ -781,10 +782,10 @@ piix3_4_setup_channel(struct ata_channel *chp)
ideconf &= ~PIIX_CONFIG_UDMA66(channel, drive);
}
if ((wdc->sc_atac.atac_cap & ATAC_CAP_UDMA) &&
- (drvp->drive_flags & DRIVE_UDMA)) {
+ (drvp->drive_flags & ATA_DRIVE_UDMA)) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
udmareg |= PIIX_UDMACTL_DRV_EN( channel, drive);
udmareg |= PIIX_UDMATIM_SET(
@@ -792,7 +793,7 @@ piix3_4_setup_channel(struct ata_channel *chp)
} else {
/* use Multiword DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
splx(s);
if (drive == 0) {
idetim |= piix_setup_idetim_timings(
@@ -860,9 +861,9 @@ piix_setup_idetim_drvs(struct ata_drive_datas *drvp)
* If drive is using UDMA, timings setups are independent
* So just check DMA and PIO here.
*/
- if (drvp->drive_flags & DRIVE_DMA) {
+ if (drvp->drive_flags & ATA_DRIVE_DMA) {
/* if mode = DMA mode 0, use compatible timings */
- if ((drvp->drive_flags & DRIVE_DMA) &&
+ if ((drvp->drive_flags & ATA_DRIVE_DMA) &&
drvp->DMA_mode == 0) {
drvp->PIO_mode = 0;
return ret;
@@ -943,6 +944,7 @@ piixsata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
cmdsts = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
cmdsts &= ~PCI_COMMAND_INTERRUPT_DISABLE;
diff --git a/sys/dev/pci/rccide.c b/sys/dev/pci/rccide.c
index d53acfaf773..a269c887d5a 100644
--- a/sys/dev/pci/rccide.c
+++ b/sys/dev/pci/rccide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rccide.c,v 1.25 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: rccide.c,v 1.26 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2003 By Noon Software, Inc. All rights reserved.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rccide.c,v 1.25 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rccide.c,v 1.26 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -152,6 +152,7 @@ serverworks_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = serverworks_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 2;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -211,14 +212,14 @@ serverworks_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
unit = drive + 2 * channel;
/* add timing values, setup DMA if needed */
pio_time |= pio_modes[drvp->PIO_mode] << (8 * (unit^1));
pio_mode |= drvp->PIO_mode << (4 * unit + 16);
if ((atac->atac_cap & ATAC_CAP_UDMA) &&
- (drvp->drive_flags & DRIVE_UDMA)) {
+ (drvp->drive_flags & ATA_DRIVE_UDMA)) {
/* use Ultra/DMA, check for 80-pin cable */
if (drvp->UDMA_mode > 2 &&
(PCI_PRODUCT(pci_conf_read(sc->sc_pc, sc->sc_tag,
@@ -230,17 +231,17 @@ serverworks_setup_channel(struct ata_channel *chp)
udma_mode |= 1 << unit;
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
} else if ((atac->atac_cap & ATAC_CAP_DMA) &&
- (drvp->drive_flags & DRIVE_DMA)) {
+ (drvp->drive_flags & ATA_DRIVE_DMA)) {
/* use Multiword DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
splx(s);
dma_time |= dma_modes[drvp->DMA_mode] << (8 * (unit^1));
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
} else {
/* PIO only */
s = splbio();
- drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA);
splx(s);
}
}
diff --git a/sys/dev/pci/rdcide.c b/sys/dev/pci/rdcide.c
index f3528a2dde3..fb87ed56abf 100644
--- a/sys/dev/pci/rdcide.c
+++ b/sys/dev/pci/rdcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rdcide.c,v 1.6 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: rdcide.c,v 1.7 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2011 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rdcide.c,v 1.6 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rdcide.c,v 1.7 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -144,6 +144,7 @@ rdcide_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = rdcide_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
ATADEBUG_PRINT(("rdcide_setup_chip: old PATR=0x%x",
pci_conf_read(sc->sc_pc, sc->sc_tag, RDCIDE_PATR)),
@@ -219,9 +220,9 @@ rdcide_setup_channel(struct ata_channel *chp)
}
/* now setup modes */
for (drive = 0; drive < 2; drive++) {
- if ((drvp[drive].drive_flags & DRIVE) == 0)
+ if (drvp[drive].drive_type == ATA_DRIVET_NONE)
continue;
- if ((drvp[drive].drive_flags & DRIVE_ATAPI) == 0)
+ if (drvp[drive].drive_type == ATA_DRIVET_ATAPI)
patr |= RDCIDE_PATR_ATA(chp->ch_channel, drive);
if (drive == 0) {
patr |= RDCIDE_PATR_SETUP(
@@ -243,10 +244,10 @@ rdcide_setup_channel(struct ata_channel *chp)
patr |= RDCIDE_PATR_FTIM(chp->ch_channel, drive);
patr |= RDCIDE_PATR_IORDY(chp->ch_channel, drive);
}
- if (drvp[drive].drive_flags & DRIVE_DMA) {
+ if (drvp[drive].drive_flags & ATA_DRIVE_DMA) {
patr |= RDCIDE_PATR_DMAEN(chp->ch_channel, drive);
}
- if ((drvp[drive].drive_flags & DRIVE_UDMA) == 0)
+ if ((drvp[drive].drive_flags & ATA_DRIVE_UDMA) == 0)
continue;
if ((iiocr & RDCIDE_IIOCR_CABLE(chp->ch_channel, drive)) == 0
diff --git a/sys/dev/pci/satalink.c b/sys/dev/pci/satalink.c
index e1eaffd0559..aefda296cee 100644
--- a/sys/dev/pci/satalink.c
+++ b/sys/dev/pci/satalink.c
@@ -1,4 +1,4 @@
-/* $NetBSD: satalink.c,v 1.47 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: satalink.c,v 1.48 2012/07/31 15:50:36 bouyer Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: satalink.c,v 1.47 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: satalink.c,v 1.48 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -505,6 +505,7 @@ sii3112_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -606,7 +607,6 @@ sii3114_chansetup(struct pciide_softc *sc, int channel)
cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
cp->ata_channel.ch_queue =
malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
- cp->ata_channel.ch_ndrive = 2;
if (cp->ata_channel.ch_queue == NULL) {
aprint_error("%s %s channel: "
"can't allocate memory for command queue",
@@ -750,6 +750,7 @@ sii3114_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 4;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -795,13 +796,7 @@ sii3112_drv_probe(struct ata_channel *chp)
struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
uint32_t scontrol, sstatus;
uint8_t scnt, sn, cl, ch;
- int i, s;
-
- /* XXX This should be done by other code. */
- for (i = 0; i < 2; i++) {
- chp->ch_drive[i].chnl_softc = chp;
- chp->ch_drive[i].drive = i;
- }
+ int s;
/*
* The 3112 is a 2-port part, and only has one drive per channel
@@ -875,15 +870,17 @@ sii3112_drv_probe(struct ata_channel *chp)
device_xname(&sc->sc_wdcdev.sc_atac.atac_dev), chp->ch_channel,
scnt, sn, cl, ch);
#endif
+ if (atabus_alloc_drives(chp, 1) != 0)
+ return;
/*
* scnt and sn are supposed to be 0x1 for ATAPI, but in some
* cases we get wrong values here, so ignore it.
*/
s = splbio();
if (cl == 0x14 && ch == 0xeb)
- chp->ch_drive[0].drive_flags |= DRIVE_ATAPI;
+ chp->ch_drive[0].drive_type = ATA_DRIVET_ATAPI;
else
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
+ chp->ch_drive[0].drive_type = ATA_DRIVET_ATA;
splx(s);
aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
@@ -917,16 +914,16 @@ sii3112_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
dtm |= DTM_IDEx_DMA;
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
dtm |= DTM_IDEx_DMA;
} else {
diff --git a/sys/dev/pci/schide.c b/sys/dev/pci/schide.c
index 84206f8fad3..688beb40a47 100644
--- a/sys/dev/pci/schide.c
+++ b/sys/dev/pci/schide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: schide.c,v 1.6 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: schide.c,v 1.7 2012/07/31 15:50:36 bouyer Exp $ */
/* $OpenBSD: pciide.c,v 1.305 2009/11/01 01:50:15 dlg Exp $ */
/*
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: schide.c,v 1.6 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: schide.c,v 1.7 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -140,6 +140,7 @@ sch_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = sch_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
ATADEBUG_PRINT(("sch_setup_chip: old d0tim=0x%x, d1tim=0x%x\n",
@@ -184,26 +185,26 @@ sch_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
timaddr = (drive == 0) ? SCH_D0TIM : SCH_D1TIM;
tim = pci_conf_read(sc->sc_pc, sc->sc_tag, timaddr);
tim &= ~SCH_TIM_MASK;
- if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
- (drvp->drive_flags & DRIVE_UDMA) == 0))
+ if (((drvp->drive_flags & ATA_DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & ATA_DRIVE_UDMA) == 0))
goto pio;
/* add timing values, setup DMA if needed */
if ((atac->atac_cap & ATAC_CAP_UDMA) &&
- (drvp->drive_flags & DRIVE_UDMA)) {
+ (drvp->drive_flags & ATA_DRIVE_UDMA)) {
/* use Ultra/DMA */
tim |= (drvp->UDMA_mode << 16) | SCH_TIM_SYNCDMA;
} else {
/* use Multiword DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
splx(s);
tim &= ~SCH_TIM_SYNCDMA;
}
diff --git a/sys/dev/pci/siside.c b/sys/dev/pci/siside.c
index 09ebb4986e1..695209c5e04 100644
--- a/sys/dev/pci/siside.c
+++ b/sys/dev/pci/siside.c
@@ -1,4 +1,4 @@
-/* $NetBSD: siside.c,v 1.32 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: siside.c,v 1.33 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siside.c,v 1.32 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siside.c,v 1.33 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -293,6 +293,7 @@ sis_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
switch(sc->sis_type) {
case SIS_TYPE_NOUDMA:
case SIS_TYPE_66:
@@ -357,13 +358,13 @@ sis96x_setup_channel(struct ata_channel *chp)
chp->ch_channel, drive);
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
if (pciide_pci_read(sc->sc_pc, sc->sc_tag,
SIS96x_REG_CBL(chp->ch_channel)) & SIS96x_REG_CBL_33) {
@@ -373,7 +374,7 @@ sis96x_setup_channel(struct ata_channel *chp)
sis_tim |= sis_udma133new_tim[drvp->UDMA_mode];
sis_tim |= sis_pio133new_tim[drvp->PIO_mode];
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
- } else if (drvp->drive_flags & DRIVE_DMA) {
+ } else if (drvp->drive_flags & ATA_DRIVE_DMA) {
/*
* use Multiword DMA
* Timings will be used for both PIO and DMA,
@@ -423,17 +424,17 @@ sis_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
- if ((drvp->drive_flags & DRIVE_DMA) == 0 &&
- (drvp->drive_flags & DRIVE_UDMA) == 0)
+ if ((drvp->drive_flags & ATA_DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & ATA_DRIVE_UDMA) == 0)
goto pio;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
if (pciide_pci_read(sc->sc_pc, sc->sc_tag,
SIS_REG_CBL) & SIS_REG_CBL_33(chp->ch_channel)) {
@@ -544,6 +545,7 @@ sis_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
diff --git a/sys/dev/pci/slide.c b/sys/dev/pci/slide.c
index 6a688a02859..29ea3882c19 100644
--- a/sys/dev/pci/slide.c
+++ b/sys/dev/pci/slide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: slide.c,v 1.27 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: slide.c,v 1.28 2012/07/31 15:50:36 bouyer Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: slide.c,v 1.27 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: slide.c,v 1.28 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -160,6 +160,7 @@ sl82c105_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
idecr = pci_conf_read(sc->sc_pc, sc->sc_tag, SYMPH_IDECSR);
@@ -207,12 +208,12 @@ sl82c105_setup_channel(struct ata_channel *chp)
drvp = &chp->ch_drive[drive];
/* If no drive, skip. */
- if ((drvp->drive_flags & DRIVE) == 0) {
+ if (drvp->drive_type == ATA_DRIVET_NONE) {
pci_conf_write(sc->sc_pc, sc->sc_tag, pxdx_reg, pxdx);
continue;
}
- if (drvp->drive_flags & DRIVE_DMA) {
+ if (drvp->drive_flags & ATA_DRIVE_DMA) {
/*
* Timings will be used for both PIO and DMA,
* so adjust DMA mode if needed.
@@ -226,7 +227,7 @@ sl82c105_setup_channel(struct ata_channel *chp)
* Disable DMA.
*/
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
}
} else {
@@ -235,12 +236,12 @@ sl82c105_setup_channel(struct ata_channel *chp)
* DMA.
*/
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
}
}
- if (drvp->drive_flags & DRIVE_DMA) {
+ if (drvp->drive_flags & ATA_DRIVE_DMA) {
/* Use multi-word DMA. */
pxdx |= symph_mw_dma_times[drvp->DMA_mode].cmd_on <<
PxDx_CMD_ON_SHIFT;
diff --git a/sys/dev/pci/stpcide.c b/sys/dev/pci/stpcide.c
index 14ae1623077..56d72130f81 100644
--- a/sys/dev/pci/stpcide.c
+++ b/sys/dev/pci/stpcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: stpcide.c,v 1.25 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: stpcide.c,v 1.26 2012/07/31 15:50:36 bouyer Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: stpcide.c,v 1.25 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: stpcide.c,v 1.26 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -109,6 +109,7 @@ stpc_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = stpc_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -158,14 +159,14 @@ stpc_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if ((atac->atac_cap & ATAC_CAP_DMA) &&
- (drvp->drive_flags & DRIVE_DMA)) {
+ (drvp->drive_flags & ATA_DRIVE_DMA)) {
/* use Multiword DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
splx(s);
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
bits[drive] = 0xe; /* IOCHRDY,wr/post,rd/prefetch */
@@ -173,7 +174,7 @@ stpc_setup_channel(struct ata_channel *chp)
else {
/* PIO only */
s = splbio();
- drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
+ drvp->drive_flags &= ~(ATA_DRIVE_UDMA | ATA_DRIVE_DMA);
splx(s);
bits[drive] = 0x8; /* IOCHRDY */
}
diff --git a/sys/dev/pci/svwsata.c b/sys/dev/pci/svwsata.c
index c7c44b8c3dc..ad89a6410fe 100644
--- a/sys/dev/pci/svwsata.c
+++ b/sys/dev/pci/svwsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: svwsata.c,v 1.15 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: svwsata.c,v 1.16 2012/07/31 15:50:36 bouyer Exp $ */
/*
* Copyright (c) 2005 Mark Kettenis
@@ -17,7 +17,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svwsata.c,v 1.15 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svwsata.c,v 1.16 2012/07/31 15:50:36 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -151,6 +151,7 @@ svwsata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
/* We can use SControl and SStatus to probe for drives. */
sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
wdc_allocate_regs(&sc->sc_wdcdev);
diff --git a/sys/dev/pci/toshide.c b/sys/dev/pci/toshide.c
index 85937355d2f..100f4574810 100644
--- a/sys/dev/pci/toshide.c
+++ b/sys/dev/pci/toshide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: toshide.c,v 1.8 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: toshide.c,v 1.9 2012/07/31 15:50:37 bouyer Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: toshide.c,v 1.8 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: toshide.c,v 1.9 2012/07/31 15:50:37 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -141,6 +141,7 @@ piccolo_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
/*
* XXX one for now. We'll figure out how to talk to the second channel
* later, hopefully! Second interface config is via the
@@ -183,13 +184,13 @@ piccolo_setup_channel(struct ata_channel *chp)
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
- if (drvp->drive_flags & DRIVE_UDMA) {
+ if (drvp->drive_flags & ATA_DRIVE_UDMA) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
/*
@@ -214,7 +215,7 @@ piccolo_setup_channel(struct ata_channel *chp)
idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
}
- else if (drvp->drive_flags & DRIVE_DMA) {
+ else if (drvp->drive_flags & ATA_DRIVE_DMA) {
/*
* Use Multiword DMA
*/
diff --git a/sys/dev/pci/viaide.c b/sys/dev/pci/viaide.c
index c3cadec2abc..a215fab2da1 100644
--- a/sys/dev/pci/viaide.c
+++ b/sys/dev/pci/viaide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: viaide.c,v 1.82 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: viaide.c,v 1.83 2012/07/31 15:50:37 bouyer Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.82 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.83 2012/07/31 15:50:37 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -614,6 +614,7 @@ via_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa)
sc->sc_wdcdev.sc_atac.atac_set_modes = via_setup_channel;
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID)
@@ -743,19 +744,19 @@ via_setup_channel(struct ata_channel *chp)
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
- if ((drvp->drive_flags & DRIVE) == 0)
+ if (drvp->drive_type == ATA_DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
- if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
- (drvp->drive_flags & DRIVE_UDMA) == 0)) {
+ if (((drvp->drive_flags & ATA_DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & ATA_DRIVE_UDMA) == 0)) {
mode = drvp->PIO_mode;
goto pio;
}
if ((atac->atac_cap & ATAC_CAP_UDMA) &&
- (drvp->drive_flags & DRIVE_UDMA)) {
+ (drvp->drive_flags & ATA_DRIVE_UDMA)) {
/* use Ultra/DMA */
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
udmatim_reg |= APO_UDMA_EN(chp->ch_channel, drive) |
APO_UDMA_EN_MTH(chp->ch_channel, drive);
@@ -800,7 +801,7 @@ via_setup_channel(struct ata_channel *chp)
} else {
/* use Multiword DMA, but only if revision is OK */
s = splbio();
- drvp->drive_flags &= ~DRIVE_UDMA;
+ drvp->drive_flags &= ~ATA_DRIVE_UDMA;
splx(s);
#ifndef PCIIDE_AMD756_ENABLEDMA
/*
@@ -821,7 +822,7 @@ via_setup_channel(struct ata_channel *chp)
chp->ch_channel, drive);
mode = drvp->PIO_mode;
s = splbio();
- drvp->drive_flags &= ~DRIVE_DMA;
+ drvp->drive_flags &= ~ATA_DRIVE_DMA;
splx(s);
goto pio;
}
@@ -891,6 +892,7 @@ via_sata_chip_map_common(struct pciide_softc *sc,
sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32;
sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID)
@@ -960,6 +962,8 @@ via_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa,
PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
}
+ sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
+ sc->sc_wdcdev.wdc_maxdrives = 1;
for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels;
channel++) {
cp = &sc->pciide_channels[channel];
@@ -993,7 +997,6 @@ via_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa,
wdc_cp->ch_channel);
continue;
}
- sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe;
pciide_mapchan(pa, cp, interface, pciide_pci_intr);
}
}
@@ -1070,7 +1073,6 @@ via_vt6421_chansetup(struct pciide_softc *sc, int channel)
cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac;
cp->ata_channel.ch_queue =
malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
- cp->ata_channel.ch_ndrive = 2;
if (cp->ata_channel.ch_queue == NULL) {
aprint_error("%s channel %d: "
"can't allocate memory for command queue",
@@ -1120,6 +1122,7 @@ via_sata_chip_map_new(struct pciide_softc *sc,
sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
sc->sc_wdcdev.sc_atac.atac_nchannels = 3;
+ sc->sc_wdcdev.wdc_maxdrives = 2;
wdc_allocate_regs(&sc->sc_wdcdev);
@@ -1148,7 +1151,6 @@ via_sata_chip_map_new(struct pciide_softc *sc,
cp = &sc->pciide_channels[channel];
if (via_vt6421_chansetup(sc, channel) == 0)
continue;
- cp->ata_channel.ch_ndrive = 2;
wdc_cp = &cp->ata_channel;
wdr = CHAN_TO_WDC_REGS(wdc_cp);
diff --git a/sys/dev/pcmcia/wdc_pcmcia.c b/sys/dev/pcmcia/wdc_pcmcia.c
index 1ca2e2aef06..010979c9a04 100644
--- a/sys/dev/pcmcia/wdc_pcmcia.c
+++ b/sys/dev/pcmcia/wdc_pcmcia.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_pcmcia.c,v 1.122 2012/07/26 20:49:50 jakllsch Exp $ */
+/* $NetBSD: wdc_pcmcia.c,v 1.123 2012/07/31 15:50:37 bouyer Exp $ */
/*-
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_pcmcia.c,v 1.122 2012/07/26 20:49:50 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_pcmcia.c,v 1.123 2012/07/31 15:50:37 bouyer Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -299,7 +299,7 @@ wdc_pcmcia_attach(device_t parent, device_t self, void *aux)
sc->ata_channel.ch_queue = &sc->wdc_chqueue;
wdcp = pcmcia_product_lookup(pa, wdc_pcmcia_products,
wdc_pcmcia_nproducts, sizeof(wdc_pcmcia_products[0]), NULL);
- sc->ata_channel.ch_ndrive = wdcp ? wdcp->wdc_ndrive : 2;
+ sc->sc_wdcdev.wdc_maxdrives = wdcp ? wdcp->wdc_ndrive : 2;
wdc_init_shadow_regs(&sc->ata_channel);
error = wdc_pcmcia_enable(self, 1);
@@ -404,7 +404,7 @@ wdc_pcmcia_datain_memory(struct ata_channel *chp, int flags, void *buf,
size_t n;
n = min(len, 1024);
- if ((flags & DRIVE_CAP32) && (n & 3) == 0)
+ if ((flags & ATA_DRIVE_CAP32) && (n & 3) == 0)
bus_space_read_region_stream_4(wdr->data32iot,
wdr->data32ioh, 0, buf, n >> 2);
else
@@ -425,7 +425,7 @@ wdc_pcmcia_dataout_memory(struct ata_channel *chp, int flags, void *buf,
size_t n;
n = min(len, 1024);
- if ((flags & DRIVE_CAP32) && (n & 3) == 0)
+ if ((flags & ATA_DRIVE_CAP32) && (n & 3) == 0)
bus_space_write_region_stream_4(wdr->data32iot,
wdr->data32ioh, 0, buf, n >> 2);
else
diff --git a/sys/dev/podulebus/dtide.c b/sys/dev/podulebus/dtide.c
index 9bd9ca4940d..1d5347fb324 100644
--- a/sys/dev/podulebus/dtide.c
+++ b/sys/dev/podulebus/dtide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dtide.c,v 1.27 2012/07/26 20:49:51 jakllsch Exp $ */
+/* $NetBSD: dtide.c,v 1.28 2012/07/31 15:50:37 bouyer Exp $ */
/*-
* Copyright (c) 2000, 2001 Ben Harris
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dtide.c,v 1.27 2012/07/26 20:49:51 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dtide.c,v 1.28 2012/07/31 15:50:37 bouyer Exp $");
#include <sys/param.h>
@@ -93,6 +93,7 @@ dtide_attach(device_t parent, device_t self, void *aux)
sc->sc_wdc.sc_atac.atac_pio_cap = 0; /* XXX correct? */
sc->sc_wdc.sc_atac.atac_nchannels = DTIDE_NCHANNELS;
sc->sc_wdc.sc_atac.atac_channels = sc->sc_chp;
+ sc->sc_wdc.wdc_maxdrives = 2;
sc->sc_magict = pa->pa_fast_t;
bus_space_map(pa->pa_fast_t, pa->pa_fast_base + DTIDE_MAGICBASE, 0, 1,
&sc->sc_magich);
@@ -106,7 +107,6 @@ dtide_attach(device_t parent, device_t self, void *aux)
wdr->cmd_iot = bst;
wdr->ctl_iot = bst;
ch->ch_queue = &sc->sc_chq[i];
- ch->ch_ndrive = 2;
bus_space_map(pa->pa_fast_t,
pa->pa_fast_base + dtide_cmdoffsets[i], 0, 8,
&wdr->cmd_baseioh);
diff --git a/sys/dev/podulebus/hcide.c b/sys/dev/podulebus/hcide.c
index e0c07c20e04..0fe81feced1 100644
--- a/sys/dev/podulebus/hcide.c
+++ b/sys/dev/podulebus/hcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hcide.c,v 1.24 2012/07/26 20:49:51 jakllsch Exp $ */
+/* $NetBSD: hcide.c,v 1.25 2012/07/31 15:50:37 bouyer Exp $ */
/*-
* Copyright (c) 2000, 2001 Ben Harris
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hcide.c,v 1.24 2012/07/26 20:49:51 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hcide.c,v 1.25 2012/07/31 15:50:37 bouyer Exp $");
#include <sys/param.h>
@@ -92,6 +92,7 @@ hcide_attach(device_t parent, device_t self, void *aux)
sc->sc_wdc.sc_atac.atac_pio_cap = 0; /* XXX correct? */
sc->sc_wdc.sc_atac.atac_nchannels = HCIDE_NCHANNELS;
sc->sc_wdc.sc_atac.atac_channels = sc->sc_chp;
+ sc->sc_wdc.wdc_maxdrives = 2;
aprint_normal("\n");
for (i = 0; i < HCIDE_NCHANNELS; i++) {
ch = sc->sc_chp[i] = &sc->sc_chan[i];
@@ -101,7 +102,6 @@ hcide_attach(device_t parent, device_t self, void *aux)
wdr->cmd_iot = pa->pa_mod_t;
wdr->ctl_iot = pa->pa_mod_t;
ch->ch_queue = &sc->sc_chq[i];
- ch->ch_ndrive = 2;
bus_space_map(pa->pa_fast_t,
pa->pa_fast_base + hcide_cmdoffsets[i], 0, 8,
&wdr->cmd_baseioh);
diff --git a/sys/dev/scsipi/atapi_wdc.c b/sys/dev/scsipi/atapi_wdc.c
index a037c1b8bab..f8179c479be 100644
--- a/sys/dev/scsipi/atapi_wdc.c
+++ b/sys/dev/scsipi/atapi_wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: atapi_wdc.c,v 1.117 2012/07/26 20:49:51 jakllsch Exp $ */
+/* $NetBSD: atapi_wdc.c,v 1.118 2012/07/31 15:50:37 bouyer Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.117 2012/07/26 20:49:51 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.118 2012/07/31 15:50:37 bouyer Exp $");
#ifndef ATADEBUG
#define ATADEBUG
@@ -199,7 +199,7 @@ wdc_atapi_get_params(struct scsipi_channel *chan, int drive,
struct ata_command ata_c;
/* if no ATAPI device detected at wdc attach time, skip */
- if ((chp->ch_drive[drive].drive_flags & DRIVE_ATAPI) == 0) {
+ if (chp->ch_drive[drive].drive_type != ATA_DRIVET_ATAPI) {
ATADEBUG_PRINT(("wdc_atapi_get_params: drive %d not present\n",
drive), DEBUG_PROBE);
return -1;
@@ -290,7 +290,7 @@ wdc_atapi_probe_device(struct atapibus_softc *sc, int target)
periph->periph_flags |= PERIPH_REMOVABLE;
if (periph->periph_type == T_SEQUENTIAL) {
s = splbio();
- drvp->drive_flags |= DRIVE_ATAPIST;
+ drvp->drive_flags |= ATA_DRIVE_ATAPIDSCW;
splx(s);
}
@@ -321,12 +321,12 @@ wdc_atapi_probe_device(struct atapibus_softc *sc, int target)
ata_probe_caps(drvp);
else {
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
} else {
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = ATA_DRIVET_NONE;
splx(s);
}
}
@@ -370,7 +370,7 @@ wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
xfer->c_flags |= C_POLL;
#if NATA_DMA
if ((atac->atac_channels[channel]->ch_drive[drive].drive_flags &
- (DRIVE_DMA | DRIVE_UDMA)) && sc_xfer->datalen > 0)
+ (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && sc_xfer->datalen > 0)
xfer->c_flags |= C_DMA;
#endif
#if NATA_DMA && NATA_PIOBM
@@ -486,7 +486,7 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
if (atac->atac_set_modes == NULL)
goto ready;
/* 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 ready;
errstring = "unbusy";
if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags))
@@ -515,12 +515,12 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
}
#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 {
@@ -532,7 +532,7 @@ wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
if (chp->ch_status & WDCS_ERR) {
if (chp->ch_error == WDCE_ABRT) {
#if NATA_UDMA
- if (drvp->drive_flags & DRIVE_UDMA)
+ if (drvp->drive_flags & ATA_DRIVE_UDMA)
goto error;
else
#endif
@@ -995,7 +995,7 @@ wdc_atapi_phase_complete(struct ata_xfer *xfer)
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
/* wait for DSC if needed */
- if (drvp->drive_flags & DRIVE_ATAPIST) {
+ if (drvp->drive_flags & ATA_DRIVE_ATAPIDSCW) {
ATADEBUG_PRINT(("wdc_atapi_phase_complete(%s:%d:%d) "
"polldsc %d\n", device_xname(atac->atac_dev),
chp->ch_channel,
@@ -1085,9 +1085,9 @@ wdc_atapi_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) {
sc_xfer->error = XS_DRIVER_STUFFUP;
- chp->ch_drive[drive].drive_flags &= ~DRIVE_WAITDRAIN;
+ chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN;
wakeup(&chp->ch_queue->active_xfer);
}
diff --git a/sys/dev/usb/umass_isdata.c b/sys/dev/usb/umass_isdata.c
index ab735f56e6c..e582e16d03a 100644
--- a/sys/dev/usb/umass_isdata.c
+++ b/sys/dev/usb/umass_isdata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: umass_isdata.c,v 1.26 2012/07/26 20:49:51 jakllsch Exp $ */
+/* $NetBSD: umass_isdata.c,v 1.27 2012/07/31 15:50:37 bouyer Exp $ */
/*
* TODO:
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.26 2012/07/26 20:49:51 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.27 2012/07/31 15:50:37 bouyer Exp $");
#ifdef _KERNEL_OPT
#include "opt_umass.h"
@@ -110,7 +110,7 @@ int uisdatadebug = 0;
int uisdata_bio(struct ata_drive_datas *, struct ata_bio *);
int uisdata_bio1(struct ata_drive_datas *, struct ata_bio *);
-void uisdata_reset_drive(struct ata_drive_datas *, int);
+void uisdata_reset_drive(struct ata_drive_datas *, int, uint32_t *);
void uisdata_reset_channel(struct ata_channel *, int);
int uisdata_exec_command(struct ata_drive_datas *, struct ata_command *);
int uisdata_get_params(struct ata_drive_datas *, u_int8_t, struct ataparams *);
@@ -215,7 +215,7 @@ umass_isdata_attach(struct umass_softc *sc)
adev.adev_channel = 1; /* XXX */
adev.adev_openings = 1;
adev.adev_drv_data = &scbus->sc_drv_data;
- scbus->sc_drv_data.drive_flags = DRIVE_ATA;
+ scbus->sc_drv_data.drive_type = ATA_DRIVET_ATA;
scbus->sc_drv_data.chnl_softc = sc;
scbus->base.sc_child = config_found(sc->sc_dev, &adev, uwdprint);
@@ -376,9 +376,10 @@ uisdata_bio1(struct ata_drive_datas *drv, struct ata_bio *ata_bio)
}
void
-uisdata_reset_drive(struct ata_drive_datas *drv, int flags)
+uisdata_reset_drive(struct ata_drive_datas *drv, int flags, uint32_t *sigp)
{
DPRINTFN(-1,("%s\n", __func__));
+ KASSERT(sigp == NULL);
/* XXX what? */
}