- Revert r191568 partially. Forcing AHCI mode by changing device subclass

and progif is evil.  It doesn't work reliably[1] and we should honor BIOS
configuration by the user.
- If the SATA controller is enbled but combined mode is disabled, mask off
the emulated IDE channel on the legacy IDE controller.

Pointed out by:	mav[1]
This commit is contained in:
Jung-uk Kim 2009-10-05 16:26:54 +00:00
parent 9cad1429d6
commit b6e6000971

View File

@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
#include <machine/resource.h>
#include <machine/bus.h>
#include <sys/pciio.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@ -55,9 +54,6 @@ __FBSDID("$FreeBSD$");
/* local prototypes */
static int ata_ati_chipinit(device_t dev);
static void ata_ati_setmode(device_t dev, int mode);
static void ata_ati_ahci_enable(device_t dev);
static int ata_ati_ahci_chipinit(device_t dev);
static int ata_ati_ahci_resume(device_t dev);
/* misc defines */
#define ATI_PATA 0x01
@ -66,13 +62,6 @@ static int ata_ati_ahci_resume(device_t dev);
#define SII_MEMIO 1
#define SII_BUG 0x04
/* Misc Control Register */
#define ATI_PCI_MISC_CTRL 0x40
#define ATI_PCI_MISCCTRL_ENABLE_WR 0x00000001
/* Watchdog Control/Status Register */
#define ATI_PCI_WD_CTRL 0x44
#define ATI_PCI_WDCTRL_ENABLE 0x0001
/*
* ATI chipset support functions
@ -121,19 +110,7 @@ ata_ati_probe(device_t dev)
ctlr->chipinit = ata_sii_chipinit;
break;
case ATI_AHCI:
/*
* Force AHCI mode if IDE mode is set from BIOS.
*/
if ((ctlr->chip->chipid == ATA_ATI_IXP600_S1 ||
ctlr->chip->chipid == ATA_ATI_IXP700_S1) &&
pci_get_subclass(dev) == PCIS_STORAGE_IDE) {
struct pci_devinfo *dinfo = device_get_ivars(dev);
pcicfgregs *cfg = &dinfo->cfg;
cfg->subclass = PCIS_STORAGE_SATA;
cfg->progif = PCIP_STORAGE_SATA_AHCI_1_0;
ata_ati_ahci_enable(dev);
}
ctlr->chipinit = ata_ati_ahci_chipinit;
ctlr->chipinit = ata_ahci_chipinit;
break;
}
return (BUS_PROBE_DEFAULT);
@ -143,13 +120,41 @@ static int
ata_ati_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
device_t smbdev;
int satacfg;
if (ata_setup_interrupt(dev, ata_generic_intr))
return ENXIO;
/* IXP600 only has 1 PATA channel */
if (ctlr->chip->chipid == ATA_ATI_IXP600)
switch (ctlr->chip->chipid) {
case ATA_ATI_IXP600:
/* IXP600 only has 1 PATA channel */
ctlr->channels = 1;
break;
case ATA_ATI_IXP700:
/*
* When "combined mode" is enabled, an additional PATA channel is
* emulated with two SATA ports and appears on this device.
* This mode can only be detected via SMB controller.
*/
smbdev = pci_find_device(ATA_ATI_ID, 0x4385);
if (smbdev != NULL) {
satacfg = pci_read_config(smbdev, 0xad, 1);
if (bootverbose)
device_printf(dev, "SATA controller %s (%s%s channel)\n",
(satacfg & 0x01) == 0 ? "disabled" : "enabled",
(satacfg & 0x08) == 0 ? "" : "combined mode, ",
(satacfg & 0x10) == 0 ? "primary" : "secondary");
/*
* If SATA controller is enabled but combined mode is disabled,
* we have only one PATA channel. Ignore a non-existent channel.
*/
if ((satacfg & 0x09) == 0x01)
ctlr->ichannels &= ~(1 << ((satacfg & 0x10) >> 4));
}
break;
}
ctlr->setmode = ata_ati_setmode;
return 0;
@ -219,43 +224,6 @@ ata_ati_setmode(device_t dev, int mode)
}
}
static void
ata_ati_ahci_enable(device_t dev)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
pcicfgregs *cfg = &dinfo->cfg;
uint32_t ctrl;
ctrl = pci_read_config(dev, ATI_PCI_MISC_CTRL, 4);
pci_write_config(dev, ATI_PCI_MISC_CTRL,
ctrl | ATI_PCI_MISCCTRL_ENABLE_WR, 4);
pci_write_config(dev, PCIR_SUBCLASS, cfg->subclass, 1);
pci_write_config(dev, PCIR_PROGIF, cfg->progif, 1);
pci_write_config(dev, ATI_PCI_WD_CTRL,
pci_read_config(dev, ATI_PCI_WD_CTRL, 2) | ATI_PCI_WDCTRL_ENABLE, 2);
pci_write_config(dev, ATI_PCI_MISC_CTRL,
ctrl & ~ATI_PCI_MISCCTRL_ENABLE_WR, 4);
}
static int
ata_ati_ahci_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
int error;
error = ata_ahci_chipinit(dev);
ctlr->resume = ata_ati_ahci_resume;
return (error);
}
static int
ata_ati_ahci_resume(device_t dev)
{
ata_ati_ahci_enable(dev);
return (ata_ahci_ctlr_reset(dev));
}
ATA_DECLARE_DRIVER(ata_ati);
MODULE_DEPEND(ata_ati, ata_ahci, 1, 1, 1);
MODULE_DEPEND(ata_ati, ata_sii, 1, 1, 1);