home *** CD-ROM | disk | FTP | other *** search
- /* aha152x.c -- Adaptec AHA-152x driver
- * Author: Juergen E. Fischer, fischer@server.et-inf.fho-emden.de
- * Copyright 1993, 1994 Juergen E. Fischer
- *
- *
- * This driver is based on
- * fdomain.c -- Future Domain TMC-16x0 driver
- * which is
- * Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
- *
-
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
-
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
-
- *
- * $Id: aha152x.c,v 1.8 1995/01/21 22:07:19 root Exp root $
- *
-
- * $Log: aha152x.c,v $
- * Revision 1.8 1995/01/21 22:07:19 root
- * - snarf_region => request_region
- * - aha152x_intr interface change
- *
- * Revision 1.7 1995/01/02 23:19:36 root
- * - updated COMMAND_SIZE to cmd_len
- * - changed sti() to restore_flags()
- * - fixed some #ifdef which generated warnings
- *
- * Revision 1.6 1994/11/24 20:35:27 root
- * - problem with odd number of bytes in fifo fixed
- *
- * Revision 1.5 1994/10/30 14:39:56 root
- * - abort code fixed
- * - debugging improved
- *
- * Revision 1.4 1994/09/12 11:33:01 root
- * - irqaction to request_irq
- * - abortion updated
- *
- * Revision 1.3 1994/08/04 13:53:05 root
- * - updates for mid-level-driver changes
- * - accept unexpected BUSFREE phase as error condition
- * - parity check now configurable
- *
- * Revision 1.2 1994/07/03 12:56:36 root
- * - cleaned up debugging code
- * - more tweaking on reset delays
- * - updated abort/reset code (pretty untested...)
- *
- * Revision 1.1 1994/05/28 21:18:49 root
- * - update for mid-level interface change (abort-reset)
- * - delays after resets adjusted for some slow devices
- *
- * Revision 1.0 1994/03/25 12:52:00 root
- * - Fixed "more data than expected" problem
- * - added new BIOS signatures
- *
- * Revision 0.102 1994/01/31 20:44:12 root
- * - minor changes in insw/outsw handling
- *
- * Revision 0.101 1993/12/13 01:16:27 root
- * - fixed STATUS phase (non-GOOD stati were dropped sometimes;
- * fixes problems with CD-ROM sector size detection & media change)
- *
- * Revision 0.100 1993/12/10 16:58:47 root
- * - fix for unsuccessful selections in case of non-continuous id assignments
- * on the scsi bus.
- *
- * Revision 0.99 1993/10/24 16:19:59 root
- * - fixed DATA IN (rare read errors gone)
- *
- * Revision 0.98 1993/10/17 12:54:44 root
- * - fixed some recent fixes (shame on me)
- * - moved initialization of scratch area to aha152x_queue
- *
- * Revision 0.97 1993/10/09 18:53:53 root
- * - DATA IN fixed. Rarely left data in the fifo.
- *
- * Revision 0.96 1993/10/03 00:53:59 root
- * - minor changes on DATA IN
- *
- * Revision 0.95 1993/09/24 10:36:01 root
- * - change handling of MSGI after reselection
- * - fixed sti/cli
- * - minor changes
- *
- * Revision 0.94 1993/09/18 14:08:22 root
- * - fixed bug in multiple outstanding command code
- * - changed detection
- * - support for kernel command line configuration
- * - reset corrected
- * - changed message handling
- *
- * Revision 0.93 1993/09/15 20:41:19 root
- * - fixed bugs with multiple outstanding commands
- *
- * Revision 0.92 1993/09/13 02:46:33 root
- * - multiple outstanding commands work (no problems with IBM drive)
- *
- * Revision 0.91 1993/09/12 20:51:46 root
- * added multiple outstanding commands
- * (some problem with this $%&? IBM device remain)
- *
- * Revision 0.9 1993/09/12 11:11:22 root
- * - corrected auto-configuration
- * - changed the auto-configuration (added some '#define's)
- * - added support for dis-/reconnection
- *
- * Revision 0.8 1993/09/06 23:09:39 root
- * - added support for the drive activity light
- * - minor changes
- *
- * Revision 0.7 1993/09/05 14:30:15 root
- * - improved phase detection
- * - now using the new snarf_region code of 0.99pl13
- *
- * Revision 0.6 1993/09/02 11:01:38 root
- * first public release; added some signatures and biosparam()
- *
- * Revision 0.5 1993/08/30 10:23:30 root
- * fixed timing problems with my IBM drive
- *
- * Revision 0.4 1993/08/29 14:06:52 root
- * fixed some problems with timeouts due incomplete commands
- *
- * Revision 0.3 1993/08/28 15:55:03 root
- * writing data works too. mounted and worked on a dos partition
- *
- * Revision 0.2 1993/08/27 22:42:07 root
- * reading data works. Mounted a msdos partition.
- *
- * Revision 0.1 1993/08/25 13:38:30 root
- * first "damn thing doesn't work" version
- *
- * Revision 0.0 1993/08/14 19:54:25 root
- * empty function bodies; detect() works.
- *
-
- **************************************************************************
-
-
-
- DESCRIPTION:
-
- This is the Linux low-level SCSI driver for Adaptec AHA-1520/1522
- SCSI host adapters.
-
-
- PER-DEFINE CONFIGURABLE OPTIONS:
-
- AUTOCONF : use configuration the controller reports (only 152x)
- IRQ : override interrupt channel (9,10,11 or 12) (default 11)
- SCSI_ID : override scsiid of AIC-6260 (0-7) (default 7)
- RECONNECT : override target dis-/reconnection/multiple outstanding commands (default on)
- PARITY : override parity check (default on)
- SKIP_BIOSTEST : Don't test for BIOS signature (AHA-1510 or disabled BIOS)
- PORTBASE : Force port base. Don't try to probe
-
-
- LILO COMMAND LINE OPTIONS:
-
- aha152x=<PORTBASE>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>]]]]
-
- The normal configuration can be overridden by specifying a command line.
- When you do this, the BIOS test is skipped. Entered values have to be
- valid (known). Don't use values that aren't support under normal operation.
- If you think that you need other values: contact me.
-
-
- REFERENCES USED:
-
- "AIC-6260 SCSI Chip Specification", Adaptec Corporation.
-
- "SCSI COMPUTER SYSTEM INTERFACE - 2 (SCSI-2)", X3T9.2/86-109 rev. 10h
-
- "Writing a SCSI device driver for Linux", Rik Faith (faith@cs.unc.edu)
-
- "Kernel Hacker's Guide", Michael K. Johnson (johnsonm@sunsite.unc.edu)
-
- "Adaptec 1520/1522 User's Guide", Adaptec Corporation.
-
- Michael K. Johnson (johnsonm@sunsite.unc.edu)
-
- Drew Eckhardt (drew@cs.colorado.edu)
-
- Eric Youngdale (ericy@cais.com)
-
- special thanks to Eric Youngdale for the free(!) supplying the
- documentation on the chip.
-
- **************************************************************************/
-
- #include <linux/sched.h>
- #include <asm/io.h>
- #include "../block/blk.h"
- #include "scsi.h"
- #include "sd.h"
- #include "hosts.h"
- #include "constants.h"
- #include <asm/system.h>
- #include <linux/errno.h>
- #include <linux/string.h>
- #include <linux/wait.h>
- #include <linux/ioport.h>
-
- #include "aha152x.h"
-
- /* DEFINES */
-
-
- /* If auto configuration is disabled, IRQ, SCSI_ID and RECONNECT have to
- be predefined */
- #if !defined(AUTOCONF)
- #if !defined(IRQ)
- #error undefined IRQ; define AUTOCONF or IRQ
- #endif
- #if !defined(SCSI_ID)
- #error undefined SCSI_ID; define AUTOCONF or SCSI_ID
- #endif
- #if !defined(RECONNECT)
- #error undefined RECONNECT; define AUTOCONF or RECONNECT
- #endif
- #if !defined(PARITY)
- #error undefined PARITY; define AUTOCONF or PARITY
- #endif
- #endif
-
- /* I use this when I'm looking for weird bugs */
- #define DEBUG_TIMING
-
- #if defined(DEBUG_AHA152X)
-
- #undef SKIP_PORTS /* don't display ports */
-
- #undef DEBUG_QUEUE /* debug queue() */
- #undef DEBUG_RESET /* debug reset() */
- #undef DEBUG_INTR /* debug intr() */
- #undef DEBUG_SELECTION /* debug selection part in intr() */
- #undef DEBUG_MSGO /* debug message out phase in intr() */
- #undef DEBUG_MSGI /* debug message in phase in intr() */
- #undef DEBUG_STATUS /* debug status phase in intr() */
- #undef DEBUG_CMD /* debug command phase in intr() */
- #undef DEBUG_DATAI /* debug data in phase in intr() */
- #undef DEBUG_DATAO /* debug data out phase in intr() */
- #undef DEBUG_ABORT /* debug abort() */
- #undef DEBUG_DONE /* debug done() */
- #undef DEBUG_BIOSPARAM /* debug biosparam() */
-
- #undef DEBUG_RACE /* debug race conditions */
- #undef DEBUG_PHASES /* debug phases (useful to trace) */
- #undef DEBUG_QUEUES /* debug reselection */
-
- /* recently used for debugging */
- #if 0
- #endif
-
- #define DEBUG_PHASES
- #define DEBUG_RESET
- #define DEBUG_ABORT
-
- #define DEBUG_DEFAULT (debug_reset|debug_abort)
-
- #endif
-
- /* END OF DEFINES */
-
- /* some additional "phases" for getphase() */
- #define P_BUSFREE 1
- #define P_PARITY 2
-
- static int port_base = 0;
- static int this_host = 0;
- static int can_disconnect = 0;
- static int can_doparity = 0;
- static int commands = 0;
-
- #ifdef DEBUG_AHA152X
- unsigned int aha152x_debug = DEBUG_DEFAULT;
- #endif
-
- /* set by aha152x_setup according to the command line */
- static int setup_called = 0;
- static int setup_portbase = 0;
- static int setup_irq = 0;
- static int setup_scsiid = 0;
- static int setup_reconnect = 0;
- static int setup_doparity = 0;
-
- #ifdef DEBUG_AHA152X
- static int setup_debug = 0;
- #endif
-
- static char *setup_str = (char *)NULL;
-
- enum {
- not_issued = 0x01,
- in_selection = 0x02,
- disconnected = 0x04,
- aborted = 0x08,
- sent_ident = 0x10,
- in_other = 0x20,
- };
-
- /*
- * Command queues:
- * issue_SC : commands that are queued to be issued
- * current_SC : command that's currently using the bus
- * disconnected_SC : commands that that have been disconnected
- */
- static Scsi_Cmnd *issue_SC = NULL;
- static Scsi_Cmnd *current_SC = NULL;
- static Scsi_Cmnd *disconnected_SC = NULL;
-
- static int aborting=0, abortion_complete=0, abort_result;
-
- void aha152x_intr( int irq, struct pt_regs * );
- void aha152x_done( int error );
- void aha152x_setup( char *str, int *ints );
-
- static void aha152x_reset_ports(void);
- static void aha152x_panic(char *msg);
-
- static void disp_ports(void);
- static void show_command(Scsi_Cmnd *ptr);
- static void show_queues(void);
- static void disp_enintr(void);
-
- #if defined(DEBUG_RACE)
- static void enter_driver(const char *);
- static void leave_driver(const char *);
- #endif
-
- /* possible i/o addresses for the AIC-6260 */
- static unsigned short ports[] =
- {
- 0x340, /* default first */
- 0x140
- };
- #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
-
- /* possible interrupt channels */
- static unsigned short irqs[] = { 9, 10, 11, 12, 0 };
-
- #if !defined(SKIP_BIOSTEST)
- /* possible locations for the Adaptec BIOS */
- static void *addresses[] =
- {
- (void *) 0xdc000, /* default first */
- (void *) 0xc8000,
- (void *) 0xcc000,
- (void *) 0xd0000,
- (void *) 0xd4000,
- (void *) 0xd8000,
- (void *) 0xe0000,
- (void *) 0xf0000,
- (void *) 0xeb800, /* VTech Platinum SMP */
- };
- #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( void * ))
-
- /* 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. */
- static struct signature {
- char *signature;
- int sig_offset;
- int sig_length;
- } signatures[] =
- {
- { "Adaptec AHA-1520 BIOS", 0x102e, 21 }, /* Adaptec 152x */
- { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, /* on-board controller */
- { "Adaptec BIOS: ASW-B626", 0x0f, 22 }, /* on-board controller */
- { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, /* on-board controller */
- { "Adaptec BIOS:AIC-6360", 0xc, 21 }, /* on-board controller */
- { "ScsiPro SP-360 BIOS", 0x2873, 19 }, /* ScsiPro-Controller with AIC-6360 */
- { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 }, /* Gigabyte Local-Bus-SCSI */
- };
- #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
- #endif
-
-
- static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
- {
- unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
-
- while (jiffies < the_time)
- ;
- }
-
- /*
- * queue services:
- */
- static inline void append_SC( Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
- {
- Scsi_Cmnd *end;
-
- new_SC->host_scribble = (unsigned char *) NULL;
- if(!*SC)
- *SC=new_SC;
- else
- {
- for( end=*SC;
- end->host_scribble;
- end = (Scsi_Cmnd *) end->host_scribble )
- ;
- end->host_scribble = (unsigned char *) new_SC;
- }
- }
-
- static inline Scsi_Cmnd *remove_first_SC( Scsi_Cmnd **SC )
- {
- Scsi_Cmnd *ptr;
-
- ptr=*SC;
- if(ptr)
- *SC= (Scsi_Cmnd *) (*SC)->host_scribble;
- return ptr;
- }
-
- static inline Scsi_Cmnd *remove_SC( Scsi_Cmnd **SC, int target, int lun )
- {
- Scsi_Cmnd *ptr, *prev;
-
- for( ptr=*SC, prev=NULL;
- ptr && ((ptr->target!=target) || (ptr->lun!=lun));
- prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble )
- ;
-
- if(ptr)
- if(prev)
- prev->host_scribble = ptr->host_scribble;
- else
- *SC= (Scsi_Cmnd *) ptr->host_scribble;
- return ptr;
- }
-
- /*
- * read inbound byte and wait for ACK to get low
- */
- static void make_acklow(void)
- {
- SETPORT( SXFRCTL0, CH1|SPIOEN );
- GETPORT(SCSIDAT);
- SETPORT( SXFRCTL0, CH1 );
-
- while( TESTHI( SCSISIG, ACKI ) )
- ;
- }
-
- /*
- * detect current phase more reliable:
- * phase is valid, when the target asserts REQ after we've deasserted ACK.
- *
- * return value is a valid phase or an error code.
- *
- * errorcodes:
- * P_BUSFREE BUS FREE phase detected
- * P_PARITY parity error in DATA phase
- */
- static int getphase(void)
- {
- int phase, sstat1;
-
- while( 1 )
- {
- do
- {
- while( !( ( sstat1 = GETPORT( SSTAT1 ) ) & (BUSFREE|SCSIRSTI|REQINIT ) ) )
- ;
- if( sstat1 & BUSFREE )
- return P_BUSFREE;
- if( sstat1 & SCSIRSTI )
- {
- /* IBM drive responds with RSTI to RSTO */
- printk("aha152x: RESET IN\n");
- SETPORT( SSTAT1, SCSIRSTI );
- }
- }
- while( TESTHI( SCSISIG, ACKI ) || TESTLO( SSTAT1, REQINIT ) );
-
- SETPORT( SSTAT1, CLRSCSIPERR );
-
- phase = GETPORT( SCSISIG ) & P_MASK ;
-
- if( TESTHI( SSTAT1, SCSIPERR ) )
- {
- if( (phase & (CDO|MSGO))==0 ) /* DATA phase */
- return P_PARITY;
-
- make_acklow();
- }
- else
- return phase;
- }
- }
-
- /* called from init/main.c */
- void aha152x_setup( char *str, int *ints)
- {
- if(setup_called)
- panic("aha152x: aha152x_setup called twice.\n");
-
- setup_called=ints[0];
- setup_str=str;
-
- setup_portbase = ints[0] >= 1 ? ints[1] : 0x340;
- setup_irq = ints[0] >= 2 ? ints[2] : 11;
- setup_scsiid = ints[0] >= 3 ? ints[3] : 7;
- setup_reconnect = ints[0] >= 4 ? ints[4] : 1;
- setup_doparity = ints[0] >= 5 ? ints[5] : 1;
- #ifdef DEBUG_AHA152X
- setup_debug = ints[0] >= 6 ? ints[6] : DEBUG_DEFAULT;
- #endif
- }
-
- /*
- Test, if port_base is valid.
- */
- static int aha152x_porttest(int port_base)
- {
- int i;
-
- if(check_region(port_base, TEST-SCSISEQ))
- return 0;
-
- SETPORT( DMACNTRL1, 0 ); /* reset stack pointer */
- for(i=0; i<16; i++)
- SETPORT( STACK, i );
-
- SETPORT( DMACNTRL1, 0 ); /* reset stack pointer */
- for(i=0; i<16 && GETPORT(STACK)==i; i++)
- ;
-
- return(i==16);
- }
-
- int aha152x_detect(Scsi_Host_Template * tpnt)
- {
- int i, ok;
- #if defined(AUTOCONF)
- aha152x_config conf;
- #endif
- int interrupt_level;
-
- if(setup_called)
- {
- printk("aha152x: processing commandline: ");
-
- #ifdef DEBUG_AHA152X
- if(setup_called>6)
- #else
- if(setup_called>5)
- #endif
- {
- printk("\naha152x: %s\n", setup_str );
- #ifdef DEBUG_AHA152X
- printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>[,<DEBUG>]]]]]\n");
- #else
- printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>]]]]\n");
- #endif
- panic("aha152x panics in line %d", __LINE__);
- }
-
- port_base = setup_portbase;
- interrupt_level = setup_irq;
- this_host = setup_scsiid;
- can_disconnect = setup_reconnect;
- can_doparity = setup_doparity;
- #ifdef DEBUG_AHA152X
- aha152x_debug = setup_debug;
- #endif
-
- for( i=0; i<PORT_COUNT && (port_base != ports[i]); i++)
- ;
-
- if(i==PORT_COUNT)
- {
- printk("unknown portbase 0x%03x\n", port_base);
- panic("aha152x panics in line %d", __LINE__);
- }
-
- if(!aha152x_porttest(port_base))
- {
- printk("portbase 0x%03x fails probe\n", port_base);
- panic("aha152x panics in line %d", __LINE__);
- }
-
- i=0;
- while(irqs[i] && (interrupt_level!=irqs[i]))
- i++;
- if(!irqs[i])
- {
- printk("illegal IRQ %d\n", interrupt_level);
- panic("aha152x panics in line %d", __LINE__);
- }
-
- if( (this_host < 0) || (this_host > 7) )
- {
- printk("illegal SCSI ID %d\n", this_host);
- panic("aha152x panics in line %d", __LINE__);
- }
-
- if( (can_disconnect < 0) || (can_disconnect > 1) )
- {
- printk("reconnect %d should be 0 or 1\n", can_disconnect);
- panic("aha152x panics in line %d", __LINE__);
- }
-
- if( (can_doparity < 0) || (can_doparity > 1) )
- {
- printk("parity %d should be 0 or 1\n", can_doparity);
- panic("aha152x panics in line %d", __LINE__);
- }
- printk("ok\n");
- }
- else
- {
- #if !defined(SKIP_BIOSTEST)
- int j;
-
- ok=0;
- for( i=0; i < ADDRESS_COUNT && !ok; i++)
- for( j=0; (j < SIGNATURE_COUNT) && !ok; j++)
- ok=!memcmp((void *) addresses[i]+signatures[j].sig_offset,
- (void *) signatures[j].signature,
- (int) signatures[j].sig_length);
-
- if(!ok)
- return 0;
-
- printk("aha152x: BIOS test: passed, ");
- #else
- printk("aha152x: ");
- #endif /* !SKIP_BIOSTEST */
-
- #if !defined(PORTBASE)
- printk("porttest: ");
- for( i=0; i<PORT_COUNT && !aha152x_porttest(ports[i]); i++)
- ;
-
- if(i==PORT_COUNT)
- {
- printk("failed\n");
- return 0;
- }
- else
- port_base=ports[i];
- printk("ok, ");
- #else
- port_base=PORTBASE;
- #endif /* !PORTBASE */
-
- #if defined(AUTOCONF)
-
- conf.cf_port = (GETPORT(PORTA)<<8) + GETPORT(PORTB);
-
- interrupt_level = irqs[conf.cf_irq];
- this_host = conf.cf_id;
- can_disconnect = conf.cf_tardisc;
- can_doparity = !conf.cf_parity;
-
- printk("auto configuration: ok, ");
-
- #endif /* AUTOCONF */
-
- #if defined(IRQ)
- interrupt_level = IRQ;
- #endif
-
- #if defined(SCSI_ID)
- this_host = SCSI_ID;
- #endif
-
- #if defined(RECONNECT)
- can_disconnect=RECONNECT;
- #endif
-
- #if defined(PARITY)
- can_doparity=PARITY;
- #endif
- }
-
- printk("detection complete\n");
-
- ok = request_irq(interrupt_level, aha152x_intr, SA_INTERRUPT, "aha152x");
-
- if(ok<0)
- {
- if(ok == -EINVAL)
- {
- printk("aha152x: bad IRQ %d.\n", interrupt_level);
- printk(" Contact author.\n");
- }
- else
- if( ok == -EBUSY)
- printk( "aha152x: IRQ %d already in use. Configure another.\n",
- interrupt_level);
- else
- {
- printk( "\naha152x: Unexpected error code on requesting IRQ %d.\n",
- interrupt_level);
- printk(" Contact author.\n");
- }
- panic("aha152x: driver needs an IRQ.\n");
- }
-
- SETPORT( SCSIID, this_host << 4 );
- tpnt->this_id=this_host;
-
- if(can_disconnect)
- tpnt->can_queue=AHA152X_MAXQUEUE;
-
- /* RESET OUT */
- SETBITS(SCSISEQ, SCSIRSTO );
- do_pause(30);
- CLRBITS(SCSISEQ, SCSIRSTO );
- do_pause(60);
-
- aha152x_reset(NULL);
-
- printk("aha152x: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d, reconnect=%s, parity=%s\n",
- port_base,
- interrupt_level,
- this_host,
- can_disconnect ? "enabled" : "disabled",
- can_doparity ? "enabled" : "disabled");
-
- request_region(port_base, TEST-SCSISEQ, "aha152x"); /* Register */
-
- /* not expecting any interrupts */
- SETPORT(SIMODE0, 0);
- SETPORT(SIMODE1, 0);
-
- SETBITS( DMACNTRL0, INTEN);
- return 1;
- }
-
- /*
- * Queue a command and setup interrupts for a free bus.
- */
- int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
- {
- unsigned long flags;
-
- #if defined(DEBUG_RACE)
- enter_driver("queue");
- #else
- #if defined(DEBUG_QUEUE)
- if(aha152x_debug & debug_queue)
- printk("aha152x: queue(), ");
- #endif
- #endif
-
- #if defined(DEBUG_QUEUE)
- if(aha152x_debug & debug_queue)
- {
- printk( "SCpnt (target = %d lun = %d cmnd = ", SCpnt->target, SCpnt->lun);
- print_command(SCpnt->cmnd);
- printk( ", cmd_len=%d, pieces = %d size = %u), ",
- SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen );
- disp_ports();
- }
- #endif
-
- SCpnt->scsi_done = done;
-
- /* 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 */
- SCpnt->SCp.phase = not_issued;
- if (SCpnt->use_sg)
- {
- SCpnt->SCp.buffer = (struct scatterlist *)SCpnt->request_buffer;
- SCpnt->SCp.ptr = SCpnt->SCp.buffer->address;
- 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;
- }
-
- SCpnt->SCp.Status = CHECK_CONDITION;
- SCpnt->SCp.Message = 0;
- SCpnt->SCp.have_data_in = 0;
- SCpnt->SCp.sent_command = 0;
-
- /* Turn led on, when this is the first command. */
- save_flags(flags);
- cli();
- commands++;
- if(commands==1)
- SETPORT( PORTA, 1 );
-
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("i+ (%d), ", commands );
- #endif
- append_SC( &issue_SC, SCpnt);
-
- /* Enable bus free interrupt, when we aren't currently on the bus */
- if(!current_SC)
- {
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
- }
- restore_flags(flags);
-
- #if defined(DEBUG_RACE)
- leave_driver("queue");
- #endif
-
- return 0;
- }
-
- /*
- * We only support command in interrupt-driven fashion
- */
- int aha152x_command( Scsi_Cmnd *SCpnt )
- {
- printk( "aha152x: interrupt driven driver; use aha152x_queue()\n" );
- return -1;
- }
-
- /*
- * Abort a queued command
- * (commands that are on the bus can't be aborted easily)
- */
- int aha152x_abort( Scsi_Cmnd *SCpnt)
- {
- unsigned long flags;
- Scsi_Cmnd *ptr, *prev;
-
- save_flags(flags);
- cli();
-
- #if defined(DEBUG_ABORT)
- if(aha152x_debug & debug_abort)
- {
- printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt );
-
- show_queues();
- }
- #endif
-
- /* look for command in issue queue */
- for( ptr=issue_SC, prev=NULL;
- ptr && ptr!=SCpnt;
- prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
- ;
-
- if(ptr)
- {
- /* dequeue */
- if(prev)
- prev->host_scribble = ptr->host_scribble;
- else
- issue_SC = (Scsi_Cmnd *) ptr->host_scribble;
- restore_flags(flags);
-
- ptr->host_scribble = NULL;
- ptr->result = DID_ABORT << 16;
- ptr->done(ptr);
- return SCSI_ABORT_SUCCESS;
- }
-
- /* if the bus is busy or a command is currently processed,
- we can't do anything more */
- if ( TESTLO(SSTAT1, BUSFREE) || (current_SC && current_SC!=SCpnt))
- {
- /* fail abortion, if bus is busy */
-
- if(!current_SC)
- printk("bus busy w/o current command, ");
-
- restore_flags(flags);
- return SCSI_ABORT_BUSY;
- }
-
- /* bus is free */
-
- if(current_SC)
- {
- /* target entered bus free before COMMAND COMPLETE, nothing to abort */
- restore_flags(flags);
- current_SC->result = DID_ERROR << 16;
- current_SC->done(current_SC);
- current_SC = (Scsi_Cmnd *) NULL;
- return SCSI_ABORT_SUCCESS;
- }
-
- /* look for command in disconnected queue */
- for( ptr=disconnected_SC, prev=NULL;
- ptr && ptr!=SCpnt;
- prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
- ;
-
- if(ptr)
- if(!aborting)
- {
- /* dequeue */
- if(prev)
- prev->host_scribble = ptr->host_scribble;
- else
- disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
-
- /* set command current and initiate selection,
- let the interrupt routine take care of the abortion */
- current_SC = ptr;
- ptr->SCp.phase = in_selection|aborted;
- SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
-
- /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
- SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
- SETPORT( SIMODE1, ENSELTIMO );
-
- /* Enable SELECTION OUT sequence */
- SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
-
- SETBITS( DMACNTRL0, INTEN );
- abort_result=SCSI_ABORT_SUCCESS;
- aborting++;
- abortion_complete=0;
-
- sti(); /* Hi Eric, guess what ;-) */
-
- /* sleep until the abortion is complete */
- while(!abortion_complete)
- ;
- aborting=0;
- return abort_result;
- }
- else
- {
- /* we're already aborting a command */
- restore_flags(flags);
- return SCSI_ABORT_BUSY;
- }
-
- /* command wasn't found */
- printk("command not found\n");
- restore_flags(flags);
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- /*
- * Restore default values to the AIC-6260 registers and reset the fifos
- */
- static void aha152x_reset_ports(void)
- {
- /* disable interrupts */
- SETPORT(DMACNTRL0, RSTFIFO);
-
- SETPORT(SCSISEQ, 0);
-
- SETPORT(SXFRCTL1, 0);
- SETPORT( SCSISIG, 0);
- SETPORT(SCSIRATE, 0);
-
- /* clear all interrupt conditions */
- SETPORT(SSTAT0, 0x7f);
- SETPORT(SSTAT1, 0xef);
-
- SETPORT(SSTAT4, SYNCERR|FWERR|FRERR);
-
- SETPORT(DMACNTRL0, 0);
- SETPORT(DMACNTRL1, 0);
-
- SETPORT(BRSTCNTRL, 0xf1);
-
- /* clear SCSI fifo and transfer count */
- SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
- SETPORT(SXFRCTL0, CH1);
-
- /* enable interrupts */
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
- }
-
- /*
- * Reset registers, reset a hanging bus and
- * kill active and disconnected commands for target w/o soft reset
- */
- int aha152x_reset(Scsi_Cmnd * __unused)
- {
- unsigned long flags;
- Scsi_Cmnd *ptr, *prev, *next;
-
- aha152x_reset_ports();
-
- /* Reset, if bus hangs */
- if( TESTLO( SSTAT1, BUSFREE ) )
- {
- CLRBITS( DMACNTRL0, INTEN );
-
- #if defined(DEBUG_RESET)
- if(aha152x_debug & debug_reset)
- {
- printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");
- show_queues();
- }
- #endif
-
- if(current_SC && !current_SC->device->soft_reset)
- {
- current_SC->host_scribble = NULL;
- current_SC->result = DID_RESET << 16;
- current_SC->done(current_SC);
- current_SC=NULL;
- }
-
- save_flags(flags);
- cli();
- prev=NULL; ptr=disconnected_SC;
- while(ptr)
- {
- if(!ptr->device->soft_reset)
- {
- if(prev)
- prev->host_scribble = ptr->host_scribble;
- else
- disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
-
- next = (Scsi_Cmnd *) ptr->host_scribble;
-
- ptr->host_scribble = NULL;
- ptr->result = DID_RESET << 16;
- ptr->done(ptr);
-
- ptr = next;
- }
- else
- {
- prev=ptr;
- ptr = (Scsi_Cmnd *) ptr->host_scribble;
- }
- }
- restore_flags(flags);
-
- #if defined( DEBUG_RESET )
- if(aha152x_debug & debug_reset)
- {
- printk("commands on targets w/ soft-resets:\n");
- show_queues();
- }
- #endif
-
- /* RESET OUT */
- SETPORT(SCSISEQ, SCSIRSTO);
- do_pause(30);
- SETPORT(SCSISEQ, 0);
- do_pause(60);
-
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-
- SETPORT( DMACNTRL0, INTEN );
- }
-
- return SCSI_RESET_SUCCESS;
- }
-
- /*
- * Return the "logical geometry"
- */
- int aha152x_biosparam(Scsi_Disk * disk, int dev, int *info_array )
- {
- int size = disk->capacity;
-
- #if defined(DEBUG_BIOSPARAM)
- if(aha152x_debug & debug_biosparam)
- printk("aha152x_biosparam: dev=%x, size=%d, ", dev, size);
- #endif
-
- /* I took this from other SCSI drivers, since it provides
- the correct data for my devices. */
- info_array[0]=64;
- info_array[1]=32;
- info_array[2]=size>>11;
-
- #if defined(DEBUG_BIOSPARAM)
- if(aha152x_debug & debug_biosparam)
- {
- printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
- info_array[0], info_array[1], info_array[2]);
- printk("WARNING: check, if the bios geometry is correct.\n");
- }
- #endif
-
- return 0;
- }
-
- /*
- * Internal done function
- */
- void aha152x_done( int error )
- {
- unsigned long flags;
- Scsi_Cmnd *done_SC;
-
- #if defined(DEBUG_DONE)
- if(aha152x_debug & debug_done)
- {
- printk("\naha152x: done(), ");
- disp_ports();
- }
- #endif
-
- if (current_SC)
- {
- #if defined(DEBUG_DONE)
- if(aha152x_debug & debug_done)
- printk("done(%x), ", error);
- #endif
-
- save_flags(flags);
- cli();
-
- done_SC = current_SC;
- current_SC = NULL;
-
- /* turn led off, when no commands are in the driver */
- commands--;
- if(!commands)
- SETPORT( PORTA, 0 ); /* turn led off */
-
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("ok (%d), ", commands);
- #endif
- restore_flags(flags);
-
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-
- #if defined(DEBUG_PHASES)
- if(aha152x_debug & debug_phases)
- printk("BUS FREE loop, ");
- #endif
- while( TESTLO( SSTAT1, BUSFREE ) )
- ;
- #if defined(DEBUG_PHASES)
- if(aha152x_debug & debug_phases)
- printk("BUS FREE\n");
- #endif
-
- done_SC->result = error;
- if(done_SC->scsi_done)
- {
- #if defined(DEBUG_DONE)
- if(aha152x_debug & debug_done)
- printk("calling scsi_done, ");
- #endif
- done_SC->scsi_done( done_SC );
- #if defined(DEBUG_DONE)
- if(aha152x_debug & debug_done)
- printk("done returned, ");
- #endif
- }
- else
- panic( "aha152x: current_SC->scsi_done() == NULL" );
- }
- else
- aha152x_panic( "done() called outside of command" );
- }
-
- /*
- * Interrupts handler (main routine of the driver)
- */
- void aha152x_intr( int irqno, struct pt_regs * regs )
- {
- unsigned int flags;
- int done=0, phase;
-
- #if defined(DEBUG_RACE)
- enter_driver("intr");
- #else
- #if defined(DEBUG_INTR)
- if(aha152x_debug & debug_intr)
- printk("\naha152x: intr(), ");
- #endif
- #endif
-
- /* no more interrupts from the controller, while we busy.
- INTEN has to be restored, when we're ready to leave
- intr(). To avoid race conditions we have to return
- immediately afterwards. */
- CLRBITS( DMACNTRL0, INTEN);
- sti(); /* Yes, sti() really needs to be here */
-
- /* disconnected target is trying to reconnect.
- Only possible, if we have disconnected nexuses and
- nothing is occupying the bus.
- */
- if( TESTHI( SSTAT0, SELDI ) &&
- disconnected_SC &&
- ( !current_SC || ( current_SC->SCp.phase & in_selection ) )
- )
- {
- int identify_msg, target, i;
-
- /* Avoid conflicts when a target reconnects
- while we are trying to connect to another. */
- if(current_SC)
- {
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("i+, ");
- #endif
- save_flags(flags);
- cli();
- append_SC( &issue_SC, current_SC);
- current_SC=NULL;
- restore_flags(flags);
- }
-
- /* disable sequences */
- SETPORT( SCSISEQ, 0 );
- SETPORT( SSTAT0, CLRSELDI );
- SETPORT( SSTAT1, CLRBUSFREE );
-
- #if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_queues|debug_phases))
- printk("reselected, ");
- #endif
-
- i = GETPORT(SELID) & ~(1 << this_host);
- target=0;
- if(i)
- for( ; (i & 1)==0; target++, i>>=1)
- ;
- else
- aha152x_panic("reconnecting target unknown");
-
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("SELID=%02x, target=%d, ", GETPORT(SELID), target );
- #endif
- SETPORT( SCSIID, (this_host << OID_) | target );
- SETPORT( SCSISEQ, ENRESELI );
-
- if(TESTLO( SSTAT0, SELDI ))
- aha152x_panic("RESELI failed");
-
- SETPORT( SCSISIG, P_MSGI );
-
- /* Get identify message */
- if((i=getphase())!=P_MSGI)
- {
- printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
- aha152x_panic("unknown lun");
- }
- SETPORT( SCSISEQ, 0 );
-
- SETPORT( SXFRCTL0, CH1);
-
- identify_msg = GETPORT(SCSIBUS);
-
- if(!(identify_msg & IDENTIFY_BASE))
- {
- printk("target=%d, inbound message (%02x) != IDENTIFY\n",
- target, identify_msg);
- aha152x_panic("unknown lun");
- }
-
- make_acklow();
- getphase();
-
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f );
- #endif
-
- save_flags(flags);
- cli();
-
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("d-, ");
- #endif
- current_SC = remove_SC( &disconnected_SC,
- target,
- identify_msg & 0x3f );
-
- if(!current_SC)
- {
- printk("lun=%d, ", identify_msg & 0x3f );
- aha152x_panic("no disconnected command for that lun");
- }
-
- current_SC->SCp.phase &= ~disconnected;
- restore_flags(flags);
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
- #if defined(DEBUG_RACE)
- leave_driver("(reselected) intr");
- #endif
- SETBITS( DMACNTRL0, INTEN);
- return;
- }
-
- /* Check, if we aren't busy with a command */
- if(!current_SC)
- {
- /* bus is free to issue a queued command */
- if(TESTHI( SSTAT1, BUSFREE) && issue_SC)
- {
- save_flags(flags);
- cli();
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("i-, ");
- #endif
- current_SC = remove_first_SC( &issue_SC );
- restore_flags(flags);
-
- #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_intr|debug_selection|debug_phases))
- printk("issuing command, ");
- #endif
- current_SC->SCp.phase = in_selection;
-
- #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_intr|debug_selection|debug_phases))
- printk("selecting %d, ", current_SC->target);
- #endif
- SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
-
- /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
- SETPORT( SXFRCTL1, can_doparity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
-
- /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
- SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
- SETPORT( SIMODE1, ENSELTIMO );
-
- /* Enable SELECTION OUT sequence */
- SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
-
- #if defined(DEBUG_RACE)
- leave_driver("(selecting) intr");
- #endif
- SETBITS( DMACNTRL0, INTEN );
- return;
- }
-
- /* No command we are busy with and no new to issue */
- printk("aha152x: ignoring spurious interrupt, nothing to do\n");
- return;
- }
-
- /* the bus is busy with something */
-
- #if defined(DEBUG_INTR)
- if(aha152x_debug & debug_intr)
- disp_ports();
- #endif
-
- /* we are waiting for the result of a selection attempt */
- if(current_SC->SCp.phase & in_selection)
- {
- if( TESTLO( SSTAT1, SELTO ) )
- /* no timeout */
- if( TESTHI( SSTAT0, SELDO ) )
- {
- /* clear BUS FREE interrupt */
- SETPORT( SSTAT1, CLRBUSFREE);
-
- /* Disable SELECTION OUT sequence */
- CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
-
- /* Disable SELECTION OUT DONE interrupt */
- CLRBITS(SIMODE0, ENSELDO);
- CLRBITS(SIMODE1, ENSELTIMO);
-
- if( TESTLO(SSTAT0, SELDO) )
- {
- printk("aha152x: passing bus free condition\n");
-
- #if defined(DEBUG_RACE)
- leave_driver("(passing bus free) intr");
- #endif
- SETBITS( DMACNTRL0, INTEN);
-
- if(current_SC->SCp.phase & aborted)
- {
- abort_result=SCSI_ABORT_ERROR;
- abortion_complete++;
- }
-
- aha152x_done( DID_NO_CONNECT << 16 );
- return;
- }
- #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_selection|debug_phases))
- printk("SELDO (SELID=%x), ", GETPORT(SELID));
- #endif
-
- /* selection was done */
- SETPORT( SSTAT0, CLRSELDO );
-
- #if defined(DEBUG_ABORT)
- if((aha152x_debug & debug_abort) && (current_SC->SCp.phase & aborted))
- printk("(ABORT) target selected, ");
- #endif
-
- current_SC->SCp.phase &= ~in_selection;
- current_SC->SCp.phase |= in_other;
-
- #if defined(DEBUG_RACE)
- leave_driver("(SELDO) intr");
- #endif
-
- SETPORT( SCSISIG, P_MSGO );
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
- SETBITS( DMACNTRL0, INTEN);
- return;
- }
- else
- aha152x_panic("neither timeout nor selection\007");
- else
- {
- #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_selection|debug_phases))
- printk("SELTO, ");
- #endif
- /* end selection attempt */
- CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
-
- /* timeout */
- SETPORT( SSTAT1, CLRSELTIMO );
-
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
- SETBITS( DMACNTRL0, INTEN );
- #if defined(DEBUG_RACE)
- leave_driver("(SELTO) intr");
- #endif
-
- if(current_SC->SCp.phase & aborted)
- {
- #if defined(DEBUG_ABORT)
- if(aha152x_debug & debug_abort)
- printk("(ABORT) selection timeout, ");
- #endif
- abort_result=SCSI_ABORT_ERROR;
- abortion_complete++;
- }
-
- if( TESTLO( SSTAT0, SELINGO ) )
- /* ARBITRATION not won */
- aha152x_done( DID_BUS_BUSY << 16 );
- else
- /* ARBITRATION won, but SELECTION failed */
- aha152x_done( DID_NO_CONNECT << 16 );
- return;
- }
- }
-
- /* enable interrupt, when target leaves current phase */
- phase = getphase();
- if(!(phase & ~P_MASK)) /* "real" phase */
- SETPORT(SCSISIG, phase);
- SETPORT(SSTAT1, CLRPHASECHG);
- current_SC->SCp.phase =
- (current_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16 );
-
- /* information transfer phase */
- switch( phase )
- {
- case P_MSGO: /* MESSAGE OUT */
- {
- unsigned char message;
-
- #if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_intr|debug_msgo|debug_phases))
- printk("MESSAGE OUT, ");
- #endif
-
- if( current_SC->SCp.phase & aborted )
- {
- #if defined(DEBUG_MSGO) || defined(DEBUG_ABORT)
- if(aha152x_debug & (debug_msgo|debug_abort))
- printk("ABORT, ");
- #endif
- message=ABORT;
- }
- else
- /* If we didn't identify yet, do it. Otherwise there's nothing to do,
- but reject (probably we got an message before, that we have to
- reject (SDTR, WDTR, etc.) */
- if( !(current_SC->SCp.phase & sent_ident))
- {
- message=IDENTIFY(can_disconnect,current_SC->lun);
- #if defined(DEBUG_MSGO)
- if(aha152x_debug & debug_msgo)
- printk("IDENTIFY (reconnect=%s;lun=%d), ",
- can_disconnect ? "enabled" : "disabled", current_SC->lun);
- #endif
- }
- else
- {
- message=MESSAGE_REJECT;
- #if defined(DEBUG_MSGO)
- if(aha152x_debug & debug_msgo)
- printk("REJECT, ");
- #endif
- }
-
- CLRBITS( SXFRCTL0, ENDMA);
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE );
-
- /* wait for data latch to become ready or a phase change */
- while( TESTLO( DMASTAT, INTSTAT ) )
- ;
-
- if( TESTHI( SSTAT1, PHASEMIS ) )
- aha152x_panic("unable to send message");
-
- /* Leave MESSAGE OUT after transfer */
- SETPORT( SSTAT1, CLRATNO);
-
- SETPORT( SCSIDAT, message );
-
- make_acklow();
- getphase();
-
- if(message==IDENTIFY(can_disconnect,current_SC->lun))
- current_SC->SCp.phase |= sent_ident;
-
- if(message==ABORT)
- {
- /* revive abort(); abort() enables interrupts */
- abort_result=SCSI_ABORT_SUCCESS;
- abortion_complete++;
-
- current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
-
- /* exit */
- SETBITS( DMACNTRL0, INTEN );
- #if defined(DEBUG_RACE)
- leave_driver("(ABORT) intr");
- #endif
- aha152x_done(DID_ABORT<<16);
- return;
- }
- }
- break;
-
- case P_CMD: /* COMMAND phase */
- #if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_intr|debug_cmd|debug_phases))
- printk("COMMAND, ");
- #endif
- if( !(current_SC->SCp.sent_command) )
- {
- if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
- printk("aha152x: P_CMD: %d(%d) bytes left in FIFO, resetting\n",
- GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
-
- /* reset fifo and enable writes */
- SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
- SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
-
- /* clear transfer count and scsi fifo */
- SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
- SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
-
- /* missing phase raises INTSTAT */
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
-
- #if defined(DEBUG_CMD)
- if(aha152x_debug & debug_cmd)
- printk("waiting, ");
- #endif
- /* wait for FIFO to get empty */
- while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
- ;
-
- if( TESTHI( SSTAT1, PHASEMIS ) )
- aha152x_panic("target left COMMAND phase");
-
- #if defined(DEBUG_CMD)
- if(aha152x_debug & debug_cmd)
- {
- printk("DFIFOEMP, outsw (%d bytes, %d words), ",
- current_SC->cmd_len, current_SC->cmd_len >> 1 );
- disp_ports();
- }
- #endif
-
- outsw( DATAPORT, ¤t_SC->cmnd, current_SC->cmd_len >> 1 );
-
- #if defined(DEBUG_CMD)
- if(aha152x_debug & debug_cmd)
- {
- printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() );
- disp_ports();
- }
- #endif
-
- #if defined(DEBUG_CMD)
- if(aha152x_debug & debug_cmd)
- printk("waiting for SEMPTY, ");
- #endif
-
- /* wait for SCSI FIFO to get empty.
- very important to send complete commands. */
- while( TESTLO ( SSTAT2, SEMPTY ) )
- ;
-
- #if defined(DEBUG_CMD)
- if(aha152x_debug & debug_cmd)
- printk("SEMPTY, ");
- #endif
-
- CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
- /* transfer can be considered ended, when SCSIEN reads back zero */
- while( TESTHI( SXFRCTL0, SCSIEN ) )
- ;
-
- #if defined(DEBUG_CMD)
- if(aha152x_debug & debug_cmd)
- printk("!SEMPTY, ");
- #endif
-
- CLRBITS(DMACNTRL0, ENDMA);
-
- #if defined(DEBUG_CMD) || defined(DEBUG_INTR)
- if(debug_cmd & debug_intr)
- printk("sent %d/%d command bytes, ", GETSTCNT(),
- current_SC->cmd_len);
- #endif
-
- }
- else
- aha152x_panic("Nothing to sent while in COMMAND OUT");
- break;
-
- case P_MSGI: /* MESSAGE IN phase */
- #if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_intr|debug_msgi|debug_phases))
- printk("MESSAGE IN, ");
- #endif
- SETPORT( SXFRCTL0, CH1);
-
- SETPORT( SIMODE0, 0);
- SETPORT( SIMODE1, ENBUSFREE);
-
- while( phase == P_MSGI )
- {
- current_SC->SCp.Message = GETPORT( SCSIBUS );
- switch(current_SC->SCp.Message)
- {
- case DISCONNECT:
- #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_msgi|debug_phases))
- printk("target disconnected, ");
- #endif
- current_SC->SCp.Message = 0;
- current_SC->SCp.phase |= disconnected;
- if(!can_disconnect)
- aha152x_panic("target was not allowed to disconnect");
- break;
-
- case COMMAND_COMPLETE:
- #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_msgi|debug_phases))
- printk("inbound message ( COMMAND COMPLETE ), ");
- #endif
- done++;
- break;
-
- case MESSAGE_REJECT:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("inbound message ( MESSAGE REJECT ), ");
- #endif
- break;
-
- case SAVE_POINTERS:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("inbound message ( SAVE DATA POINTERS ), ");
- #endif
- break;
-
- case EXTENDED_MESSAGE:
- {
- int i, code;
-
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("inbound message ( EXTENDED MESSAGE ), ");
- #endif
- make_acklow();
- if(getphase()!=P_MSGI)
- break;
-
- i=GETPORT(SCSIBUS);
-
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("length (%d), code ( ", i);
- #endif
-
- make_acklow();
- if(getphase()!=P_MSGI)
- break;
-
- code = GETPORT(SCSIBUS);
-
- switch( code )
- {
- case 0x00:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("MODIFY DATA POINTER ");
- #endif
- SETPORT(SCSISIG, P_MSGI|ATNO);
- break;
- case 0x01:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("SYNCHRONOUS DATA TRANSFER REQUEST ");
- #endif
- SETPORT(SCSISIG, P_MSGI|ATNO);
- break;
- case 0x02:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("EXTENDED IDENTIFY ");
- #endif
- break;
- case 0x03:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("WIDE DATA TRANSFER REQUEST ");
- #endif
- SETPORT(SCSISIG, P_MSGI|ATNO);
- break;
- default:
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- if( code & 0x80 )
- printk("reserved (%d) ", code );
- else
- printk("vendor specific (%d) ", code);
- #endif
- SETPORT(SCSISIG, P_MSGI|ATNO);
- break;
- }
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk(" ), data ( ");
- #endif
- while( --i && (make_acklow(), getphase()==P_MSGI))
- {
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk("%x ", GETPORT(SCSIBUS) );
- #else
- GETPORT(SCSIBUS);
- #endif
- }
- #if defined(DEBUG_MSGI)
- if(aha152x_debug & debug_msgi)
- printk(" ), ");
- #endif
- /* We reject all extended messages. To do this
- we just enter MSGO by asserting ATN. Since
- we have already identified a REJECT message
- will be sent. */
- SETPORT(SCSISIG, P_MSGI|ATNO);
- }
- break;
-
- default:
- printk("unsupported inbound message %x, ", current_SC->SCp.Message);
- break;
-
- }
-
- make_acklow();
- phase=getphase();
- }
-
- /* clear SCSI fifo on BUSFREE */
- if(phase==P_BUSFREE)
- SETPORT(SXFRCTL0, CH1|CLRCH1);
-
- if(current_SC->SCp.phase & disconnected)
- {
- save_flags(flags);
- cli();
- #if defined(DEBUG_QUEUES)
- if(aha152x_debug & debug_queues)
- printk("d+, ");
- #endif
- append_SC( &disconnected_SC, current_SC);
- current_SC = NULL;
- restore_flags(flags);
-
- SETBITS( SCSISEQ, ENRESELI );
-
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-
- SETBITS( DMACNTRL0, INTEN );
- return;
- }
- break;
-
- case P_STATUS: /* STATUS IN phase */
- #if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_status|debug_intr|debug_phases))
- printk("STATUS, ");
- #endif
- SETPORT( SXFRCTL0, CH1);
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
-
- if( TESTHI( SSTAT1, PHASEMIS ) )
- printk("aha152x: passing STATUS phase");
-
- current_SC->SCp.Status = GETPORT( SCSIBUS );
- make_acklow();
- getphase();
-
- #if defined(DEBUG_STATUS)
- if(aha152x_debug & debug_status)
- {
- printk("inbound status ");
- print_status( current_SC->SCp.Status );
- printk(", ");
- }
- #endif
- break;
-
- case P_DATAI: /* DATA IN phase */
- {
- int fifodata, data_count, done;
-
- #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_datai|debug_intr|debug_phases))
- printk("DATA IN, ");
- #endif
-
- if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
- printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n",
- GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
-
- /* reset host fifo */
- SETPORT(DMACNTRL0, RSTFIFO);
- SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
-
- SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN );
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
-
- /* done is set when the FIFO is empty after the target left DATA IN */
- done=0;
-
- /* while the target stays in DATA to transfer data */
- while ( !done )
- {
- #if defined(DEBUG_DATAI)
- if(aha152x_debug & debug_datai)
- printk("expecting data, ");
- #endif
- /* wait for PHASEMIS or full FIFO */
- while( TESTLO ( DMASTAT, DFIFOFULL|INTSTAT ) )
- ;
-
- if( TESTHI( DMASTAT, DFIFOFULL ) )
- fifodata=GETPORT(FIFOSTAT);
- else
- {
- /* wait for SCSI fifo to get empty */
- while( TESTLO( SSTAT2, SEMPTY ) )
- ;
-
- /* rest of data in FIFO */
- fifodata=GETPORT(FIFOSTAT);
- #if defined(DEBUG_DATAI)
- if(aha152x_debug & debug_datai)
- printk("last transfer, ");
- #endif
- done=1;
- }
-
- #if defined(DEBUG_DATAI)
- if(aha152x_debug & debug_datai)
- printk("fifodata=%d, ", fifodata);
- #endif
-
- while( fifodata && current_SC->SCp.this_residual )
- {
- data_count=fifodata;
-
- /* limit data transfer to size of first sg buffer */
- if (data_count > current_SC->SCp.this_residual)
- data_count = current_SC->SCp.this_residual;
-
- fifodata -= data_count;
-
- #if defined(DEBUG_DATAI)
- if(aha152x_debug & debug_datai)
- printk("data_count=%d, ", data_count);
- #endif
-
- if(data_count&1)
- {
- /* get a single byte in byte mode */
- SETBITS(DMACNTRL0, _8BIT );
- *current_SC->SCp.ptr++ = GETPORT( DATAPORT );
- current_SC->SCp.this_residual--;
- }
- if(data_count>1)
- {
- CLRBITS(DMACNTRL0, _8BIT );
- data_count >>= 1; /* Number of words */
- insw( DATAPORT, current_SC->SCp.ptr, data_count );
- #if defined(DEBUG_DATAI)
- if(aha152x_debug & debug_datai)
- /* show what comes with the last transfer */
- if(done)
- {
- int i;
- unsigned char *data;
-
- printk("data on last transfer (%d bytes: ",
- 2*data_count);
- data = (unsigned char *) current_SC->SCp.ptr;
- for( i=0; i<2*data_count; i++)
- printk("%2x ", *data++);
- printk("), ");
- }
- #endif
- current_SC->SCp.ptr += 2 * data_count;
- current_SC->SCp.this_residual -= 2 * data_count;
- }
-
- /* if this buffer is full and there are more buffers left */
- if (!current_SC->SCp.this_residual &&
- current_SC->SCp.buffers_residual)
- {
- /* advance to next buffer */
- current_SC->SCp.buffers_residual--;
- current_SC->SCp.buffer++;
- current_SC->SCp.ptr =
- current_SC->SCp.buffer->address;
- current_SC->SCp.this_residual =
- current_SC->SCp.buffer->length;
- }
- }
-
- /*
- * Fifo should be empty
- */
- if(fifodata>0)
- {
- printk("aha152x: more data than expected (%d bytes)\n",
- GETPORT(FIFOSTAT));
- SETBITS(DMACNTRL0, _8BIT );
- printk("aha152x: data ( ");
- while(fifodata--)
- printk("%2x ", GETPORT( DATAPORT ));
- printk(")\n");
- }
-
- #if defined(DEBUG_DATAI)
- if(aha152x_debug & debug_datai)
- if(!fifodata)
- printk("fifo empty, ");
- else
- printk("something left in fifo, ");
- #endif
- }
-
- #if defined(DEBUG_DATAI)
- if((aha152x_debug & debug_datai) && (current_SC->SCp.buffers_residual || current_SC->SCp.this_residual))
- printk("left buffers (buffers=%d, bytes=%d), ",
- current_SC->SCp.buffers_residual,
- current_SC->SCp.this_residual);
- #endif
- /* transfer can be considered ended, when SCSIEN reads back zero */
- CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
- while( TESTHI( SXFRCTL0, SCSIEN ) )
- ;
- CLRBITS(DMACNTRL0, ENDMA );
-
- #if defined(DEBUG_DATAI) || defined(DEBUG_INTR)
- if(aha152x_debug & (debug_datai|debug_intr))
- printk("got %d bytes, ", GETSTCNT());
- #endif
-
- current_SC->SCp.have_data_in++;
- }
- break;
-
- case P_DATAO: /* DATA OUT phase */
- {
- int data_count;
-
- #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
- if(aha152x_debug & (debug_datao|debug_intr|debug_phases))
- printk("DATA OUT, ");
- #endif
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("got data to send (bytes=%d, buffers=%d), ",
- current_SC->SCp.this_residual,
- current_SC->SCp.buffers_residual );
- #endif
-
- if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT) )
- {
- printk("%d(%d) left in FIFO, ", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT) );
- aha152x_panic("FIFO should be empty");
- }
-
- SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
- SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
-
- SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
- SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
-
- /* while current buffer is not empty or
- there are more buffers to transfer */
- while( TESTLO( SSTAT1, PHASEMIS ) &&
- (current_SC->SCp.this_residual ||
- current_SC->SCp.buffers_residual) )
- {
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
- current_SC->SCp.this_residual,
- current_SC->SCp.buffers_residual);
- #endif
- /* transfer rest of buffer, but max. 128 byte */
- data_count = current_SC->SCp.this_residual > 128 ?
- 128 : current_SC->SCp.this_residual ;
-
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("data_count=%d, ", data_count);
- #endif
-
- if(data_count&1)
- {
- /* put a single byte in byte mode */
- SETBITS(DMACNTRL0, _8BIT );
- SETPORT(DATAPORT, *current_SC->SCp.ptr++);
- current_SC->SCp.this_residual--;
- }
- if(data_count>1)
- {
- CLRBITS(DMACNTRL0, _8BIT );
- data_count >>= 1; /* Number of words */
- outsw( DATAPORT, current_SC->SCp.ptr, data_count );
- current_SC->SCp.ptr += 2 * data_count;
- current_SC->SCp.this_residual -= 2 * data_count;
- }
-
- /* wait for FIFO to get empty */
- while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
- ;
-
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("fifo (%d bytes), transfered (%d bytes), ",
- GETPORT(FIFOSTAT), GETSTCNT() );
- #endif
-
- /* if this buffer is empty and there are more buffers left */
- if ( TESTLO( SSTAT1, PHASEMIS ) &&
- !current_SC->SCp.this_residual &&
- current_SC->SCp.buffers_residual)
- {
- /* advance to next buffer */
- current_SC->SCp.buffers_residual--;
- current_SC->SCp.buffer++;
- current_SC->SCp.ptr =
- current_SC->SCp.buffer->address;
- current_SC->SCp.this_residual =
- current_SC->SCp.buffer->length;
- }
- }
-
- if ( current_SC->SCp.this_residual ||
- current_SC->SCp.buffers_residual )
- {
- /* target leaves DATA OUT for an other phase
- (perhaps disconnect) */
-
- /* data in fifos has to be resend */
- data_count = GETPORT(SSTAT2) & (SFULL|SFCNT);
-
- data_count += GETPORT(FIFOSTAT) ;
- current_SC->SCp.ptr -= data_count;
- current_SC->SCp.this_residual += data_count;
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), transfer incomplete, resetting fifo, ",
- current_SC->SCp.this_residual,
- current_SC->SCp.buffers_residual,
- data_count );
- #endif
- SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
- CLRBITS(SXFRCTL0, SCSIEN|DMAEN );
- CLRBITS(DMACNTRL0, ENDMA);
- }
- else
- {
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("waiting for SCSI fifo to get empty, ");
- #endif
- /* wait for SCSI fifo to get empty */
- while( TESTLO( SSTAT2, SEMPTY ) )
- ;
- #if defined(DEBUG_DATAO)
- if(aha152x_debug & debug_datao)
- printk("ok, left data (bytes=%d, buffers=%d) ",
- current_SC->SCp.this_residual,
- current_SC->SCp.buffers_residual);
- #endif
- CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-
- /* transfer can be considered ended, when SCSIEN reads back zero */
- while( TESTHI( SXFRCTL0, SCSIEN ) )
- ;
-
- CLRBITS(DMACNTRL0, ENDMA);
- }
-
- #if defined(DEBUG_DATAO) || defined(DEBUG_INTR)
- if(aha152x_debug & (debug_datao|debug_intr))
- printk("sent %d data bytes, ", GETSTCNT() );
- #endif
- }
- break;
-
- case P_BUSFREE: /* BUSFREE */
- #if defined(DEBUG_RACE)
- leave_driver("(BUSFREE) intr");
- #endif
- #if defined(DEBUG_PHASES)
- if(aha152x_debug & debug_phases)
- printk("unexpected BUS FREE, ");
- #endif
- current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
-
- aha152x_done( DID_ERROR << 16 ); /* Don't know any better */
- return;
- break;
-
- case P_PARITY: /* parity error in DATA phase */
- #if defined(DEBUG_RACE)
- leave_driver("(DID_PARITY) intr");
- #endif
- printk("PARITY error in DATA phase, ");
-
- current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
-
- SETBITS( DMACNTRL0, INTEN );
- aha152x_done( DID_PARITY << 16 );
- return;
- break;
-
- default:
- printk("aha152x: unexpected phase\n");
- break;
- }
-
- if(done)
- {
- #if defined(DEBUG_INTR)
- if(aha152x_debug & debug_intr)
- printk("command done.\n");
- #endif
- #if defined(DEBUG_RACE)
- leave_driver("(done) intr");
- #endif
-
- SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
- SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
- SETPORT(SCSISEQ, disconnected_SC ? ENRESELI : 0 );
-
- SETBITS( DMACNTRL0, INTEN );
-
- aha152x_done( (current_SC->SCp.Status & 0xff)
- | ( (current_SC->SCp.Message & 0xff) << 8)
- | ( DID_OK << 16) );
-
- #if defined(DEBUG_RACE)
- printk("done returned (DID_OK: Status=%x; Message=%x).\n",
- current_SC->SCp.Status, current_SC->SCp.Message);
- #endif
- return;
- }
-
- if(current_SC)
- current_SC->SCp.phase |= 1<<16 ;
-
- SETPORT( SIMODE0, 0 );
- SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
- #if defined(DEBUG_INTR)
- if(aha152x_debug & debug_intr)
- disp_enintr();
- #endif
- #if defined(DEBUG_RACE)
- leave_driver("(PHASEEND) intr");
- #endif
-
- SETBITS( DMACNTRL0, INTEN);
- return;
- }
-
- /*
- * Dump the current driver status and panic...
- */
- static void aha152x_panic(char *msg)
- {
- printk("\naha152x_panic: %s\n", msg);
- show_queues();
- panic("aha152x panic");
- }
-
- /*
- * Display registers of AIC-6260
- */
- static void disp_ports(void)
- {
- #ifdef DEBUG_AHA152X
- int s;
-
- #ifdef SKIP_PORTS
- if(aha152x_debug & debug_skipports)
- return;
- #endif
-
- printk("\n%s: ", current_SC ? "on bus" : "waiting");
-
- s=GETPORT(SCSISEQ);
- printk("SCSISEQ ( ");
- if( s & TEMODEO ) printk("TARGET MODE ");
- if( s & ENSELO ) printk("SELO ");
- if( s & ENSELI ) printk("SELI ");
- if( s & ENRESELI ) printk("RESELI ");
- if( s & ENAUTOATNO ) printk("AUTOATNO ");
- if( s & ENAUTOATNI ) printk("AUTOATNI ");
- if( s & ENAUTOATNP ) printk("AUTOATNP ");
- if( s & SCSIRSTO ) printk("SCSIRSTO ");
- printk(");");
-
- printk(" SCSISIG ( ");
- s=GETPORT(SCSISIG);
- switch(s & P_MASK)
- {
- case P_DATAO:
- printk("DATA OUT");
- break;
- case P_DATAI:
- printk("DATA IN");
- break;
- case P_CMD:
- printk("COMMAND");
- break;
- case P_STATUS:
- printk("STATUS");
- break;
- case P_MSGO:
- printk("MESSAGE OUT");
- break;
- case P_MSGI:
- printk("MESSAGE IN");
- break;
- default:
- printk("*illegal*");
- break;
- }
-
- printk(" ); ");
-
- printk("INTSTAT ( %s ); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
-
- printk("SSTAT ( ");
- s=GETPORT(SSTAT0);
- if( s & TARGET ) printk("TARGET ");
- if( s & SELDO ) printk("SELDO ");
- if( s & SELDI ) printk("SELDI ");
- if( s & SELINGO ) printk("SELINGO ");
- if( s & SWRAP ) printk("SWRAP ");
- if( s & SDONE ) printk("SDONE ");
- if( s & SPIORDY ) printk("SPIORDY ");
- if( s & DMADONE ) printk("DMADONE ");
-
- s=GETPORT(SSTAT1);
- if( s & SELTO ) printk("SELTO ");
- if( s & ATNTARG ) printk("ATNTARG ");
- if( s & SCSIRSTI ) printk("SCSIRSTI ");
- if( s & PHASEMIS ) printk("PHASEMIS ");
- if( s & BUSFREE ) printk("BUSFREE ");
- if( s & SCSIPERR ) printk("SCSIPERR ");
- if( s & PHASECHG ) printk("PHASECHG ");
- if( s & REQINIT ) printk("REQINIT ");
- printk("); ");
-
-
- printk("SSTAT ( ");
-
- s=GETPORT(SSTAT0) & GETPORT(SIMODE0);
-
- if( s & TARGET ) printk("TARGET ");
- if( s & SELDO ) printk("SELDO ");
- if( s & SELDI ) printk("SELDI ");
- if( s & SELINGO ) printk("SELINGO ");
- if( s & SWRAP ) printk("SWRAP ");
- if( s & SDONE ) printk("SDONE ");
- if( s & SPIORDY ) printk("SPIORDY ");
- if( s & DMADONE ) printk("DMADONE ");
-
- s=GETPORT(SSTAT1) & GETPORT(SIMODE1);
-
- if( s & SELTO ) printk("SELTO ");
- if( s & ATNTARG ) printk("ATNTARG ");
- if( s & SCSIRSTI ) printk("SCSIRSTI ");
- if( s & PHASEMIS ) printk("PHASEMIS ");
- if( s & BUSFREE ) printk("BUSFREE ");
- if( s & SCSIPERR ) printk("SCSIPERR ");
- if( s & PHASECHG ) printk("PHASECHG ");
- if( s & REQINIT ) printk("REQINIT ");
- printk("); ");
-
- printk("SXFRCTL0 ( ");
-
- s=GETPORT(SXFRCTL0);
- if( s & SCSIEN ) printk("SCSIEN ");
- if( s & DMAEN ) printk("DMAEN ");
- if( s & CH1 ) printk("CH1 ");
- if( s & CLRSTCNT ) printk("CLRSTCNT ");
- if( s & SPIOEN ) printk("SPIOEN ");
- if( s & CLRCH1 ) printk("CLRCH1 ");
- printk("); ");
-
- printk("SIGNAL ( ");
-
- s=GETPORT(SCSISIG);
- if( s & ATNI ) printk("ATNI ");
- if( s & SELI ) printk("SELI ");
- if( s & BSYI ) printk("BSYI ");
- if( s & REQI ) printk("REQI ");
- if( s & ACKI ) printk("ACKI ");
- printk("); ");
-
- printk("SELID ( %02x ), ", GETPORT(SELID) );
-
- printk("SSTAT2 ( ");
-
- s=GETPORT(SSTAT2);
- if( s & SOFFSET) printk("SOFFSET ");
- if( s & SEMPTY) printk("SEMPTY ");
- if( s & SFULL) printk("SFULL ");
- printk("); SFCNT ( %d ); ", s & (SFULL|SFCNT) );
-
- #if 0
- printk("SSTAT4 ( ");
- s=GETPORT(SSTAT4);
- if( s & SYNCERR) printk("SYNCERR ");
- if( s & FWERR) printk("FWERR ");
- if( s & FRERR) printk("FRERR ");
- printk("); ");
- #endif
-
- printk("FCNT ( %d ); ", GETPORT(FIFOSTAT) );
-
- printk("DMACNTRL0 ( ");
- s=GETPORT(DMACNTRL0);
- printk( "%s ", s & _8BIT ? "8BIT" : "16BIT" );
- printk( "%s ", s & DMA ? "DMA" : "PIO" );
- printk( "%s ", s & WRITE_READ ? "WRITE" : "READ" );
- if( s & ENDMA ) printk("ENDMA ");
- if( s & INTEN ) printk("INTEN ");
- if( s & RSTFIFO ) printk("RSTFIFO ");
- if( s & SWINT ) printk("SWINT ");
- printk("); ");
-
-
- #if 0
- printk("DMACNTRL1 ( ");
-
- s=GETPORT(DMACNTRL1);
- if( s & PWRDWN ) printk("PWRDN ");
- printk("); ");
-
-
- printk("STK ( %d ); ", s & 0xf);
-
- printk("DMASTAT (");
- s=GETPORT(DMASTAT);
- if( s & ATDONE ) printk("ATDONE ");
- if( s & WORDRDY ) printk("WORDRDY ");
- if( s & DFIFOFULL ) printk("DFIFOFULL ");
- if( s & DFIFOEMP ) printk("DFIFOEMP ");
- printk(")");
-
- #endif
-
- printk("\n");
- #endif
- }
-
- /*
- * display enabled interrupts
- */
- static void disp_enintr(void)
- {
- int s;
-
- printk("enabled interrupts ( ");
-
- s=GETPORT(SIMODE0);
- if( s & ENSELDO ) printk("ENSELDO ");
- if( s & ENSELDI ) printk("ENSELDI ");
- if( s & ENSELINGO ) printk("ENSELINGO ");
- if( s & ENSWRAP ) printk("ENSWRAP ");
- if( s & ENSDONE ) printk("ENSDONE ");
- if( s & ENSPIORDY ) printk("ENSPIORDY ");
- if( s & ENDMADONE ) printk("ENDMADONE ");
-
- s=GETPORT(SIMODE1);
- if( s & ENSELTIMO ) printk("ENSELTIMO ");
- if( s & ENATNTARG ) printk("ENATNTARG ");
- if( s & ENPHASEMIS ) printk("ENPHASEMIS ");
- if( s & ENBUSFREE ) printk("ENBUSFREE ");
- if( s & ENSCSIPERR ) printk("ENSCSIPERR ");
- if( s & ENPHASECHG ) printk("ENPHASECHG ");
- if( s & ENREQINIT ) printk("ENREQINIT ");
- printk(")\n");
- }
-
- #if defined(DEBUG_RACE)
-
- static const char *should_leave;
- static int in_driver=0;
-
- /*
- * Only one routine can be in the driver at once.
- */
- static void enter_driver(const char *func)
- {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- printk("aha152x: entering %s() (%x)\n", func, jiffies);
- if(in_driver)
- {
- printk("%s should leave first.\n", should_leave);
- panic("aha152x: already in driver\n");
- }
-
- in_driver++;
- should_leave=func;
- restore_flags(flags);
- }
-
- static void leave_driver(const char *func)
- {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- printk("\naha152x: leaving %s() (%x)\n", func, jiffies);
- if(!in_driver)
- {
- printk("aha152x: %s already left.\n", should_leave);
- panic("aha152x: %s already left driver.\n");
- }
-
- in_driver--;
- should_leave=func;
- restore_flags(flags);
- }
- #endif
-
- /*
- * Show the command data of a command
- */
- static void show_command(Scsi_Cmnd *ptr)
- {
- printk("0x%08x: target=%d; lun=%d; cmnd=( ",
- (unsigned int) ptr, ptr->target, ptr->lun);
-
- print_command(ptr->cmnd);
-
- printk("); residual=%d; buffers=%d; phase |",
- ptr->SCp.this_residual, ptr->SCp.buffers_residual);
-
- if( ptr->SCp.phase & not_issued ) printk("not issued|");
- if( ptr->SCp.phase & in_selection ) printk("in selection|");
- if( ptr->SCp.phase & disconnected ) printk("disconnected|");
- if( ptr->SCp.phase & aborted ) printk("aborted|");
- if( ptr->SCp.phase & sent_ident ) printk("send_ident|");
- if( ptr->SCp.phase & in_other )
- {
- printk("; in other(");
- switch( (ptr->SCp.phase >> 16) & P_MASK )
- {
- case P_DATAO:
- printk("DATA OUT");
- break;
- case P_DATAI:
- printk("DATA IN");
- break;
- case P_CMD:
- printk("COMMAND");
- break;
- case P_STATUS:
- printk("STATUS");
- break;
- case P_MSGO:
- printk("MESSAGE OUT");
- break;
- case P_MSGI:
- printk("MESSAGE IN");
- break;
- default:
- printk("*illegal*");
- break;
- }
- printk(")");
- if(ptr->SCp.phase & (1<<16))
- printk("; phaseend");
- }
- printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
- }
-
- /*
- * Dump the queued data
- */
- static void show_queues(void)
- {
- unsigned long flags;
- Scsi_Cmnd *ptr;
-
- save_flags(flags);
- cli();
- printk("QUEUE STATUS:\nissue_SC:\n");
- for(ptr=issue_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
- show_command(ptr);
-
- printk("current_SC:\n");
- if(current_SC)
- show_command(current_SC);
- else
- printk("none\n");
-
- printk("disconnected_SC:\n");
- for(ptr=disconnected_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
- show_command(ptr);
-
- disp_ports();
- disp_enintr();
- restore_flags(flags);
- }
-