From: "Juergen E. Fischer" 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. --- drivers/scsi/aha152x.c | 1237 +++++++++++++++++++------------------ drivers/scsi/aha152x.h | 7 drivers/scsi/pcmcia/aha152x_stub.c | 11 3 files changed, 651 insertions(+), 604 deletions(-) diff -puN drivers/scsi/aha152x.c~aha152x-update drivers/scsi/aha152x.c --- 25/drivers/scsi/aha152x.c~aha152x-update 2004-01-24 10:47:31.000000000 -0800 +++ 25-akpm/drivers/scsi/aha152x.c 2004-01-24 10:47:31.000000000 -0800 @@ -1,6 +1,6 @@ /* aha152x.c -- Adaptec AHA-152x driver * 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 * under the terms of the GNU General Public License as published by the @@ -13,9 +13,17 @@ * 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 $ + * 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 * - interfaces changes for kernel 2.6 * - aha152x_probe_one introduced for pcmcia stub @@ -344,7 +352,8 @@ MODULE_AUTHOR("Jürgen Fischer"); MODULE_DESCRIPTION(AHA152X_REVID); MODULE_LICENSE("GPL"); -#if defined(MODULE) && !defined(PCMCIA) +#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}; @@ -398,21 +407,23 @@ 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}; #endif /* !defined(AHA152X_DEBUG) */ -#endif /* MODULE && !PCMCIA */ +#endif /* MODULE */ #ifdef __ISAPNP__ 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, } }; MODULE_DEVICE_TABLE(isapnp, id_table); #endif /* ISAPNP */ -/* set by aha152x_setup according to the command line */ -static int setup_count; -static int registered_count; -static struct aha152x_setup setup[2]; -static struct Scsi_Host *aha152x_host[2]; +#endif /* !PCMCIA */ + +static int registered_count=0; +static struct Scsi_Host *aha152x_host[2] = {0, 0}; static Scsi_Host_Template aha152x_driver_template; /* @@ -658,7 +669,6 @@ static irqreturn_t intr(int irq, void *d 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); -static int checksetup(struct aha152x_setup *setup); /* diagnostics */ static void disp_ports(struct Scsi_Host *shpnt); @@ -666,66 +676,6 @@ static void show_command(Scsi_Cmnd * ptr static void show_queues(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: @@ -799,141 +749,6 @@ static inline Scsi_Cmnd *remove_SC(Scsi_ 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=[,[," - "[,[,[,[,[,[,]]]]]]]]\n"); -#else - if (ints[0] > 8) { /*}*/ - printk(KERN_NOTICE "aha152x: usage: aha152x=[,[," - "[,[,[,[,[,]]]]]]]\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 countio_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) { int i; @@ -950,7 +765,6 @@ static irqreturn_t swintr(int irqno, voi struct Scsi_Host *shpnt = lookup_irq(irqno); if (!shpnt) { - /* no point using HOSTNO here! */ printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno); return IRQ_NONE; } @@ -961,17 +775,19 @@ static irqreturn_t swintr(int irqno, voi return IRQ_HANDLED; } - struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) { struct Scsi_Host *shpnt; shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata)); if (!shpnt) { - printk(KERN_ERR "aha152x: scsi_register failed\n"); + printk(KERN_ERR "aha152x: scsi_host_alloc failed\n"); return NULL; } + /* need to have host registered before triggering any interrupt */ + aha152x_host[registered_count] = shpnt; + memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt)); shpnt->io_port = setup->io_port; @@ -1034,24 +850,19 @@ struct Scsi_Host *aha152x_probe_one(stru DELAY, EXT_TRANS ? "enabled" : "disabled"); - if (!request_region(shpnt->io_port, IO_RANGE, "aha152x")) - goto out_unregister; - /* not expecting any interrupts */ SETPORT(SIMODE0, 0); SETPORT(SIMODE1, 0); - if (request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) { - printk(KERN_ERR "aha152x%d: driver needs an IRQ.\n", shpnt->host_no); - goto out_release_region; + if( request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) { + printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq); + goto out_host_put; } HOSTDATA(shpnt)->swint = 0; 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(); SETPORT(DMACNTRL0, SWINT|INTEN); mdelay(1000); @@ -1066,9 +877,9 @@ struct Scsi_Host *aha152x_probe_one(stru 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); - goto out_unregister_host; + goto out_host_put; } printk("ok.\n"); @@ -1077,335 +888,63 @@ struct Scsi_Host *aha152x_probe_one(stru SETPORT(SSTAT0, 0x7f); SETPORT(SSTAT1, 0xef); - if (request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) { - printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", shpnt->host_no); - goto out_unregister_host; + if ( request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) ) { + printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq); + 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); - return shpnt; /* the pcmcia stub needs the return value; */ -out_unregister_host: - aha152x_host[registered_count] = NULL; -out_release_region: - release_region(shpnt->io_port, IO_RANGE); -out_unregister: + registered_count++; + + return shpnt; + +out_host_put: + aha152x_host[registered_count]=0; 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 defined(AUTOCONF) - aha152x_config conf; + if(!shpnt) + return; + + if (shpnt->irq) + free_irq(shpnt->irq, shpnt); + +#if !defined(PCMCIA) + if (shpnt->io_port) + release_region(shpnt->io_port, IO_RANGE); #endif + #ifdef __ISAPNP__ - struct pnp_dev *dev=0, *pnpdev[2] = {0, 0}; + if (HOSTDATA(shpnt)->pnpdev) + pnp_device_detach(HOSTDATA(shpnt)->pnpdev); #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"); - } + scsi_remove_host(shpnt); + scsi_host_put(shpnt); +} -#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 +/* + * 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 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) && !defined(PCMCIA) - if (setup_countpnpdev=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; iSCp.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); @@ -1414,12 +953,12 @@ static int setup_expected_interrupts(str } 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); + 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); + SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE); } else { DPRINTK(debug_intr, DEBUG_LEAD "expecting: %s %s\n", CMDINFO(CURRENT_SC), @@ -1436,7 +975,7 @@ static int setup_expected_interrupts(str } -/* +/* * 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 *)) @@ -1446,8 +985,8 @@ static int aha152x_internal_queue(Scsi_C #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); + 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); } #endif @@ -1466,7 +1005,7 @@ static int aha152x_internal_queue(Scsi_C return FAILED; } } else { - SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); + 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; @@ -1561,11 +1100,6 @@ static int aha152x_abort(Scsi_Cmnd *SCpn Scsi_Cmnd *ptr; unsigned long flags; - if(!shpnt) { - printk(ERR_LEAD "abort(%p): no host structure\n", CMDINFO(SCpnt), SCpnt); - return FAILED; - } - #if defined(AHA152X_DEBUG) if(HOSTDATA(shpnt)->debug & debug_eh) { printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt); @@ -1610,15 +1144,12 @@ static void timer_expired(unsigned long Scsi_Cmnd *SCp = (Scsi_Cmnd *)p; struct semaphore *sem = SCSEM(SCp); struct Scsi_Host *shpnt = SCp->device->host; + unsigned long flags; /* 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"); - } + DO_LOCK(flags); + remove_SC(&ISSUE_SC, SCp); + DO_UNLOCK(flags); up(sem); } @@ -1626,15 +1157,14 @@ static void timer_expired(unsigned long /* * Reset a device * - * FIXME: never seen this live. might lockup... - * */ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) { struct Scsi_Host *shpnt = SCpnt->device->host; DECLARE_MUTEX_LOCKED(sem); struct timer_list timer; - int ret; + int ret, issued, disconnected; + unsigned long flags; #if defined(AHA152X_DEBUG) if(HOSTDATA(shpnt)->debug & debug_eh) { @@ -1648,13 +1178,18 @@ static int aha152x_device_reset(Scsi_Cmn 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->use_sg = 0; SCpnt->request_buffer = 0; SCpnt->request_bufflen = 0; init_timer(&timer); - timer.data = (unsigned long) cmd; + timer.data = (unsigned long) SCpnt; timer.expires = jiffies + 100*HZ; /* 10s */ timer.function = (void (*)(unsigned long)) timer_expired; @@ -1668,12 +1203,29 @@ static int aha152x_device_reset(Scsi_Cmn SCpnt->request_buffer = SCpnt->buffer; SCpnt->request_bufflen = SCpnt->bufflen; + DO_LOCK(flags); + 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; } else { - ret = FAILED; + /* requeue */ + if(!issued) { + append_SC(&ISSUE_SC, SCpnt); + } else if(disconnected) { + append_SC(&DISCONNECTED_SC, SCpnt); + } + + ret = FAILED; } + DO_UNLOCK(flags); + spin_lock_irq(shpnt->host_lock); return ret; } @@ -1681,13 +1233,17 @@ static int aha152x_device_reset(Scsi_Cmn static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) { Scsi_Cmnd *ptr; - unsigned long flags; - - DO_LOCK(flags); ptr=*SCs; 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) { DPRINTK(debug_eh, DEBUG_LEAD "disconnected command %p removed\n", CMDINFO(ptr), ptr); @@ -1699,8 +1255,6 @@ static void free_hard_reset_SCs(struct S ptr = next; } - - DO_UNLOCK(flags); } /* @@ -1712,6 +1266,8 @@ static int aha152x_bus_reset(Scsi_Cmnd * 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); @@ -1729,12 +1285,12 @@ static int aha152x_bus_reset(Scsi_Cmnd * SETPORT(SCSISEQ, 0); 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); if(HOSTDATA(shpnt)->commands==0) SETPORT(PORTA, 0); + DO_UNLOCK(flags); return SUCCESS; @@ -2000,6 +1556,7 @@ static void busfree_run(struct Scsi_Host #if defined(AHA152X_STAT) action++; #endif + if(DONE_SC->SCp.phase & check_condition) { #if 0 if(HOSTDATA(shpnt)->debug & debug_eh) { @@ -2029,47 +1586,57 @@ static void busfree_run(struct Scsi_Host #endif if(!(DONE_SC->SCp.Status & not_issued)) { + Scsi_Cmnd *ptr = DONE_SC; + DONE_SC=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 - DONE_SC->cmnd[0] = REQUEST_SENSE; - DONE_SC->cmnd[1] = 0; - DONE_SC->cmnd[2] = 0; - DONE_SC->cmnd[3] = 0; - DONE_SC->cmnd[4] = sizeof(DONE_SC->sense_buffer); - DONE_SC->cmnd[5] = 0; - DONE_SC->cmd_len = 6; - DONE_SC->use_sg = 0; - DONE_SC->request_buffer = DONE_SC->sense_buffer; - DONE_SC->request_bufflen = sizeof(DONE_SC->sense_buffer); + ptr->cmnd[0] = REQUEST_SENSE; + ptr->cmnd[1] = 0; + ptr->cmnd[2] = 0; + ptr->cmnd[3] = 0; + ptr->cmnd[4] = sizeof(ptr->sense_buffer); + ptr->cmnd[5] = 0; + ptr->cmd_len = 6; + ptr->use_sg = 0; + ptr->request_buffer = ptr->sense_buffer; + ptr->request_bufflen = sizeof(ptr->sense_buffer); 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); - - DONE_SC=0; - } else { #if 0 + } else { DPRINTK(debug_eh, ERR_LEAD "command not issued - CHECK CONDITION ignored\n", CMDINFO(DONE_SC)); #endif } } 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 */ HOSTDATA(shpnt)->commands--; if (!HOSTDATA(shpnt)->commands) SETPORT(PORTA, 0); /* turn led off */ + if(ptr->scsi_done != reset_done) { + kfree(ptr->host_scribble); + ptr->host_scribble=0; + } + DO_UNLOCK(flags); - DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", CMDINFO(DONE_SC), DONE_SC); - DONE_SC->scsi_done(DONE_SC); - DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", CMDINFO(DONE_SC), DONE_SC); + DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", hostno, id, lun, ptr); + ptr->scsi_done(ptr); + DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", hostno, id, lun, ptr); DO_LOCK(flags); - - kfree(DONE_SC->host_scribble); - DONE_SC->host_scribble=0; } DONE_SC=0; @@ -2936,11 +2503,11 @@ static void rsti_run(struct Scsi_Host *s if (!ptr->device->soft_reset) { remove_SC(&DISCONNECTED_SC, ptr); - ptr->result = DID_RESET << 16; - ptr->scsi_done(ptr); - kfree(ptr->host_scribble); ptr->host_scribble=0; + + ptr->result = DID_RESET << 16; + ptr->scsi_done(ptr); } ptr = next; @@ -3382,7 +2949,11 @@ static void show_command(Scsi_Cmnd *ptr) printk("aborted|"); if (ptr->SCp.phase & resetted) printk("resetted|"); - printk("; next=0x%p\n", SCNEXT(ptr)); + if( SCDATA(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 printk(KERN_DEBUG "none\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); disp_ports(shpnt); @@ -3769,7 +3340,7 @@ static int aha152x_proc_info(struct Scsi unsigned long flags; int thislength; - DPRINTK(debug_procinfo, + 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); @@ -3914,7 +3485,489 @@ static Scsi_Host_Template aha152x_driver .use_clustering = DISABLE_CLUSTERING, }; -#ifndef PCMCIA +#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; ipnpdev=pnpdev[i]; + pnpdev[i]=0; +#endif + } + } 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 registered_count>0; +} + +static void __exit aha152x_exit(void) +{ + int i; + + for(i=0; i=ARRAY_SIZE(setup)) { + printk(KERN_ERR "aha152x: you can only configure up to two controllers\n"); + return 1; + } + + 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=[,[," + "[,[,[,[,[,[,]]]]]]]]\n"); +#else + if (ints[0] > 8) { /*}*/ + printk(KERN_NOTICE "aha152x: usage: aha152x=[,[," + "[,[,[,[,[,]]]]]]]\n"); +#endif + } else { + setup_count++; + return 0; + } + + return 1; +} +__setup("aha152x=", aha152x_setup); #endif + +#endif /* !PCMCIA */ diff -puN drivers/scsi/aha152x.h~aha152x-update drivers/scsi/aha152x.h --- 25/drivers/scsi/aha152x.h~aha152x-update 2004-01-24 10:47:31.000000000 -0800 +++ 25-akpm/drivers/scsi/aha152x.h 2004-01-24 10:47:31.000000000 -0800 @@ -2,14 +2,14 @@ #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 (unless we support more than 1 cmd_per_lun this should do) */ #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 */ #define SCSISEQ (HOSTIOPORT0+0x00) /* SCSI sequence control */ @@ -331,6 +331,7 @@ 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 */ diff -puN drivers/scsi/pcmcia/aha152x_stub.c~aha152x-update drivers/scsi/pcmcia/aha152x_stub.c --- 25/drivers/scsi/pcmcia/aha152x_stub.c~aha152x-update 2004-01-24 10:47:31.000000000 -0800 +++ 25-akpm/drivers/scsi/pcmcia/aha152x_stub.c 2004-01-24 10:47:31.000000000 -0800 @@ -78,7 +78,7 @@ static int irq_list[4] = { -1 }; static int host_id = 7; static int reconnect = 1; static int parity = 1; -static int synchronous = 0; +static int synchronous = 1; static int reset_delay = 100; static int ext_trans = 0; @@ -244,9 +244,6 @@ static void aha152x_config_cs(dev_link_t CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); 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 */ memset(&s, 0, sizeof(s)); s.conf = "PCMCIA setup"; @@ -266,9 +263,6 @@ static void aha152x_config_cs(dev_link_t 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); link->dev = &info->node; info->host = host; @@ -286,7 +280,7 @@ static void aha152x_release_cs(dev_link_ { scsi_info_t *info = link->priv; - scsi_remove_host(info->host); + aha152x_release(info->host); link->dev = NULL; pcmcia_release_configuration(link->handle); @@ -294,7 +288,6 @@ static void aha152x_release_cs(dev_link_ pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - scsi_unregister(info->host); } static int aha152x_event(event_t event, int priority, _