summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ahci.c80
-rw-r--r--drivers/scsi/sata_promise.c26
-rw-r--r--drivers/scsi/sata_svw.c25
3 files changed, 108 insertions, 23 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index fc5263c6b102..1799233dcf9f 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -39,7 +39,7 @@
#include <asm/io.h>
#define DRV_NAME "ahci"
-#define DRV_VERSION "1.00"
+#define DRV_VERSION "1.01"
enum {
@@ -134,6 +134,9 @@ enum {
PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
+
+ /* hpriv->flags bits */
+ AHCI_FLAG_MSI = (1 << 0),
};
struct ahci_cmd_hdr {
@@ -183,6 +186,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
static u8 ahci_check_err(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+static void ahci_remove_one (struct pci_dev *pdev);
static Scsi_Host_Template ahci_sht = {
.module = THIS_MODULE,
@@ -272,7 +276,7 @@ static struct pci_driver ahci_pci_driver = {
.name = DRV_NAME,
.id_table = ahci_pci_tbl,
.probe = ahci_init_one,
- .remove = ata_pci_remove_one,
+ .remove = ahci_remove_one,
};
@@ -795,8 +799,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
return rc;
}
}
-
- hpriv->flags |= HOST_CAP_64;
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
@@ -879,15 +881,19 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
}
/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
+static void pci_intx(struct pci_dev *pdev, int enable)
{
- u16 pci_command;
+ u16 pci_command, new;
pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+
+ if (enable)
+ new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+ else
+ new = pci_command | PCI_COMMAND_INTX_DISABLE;
+
+ if (new != pci_command)
pci_write_config_word(pdev, PCI_COMMAND, pci_command);
- }
}
static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@ -969,7 +975,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
unsigned long base;
void *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
- int pci_dev_busy = 0;
+ int have_msi, pci_dev_busy = 0;
int rc;
VPRINTK("ENTER\n");
@@ -987,12 +993,17 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out;
}
- pci_enable_intx(pdev);
+ if (pci_enable_msi(pdev) == 0)
+ have_msi = 1;
+ else {
+ pci_intx(pdev, 1);
+ have_msi = 0;
+ }
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
- goto err_out_regions;
+ goto err_out_msi;
}
memset(probe_ent, 0, sizeof(*probe_ent));
@@ -1025,6 +1036,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->mmio_base = mmio_base;
probe_ent->private_data = hpriv;
+ if (have_msi)
+ hpriv->flags |= AHCI_FLAG_MSI;
+
/* initialize adapter */
rc = ahci_host_init(probe_ent);
if (rc)
@@ -1044,7 +1058,11 @@ err_out_iounmap:
iounmap(mmio_base);
err_out_free_ent:
kfree(probe_ent);
-err_out_regions:
+err_out_msi:
+ if (have_msi)
+ pci_disable_msi(pdev);
+ else
+ pci_intx(pdev, 0);
pci_release_regions(pdev);
err_out:
if (!pci_dev_busy)
@@ -1052,6 +1070,42 @@ err_out:
return rc;
}
+static void ahci_remove_one (struct pci_dev *pdev)
+{
+ struct device *dev = pci_dev_to_dev(pdev);
+ struct ata_host_set *host_set = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host_set->private_data;
+ struct ata_port *ap;
+ unsigned int i;
+ int have_msi;
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ ap = host_set->ports[i];
+
+ scsi_remove_host(ap->host);
+ }
+
+ have_msi = hpriv->flags & AHCI_FLAG_MSI;
+ free_irq(host_set->irq, host_set);
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ ap = host_set->ports[i];
+
+ ata_scsi_release(ap->host);
+ scsi_host_put(ap->host);
+ }
+
+ host_set->ops->host_stop(host_set);
+ kfree(host_set);
+
+ if (have_msi)
+ pci_disable_msi(pdev);
+ else
+ pci_intx(pdev, 0);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ dev_set_drvdata(dev, NULL);
+}
static int __init ahci_init(void)
{
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index b18c90582e67..5c1d4411457a 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -59,6 +59,7 @@ enum {
board_2037x = 0, /* FastTrak S150 TX2plus */
board_20319 = 1, /* FastTrak S150 TX4 */
+ board_20619 = 2, /* FastTrak TX4000 */
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
@@ -147,6 +148,17 @@ static struct ata_port_info pdc_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_ata_ops,
},
+
+ /* board_20619 */
+ {
+ .sht = &pdc_ata_sht,
+ .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+ ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_ata_ops,
+ },
};
static struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -172,6 +184,9 @@ static struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
+ { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20619 },
+
{ } /* terminate list */
};
@@ -636,6 +651,15 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
case board_2037x:
probe_ent->n_ports = 2;
break;
+ case board_20619:
+ probe_ent->n_ports = 4;
+
+ pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+ pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
+
+ probe_ent->port[2].scr_addr = base + 0x600;
+ probe_ent->port[3].scr_addr = base + 0x700;
+ break;
default:
BUG();
break;
@@ -676,7 +700,7 @@ static void __exit pdc_ata_exit(void)
MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver");
+MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index edef1fa969fc..189744887628 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -344,6 +344,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
void *mmio_base;
int pci_dev_busy = 0;
int rc;
+ int i;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -421,11 +422,11 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->mwdma_mask = 0x7;
probe_ent->udma_mask = 0x7f;
- /* We have 4 ports per PCI function */
- k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET);
- k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET);
- k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET);
- k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET);
+ /* different controllers have different number of ports - currently 4 or 8 */
+ /* All ports are on the same function. Multi-function device is no
+ * longer available. This should not be seen in any system. */
+ for (i = 0; i < ent->driver_data; i++)
+ k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
pci_set_master(pdev);
@@ -445,11 +446,17 @@ err_out:
return rc;
}
-
+/* 0x240 is device ID for Apple K2 device
+ * 0x241 is device ID for Serverworks Frodo4
+ * 0x242 is device ID for Serverworks Frodo8
+ * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
+ * controller
+ * */
static struct pci_device_id k2_sata_pci_tbl[] = {
- { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ }
};
OpenPOWER on IntegriCloud