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