summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorbouyer <bouyer@NetBSD.org>2012-07-02 18:15:44 +0000
committerbouyer <bouyer@NetBSD.org>2012-07-02 18:15:44 +0000
commite71c312b36758c88cddf238ea7a428e0d0b5b282 (patch)
tree30524ef2398f3971778b2857026dbec86ff3e6f5 /sys/dev
parent70ef220e99b4b94d8d10af02c721ba7818e4d663 (diff)
Add sata Port MultiPlier (PMP) support to the ata bus layer,
as described in http://mail-index.netbsd.org/tech-kern/2012/06/23/msg013442.html PMP support in integrated to the atabus layer. struct ata_channel's ch_drive[] is not dynamically allocated, and ch_ndrive (renamed to ch_ndrives) closely reflects the size of the ch_drive[] array. Add helper functions atabus_alloc_drives() and atabus_free_drives() to manage ch_drive[]/ch_ndrives. Add wdc_maxdrives to struct wdc_softc so that bus front-end can specify how much drive they really support (master/slave or single). ata_reset_drive() callback gains a uint32_t *sigp argument which, when not NULL, will contain the signature of the device being reset. While there, some cosmetic changes: - added a drive_type enum to ata_drive_datas, and stop encoding the probed drive type in drive_flags (we were out of drive flags anyway). - rename DRIVE_ATAPIST to DRIVE_ATAPIDSCW to better reflect what this really is - remove ata_channel->ata_drives, it's redundant with the pointer in ata_drive_datas - factor out the interpretation of SATA signatures in sata_interpet_sig() propagate these changes to the ATA HBA drivers, and add support for PMP to ahcisata(4) and siisata(4). Thanks to: - Protocase (http://www.protocase.com/) which provided a system with lots of controllers, SATA PMP and drive slots - Conservation Genomics Laboratory, Department of Biology, New Mexico State University for hosting the above system - Brook Milligan, who set up remote access and has been very responsive when SATA cable move was needed
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata.c249
-rw-r--r--sys/dev/ata/ata_wdc.c12
-rw-r--r--sys/dev/ata/atavar.h50
-rw-r--r--sys/dev/ata/files.ata5
-rw-r--r--sys/dev/ata/sata_subr.c55
-rw-r--r--sys/dev/ata/satapmp_subr.c251
-rw-r--r--sys/dev/ata/satapmpreg.h7
-rw-r--r--sys/dev/ata/satapmpvar.h35
-rw-r--r--sys/dev/ata/satavar.h3
-rw-r--r--sys/dev/ata/wd.c32
-rw-r--r--sys/dev/ic/ahcisata_core.c298
-rw-r--r--sys/dev/ic/ahcisatavar.h3
-rw-r--r--sys/dev/ic/mvsata.c32
-rw-r--r--sys/dev/ic/ninjaata32.c12
-rw-r--r--sys/dev/ic/siisata.c152
-rw-r--r--sys/dev/ic/wdc.c116
-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/ofisa/wdc_ofisa.c6
-rw-r--r--sys/dev/pci/acardide.c7
-rw-r--r--sys/dev/pci/aceride.c7
-rw-r--r--sys/dev/pci/artsata.c6
-rw-r--r--sys/dev/pci/cmdide.c12
-rw-r--r--sys/dev/pci/cypide.c8
-rw-r--r--sys/dev/pci/geodeide.c7
-rw-r--r--sys/dev/pci/hptide.c9
-rw-r--r--sys/dev/pci/iteide.c7
-rw-r--r--sys/dev/pci/ixpide.c7
-rw-r--r--sys/dev/pci/jmide.c7
-rw-r--r--sys/dev/pci/nside.c7
-rw-r--r--sys/dev/pci/optiide.c7
-rw-r--r--sys/dev/pci/pciide_common.c21
-rw-r--r--sys/dev/pci/pciidevar.h4
-rw-r--r--sys/dev/pci/pdcide.c19
-rw-r--r--sys/dev/pci/pdcsata.c10
-rw-r--r--sys/dev/pci/piixide.c10
-rw-r--r--sys/dev/pci/rccide.c7
-rw-r--r--sys/dev/pci/rdcide.c9
-rw-r--r--sys/dev/pci/satalink.c23
-rw-r--r--sys/dev/pci/schide.c7
-rw-r--r--sys/dev/pci/siside.c10
-rw-r--r--sys/dev/pci/slide.c7
-rw-r--r--sys/dev/pci/stpcide.c7
-rw-r--r--sys/dev/pci/svwsata.c5
-rw-r--r--sys/dev/pci/toshide.c7
-rw-r--r--sys/dev/pci/viaide.c14
-rw-r--r--sys/dev/pcmcia/wdc_pcmcia.c6
-rw-r--r--sys/dev/podulebus/dtide.c6
-rw-r--r--sys/dev/podulebus/hcide.c6
-rw-r--r--sys/dev/scsipi/atapi_wdc.c14
-rw-r--r--sys/dev/usb/umass_isdata.c11
53 files changed, 1158 insertions, 482 deletions
diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c
index 8fbb91b170c..90205cc4fa7 100644
--- a/sys/dev/ata/ata.c
+++ b/sys/dev/ata/ata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.116 2012/04/06 02:52:00 isaki Exp $ */
+/* $NetBSD: ata.c,v 1.117 2012/07/02 18:15:46 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.116 2012/04/06 02:52:00 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.117 2012/07/02 18:15:46 bouyer Exp $");
#include "opt_ata.h"
@@ -55,10 +55,15 @@ __KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.116 2012/04/06 02:52:00 isaki 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,12 +204,16 @@ 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),
+ 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 */
@@ -223,17 +232,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 != 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 +285,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 == 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 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 == DRIVET_ATAPI) {
#if NATAPIBUS > 0
(*atac->atac_atapibus_attach)(atabus_sc);
#else
@@ -288,33 +314,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 == DRIVET_ATAPI)
+ chp->ch_drive[i].drive_type = 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 != DRIVET_ATA &&
+ chp->ch_drive[i].drive_type != 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];
- chp->ata_drives[i] = config_found_ia(atabus_sc->sc_dev,
+ chp->ch_drive[i].drv_softc = config_found_ia(atabus_sc->sc_dev,
"ata_hl", &adev, ataprint);
- if (chp->ata_drives[i] != 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 = DRIVET_NONE;
splx(s);
}
}
@@ -325,10 +354,14 @@ atabusconfig_thread(void *arg)
ata_print_modes(chp);
}
#if NATARAID > 0
- if (atac->atac_cap & ATAC_CAP_RAID)
- for (i = 0; i < chp->ch_ndrive; i++)
- if (chp->ata_drives[i] != NULL)
- ata_raid_check_component(chp->ata_drives[i]);
+ if (atac->atac_cap & ATAC_CAP_RAID) {
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ if (chp->ch_drive[i].drive_type == DRIVET_ATA) {
+ ata_raid_check_component(
+ chp->ch_drive[i].drv_softc);
+ }
+ }
+ }
#endif /* NATARAID > 0 */
/*
@@ -336,10 +369,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 == 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 = DRIVET_NONE;
+ } else
chp->ch_drive[i].state = 0;
}
splx(s);
@@ -374,13 +410,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 = DRIVET_NONE;
+ }
splx(s);
atabusconfig(sc);
@@ -522,24 +561,28 @@ 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 == DRIVET_ATAPI)
continue;
- if ((dev = chp->ata_drives[i]) != NULL) {
+ if (chp->ch_drive[i].drive_type == DRIVET_PM)
+ chp->ch_drive[i].drive_type = 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)),
DEBUG_DETACH);
- KASSERT(chp->ch_drive[i].drv_softc ==
- chp->ata_drives[i]);
error = config_detach(dev, flags);
if (error)
goto out;
- KASSERT(chp->ata_drives[i] == NULL);
+ KASSERT(chp->ch_drive[i].drv_softc == NULL);
+ KASSERT(chp->ch_drive[i].drive_type == 0);
}
}
+ atabus_free_drives(chp);
out:
#ifdef ATADEBUG
@@ -560,26 +603,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 != 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 = 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 == DRIVET_ATAPI)
continue;
- if (child == chp->ata_drives[i]) {
- KASSERT(chp->ata_drives[i] ==
- chp->ch_drive[i].drv_softc);
- chp->ata_drives[i] = NULL;
+ 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 == DRIVET_PM)
+ chp->ch_satapmp_nports = 0;
+ chp->ch_drive[i].drive_type = DRIVET_NONE;
found = true;
}
}
@@ -597,6 +649,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 != DRIVET_NONE) {
+ printf("%s: ch_drive[%d] type %d != 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,
@@ -615,12 +725,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 == 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 == DRIVET_ATAPI) {
ata_c.r_command = ATAPI_IDENTIFY_DEVICE;
ata_c.r_st_bmask = 0;
ata_c.r_st_pmask = WDCS_DRQ;
@@ -671,7 +781,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 == DRIVET_ATAPI) ?
((M(0) == 'N' && M(1) == 'E') ||
(M(0) == 'F' && M(1) == 'X') ||
(M(0) == 'P' && M(1) == 'i')) :
@@ -1009,7 +1119,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;
@@ -1063,9 +1174,11 @@ 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 == DRIVET_NONE ||
+ drvp->drv_softc == NULL)
continue;
aprint_verbose("%s(%s:%d:%d): using PIO mode %d",
device_xname(drvp->drv_softc),
@@ -1215,7 +1328,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 == DRIVET_ATAPI)
drvp->PIO_mode = 3;
/*
@@ -1354,7 +1467,7 @@ ata_probe_caps(struct ata_drive_datas *drvp)
s = splbio();
drvp->drive_flags &= ~DRIVE_NOSTREAM;
- if (drvp->drive_flags & DRIVE_ATAPI) {
+ if (drvp->drive_type == DRIVET_ATAPI) {
if (atac->atac_cap & ATAC_CAP_ATAPI_NOSTREAM)
drvp->drive_flags |= DRIVE_NOSTREAM;
} else {
@@ -1490,8 +1603,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 == DRIVET_OLD) ||
+ (chp->ch_drive[1].drive_type == DRIVET_OLD))
return (EOPNOTSUPP);
return (EOPNOTSUPP);
}
@@ -1499,8 +1612,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 == DRIVET_OLD) ||
+ (chp->ch_drive[1].drive_type == DRIVET_OLD))
return (EOPNOTSUPP);
switch (a->at_dev) {
case -1:
@@ -1573,23 +1686,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->ata_drives[i] != 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 5cc3d474dfe..3418679f6ef 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.96 2012/01/09 01:01:48 jakllsch Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.97 2012/07/02 18:15:46 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.96 2012/01/09 01:01:48 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.97 2012/07/02 18:15:46 bouyer Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -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. */
@@ -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);
}
diff --git a/sys/dev/ata/atavar.h b/sys/dev/ata/atavar.h
index 21df35baba0..7d94a24b7c1 100644
--- a/sys/dev/ata/atavar.h
+++ b/sys/dev/ata/atavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.84 2012/01/24 20:04:07 jakllsch Exp $ */
+/* $NetBSD: atavar.h,v 1.85 2012/07/02 18:15:46 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.
*/
@@ -113,22 +108,24 @@ struct ataparams;
/* Datas common to drives and controller drivers */
struct ata_drive_datas {
+ enum {
+ DRIVET_NONE = 0,
+ DRIVET_ATA,
+ DRIVET_ATAPI,
+ DRIVET_OLD,
+ DRIVET_PM,
+ } drive_type;
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 DRIVE_CAP32 0x0001
+#define DRIVE_DMA 0x0002
+#define DRIVE_UDMA 0x0004
+#define DRIVE_MODE 0x0008 /* the drive reported its mode */
+#define DRIVE_RESET 0x0010 /* reset the drive state at next xfer */
+#define DRIVE_WAITDRAIN 0x0020 /* device is waiting for the queue to drain */
+#define DRIVE_NOSTREAM 0x0040 /* no stream methods on this drive */
+#define DRIVE_ATAPIDSCW 0x0080 /* needs to wait for DSC in phase_complete */
/*
* 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 */
@@ -356,9 +353,6 @@ struct ata_channel {
device_t atapibus;
struct scsipi_channel ch_atapi_channel;
- /* ATA children */
- device_t ata_drives[ATA_MAXDRIVES];
-
/*
* Channel queues. May be the same for all channels, if hw
* channels are not independent.
@@ -367,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;
};
/*
@@ -434,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 343a10fdf8f..0aa6a52d79a 100644
--- a/sys/dev/ata/files.ata
+++ b/sys/dev/ata/files.ata
@@ -1,4 +1,4 @@
-# $NetBSD: files.ata,v 1.21 2009/06/17 03:07:51 jakllsch Exp $
+# $NetBSD: files.ata,v 1.22 2012/07/02 18:15:46 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 fb43d1c4c1c..148d2d2f5d4 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.15 2012/05/15 19:01:10 bouyer Exp $ */
+/* $NetBSD: sata_subr.c,v 1.16 2012/07/02 18:15:46 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.15 2012/05/15 19:01:10 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.16 2012/07/02 18:15:46 bouyer Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.15 2012/05/15 19:01:10 bouyer 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 = 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 = DRIVET_ATAPI;
+ break;
+ case 0x00000101:
+ chp->ch_drive[port].drive_type = DRIVET_ATA;
+ break;
+ case 0xffffffff:
+ /* COMRESET time out */
+ break;
+ default:
+ chp->ch_drive[port].drive_type = 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/satapmp_subr.c b/sys/dev/ata/satapmp_subr.c
new file mode 100644
index 00000000000..d94c4be42a8
--- /dev/null
+++ b/sys/dev/ata/satapmp_subr.c
@@ -0,0 +1,251 @@
+/* $NetBSD: satapmp_subr.c,v 1.1 2012/07/02 18:15:46 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2012 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.1 2012/07/02 18:15:46 bouyer Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/kmem.h>
+#include <sys/intr.h>
+
+#include <dev/ata/ataconf.h>
+#include <dev/ata/atareg.h>
+#include <dev/ata/atavar.h>
+
+#include <dev/ata/satapmpvar.h>
+#include <dev/ata/satapmpreg.h>
+#include <dev/ata/satavar.h>
+#include <dev/ata/satareg.h>
+
+static int
+satapmp_read(struct ata_channel *chp, int port, int reg, uint32_t *value)
+{
+ struct ata_command ata_c;
+ struct atac_softc *atac = chp->ch_atac;
+ struct ata_drive_datas *drvp;
+
+ KASSERT(reg < PMP_GSCR_NREGS);
+ KASSERT(chp->ch_ndrives >= PMP_MAX_DRIVES);
+ drvp = &chp->ch_drive[PMP_PORT_CTL];
+ KASSERT(drvp->drive == PMP_PORT_CTL);
+
+ memset(&ata_c, 0, sizeof(struct ata_command));
+
+ ata_c.r_command = PMPC_READ_PORT;
+ ata_c.r_features = reg;
+ ata_c.r_lba = (port & 0xf) << 24;
+ ata_c.timeout = 3000; /* 3s */
+ ata_c.r_st_bmask = WDCS_DRDY;
+ ata_c.r_st_pmask = 0;
+ ata_c.flags = AT_READREG | AT_WAIT;
+
+ if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
+ &ata_c) != ATACMD_COMPLETE) {
+ aprint_error_dev(chp->atabus,
+ "PMP register %d read failed\n", reg);
+ return EIO;
+ }
+ if (ata_c.flags & (AT_TIMEOU | AT_DF)) {
+ aprint_error_dev(chp->atabus,
+ "PMP register %d read failed, flags 0x%x\n",
+ reg, ata_c.flags);
+ return EIO;
+ }
+ if (ata_c.flags & AT_ERROR) {
+ aprint_verbose_dev(chp->atabus,
+ "PMP register %d read failed, error 0x%x\n",
+ reg, ata_c.r_error);
+ return EIO;
+ }
+ *value = ata_c.r_lba << 8 | ata_c.r_count;
+ return 0;
+}
+
+static int satapmp_write(struct ata_channel *chp, int, int, uint32_t) __unused;
+static int
+satapmp_write(struct ata_channel *chp, int port, int reg, uint32_t value)
+{
+ struct ata_command ata_c;
+ struct atac_softc *atac = chp->ch_atac;
+ struct ata_drive_datas *drvp;
+
+ KASSERT(reg < PMP_GSCR_NREGS);
+ KASSERT(chp->ch_ndrives >= PMP_MAX_DRIVES);
+ drvp = &chp->ch_drive[PMP_PORT_CTL];
+ KASSERT(drvp->drive == PMP_PORT_CTL);
+
+
+ memset(&ata_c, 0, sizeof(struct ata_command));
+
+ ata_c.r_command = PMPC_WRITE_PORT;
+ ata_c.r_features = reg;
+ ata_c.r_lba = (port & 0xf) << 24;
+ ata_c.r_lba |= (value & 0xffffff00) >> 8;
+ ata_c.r_count = value & 0xff;
+ ata_c.timeout = 3000; /* 3s */
+ ata_c.r_st_bmask = WDCS_DRDY;
+ ata_c.r_st_pmask = 0;
+ ata_c.flags = AT_WAIT;
+
+ if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
+ &ata_c) != ATACMD_COMPLETE) {
+ aprint_error_dev(chp->atabus,
+ "PMP register %d write failed\n", reg);
+ return EIO;
+ }
+ if (ata_c.flags & (AT_TIMEOU | AT_DF)) {
+ aprint_error_dev(chp->atabus,
+ "PMP register %d write failed, flags 0x%x\n",
+ reg, ata_c.flags);
+ return EIO;
+ }
+ if (ata_c.flags & AT_ERROR) {
+ aprint_verbose_dev(chp->atabus,
+ "PMP register %d write failed, error 0x%x\n",
+ reg, ata_c.r_error);
+ return EIO;
+ }
+ return 0;
+}
+
+/*
+ * Reset one port's PHY and bring it online
+ * XXX duplicate of sata_reset_interface()
+ */
+static uint32_t
+satapmp_reset_device_port(struct ata_channel *chp, int port)
+{
+ uint32_t scontrol, sstatus;
+ int i;
+
+ /* bring the PHY online */
+ scontrol = SControl_IPM_NONE | SControl_SPD_ANY | SControl_DET_INIT;
+ if (satapmp_write(chp, port, PMP_PSCR_SControl, scontrol) != 0)
+ return 0;
+
+ tsleep(chp, PRIBIO, "sataup", mstohz(50));
+ scontrol &= ~SControl_DET_INIT;
+ if (satapmp_write(chp, port, PMP_PSCR_SControl, scontrol) != 0)
+ return 0;
+ tsleep(chp, PRIBIO, "sataup", mstohz(50));
+
+ /* wait up to 1s for device to come up */
+ for (i = 0; i < 100; i++) {
+
+ if (satapmp_read(chp, port, PMP_PSCR_SStatus, &sstatus) != 0)
+ return 0;
+ if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV)
+ break;
+ tsleep(chp, PRIBIO, "sataup", mstohz(10));
+ }
+
+ switch (sstatus & SStatus_DET_mask) {
+ case SStatus_DET_NODEV:
+ /* No Device; be silent. */
+ break;
+ case SStatus_DET_DEV_NE:
+ aprint_error("%s PMP port %d: device connected, but "
+ "communication not established\n",
+ device_xname(chp->atabus), port);
+ break;
+ case SStatus_DET_OFFLINE:
+ aprint_error("%s PMP port %d: PHY offline\n",
+ device_xname(chp->atabus), port);
+ break;
+ case SStatus_DET_DEV:
+ aprint_normal("%s PMP port %d: device present, speed: %s\n",
+ device_xname(chp->atabus), port, sata_speed(sstatus));
+ break;
+ default:
+ aprint_error("%s PMP port %d: unknown SStatus: 0x%08x\n",
+ device_xname(chp->atabus), port, sstatus);
+ }
+ return(sstatus & SStatus_DET_mask);
+}
+
+void
+satapmp_rescan(struct ata_channel *chp) {
+ int i;
+ uint32_t sig;
+
+ KASSERT(chp->ch_satapmp_nports <= PMP_PORT_CTL);
+ KASSERT(chp->ch_satapmp_nports <= chp->ch_ndrives);
+
+ for (i = 0; i < chp->ch_satapmp_nports; i++) {
+ if (chp->ch_drive[i].drive_type != DRIVET_NONE ||
+ satapmp_reset_device_port(chp, i) != SStatus_DET_DEV) {
+ continue;
+ }
+ if (satapmp_write(chp, i, PMP_PSCR_SError, 0xffffffff) != 0) {
+ aprint_error("%s PMP port %d: can't write SError\n",
+ device_xname(chp->atabus), i);
+ continue;
+ }
+ chp->ch_atac->atac_bustype_ata->ata_reset_drive(
+ &chp->ch_drive[i], AT_WAIT, &sig);
+
+ sata_interpret_sig(chp, i, sig);
+ }
+}
+
+void
+satapmp_attach(struct ata_channel *chp)
+{
+ uint32_t id, rev, inf;
+
+ if (satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_ID, &id) != 0 ||
+ satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_REV, &rev) != 0 ||
+ satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_INF, &inf) != 0) {
+ aprint_normal_dev(chp->atabus, "can't read PMP registers\n");
+ return;
+ }
+
+ aprint_normal_dev(chp->atabus,
+ "SATA port multiplier, %d ports\n", PMP_INF_NPORTS(inf));
+ aprint_verbose_dev(chp->atabus,
+ "vendor 0x%x, product 0x%x",
+ PMP_ID_VEND(id), PMP_ID_DEV(id));
+ if (rev & PMP_REV_SPEC_11) {
+ aprint_verbose(", revision 1.1");
+ } else if (rev & PMP_REV_SPEC_10) {
+ aprint_verbose(", revision 1.0");
+ } else {
+ aprint_verbose(", unknown revision 0x%x", rev & 0x0f);
+ }
+ aprint_verbose(", level %d\n", PMP_REV_LEVEL(rev));
+
+ chp->ch_satapmp_nports = PMP_INF_NPORTS(inf);
+
+ /* reset and bring up PHYs */
+ satapmp_rescan(chp);
+}
diff --git a/sys/dev/ata/satapmpreg.h b/sys/dev/ata/satapmpreg.h
index 9404861125f..8d732c57bfb 100644
--- a/sys/dev/ata/satapmpreg.h
+++ b/sys/dev/ata/satapmpreg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: satapmpreg.h,v 1.3 2008/04/28 20:23:47 martin Exp $ */
+/* $NetBSD: satapmpreg.h,v 1.4 2012/07/02 18:15:46 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/satapmpvar.h b/sys/dev/ata/satapmpvar.h
new file mode 100644
index 00000000000..f2031d59744
--- /dev/null
+++ b/sys/dev/ata/satapmpvar.h
@@ -0,0 +1,35 @@
+/* $NetBSD: satapmpvar.h,v 1.1 2012/07/02 18:15:46 bouyer Exp $ */
+
+
+/*
+ * Copyright (c) 2012 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_ATA_SATAPMPVAR_H_
+#define _DEV_ATA_SATAPMPVAR_H_
+
+void satapmp_attach(struct ata_channel *);
+void satapmp_rescan(struct ata_channel *);
+
+#endif /* _DEV_ATA_SATAPMPVAR_H_ */
+
diff --git a/sys/dev/ata/satavar.h b/sys/dev/ata/satavar.h
index 0e86f6668cf..526b9542190 100644
--- a/sys/dev/ata/satavar.h
+++ b/sys/dev/ata/satavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: satavar.h,v 1.5 2008/04/28 20:23:47 martin Exp $ */
+/* $NetBSD: satavar.h,v 1.6 2012/07/02 18:15:46 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 29a695cbaef..46f26e90af2 100644
--- a/sys/dev/ata/wd.c
+++ b/sys/dev/ata/wd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.393 2012/06/26 09:49:24 bouyer Exp $ */
+/* $NetBSD: wd.c,v 1.394 2012/07/02 18:15:46 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.393 2012/06/26 09:49:24 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.394 2012/07/02 18:15:46 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 = 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);
}
@@ -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 != 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 67c03b1d42e..bb0a55f3c74 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.34 2012/04/20 20:23:20 bouyer Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.35 2012/07/02 18:15:46 bouyer Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.34 2012/04/20 20:23:20 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.35 2012/07/02 18:15:46 bouyer Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -42,21 +42,25 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.34 2012/04/20 20:23:20 bouyer Ex
#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,167 @@ 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_SPM | AHCI_CAP_CLO)) ==
+ (AHCI_CAP_SPM | 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 +754,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 +797,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 +808,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 == 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 +914,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 +930,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);
@@ -999,6 +1136,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 +1150,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);
@@ -1164,7 +1302,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 +1314,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 == DRIVET_PM) {
+ p_cmd |= AHCI_P_CMD_PMA;
+ }
+ AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel), p_cmd);
}
static void
@@ -1378,6 +1544,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 +1561,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);
@@ -1545,7 +1713,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 != DRIVET_ATAPI) {
AHCIDEBUG_PRINT(("ahci_atapi_probe_device: drive %d "
"not present\n", target), DEBUG_PROBE);
return;
@@ -1584,7 +1752,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 |= DRIVE_ATAPIDSCW;
splx(s);
}
@@ -1615,7 +1783,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 = DRIVET_NONE;
splx(s);
}
} else {
@@ -1624,7 +1792,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 = DRIVET_NONE;
splx(s);
}
}
diff --git a/sys/dev/ic/ahcisatavar.h b/sys/dev/ic/ahcisatavar.h
index 94473ad5554..c9a766e175b 100644
--- a/sys/dev/ic/ahcisatavar.h
+++ b/sys/dev/ic/ahcisatavar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisatavar.h,v 1.7 2010/07/27 22:07:50 jakllsch Exp $ */
+/* $NetBSD: ahcisatavar.h,v 1.8 2012/07/02 18:15:46 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 32434b2780e..4a47b0de8d1 100644
--- a/sys/dev/ic/mvsata.c
+++ b/sys/dev/ic/mvsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsata.c,v 1.16 2012/04/20 20:23:20 bouyer Exp $ */
+/* $NetBSD: mvsata.c,v 1.17 2012/07/02 18:15:46 bouyer Exp $ */
/*
* Copyright (c) 2008 KIYOHARA Takashi
* All rights reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.16 2012/04/20 20:23:20 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.17 2012/07/02 18:15:46 bouyer Exp $");
#include "opt_mvsata.h"
@@ -103,7 +103,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 +304,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;
@@ -519,12 +520,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 +792,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 != 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 +833,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 |= DRIVE_ATAPIDSCW;
splx(s);
}
@@ -860,7 +863,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 = DRIVET_NONE;
splx(s);
}
} else {
@@ -869,7 +872,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 = DRIVET_NONE;
splx(s);
}
}
@@ -918,11 +921,11 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
@@ -933,7 +936,7 @@ mvsata_setup_channel(struct ata_channel *chp)
}
if (drvp->drive_flags & (DRIVE_UDMA | DRIVE_DMA))
- if (drvp->drive_flags & DRIVE_ATA)
+ if (drvp->drive_type == DRIVET_ATA)
edma_mode = dma;
}
@@ -978,11 +981,11 @@ 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 == DRIVET_NONE)
continue;
drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
@@ -2248,7 +2251,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 & DRIVE_ATAPIDSCW) {
DPRINTFN(1,
("%s:%d:%d: mvsata_atapi_phase_complete: polldsc %d\n",
device_xname(atac->atac_dev), chp->ch_channel,
@@ -2823,7 +2826,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 16406f88e12..39458cb6fd8 100644
--- a/sys/dev/ic/ninjaata32.c
+++ b/sys/dev/ic/ninjaata32.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ninjaata32.c,v 1.13 2011/02/21 02:32:00 itohy Exp $ */
+/* $NetBSD: ninjaata32.c,v 1.14 2012/07/02 18:15:46 bouyer Exp $ */
/*
* Copyright (c) 2006 ITOH Yasufumi.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ninjaata32.c,v 1.13 2011/02/21 02:32:00 itohy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ninjaata32.c,v 1.14 2012/07/02 18:15:46 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,16 +317,16 @@ 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 == DRIVET_NONE)
continue; /* no drive */
#if 0 /* ATA DMA is currently unused */
diff --git a/sys/dev/ic/siisata.c b/sys/dev/ic/siisata.c
index 6a1eacbb660..37ea92b9069 100644
--- a/sys/dev/ic/siisata.c
+++ b/sys/dev/ic/siisata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.17 2012/05/15 19:06:26 bouyer Exp $ */
+/* $NetBSD: siisata.c,v 1.18 2012/07/02 18:15:47 bouyer Exp $ */
/* from ahcisata_core.c */
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.17 2012/05/15 19:06:26 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.18 2012/07/02 18:15:47 bouyer Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -96,6 +96,7 @@ __KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.17 2012/05/15 19:06:26 bouyer 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)
@@ -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;
}
@@ -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 == 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 &= 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 &= 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;
}
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c
index 3742aa9fd8c..430fe3328c7 100644
--- a/sys/dev/ic/wdc.c
+++ b/sys/dev/ic/wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.268 2012/01/24 20:04:08 jakllsch Exp $ */
+/* $NetBSD: wdc.c,v 1.269 2012/07/02 18:15:47 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.268 2012/01/24 20:04:08 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.269 2012/07/02 18:15:47 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 = DRIVET_ATAPI;
else
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
+ chp->ch_drive[0].drive_type = 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 = 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 == 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 == 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 != DRIVET_ATA ||
+ (st0 & WDCS_DRDY)) &&
+ (chp->ch_ndrives < 2 ||
+ chp->ch_drive[1].drive_type != 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 != DRIVET_ATAPI)
+ chp->ch_drive[0].drive_type = DRIVET_NONE;
+ if (chp->ch_ndrives > 1 && (st1 & WDCS_DRDY) == 0 &&
+ chp->ch_drive[1].drive_type != DRIVET_ATAPI)
+ chp->ch_drive[1].drive_type = 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
@@ -375,7 +374,7 @@ wdc_drvprobe(struct ata_channel *chp)
chp->ch_drive[i].drive_flags |= DRIVE_CAP32;
splx(s);
}
- if ((chp->ch_drive[i].drive_flags & DRIVE) == 0)
+ if (chp->ch_drive[i].drive_type == 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 != DRIVET_ATA ||
+ (wdc->cap & WDC_CAPABILITY_PREATA) == 0) {
+ chp->ch_drive[i].drive_type = 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 = 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 = 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 = 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 !=
+ DRIVET_NONE) {
+ chp->ch_drive[j].drive_type =
+ 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 = DRIVET_ATAPI;
+ } else {
+ chp->ch_drive[drive].drive_type = 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 != DRIVET_NONE) ? 0x01:0x00;
+ if (chp->ch_ndrives > 1)
+ drv_mask1 |=
+ (chp->ch_drive[1].drive_type != DRIVET_NONE) ? 0x02:0x00;
drv_mask2 = __wdcwait_reset(chp, drv_mask1,
(poll == RESET_SLEEP) ? 0 : 1);
if (drv_mask2 != drv_mask1) {
diff --git a/sys/dev/ic/wdc_upc.c b/sys/dev/ic/wdc_upc.c
index c1bd5628c2b..751298b9b63 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.26 2009/01/25 14:34:14 bjh21 Exp $ */
+/* $NetBSD: wdc_upc.c,v 1.27 2012/07/02 18:15:47 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.26 2009/01/25 14:34:14 bjh21 Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_upc.c,v 1.27 2012/07/02 18:15:47 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 6c317ea6e90..4cd1052cfd9 100644
--- a/sys/dev/ic/wdcvar.h
+++ b/sys/dev/ic/wdcvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: wdcvar.h,v 1.92 2012/01/09 01:01:49 jakllsch Exp $ */
+/* $NetBSD: wdcvar.h,v 1.93 2012/07/02 18:15:47 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 fa5f2e157a7..1731b5ed868 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.56 2009/04/02 00:09:33 dyoung Exp $ */
+/* $NetBSD: wdc_isa.c,v 1.57 2012/07/02 18:15:47 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.56 2009/04/02 00:09:33 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_isa.c,v 1.57 2012/07/02 18:15:47 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 279576e99f5..f7c20bdeb3d 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.39 2008/04/28 20:23:53 martin Exp $ */
+/* $NetBSD: wdc_isapnp.c,v 1.40 2012/07/02 18:15:47 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.39 2008/04/28 20:23:53 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_isapnp.c,v 1.40 2012/07/02 18:15:47 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/ofisa/wdc_ofisa.c b/sys/dev/ofisa/wdc_ofisa.c
index b41f3bd1f86..a21d146ad11 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.30 2008/03/18 20:46:36 cube Exp $ */
+/* $NetBSD: wdc_ofisa.c,v 1.31 2012/07/02 18:15:47 bouyer Exp $ */
/*
* Copyright 1997, 1998
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_ofisa.c,v 1.30 2008/03/18 20:46:36 cube Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_ofisa.c,v 1.31 2012/07/02 18:15:47 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 9471715c8a7..4e15234badc 100644
--- a/sys/dev/pci/acardide.c
+++ b/sys/dev/pci/acardide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: acardide.c,v 1.25 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: acardide.c,v 1.26 2012/07/02 18:15:47 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.25 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acardide.c,v 1.26 2012/07/02 18:15:47 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);
@@ -220,7 +221,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if ((atac->atac_cap & ATAC_CAP_UDMA) &&
diff --git a/sys/dev/pci/aceride.c b/sys/dev/pci/aceride.c
index 7998a317a35..259c3f90432 100644
--- a/sys/dev/pci/aceride.c
+++ b/sys/dev/pci/aceride.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aceride.c,v 1.30 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: aceride.c,v 1.31 2012/07/02 18:15:47 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.30 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: aceride.c,v 1.31 2012/07/02 18:15:47 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) |
@@ -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 == DRIVET_NONE)
continue;
ATADEBUG_PRINT(("acer_setup_channel: old timings reg for "
"channel %d drive %d 0x%x\n", chp->ch_channel, drive,
diff --git a/sys/dev/pci/artsata.c b/sys/dev/pci/artsata.c
index cd7d176b44d..cb047ab0ced 100644
--- a/sys/dev/pci/artsata.c
+++ b/sys/dev/pci/artsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: artsata.c,v 1.21 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: artsata.c,v 1.22 2012/07/02 18:15:47 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.21 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: artsata.c,v 1.22 2012/07/02 18:15:47 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 1b2392f011f..755031e9358 100644
--- a/sys/dev/pci/cmdide.c
+++ b/sys/dev/pci/cmdide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cmdide.c,v 1.32 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: cmdide.c,v 1.33 2012/07/02 18:15:47 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.32 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.33 2012/07/02 18:15:47 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,7 +379,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
tim = cmd0643_9_data_tim_pio[drvp->PIO_mode];
@@ -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,7 +572,7 @@ 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 == DRIVET_NONE)
continue;
mode &= ~(0x03 << (drive * 4));
if (drvp->drive_flags & DRIVE_UDMA) {
diff --git a/sys/dev/pci/cypide.c b/sys/dev/pci/cypide.c
index 39a55ee8b61..754fc7dc4db 100644
--- a/sys/dev/pci/cypide.c
+++ b/sys/dev/pci/cypide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cypide.c,v 1.24 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: cypide.c,v 1.25 2012/07/02 18:15:47 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.24 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cypide.c,v 1.25 2012/07/02 18:15:47 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,7 +195,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if (drvp->drive_flags & DRIVE_DMA) {
diff --git a/sys/dev/pci/geodeide.c b/sys/dev/pci/geodeide.c
index 428a23223c3..d105b4defae 100644
--- a/sys/dev/pci/geodeide.c
+++ b/sys/dev/pci/geodeide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: geodeide.c,v 1.19 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: geodeide.c,v 1.20 2012/07/02 18:15:47 bouyer Exp $ */
/*
* Copyright (c) 2004 Manuel Bouyer.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.19 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.20 2012/07/02 18:15:47 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 == DRIVET_NONE)
continue;
switch (sc->sc_pp->ide_product) {
diff --git a/sys/dev/pci/hptide.c b/sys/dev/pci/hptide.c
index 52a085c984d..14ed634ac80 100644
--- a/sys/dev/pci/hptide.c
+++ b/sys/dev/pci/hptide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hptide.c,v 1.28 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: hptide.c,v 1.29 2012/07/02 18:15:47 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.28 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hptide.c,v 1.29 2012/07/02 18:15:47 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,10 +335,10 @@ 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 == DRIVET_NONE)
continue;
before = pci_conf_read(sc->sc_pc, sc->sc_tag,
HPT_IDETIM(chp->ch_channel, drive));
diff --git a/sys/dev/pci/iteide.c b/sys/dev/pci/iteide.c
index 4044da69587..fbd6b1b6128 100644
--- a/sys/dev/pci/iteide.c
+++ b/sys/dev/pci/iteide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: iteide.c,v 1.12 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: iteide.c,v 1.13 2012/07/02 18:15:47 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.12 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: iteide.c,v 1.13 2012/07/02 18:15:47 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,7 +189,7 @@ 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 == DRIVET_NONE)
continue;
if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 &&
diff --git a/sys/dev/pci/ixpide.c b/sys/dev/pci/ixpide.c
index 5320a904ae0..9c9982116b1 100644
--- a/sys/dev/pci/ixpide.c
+++ b/sys/dev/pci/ixpide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ixpide.c,v 1.19 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: ixpide.c,v 1.20 2012/07/02 18:15:47 bouyer Exp $ */
/*
* Copyright (c) 2004 The NetBSD Foundation.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixpide.c,v 1.19 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixpide.c,v 1.20 2012/07/02 18:15:47 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,7 +188,7 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
s = splbio();
diff --git a/sys/dev/pci/jmide.c b/sys/dev/pci/jmide.c
index 5c7a073272a..547269f46b0 100644
--- a/sys/dev/pci/jmide.c
+++ b/sys/dev/pci/jmide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: jmide.c,v 1.13 2012/03/29 00:02:41 pgoyette Exp $ */
+/* $NetBSD: jmide.c,v 1.14 2012/07/02 18:15:47 bouyer Exp $ */
/*
* Copyright (c) 2007 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: jmide.c,v 1.13 2012/03/29 00:02:41 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: jmide.c,v 1.14 2012/07/02 18:15:47 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,7 +396,7 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
/* use Ultra/DMA */
diff --git a/sys/dev/pci/nside.c b/sys/dev/pci/nside.c
index afa89c7a45e..f01ebc61390 100644
--- a/sys/dev/pci/nside.c
+++ b/sys/dev/pci/nside.c
@@ -1,4 +1,4 @@
-/* $NetBSD: nside.c,v 1.2 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: nside.c,v 1.3 2012/07/02 18:15:47 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.2 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nside.c,v 1.3 2012/07/02 18:15:47 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,7 +173,7 @@ 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 == DRIVET_NONE)
continue;
ndrives++;
diff --git a/sys/dev/pci/optiide.c b/sys/dev/pci/optiide.c
index e51f0820579..602d38e99b9 100644
--- a/sys/dev/pci/optiide.c
+++ b/sys/dev/pci/optiide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: optiide.c,v 1.19 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: optiide.c,v 1.20 2012/07/02 18:15:47 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.19 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: optiide.c,v 1.20 2012/07/02 18:15:47 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,7 +198,7 @@ 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 == DRIVET_NONE) {
mode[drive] = -1;
continue;
}
diff --git a/sys/dev/pci/pciide_common.c b/sys/dev/pci/pciide_common.c
index d073269a00e..874d739cb6f 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.52 2012/01/30 19:41:22 drochner Exp $ */
+/* $NetBSD: pciide_common.c,v 1.53 2012/07/02 18:15:47 bouyer Exp $ */
/*
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.52 2012/01/30 19:41:22 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.53 2012/07/02 18:15:47 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,12 +568,12 @@ 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 == DRIVET_NONE)
continue;
/* setup DMA if needed */
if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
@@ -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,10 +1116,11 @@ 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 == DRIVET_NONE)
continue;
#if NATA_UDMA
if (drvp->drive_flags & DRIVE_UDMA) {
diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h
index 1f73d87f092..5900db53451 100644
--- a/sys/dev/pci/pciidevar.h
+++ b/sys/dev/pci/pciidevar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pciidevar.h,v 1.43 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: pciidevar.h,v 1.44 2012/07/02 18:15:47 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 d56509bd9da..6a16cf0c6ab 100644
--- a/sys/dev/pci/pdcide.c
+++ b/sys/dev/pci/pdcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pdcide.c,v 1.29 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: pdcide.c,v 1.30 2012/07/02 18:15:47 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.29 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pdcide.c,v 1.30 2012/07/02 18:15:47 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);
@@ -372,8 +373,8 @@ 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_type == DRIVET_ATAPI ||
+ chp->ch_drive[1].drive_type == DRIVET_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)) ||
@@ -390,7 +391,7 @@ 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 == DRIVET_NONE)
continue;
mode = 0;
if (drvp->drive_flags & DRIVE_UDMA) {
@@ -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 == DRIVET_ATA)
mode |= PDC2xx_TIM_PRE;
mode |= PDC2xx_TIM_SYNC | PDC2xx_TIM_ERRDY;
if (drvp->PIO_mode >= 3) {
@@ -468,7 +469,7 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
/* use Ultra/DMA */
@@ -594,8 +595,8 @@ 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_type == DRIVET_ATAPI ||
+ chp->ch_drive[1].drive_type == DRIVET_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)) &&
diff --git a/sys/dev/pci/pdcsata.c b/sys/dev/pci/pdcsata.c
index ec560eb3934..57a9fc2e800 100644
--- a/sys/dev/pci/pdcsata.c
+++ b/sys/dev/pci/pdcsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pdcsata.c,v 1.20 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: pdcsata.c,v 1.21 2012/07/02 18:15:47 bouyer Exp $ */
/*
* Copyright (c) 2004, Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pdcsata.c,v 1.20 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pdcsata.c,v 1.21 2012/07/02 18:15:47 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,7 +498,7 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
s = splbio();
diff --git a/sys/dev/pci/piixide.c b/sys/dev/pci/piixide.c
index 650c5f4590e..03c94e16ed1 100644
--- a/sys/dev/pci/piixide.c
+++ b/sys/dev/pci/piixide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: piixide.c,v 1.58 2012/03/05 16:21:44 sborrill Exp $ */
+/* $NetBSD: piixide.c,v 1.59 2012/07/02 18:15:47 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.58 2012/03/05 16:21:44 sborrill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixide.c,v 1.59 2012/07/02 18:15:47 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)),
@@ -676,7 +677,7 @@ end: /*
*/
for (drive = 0; drive < 2; drive++) {
/* If no drive, skip */
- if ((drvp[drive].drive_flags & DRIVE) == 0)
+ if (drvp[drive].drive_type == DRIVET_NONE)
continue;
idetim |= piix_setup_idetim_drvs(&drvp[drive]);
if (drvp[drive].drive_flags & DRIVE_DMA)
@@ -721,7 +722,7 @@ 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 == DRIVET_NONE)
continue;
if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
(drvp->drive_flags & DRIVE_UDMA) == 0))
@@ -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 c6e77e752ed..15b775bec4d 100644
--- a/sys/dev/pci/rccide.c
+++ b/sys/dev/pci/rccide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rccide.c,v 1.21 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: rccide.c,v 1.22 2012/07/02 18:15:48 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.21 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rccide.c,v 1.22 2012/07/02 18:15:48 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,7 +212,7 @@ 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 == DRIVET_NONE)
continue;
unit = drive + 2 * channel;
/* add timing values, setup DMA if needed */
diff --git a/sys/dev/pci/rdcide.c b/sys/dev/pci/rdcide.c
index f8a8d01564f..ec9dcab7d9a 100644
--- a/sys/dev/pci/rdcide.c
+++ b/sys/dev/pci/rdcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rdcide.c,v 1.2 2011/04/04 22:13:58 dyoung Exp $ */
+/* $NetBSD: rdcide.c,v 1.3 2012/07/02 18:15:48 bouyer Exp $ */
/*
* Copyright (c) 2011 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rdcide.c,v 1.2 2011/04/04 22:13:58 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rdcide.c,v 1.3 2012/07/02 18:15:48 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 == DRIVET_NONE)
continue;
- if ((drvp[drive].drive_flags & DRIVE_ATAPI) == 0)
+ if (drvp[drive].drive_type == DRIVET_ATAPI)
patr |= RDCIDE_PATR_ATA(chp->ch_channel, drive);
if (drive == 0) {
patr |= RDCIDE_PATR_SETUP(
diff --git a/sys/dev/pci/satalink.c b/sys/dev/pci/satalink.c
index 55eca5bf4cb..8c394154f39 100644
--- a/sys/dev/pci/satalink.c
+++ b/sys/dev/pci/satalink.c
@@ -1,4 +1,4 @@
-/* $NetBSD: satalink.c,v 1.43 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: satalink.c,v 1.44 2012/07/02 18:15:48 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.43 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: satalink.c,v 1.44 2012/07/02 18:15:48 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 = DRIVET_ATAPI;
else
- chp->ch_drive[0].drive_flags |= DRIVE_ATA;
+ chp->ch_drive[0].drive_type = DRIVET_ATA;
splx(s);
aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
@@ -917,7 +914,7 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
/* use Ultra/DMA */
diff --git a/sys/dev/pci/schide.c b/sys/dev/pci/schide.c
index 938575ba47d..7abcd47171b 100644
--- a/sys/dev/pci/schide.c
+++ b/sys/dev/pci/schide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: schide.c,v 1.2 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: schide.c,v 1.3 2012/07/02 18:15:48 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.2 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: schide.c,v 1.3 2012/07/02 18:15:48 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,7 +185,7 @@ 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 == DRIVET_NONE)
continue;
timaddr = (drive == 0) ? SCH_D0TIM : SCH_D1TIM;
diff --git a/sys/dev/pci/siside.c b/sys/dev/pci/siside.c
index 6357c7bd2da..f8f7272522a 100644
--- a/sys/dev/pci/siside.c
+++ b/sys/dev/pci/siside.c
@@ -1,4 +1,4 @@
-/* $NetBSD: siside.c,v 1.28 2011/05/24 16:42:10 joerg Exp $ */
+/* $NetBSD: siside.c,v 1.29 2012/07/02 18:15:48 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.28 2011/05/24 16:42:10 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siside.c,v 1.29 2012/07/02 18:15:48 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,7 +358,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if (drvp->drive_flags & DRIVE_UDMA) {
@@ -423,7 +424,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if ((drvp->drive_flags & DRIVE_DMA) == 0 &&
@@ -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 93504729052..441fed34dd0 100644
--- a/sys/dev/pci/slide.c
+++ b/sys/dev/pci/slide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: slide.c,v 1.23 2012/04/08 13:08:02 jakllsch Exp $ */
+/* $NetBSD: slide.c,v 1.24 2012/07/02 18:15:48 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.23 2012/04/08 13:08:02 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: slide.c,v 1.24 2012/07/02 18:15:48 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,7 +208,7 @@ 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 == DRIVET_NONE) {
pci_conf_write(sc->sc_pc, sc->sc_tag, pxdx_reg, pxdx);
continue;
}
diff --git a/sys/dev/pci/stpcide.c b/sys/dev/pci/stpcide.c
index 41361b303ed..df3c51e5887 100644
--- a/sys/dev/pci/stpcide.c
+++ b/sys/dev/pci/stpcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: stpcide.c,v 1.21 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: stpcide.c,v 1.22 2012/07/02 18:15:48 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.21 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: stpcide.c,v 1.22 2012/07/02 18:15:48 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,7 +159,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if ((atac->atac_cap & ATAC_CAP_DMA) &&
diff --git a/sys/dev/pci/svwsata.c b/sys/dev/pci/svwsata.c
index 93151d1f238..8917e579cb5 100644
--- a/sys/dev/pci/svwsata.c
+++ b/sys/dev/pci/svwsata.c
@@ -1,4 +1,4 @@
-/* $NetBSD: svwsata.c,v 1.13 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: svwsata.c,v 1.14 2012/07/02 18:15:48 bouyer Exp $ */
/*
* Copyright (c) 2005 Mark Kettenis
@@ -17,7 +17,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svwsata.c,v 1.13 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svwsata.c,v 1.14 2012/07/02 18:15:48 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 07ec4748c2f..38c9ce9592c 100644
--- a/sys/dev/pci/toshide.c
+++ b/sys/dev/pci/toshide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: toshide.c,v 1.4 2011/04/04 20:37:56 dyoung Exp $ */
+/* $NetBSD: toshide.c,v 1.5 2012/07/02 18:15:48 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.4 2011/04/04 20:37:56 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: toshide.c,v 1.5 2012/07/02 18:15:48 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,7 +184,7 @@ 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 == DRIVET_NONE)
continue;
if (drvp->drive_flags & DRIVE_UDMA) {
diff --git a/sys/dev/pci/viaide.c b/sys/dev/pci/viaide.c
index 05be79d8fb1..a6e536a1764 100644
--- a/sys/dev/pci/viaide.c
+++ b/sys/dev/pci/viaide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: viaide.c,v 1.78 2012/03/18 17:50:43 tsutsui Exp $ */
+/* $NetBSD: viaide.c,v 1.79 2012/07/02 18:15:48 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.78 2012/03/18 17:50:43 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.79 2012/07/02 18:15:48 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,7 +744,7 @@ 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 == DRIVET_NONE)
continue;
/* add timing values, setup DMA if needed */
if (((drvp->drive_flags & DRIVE_DMA) == 0 &&
@@ -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 3bcd5f72834..fd625aa7b1a 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.117 2009/11/12 19:37:17 dyoung Exp $ */
+/* $NetBSD: wdc_pcmcia.c,v 1.118 2012/07/02 18:15:48 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.117 2009/11/12 19:37:17 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_pcmcia.c,v 1.118 2012/07/02 18:15:48 bouyer Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -294,12 +294,12 @@ wdc_pcmcia_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 = wdcp ? wdcp->wdc_ndrive : 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;
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;
wdc_init_shadow_regs(&sc->ata_channel);
error = wdc_pcmcia_enable(self, 1);
diff --git a/sys/dev/podulebus/dtide.c b/sys/dev/podulebus/dtide.c
index de882adf133..3ec9af21b89 100644
--- a/sys/dev/podulebus/dtide.c
+++ b/sys/dev/podulebus/dtide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dtide.c,v 1.25 2008/03/18 20:46:37 cube Exp $ */
+/* $NetBSD: dtide.c,v 1.26 2012/07/02 18:15:48 bouyer Exp $ */
/*-
* Copyright (c) 2000, 2001 Ben Harris
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dtide.c,v 1.25 2008/03/18 20:46:37 cube Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dtide.c,v 1.26 2012/07/02 18:15:48 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 a7fd548a69b..ee05a468199 100644
--- a/sys/dev/podulebus/hcide.c
+++ b/sys/dev/podulebus/hcide.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hcide.c,v 1.22 2008/03/18 20:46:37 cube Exp $ */
+/* $NetBSD: hcide.c,v 1.23 2012/07/02 18:15:48 bouyer Exp $ */
/*-
* Copyright (c) 2000, 2001 Ben Harris
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hcide.c,v 1.22 2008/03/18 20:46:37 cube Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hcide.c,v 1.23 2012/07/02 18:15:48 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 b21943840aa..646f5e108d1 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.113 2012/04/20 20:23:21 bouyer Exp $ */
+/* $NetBSD: atapi_wdc.c,v 1.114 2012/07/02 18:15:48 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.113 2012/04/20 20:23:21 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.114 2012/07/02 18:15:48 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 != 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 |= 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 = DRIVET_NONE;
splx(s);
}
} else {
s = splbio();
- drvp->drive_flags &= ~DRIVE_ATAPI;
+ drvp->drive_type = DRIVET_NONE;
splx(s);
}
}
@@ -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 & DRIVE_ATAPIDSCW) {
ATADEBUG_PRINT(("wdc_atapi_phase_complete(%s:%d:%d) "
"polldsc %d\n", device_xname(atac->atac_dev),
chp->ch_channel,
diff --git a/sys/dev/usb/umass_isdata.c b/sys/dev/usb/umass_isdata.c
index 9e76b84a44f..148db9f421c 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.22 2012/03/04 00:21:20 mrg Exp $ */
+/* $NetBSD: umass_isdata.c,v 1.23 2012/07/02 18:15:48 bouyer Exp $ */
/*
* TODO:
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.22 2012/03/04 00:21:20 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.23 2012/07/02 18:15:48 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 = 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? */
}