aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-02-28 11:25:39 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-03 15:39:54 -0500
commitd133ecab8ff1233c2eb3ecb94f7956aa10002300 (patch)
treef4b508d49bd57d0e8a4e8e5d7975f7513f275413 /drivers
parentd33f58b883a3f624b9362227bf73fc52a6cbd4b4 (diff)
[PATCH] ata_piix: reimplement piix_sata_probe()
Reimplement piix_sata_probe() such that it turns on PCS enable bits on all avaliable ports and check present bits after a while to determine device presence. This should help broken BIOSes. After device presence detection is complete, PCS enable bits of unoccupied bits are turned off unless the controller supports AHCI (ICH6/7 docs mandate all enables bits are always set on AHCI capable controllers). Note that PCS present bits are ignored on 6300ESB as described in the datasheet. This should fix device detection problems reported with the controller. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ata_piix.c61
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 */
513static int piix_sata_probe (struct ata_port *ap) 512static 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/**