diff options
Diffstat (limited to 'drivers/ata/pata_amd.c')
-rw-r--r-- | drivers/ata/pata_amd.c | 129 |
1 files changed, 93 insertions, 36 deletions
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index e71125a4bd9b..761a66608d7b 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c | |||
@@ -220,6 +220,62 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
220 | timing_setup(ap, adev, 0x40, adev->dma_mode, 4); | 220 | timing_setup(ap, adev, 0x40, adev->dma_mode, 4); |
221 | } | 221 | } |
222 | 222 | ||
223 | /* Both host-side and drive-side detection results are worthless on NV | ||
224 | * PATAs. Ignore them and just follow what BIOS configured. Both the | ||
225 | * current configuration in PCI config reg and ACPI GTM result are | ||
226 | * cached during driver attach and are consulted to select transfer | ||
227 | * mode. | ||
228 | */ | ||
229 | static unsigned long nv_mode_filter(struct ata_device *dev, | ||
230 | unsigned long xfer_mask) | ||
231 | { | ||
232 | static const unsigned int udma_mask_map[] = | ||
233 | { ATA_UDMA2, ATA_UDMA1, ATA_UDMA0, 0, | ||
234 | ATA_UDMA3, ATA_UDMA4, ATA_UDMA5, ATA_UDMA6 }; | ||
235 | struct ata_port *ap = dev->link->ap; | ||
236 | char acpi_str[32] = ""; | ||
237 | u32 saved_udma, udma; | ||
238 | const struct ata_acpi_gtm *gtm; | ||
239 | unsigned long bios_limit = 0, acpi_limit = 0, limit; | ||
240 | |||
241 | /* find out what BIOS configured */ | ||
242 | udma = saved_udma = (unsigned long)ap->host->private_data; | ||
243 | |||
244 | if (ap->port_no == 0) | ||
245 | udma >>= 16; | ||
246 | if (dev->devno == 0) | ||
247 | udma >>= 8; | ||
248 | |||
249 | if ((udma & 0xc0) == 0xc0) | ||
250 | bios_limit = ata_pack_xfermask(0, 0, udma_mask_map[udma & 0x7]); | ||
251 | |||
252 | /* consult ACPI GTM too */ | ||
253 | gtm = ata_acpi_init_gtm(ap); | ||
254 | if (gtm) { | ||
255 | acpi_limit = ata_acpi_gtm_xfermask(dev, gtm); | ||
256 | |||
257 | snprintf(acpi_str, sizeof(acpi_str), " (%u:%u:0x%x)", | ||
258 | gtm->drive[0].dma, gtm->drive[1].dma, gtm->flags); | ||
259 | } | ||
260 | |||
261 | /* be optimistic, EH can take care of things if something goes wrong */ | ||
262 | limit = bios_limit | acpi_limit; | ||
263 | |||
264 | /* If PIO or DMA isn't configured at all, don't limit. Let EH | ||
265 | * handle it. | ||
266 | */ | ||
267 | if (!(limit & ATA_MASK_PIO)) | ||
268 | limit |= ATA_MASK_PIO; | ||
269 | if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA))) | ||
270 | limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA; | ||
271 | |||
272 | ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, " | ||
273 | "BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n", | ||
274 | xfer_mask, limit, xfer_mask & limit, bios_limit, | ||
275 | saved_udma, acpi_limit, acpi_str); | ||
276 | |||
277 | return xfer_mask & limit; | ||
278 | } | ||
223 | 279 | ||
224 | /** | 280 | /** |
225 | * nv_probe_init - cable detection | 281 | * nv_probe_init - cable detection |
@@ -252,32 +308,6 @@ static void nv_error_handler(struct ata_port *ap) | |||
252 | ata_std_postreset); | 308 | ata_std_postreset); |
253 | } | 309 | } |
254 | 310 | ||
255 | static int nv_cable_detect(struct ata_port *ap) | ||
256 | { | ||
257 | static const u8 bitmask[2] = {0x03, 0x0C}; | ||
258 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
259 | u8 ata66; | ||
260 | u16 udma; | ||
261 | int cbl; | ||
262 | |||
263 | pci_read_config_byte(pdev, 0x52, &ata66); | ||
264 | if (ata66 & bitmask[ap->port_no]) | ||
265 | cbl = ATA_CBL_PATA80; | ||
266 | else | ||
267 | cbl = ATA_CBL_PATA40; | ||
268 | |||
269 | /* We now have to double check because the Nvidia boxes BIOS | ||
270 | doesn't always set the cable bits but does set mode bits */ | ||
271 | pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma); | ||
272 | if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400) | ||
273 | cbl = ATA_CBL_PATA80; | ||
274 | /* And a triple check across suspend/resume with ACPI around */ | ||
275 | if (ata_acpi_init_gtm(ap) && | ||
276 | ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap))) | ||
277 | cbl = ATA_CBL_PATA80; | ||
278 | return cbl; | ||
279 | } | ||
280 | |||
281 | /** | 311 | /** |
282 | * nv100_set_piomode - set initial PIO mode data | 312 | * nv100_set_piomode - set initial PIO mode data |
283 | * @ap: ATA interface | 313 | * @ap: ATA interface |
@@ -315,6 +345,14 @@ static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
315 | timing_setup(ap, adev, 0x50, adev->dma_mode, 4); | 345 | timing_setup(ap, adev, 0x50, adev->dma_mode, 4); |
316 | } | 346 | } |
317 | 347 | ||
348 | static void nv_host_stop(struct ata_host *host) | ||
349 | { | ||
350 | u32 udma = (unsigned long)host->private_data; | ||
351 | |||
352 | /* restore PCI config register 0x60 */ | ||
353 | pci_write_config_dword(to_pci_dev(host->dev), 0x60, udma); | ||
354 | } | ||
355 | |||
318 | static struct scsi_host_template amd_sht = { | 356 | static struct scsi_host_template amd_sht = { |
319 | .module = THIS_MODULE, | 357 | .module = THIS_MODULE, |
320 | .name = DRV_NAME, | 358 | .name = DRV_NAME, |
@@ -479,7 +517,8 @@ static struct ata_port_operations nv100_port_ops = { | |||
479 | .thaw = ata_bmdma_thaw, | 517 | .thaw = ata_bmdma_thaw, |
480 | .error_handler = nv_error_handler, | 518 | .error_handler = nv_error_handler, |
481 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 519 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
482 | .cable_detect = nv_cable_detect, | 520 | .cable_detect = ata_cable_ignore, |
521 | .mode_filter = nv_mode_filter, | ||
483 | 522 | ||
484 | .bmdma_setup = ata_bmdma_setup, | 523 | .bmdma_setup = ata_bmdma_setup, |
485 | .bmdma_start = ata_bmdma_start, | 524 | .bmdma_start = ata_bmdma_start, |
@@ -496,6 +535,7 @@ static struct ata_port_operations nv100_port_ops = { | |||
496 | .irq_on = ata_irq_on, | 535 | .irq_on = ata_irq_on, |
497 | 536 | ||
498 | .port_start = ata_sff_port_start, | 537 | .port_start = ata_sff_port_start, |
538 | .host_stop = nv_host_stop, | ||
499 | }; | 539 | }; |
500 | 540 | ||
501 | static struct ata_port_operations nv133_port_ops = { | 541 | static struct ata_port_operations nv133_port_ops = { |
@@ -512,7 +552,8 @@ static struct ata_port_operations nv133_port_ops = { | |||
512 | .thaw = ata_bmdma_thaw, | 552 | .thaw = ata_bmdma_thaw, |
513 | .error_handler = nv_error_handler, | 553 | .error_handler = nv_error_handler, |
514 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 554 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
515 | .cable_detect = nv_cable_detect, | 555 | .cable_detect = ata_cable_ignore, |
556 | .mode_filter = nv_mode_filter, | ||
516 | 557 | ||
517 | .bmdma_setup = ata_bmdma_setup, | 558 | .bmdma_setup = ata_bmdma_setup, |
518 | .bmdma_start = ata_bmdma_start, | 559 | .bmdma_start = ata_bmdma_start, |
@@ -529,6 +570,7 @@ static struct ata_port_operations nv133_port_ops = { | |||
529 | .irq_on = ata_irq_on, | 570 | .irq_on = ata_irq_on, |
530 | 571 | ||
531 | .port_start = ata_sff_port_start, | 572 | .port_start = ata_sff_port_start, |
573 | .host_stop = nv_host_stop, | ||
532 | }; | 574 | }; |
533 | 575 | ||
534 | static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 576 | static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
@@ -615,7 +657,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
615 | .port_ops = &amd100_port_ops | 657 | .port_ops = &amd100_port_ops |
616 | } | 658 | } |
617 | }; | 659 | }; |
618 | const struct ata_port_info *ppi[] = { NULL, NULL }; | 660 | struct ata_port_info pi; |
661 | const struct ata_port_info *ppi[] = { &pi, NULL }; | ||
619 | static int printed_version; | 662 | static int printed_version; |
620 | int type = id->driver_data; | 663 | int type = id->driver_data; |
621 | u8 fifo; | 664 | u8 fifo; |
@@ -629,6 +672,19 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
629 | if (type == 1 && pdev->revision > 0x7) | 672 | if (type == 1 && pdev->revision > 0x7) |
630 | type = 2; | 673 | type = 2; |
631 | 674 | ||
675 | /* Serenade ? */ | ||
676 | if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD && | ||
677 | pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE) | ||
678 | type = 6; /* UDMA 100 only */ | ||
679 | |||
680 | /* | ||
681 | * Okay, type is determined now. Apply type-specific workarounds. | ||
682 | */ | ||
683 | pi = info[type]; | ||
684 | |||
685 | if (type < 3) | ||
686 | ata_pci_clear_simplex(pdev); | ||
687 | |||
632 | /* Check for AMD7411 */ | 688 | /* Check for AMD7411 */ |
633 | if (type == 3) | 689 | if (type == 3) |
634 | /* FIFO is broken */ | 690 | /* FIFO is broken */ |
@@ -636,16 +692,17 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
636 | else | 692 | else |
637 | pci_write_config_byte(pdev, 0x41, fifo | 0xF0); | 693 | pci_write_config_byte(pdev, 0x41, fifo | 0xF0); |
638 | 694 | ||
639 | /* Serenade ? */ | 695 | /* Cable detection on Nvidia chips doesn't work too well, |
640 | if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD && | 696 | * cache BIOS programmed UDMA mode. |
641 | pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE) | 697 | */ |
642 | type = 6; /* UDMA 100 only */ | 698 | if (type == 7 || type == 8) { |
699 | u32 udma; | ||
643 | 700 | ||
644 | if (type < 3) | 701 | pci_read_config_dword(pdev, 0x60, &udma); |
645 | ata_pci_clear_simplex(pdev); | 702 | pi.private_data = (void *)(unsigned long)udma; |
703 | } | ||
646 | 704 | ||
647 | /* And fire it up */ | 705 | /* And fire it up */ |
648 | ppi[0] = &info[type]; | ||
649 | return ata_pci_init_one(pdev, ppi); | 706 | return ata_pci_init_one(pdev, ppi); |
650 | } | 707 | } |
651 | 708 | ||