summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/stex.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/stex.c')
-rw-r--r--drivers/scsi/stex.c319
1 files changed, 245 insertions, 74 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 3cf3106a29b..ba6bcdaf2a6 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -11,8 +11,6 @@
* Written By:
* Ed Lin <promise_linux@promise.com>
*
- * Version: 2.9.0.13
- *
*/
#include <linux/init.h>
@@ -37,11 +35,11 @@
#include <scsi/scsi_tcq.h>
#define DRV_NAME "stex"
-#define ST_DRIVER_VERSION "2.9.0.13"
-#define ST_VER_MAJOR 2
-#define ST_VER_MINOR 9
+#define ST_DRIVER_VERSION "3.1.0.1"
+#define ST_VER_MAJOR 3
+#define ST_VER_MINOR 1
#define ST_OEM 0
-#define ST_BUILD_VER 13
+#define ST_BUILD_VER 1
enum {
/* MU register offset */
@@ -76,8 +74,10 @@ enum {
MU_STATE_STARTED = 4,
MU_STATE_RESETTING = 5,
- MU_MAX_DELAY_TIME = 240000,
+ MU_MAX_DELAY = 120,
MU_HANDSHAKE_SIGNATURE = 0x55aaaa55,
+ MU_HANDSHAKE_SIGNATURE_HALF = 0x5a5a0000,
+ MU_HARD_RESET_WAIT = 30000,
HMU_PARTNER_TYPE = 2,
/* firmware returned values */
@@ -120,12 +120,19 @@ enum {
st_shasta = 0,
st_vsc = 1,
+ st_vsc1 = 2,
+ st_yosemite = 3,
PASSTHRU_REQ_TYPE = 0x00000001,
PASSTHRU_REQ_NO_WAKEUP = 0x00000100,
ST_INTERNAL_TIMEOUT = 30,
+ ST_TO_CMD = 0,
+ ST_FROM_CMD = 1,
+
/* vendor specific commands of Promise */
+ MGT_CMD = 0xd8,
+ SINBAND_MGT_CMD = 0xd9,
ARRAY_CMD = 0xe0,
CONTROLLER_CMD = 0xe1,
DEBUGGING_CMD = 0xe2,
@@ -133,14 +140,50 @@ enum {
PASSTHRU_GET_ADAPTER = 0x05,
PASSTHRU_GET_DRVVER = 0x10,
+
+ CTLR_CONFIG_CMD = 0x03,
+ CTLR_SHUTDOWN = 0x0d,
+
CTLR_POWER_STATE_CHANGE = 0x0e,
CTLR_POWER_SAVING = 0x01,
PASSTHRU_SIGNATURE = 0x4e415041,
+ MGT_CMD_SIGNATURE = 0xba,
INQUIRY_EVPD = 0x01,
+
+ ST_ADDITIONAL_MEM = 0x200000,
};
+/* SCSI inquiry data */
+typedef struct st_inq {
+ u8 DeviceType :5;
+ u8 DeviceTypeQualifier :3;
+ u8 DeviceTypeModifier :7;
+ u8 RemovableMedia :1;
+ u8 Versions;
+ u8 ResponseDataFormat :4;
+ u8 HiSupport :1;
+ u8 NormACA :1;
+ u8 ReservedBit :1;
+ u8 AERC :1;
+ u8 AdditionalLength;
+ u8 Reserved[2];
+ u8 SoftReset :1;
+ u8 CommandQueue :1;
+ u8 Reserved2 :1;
+ u8 LinkedCommands :1;
+ u8 Synchronous :1;
+ u8 Wide16Bit :1;
+ u8 Wide32Bit :1;
+ u8 RelativeAddressing :1;
+ u8 VendorId[8];
+ u8 ProductId[16];
+ u8 ProductRevisionLevel[4];
+ u8 VendorSpecific[20];
+ u8 Reserved3[40];
+} ST_INQ;
+
struct st_sgitem {
u8 ctrl; /* SG_CF_xxx */
u8 reserved[3];
@@ -171,7 +214,9 @@ struct handshake_frame {
__le32 partner_ver_minor;
__le32 partner_ver_oem;
__le32 partner_ver_build;
- u32 reserved1[4];
+ __le32 extra_offset; /* NEW */
+ __le32 extra_size; /* NEW */
+ u32 reserved1[2];
};
struct req_msg {
@@ -181,7 +226,7 @@ struct req_msg {
u8 task_attr;
u8 task_manage;
u8 prd_entry;
- u8 payload_sz; /* payload size in 4-byte */
+ u8 payload_sz; /* payload size in 4-byte, not used */
u8 cdb[STEX_CDB_LENGTH];
u8 variable[REQ_VARIABLE_LEN];
};
@@ -242,7 +287,8 @@ struct st_drvver {
#define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg))
#define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg))
#define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE)
-#define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + sizeof(struct st_frame))
+#define STEX_EXTRA_SIZE max(sizeof(struct st_frame), sizeof(ST_INQ))
+#define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE)
struct st_ccb {
struct req_msg *req;
@@ -261,6 +307,7 @@ struct st_hba {
void __iomem *mmio_base; /* iomapped PCI memory space */
void *dma_mem;
dma_addr_t dma_handle;
+ size_t dma_size;
struct Scsi_Host *host;
struct pci_dev *pdev;
@@ -403,7 +450,7 @@ static int stex_map_sg(struct st_hba *hba,
}
static void stex_internal_copy(struct scsi_cmnd *cmd,
- const void *src, size_t *count, int sg_count)
+ const void *src, size_t *count, int sg_count, int direction)
{
size_t lcount;
size_t len;
@@ -427,7 +474,10 @@ static void stex_internal_copy(struct scsi_cmnd *cmd,
} else
d = cmd->request_buffer;
- memcpy(d, s, len);
+ if (direction == ST_TO_CMD)
+ memcpy(d, s, len);
+ else
+ memcpy(s, d, len);
lcount -= len;
if (cmd->use_sg)
@@ -449,7 +499,7 @@ static int stex_direct_copy(struct scsi_cmnd *cmd,
return 0;
}
- stex_internal_copy(cmd, src, &cp_len, n_elem);
+ stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
if (cmd->use_sg)
pci_unmap_sg(hba->pdev, cmd->request_buffer,
@@ -463,6 +513,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
size_t count = sizeof(struct st_frame);
p = hba->copy_buffer;
+ stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD);
memset(p->base, 0, sizeof(u32)*6);
*(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
p->rom_addr = 0;
@@ -480,7 +531,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
p->subid =
hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
- stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count);
+ stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_TO_CMD);
}
static void
@@ -489,7 +540,6 @@ stex_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
req->tag = cpu_to_le16(tag);
req->task_attr = TASK_ATTRIBUTE_SIMPLE;
req->task_manage = 0; /* not supported yet */
- req->payload_sz = (u8)(sizeof(struct req_msg)/sizeof(u32));
hba->ccb[tag].req = req;
hba->out_req_cnt++;
@@ -595,8 +645,14 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
return SCSI_MLQUEUE_HOST_BUSY;
req = stex_alloc_req(hba);
- req->lun = lun;
- req->target = id;
+
+ if (hba->cardtype == st_yosemite) {
+ req->lun = lun * (ST_MAX_TARGET_NUM - 1) + id;
+ req->target = 0;
+ } else {
+ req->lun = lun;
+ req->target = id;
+ }
/* cdb */
memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
@@ -680,7 +736,51 @@ static void stex_copy_data(struct st_ccb *ccb,
if (ccb->cmd == NULL)
return;
- stex_internal_copy(ccb->cmd, resp->variable, &count, ccb->sg_count);
+ stex_internal_copy(ccb->cmd,
+ resp->variable, &count, ccb->sg_count, ST_TO_CMD);
+}
+
+static void stex_ys_commands(struct st_hba *hba,
+ struct st_ccb *ccb, struct status_msg *resp)
+{
+ size_t count;
+
+ if (ccb->cmd->cmnd[0] == MGT_CMD &&
+ resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
+ ccb->cmd->request_bufflen =
+ le32_to_cpu(*(__le32 *)&resp->variable[0]);
+ return;
+ }
+
+ if (resp->srb_status != 0)
+ return;
+
+ /* determine inquiry command status by DeviceTypeQualifier */
+ if (ccb->cmd->cmnd[0] == INQUIRY &&
+ resp->scsi_status == SAM_STAT_GOOD) {
+ ST_INQ *inq_data;
+
+ count = STEX_EXTRA_SIZE;
+ stex_internal_copy(ccb->cmd, hba->copy_buffer,
+ &count, ccb->sg_count, ST_FROM_CMD);
+ inq_data = (ST_INQ *)hba->copy_buffer;
+ if (inq_data->DeviceTypeQualifier != 0)
+ ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
+ else
+ ccb->srb_status = SRB_STATUS_SUCCESS;
+ } else if (ccb->cmd->cmnd[0] == REPORT_LUNS) {
+ u8 *report_lun_data = (u8 *)hba->copy_buffer;
+
+ count = STEX_EXTRA_SIZE;
+ stex_internal_copy(ccb->cmd, report_lun_data,
+ &count, ccb->sg_count, ST_FROM_CMD);
+ if (report_lun_data[2] || report_lun_data[3]) {
+ report_lun_data[2] = 0x00;
+ report_lun_data[3] = 0x08;
+ stex_internal_copy(ccb->cmd, report_lun_data,
+ &count, ccb->sg_count, ST_TO_CMD);
+ }
+ }
}
static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
@@ -702,8 +802,17 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
return;
}
- if (unlikely(hba->mu_status != MU_STATE_STARTED ||
- hba->out_req_cnt <= 0)) {
+ /*
+ * it's not a valid status payload if:
+ * 1. there are no pending requests(e.g. during init stage)
+ * 2. there are some pending requests, but the controller is in
+ * reset status, and its type is not st_yosemite
+ * firmware of st_yosemite in reset status will return pending requests
+ * to driver, so we allow it to pass
+ */
+ if (unlikely(hba->out_req_cnt <= 0 ||
+ (hba->mu_status == MU_STATE_RESETTING &&
+ hba->cardtype != st_yosemite))) {
hba->status_tail = hba->status_head;
goto update_status;
}
@@ -723,6 +832,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
if (unlikely(ccb->req == NULL)) {
printk(KERN_WARNING DRV_NAME
"(%s): lagging req\n", pci_name(hba->pdev));
+ hba->out_req_cnt--;
continue;
}
@@ -741,9 +851,13 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
ccb->scsi_status = resp->scsi_status;
if (likely(ccb->cmd != NULL)) {
+ if (hba->cardtype == st_yosemite)
+ stex_ys_commands(hba, ccb, resp);
+
if (unlikely(ccb->cmd->cmnd[0] == PASSTHRU_CMD &&
ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
stex_controller_info(hba, ccb);
+
stex_unmap_sg(hba, ccb->cmd);
stex_scsi_done(ccb);
hba->out_req_cnt--;
@@ -764,7 +878,7 @@ update_status:
readl(base + IMR1); /* flush */
}
-static irqreturn_t stex_intr(int irq, void *__hba, struct pt_regs *regs)
+static irqreturn_t stex_intr(int irq, void *__hba)
{
struct st_hba *hba = __hba;
void __iomem *base = hba->mmio_base;
@@ -794,27 +908,34 @@ static int stex_handshake(struct st_hba *hba)
void __iomem *base = hba->mmio_base;
struct handshake_frame *h;
dma_addr_t status_phys;
- int i;
+ u32 data;
+ unsigned long before;
if (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) {
writel(MU_INBOUND_DOORBELL_HANDSHAKE, base + IDBL);
readl(base + IDBL);
- for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE
- && i < MU_MAX_DELAY_TIME; i++) {
+ before = jiffies;
+ while (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) {
+ if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): no handshake signature\n",
+ pci_name(hba->pdev));
+ return -1;
+ }
rmb();
msleep(1);
}
-
- if (i == MU_MAX_DELAY_TIME) {
- printk(KERN_ERR DRV_NAME
- "(%s): no handshake signature\n",
- pci_name(hba->pdev));
- return -1;
- }
}
udelay(10);
+ data = readl(base + OMR1);
+ if ((data & 0xffff0000) == MU_HANDSHAKE_SIGNATURE_HALF) {
+ data &= 0x0000ffff;
+ if (hba->host->can_queue > data)
+ hba->host->can_queue = data;
+ }
+
h = (struct handshake_frame *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
h->rb_phy = cpu_to_le32(hba->dma_handle);
h->rb_phy_hi = cpu_to_le32((hba->dma_handle >> 16) >> 16);
@@ -824,6 +945,11 @@ static int stex_handshake(struct st_hba *hba)
h->status_cnt = cpu_to_le16(MU_STATUS_COUNT);
stex_gettime(&h->hosttime);
h->partner_type = HMU_PARTNER_TYPE;
+ if (hba->dma_size > STEX_BUFFER_SIZE) {
+ h->extra_offset = cpu_to_le32(STEX_BUFFER_SIZE);
+ h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM);
+ } else
+ h->extra_offset = h->extra_size = 0;
status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE;
writel(status_phys, base + IMR0);
@@ -837,19 +963,18 @@ static int stex_handshake(struct st_hba *hba)
readl(base + IDBL); /* flush */
udelay(10);
- for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE
- && i < MU_MAX_DELAY_TIME; i++) {
+ before = jiffies;
+ while (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) {
+ if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): no signature after handshake frame\n",
+ pci_name(hba->pdev));
+ return -1;
+ }
rmb();
msleep(1);
}
- if (i == MU_MAX_DELAY_TIME) {
- printk(KERN_ERR DRV_NAME
- "(%s): no signature after handshake frame\n",
- pci_name(hba->pdev));
- return -1;
- }
-
writel(0, base + IMR0);
readl(base + IMR0);
writel(0, base + OMR0);
@@ -931,9 +1056,9 @@ static void stex_hard_reset(struct st_hba *hba)
pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
- for (i = 0; i < MU_MAX_DELAY_TIME; i++) {
+ for (i = 0; i < MU_HARD_RESET_WAIT; i++) {
pci_read_config_word(hba->pdev, PCI_COMMAND, &pci_cmd);
- if (pci_cmd & PCI_COMMAND_MASTER)
+ if (pci_cmd != 0xffff && (pci_cmd & PCI_COMMAND_MASTER))
break;
msleep(1);
}
@@ -948,6 +1073,7 @@ static int stex_reset(struct scsi_cmnd *cmd)
{
struct st_hba *hba;
unsigned long flags;
+ unsigned long before;
hba = (struct st_hba *) &cmd->device->host->hostdata[0];
hba->mu_status = MU_STATE_RESETTING;
@@ -955,38 +1081,55 @@ static int stex_reset(struct scsi_cmnd *cmd)
if (hba->cardtype == st_shasta)
stex_hard_reset(hba);
- if (stex_handshake(hba)) {
- printk(KERN_WARNING DRV_NAME
- "(%s): resetting: handshake failed\n",
- pci_name(hba->pdev));
- return FAILED;
+ if (hba->cardtype != st_yosemite) {
+ if (stex_handshake(hba)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): resetting: handshake failed\n",
+ pci_name(hba->pdev));
+ return FAILED;
+ }
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->req_head = 0;
+ hba->req_tail = 0;
+ hba->status_head = 0;
+ hba->status_tail = 0;
+ hba->out_req_cnt = 0;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ return SUCCESS;
+ }
+
+ /* st_yosemite */
+ writel(MU_INBOUND_DOORBELL_RESET, hba->mmio_base + IDBL);
+ readl(hba->mmio_base + IDBL); /* flush */
+ before = jiffies;
+ while (hba->out_req_cnt > 0) {
+ if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): reset timeout\n", pci_name(hba->pdev));
+ return FAILED;
+ }
+ msleep(1);
}
- spin_lock_irqsave(hba->host->host_lock, flags);
- hba->req_head = 0;
- hba->req_tail = 0;
- hba->status_head = 0;
- hba->status_tail = 0;
- hba->out_req_cnt = 0;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
+ hba->mu_status = MU_STATE_STARTED;
return SUCCESS;
}
static int stex_biosparam(struct scsi_device *sdev,
struct block_device *bdev, sector_t capacity, int geom[])
{
- int heads = 255, sectors = 63, cylinders;
+ int heads = 255, sectors = 63;
if (capacity < 0x200000) {
heads = 64;
sectors = 32;
}
- cylinders = sector_div(capacity, heads * sectors);
+ sector_div(capacity, heads * sectors);
geom[0] = heads;
geom[1] = sectors;
- geom[2] = cylinders;
+ geom[2] = capacity;
return 0;
}
@@ -1068,8 +1211,13 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_iounmap;
}
+ hba->cardtype = (unsigned int) id->driver_data;
+ if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1)
+ hba->cardtype = st_vsc1;
+ hba->dma_size = (hba->cardtype == st_vsc1) ?
+ (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE);
hba->dma_mem = dma_alloc_coherent(&pdev->dev,
- STEX_BUFFER_SIZE, &hba->dma_handle, GFP_KERNEL);
+ hba->dma_size, &hba->dma_handle, GFP_KERNEL);
if (!hba->dma_mem) {
err = -ENOMEM;
printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n",
@@ -1082,8 +1230,6 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE;
hba->mu_status = MU_STATE_STARTING;
- hba->cardtype = (unsigned int) id->driver_data;
-
/* firmware uses id/lun pair for a logical drive, but lun would be
always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use
channel to map lun here */
@@ -1108,7 +1254,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto out_free_irq;
- err = scsi_init_shared_tag_map(host, ST_CAN_QUEUE);
+ err = scsi_init_shared_tag_map(host, host->can_queue);
if (err) {
printk(KERN_ERR DRV_NAME "(%s): init shared queue failed\n",
pci_name(pdev));
@@ -1131,7 +1277,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_free_irq:
free_irq(pdev->irq, hba);
out_pci_free:
- dma_free_coherent(&pdev->dev, STEX_BUFFER_SIZE,
+ dma_free_coherent(&pdev->dev, hba->dma_size,
hba->dma_mem, hba->dma_handle);
out_iounmap:
iounmap(hba->mmio_base);
@@ -1156,9 +1302,16 @@ static void stex_hba_stop(struct st_hba *hba)
req = stex_alloc_req(hba);
memset(req->cdb, 0, STEX_CDB_LENGTH);
- req->cdb[0] = CONTROLLER_CMD;
- req->cdb[1] = CTLR_POWER_STATE_CHANGE;
- req->cdb[2] = CTLR_POWER_SAVING;
+ if (hba->cardtype == st_yosemite) {
+ req->cdb[0] = MGT_CMD;
+ req->cdb[1] = MGT_CMD_SIGNATURE;
+ req->cdb[2] = CTLR_CONFIG_CMD;
+ req->cdb[3] = CTLR_SHUTDOWN;
+ } else {
+ req->cdb[0] = CONTROLLER_CMD;
+ req->cdb[1] = CTLR_POWER_STATE_CHANGE;
+ req->cdb[2] = CTLR_POWER_SAVING;
+ }
hba->ccb[tag].cmd = NULL;
hba->ccb[tag].sg_count = 0;
@@ -1185,7 +1338,7 @@ static void stex_hba_free(struct st_hba *hba)
pci_release_regions(hba->pdev);
- dma_free_coherent(&hba->pdev->dev, STEX_BUFFER_SIZE,
+ dma_free_coherent(&hba->pdev->dev, hba->dma_size,
hba->dma_mem, hba->dma_handle);
}
@@ -1214,14 +1367,32 @@ static void stex_shutdown(struct pci_dev *pdev)
}
static struct pci_device_id stex_pci_tbl[] = {
- { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x105a, 0xf350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x105a, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x105a, 0x8301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x105a, 0x8302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta },
- { 0x1725, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc },
+ /* st_shasta */
+ { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */
+ { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX12350 */
+ { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX4350 */
+ { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX24350 */
+
+ /* st_vsc */
+ { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc },
+
+ /* st_yosemite */
+ { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0,
+ st_yosemite }, /* SuperTrak EX4650 */
+ { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0,
+ st_yosemite }, /* SuperTrak EX4650o */
+ { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0,
+ st_yosemite }, /* SuperTrak EX8650EL */
+ { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0,
+ st_yosemite }, /* SuperTrak EX8650 */
+ { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0,
+ st_yosemite }, /* SuperTrak EX8654 */
+ { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_yosemite }, /* generic st_yosemite */
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, stex_pci_tbl);