From owner-svn-src-all@FreeBSD.ORG Fri Jun 10 08:32:33 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 70212106566C; Fri, 10 Jun 2011 08:32:33 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 55C8C8FC0A; Fri, 10 Jun 2011 08:32:33 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p5A8WXNK016833; Fri, 10 Jun 2011 08:32:33 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p5A8WXUB016831; Fri, 10 Jun 2011 08:32:33 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201106100832.p5A8WXUB016831@svn.freebsd.org> From: Alexander Motin Date: Fri, 10 Jun 2011 08:32:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r222915 - stable/8/sys/dev/ata/chipsets X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jun 2011 08:32:33 -0000 Author: mav Date: Fri Jun 10 08:32:33 2011 New Revision: 222915 URL: http://svn.freebsd.org/changeset/base/222915 Log: MFC r220929: According to ATA specifications, when ATAPI master is the only device, it should respond with all zeroes to any access to slave registers. Test with PATA devices confirmed such behavior. Unluckily, Intel SATA controllers in legacy emulation mode behave differently, not making any difference between ATA and ATAPI devices. It causes false positive slave device detection and, as result, command timeouts. To workaround this problem, mask result of legacy-emulated soft-reset with the device presence information received from the SATA-specific registers. Modified: stable/8/sys/dev/ata/chipsets/ata-intel.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/dev/ata/chipsets/ata-intel.c ============================================================================== --- stable/8/sys/dev/ata/chipsets/ata-intel.c Fri Jun 10 07:54:38 2011 (r222914) +++ stable/8/sys/dev/ata/chipsets/ata-intel.c Fri Jun 10 08:32:33 2011 (r222915) @@ -404,8 +404,9 @@ ata_intel_reset(device_t dev) device_t parent = device_get_parent(dev); struct ata_pci_controller *ctlr = device_get_softc(parent); struct ata_channel *ch = device_get_softc(dev); - int mask, pmask, timeout, devs; + int mask, pshift, timeout, devs; u_char *smap; + uint16_t pcs; /* In combined mode, skip SATA stuff for PATA channel. */ if ((ch->flags & ATA_SATA) == 0) @@ -424,26 +425,35 @@ ata_intel_reset(device_t dev) /* Wait up to 1 sec for "connect well". */ if (ctlr->chip->cfg1 & (INTEL_6CH | INTEL_6CH2)) - pmask = mask << 8; + pshift = 8; else - pmask = mask << 4; + pshift = 4; for (timeout = 0; timeout < 100 ; timeout++) { - if (((pci_read_config(parent, 0x92, 2) & pmask) == pmask) && - (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) + pcs = (pci_read_config(parent, 0x92, 2) >> pshift) & mask; + if ((pcs == mask) && (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) break; ata_udelay(10000); } + if (bootverbose) + device_printf(dev, "SATA reset: ports status=0x%02x\n", pcs); /* If any device found, do soft-reset. */ if (ch->hw.pm_read != NULL) { - devs = ata_sata_phy_reset(dev, 0, 2); + devs = ata_sata_phy_reset(dev, 0, 2) ? ATA_ATA_MASTER : 0; if ((ch->flags & ATA_NO_SLAVE) == 0) - devs += ata_sata_phy_reset(dev, 1, 2); - } else - devs = 1; - if (devs) + devs |= ata_sata_phy_reset(dev, 1, 2) ? + ATA_ATA_SLAVE : 0; + } else { + devs = (pcs & (1 << smap[0])) ? ATA_ATA_MASTER : 0; + if ((ch->flags & ATA_NO_SLAVE) == 0) + devs |= (pcs & (1 << smap[1])) ? + ATA_ATA_SLAVE : 0; + } + if (devs) { ata_generic_reset(dev); - else + /* Reset may give fake slave when only ATAPI master present. */ + ch->devices &= (devs | (devs * ATA_ATAPI_MASTER)); + } else ch->devices = 0; }