diff options
Diffstat (limited to 'drivers/ata/ata_piix.c')
-rw-r--r-- | drivers/ata/ata_piix.c | 194 |
1 files changed, 54 insertions, 140 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 720174d628fa..c7de0bb1591f 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -40,7 +40,7 @@ * Documentation * Publically available from Intel web site. Errata documentation * is also publically available. As an aide to anyone hacking on this - * driver the list of errata that are relevant is below.going back to + * driver the list of errata that are relevant is below, going back to * PIIX4. Older device documentation is now a bit tricky to find. * * The chipsets all follow very much the same design. The orginal Triton @@ -93,7 +93,7 @@ #include <linux/libata.h> #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.00ac6" +#define DRV_VERSION "2.00ac7" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -101,11 +101,13 @@ enum { ICH5_PCS = 0x92, /* port control and status */ PIIX_SCC = 0x0A, /* sub-class code register */ - PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */ PIIX_FLAG_SCR = (1 << 26), /* SCR available */ PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ + PIIX_PATA_FLAGS = ATA_FLAG_SLAVE_POSS, + PIIX_SATA_FLAGS = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, + /* combined mode. if set, PATA is channel 0. * if clear, PATA is channel 1. */ @@ -122,11 +124,10 @@ enum { ich_pata_100 = 3, /* ICH up to UDMA 100 */ ich_pata_133 = 4, /* ICH up to UDMA 133 */ ich5_sata = 5, - esb_sata = 6, - ich6_sata = 7, - ich6_sata_ahci = 8, - ich6m_sata_ahci = 9, - ich8_sata_ahci = 10, + ich6_sata = 6, + ich6_sata_ahci = 7, + ich6m_sata_ahci = 8, + ich8_sata_ahci = 9, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -143,13 +144,11 @@ enum { struct piix_map_db { const u32 mask; const u16 port_enable; - const int present_shift; const int map[][4]; }; struct piix_host_priv { const int *map; - const struct piix_map_db *map_db; }; static int piix_init_one (struct pci_dev *pdev, @@ -214,9 +213,9 @@ static const struct pci_device_id piix_pci_tbl[] = { /* 82801EB (ICH5) */ { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 6300ESB (ICH5 variant with broken PCS present bits) */ - { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 6300ESB pretending RAID */ - { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 82801FB/FW (ICH6/ICH6W) */ { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, /* 82801FR/FRW (ICH6R/ICH6RW) */ @@ -367,7 +366,6 @@ static const struct ata_port_operations piix_sata_ops = { static const struct piix_map_db ich5_map_db = { .mask = 0x7, .port_enable = 0x3, - .present_shift = 4, .map = { /* PM PS SM SS MAP */ { P0, NA, P1, NA }, /* 000b */ @@ -384,7 +382,6 @@ static const struct piix_map_db ich5_map_db = { static const struct piix_map_db ich6_map_db = { .mask = 0x3, .port_enable = 0xf, - .present_shift = 4, .map = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b */ @@ -397,7 +394,6 @@ static const struct piix_map_db ich6_map_db = { static const struct piix_map_db ich6m_map_db = { .mask = 0x3, .port_enable = 0x5, - .present_shift = 4, /* Map 01b isn't specified in the doc but some notebooks use * it anyway. MAP 01b have been spotted on both ICH6M and @@ -415,7 +411,6 @@ static const struct piix_map_db ich6m_map_db = { static const struct piix_map_db ich8_map_db = { .mask = 0x3, .port_enable = 0x3, - .present_shift = 8, .map = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ @@ -427,7 +422,6 @@ static const struct piix_map_db ich8_map_db = { static const struct piix_map_db *piix_map_db_table[] = { [ich5_sata] = &ich5_map_db, - [esb_sata] = &ich5_map_db, [ich6_sata] = &ich6_map_db, [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, @@ -438,7 +432,7 @@ static struct ata_port_info piix_port_info[] = { /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */ { .sht = &piix_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .flags = PIIX_PATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ .udma_mask = ATA_UDMA_MASK_40C, @@ -448,7 +442,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, + .flags = PIIX_PATA_FLAGS, .pio_mask = 0x1f, /* pio 0-4 */ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ .udma_mask = ATA_UDMA2, /* UDMA33 */ @@ -457,7 +451,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_66: 2 ICH controllers up to 66MHz */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, + .flags = PIIX_PATA_FLAGS, .pio_mask = 0x1f, /* pio 0-4 */ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ .udma_mask = ATA_UDMA4, @@ -467,7 +461,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_100: 3 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x06, /* mwdma1-2 */ .udma_mask = ATA_UDMA5, /* udma0-5 */ @@ -477,7 +471,7 @@ static struct ata_port_info piix_port_info[] = { /* ich_pata_133: 4 ICH with full UDMA6 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR, + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio 0-4 */ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ .udma_mask = ATA_UDMA6, /* UDMA133 */ @@ -487,41 +481,27 @@ static struct ata_port_info piix_port_info[] = { /* ich5_sata: 5 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | - PIIX_FLAG_IGNORE_PCS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ - .port_ops = &piix_sata_ops, - }, - - /* i6300esb_sata: 6 */ - { - .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, + .flags = PIIX_SATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, - /* ich6_sata: 7 */ + /* ich6_sata: 6 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, - /* ich6_sata_ahci: 8 */ + /* ich6_sata_ahci: 7 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -529,11 +509,10 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich6m_sata_ahci: 9 */ + /* ich6m_sata_ahci: 8 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -541,11 +520,10 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich8_sata_ahci: 10 */ + /* ich8_sata_ahci: 9 */ { .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ @@ -566,10 +544,22 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, piix_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int force_pcs = 0; -module_param(force_pcs, int, 0444); -MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " - "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)"); +struct ich_laptop { + u16 device; + u16 subvendor; + u16 subdevice; +}; + +/* + * List of laptops that use short cables rather than 80 wire + */ + +static const struct ich_laptop ich_laptop[] = { + /* devid, subvendor, subdev */ + { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ + /* end marker */ + { 0, } +}; /** * piix_pata_cbl_detect - Probe host controller cable detect info @@ -585,12 +575,24 @@ MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " static void ich_pata_cbl_detect(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); + const struct ich_laptop *lap = &ich_laptop[0]; u8 tmp, mask; /* no 80c support in host controller? */ if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) goto cbl40; + /* Check for specials - Acer Aspire 5602WLMi */ + while (lap->device) { + if (lap->device == pdev->device && + lap->subvendor == pdev->subsystem_vendor && + lap->subdevice == pdev->subsystem_device) { + ap->cbl = ATA_CBL_PATA40_SHORT; + return; + } + lap++; + } + /* check BIOS cable detect results */ mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); @@ -659,84 +661,9 @@ static void ich_pata_error_handler(struct ata_port *ap) ata_std_postreset); } -/** - * piix_sata_present_mask - determine present mask for SATA host controller - * @ap: Target port - * - * Reads SATA PCI device's PCI config register Port Configuration - * and Status (PCS) to determine port and device availability. - * - * LOCKING: - * None (inherited from caller). - * - * RETURNS: - * determined present_mask - */ -static unsigned int piix_sata_present_mask(struct ata_port *ap) -{ - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - struct piix_host_priv *hpriv = ap->host->private_data; - const unsigned int *map = hpriv->map; - int base = 2 * ap->port_no; - unsigned int present_mask = 0; - int port, i; - u16 pcs; - - pci_read_config_word(pdev, ICH5_PCS, &pcs); - DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); - - for (i = 0; i < 2; i++) { - port = map[base + i]; - if (port < 0) - continue; - if ((ap->flags & PIIX_FLAG_IGNORE_PCS) || - (pcs & 1 << (hpriv->map_db->present_shift + port))) - present_mask |= 1 << i; - } - - DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", - ap->id, pcs, present_mask); - - return present_mask; -} - -/** - * piix_sata_softreset - reset SATA host port via ATA SRST - * @ap: port to reset - * @classes: resulting classes of attached devices - * - * Reset SATA host port via ATA SRST. On controllers with - * reliable PCS present bits, the bits are used to determine - * device presence. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes) -{ - unsigned int present_mask; - int i, rc; - - present_mask = piix_sata_present_mask(ap); - - rc = ata_std_softreset(ap, classes); - if (rc) - return rc; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (!(present_mask & (1 << i))) - classes[i] = ATA_DEV_NONE; - } - - return 0; -} - static void piix_sata_error_handler(struct ata_port *ap) { - ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL, + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL, ata_std_postreset); } @@ -1051,18 +978,6 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev, pci_write_config_word(pdev, ICH5_PCS, new_pcs); msleep(150); } - - if (force_pcs == 1) { - dev_printk(KERN_INFO, &pdev->dev, - "force ignoring PCS (0x%x)\n", new_pcs); - pinfo[0].flags |= PIIX_FLAG_IGNORE_PCS; - pinfo[1].flags |= PIIX_FLAG_IGNORE_PCS; - } else if (force_pcs == 2) { - dev_printk(KERN_INFO, &pdev->dev, - "force honoring PCS (0x%x)\n", new_pcs); - pinfo[0].flags &= ~PIIX_FLAG_IGNORE_PCS; - pinfo[1].flags &= ~PIIX_FLAG_IGNORE_PCS; - } } static void __devinit piix_init_sata_map(struct pci_dev *pdev, @@ -1112,7 +1027,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, "invalid MAP value %u\n", map_value); hpriv->map = map; - hpriv->map_db = map_db; } /** |