diff options
Diffstat (limited to 'drivers/ata/pata_serverworks.c')
| -rw-r--r-- | drivers/ata/pata_serverworks.c | 147 | 
1 files changed, 46 insertions, 101 deletions
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 86dd714e3e1..fc5f31d4828 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -34,7 +34,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -58,31 +57,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 +73,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 },  	{ }  }; @@ -393,6 +348,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)  { @@ -430,13 +410,12 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id  	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];  	}  	/* setup CSB5/CSB6 : South Bridge and IDE option RAID */ @@ -446,51 +425,28 @@ 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);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int serverworks_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(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; @@ -512,27 +468,16 @@ static struct pci_driver serverworks_pci_driver = {  	.id_table	= serverworks,  	.probe 		= serverworks_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= serverworks_reinit_one,  #endif  }; -static int __init serverworks_init(void) -{ -	return pci_register_driver(&serverworks_pci_driver); -} - -static void __exit serverworks_exit(void) -{ -	pci_unregister_driver(&serverworks_pci_driver); -} +module_pci_driver(serverworks_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Serverworks OSB4/CSB5/CSB6");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, serverworks);  MODULE_VERSION(DRV_VERSION); - -module_init(serverworks_init); -module_exit(serverworks_exit);  | 
