diff options
Diffstat (limited to 'drivers/ata/pata_via.c')
-rw-r--r-- | drivers/ata/pata_via.c | 56 |
1 files changed, 44 insertions, 12 deletions
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 88984b803d6d..0d97890af681 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c | |||
@@ -303,14 +303,21 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mo | |||
303 | } | 303 | } |
304 | 304 | ||
305 | /* Set UDMA unless device is not UDMA capable */ | 305 | /* Set UDMA unless device is not UDMA capable */ |
306 | if (udma_type && t.udma) { | 306 | if (udma_type) { |
307 | u8 cable80_status; | 307 | u8 udma_etc; |
308 | 308 | ||
309 | /* Get 80-wire cable detection bit */ | 309 | pci_read_config_byte(pdev, 0x50 + offset, &udma_etc); |
310 | pci_read_config_byte(pdev, 0x50 + offset, &cable80_status); | ||
311 | cable80_status &= 0x10; | ||
312 | 310 | ||
313 | pci_write_config_byte(pdev, 0x50 + offset, ut | cable80_status); | 311 | /* clear transfer mode bit */ |
312 | udma_etc &= ~0x20; | ||
313 | |||
314 | if (t.udma) { | ||
315 | /* preserve 80-wire cable detection bit */ | ||
316 | udma_etc &= 0x10; | ||
317 | udma_etc |= ut; | ||
318 | } | ||
319 | |||
320 | pci_write_config_byte(pdev, 0x50 + offset, udma_etc); | ||
314 | } | 321 | } |
315 | } | 322 | } |
316 | 323 | ||
@@ -337,6 +344,32 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
337 | } | 344 | } |
338 | 345 | ||
339 | /** | 346 | /** |
347 | * via_mode_filter - filter buggy device/mode pairs | ||
348 | * @dev: ATA device | ||
349 | * @mask: Mode bitmask | ||
350 | * | ||
351 | * We need to apply some minimal filtering for old controllers and at least | ||
352 | * one breed of Transcend SSD. Return the updated mask. | ||
353 | */ | ||
354 | |||
355 | static unsigned long via_mode_filter(struct ata_device *dev, unsigned long mask) | ||
356 | { | ||
357 | struct ata_host *host = dev->link->ap->host; | ||
358 | const struct via_isa_bridge *config = host->private_data; | ||
359 | unsigned char model_num[ATA_ID_PROD_LEN + 1]; | ||
360 | |||
361 | if (config->id == PCI_DEVICE_ID_VIA_82C586_0) { | ||
362 | ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); | ||
363 | if (strcmp(model_num, "TS64GSSD25-M") == 0) { | ||
364 | ata_dev_printk(dev, KERN_WARNING, | ||
365 | "disabling UDMA mode due to reported lockups with this device.\n"); | ||
366 | mask &= ~ ATA_MASK_UDMA; | ||
367 | } | ||
368 | } | ||
369 | return ata_bmdma_mode_filter(dev, mask); | ||
370 | } | ||
371 | |||
372 | /** | ||
340 | * via_tf_load - send taskfile registers to host controller | 373 | * via_tf_load - send taskfile registers to host controller |
341 | * @ap: Port to which output is sent | 374 | * @ap: Port to which output is sent |
342 | * @tf: ATA taskfile register set | 375 | * @tf: ATA taskfile register set |
@@ -427,6 +460,7 @@ static struct ata_port_operations via_port_ops = { | |||
427 | .prereset = via_pre_reset, | 460 | .prereset = via_pre_reset, |
428 | .sff_tf_load = via_tf_load, | 461 | .sff_tf_load = via_tf_load, |
429 | .port_start = via_port_start, | 462 | .port_start = via_port_start, |
463 | .mode_filter = via_mode_filter, | ||
430 | }; | 464 | }; |
431 | 465 | ||
432 | static struct ata_port_operations via_port_ops_noirq = { | 466 | static struct ata_port_operations via_port_ops_noirq = { |
@@ -526,7 +560,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
526 | .port_ops = &via_port_ops | 560 | .port_ops = &via_port_ops |
527 | }; | 561 | }; |
528 | const struct ata_port_info *ppi[] = { NULL, NULL }; | 562 | const struct ata_port_info *ppi[] = { NULL, NULL }; |
529 | struct pci_dev *isa = NULL; | 563 | struct pci_dev *isa; |
530 | const struct via_isa_bridge *config; | 564 | const struct via_isa_bridge *config; |
531 | static int printed_version; | 565 | static int printed_version; |
532 | u8 enable; | 566 | u8 enable; |
@@ -551,15 +585,13 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
551 | if ((isa = pci_get_device(PCI_VENDOR_ID_VIA + | 585 | if ((isa = pci_get_device(PCI_VENDOR_ID_VIA + |
552 | !!(config->flags & VIA_BAD_ID), | 586 | !!(config->flags & VIA_BAD_ID), |
553 | config->id, NULL))) { | 587 | config->id, NULL))) { |
588 | u8 rev = isa->revision; | ||
589 | pci_dev_put(isa); | ||
554 | 590 | ||
555 | if (isa->revision >= config->rev_min && | 591 | if (rev >= config->rev_min && rev <= config->rev_max) |
556 | isa->revision <= config->rev_max) | ||
557 | break; | 592 | break; |
558 | pci_dev_put(isa); | ||
559 | } | 593 | } |
560 | 594 | ||
561 | pci_dev_put(isa); | ||
562 | |||
563 | if (!(config->flags & VIA_NO_ENABLES)) { | 595 | if (!(config->flags & VIA_NO_ENABLES)) { |
564 | /* 0x40 low bits indicate enabled channels */ | 596 | /* 0x40 low bits indicate enabled channels */ |
565 | pci_read_config_byte(pdev, 0x40 , &enable); | 597 | pci_read_config_byte(pdev, 0x40 , &enable); |