* General Public License for more details.
*
*
- * $Id: aha152x.c,v 2.4 2000/12/16 12:53:56 fischer Exp $
+ * $Id: aha152x.c,v 2.5 2002/04/14 11:24:53 fischer Exp $
*
* $Log: aha152x.c,v $
+ * Revision 2.5 2002/04/14 11:24:53 fischer
+ * - isapnp support
+ * - abort fixed
+ * - 2.5 support
+ *
* Revision 2.4 2000/12/16 12:53:56 fischer
* - allow REQUEST SENSE to be queued
* - handle shared PCI interrupts
#endif
#include <linux/sched.h>
+#include <asm/irq.h>
#include <asm/io.h>
+#include <linux/version.h>
#include <linux/blk.h>
#include "scsi.h"
#include "sd.h"
#define DELAY_DEFAULT 1000
-/* possible irq range */
#if defined(PCMCIA)
#define IRQ_MIN 0
#define IRQ_MAX 16
#else
#define IRQ_MIN 9
+#if defined(__PPC)
+#define IRQ_MAX (NR_IRQS-1)
+#else
#define IRQ_MAX 12
#endif
-#define IRQS IRQ_MAX-IRQ_MIN+1
+#endif
enum {
not_issued = 0x0001, /* command not yet issued */
char *conf;
} setup[2];
-static struct Scsi_Host *aha152x_host[IRQS];
+static struct Scsi_Host *aha152x_host[2];
/*
* internal states of the host
#define SCDONE(SCpnt) SCDATA(SCpnt)->done
#define SCSEM(SCpnt) SCDATA(SCpnt)->sem
+#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset))
/* state handling */
static void seldi_run(struct Scsi_Host *shpnt);
/* possible i/o addresses for the AIC-6260; default first */
static unsigned short ports[] = { 0x340, 0x140 };
-#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))
#if !defined(SKIP_BIOSTEST)
/* possible locations for the Adaptec BIOS; defaults first */
0xeb800, /* VTech Platinum SMP */
0xf0000,
};
-#define ADDRESS_COUNT (sizeof(addresses) / sizeof(unsigned int))
/* signatures for various AIC-6[23]60 based controllers.
The point in detecting signatures is to avoid useless and maybe
{ "DTC3520A Host Adapter BIOS", 0x318a, 26 },
/* DTC 3520A ISA SCSI */
};
-
-#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
#endif
#if defined(PCMCIA) || !defined(MODULE)
void aha152x_setup(char *str, int *ints)
{
- if(setup_count>2) {
+ if(setup_count>=ARRAY_SIZE(setup)) {
printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
return;
}
#endif
int count=setup_count;
- get_options(str, sizeof(ints)/sizeof(int), ints);
+ get_options(str, ARRAY_SIZE(ints), ints);
aha152x_setup(str,ints);
return count<setup_count;
#if !defined(PCMCIA)
int i;
- for (i = 0; i < PORT_COUNT && (setup->io_port != ports[i]); i++)
+ for (i = 0; i < ARRAY_SIZE(ports) && (setup->io_port != ports[i]); i++)
;
- if (i == PORT_COUNT)
+ if (i == ARRAY_SIZE(ports))
return 0;
#endif
return 1;
}
+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 0;
+}
+
static void swintr(int irqno, void *dev_id, struct pt_regs *regs)
{
- struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN];
+ struct Scsi_Host *shpnt = lookup_irq(irqno);
- if (!shpnt)
- printk(KERN_ERR "aha152x%d: catched software interrupt for unknown controller.\n", HOSTNO);
+ if (!shpnt) {
+ printk(KERN_ERR "aha152x%d: catched software interrupt %d for unknown controller.\n", HOSTNO, irqno);
+ return;
+ }
HOSTDATA(shpnt)->swint++;
#endif
tpnt->proc_name = "aha152x";
- for (i = 0; i < IRQS; i++)
+ for (i = 0; i < ARRAY_SIZE(aha152x_host); i++)
aha152x_host[i] = (struct Scsi_Host *) NULL;
if (setup_count) {
}
#if defined(SETUP0)
- if (setup_count < 2) {
+ if (setup_count < ARRAY_SIZE(setup)) {
struct aha152x_setup override = SETUP0;
if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
#endif
#if defined(SETUP1)
- if (setup_count < 2) {
+ if (setup_count < ARRAY_SIZE(setup)) {
struct aha152x_setup override = SETUP1;
if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
#endif
#if defined(MODULE)
- if (setup_count<2 && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) {
+ if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) {
if(aha152x[0]!=0) {
setup[setup_count].conf = "";
setup[setup_count].io_port = aha152x[0];
setup[setup_count].ext_trans);
}
- if (setup_count < 2 && (aha152x1[0]!=0 || io[1]!=0 || irq[1]!=0)) {
+ if (setup_count<ARRAY_SIZE(setup) && (aha152x1[0]!=0 || io[1]!=0 || irq[1]!=0)) {
if(aha152x1[0]!=0) {
setup[setup_count].conf = "";
setup[setup_count].io_port = aha152x1[0];
#endif
#ifdef __ISAPNP__
- while ( setup_count<2 && (dev=isapnp_find_dev(NULL, ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), dev)) ) {
+ while ( setup_count<ARRAY_SIZE(setup) && (dev=isapnp_find_dev(NULL, ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), dev)) ) {
if (dev->prepare(dev) < 0)
continue;
if (dev->active)
#if defined(AUTOCONF)
- if (setup_count < 2) {
+ if (setup_count<ARRAY_SIZE(setup)) {
#if !defined(SKIP_BIOSTEST)
ok = 0;
- for (i = 0; i < ADDRESS_COUNT && !ok; i++)
- for (j = 0; (j < SIGNATURE_COUNT) && !ok; j++)
+ for (i = 0; i < ARRAY_SIZE(addresses) && !ok; i++)
+ for (j = 0; j<ARRAY_SIZE(signatures) && !ok; j++)
ok = isa_check_signature(addresses[i] + signatures[j].sig_offset,
signatures[j].signature, signatures[j].sig_length);
#endif /* !SKIP_BIOSTEST */
ok = 0;
- for (i = 0; i < PORT_COUNT && setup_count < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(ports) && setup_count < 2; i++) {
if ((setup_count == 1) && (setup[0].io_port == ports[i]))
continue;
for (i=0; i<setup_count; i++) {
struct Scsi_Host *shpnt;
- aha152x_host[setup[i].irq - IRQ_MIN] = shpnt =
+ aha152x_host[registered_count] = shpnt =
scsi_register(tpnt, sizeof(struct aha152x_hostdata));
if(!shpnt) {
scsi_unregister(shpnt);
registered_count--;
release_region(shpnt->io_port, IO_RANGE);
- aha152x_host[shpnt->irq - IRQ_MIN] = 0;
+ aha152x_host[registered_count] = 0;
shpnt = 0;
continue;
}
printk(KERN_INFO "aha152x%d: trying software interrupt, ", HOSTNO);
SETPORT(DMACNTRL0, SWINT|INTEN);
- spin_unlock_irq(shpnt->host_lock);
mdelay(1000);
- spin_lock_irq(shpnt->host_lock);
free_irq(shpnt->irq, shpnt);
if (!HOSTDATA(shpnt)->swint) {
registered_count--;
release_region(shpnt->io_port, IO_RANGE);
- aha152x_host[shpnt->irq - IRQ_MIN] = 0;
+ aha152x_host[registered_count] = 0;
scsi_unregister(shpnt);
shpnt=NULL;
continue;
if (request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) {
printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", HOSTNO);
- scsi_unregister(shpnt);
registered_count--;
release_region(shpnt->io_port, IO_RANGE);
- shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0;
+ aha152x_host[registered_count] = 0;
+ scsi_unregister(shpnt);
+ shpnt=NULL;
continue;
}
}
SCp.phase : current state of the command */
if (SCpnt->use_sg) {
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
- SCpnt->SCp.ptr = SCpnt->SCp.buffer->address;
+ SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer);
SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
} else {
if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt);
show_queues(shpnt);
- mdelay(1000);
}
#endif
static void timer_expired(unsigned long p)
{
- struct semaphore *sem = (void *)p;
+ Scsi_Cmnd *SCp = (Scsi_Cmnd *)p;
+ struct semaphore *sem = SCSEM(SCp);
+ struct Scsi_Host *shpnt = SCp->host;
+
+ /* remove command from issue queue */
+ if(remove_SC(&ISSUE_SC, SCp)) {
+ printk(KERN_INFO "aha152x: ABORT timed out - removed from issue queue\n");
+ kfree(SCp->host_scribble);
+ SCp->host_scribble=0;
+ } else {
+ printk(KERN_INFO "aha152x: ABORT timed out - not on issue queue\n");
+ }
- printk(KERN_INFO "aha152x: timer expired\n");
up(sem);
}
if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(INFO_LEAD "aha152x_device_reset(%p)", CMDINFO(SCpnt), SCpnt);
show_queues(shpnt);
- mdelay(1000);
}
#endif
cmnd.request_bufflen = 0;
init_timer(&timer);
- timer.data = (unsigned long) &sem;
+ timer.data = (unsigned long) &cmnd;
timer.expires = jiffies + 100*HZ; /* 10s */
timer.function = (void (*)(unsigned long)) timer_expired;
- add_timer(&timer);
aha152x_internal_queue(&cmnd, &sem, resetting, 0, internal_done);
+ add_timer(&timer);
down(&sem);
del_timer(&timer);
if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt);
show_queues(shpnt);
- mdelay(1000);
}
#endif
static void run(void)
{
int i;
- for (i = 0; i < IRQS; 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;
static void intr(int irqno, void *dev_id, struct pt_regs *regs)
{
- struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN];
+ struct Scsi_Host *shpnt = lookup_irq(irqno);
if (!shpnt) {
- printk(KERN_ERR "aha152x: catched interrupt for unknown controller.\n");
+ printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno);
return;
}
/* advance to next buffer */
CURRENT_SC->SCp.buffers_residual--;
CURRENT_SC->SCp.buffer++;
- CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address;
+ CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
}
}
/* advance to next buffer */
CURRENT_SC->SCp.buffers_residual--;
CURRENT_SC->SCp.buffer++;
- CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address;
+ CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer);
CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
}
CURRENT_SC->resid += data_count;
if(CURRENT_SC->use_sg) {
- data_count -= CURRENT_SC->SCp.ptr - CURRENT_SC->SCp.buffer->address;
+ data_count -= CURRENT_SC->SCp.ptr - SG_ADDRESS(CURRENT_SC->SCp.buffer);
while(data_count>0) {
CURRENT_SC->SCp.buffer--;
CURRENT_SC->SCp.buffers_residual++;
data_count -= CURRENT_SC->SCp.buffer->length;
}
- CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address - data_count;
+ CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) - data_count;
CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count;
} else {
CURRENT_SC->SCp.ptr -= data_count;
int pending;
DO_LOCK(flags);
- if(HOSTDATA(shpnt)->in_intr!=0)
- {
+ if(HOSTDATA(shpnt)->in_intr!=0) {
DO_UNLOCK(flags);
- /* _error never returns.. */
+ /* aha152x_error never returns.. */
aha152x_error(shpnt, "bottom-half already running!?");
}
HOSTDATA(shpnt)->in_intr++;
unsigned long flags;
int thislength;
- for (i = 0, shpnt = (struct Scsi_Host *) NULL; i < IRQS; i++)
+ for (i = 0, shpnt = (struct Scsi_Host *) NULL; i<ARRAY_SIZE(aha152x_host); i++)
if (aha152x_host[i] && aha152x_host[i]->host_no == hostno)
shpnt = aha152x_host[i];