diff options
Diffstat (limited to 'drivers/ata/pata_serverworks.c')
-rw-r--r-- | drivers/ata/pata_serverworks.c | 127 |
1 files changed, 42 insertions, 85 deletions
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 86dd714e3e1d..71eaf385e970 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c | |||
@@ -58,31 +58,15 @@ static const char *csb_bad_ata100[] = { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | /** | 60 | /** |
61 | * dell_cable - Dell serverworks cable detection | 61 | * oem_cable - Dell/Sun serverworks cable detection |
62 | * @ap: ATA port to do cable detect | 62 | * @ap: ATA port to do cable detect |
63 | * | 63 | * |
64 | * Dell hide the 40/80 pin select for their interfaces in the top two | 64 | * Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select |
65 | * bits of the subsystem ID. | 65 | * for their interfaces in the top two bits of the subsystem ID. |
66 | */ | 66 | */ |
67 | 67 | ||
68 | static int dell_cable(struct ata_port *ap) { | 68 | static int oem_cable(struct ata_port *ap) |
69 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 69 | { |
70 | |||
71 | if (pdev->subsystem_device & (1 << (ap->port_no + 14))) | ||
72 | return ATA_CBL_PATA80; | ||
73 | return ATA_CBL_PATA40; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * sun_cable - Sun Cobalt 'Alpine' cable detection | ||
78 | * @ap: ATA port to do cable select | ||
79 | * | ||
80 | * Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the | ||
81 | * subsystem ID the same as dell. We could use one function but we may | ||
82 | * need to extend the Dell one in future | ||
83 | */ | ||
84 | |||
85 | static int sun_cable(struct ata_port *ap) { | ||
86 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 70 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
87 | 71 | ||
88 | if (pdev->subsystem_device & (1 << (ap->port_no + 14))) | 72 | if (pdev->subsystem_device & (1 << (ap->port_no + 14))) |
@@ -90,49 +74,21 @@ static int sun_cable(struct ata_port *ap) { | |||
90 | return ATA_CBL_PATA40; | 74 | return ATA_CBL_PATA40; |
91 | } | 75 | } |
92 | 76 | ||
93 | /** | ||
94 | * osb4_cable - OSB4 cable detect | ||
95 | * @ap: ATA port to check | ||
96 | * | ||
97 | * The OSB4 isn't UDMA66 capable so this is easy | ||
98 | */ | ||
99 | |||
100 | static int osb4_cable(struct ata_port *ap) { | ||
101 | return ATA_CBL_PATA40; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * csb_cable - CSB5/6 cable detect | ||
106 | * @ap: ATA port to check | ||
107 | * | ||
108 | * Serverworks default arrangement is to use the drive side detection | ||
109 | * only. | ||
110 | */ | ||
111 | |||
112 | static int csb_cable(struct ata_port *ap) { | ||
113 | return ATA_CBL_PATA_UNK; | ||
114 | } | ||
115 | |||
116 | struct sv_cable_table { | 77 | struct sv_cable_table { |
117 | int device; | 78 | int device; |
118 | int subvendor; | 79 | int subvendor; |
119 | int (*cable_detect)(struct ata_port *ap); | 80 | int (*cable_detect)(struct ata_port *ap); |
120 | }; | 81 | }; |
121 | 82 | ||
122 | /* | ||
123 | * Note that we don't copy the old serverworks code because the old | ||
124 | * code contains obvious mistakes | ||
125 | */ | ||
126 | |||
127 | static struct sv_cable_table cable_detect[] = { | 83 | static struct sv_cable_table cable_detect[] = { |
128 | { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable }, | 84 | { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, oem_cable }, |
129 | { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable }, | 85 | { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, oem_cable }, |
130 | { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, sun_cable }, | 86 | { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, oem_cable }, |
131 | { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable }, | 87 | { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, ata_cable_40wire }, |
132 | { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable }, | 88 | { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, ata_cable_unknown }, |
133 | { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable }, | 89 | { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, ata_cable_unknown }, |
134 | { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable }, | 90 | { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, ata_cable_unknown }, |
135 | { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable }, | 91 | { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown }, |
136 | { } | 92 | { } |
137 | }; | 93 | }; |
138 | 94 | ||
@@ -393,6 +349,31 @@ static void serverworks_fixup_ht1000(struct pci_dev *pdev) | |||
393 | pci_write_config_byte(pdev, 0x5A, btr); | 349 | pci_write_config_byte(pdev, 0x5A, btr); |
394 | } | 350 | } |
395 | 351 | ||
352 | static int serverworks_fixup(struct pci_dev *pdev) | ||
353 | { | ||
354 | int rc = 0; | ||
355 | |||
356 | /* Force master latency timer to 64 PCI clocks */ | ||
357 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); | ||
358 | |||
359 | switch (pdev->device) { | ||
360 | case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: | ||
361 | rc = serverworks_fixup_osb4(pdev); | ||
362 | break; | ||
363 | case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: | ||
364 | ata_pci_bmdma_clear_simplex(pdev); | ||
365 | /* fall through */ | ||
366 | case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: | ||
367 | case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: | ||
368 | rc = serverworks_fixup_csb(pdev); | ||
369 | break; | ||
370 | case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: | ||
371 | serverworks_fixup_ht1000(pdev); | ||
372 | break; | ||
373 | } | ||
374 | |||
375 | return rc; | ||
376 | } | ||
396 | 377 | ||
397 | static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 378 | static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
398 | { | 379 | { |
@@ -430,13 +411,12 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id | |||
430 | if (rc) | 411 | if (rc) |
431 | return rc; | 412 | return rc; |
432 | 413 | ||
433 | /* Force master latency timer to 64 PCI clocks */ | 414 | rc = serverworks_fixup(pdev); |
434 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); | ||
435 | 415 | ||
436 | /* OSB4 : South Bridge and IDE */ | 416 | /* OSB4 : South Bridge and IDE */ |
437 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { | 417 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { |
438 | /* Select non UDMA capable OSB4 if we can't do fixups */ | 418 | /* Select non UDMA capable OSB4 if we can't do fixups */ |
439 | if ( serverworks_fixup_osb4(pdev) < 0) | 419 | if (rc < 0) |
440 | ppi[0] = &info[1]; | 420 | ppi[0] = &info[1]; |
441 | } | 421 | } |
442 | /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ | 422 | /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ |
@@ -446,19 +426,13 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id | |||
446 | 426 | ||
447 | /* If the returned btr is the newer revision then | 427 | /* If the returned btr is the newer revision then |
448 | select the right info block */ | 428 | select the right info block */ |
449 | if (serverworks_fixup_csb(pdev) == 3) | 429 | if (rc == 3) |
450 | ppi[0] = &info[3]; | 430 | ppi[0] = &info[3]; |
451 | 431 | ||
452 | /* Is this the 3rd channel CSB6 IDE ? */ | 432 | /* Is this the 3rd channel CSB6 IDE ? */ |
453 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) | 433 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) |
454 | ppi[1] = &ata_dummy_port_info; | 434 | ppi[1] = &ata_dummy_port_info; |
455 | } | 435 | } |
456 | /* setup HT1000E */ | ||
457 | else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) | ||
458 | serverworks_fixup_ht1000(pdev); | ||
459 | |||
460 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) | ||
461 | ata_pci_bmdma_clear_simplex(pdev); | ||
462 | 436 | ||
463 | return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0); | 437 | return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0); |
464 | } | 438 | } |
@@ -473,24 +447,7 @@ static int serverworks_reinit_one(struct pci_dev *pdev) | |||
473 | if (rc) | 447 | if (rc) |
474 | return rc; | 448 | return rc; |
475 | 449 | ||
476 | /* Force master latency timer to 64 PCI clocks */ | 450 | (void)serverworks_fixup(pdev); |
477 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); | ||
478 | |||
479 | switch (pdev->device) { | ||
480 | case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: | ||
481 | serverworks_fixup_osb4(pdev); | ||
482 | break; | ||
483 | case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: | ||
484 | ata_pci_bmdma_clear_simplex(pdev); | ||
485 | /* fall through */ | ||
486 | case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: | ||
487 | case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: | ||
488 | serverworks_fixup_csb(pdev); | ||
489 | break; | ||
490 | case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: | ||
491 | serverworks_fixup_ht1000(pdev); | ||
492 | break; | ||
493 | } | ||
494 | 451 | ||
495 | ata_host_resume(host); | 452 | ata_host_resume(host); |
496 | return 0; | 453 | return 0; |