--- sys/dev/ata/ata-pci.h 30 Mar 2009 22:18:38 -0000 1.104 +++ sys/dev/ata/ata-pci.h 22 Apr 2009 18:44:04 -0000 @@ -108,6 +108,11 @@ #define ATA_ATI_IXP600_S1 0x43801002 #define ATA_ATI_IXP700 0x439c1002 #define ATA_ATI_IXP700_S1 0x43901002 +#define ATA_ATI_IXP700_S2 0x43911002 +#define ATA_ATI_IXP700_S3 0x43921002 +#define ATA_ATI_IXP700_S4 0x43931002 +#define ATA_ATI_IXP700_S5 0x43941002 +#define ATA_ATI_IXP700_S6 0x43951002 #define ATA_CENATEK_ID 0x16ca #define ATA_CENATEK_ROCKET 0x000116ca @@ -458,6 +463,7 @@ int ata_ahci_ch_detach(device_t dev); int ata_ahci_ch_suspend(device_t dev); int ata_ahci_ch_resume(device_t dev); +int ata_ahci_ctlr_reset(device_t dev); void ata_ahci_reset(device_t dev); int ata_marvell_edma_chipinit(device_t); int ata_sii_chipinit(device_t); --- sys/dev/ata/chipsets/ata-ahci.c 30 Mar 2009 22:18:38 -0000 1.20 +++ sys/dev/ata/chipsets/ata-ahci.c 22 Apr 2009 18:44:04 -0000 @@ -52,7 +52,6 @@ #include /* local prototypes */ -static int ata_ahci_ctlr_reset(device_t dev); static int ata_ahci_suspend(device_t dev); static int ata_ahci_status(device_t dev); static int ata_ahci_begin_transaction(struct ata_request *request); @@ -155,7 +154,7 @@ return 0; } -static int +int ata_ahci_ctlr_reset(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); --- sys/dev/ata/chipsets/ata-ati.c 9 Oct 2008 12:56:57 -0000 1.1 +++ sys/dev/ata/chipsets/ata-ati.c 22 Apr 2009 18:44:04 -0000 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -54,14 +55,26 @@ /* local prototypes */ static int ata_ati_chipinit(device_t dev); static void ata_ati_setmode(device_t dev, int mode); +static int ata_ati_ahci_chipinit(device_t dev); +static int ata_ati_ahci_resume(device_t dev); +static void ata_ati_ahci_fixup(device_t dev); /* misc defines */ #define ATI_PATA 0x01 #define ATI_SATA 0x02 #define ATI_AHCI 0x04 #define SII_MEMIO 1 +#define ATI_FORCE_AHCI 0x01 +#define ATI_INTx_BUG 0x02 #define SII_BUG 0x04 +#define ATI_SMBUS_DEV 0x4385 +/* Misc Control Register */ +#define ATI_PCI_MISC_CTRL 0x40 +#define ATI_PCI_MISCCTRL_ENABLE_WR 0x00000001 + +/* MSI Control Register */ +#define ATI_PCI_MSI_CTRL 0x50 /* * ATI chipset support functions @@ -81,7 +94,16 @@ { ATA_ATI_IXP600_S1, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP600" }, { ATA_ATI_IXP700, 0x00, ATI_PATA, 0, ATA_UDMA6, "IXP700" }, { ATA_ATI_IXP700_S1, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" }, + { ATA_ATI_IXP700_S2, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" }, + { ATA_ATI_IXP700_S3, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" }, + { ATA_ATI_IXP700_S4, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" }, + { ATA_ATI_IXP700_S5, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" }, + { ATA_ATI_IXP700_S6, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" }, { 0, 0, 0, 0, 0, 0}}; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + device_t smbdev; + uint8_t revid; if (pci_get_vendor(dev) != ATA_ATI_ID) return ENXIO; @@ -105,7 +127,43 @@ ctlr->chipinit = ata_sii_chipinit; break; case ATI_AHCI: - ctlr->chipinit = ata_ahci_chipinit; + /* Force AHCI mode on SATA controllers if IDE mode is set. */ + if ((ctlr->chip->chipid == ATA_ATI_IXP600_S1 || + ctlr->chip->chipid == ATA_ATI_IXP700_S1) && + pci_get_subclass(dev) == PCIS_STORAGE_IDE) { + ctlr->chip->cfg2 = ATI_FORCE_AHCI; + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + cfg->subclass = PCIS_STORAGE_SATA; + cfg->progif = PCIP_STORAGE_SATA_AHCI_1_0; + if (cfg->msi.msi_location == 0) { + cfg->msi.msi_location = ATI_PCI_MSI_CTRL; + cfg->msi.msi_ctrl = pci_read_config(dev, + ATI_PCI_MSI_CTRL + PCIR_MSI_CTRL, 2) & + ~PCIM_MSICTRL_MME_MASK; + cfg->msi.msi_msgnum = + 1 << ((cfg->msi.msi_ctrl & PCIM_MSICTRL_MMC_MASK) >> 1); + cfg->msi.msi_ctrl |= cfg->msi.msi_msgnum << 4; + } + } + /* + * Some IXP700 revisions require INTx even with MSI. + * XXX Chip revision must be obtained from SMBUS device. + */ + if ((ctlr->chip->chipid == ATA_ATI_IXP700_S1 || + ctlr->chip->chipid == ATA_ATI_IXP700_S2 || + ctlr->chip->chipid == ATA_ATI_IXP700_S3 || + ctlr->chip->chipid == ATA_ATI_IXP700_S4 || + ctlr->chip->chipid == ATA_ATI_IXP700_S5) && + (smbdev = pci_find_device(ATA_ATI_ID, ATI_SMBUS_DEV)) != NULL) { + revid = pci_get_revid(smbdev); + if (revid >= 0x30 && revid < 0x3b) + ctlr->chip->cfg2 |= ATI_INTx_BUG; + } + if (ctlr->chip->cfg2 != 0) + ctlr->chipinit = ata_ati_ahci_chipinit; + else + ctlr->chipinit = ata_ahci_chipinit; break; } return 0; @@ -119,9 +177,8 @@ if (ata_setup_interrupt(dev, ata_generic_intr)) return ENXIO; - /* IXP600 & IXP700 only have 1 PATA channel */ - if ((ctlr->chip->chipid == ATA_ATI_IXP600) || - (ctlr->chip->chipid == ATA_ATI_IXP700)) + /* IXP600 only has 1 PATA channel */ + if (ctlr->chip->chipid == ATA_ATI_IXP600) ctlr->channels = 1; ctlr->setmode = ata_ati_setmode; @@ -192,6 +249,49 @@ } } +static int +ata_ati_ahci_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int error; + + ata_ati_ahci_fixup(dev); + error = ata_ahci_chipinit(dev); + if ((ctlr->chip->cfg2 & ATI_FORCE_AHCI) != 0) + ctlr->resume = ata_ati_ahci_resume; + if ((ctlr->chip->cfg2 & ATI_INTx_BUG) != 0) + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~PCIM_CMD_INTxDIS, 2); + return (error); +} + +static int +ata_ati_ahci_resume(device_t dev) +{ + + ata_ati_ahci_fixup(dev); + return (ata_ahci_ctlr_reset(dev)); +} + +static void +ata_ati_ahci_fixup(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); + if (cfg->msi.msi_location != 0) + pci_write_config(dev, cfg->msi.msi_location + PCIR_MSI_CTRL, + cfg->msi.msi_ctrl, 2); + pci_write_config(dev, ATI_PCI_MISC_CTRL, + ctrl & ~ATI_PCI_MISCCTRL_ENABLE_WR, 4); +} + ATA_DECLARE_DRIVER(ata_ati); MODULE_DEPEND(ata_ati, ata_ahci, 1, 1, 1); MODULE_DEPEND(ata_ati, ata_sii, 1, 1, 1);