diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ata_piix.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 4080b8be847b..72e38e6ea756 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -499,44 +499,59 @@ static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) | |||
499 | * piix_sata_probe - Probe PCI device for present SATA devices | 499 | * piix_sata_probe - Probe PCI device for present SATA devices |
500 | * @ap: Port associated with the PCI device we wish to probe | 500 | * @ap: Port associated with the PCI device we wish to probe |
501 | * | 501 | * |
502 | * Reads SATA PCI device's PCI config register Port Configuration | 502 | * Reads and configures SATA PCI device's PCI config register |
503 | * and Status (PCS) to determine port and device availability. | 503 | * Port Configuration and Status (PCS) to determine port and |
504 | * device availability. | ||
504 | * | 505 | * |
505 | * LOCKING: | 506 | * LOCKING: |
506 | * None (inherited from caller). | 507 | * None (inherited from caller). |
507 | * | 508 | * |
508 | * RETURNS: | 509 | * RETURNS: |
509 | * Non-zero if port is enabled, it may or may not have a device | 510 | * Mask of avaliable devices on the port. |
510 | * attached in that case (PRESENT bit would only be set if BIOS probe | ||
511 | * was done). Zero is returned if port is disabled. | ||
512 | */ | 511 | */ |
513 | static int piix_sata_probe (struct ata_port *ap) | 512 | static unsigned int piix_sata_probe (struct ata_port *ap) |
514 | { | 513 | { |
515 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | 514 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); |
516 | int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); | 515 | const unsigned int *map = ap->host_set->private_data; |
517 | int orig_mask, mask, i; | 516 | int base = 2 * ap->hard_port_no; |
517 | unsigned int present_mask = 0; | ||
518 | int port, i; | ||
518 | u8 pcs; | 519 | u8 pcs; |
519 | 520 | ||
520 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); | 521 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); |
521 | orig_mask = (int) pcs & 0xff; | 522 | DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); |
522 | |||
523 | /* TODO: this is vaguely wrong for ICH6 combined mode, | ||
524 | * where only two of the four SATA ports are mapped | ||
525 | * onto a single ATA channel. It is also vaguely inaccurate | ||
526 | * for ICH5, which has only two ports. However, this is ok, | ||
527 | * as further device presence detection code will handle | ||
528 | * any false positives produced here. | ||
529 | */ | ||
530 | 523 | ||
531 | for (i = 0; i < 4; i++) { | 524 | /* enable all ports on this ap and wait for them to settle */ |
532 | mask = (PIIX_PORT_ENABLED << i); | 525 | for (i = 0; i < 2; i++) { |
526 | port = map[base + i]; | ||
527 | if (port >= 0) | ||
528 | pcs |= 1 << port; | ||
529 | } | ||
533 | 530 | ||
534 | if ((orig_mask & mask) == mask) | 531 | pci_write_config_byte(pdev, ICH5_PCS, pcs); |
535 | if (combined || (i == ap->hard_port_no)) | 532 | msleep(100); |
536 | return 1; | 533 | |
534 | /* let's see which devices are present */ | ||
535 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); | ||
536 | |||
537 | for (i = 0; i < 2; i++) { | ||
538 | port = map[base + i]; | ||
539 | if (port < 0) | ||
540 | continue; | ||
541 | if (ap->flags & PIIX_FLAG_IGN_PRESENT || pcs & 1 << (4 + port)) | ||
542 | present_mask |= 1 << i; | ||
543 | else | ||
544 | pcs &= ~(1 << port); | ||
537 | } | 545 | } |
538 | 546 | ||
539 | return 0; | 547 | /* disable offline ports on non-AHCI controllers */ |
548 | if (!(ap->flags & PIIX_FLAG_AHCI)) | ||
549 | pci_write_config_byte(pdev, ICH5_PCS, pcs); | ||
550 | |||
551 | DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", | ||
552 | ap->id, pcs, present_mask); | ||
553 | |||
554 | return present_mask; | ||
540 | } | 555 | } |
541 | 556 | ||
542 | /** | 557 | /** |