aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_serverworks.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/pata_serverworks.c')
-rw-r--r--drivers/ata/pata_serverworks.c127
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
68static int dell_cable(struct ata_port *ap) { 68static 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
85static 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
100static 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
112static int csb_cable(struct ata_port *ap) {
113 return ATA_CBL_PATA_UNK;
114}
115
116struct sv_cable_table { 77struct 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
127static struct sv_cable_table cable_detect[] = { 83static 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
352static 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
397static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 378static 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;