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.c140
1 files changed, 53 insertions, 87 deletions
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 86dd714..5929dde 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -58,31 +58,15 @@ static const char *csb_bad_ata100[] = {
};
/**
- * dell_cable - Dell serverworks cable detection
+ * oem_cable - Dell/Sun serverworks cable detection
* @ap: ATA port to do cable detect
*
- * Dell hide the 40/80 pin select for their interfaces in the top two
- * bits of the subsystem ID.
+ * Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select
+ * for their interfaces in the top two bits of the subsystem ID.
*/
-static int dell_cable(struct ata_port *ap) {
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
- if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
- return ATA_CBL_PATA80;
- return ATA_CBL_PATA40;
-}
-
-/**
- * sun_cable - Sun Cobalt 'Alpine' cable detection
- * @ap: ATA port to do cable select
- *
- * Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the
- * subsystem ID the same as dell. We could use one function but we may
- * need to extend the Dell one in future
- */
-
-static int sun_cable(struct ata_port *ap) {
+static int oem_cable(struct ata_port *ap)
+{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (pdev->subsystem_device & (1 << (ap->port_no + 14)))
@@ -90,49 +74,21 @@ static int sun_cable(struct ata_port *ap) {
return ATA_CBL_PATA40;
}
-/**
- * osb4_cable - OSB4 cable detect
- * @ap: ATA port to check
- *
- * The OSB4 isn't UDMA66 capable so this is easy
- */
-
-static int osb4_cable(struct ata_port *ap) {
- return ATA_CBL_PATA40;
-}
-
-/**
- * csb_cable - CSB5/6 cable detect
- * @ap: ATA port to check
- *
- * Serverworks default arrangement is to use the drive side detection
- * only.
- */
-
-static int csb_cable(struct ata_port *ap) {
- return ATA_CBL_PATA_UNK;
-}
-
struct sv_cable_table {
int device;
int subvendor;
int (*cable_detect)(struct ata_port *ap);
};
-/*
- * Note that we don't copy the old serverworks code because the old
- * code contains obvious mistakes
- */
-
static struct sv_cable_table cable_detect[] = {
- { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, sun_cable },
- { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable },
- { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable },
- { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, oem_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, oem_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, oem_cable },
+ { PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, ata_cable_40wire },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, ata_cable_unknown },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, ata_cable_unknown },
+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, ata_cable_unknown },
+ { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown },
{ }
};
@@ -296,12 +252,18 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev
pci_write_config_byte(pdev, 0x54, ultra_cfg);
}
-static struct scsi_host_template serverworks_sht = {
+static struct scsi_host_template serverworks_osb4_sht = {
+ ATA_BMDMA_SHT(DRV_NAME),
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+};
+
+static struct scsi_host_template serverworks_csb_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
static struct ata_port_operations serverworks_osb4_port_ops = {
.inherits = &ata_bmdma_port_ops,
+ .qc_prep = ata_bmdma_dumb_qc_prep,
.cable_detect = serverworks_cable_detect,
.mode_filter = serverworks_osb4_filter,
.set_piomode = serverworks_set_piomode,
@@ -310,6 +272,7 @@ static struct ata_port_operations serverworks_osb4_port_ops = {
static struct ata_port_operations serverworks_csb_port_ops = {
.inherits = &serverworks_osb4_port_ops,
+ .qc_prep = ata_bmdma_qc_prep,
.mode_filter = serverworks_csb_filter,
};
@@ -393,6 +356,31 @@ static void serverworks_fixup_ht1000(struct pci_dev *pdev)
pci_write_config_byte(pdev, 0x5A, btr);
}
+static int serverworks_fixup(struct pci_dev *pdev)
+{
+ int rc = 0;
+
+ /* Force master latency timer to 64 PCI clocks */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
+ rc = serverworks_fixup_osb4(pdev);
+ break;
+ case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+ ata_pci_bmdma_clear_simplex(pdev);
+ /* fall through */
+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+ rc = serverworks_fixup_csb(pdev);
+ break;
+ case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
+ serverworks_fixup_ht1000(pdev);
+ break;
+ }
+
+ return rc;
+}
static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -424,20 +412,21 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
}
};
const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL };
+ struct scsi_host_template *sht = &serverworks_csb_sht;
int rc;
rc = pcim_enable_device(pdev);
if (rc)
return rc;
- /* Force master latency timer to 64 PCI clocks */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+ rc = serverworks_fixup(pdev);
/* OSB4 : South Bridge and IDE */
if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
/* Select non UDMA capable OSB4 if we can't do fixups */
- if ( serverworks_fixup_osb4(pdev) < 0)
+ if (rc < 0)
ppi[0] = &info[1];
+ sht = &serverworks_osb4_sht;
}
/* setup CSB5/CSB6 : South Bridge and IDE option RAID */
else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ||
@@ -446,21 +435,15 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
/* If the returned btr is the newer revision then
select the right info block */
- if (serverworks_fixup_csb(pdev) == 3)
+ if (rc == 3)
ppi[0] = &info[3];
/* Is this the 3rd channel CSB6 IDE ? */
if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)
ppi[1] = &ata_dummy_port_info;
}
- /* setup HT1000E */
- else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
- serverworks_fixup_ht1000(pdev);
- if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
- ata_pci_bmdma_clear_simplex(pdev);
-
- return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
+ return ata_pci_bmdma_init_one(pdev, ppi, sht, NULL, 0);
}
#ifdef CONFIG_PM
@@ -473,24 +456,7 @@ static int serverworks_reinit_one(struct pci_dev *pdev)
if (rc)
return rc;
- /* Force master latency timer to 64 PCI clocks */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
-
- switch (pdev->device) {
- case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
- serverworks_fixup_osb4(pdev);
- break;
- case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
- ata_pci_bmdma_clear_simplex(pdev);
- /* fall through */
- case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
- case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
- serverworks_fixup_csb(pdev);
- break;
- case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE:
- serverworks_fixup_ht1000(pdev);
- break;
- }
+ (void)serverworks_fixup(pdev);
ata_host_resume(host);
return 0;