#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ioport.h>
/* ================================================================== */
struct scsi_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
struct Scsi_Host *host;
unsigned short manf_id;
/* ================================================================== */
-/*
-* Global (within this module) variables other than
-* sym53c500_driver_template (the scsi_host_template).
-*/
-static dev_link_t *dev_list;
-static dev_info_t dev_info = "sym53c500_cs";
-
-/* ================================================================== */
-
static void
chip_init(int io_port)
{
}
static irqreturn_t
-SYM53C500_intr(int irq, void *dev_id, struct pt_regs *regs)
+SYM53C500_intr(int irq, void *dev_id)
{
unsigned long flags;
struct Scsi_Host *dev = dev_id;
DEB(unsigned char seq_reg;)
unsigned char status, int_reg;
unsigned char pio_status;
- struct scatterlist *sglist;
- unsigned int sgcount;
int port_base = dev->io_port;
struct sym53c500_data *data =
(struct sym53c500_data *)dev->hostdata;
switch (status & 0x07) { /* scsi phase */
case 0x00: /* DATA-OUT */
if (int_reg & 0x10) { /* Target requesting info transfer */
+ struct scatterlist *sg;
+ int i;
+
curSC->SCp.phase = data_out;
VDEB(printk("SYM53C500: Data-Out phase\n"));
outb(FLUSH_FIFO, port_base + CMD_REG);
- LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */
+ LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
- if (!curSC->use_sg) /* Don't use scatter-gather */
- SYM53C500_pio_write(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
- else { /* use scatter-gather */
- sgcount = curSC->use_sg;
- sglist = curSC->request_buffer;
- while (sgcount--) {
- SYM53C500_pio_write(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
- sglist++;
- }
+
+ scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+ SYM53C500_pio_write(fast_pio, port_base,
+ page_address(sg->page) + sg->offset,
+ sg->length);
}
REG0(port_base);
}
case 0x01: /* DATA-IN */
if (int_reg & 0x10) { /* Target requesting info transfer */
+ struct scatterlist *sg;
+ int i;
+
curSC->SCp.phase = data_in;
VDEB(printk("SYM53C500: Data-In phase\n"));
outb(FLUSH_FIFO, port_base + CMD_REG);
- LOAD_DMA_COUNT(port_base, curSC->request_bufflen); /* Max transfer size */
+ LOAD_DMA_COUNT(port_base, scsi_bufflen(curSC)); /* Max transfer size */
outb(TRANSFER_INFO | DMA_OP, port_base + CMD_REG);
- if (!curSC->use_sg) /* Don't use scatter-gather */
- SYM53C500_pio_read(fast_pio, port_base, curSC->request_buffer, curSC->request_bufflen);
- else { /* Use scatter-gather */
- sgcount = curSC->use_sg;
- sglist = curSC->request_buffer;
- while (sgcount--) {
- SYM53C500_pio_read(fast_pio, port_base, page_address(sglist->page) + sglist->offset, sglist->length);
- sglist++;
- }
+
+ scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) {
+ SYM53C500_pio_read(fast_pio, port_base,
+ page_address(sg->page) + sg->offset,
+ sg->length);
}
REG0(port_base);
}
}
static void
-SYM53C500_release(dev_link_t *link)
+SYM53C500_release(struct pcmcia_device *link)
{
struct scsi_info_t *info = link->priv;
struct Scsi_Host *shost = info->host;
*/
if (shost->irq)
free_irq(shost->irq, shost);
- if (shost->dma_channel != 0xff)
- free_dma(shost->dma_channel);
if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port);
- link->dev = NULL;
-
- pcmcia_release_configuration(link->handle);
- pcmcia_release_io(link->handle, &link->io);
- pcmcia_release_irq(link->handle, &link->irq);
-
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
scsi_host_put(shost);
} /* SYM53C500_release */
DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n",
SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id,
- SCpnt->device->lun, SCpnt->request_bufflen));
+ SCpnt->device->lun, scsi_bufflen(SCpnt)));
VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i]));
/* We are locked here already by the mid layer */
REG0(port_base);
- outb(SCpnt->device->id, port_base + DEST_ID); /* set destination */
+ outb(scmd_id(SCpnt), port_base + DEST_ID); /* set destination */
outb(FLUSH_FIFO, port_base + CMD_REG); /* reset the fifos */
for (i = 0; i < SCpnt->cmd_len; i++) {
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void
-SYM53C500_config(dev_link_t *link)
+static int
+SYM53C500_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
struct scsi_info_t *info = link->priv;
tuple_t tuple;
cisparse_t parse;
DEBUG(0, "SYM53C500_config(0x%p)\n", link);
+ info->manf_id = link->manf_id;
+
tuple.TupleData = (cisdata_t *)tuple_data;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CONFIG;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
- link->conf.ConfigBase = parse.config.base;
-
- tuple.DesiredTuple = CISTPL_MANFID;
- if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
- info->manf_id = le16_to_cpu(tuple.TupleData[0]);
-
- /* Configure card */
- link->state |= DEV_CONFIG;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
- i = pcmcia_request_io(handle, &link->io);
+ i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
- CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
* That's the trouble with copying liberally from another driver.
data = (struct sym53c500_data *)host->hostdata;
if (irq_level > 0) {
- if (request_irq(irq_level, SYM53C500_intr, SA_SHIRQ, "SYM53C500", host)) {
+ if (request_irq(irq_level, SYM53C500_intr, IRQF_SHARED, "SYM53C500", host)) {
printk("SYM53C500: unable to allocate IRQ %d\n", irq_level);
goto err_free_scsi;
}
data->fast_pio = USE_FAST_PIO;
sprintf(info->node.dev_name, "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
if (scsi_add_host(host, NULL))
scsi_scan_host(host);
- goto out; /* SUCCESS */
+ return 0;
err_free_irq:
free_irq(irq_level, host);
err_release:
release_region(port_base, 0x10);
printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");
-
-out:
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ return -ENODEV;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
SYM53C500_release(link);
- return;
+ return -ENODEV;
} /* SYM53C500_config */
-static int
-SYM53C500_event(event_t event, int priority, event_callback_args_t *args)
+static int sym53c500_resume(struct pcmcia_device *link)
{
- dev_link_t *link = args->client_data;
struct scsi_info_t *info = link->priv;
- DEBUG(1, "SYM53C500_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- SYM53C500_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- SYM53C500_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- /* See earlier comment about manufacturer IDs. */
- if ((info->manf_id == MANFID_MACNICA) ||
- (info->manf_id == MANFID_PIONEER) ||
- (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /*
- * If things don't work after a "resume",
- * this is a good place to start looking.
- */
- SYM53C500_int_host_reset(link->io.BasePort1);
- }
- break;
+ /* See earlier comment about manufacturer IDs. */
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
+ /*
+ * If things don't work after a "resume",
+ * this is a good place to start looking.
+ */
+ SYM53C500_int_host_reset(link->io.BasePort1);
+
return 0;
-} /* SYM53C500_event */
+}
static void
-SYM53C500_detach(dev_link_t *link)
+SYM53C500_detach(struct pcmcia_device *link)
{
- dev_link_t **linkp;
-
DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (*linkp == NULL)
- return;
-
- if (link->state & DEV_CONFIG)
- SYM53C500_release(link);
-
- if (link->handle)
- pcmcia_deregister_client(link->handle);
+ SYM53C500_release(link);
- /* Unlink device structure, free bits. */
- *linkp = link->next;
kfree(link->priv);
link->priv = NULL;
} /* SYM53C500_detach */
-static dev_link_t *
-SYM53C500_attach(void)
+static int
+SYM53C500_probe(struct pcmcia_device *link)
{
struct scsi_info_t *info;
- client_reg_t client_reg;
- dev_link_t *link;
- int ret;
DEBUG(0, "SYM53C500_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
-
- /* Register with Card Services */
- link->next = dev_list;
- dev_list = link;
- client_reg.dev_info = &dev_info;
- client_reg.event_handler = &SYM53C500_event;
- client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
- ret = pcmcia_register_client(&link->handle, &client_reg);
- if (ret != 0) {
- cs_error(link->handle, RegisterClient, ret);
- SYM53C500_detach(link);
- return NULL;
- }
- return link;
+ return SYM53C500_config(link);
} /* SYM53C500_attach */
MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
MODULE_DESCRIPTION("SYM53C500 PCMCIA SCSI driver");
MODULE_LICENSE("GPL");
+static struct pcmcia_device_id sym53c500_ids[] = {
+ PCMCIA_DEVICE_PROD_ID12("BASICS by New Media Corporation", "SCSI Sym53C500", 0x23c78a9d, 0x0099e7f7),
+ PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "SCSI Bus Toaster Sym53C500", 0x085a850b, 0x45432eb8),
+ PCMCIA_DEVICE_PROD_ID2("SCSI9000", 0x21648f44),
+ PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, sym53c500_ids);
+
static struct pcmcia_driver sym53c500_cs_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "sym53c500_cs",
},
- .attach = SYM53C500_attach,
- .detach = SYM53C500_detach,
+ .probe = SYM53C500_probe,
+ .remove = SYM53C500_detach,
+ .id_table = sym53c500_ids,
+ .resume = sym53c500_resume,
};
static int __init