diff options
Diffstat (limited to 'drivers/scsi/ata_piix.c')
-rw-r--r-- | drivers/scsi/ata_piix.c | 53 |
1 files changed, 28 insertions, 25 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index bf41dd3a35d2..18b3542236d2 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -141,6 +141,7 @@ enum { | |||
141 | 141 | ||
142 | struct piix_map_db { | 142 | struct piix_map_db { |
143 | const u32 mask; | 143 | const u32 mask; |
144 | const u32 port_enable; | ||
144 | const int map[][4]; | 145 | const int map[][4]; |
145 | }; | 146 | }; |
146 | 147 | ||
@@ -294,6 +295,7 @@ static const struct ata_port_operations piix_sata_ops = { | |||
294 | 295 | ||
295 | static const struct piix_map_db ich5_map_db = { | 296 | static const struct piix_map_db ich5_map_db = { |
296 | .mask = 0x7, | 297 | .mask = 0x7, |
298 | .port_enable = 0x3, | ||
297 | .map = { | 299 | .map = { |
298 | /* PM PS SM SS MAP */ | 300 | /* PM PS SM SS MAP */ |
299 | { P0, NA, P1, NA }, /* 000b */ | 301 | { P0, NA, P1, NA }, /* 000b */ |
@@ -309,6 +311,7 @@ static const struct piix_map_db ich5_map_db = { | |||
309 | 311 | ||
310 | static const struct piix_map_db ich6_map_db = { | 312 | static const struct piix_map_db ich6_map_db = { |
311 | .mask = 0x3, | 313 | .mask = 0x3, |
314 | .port_enable = 0xf, | ||
312 | .map = { | 315 | .map = { |
313 | /* PM PS SM SS MAP */ | 316 | /* PM PS SM SS MAP */ |
314 | { P0, P2, P1, P3 }, /* 00b */ | 317 | { P0, P2, P1, P3 }, /* 00b */ |
@@ -320,6 +323,7 @@ static const struct piix_map_db ich6_map_db = { | |||
320 | 323 | ||
321 | static const struct piix_map_db ich6m_map_db = { | 324 | static const struct piix_map_db ich6m_map_db = { |
322 | .mask = 0x3, | 325 | .mask = 0x3, |
326 | .port_enable = 0x5, | ||
323 | .map = { | 327 | .map = { |
324 | /* PM PS SM SS MAP */ | 328 | /* PM PS SM SS MAP */ |
325 | { P0, P2, RV, RV }, /* 00b */ | 329 | { P0, P2, RV, RV }, /* 00b */ |
@@ -519,44 +523,25 @@ static int piix_sata_prereset(struct ata_port *ap) | |||
519 | struct piix_host_priv *hpriv = ap->host_set->private_data; | 523 | struct piix_host_priv *hpriv = ap->host_set->private_data; |
520 | const unsigned int *map = hpriv->map; | 524 | const unsigned int *map = hpriv->map; |
521 | int base = 2 * ap->hard_port_no; | 525 | int base = 2 * ap->hard_port_no; |
522 | unsigned int present_mask = 0; | 526 | unsigned int present = 0; |
523 | int port, i; | 527 | int port, i; |
524 | u8 pcs; | 528 | u16 pcs; |
525 | 529 | ||
526 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); | 530 | pci_read_config_word(pdev, ICH5_PCS, &pcs); |
527 | DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); | 531 | DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); |
528 | 532 | ||
529 | /* enable all ports on this ap and wait for them to settle */ | ||
530 | for (i = 0; i < 2; i++) { | ||
531 | port = map[base + i]; | ||
532 | if (port >= 0) | ||
533 | pcs |= 1 << port; | ||
534 | } | ||
535 | |||
536 | pci_write_config_byte(pdev, ICH5_PCS, pcs); | ||
537 | msleep(100); | ||
538 | |||
539 | /* let's see which devices are present */ | ||
540 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); | ||
541 | |||
542 | for (i = 0; i < 2; i++) { | 533 | for (i = 0; i < 2; i++) { |
543 | port = map[base + i]; | 534 | port = map[base + i]; |
544 | if (port < 0) | 535 | if (port < 0) |
545 | continue; | 536 | continue; |
546 | if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port)) | 537 | if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port)) |
547 | present_mask |= 1 << i; | 538 | present = 1; |
548 | else | ||
549 | pcs &= ~(1 << port); | ||
550 | } | 539 | } |
551 | 540 | ||
552 | /* disable offline ports on non-AHCI controllers */ | ||
553 | if (!(ap->flags & PIIX_FLAG_AHCI)) | ||
554 | pci_write_config_byte(pdev, ICH5_PCS, pcs); | ||
555 | |||
556 | DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", | 541 | DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", |
557 | ap->id, pcs, present_mask); | 542 | ap->id, pcs, present_mask); |
558 | 543 | ||
559 | if (!present_mask) { | 544 | if (!present) { |
560 | ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); | 545 | ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); |
561 | ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; | 546 | ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; |
562 | return 0; | 547 | return 0; |
@@ -770,6 +755,22 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) | |||
770 | return no_piix_dma; | 755 | return no_piix_dma; |
771 | } | 756 | } |
772 | 757 | ||
758 | static void __devinit piix_init_pcs(struct pci_dev *pdev, | ||
759 | const struct piix_map_db *map_db) | ||
760 | { | ||
761 | u16 pcs, new_pcs; | ||
762 | |||
763 | pci_read_config_word(pdev, ICH5_PCS, &pcs); | ||
764 | |||
765 | new_pcs = pcs | map_db->port_enable; | ||
766 | |||
767 | if (new_pcs != pcs) { | ||
768 | DPRINTK("updating PCS from 0x%x to 0x%x\n", pcs, new_pcs); | ||
769 | pci_write_config_word(pdev, ICH5_PCS, new_pcs); | ||
770 | msleep(150); | ||
771 | } | ||
772 | } | ||
773 | |||
773 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, | 774 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, |
774 | struct ata_port_info *pinfo, | 775 | struct ata_port_info *pinfo, |
775 | const struct piix_map_db *map_db) | 776 | const struct piix_map_db *map_db) |
@@ -871,9 +872,11 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
871 | } | 872 | } |
872 | 873 | ||
873 | /* Initialize SATA map */ | 874 | /* Initialize SATA map */ |
874 | if (host_flags & ATA_FLAG_SATA) | 875 | if (host_flags & ATA_FLAG_SATA) { |
875 | piix_init_sata_map(pdev, port_info, | 876 | piix_init_sata_map(pdev, port_info, |
876 | piix_map_db_table[ent->driver_data]); | 877 | piix_map_db_table[ent->driver_data]); |
878 | piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]); | ||
879 | } | ||
877 | 880 | ||
878 | /* On ICH5, some BIOSen disable the interrupt using the | 881 | /* On ICH5, some BIOSen disable the interrupt using the |
879 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. | 882 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. |