#include <linux/module.h>
#include <linux/sched.h>
#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/blkdev.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/isapnp.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
+#include <linux/list.h>
#include <asm/semaphore.h>
#include <scsi/scsicam.h>
#include "scsi.h"
+#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
#include "aha152x.h"
+static LIST_HEAD(aha152x_host_list);
+
/* DEFINES */
#if !defined(PCMCIA)
#if defined(MODULE)
-MODULE_PARM(io, "1-2i");
-MODULE_PARM_DESC(io,"base io address of controller");
static int io[] = {0, 0};
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io,"base io address of controller");
-MODULE_PARM(irq, "1-2i");
-MODULE_PARM_DESC(irq,"interrupt for controller");
static int irq[] = {0, 0};
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq,"interrupt for controller");
-MODULE_PARM(scsiid, "1-2i");
-MODULE_PARM_DESC(scsiid,"scsi id of controller");
static int scsiid[] = {7, 7};
+module_param_array(scsiid, int, NULL, 0);
+MODULE_PARM_DESC(scsiid,"scsi id of controller");
-MODULE_PARM(reconnect, "1-2i");
-MODULE_PARM_DESC(reconnect,"allow targets to disconnect");
static int reconnect[] = {1, 1};
+module_param_array(reconnect, int, NULL, 0);
+MODULE_PARM_DESC(reconnect,"allow targets to disconnect");
-MODULE_PARM(parity, "1-2i");
-MODULE_PARM_DESC(parity,"use scsi parity");
static int parity[] = {1, 1};
+module_param_array(parity, int, NULL, 0);
+MODULE_PARM_DESC(parity,"use scsi parity");
-MODULE_PARM(sync, "1-2i");
-MODULE_PARM_DESC(sync,"use synchronous transfers");
static int sync[] = {1, 1};
+module_param_array(sync, int, NULL, 0);
+MODULE_PARM_DESC(sync,"use synchronous transfers");
-MODULE_PARM(delay, "1-2i");
-MODULE_PARM_DESC(delay,"scsi reset delay");
static int delay[] = {DELAY_DEFAULT, DELAY_DEFAULT};
+module_param_array(delay, int, NULL, 0);
+MODULE_PARM_DESC(delay,"scsi reset delay");
-MODULE_PARM(exttrans, "1-2i");
-MODULE_PARM_DESC(exttrans,"use extended translation");
static int exttrans[] = {0, 0};
+module_param_array(exttrans, int, NULL, 0);
+MODULE_PARM_DESC(exttrans,"use extended translation");
#if !defined(AHA152X_DEBUG)
-MODULE_PARM(aha152x, "1-8i");
-MODULE_PARM_DESC(aha152x, "parameters for first controller");
static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
+module_param_array(aha152x, int, NULL, 0);
+MODULE_PARM_DESC(aha152x, "parameters for first controller");
-MODULE_PARM(aha152x1, "1-8i");
-MODULE_PARM_DESC(aha152x1, "parameters for second controller");
static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
+module_param_array(aha152x1, int, NULL, 0);
+MODULE_PARM_DESC(aha152x1, "parameters for second controller");
#else
-MODULE_PARM(debug, "1-2i");
-MODULE_PARM_DESC(debug, "flags for driver debugging");
static int debug[] = {DEBUG_DEFAULT, DEBUG_DEFAULT};
+module_param_array(debug, int, NULL, 0);
+MODULE_PARM_DESC(debug, "flags for driver debugging");
-MODULE_PARM(aha152x, "1-9i");
-MODULE_PARM_DESC(aha152x, "parameters for first controller");
static int aha152x[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
+module_param_array(aha152x, int, NULL, 0);
+MODULE_PARM_DESC(aha152x, "parameters for first controller");
-MODULE_PARM(aha152x1, "1-9i");
-MODULE_PARM_DESC(aha152x1, "parameters for second controller");
static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
+module_param_array(aha152x1, int, NULL, 0);
+MODULE_PARM_DESC(aha152x1, "parameters for second controller");
#endif /* !defined(AHA152X_DEBUG) */
#endif /* MODULE */
#endif /* !PCMCIA */
-static int registered_count=0;
-static struct Scsi_Host *aha152x_host[2];
-static Scsi_Host_Template aha152x_driver_template;
+static struct scsi_host_template aha152x_driver_template;
/*
* internal states of the host
#ifdef __ISAPNP__
struct pnp_dev *pnpdev;
#endif
+ struct list_head host_list;
};
struct aha152x_scdata {
Scsi_Cmnd *next; /* next sc in queue */
struct semaphore *sem; /* semaphore to block on */
+ unsigned char cmd_len;
+ unsigned char cmnd[MAX_COMMAND_SIZE];
+ unsigned short use_sg;
+ unsigned request_bufflen;
+ void *request_buffer;
};
};
/* setup & interrupt */
-static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *);
+static irqreturn_t intr(int irq, void *dev_id);
static void reset_ports(struct Scsi_Host *shpnt);
static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
static void done(struct Scsi_Host *shpnt, int error);
return ptr;
}
-static inline struct Scsi_Host *lookup_irq(int irqno)
-{
- int i;
-
- for(i=0; i<ARRAY_SIZE(aha152x_host); i++)
- if(aha152x_host[i] && aha152x_host[i]->irq==irqno)
- return aha152x_host[i];
-
- return NULL;
-}
-
-static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs)
+static irqreturn_t swintr(int irqno, void *dev_id)
{
- struct Scsi_Host *shpnt = lookup_irq(irqno);
-
- if (!shpnt) {
- printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno);
- return IRQ_NONE;
- }
+ struct Scsi_Host *shpnt = dev_id;
HOSTDATA(shpnt)->swint++;
return NULL;
}
- /* need to have host registered before triggering any interrupt */
- aha152x_host[registered_count] = shpnt;
-
memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
+ INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list);
+
+ /* need to have host registered before triggering any interrupt */
+ list_add_tail(&HOSTDATA(shpnt)->host_list, &aha152x_host_list);
shpnt->io_port = setup->io_port;
shpnt->n_io_port = IO_RANGE;
SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, 0);
- if( request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) {
+ if( request_irq(shpnt->irq, swintr, IRQF_DISABLED|IRQF_SHARED, "aha152x", shpnt) ) {
printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq);
goto out_host_put;
}
SETPORT(SSTAT0, 0x7f);
SETPORT(SSTAT1, 0xef);
- if ( request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) {
+ if ( request_irq(shpnt->irq, intr, IRQF_DISABLED|IRQF_SHARED, "aha152x", shpnt) ) {
printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq);
goto out_host_put;
}
scsi_scan_host(shpnt);
- registered_count++;
-
return shpnt;
out_host_put:
- aha152x_host[registered_count]=NULL;
+ list_del(&HOSTDATA(shpnt)->host_list);
scsi_host_put(shpnt);
return NULL;
#endif
scsi_remove_host(shpnt);
+ list_del(&HOSTDATA(shpnt)->host_list);
scsi_host_put(shpnt);
}
if (HOSTDATA(shpnt)->debug & debug_queue) {
printk(INFO_LEAD "queue: %p; cmd_len=%d pieces=%d size=%u cmnd=",
CMDINFO(SCpnt), SCpnt, SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
- print_command(SCpnt->cmnd);
+ __scsi_print_command(SCpnt->cmnd);
}
#endif
return FAILED;
}
} else {
+ struct aha152x_scdata *sc;
+
SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
if(SCpnt->host_scribble==0) {
printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
return FAILED;
}
+
+ sc = SCDATA(SCpnt);
+ memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd));
+ sc->request_buffer = SCpnt->request_buffer;
+ sc->request_bufflen = SCpnt->request_bufflen;
+ sc->use_sg = SCpnt->use_sg;
+ sc->cmd_len = SCpnt->cmd_len;
}
SCNEXT(SCpnt) = NULL;
DECLARE_MUTEX_LOCKED(sem);
struct timer_list timer;
int ret, issued, disconnected;
+ unsigned char old_cmd_len = SCpnt->cmd_len;
+ unsigned short old_use_sg = SCpnt->use_sg;
+ void *old_buffer = SCpnt->request_buffer;
+ unsigned old_bufflen = SCpnt->request_bufflen;
unsigned long flags;
#if defined(AHA152X_DEBUG)
add_timer(&timer);
down(&sem);
del_timer(&timer);
-
- SCpnt->cmd_len = SCpnt->old_cmd_len;
- SCpnt->use_sg = SCpnt->old_use_sg;
- SCpnt->request_buffer = SCpnt->buffer;
- SCpnt->request_bufflen = SCpnt->bufflen;
+
+ SCpnt->cmd_len = old_cmd_len;
+ SCpnt->use_sg = old_use_sg;
+ SCpnt->request_buffer = old_buffer;
+ SCpnt->request_bufflen = old_bufflen;
DO_LOCK(flags);
}
DO_UNLOCK(flags);
-
- spin_lock_irq(shpnt->host_lock);
return ret;
}
* Reset the bus
*
*/
-static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
+static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
{
- struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags;
DO_LOCK(flags);
#if defined(AHA152X_DEBUG)
if(HOSTDATA(shpnt)->debug & debug_eh) {
- printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt);
+ printk(KERN_DEBUG "scsi%d: bus reset", shpnt->host_no);
show_queues(shpnt);
}
#endif
free_hard_reset_SCs(shpnt, &ISSUE_SC);
free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
- DPRINTK(debug_eh, DEBUG_LEAD "resetting bus\n", CMDINFO(SCpnt));
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting bus\n", shpnt->host_no);
SETPORT(SCSISEQ, SCSIRSTO);
mdelay(256);
SETPORT(SCSISEQ, 0);
mdelay(DELAY);
- DPRINTK(debug_eh, DEBUG_LEAD "bus resetted\n", CMDINFO(SCpnt));
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: bus resetted\n", shpnt->host_no);
setup_expected_interrupts(shpnt);
if(HOSTDATA(shpnt)->commands==0)
return SUCCESS;
}
+/*
+ * Reset the bus
+ *
+ */
+static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
+{
+ return aha152x_bus_reset_host(SCpnt->device->host);
+}
/*
* Restore default values to the AIC-6260 registers and reset the fifos
* Reset the host (bus and controller)
*
*/
-int aha152x_host_reset(Scsi_Cmnd * SCpnt)
+int aha152x_host_reset_host(struct Scsi_Host *shpnt)
{
-#if defined(AHA152X_DEBUG)
- struct Scsi_Host *shpnt = SCpnt->device->host;
-#endif
-
- DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt);
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: host reset\n", shpnt->host_no);
- aha152x_bus_reset(SCpnt);
+ aha152x_bus_reset_host(shpnt);
- DPRINTK(debug_eh, DEBUG_LEAD "resetting ports\n", CMDINFO(SCpnt));
- reset_ports(SCpnt->device->host);
+ DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting ports\n", shpnt->host_no);
+ reset_ports(shpnt);
return SUCCESS;
}
+/*
+ * Reset the host (bus and controller)
+ *
+ */
+static int aha152x_host_reset(Scsi_Cmnd *SCpnt)
+{
+ return aha152x_host_reset_host(SCpnt->device->host);
+}
+
/*
* Return the "logical geometry"
*
* Run service completions on the card with interrupts enabled.
*
*/
-static void run(void)
+static void run(struct work_struct *work)
{
- int i;
- for (i = 0; i<ARRAY_SIZE(aha152x_host); i++) {
- struct Scsi_Host *shpnt = aha152x_host[i];
- if (shpnt && HOSTDATA(shpnt)->service) {
- HOSTDATA(shpnt)->service=0;
- is_complete(shpnt);
- }
+ struct aha152x_hostdata *hd;
+
+ list_for_each_entry(hd, &aha152x_host_list, host_list) {
+ struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
+
+ is_complete(shost);
}
}
/*
- * Interrupts handler
+ * Interrupt handler
*
*/
-
-static irqreturn_t intr(int irqno, void *dev_id, struct pt_regs *regs)
+static irqreturn_t intr(int irqno, void *dev_id)
{
- struct Scsi_Host *shpnt = lookup_irq(irqno);
+ struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
+ unsigned long flags;
unsigned char rev, dmacntrl0;
if (!shpnt) {
if ((rev == 0xFF) && (dmacntrl0 == 0xFF))
return IRQ_NONE;
+ if( TESTLO(DMASTAT, INTSTAT) )
+ return IRQ_NONE;
+
/* no more interrupts from the controller, while we're busy.
INTEN is restored by the BH handler */
CLRBITS(DMACNTRL0, INTEN);
-#if 0
- /* check if there is already something to be
- serviced; should not happen */
- if(HOSTDATA(shpnt)->service) {
- printk(KERN_ERR "aha152x%d: lost interrupt (%d)\n", HOSTNO, HOSTDATA(shpnt)->service);
- show_queues(shpnt);
+ DO_LOCK(flags);
+ if( HOSTDATA(shpnt)->service==0 ) {
+ HOSTDATA(shpnt)->service=1;
+
+ /* Poke the BH handler */
+ INIT_WORK(&aha152x_tq, run);
+ schedule_work(&aha152x_tq);
}
-#endif
-
- /* Poke the BH handler */
- HOSTDATA(shpnt)->service++;
- INIT_WORK(&aha152x_tq, (void *) run, NULL);
- schedule_work(&aha152x_tq);
+ DO_UNLOCK(flags);
+
return IRQ_HANDLED;
}
#endif
if(DONE_SC->SCp.phase & check_condition) {
+ struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
+ struct aha152x_scdata *sc = SCDATA(cmd);
+
#if 0
if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC));
- print_sense("bh", DONE_SC);
+ scsi_print_sense("bh", DONE_SC);
}
#endif
/* restore old command */
- memcpy((void *) DONE_SC->cmnd, (void *) DONE_SC->data_cmnd, sizeof(DONE_SC->data_cmnd));
- DONE_SC->request_buffer = DONE_SC->buffer;
- DONE_SC->request_bufflen = DONE_SC->bufflen;
- DONE_SC->use_sg = DONE_SC->old_use_sg;
- DONE_SC->cmd_len = DONE_SC->old_cmd_len;
+ memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd));
+ cmd->request_buffer = sc->request_buffer;
+ cmd->request_bufflen = sc->request_bufflen;
+ cmd->use_sg = sc->use_sg;
+ cmd->cmd_len = sc->cmd_len;
- DONE_SC->SCp.Status = 0x02;
+ cmd->SCp.Status = 0x02;
HOSTDATA(shpnt)->commands--;
if (!HOSTDATA(shpnt)->commands)
ADDMSGO(BUS_DEVICE_RESET);
} else if (SYNCNEG==0 && SYNCHRONOUS) {
CURRENT_SC->SCp.phase |= syncneg;
- ADDMSGO(EXTENDED_MESSAGE);
- ADDMSGO(3);
- ADDMSGO(EXTENDED_SDTR);
- ADDMSGO(50); /* 200ns */
- ADDMSGO(8); /* 8 byte req/ack offset */
-
+ MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
SYNCNEG=1; /* negotiation in progress */
}
#if defined(AHA152X_DEBUG)
if (HOSTDATA(shpnt)->debug & debug_msgi) {
printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0));
- print_msg(&MSGI(0));
+ spi_print_msg(&MSGI(0));
printk("\n");
}
#endif
break;
printk(INFO_LEAD, CMDINFO(CURRENT_SC));
- print_msg(&MSGI(0));
+ spi_print_msg(&MSGI(0));
printk("\n");
ticks = (MSGI(3) * 4 + 49) / 50;
int i;
printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC));
- for (i=0; i<MSGOLEN; i+=print_msg(&MSGO(i)), printk(" "))
+ for (i=0; i<MSGOLEN; i+=spi_print_msg(&MSGO(i)), printk(" "))
;
printk(")\n");
}
#if defined(AHA152X_DEBUG)
if (HOSTDATA(shpnt)->debug & debug_cmd) {
printk(DEBUG_LEAD "cmd_init: ", CMDINFO(CURRENT_SC));
- print_command(CURRENT_SC->cmnd);
+ __scsi_print_command(CURRENT_SC->cmnd);
}
#endif
#if defined(AHA152X_DEBUG)
if (HOSTDATA(shpnt)->debug & debug_status) {
printk(DEBUG_LEAD "inbound status %02x ", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.Status);
- print_status(CURRENT_SC->SCp.Status);
+ scsi_print_status(CURRENT_SC->SCp.Status);
printk("\n");
}
#endif
unsigned long flags;
int pending;
+ if(!shpnt)
+ return;
+
DO_LOCK(flags);
+
+ if( HOSTDATA(shpnt)->service==0 ) {
+ DO_UNLOCK(flags);
+ return;
+ }
+
+ HOSTDATA(shpnt)->service = 0;
+
if(HOSTDATA(shpnt)->in_intr) {
DO_UNLOCK(flags);
/* aha152x_error never returns.. */
*/
static void show_command(Scsi_Cmnd *ptr)
{
- printk(KERN_DEBUG "0x%08x: target=%d; lun=%d; cmnd=(",
- (unsigned int) ptr, ptr->device->id, ptr->device->lun);
+ scmd_printk(KERN_DEBUG, ptr, "%p: cmnd=(", ptr);
- print_command(ptr->cmnd);
+ __scsi_print_command(ptr->cmnd);
printk(KERN_DEBUG "); request_bufflen=%d; resid=%d; phase |",
ptr->request_bufflen, ptr->resid);
return thislength < length ? thislength : length;
}
-static Scsi_Host_Template aha152x_driver_template = {
+static struct scsi_host_template aha152x_driver_template = {
.module = THIS_MODULE,
.name = AHA152X_REVID,
.proc_name = "aha152x",
if (setup_count<ARRAY_SIZE(setup)) {
#if !defined(SKIP_BIOSTEST)
ok = 0;
- for (i = 0; i < ARRAY_SIZE(addresses) && !ok; i++)
+ for (i = 0; i < ARRAY_SIZE(addresses) && !ok; i++) {
+ void __iomem *p = ioremap(addresses[i], 0x4000);
+ if (!p)
+ continue;
for (j = 0; j<ARRAY_SIZE(signatures) && !ok; j++)
- ok = isa_check_signature(addresses[i] + signatures[j].sig_offset,
+ ok = check_signature(p + signatures[j].sig_offset,
signatures[j].signature, signatures[j].sig_length);
+ iounmap(p);
+ }
if (!ok && setup_count == 0)
return 0;
#endif
}
- return registered_count>0;
+ return 1;
}
static void __exit aha152x_exit(void)
{
- int i;
+ struct aha152x_hostdata *hd;
+
+ list_for_each_entry(hd, &aha152x_host_list, host_list) {
+ struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata);
- for(i=0; i<ARRAY_SIZE(setup); i++) {
- aha152x_release(aha152x_host[i]);
- aha152x_host[i]=NULL;
+ aha152x_release(shost);
}
}