Commit 4d5d8e2a authored by Jürgen E. Fischer's avatar Jürgen E. Fischer Committed by James Bottomley

[PATCH] aha152x

attached my patch for the aha152x driver.  Tested for pcmcia and not
pcmcia and various devices.

changes in the aha152x driver:
- gather code that is not used by PCMCIA at the end
- move request_region for !PCMCIA case to detection
- migration to new scsi host api (remove legacy code)
- free host scribble before scsi_done
- fix error handling
- one isapnp device added to id_table

and in the pcmcia stub module:
- default to synchronous transfers
- release_region hack removed
- let core module do the scsi host api calls.
parent 53e978e8
/* aha152x.c -- Adaptec AHA-152x driver /* aha152x.c -- Adaptec AHA-152x driver
* Author: Jürgen E. Fischer, fischer@norbit.de * Author: Jürgen E. Fischer, fischer@norbit.de
* Copyright 1993-2000 Jürgen E. Fischer * Copyright 1993-2004 Jürgen E. Fischer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -13,9 +13,17 @@ ...@@ -13,9 +13,17 @@
* General Public License for more details. * General Public License for more details.
* *
* *
* $Id: aha152x.c,v 2.6 2003/10/30 20:52:47 fischer Exp $ * $Id: aha152x.c,v 2.7 2004/01/24 11:42:59 fischer Exp $
* *
* $Log: aha152x.c,v $ * $Log: aha152x.c,v $
* Revision 2.7 2004/01/24 11:42:59 fischer
* - gather code that is not used by PCMCIA at the end
* - move request_region for !PCMCIA case to detection
* - migration to new scsi host api (remove legacy code)
* - free host scribble before scsi_done
* - fix error handling
* - one isapnp device added to id_table
*
* Revision 2.6 2003/10/30 20:52:47 fischer * Revision 2.6 2003/10/30 20:52:47 fischer
* - interfaces changes for kernel 2.6 * - interfaces changes for kernel 2.6
* - aha152x_probe_one introduced for pcmcia stub * - aha152x_probe_one introduced for pcmcia stub
...@@ -344,7 +352,8 @@ enum { ...@@ -344,7 +352,8 @@ enum {
MODULE_DESCRIPTION(AHA152X_REVID); MODULE_DESCRIPTION(AHA152X_REVID);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#if defined(MODULE) && !defined(PCMCIA) #if !defined(PCMCIA)
#if defined(MODULE)
MODULE_PARM(io, "1-2i"); MODULE_PARM(io, "1-2i");
MODULE_PARM_DESC(io,"base io address of controller"); MODULE_PARM_DESC(io,"base io address of controller");
static int io[] = {0, 0}; static int io[] = {0, 0};
...@@ -398,21 +407,23 @@ MODULE_PARM(aha152x1, "1-9i"); ...@@ -398,21 +407,23 @@ MODULE_PARM(aha152x1, "1-9i");
MODULE_PARM_DESC(aha152x1, "parameters for second controller"); MODULE_PARM_DESC(aha152x1, "parameters for second controller");
static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
#endif /* !defined(AHA152X_DEBUG) */ #endif /* !defined(AHA152X_DEBUG) */
#endif /* MODULE && !PCMCIA */ #endif /* MODULE */
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id id_table[] __devinitdata = { static struct isapnp_device_id id_table[] __devinitdata = {
{ ISAPNP_DEVICE_SINGLE('A','D','P',0x1505, 'A','D','P',0x1505), }, { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1530), 0 },
{ ISAPNP_DEVICE_SINGLE_END, } { ISAPNP_DEVICE_SINGLE_END, }
}; };
MODULE_DEVICE_TABLE(isapnp, id_table); MODULE_DEVICE_TABLE(isapnp, id_table);
#endif /* ISAPNP */ #endif /* ISAPNP */
/* set by aha152x_setup according to the command line */ #endif /* !PCMCIA */
static int setup_count;
static int registered_count; static int registered_count=0;
static struct aha152x_setup setup[2]; static struct Scsi_Host *aha152x_host[2] = {0, 0};
static struct Scsi_Host *aha152x_host[2];
static Scsi_Host_Template aha152x_driver_template; static Scsi_Host_Template aha152x_driver_template;
/* /*
...@@ -658,7 +669,6 @@ static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *); ...@@ -658,7 +669,6 @@ static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *);
static void reset_ports(struct Scsi_Host *shpnt); static void reset_ports(struct Scsi_Host *shpnt);
static void aha152x_error(struct Scsi_Host *shpnt, char *msg); static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
static void done(struct Scsi_Host *shpnt, int error); static void done(struct Scsi_Host *shpnt, int error);
static int checksetup(struct aha152x_setup *setup);
/* diagnostics */ /* diagnostics */
static void disp_ports(struct Scsi_Host *shpnt); static void disp_ports(struct Scsi_Host *shpnt);
...@@ -666,66 +676,6 @@ static void show_command(Scsi_Cmnd * ptr); ...@@ -666,66 +676,6 @@ static void show_command(Scsi_Cmnd * ptr);
static void show_queues(struct Scsi_Host *shpnt); static void show_queues(struct Scsi_Host *shpnt);
static void disp_enintr(struct Scsi_Host *shpnt); static void disp_enintr(struct Scsi_Host *shpnt);
/* possible i/o addresses for the AIC-6260; default first */
static unsigned short ports[] = { 0x340, 0x140 };
#if !defined(SKIP_BIOSTEST)
/* possible locations for the Adaptec BIOS; defaults first */
static unsigned int addresses[] =
{
0xdc000, /* default first */
0xc8000,
0xcc000,
0xd0000,
0xd4000,
0xd8000,
0xe0000,
0xeb800, /* VTech Platinum SMP */
0xf0000,
};
/* signatures for various AIC-6[23]60 based controllers.
The point in detecting signatures is to avoid useless and maybe
harmful probes on ports. I'm not sure that all listed boards pass
auto-configuration. For those which fail the BIOS signature is
obsolete, because user intervention to supply the configuration is
needed anyway. May be an information whether or not the BIOS supports
extended translation could be also useful here. */
static struct signature {
unsigned char *signature;
int sig_offset;
int sig_length;
} signatures[] =
{
{ "Adaptec AHA-1520 BIOS", 0x102e, 21 },
/* Adaptec 152x */
{ "Adaptec AHA-1520B", 0x000b, 17 },
/* Adaptec 152x rev B */
{ "Adaptec AHA-1520B", 0x0026, 17 },
/* Iomega Jaz Jet ISA (AIC6370Q) */
{ "Adaptec ASW-B626 BIOS", 0x1029, 21 },
/* on-board controller */
{ "Adaptec BIOS: ASW-B626", 0x000f, 22 },
/* on-board controller */
{ "Adaptec ASW-B626 S2", 0x2e6c, 19 },
/* on-board controller */
{ "Adaptec BIOS:AIC-6360", 0x000c, 21 },
/* on-board controller */
{ "ScsiPro SP-360 BIOS", 0x2873, 19 },
/* ScsiPro-Controller */
{ "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },
/* Gigabyte Local-Bus-SCSI */
{ "Adaptec BIOS:AVA-282X", 0x000c, 21 },
/* Adaptec 282x */
{ "Adaptec IBM Dock II SCSI", 0x2edd, 24 },
/* IBM Thinkpad Dock II */
{ "Adaptec BIOS:AHA-1532P", 0x001c, 22 },
/* IBM Thinkpad Dock II SCSI */
{ "DTC3520A Host Adapter BIOS", 0x318a, 26 },
/* DTC 3520A ISA SCSI */
};
#endif
/* /*
* queue services: * queue services:
...@@ -799,141 +749,6 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp) ...@@ -799,141 +749,6 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp)
return ptr; return ptr;
} }
#if defined(PCMCIA) || !defined(MODULE)
static void aha152x_setup(char *str, int *ints)
{
if(setup_count>=ARRAY_SIZE(setup)) {
printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
return;
}
setup[setup_count].conf = str;
setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340;
setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11;
setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7;
setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT;
if (ints[0] > 9) {
printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
"[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");
#else
if (ints[0] > 8) { /*}*/
printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
"[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
#endif
} else {
setup_count++;
}
}
#endif
#if !defined(MODULE)
static int __init do_setup(char *str)
{
#if defined(AHA152X_DEBUG)
int ints[11];
#else
int ints[10];
#endif
int count=setup_count;
get_options(str, ARRAY_SIZE(ints), ints);
aha152x_setup(str,ints);
return count<setup_count;
}
__setup("aha152x=", do_setup);
#endif
/*
* Test, if port_base is valid.
*
*/
static int aha152x_porttest(int io_port)
{
int i;
SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16; i++)
SETPORT(io_port + O_STACK, i);
SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++)
;
return (i == 16);
}
static int tc1550_porttest(int io_port)
{
int i;
SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16; i++)
SETPORT(io_port + O_STACK, i);
SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16 && GETPORT(io_port + O_TC_STACK) == i; i++)
;
return (i == 16);
}
static int checksetup(struct aha152x_setup *setup)
{
#if !defined(PCMCIA)
int i;
for (i = 0; i < ARRAY_SIZE(ports) && (setup->io_port != ports[i]); i++)
;
if (i == ARRAY_SIZE(ports))
return 0;
#endif
if (!request_region(setup->io_port, IO_RANGE, "aha152x"))
return 0;
if(aha152x_porttest(setup->io_port)) {
setup->tc1550=0;
} else if(tc1550_porttest(setup->io_port)) {
setup->tc1550=1;
} else {
release_region(setup->io_port, IO_RANGE);
return 0;
}
release_region(setup->io_port, IO_RANGE);
if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX))
return 0;
if ((setup->scsiid < 0) || (setup->scsiid > 7))
return 0;
if ((setup->reconnect < 0) || (setup->reconnect > 1))
return 0;
if ((setup->parity < 0) || (setup->parity > 1))
return 0;
if ((setup->synchronous < 0) || (setup->synchronous > 1))
return 0;
if ((setup->ext_trans < 0) || (setup->ext_trans > 1))
return 0;
return 1;
}
static inline struct Scsi_Host *lookup_irq(int irqno) static inline struct Scsi_Host *lookup_irq(int irqno)
{ {
int i; int i;
...@@ -950,7 +765,6 @@ static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs) ...@@ -950,7 +765,6 @@ static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs)
struct Scsi_Host *shpnt = lookup_irq(irqno); struct Scsi_Host *shpnt = lookup_irq(irqno);
if (!shpnt) { if (!shpnt) {
/* no point using HOSTNO here! */
printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno); printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno);
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -961,17 +775,19 @@ static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs) ...@@ -961,17 +775,19 @@ static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
{ {
struct Scsi_Host *shpnt; struct Scsi_Host *shpnt;
shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata)); shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata));
if (!shpnt) { if (!shpnt) {
printk(KERN_ERR "aha152x: scsi_register failed\n"); printk(KERN_ERR "aha152x: scsi_host_alloc failed\n");
return NULL; return NULL;
} }
/* need to have host registered before triggering any interrupt */
aha152x_host[registered_count] = shpnt;
memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt)); memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
shpnt->io_port = setup->io_port; shpnt->io_port = setup->io_port;
...@@ -1034,24 +850,19 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) ...@@ -1034,24 +850,19 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
DELAY, DELAY,
EXT_TRANS ? "enabled" : "disabled"); EXT_TRANS ? "enabled" : "disabled");
if (!request_region(shpnt->io_port, IO_RANGE, "aha152x"))
goto out_unregister;
/* not expecting any interrupts */ /* not expecting any interrupts */
SETPORT(SIMODE0, 0); SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, 0); SETPORT(SIMODE1, 0);
if (request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) { if( request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) {
printk(KERN_ERR "aha152x%d: driver needs an IRQ.\n", shpnt->host_no); printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq);
goto out_release_region; goto out_host_put;
} }
HOSTDATA(shpnt)->swint = 0; HOSTDATA(shpnt)->swint = 0;
printk(KERN_INFO "aha152x%d: trying software interrupt, ", shpnt->host_no); printk(KERN_INFO "aha152x%d: trying software interrupt, ", shpnt->host_no);
/* need to have host registered before triggering any interrupt */
aha152x_host[registered_count] = shpnt;
mb(); mb();
SETPORT(DMACNTRL0, SWINT|INTEN); SETPORT(DMACNTRL0, SWINT|INTEN);
mdelay(1000); mdelay(1000);
...@@ -1066,9 +877,9 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) ...@@ -1066,9 +877,9 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
SETPORT(DMACNTRL0, INTEN); SETPORT(DMACNTRL0, INTEN);
printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. " printk(KERN_ERR "aha152x%d: irq %d possibly wrong. "
"Please verify.\n", shpnt->host_no, shpnt->irq); "Please verify.\n", shpnt->host_no, shpnt->irq);
goto out_unregister_host; goto out_host_put;
} }
printk("ok.\n"); printk("ok.\n");
...@@ -1077,457 +888,185 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) ...@@ -1077,457 +888,185 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
SETPORT(SSTAT0, 0x7f); SETPORT(SSTAT0, 0x7f);
SETPORT(SSTAT1, 0xef); SETPORT(SSTAT1, 0xef);
if (request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) { if ( request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) {
printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", shpnt->host_no); printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq);
goto out_unregister_host; goto out_host_put;
}
if( scsi_add_host(shpnt, 0) ) {
free_irq(shpnt->irq, shpnt);
printk(KERN_ERR "aha152x%d: failed to add host.\n", shpnt->host_no);
goto out_host_put;
} }
scsi_add_host(shpnt, 0);
scsi_scan_host(shpnt); scsi_scan_host(shpnt);
return shpnt; /* the pcmcia stub needs the return value; */
out_unregister_host: registered_count++;
aha152x_host[registered_count] = NULL;
out_release_region: return shpnt;
release_region(shpnt->io_port, IO_RANGE);
out_unregister: out_host_put:
aha152x_host[registered_count]=0;
scsi_host_put(shpnt); scsi_host_put(shpnt);
return NULL;
return 0;
} }
static int __init aha152x_init(void) void aha152x_release(struct Scsi_Host *shpnt)
{ {
int i, j, ok; if(!shpnt)
#if defined(AUTOCONF) return;
aha152x_config conf;
if (shpnt->irq)
free_irq(shpnt->irq, shpnt);
#if !defined(PCMCIA)
if (shpnt->io_port)
release_region(shpnt->io_port, IO_RANGE);
#endif #endif
#ifdef __ISAPNP__ #ifdef __ISAPNP__
struct pnp_dev *dev=0, *pnpdev[2] = {0, 0}; if (HOSTDATA(shpnt)->pnpdev)
pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
#endif #endif
if (setup_count) { scsi_remove_host(shpnt);
printk(KERN_INFO "aha152x: processing commandline: "); scsi_host_put(shpnt);
}
for (i = 0; i < setup_count; i++)
if (!checksetup(&setup[i])) {
printk(KERN_ERR "\naha152x: %s\n", setup[i].conf);
printk(KERN_ERR "aha152x: invalid line\n");
}
printk("ok\n");
}
#if defined(SETUP0) /*
if (setup_count < ARRAY_SIZE(setup)) { * setup controller to generate interrupts depending
struct aha152x_setup override = SETUP0; * on current state (lock has to be acquired)
*
*/
static int setup_expected_interrupts(struct Scsi_Host *shpnt)
{
if(CURRENT_SC) {
CURRENT_SC->SCp.phase |= 1 << 16;
if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if(CURRENT_SC->SCp.phase & selecting) {
if (!checksetup(&override)) { DPRINTK(debug_intr, DEBUG_LEAD "expecting: (seldo) (seltimo) (seldi)\n", CMDINFO(CURRENT_SC));
printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", SETPORT(SSTAT1, SELTO);
override.io_port, SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
override.irq, SETPORT(SIMODE1, ENSELTIMO);
override.scsiid, } else {
override.reconnect, DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (busfree) %s\n", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.phase & spiordy ? "(spiordy)" : "");
override.parity, SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0);
override.synchronous, SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
override.delay,
override.ext_trans);
} else
setup[setup_count++] = override;
}
}
#endif
#if defined(SETUP1)
if (setup_count < ARRAY_SIZE(setup)) {
struct aha152x_setup override = SETUP1;
if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
if (!checksetup(&override)) {
printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
override.io_port,
override.irq,
override.scsiid,
override.reconnect,
override.parity,
override.synchronous,
override.delay,
override.ext_trans);
} else
setup[setup_count++] = override;
} }
} else if(STATE==seldi) {
DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (identify)\n", CMDINFO(CURRENT_SC));
SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
} else {
DPRINTK(debug_intr, DEBUG_LEAD "expecting: %s %s\n",
CMDINFO(CURRENT_SC),
DISCONNECTED_SC ? "(reselection)" : "",
ISSUE_SC ? "(busfree)" : "");
SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
SETPORT(SIMODE1, ENSCSIRST | ( (ISSUE_SC||DONE_SC) ? ENBUSFREE : 0));
} }
#endif
#if defined(MODULE) && !defined(PCMCIA) if(!HOSTDATA(shpnt)->in_intr)
if (setup_count<ARRAY_SIZE(setup) && (aha152x[0]!=0 || io[0]!=0 || irq[0]!=0)) { SETBITS(DMACNTRL0, INTEN);
if(aha152x[0]!=0) {
setup[setup_count].conf = "";
setup[setup_count].io_port = aha152x[0];
setup[setup_count].irq = aha152x[1];
setup[setup_count].scsiid = aha152x[2];
setup[setup_count].reconnect = aha152x[3];
setup[setup_count].parity = aha152x[4];
setup[setup_count].synchronous = aha152x[5];
setup[setup_count].delay = aha152x[6];
setup[setup_count].ext_trans = aha152x[7];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = aha152x[8];
#endif
} else if(io[0]!=0 || irq[0]!=0) {
if(io[0]!=0) setup[setup_count].io_port = io[0];
if(irq[0]!=0) setup[setup_count].irq = irq[0];
setup[setup_count].scsiid = scsiid[0]; return TESTHI(DMASTAT, INTSTAT);
setup[setup_count].reconnect = reconnect[0]; }
setup[setup_count].parity = parity[0];
setup[setup_count].synchronous = sync[0];
setup[setup_count].delay = delay[0];
setup[setup_count].ext_trans = exttrans[0];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = debug[0];
#endif
}
if (checksetup(&setup[setup_count]))
setup_count++;
else
printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
setup[setup_count].io_port,
setup[setup_count].irq,
setup[setup_count].scsiid,
setup[setup_count].reconnect,
setup[setup_count].parity,
setup[setup_count].synchronous,
setup[setup_count].delay,
setup[setup_count].ext_trans);
}
if (setup_count<ARRAY_SIZE(setup) && (aha152x1[0]!=0 || io[1]!=0 || irq[1]!=0)) { /*
if(aha152x1[0]!=0) { * Queue a command and setup interrupts for a free bus.
setup[setup_count].conf = ""; */
setup[setup_count].io_port = aha152x1[0]; static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *))
setup[setup_count].irq = aha152x1[1]; {
setup[setup_count].scsiid = aha152x1[2]; struct Scsi_Host *shpnt = SCpnt->device->host;
setup[setup_count].reconnect = aha152x1[3]; unsigned long flags;
setup[setup_count].parity = aha152x1[4];
setup[setup_count].synchronous = aha152x1[5];
setup[setup_count].delay = aha152x1[6];
setup[setup_count].ext_trans = aha152x1[7];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = aha152x1[8];
#endif
} else if(io[1]!=0 || irq[1]!=0) {
if(io[1]!=0) setup[setup_count].io_port = io[1];
if(irq[1]!=0) setup[setup_count].irq = irq[1];
setup[setup_count].scsiid = scsiid[1];
setup[setup_count].reconnect = reconnect[1];
setup[setup_count].parity = parity[1];
setup[setup_count].synchronous = sync[1];
setup[setup_count].delay = delay[1];
setup[setup_count].ext_trans = exttrans[1];
#if defined(AHA152X_DEBUG) #if defined(AHA152X_DEBUG)
setup[setup_count].debug = debug[1]; if (HOSTDATA(shpnt)->debug & debug_queue) {
#endif 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);
if (checksetup(&setup[setup_count])) print_command(SCpnt->cmnd);
setup_count++;
else
printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
setup[setup_count].io_port,
setup[setup_count].irq,
setup[setup_count].scsiid,
setup[setup_count].reconnect,
setup[setup_count].parity,
setup[setup_count].synchronous,
setup[setup_count].delay,
setup[setup_count].ext_trans);
} }
#endif #endif
#ifdef __ISAPNP__ SCpnt->scsi_done = done;
while ( setup_count<ARRAY_SIZE(setup) && (dev=pnp_find_dev(NULL, ISAPNP_VENDOR('A','D','P'), ISAPNP_FUNCTION(0x1505), dev)) ) { SCpnt->resid = SCpnt->request_bufflen;
if (pnp_device_attach(dev) < 0) SCpnt->SCp.phase = not_issued | phase;
continue; SCpnt->SCp.Status = CHECK_CONDITION;
if (pnp_activate_dev(dev) < 0) { SCpnt->SCp.Message = 0;
pnp_device_detach(dev); SCpnt->SCp.have_data_in = 0;
continue; SCpnt->SCp.sent_command = 0;
if(SCpnt->SCp.phase & (resetting|check_condition)) {
if(SCpnt->host_scribble==0 || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
printk(ERR_LEAD "cannot reuse command\n", CMDINFO(SCpnt));
return FAILED;
} }
if (!pnp_port_valid(dev, 0)) { } else {
pnp_device_detach(dev); SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
continue; if(SCpnt->host_scribble==0) {
printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
return FAILED;
} }
if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) {
pnp_device_detach(dev);
continue;
} }
setup[setup_count].io_port = pnp_port_start(dev, 0);
setup[setup_count].irq = pnp_irq(dev, 0); SCNEXT(SCpnt) = 0;
setup[setup_count].scsiid = 7; SCSEM(SCpnt) = sem;
setup[setup_count].reconnect = 1;
setup[setup_count].parity = 1; /* setup scratch area
setup[setup_count].synchronous = 1; SCp.ptr : buffer pointer
setup[setup_count].delay = DELAY_DEFAULT; SCp.this_residual : buffer length
setup[setup_count].ext_trans = 0; SCp.buffer : next buffer
#if defined(AHA152X_DEBUG) SCp.buffers_residual : left buffers in list
setup[setup_count].debug = DEBUG_DEFAULT; SCp.phase : current state of the command */
#endif if (SCpnt->use_sg) {
pnpdev[setup_count] = dev; SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
printk (KERN_INFO SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer);
"aha152x: found ISAPnP AVA-1505A at io=0x%03x, irq=%d\n", SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
setup[setup_count].io_port, setup[setup_count].irq); SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
setup_count++; } else {
SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
SCpnt->SCp.this_residual = SCpnt->request_bufflen;
SCpnt->SCp.buffer = NULL;
SCpnt->SCp.buffers_residual = 0;
} }
DO_LOCK(flags);
#if defined(AHA152X_STAT)
HOSTDATA(shpnt)->total_commands++;
#endif #endif
#if defined(AUTOCONF) /* Turn led on, when this is the first command. */
if (setup_count<ARRAY_SIZE(setup)) { HOSTDATA(shpnt)->commands++;
#if !defined(SKIP_BIOSTEST) if (HOSTDATA(shpnt)->commands==1)
ok = 0; SETPORT(PORTA, 1);
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);
if (!ok && setup_count == 0) append_SC(&ISSUE_SC, SCpnt);
return 0;
printk(KERN_INFO "aha152x: BIOS test: passed, "); if(!HOSTDATA(shpnt)->in_intr)
#else setup_expected_interrupts(shpnt);
printk(KERN_INFO "aha152x: ");
#endif /* !SKIP_BIOSTEST */
ok = 0; DO_UNLOCK(flags);
for (i = 0; i < ARRAY_SIZE(ports) && setup_count < 2; i++) {
if ((setup_count == 1) && (setup[0].io_port == ports[i]))
continue;
if (aha152x_porttest(ports[i])) { return 0;
ok++; }
setup[setup_count].io_port = ports[i];
setup[setup_count].tc1550 = 0;
conf.cf_port = /*
(GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB); * queue a command
*
*/
static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
#if 0
if(*SCpnt->cmnd == REQUEST_SENSE) {
SCpnt->result = 0;
done(SCpnt);
setup[setup_count].irq = IRQ_MIN + conf.cf_irq; return 0;
setup[setup_count].scsiid = conf.cf_id; }
setup[setup_count].reconnect = conf.cf_tardisc;
setup[setup_count].parity = !conf.cf_parity;
setup[setup_count].synchronous = conf.cf_syncneg;
setup[setup_count].delay = DELAY_DEFAULT;
setup[setup_count].ext_trans = 0;
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = DEBUG_DEFAULT;
#endif
setup_count++;
} else if (tc1550_porttest(ports[i])) {
ok++;
setup[setup_count].io_port = ports[i];
setup[setup_count].tc1550 = 1;
conf.cf_port =
(GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
setup[setup_count].scsiid = conf.cf_id;
setup[setup_count].reconnect = conf.cf_tardisc;
setup[setup_count].parity = !conf.cf_parity;
setup[setup_count].synchronous = conf.cf_syncneg;
setup[setup_count].delay = DELAY_DEFAULT;
setup[setup_count].ext_trans = 0;
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = DEBUG_DEFAULT;
#endif
setup_count++;
}
}
if (ok)
printk("auto configuration: ok, ");
}
#endif
printk("detected %d controller(s)\n", setup_count);
for (i=0; i<setup_count; i++) {
aha152x_probe_one(&setup[i]);
if (aha152x_host[registered_count]) {
#ifdef __ISAPNP__
if(pnpdev[i])
HOSTDATA(aha152x_host[registered_count])->pnpdev=pnpdev[i];
#endif
registered_count++;
}
}
return registered_count>0;
}
static int aha152x_release(struct Scsi_Host *shpnt)
{
if (shpnt->irq)
free_irq(shpnt->irq, shpnt);
if (shpnt->io_port)
release_region(shpnt->io_port, IO_RANGE);
#ifdef __ISAPNP__
if (HOSTDATA(shpnt)->pnpdev)
pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
#endif
scsi_host_put(shpnt);
return 0;
}
static void __exit aha152x_exit(void)
{
int i;
for(i=0; i<ARRAY_SIZE(setup); i++) {
if(aha152x_host[i]) {
scsi_remove_host(aha152x_host[i]);
aha152x_release(aha152x_host[i]);
aha152x_host[i]=0;
}
}
}
/*
* setup controller to generate interrupts depending
* on current state (lock has to be acquired)
*
*/
static int setup_expected_interrupts(struct Scsi_Host *shpnt)
{
if(CURRENT_SC) {
CURRENT_SC->SCp.phase |= 1 << 16;
if(CURRENT_SC->SCp.phase & selecting) {
DPRINTK(debug_intr, DEBUG_LEAD "expecting: (seldo) (seltimo) (seldi)\n", CMDINFO(CURRENT_SC));
SETPORT(SSTAT1, SELTO);
SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
SETPORT(SIMODE1, ENSELTIMO);
} else {
DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (busfree) %s\n", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.phase & spiordy ? "(spiordy)" : "");
SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0);
SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
}
} else if(STATE==seldi) {
DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (identify)\n", CMDINFO(CURRENT_SC));
SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
} else {
DPRINTK(debug_intr, DEBUG_LEAD "expecting: %s %s\n",
CMDINFO(CURRENT_SC),
DISCONNECTED_SC ? "(reselection)" : "",
ISSUE_SC ? "(busfree)" : "");
SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
SETPORT(SIMODE1, ENSCSIRST | ( (ISSUE_SC||DONE_SC) ? ENBUSFREE : 0));
}
if(!HOSTDATA(shpnt)->in_intr)
SETBITS(DMACNTRL0, INTEN);
return TESTHI(DMASTAT, INTSTAT);
}
/*
* Queue a command and setup interrupts for a free bus.
*/
static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, void (*done)(Scsi_Cmnd *))
{
struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags;
#if defined(AHA152X_DEBUG)
if (HOSTDATA(shpnt)->debug & debug_queue) {
printk(INFO_LEAD "queue: cmd_len=%d pieces=%d size=%u cmnd=",
CMDINFO(SCpnt), SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
print_command(SCpnt->cmnd);
}
#endif
SCpnt->scsi_done = done;
SCpnt->resid = SCpnt->request_bufflen;
SCpnt->SCp.phase = not_issued | phase;
SCpnt->SCp.Status = CHECK_CONDITION;
SCpnt->SCp.Message = 0;
SCpnt->SCp.have_data_in = 0;
SCpnt->SCp.sent_command = 0;
if(SCpnt->SCp.phase & (resetting|check_condition)) {
if(SCpnt->host_scribble==0 || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
printk(ERR_LEAD "cannot reuse command\n", CMDINFO(SCpnt));
return FAILED;
}
} else {
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;
}
}
SCNEXT(SCpnt) = 0;
SCSEM(SCpnt) = sem;
/* setup scratch area
SCp.ptr : buffer pointer
SCp.this_residual : buffer length
SCp.buffer : next buffer
SCp.buffers_residual : left buffers in list
SCp.phase : current state of the command */
if (SCpnt->use_sg) {
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
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 {
SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
SCpnt->SCp.this_residual = SCpnt->request_bufflen;
SCpnt->SCp.buffer = NULL;
SCpnt->SCp.buffers_residual = 0;
}
DO_LOCK(flags);
#if defined(AHA152X_STAT)
HOSTDATA(shpnt)->total_commands++;
#endif
/* Turn led on, when this is the first command. */
HOSTDATA(shpnt)->commands++;
if (HOSTDATA(shpnt)->commands==1)
SETPORT(PORTA, 1);
append_SC(&ISSUE_SC, SCpnt);
if(!HOSTDATA(shpnt)->in_intr)
setup_expected_interrupts(shpnt);
DO_UNLOCK(flags);
return 0;
}
/*
* queue a command
*
*/
static int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
#if 0
if(*SCpnt->cmnd == REQUEST_SENSE) {
SCpnt->result = 0;
done(SCpnt);
return 0;
}
#endif #endif
return aha152x_internal_queue(SCpnt, 0, 0, done); return aha152x_internal_queue(SCpnt, 0, 0, done);
...@@ -1561,11 +1100,6 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt) ...@@ -1561,11 +1100,6 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt)
Scsi_Cmnd *ptr; Scsi_Cmnd *ptr;
unsigned long flags; unsigned long flags;
if(!shpnt) {
printk(ERR_LEAD "abort(%p): no host structure\n", CMDINFO(SCpnt), SCpnt);
return FAILED;
}
#if defined(AHA152X_DEBUG) #if defined(AHA152X_DEBUG)
if(HOSTDATA(shpnt)->debug & debug_eh) { if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt); printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt);
...@@ -1610,15 +1144,12 @@ static void timer_expired(unsigned long p) ...@@ -1610,15 +1144,12 @@ static void timer_expired(unsigned long p)
Scsi_Cmnd *SCp = (Scsi_Cmnd *)p; Scsi_Cmnd *SCp = (Scsi_Cmnd *)p;
struct semaphore *sem = SCSEM(SCp); struct semaphore *sem = SCSEM(SCp);
struct Scsi_Host *shpnt = SCp->device->host; struct Scsi_Host *shpnt = SCp->device->host;
unsigned long flags;
/* remove command from issue queue */ /* remove command from issue queue */
if(remove_SC(&ISSUE_SC, SCp)) { DO_LOCK(flags);
printk(KERN_INFO "aha152x: ABORT timed out - removed from issue queue\n"); remove_SC(&ISSUE_SC, SCp);
kfree(SCp->host_scribble); DO_UNLOCK(flags);
SCp->host_scribble=0;
} else {
printk(KERN_INFO "aha152x: ABORT timed out - not on issue queue\n");
}
up(sem); up(sem);
} }
...@@ -1626,15 +1157,14 @@ static void timer_expired(unsigned long p) ...@@ -1626,15 +1157,14 @@ static void timer_expired(unsigned long p)
/* /*
* Reset a device * Reset a device
* *
* FIXME: never seen this live. might lockup...
*
*/ */
static int aha152x_device_reset(Scsi_Cmnd * SCpnt) static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
{ {
struct Scsi_Host *shpnt = SCpnt->device->host; struct Scsi_Host *shpnt = SCpnt->device->host;
DECLARE_MUTEX_LOCKED(sem); DECLARE_MUTEX_LOCKED(sem);
struct timer_list timer; struct timer_list timer;
int ret; int ret, issued, disconnected;
unsigned long flags;
#if defined(AHA152X_DEBUG) #if defined(AHA152X_DEBUG)
if(HOSTDATA(shpnt)->debug & debug_eh) { if(HOSTDATA(shpnt)->debug & debug_eh) {
...@@ -1648,13 +1178,18 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) ...@@ -1648,13 +1178,18 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
return FAILED; return FAILED;
} }
DO_LOCK(flags);
issued = remove_SC(&ISSUE_SC, SCpnt)==0;
disconnected = issued && remove_SC(&DISCONNECTED_SC, SCpnt);
DO_UNLOCK(flags);
SCpnt->cmd_len = 0; SCpnt->cmd_len = 0;
SCpnt->use_sg = 0; SCpnt->use_sg = 0;
SCpnt->request_buffer = 0; SCpnt->request_buffer = 0;
SCpnt->request_bufflen = 0; SCpnt->request_bufflen = 0;
init_timer(&timer); init_timer(&timer);
timer.data = (unsigned long) cmd; timer.data = (unsigned long) SCpnt;
timer.expires = jiffies + 100*HZ; /* 10s */ timer.expires = jiffies + 100*HZ; /* 10s */
timer.function = (void (*)(unsigned long)) timer_expired; timer.function = (void (*)(unsigned long)) timer_expired;
...@@ -1668,12 +1203,29 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) ...@@ -1668,12 +1203,29 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
SCpnt->request_buffer = SCpnt->buffer; SCpnt->request_buffer = SCpnt->buffer;
SCpnt->request_bufflen = SCpnt->bufflen; SCpnt->request_bufflen = SCpnt->bufflen;
DO_LOCK(flags);
if(SCpnt->SCp.phase & resetted) { if(SCpnt->SCp.phase & resetted) {
HOSTDATA(shpnt)->commands--;
if (!HOSTDATA(shpnt)->commands)
SETPORT(PORTA, 0);
kfree(SCpnt->host_scribble);
SCpnt->host_scribble=0;
ret = SUCCESS; ret = SUCCESS;
} else { } else {
/* requeue */
if(!issued) {
append_SC(&ISSUE_SC, SCpnt);
} else if(disconnected) {
append_SC(&DISCONNECTED_SC, SCpnt);
}
ret = FAILED; ret = FAILED;
} }
DO_UNLOCK(flags);
spin_lock_irq(shpnt->host_lock); spin_lock_irq(shpnt->host_lock);
return ret; return ret;
} }
...@@ -1681,13 +1233,17 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) ...@@ -1681,13 +1233,17 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
{ {
Scsi_Cmnd *ptr; Scsi_Cmnd *ptr;
unsigned long flags;
DO_LOCK(flags);
ptr=*SCs; ptr=*SCs;
while(ptr) { while(ptr) {
Scsi_Cmnd *next = SCNEXT(ptr); Scsi_Cmnd *next;
if(SCDATA(ptr)) {
next = SCNEXT(ptr);
} else {
printk(DEBUG_LEAD "queue corrupted at %p\n", CMDINFO(ptr), ptr);
next = 0;
}
if (!ptr->device->soft_reset) { if (!ptr->device->soft_reset) {
DPRINTK(debug_eh, DEBUG_LEAD "disconnected command %p removed\n", CMDINFO(ptr), ptr); DPRINTK(debug_eh, DEBUG_LEAD "disconnected command %p removed\n", CMDINFO(ptr), ptr);
...@@ -1699,8 +1255,6 @@ static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) ...@@ -1699,8 +1255,6 @@ static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
ptr = next; ptr = next;
} }
DO_UNLOCK(flags);
} }
/* /*
...@@ -1712,6 +1266,8 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -1712,6 +1266,8 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
struct Scsi_Host *shpnt = SCpnt->device->host; struct Scsi_Host *shpnt = SCpnt->device->host;
unsigned long flags; unsigned long flags;
DO_LOCK(flags);
#if defined(AHA152X_DEBUG) #if defined(AHA152X_DEBUG)
if(HOSTDATA(shpnt)->debug & debug_eh) { if(HOSTDATA(shpnt)->debug & debug_eh) {
printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt); printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt);
...@@ -1729,12 +1285,12 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -1729,12 +1285,12 @@ static int aha152x_bus_reset(Scsi_Cmnd *SCpnt)
SETPORT(SCSISEQ, 0); SETPORT(SCSISEQ, 0);
mdelay(DELAY); mdelay(DELAY);
DPRINTK(debug_eh, DEBUG_LEAD "bus reset returns\n", CMDINFO(SCpnt)); DPRINTK(debug_eh, DEBUG_LEAD "bus resetted\n", CMDINFO(SCpnt));
DO_LOCK(flags);
setup_expected_interrupts(shpnt); setup_expected_interrupts(shpnt);
if(HOSTDATA(shpnt)->commands==0) if(HOSTDATA(shpnt)->commands==0)
SETPORT(PORTA, 0); SETPORT(PORTA, 0);
DO_UNLOCK(flags); DO_UNLOCK(flags);
return SUCCESS; return SUCCESS;
...@@ -2000,6 +1556,7 @@ static void busfree_run(struct Scsi_Host *shpnt) ...@@ -2000,6 +1556,7 @@ static void busfree_run(struct Scsi_Host *shpnt)
#if defined(AHA152X_STAT) #if defined(AHA152X_STAT)
action++; action++;
#endif #endif
if(DONE_SC->SCp.phase & check_condition) { if(DONE_SC->SCp.phase & check_condition) {
#if 0 #if 0
if(HOSTDATA(shpnt)->debug & debug_eh) { if(HOSTDATA(shpnt)->debug & debug_eh) {
...@@ -2029,47 +1586,57 @@ static void busfree_run(struct Scsi_Host *shpnt) ...@@ -2029,47 +1586,57 @@ static void busfree_run(struct Scsi_Host *shpnt)
#endif #endif
if(!(DONE_SC->SCp.Status & not_issued)) { if(!(DONE_SC->SCp.Status & not_issued)) {
Scsi_Cmnd *ptr = DONE_SC;
DONE_SC=0;
#if 0 #if 0
DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(DONE_SC)); DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr));
#endif #endif
DONE_SC->cmnd[0] = REQUEST_SENSE; ptr->cmnd[0] = REQUEST_SENSE;
DONE_SC->cmnd[1] = 0; ptr->cmnd[1] = 0;
DONE_SC->cmnd[2] = 0; ptr->cmnd[2] = 0;
DONE_SC->cmnd[3] = 0; ptr->cmnd[3] = 0;
DONE_SC->cmnd[4] = sizeof(DONE_SC->sense_buffer); ptr->cmnd[4] = sizeof(ptr->sense_buffer);
DONE_SC->cmnd[5] = 0; ptr->cmnd[5] = 0;
DONE_SC->cmd_len = 6; ptr->cmd_len = 6;
DONE_SC->use_sg = 0; ptr->use_sg = 0;
DONE_SC->request_buffer = DONE_SC->sense_buffer; ptr->request_buffer = ptr->sense_buffer;
DONE_SC->request_bufflen = sizeof(DONE_SC->sense_buffer); ptr->request_bufflen = sizeof(ptr->sense_buffer);
DO_UNLOCK(flags); DO_UNLOCK(flags);
aha152x_internal_queue(DONE_SC, 0, check_condition, DONE_SC->scsi_done); aha152x_internal_queue(ptr, 0, check_condition, ptr->scsi_done);
DO_LOCK(flags); DO_LOCK(flags);
DONE_SC=0;
} else {
#if 0 #if 0
} else {
DPRINTK(debug_eh, ERR_LEAD "command not issued - CHECK CONDITION ignored\n", CMDINFO(DONE_SC)); DPRINTK(debug_eh, ERR_LEAD "command not issued - CHECK CONDITION ignored\n", CMDINFO(DONE_SC));
#endif #endif
} }
} }
if(DONE_SC && DONE_SC->scsi_done) { if(DONE_SC && DONE_SC->scsi_done) {
#if defined(AHA152X_DEBUG)
int hostno=DONE_SC->device->host->host_no;
int id=DONE_SC->device->id & 0xf;
int lun=DONE_SC->device->lun & 0x7;
#endif
Scsi_Cmnd *ptr = DONE_SC;
DONE_SC=0;
/* turn led off, when no commands are in the driver */ /* turn led off, when no commands are in the driver */
HOSTDATA(shpnt)->commands--; HOSTDATA(shpnt)->commands--;
if (!HOSTDATA(shpnt)->commands) if (!HOSTDATA(shpnt)->commands)
SETPORT(PORTA, 0); /* turn led off */ SETPORT(PORTA, 0); /* turn led off */
if(ptr->scsi_done != reset_done) {
kfree(ptr->host_scribble);
ptr->host_scribble=0;
}
DO_UNLOCK(flags); DO_UNLOCK(flags);
DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", CMDINFO(DONE_SC), DONE_SC); DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", hostno, id, lun, ptr);
DONE_SC->scsi_done(DONE_SC); ptr->scsi_done(ptr);
DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", CMDINFO(DONE_SC), DONE_SC); DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", hostno, id, lun, ptr);
DO_LOCK(flags); DO_LOCK(flags);
kfree(DONE_SC->host_scribble);
DONE_SC->host_scribble=0;
} }
DONE_SC=0; DONE_SC=0;
...@@ -2936,11 +2503,11 @@ static void rsti_run(struct Scsi_Host *shpnt) ...@@ -2936,11 +2503,11 @@ static void rsti_run(struct Scsi_Host *shpnt)
if (!ptr->device->soft_reset) { if (!ptr->device->soft_reset) {
remove_SC(&DISCONNECTED_SC, ptr); remove_SC(&DISCONNECTED_SC, ptr);
ptr->result = DID_RESET << 16;
ptr->scsi_done(ptr);
kfree(ptr->host_scribble); kfree(ptr->host_scribble);
ptr->host_scribble=0; ptr->host_scribble=0;
ptr->result = DID_RESET << 16;
ptr->scsi_done(ptr);
} }
ptr = next; ptr = next;
...@@ -3382,7 +2949,11 @@ static void show_command(Scsi_Cmnd *ptr) ...@@ -3382,7 +2949,11 @@ static void show_command(Scsi_Cmnd *ptr)
printk("aborted|"); printk("aborted|");
if (ptr->SCp.phase & resetted) if (ptr->SCp.phase & resetted)
printk("resetted|"); printk("resetted|");
if( SCDATA(ptr) ) {
printk("; next=0x%p\n", SCNEXT(ptr)); printk("; next=0x%p\n", SCNEXT(ptr));
} else {
printk("; next=(host scribble NULL)\n");
}
} }
/* /*
...@@ -3406,7 +2977,7 @@ static void show_queues(struct Scsi_Host *shpnt) ...@@ -3406,7 +2977,7 @@ static void show_queues(struct Scsi_Host *shpnt)
printk(KERN_DEBUG "none\n"); printk(KERN_DEBUG "none\n");
printk(KERN_DEBUG "disconnected_SC:\n"); printk(KERN_DEBUG "disconnected_SC:\n");
for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr)) for (ptr = DISCONNECTED_SC; ptr; ptr = SCDATA(ptr) ? SCNEXT(ptr) : 0)
show_command(ptr); show_command(ptr);
disp_ports(shpnt); disp_ports(shpnt);
...@@ -3713,208 +3284,690 @@ static int get_ports(struct Scsi_Host *shpnt, char *pos) ...@@ -3713,208 +3284,690 @@ static int get_ports(struct Scsi_Host *shpnt, char *pos)
return (pos - start); return (pos - start);
} }
static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt) static int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
{ {
if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0) if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
return -EINVAL; return -EINVAL;
#if defined(AHA152X_DEBUG)
if(length>14 && strncmp("debug ", buffer+8, 6)==0) {
int debug = HOSTDATA(shpnt)->debug;
HOSTDATA(shpnt)->debug = simple_strtoul(buffer+14, NULL, 0);
printk(KERN_INFO "aha152x%d: debugging options set to 0x%04x (were 0x%04x)\n", HOSTNO, HOSTDATA(shpnt)->debug, debug);
} else
#endif
#if defined(AHA152X_STAT)
if(length>13 && strncmp("reset", buffer+8, 5)==0) {
int i;
HOSTDATA(shpnt)->total_commands=0;
HOSTDATA(shpnt)->disconnections=0;
HOSTDATA(shpnt)->busfree_without_any_action=0;
HOSTDATA(shpnt)->busfree_without_old_command=0;
HOSTDATA(shpnt)->busfree_without_new_command=0;
HOSTDATA(shpnt)->busfree_without_done_command=0;
HOSTDATA(shpnt)->busfree_with_check_condition=0;
for (i = idle; i<maxstate; i++) {
HOSTDATA(shpnt)->count[i]=0;
HOSTDATA(shpnt)->count_trans[i]=0;
HOSTDATA(shpnt)->time[i]=0;
}
printk(KERN_INFO "aha152x%d: stats reseted.\n", HOSTNO);
} else
#endif
{
return -EINVAL;
}
return length;
}
#undef SPRINTF
#define SPRINTF(args...) \
do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
off_t offset, int length, int inout)
{
int i;
char *pos = buffer;
Scsi_Cmnd *ptr;
unsigned long flags;
int thislength;
DPRINTK(debug_procinfo,
KERN_DEBUG "aha152x_proc_info: buffer=%p offset=%ld length=%d hostno=%d inout=%d\n",
buffer, offset, length, shpnt->host_no, inout);
if (inout)
return aha152x_set_info(buffer, length, shpnt);
SPRINTF(AHA152X_REVID "\n");
SPRINTF("ioports 0x%04lx to 0x%04lx\n",
shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1);
SPRINTF("interrupt 0x%02x\n", shpnt->irq);
SPRINTF("disconnection/reconnection %s\n",
RECONNECT ? "enabled" : "disabled");
SPRINTF("parity checking %s\n",
PARITY ? "enabled" : "disabled");
SPRINTF("synchronous transfers %s\n",
SYNCHRONOUS ? "enabled" : "disabled");
SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands);
if(SYNCHRONOUS) {
SPRINTF("synchronously operating targets (tick=50 ns):\n");
for (i = 0; i < 8; i++)
if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
i,
(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
HOSTDATA(shpnt)->syncrate[i] & 0x0f);
}
#if defined(AHA152X_DEBUG)
#define PDEBUG(flags,txt) \
if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
SPRINTF("enabled debugging options: ");
PDEBUG(debug_procinfo, "procinfo");
PDEBUG(debug_queue, "queue");
PDEBUG(debug_intr, "interrupt");
PDEBUG(debug_selection, "selection");
PDEBUG(debug_msgo, "message out");
PDEBUG(debug_msgi, "message in");
PDEBUG(debug_status, "status");
PDEBUG(debug_cmd, "command");
PDEBUG(debug_datai, "data in");
PDEBUG(debug_datao, "data out");
PDEBUG(debug_eh, "eh");
PDEBUG(debug_locks, "locks");
PDEBUG(debug_phases, "phases");
SPRINTF("\n");
#endif
SPRINTF("\nqueue status:\n");
DO_LOCK(flags);
if (ISSUE_SC) {
SPRINTF("not yet issued commands:\n");
for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
pos += get_command(pos, ptr);
} else
SPRINTF("no not yet issued commands\n");
DO_UNLOCK(flags);
if (CURRENT_SC) {
SPRINTF("current command:\n");
pos += get_command(pos, CURRENT_SC);
} else
SPRINTF("no current command\n");
if (DISCONNECTED_SC) {
SPRINTF("disconnected commands:\n");
for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
pos += get_command(pos, ptr);
} else
SPRINTF("no disconnected commands\n");
pos += get_ports(shpnt, pos);
#if defined(AHA152X_STAT)
SPRINTF("statistics:\n"
"total commands: %d\n"
"disconnections: %d\n"
"busfree with check condition: %d\n"
"busfree without old command: %d\n"
"busfree without new command: %d\n"
"busfree without done command: %d\n"
"busfree without any action: %d\n"
"state "
"transitions "
"count "
"time\n",
HOSTDATA(shpnt)->total_commands,
HOSTDATA(shpnt)->disconnections,
HOSTDATA(shpnt)->busfree_with_check_condition,
HOSTDATA(shpnt)->busfree_without_old_command,
HOSTDATA(shpnt)->busfree_without_new_command,
HOSTDATA(shpnt)->busfree_without_done_command,
HOSTDATA(shpnt)->busfree_without_any_action);
for(i=0; i<maxstate; i++) {
SPRINTF("%-10s %-12d %-12d %-12ld\n",
states[i].name,
HOSTDATA(shpnt)->count_trans[i],
HOSTDATA(shpnt)->count[i],
HOSTDATA(shpnt)->time[i]);
}
#endif
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: pos=%p\n", pos);
thislength = pos - (buffer + offset);
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: length=%d thislength=%d\n", length, thislength);
if(thislength<0) {
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: output too short\n");
*start = 0;
return 0;
}
thislength = thislength<length ? thislength : length;
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: return %d\n", thislength);
*start = buffer + offset;
return thislength < length ? thislength : length;
}
static Scsi_Host_Template aha152x_driver_template = {
.module = THIS_MODULE,
.name = AHA152X_REVID,
.proc_name = "aha152x",
.proc_info = aha152x_proc_info,
.queuecommand = aha152x_queue,
.eh_abort_handler = aha152x_abort,
.eh_device_reset_handler = aha152x_device_reset,
.eh_bus_reset_handler = aha152x_bus_reset,
.eh_host_reset_handler = aha152x_host_reset,
.bios_param = aha152x_biosparam,
.can_queue = 1,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
};
#if !defined(PCMCIA)
static int setup_count;
static struct aha152x_setup setup[2];
/* possible i/o addresses for the AIC-6260; default first */
static unsigned short ports[] = { 0x340, 0x140 };
#if !defined(SKIP_BIOSTEST)
/* possible locations for the Adaptec BIOS; defaults first */
static unsigned int addresses[] =
{
0xdc000, /* default first */
0xc8000,
0xcc000,
0xd0000,
0xd4000,
0xd8000,
0xe0000,
0xeb800, /* VTech Platinum SMP */
0xf0000,
};
/* signatures for various AIC-6[23]60 based controllers.
The point in detecting signatures is to avoid useless and maybe
harmful probes on ports. I'm not sure that all listed boards pass
auto-configuration. For those which fail the BIOS signature is
obsolete, because user intervention to supply the configuration is
needed anyway. May be an information whether or not the BIOS supports
extended translation could be also useful here. */
static struct signature {
unsigned char *signature;
int sig_offset;
int sig_length;
} signatures[] =
{
{ "Adaptec AHA-1520 BIOS", 0x102e, 21 },
/* Adaptec 152x */
{ "Adaptec AHA-1520B", 0x000b, 17 },
/* Adaptec 152x rev B */
{ "Adaptec AHA-1520B", 0x0026, 17 },
/* Iomega Jaz Jet ISA (AIC6370Q) */
{ "Adaptec ASW-B626 BIOS", 0x1029, 21 },
/* on-board controller */
{ "Adaptec BIOS: ASW-B626", 0x000f, 22 },
/* on-board controller */
{ "Adaptec ASW-B626 S2", 0x2e6c, 19 },
/* on-board controller */
{ "Adaptec BIOS:AIC-6360", 0x000c, 21 },
/* on-board controller */
{ "ScsiPro SP-360 BIOS", 0x2873, 19 },
/* ScsiPro-Controller */
{ "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },
/* Gigabyte Local-Bus-SCSI */
{ "Adaptec BIOS:AVA-282X", 0x000c, 21 },
/* Adaptec 282x */
{ "Adaptec IBM Dock II SCSI", 0x2edd, 24 },
/* IBM Thinkpad Dock II */
{ "Adaptec BIOS:AHA-1532P", 0x001c, 22 },
/* IBM Thinkpad Dock II SCSI */
{ "DTC3520A Host Adapter BIOS", 0x318a, 26 },
/* DTC 3520A ISA SCSI */
};
#endif /* !SKIP_BIOSTEST */
/*
* Test, if port_base is valid.
*
*/
static int aha152x_porttest(int io_port)
{
int i;
SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16; i++)
SETPORT(io_port + O_STACK, i);
SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++)
;
return (i == 16);
}
static int tc1550_porttest(int io_port)
{
int i;
SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16; i++)
SETPORT(io_port + O_STACK, i);
SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */
for (i = 0; i < 16 && GETPORT(io_port + O_TC_STACK) == i; i++)
;
return (i == 16);
}
static int checksetup(struct aha152x_setup *setup)
{
int i;
for (i = 0; i < ARRAY_SIZE(ports) && (setup->io_port != ports[i]); i++)
;
if (i == ARRAY_SIZE(ports))
return 0;
if( aha152x_porttest(setup->io_port) ) {
setup->tc1550=0;
} else if( tc1550_porttest(setup->io_port) ) {
setup->tc1550=1;
} else {
return 0;
}
if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX))
return 0;
if ((setup->scsiid < 0) || (setup->scsiid > 7))
return 0;
if ((setup->reconnect < 0) || (setup->reconnect > 1))
return 0;
if ((setup->parity < 0) || (setup->parity > 1))
return 0;
if ((setup->synchronous < 0) || (setup->synchronous > 1))
return 0;
if ((setup->ext_trans < 0) || (setup->ext_trans > 1))
return 0;
return 1;
}
static int __init aha152x_init(void)
{
int i, j, ok;
#if defined(AUTOCONF)
aha152x_config conf;
#endif
#ifdef __ISAPNP__
struct pnp_dev *dev=0, *pnpdev[2] = {0, 0};
#endif
if ( setup_count ) {
printk(KERN_INFO "aha152x: processing commandline: ");
for (i = 0; i<setup_count; i++) {
if (!checksetup(&setup[i])) {
printk(KERN_ERR "\naha152x: %s\n", setup[i].conf);
printk(KERN_ERR "aha152x: invalid line\n");
}
}
printk("ok\n");
}
#if defined(SETUP0)
if (setup_count < ARRAY_SIZE(setup)) {
struct aha152x_setup override = SETUP0;
if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
if (!checksetup(&override)) {
printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
override.io_port,
override.irq,
override.scsiid,
override.reconnect,
override.parity,
override.synchronous,
override.delay,
override.ext_trans);
} else
setup[setup_count++] = override;
}
}
#endif
#if defined(SETUP1)
if (setup_count < ARRAY_SIZE(setup)) {
struct aha152x_setup override = SETUP1;
if (setup_count == 0 || (override.io_port != setup[0].io_port)) {
if (!checksetup(&override)) {
printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
override.io_port,
override.irq,
override.scsiid,
override.reconnect,
override.parity,
override.synchronous,
override.delay,
override.ext_trans);
} else
setup[setup_count++] = override;
}
}
#endif
#if defined(MODULE)
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].irq = aha152x[1];
setup[setup_count].scsiid = aha152x[2];
setup[setup_count].reconnect = aha152x[3];
setup[setup_count].parity = aha152x[4];
setup[setup_count].synchronous = aha152x[5];
setup[setup_count].delay = aha152x[6];
setup[setup_count].ext_trans = aha152x[7];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = aha152x[8];
#endif
} else if(io[0]!=0 || irq[0]!=0) {
if(io[0]!=0) setup[setup_count].io_port = io[0];
if(irq[0]!=0) setup[setup_count].irq = irq[0];
setup[setup_count].scsiid = scsiid[0];
setup[setup_count].reconnect = reconnect[0];
setup[setup_count].parity = parity[0];
setup[setup_count].synchronous = sync[0];
setup[setup_count].delay = delay[0];
setup[setup_count].ext_trans = exttrans[0];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = debug[0];
#endif
}
if (checksetup(&setup[setup_count]))
setup_count++;
else
printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
setup[setup_count].io_port,
setup[setup_count].irq,
setup[setup_count].scsiid,
setup[setup_count].reconnect,
setup[setup_count].parity,
setup[setup_count].synchronous,
setup[setup_count].delay,
setup[setup_count].ext_trans);
}
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];
setup[setup_count].irq = aha152x1[1];
setup[setup_count].scsiid = aha152x1[2];
setup[setup_count].reconnect = aha152x1[3];
setup[setup_count].parity = aha152x1[4];
setup[setup_count].synchronous = aha152x1[5];
setup[setup_count].delay = aha152x1[6];
setup[setup_count].ext_trans = aha152x1[7];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = aha152x1[8];
#endif
} else if(io[1]!=0 || irq[1]!=0) {
if(io[1]!=0) setup[setup_count].io_port = io[1];
if(irq[1]!=0) setup[setup_count].irq = irq[1];
setup[setup_count].scsiid = scsiid[1];
setup[setup_count].reconnect = reconnect[1];
setup[setup_count].parity = parity[1];
setup[setup_count].synchronous = sync[1];
setup[setup_count].delay = delay[1];
setup[setup_count].ext_trans = exttrans[1];
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = debug[1];
#endif
}
if (checksetup(&setup[setup_count]))
setup_count++;
else
printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
setup[setup_count].io_port,
setup[setup_count].irq,
setup[setup_count].scsiid,
setup[setup_count].reconnect,
setup[setup_count].parity,
setup[setup_count].synchronous,
setup[setup_count].delay,
setup[setup_count].ext_trans);
}
#endif
#ifdef __ISAPNP__
for(i=0; setup_count<ARRAY_SIZE(setup) && id_table[i].vendor; i++) {
while ( setup_count<ARRAY_SIZE(setup) &&
(dev=pnp_find_dev(NULL, id_table[i].vendor, id_table[i].function, dev)) ) {
if (pnp_device_attach(dev) < 0)
continue;
if (pnp_activate_dev(dev) < 0) {
pnp_device_detach(dev);
continue;
}
if (!pnp_port_valid(dev, 0)) {
pnp_device_detach(dev);
continue;
}
if (setup_count==1 && pnp_port_start(dev, 0)==setup[0].io_port) {
pnp_device_detach(dev);
continue;
}
setup[setup_count].io_port = pnp_port_start(dev, 0);
setup[setup_count].irq = pnp_irq(dev, 0);
setup[setup_count].scsiid = 7;
setup[setup_count].reconnect = 1;
setup[setup_count].parity = 1;
setup[setup_count].synchronous = 1;
setup[setup_count].delay = DELAY_DEFAULT;
setup[setup_count].ext_trans = 0;
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = DEBUG_DEFAULT;
#endif
#if defined(__ISAPNP__)
pnpdev[setup_count] = dev;
#endif
printk (KERN_INFO
"aha152x: found ISAPnP adapter at io=0x%03x, irq=%d\n",
setup[setup_count].io_port, setup[setup_count].irq);
setup_count++;
}
}
#endif
#if defined(AUTOCONF)
if (setup_count<ARRAY_SIZE(setup)) {
#if !defined(SKIP_BIOSTEST)
ok = 0;
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);
if (!ok && setup_count == 0)
return 0;
printk(KERN_INFO "aha152x: BIOS test: passed, ");
#else
printk(KERN_INFO "aha152x: ");
#endif /* !SKIP_BIOSTEST */
ok = 0;
for (i = 0; i < ARRAY_SIZE(ports) && setup_count < 2; i++) {
if ((setup_count == 1) && (setup[0].io_port == ports[i]))
continue;
if (aha152x_porttest(ports[i])) {
ok++;
setup[setup_count].io_port = ports[i];
setup[setup_count].tc1550 = 0;
conf.cf_port =
(GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
setup[setup_count].scsiid = conf.cf_id;
setup[setup_count].reconnect = conf.cf_tardisc;
setup[setup_count].parity = !conf.cf_parity;
setup[setup_count].synchronous = conf.cf_syncneg;
setup[setup_count].delay = DELAY_DEFAULT;
setup[setup_count].ext_trans = 0;
#if defined(AHA152X_DEBUG) #if defined(AHA152X_DEBUG)
if(length>14 && strncmp("debug ", buffer+8, 6)==0) { setup[setup_count].debug = DEBUG_DEFAULT;
int debug = HOSTDATA(shpnt)->debug; #endif
setup_count++;
} else if (tc1550_porttest(ports[i])) {
ok++;
setup[setup_count].io_port = ports[i];
setup[setup_count].tc1550 = 1;
HOSTDATA(shpnt)->debug = simple_strtoul(buffer+14, NULL, 0); conf.cf_port =
(GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
printk(KERN_INFO "aha152x%d: debugging options set to 0x%04x (were 0x%04x)\n", HOSTNO, HOSTDATA(shpnt)->debug, debug); setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
} else setup[setup_count].scsiid = conf.cf_id;
setup[setup_count].reconnect = conf.cf_tardisc;
setup[setup_count].parity = !conf.cf_parity;
setup[setup_count].synchronous = conf.cf_syncneg;
setup[setup_count].delay = DELAY_DEFAULT;
setup[setup_count].ext_trans = 0;
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = DEBUG_DEFAULT;
#endif #endif
#if defined(AHA152X_STAT) setup_count++;
if(length>13 && strncmp("reset", buffer+8, 5)==0) { }
int i; }
HOSTDATA(shpnt)->total_commands=0; if (ok)
HOSTDATA(shpnt)->disconnections=0; printk("auto configuration: ok, ");
HOSTDATA(shpnt)->busfree_without_any_action=0;
HOSTDATA(shpnt)->busfree_without_old_command=0;
HOSTDATA(shpnt)->busfree_without_new_command=0;
HOSTDATA(shpnt)->busfree_without_done_command=0;
HOSTDATA(shpnt)->busfree_with_check_condition=0;
for (i = idle; i<maxstate; i++) {
HOSTDATA(shpnt)->count[i]=0;
HOSTDATA(shpnt)->count_trans[i]=0;
HOSTDATA(shpnt)->time[i]=0;
} }
#endif
printk(KERN_INFO "aha152x%d: stats reseted.\n", HOSTNO); printk("%d controller(s) configured\n", setup_count);
} else for (i=0; i<setup_count; i++) {
if ( request_region(setup[i].io_port, IO_RANGE, "aha152x") ) {
struct Scsi_Host *shpnt = aha152x_probe_one(&setup[i]);
if( !shpnt ) {
release_region(setup[i].io_port, IO_RANGE);
#if defined(__ISAPNP__)
} else if( pnpdev[i] ) {
HOSTDATA(shpnt)->pnpdev=pnpdev[i];
pnpdev[i]=0;
#endif #endif
{ }
return -EINVAL; } else {
printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup[i].io_port);
} }
#if defined(__ISAPNP__)
if( pnpdev[i] )
pnp_device_detach(pnpdev[i]);
#endif
}
return length; return registered_count>0;
} }
#undef SPRINTF static void __exit aha152x_exit(void)
#define SPRINTF(args...) \
do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start,
off_t offset, int length, int inout)
{ {
int i; int i;
char *pos = buffer;
Scsi_Cmnd *ptr;
unsigned long flags;
int thislength;
DPRINTK(debug_procinfo,
KERN_DEBUG "aha152x_proc_info: buffer=%p offset=%ld length=%d hostno=%d inout=%d\n",
buffer, offset, length, shpnt->host_no, inout);
if (inout)
return aha152x_set_info(buffer, length, shpnt);
SPRINTF(AHA152X_REVID "\n");
SPRINTF("ioports 0x%04lx to 0x%04lx\n",
shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1);
SPRINTF("interrupt 0x%02x\n", shpnt->irq);
SPRINTF("disconnection/reconnection %s\n",
RECONNECT ? "enabled" : "disabled");
SPRINTF("parity checking %s\n",
PARITY ? "enabled" : "disabled");
SPRINTF("synchronous transfers %s\n",
SYNCHRONOUS ? "enabled" : "disabled");
SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands);
if(SYNCHRONOUS) { for(i=0; i<ARRAY_SIZE(setup); i++) {
SPRINTF("synchronously operating targets (tick=50 ns):\n"); aha152x_release(aha152x_host[i]);
for (i = 0; i < 8; i++) aha152x_host[i]=0;
if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
i,
(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
HOSTDATA(shpnt)->syncrate[i] & 0x0f);
} }
#if defined(AHA152X_DEBUG) }
#define PDEBUG(flags,txt) \
if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
SPRINTF("enabled debugging options: ");
PDEBUG(debug_procinfo, "procinfo"); module_init(aha152x_init);
PDEBUG(debug_queue, "queue"); module_exit(aha152x_exit);
PDEBUG(debug_intr, "interrupt");
PDEBUG(debug_selection, "selection");
PDEBUG(debug_msgo, "message out");
PDEBUG(debug_msgi, "message in");
PDEBUG(debug_status, "status");
PDEBUG(debug_cmd, "command");
PDEBUG(debug_datai, "data in");
PDEBUG(debug_datao, "data out");
PDEBUG(debug_eh, "eh");
PDEBUG(debug_locks, "locks");
PDEBUG(debug_phases, "phases");
SPRINTF("\n"); #if !defined(MODULE)
static int __init aha152x_setup(char *str)
{
#if defined(AHA152X_DEBUG)
int ints[11];
#else
int ints[10];
#endif #endif
get_options(str, ARRAY_SIZE(ints), ints);
SPRINTF("\nqueue status:\n"); if(setup_count>=ARRAY_SIZE(setup)) {
DO_LOCK(flags); printk(KERN_ERR "aha152x: you can only configure up to two controllers\n");
if (ISSUE_SC) { return 1;
SPRINTF("not yet issued commands:\n");
for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr))
pos += get_command(pos, ptr);
} else
SPRINTF("no not yet issued commands\n");
DO_UNLOCK(flags);
if (CURRENT_SC) {
SPRINTF("current command:\n");
pos += get_command(pos, CURRENT_SC);
} else
SPRINTF("no current command\n");
if (DISCONNECTED_SC) {
SPRINTF("disconnected commands:\n");
for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr))
pos += get_command(pos, ptr);
} else
SPRINTF("no disconnected commands\n");
pos += get_ports(shpnt, pos);
#if defined(AHA152X_STAT)
SPRINTF("statistics:\n"
"total commands: %d\n"
"disconnections: %d\n"
"busfree with check condition: %d\n"
"busfree without old command: %d\n"
"busfree without new command: %d\n"
"busfree without done command: %d\n"
"busfree without any action: %d\n"
"state "
"transitions "
"count "
"time\n",
HOSTDATA(shpnt)->total_commands,
HOSTDATA(shpnt)->disconnections,
HOSTDATA(shpnt)->busfree_with_check_condition,
HOSTDATA(shpnt)->busfree_without_old_command,
HOSTDATA(shpnt)->busfree_without_new_command,
HOSTDATA(shpnt)->busfree_without_done_command,
HOSTDATA(shpnt)->busfree_without_any_action);
for(i=0; i<maxstate; i++) {
SPRINTF("%-10s %-12d %-12d %-12ld\n",
states[i].name,
HOSTDATA(shpnt)->count_trans[i],
HOSTDATA(shpnt)->count[i],
HOSTDATA(shpnt)->time[i]);
} }
#endif
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: pos=%p\n", pos);
thislength = pos - (buffer + offset); setup[setup_count].conf = str;
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: length=%d thislength=%d\n", length, thislength); setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340;
setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11;
if(thislength<0) { setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7;
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: output too short\n"); setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
*start = 0; setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
#if defined(AHA152X_DEBUG)
setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT;
if (ints[0] > 9) {
printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
"[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");
#else
if (ints[0] > 8) { /*}*/
printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
"[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
#endif
} else {
setup_count++;
return 0; return 0;
} }
thislength = thislength<length ? thislength : length; return 1;
DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: return %d\n", thislength);
*start = buffer + offset;
return thislength < length ? thislength : length;
} }
__setup("aha152x=", aha152x_setup);
static Scsi_Host_Template aha152x_driver_template = {
.module = THIS_MODULE,
.name = AHA152X_REVID,
.proc_name = "aha152x",
.proc_info = aha152x_proc_info,
.queuecommand = aha152x_queue,
.eh_abort_handler = aha152x_abort,
.eh_device_reset_handler = aha152x_device_reset,
.eh_bus_reset_handler = aha152x_bus_reset,
.eh_host_reset_handler = aha152x_host_reset,
.bios_param = aha152x_biosparam,
.can_queue = 1,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
};
#ifndef PCMCIA
module_init(aha152x_init);
module_exit(aha152x_exit);
#endif #endif
#endif /* !PCMCIA */
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
#define _AHA152X_H #define _AHA152X_H
/* /*
* $Id: aha152x.h,v 2.5 2002/04/14 11:24:12 fischer Exp $ * $Id: aha152x.h,v 2.7 2004/01/24 11:39:03 fischer Exp $
*/ */
/* number of queueable commands /* number of queueable commands
(unless we support more than 1 cmd_per_lun this should do) */ (unless we support more than 1 cmd_per_lun this should do) */
#define AHA152X_MAXQUEUE 7 #define AHA152X_MAXQUEUE 7
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.5 $" #define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.7 $"
/* port addresses */ /* port addresses */
#define SCSISEQ (HOSTIOPORT0+0x00) /* SCSI sequence control */ #define SCSISEQ (HOSTIOPORT0+0x00) /* SCSI sequence control */
...@@ -331,6 +331,7 @@ struct aha152x_setup { ...@@ -331,6 +331,7 @@ struct aha152x_setup {
}; };
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *); struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *);
int aha152x_host_reset(struct scsi_cmnd *); void aha152x_release(struct Scsi_Host *);
int aha152x_host_reset(Scsi_Cmnd *);
#endif /* _AHA152X_H */ #endif /* _AHA152X_H */
...@@ -78,7 +78,7 @@ static int irq_list[4] = { -1 }; ...@@ -78,7 +78,7 @@ static int irq_list[4] = { -1 };
static int host_id = 7; static int host_id = 7;
static int reconnect = 1; static int reconnect = 1;
static int parity = 1; static int parity = 1;
static int synchronous = 0; static int synchronous = 1;
static int reset_delay = 100; static int reset_delay = 100;
static int ext_trans = 0; static int ext_trans = 0;
...@@ -244,9 +244,6 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -244,9 +244,6 @@ static void aha152x_config_cs(dev_link_t *link)
CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
/* A bad hack... */
release_region(link->io.BasePort1, link->io.NumPorts1);
/* Set configuration options for the aha152x driver */ /* Set configuration options for the aha152x driver */
memset(&s, 0, sizeof(s)); memset(&s, 0, sizeof(s));
s.conf = "PCMCIA setup"; s.conf = "PCMCIA setup";
...@@ -266,9 +263,6 @@ static void aha152x_config_cs(dev_link_t *link) ...@@ -266,9 +263,6 @@ static void aha152x_config_cs(dev_link_t *link)
goto cs_failed; goto cs_failed;
} }
scsi_add_host(host, NULL); /* XXX handle failure */
scsi_scan_host(host);
sprintf(info->node.dev_name, "scsi%d", host->host_no); sprintf(info->node.dev_name, "scsi%d", host->host_no);
link->dev = &info->node; link->dev = &info->node;
info->host = host; info->host = host;
...@@ -286,7 +280,7 @@ static void aha152x_release_cs(dev_link_t *link) ...@@ -286,7 +280,7 @@ static void aha152x_release_cs(dev_link_t *link)
{ {
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
scsi_remove_host(info->host); aha152x_release(info->host);
link->dev = NULL; link->dev = NULL;
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
...@@ -294,7 +288,6 @@ static void aha152x_release_cs(dev_link_t *link) ...@@ -294,7 +288,6 @@ static void aha152x_release_cs(dev_link_t *link)
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
scsi_unregister(info->host);
} }
static int aha152x_event(event_t event, int priority, static int aha152x_event(event_t event, int priority,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment