patch-1.3.48 linux/drivers/scsi/aha152x.c

Next file: linux/drivers/scsi/aha152x.h
Previous file: linux/drivers/scsi/README.st
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
@@ -1,6 +1,6 @@
 /* aha152x.c -- Adaptec AHA-152x driver
- * Author: Juergen E. Fischer, fischer@server.et-inf.fho-emden.de
- * Copyright 1993, 1994 Juergen E. Fischer
+ * Author: Juergen E. Fischer, fischer@et-inf.fho-emden.de
+ * Copyright 1993, 1994, 1995 Juergen E. Fischer
  *
  *
  * This driver is based on
@@ -8,22 +8,28 @@
  * 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.9 1995/03/18 09:20:24 root Exp root $
  *
-
+ * $Id: aha152x.c,v 1.11 1995/12/06 21:18:35 fischer Exp $
+ *
  * $Log: aha152x.c,v $
+ * Revision 1.11  1995/12/06  21:18:35  fischer
+ * - some minor updates
+ *
+ * Revision 1.10  1995/07/22  19:18:45  fischer
+ * - support for 2 controllers
+ * - started synchronous data transfers (not working yet)
+ *
  * Revision 1.9  1995/03/18  09:20:24  root
  * - patches for PCMCIA and modules
  *
@@ -145,7 +151,7 @@
  * Revision 0.0  1993/08/14  19:54:25  root
  * empty function bodies; detect() works.
  *
-
+ *
  **************************************************************************
 
 
@@ -158,23 +164,28 @@
 
  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
+ AUTOCONF:
+   use configuration the controller reports (only 152x)
+
+ SKIP_BIOSTEST:
+   Don't test for BIOS signature (AHA-1510 or disabled BIOS)
+
+ SETUP0	{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS }:
+   override for the first controller
+   
+ SETUP1	{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS }:
+   override for the second controller
 
 
  LILO COMMAND LINE OPTIONS:
 
- aha152x=<PORTBASE>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>]]]]
+ aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>]]]]]
 
  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.
+ valid (known). Don't use values that aren't supported under normal operation.
+ If you think that you need other values: contact me.  For two controllers
+ use the aha152x statement twice.
 
 
  REFERENCES USED:
@@ -225,7 +236,7 @@
 #include <linux/proc_fs.h>
 
 #include "aha152x.h"
-#include<linux/stat.h>
+#include <linux/stat.h>
 
 struct proc_dir_entry proc_scsi_aha152x = {
     PROC_SCSI_AHA152X, 7, "aha152x",
@@ -241,26 +252,10 @@
 #endif
 #endif
 
-/* 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
+#if !defined(AUTOCONF) && !defined(SETUP0)
+#error define AUTOCONF or SETUP0
 #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 */
@@ -287,6 +282,7 @@
 #if 0
 #endif
 
+#define DEBUG_SELECTION
 #define DEBUG_PHASES
 #define DEBUG_RESET
 #define DEBUG_ABORT
@@ -297,66 +293,89 @@
 
 /* END OF DEFINES */
 
+extern long loops_per_sec;
+
 /* 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;
+/* possible irq range */
+#define IRQ_MIN 9
+#define IRQ_MAX 12
+#define IRQS    IRQ_MAX-IRQ_MIN+1
 
-#ifdef DEBUG_AHA152X
-unsigned int aha152x_debug  = DEBUG_DEFAULT;
-#endif
+enum {
+  not_issued   = 0x0001,
+  in_selection = 0x0002,
+  disconnected = 0x0004,
+  aborted      = 0x0008,
+  sent_ident   = 0x0010,
+  in_other     = 0x0020,
+  in_sync      = 0x0040,
+  sync_ok      = 0x0080,
+};
 
 /* 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;
-
+static int  setup_count=0;
+static struct aha152x_setup {
+  char *conf;
+  int io_port;
+  int irq;
+  int scsiid;
+  int reconnect;
+  int parity;
+  int synchronous;
 #ifdef DEBUG_AHA152X
-static int setup_debug     = 0;
+  int debug;
 #endif
+} setup[2];
 
-static char *setup_str = (char *)NULL;
+static struct Scsi_Host *aha152x_host[IRQS];
 
-enum {
-   not_issued   = 0x01,
-   in_selection = 0x02,
-   disconnected = 0x04,
-   aborted      = 0x08,
-   sent_ident   = 0x10,
-   in_other     = 0x20,
-};
+#define HOSTDATA(shpnt)   ((struct aha152x_hostdata *) &shpnt->hostdata)
+#define CURRENT_SC	  (HOSTDATA(shpnt)->current_SC)
+#define ISSUE_SC	  (HOSTDATA(shpnt)->issue_SC)
+#define DISCONNECTED_SC	  (HOSTDATA(shpnt)->disconnected_SC)
+#define SYNCRATE	  (HOSTDATA(shpnt)->syncrate[CURRENT_SC->target])
+#define MSG(i)            (HOSTDATA(shpnt)->message[i])
+#define MSGLEN            (HOSTDATA(shpnt)->message_len)
+#define ADDMSG(x)	  (MSG(MSGLEN++)=x)
+
+struct aha152x_hostdata {
+  Scsi_Cmnd     *issue_SC;
+  Scsi_Cmnd     *current_SC;
+  Scsi_Cmnd     *disconnected_SC;
+  int           aborting;
+  int           abortion_complete;
+  int           abort_result;
+  int           commands;
+  
+  int           reconnect;
+  int           parity;
+  int           synchronous;
  
-/*
- * 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;
+  unsigned char syncrate[8];
+  
+  unsigned char message[256];
+  int           message_len;
 
-static int aborting=0, abortion_complete=0, abort_result;
+#ifdef DEBUG_AHA152X
+  int           debug;
+#endif
+};
 
-void aha152x_intr( int irq, struct pt_regs * );
-void aha152x_done( int error );
-void aha152x_setup( char *str, int *ints );
+void aha152x_intr(int irq, struct pt_regs *);
+void aha152x_done(struct Scsi_Host *shpnt, int error);
+void aha152x_setup(char *str, int *ints);
+int aha152x_checksetup(struct aha152x_setup *setup);
 
-static void aha152x_reset_ports(void);
-static void aha152x_panic(const char *msg);
+static void aha152x_reset_ports(struct Scsi_Host *shpnt);
+static void aha152x_panic(struct Scsi_Host *shpnt, char *msg);
 
-static void disp_ports(void);
+static void disp_ports(struct Scsi_Host *shpnt);
 static void show_command(Scsi_Cmnd *ptr);
-static void show_queues(void);
-static void disp_enintr(void);
+static void show_queues(struct Scsi_Host *shpnt);
+static void disp_enintr(struct Scsi_Host *shpnt);
 
 #if defined(DEBUG_RACE)
 static void enter_driver(const char *);
@@ -369,10 +388,7 @@
   0x340,      /* default first */
   0x140
 };
-#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
-
-/* possible interrupt channels */
-static unsigned short irqs[] = { 9, 10, 11, 12, 0 };
+#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))
 
 #if !defined(SKIP_BIOSTEST)
 /* possible locations for the Adaptec BIOS */
@@ -385,10 +401,10 @@
   (void *) 0xd4000,
   (void *) 0xd8000,
   (void *) 0xe0000,
-  (void *) 0xf0000,
   (void *) 0xeb800,   /* VTech Platinum SMP */
+  (void *) 0xf0000,
 };
-#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( void * ))
+#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
@@ -408,14 +424,17 @@
   { "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 */
+  { "ScsiPro SP-360 BIOS",        0x2873, 19 },  /* ScsiPro-Controller  */
   { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },  /* Gigabyte Local-Bus-SCSI */
+  { "Adaptec BIOS:AVA-282X",         0xc, 21 },  /* Adaptec 282x */
+  { "Adaptec IBM Dock II SCSI",   0x2edd, 24 },  /* IBM Thinkpad Dock II */
+  { "Adaptec BIOS:AHA-1532P",       0x1c, 22 },  /* IBM Thinkpad Dock II SCSI */
 };
-#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
 #endif
 
 
-static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
+static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */
 {
    unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
 
@@ -426,7 +445,7 @@
 /*
  *  queue services:
  */
-static inline void append_SC( Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
 {
   Scsi_Cmnd *end;
 
@@ -435,15 +454,13 @@
     *SC=new_SC;
   else
     {
-      for( end=*SC;
-	   end->host_scribble;
-	   end = (Scsi_Cmnd *) end->host_scribble )
+      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 )
+static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
 {
   Scsi_Cmnd *ptr;
 
@@ -453,13 +470,13 @@
   return ptr;
 }
 
-static inline Scsi_Cmnd *remove_SC( Scsi_Cmnd **SC, int target, int lun )
+static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
 {
   Scsi_Cmnd *ptr, *prev;
 
-  for( ptr=*SC, prev=NULL;
+  for(ptr=*SC, prev=NULL;
        ptr && ((ptr->target!=target) || (ptr->lun!=lun));
-       prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble )
+      prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
     ;
 
   if(ptr)
@@ -473,13 +490,13 @@
 /*
  * read inbound byte and wait for ACK to get low
  */
-static void make_acklow(void)
+static void make_acklow(struct Scsi_Host *shpnt)
 {
-  SETPORT( SXFRCTL0, CH1|SPIOEN );
+  SETPORT(SXFRCTL0, CH1|SPIOEN);
   GETPORT(SCSIDAT);
-  SETPORT( SXFRCTL0, CH1 );
+  SETPORT(SXFRCTL0, CH1);
 
-  while( TESTHI( SCSISIG, ACKI ) )
+  while(TESTHI(SCSISIG, ACKI))
     ;
 }
 
@@ -493,37 +510,36 @@
  *   P_BUSFREE   BUS FREE phase detected
  *   P_PARITY    parity error in DATA phase
  */
-static int getphase(void)
+static int getphase(struct Scsi_Host *shpnt)
 {
   int phase, sstat1;
   
-  while( 1 )
+  while(1)
     {
       do
 	{
-	  while( !( ( sstat1 = GETPORT( SSTAT1 ) ) & (BUSFREE|SCSIRSTI|REQINIT ) ) )
+          while(!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE|SCSIRSTI|REQINIT)))
 	    ;
-	  if( sstat1 & BUSFREE )
+          if(sstat1 & BUSFREE)
 	    return P_BUSFREE;
-	  if( sstat1 & SCSIRSTI )
+          if(sstat1 & SCSIRSTI)
 	    {
-	      /* IBM drive responds with RSTI to RSTO */
 	      printk("aha152x: RESET IN\n");
-	      SETPORT( SSTAT1, SCSIRSTI );
+              SETPORT(SSTAT1, SCSIRSTI);
 	    }
 	}
-      while( TESTHI( SCSISIG, ACKI ) || TESTLO( SSTAT1, REQINIT ) );
+      while(TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT));
 
-      SETPORT( SSTAT1, CLRSCSIPERR );
+      SETPORT(SSTAT1, CLRSCSIPERR);
   
-      phase = GETPORT( SCSISIG ) & P_MASK ;
+      phase = GETPORT(SCSISIG) & P_MASK ;
 
-      if( TESTHI( SSTAT1, SCSIPERR ) )
+      if(TESTHI(SSTAT1, SCSIPERR))
 	{
-	  if( (phase & (CDO|MSGO))==0 )                         /* DATA phase */
+          if((phase & (CDO|MSGO))==0)                        /* DATA phase */
 	    return P_PARITY;
 
-	  make_acklow();
+          make_acklow(shpnt);
 	}
       else
 	return phase;
@@ -531,148 +547,170 @@
 }
 
 /* called from init/main.c */
-void aha152x_setup( char *str, int *ints)
+void aha152x_setup(char *str, int *ints)
 {
-  if(setup_called)
-    panic("aha152x: aha152x_setup called twice.\n");
-
-  setup_called=ints[0];
-  setup_str=str;
+  if(setup_count>2)
+    panic("aha152x: you can only configure up to two controllers\n");
 
-  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;
+  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] : 0 /* FIXME: 1 */;
 #ifdef DEBUG_AHA152X
-  setup_debug     = ints[0] >= 6 ? ints[6] : DEBUG_DEFAULT;
+  setup[setup_count].debug       = ints[0] >= 7 ? ints[7] : DEBUG_DEFAULT;
+  if(ints[0]>7)
+    { 
+      printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>"
+ 	         "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>,[,<DEBUG>]]]]]]\n");
+#else
+  if(ints[0]>6)
+    {
+      printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>"
+             "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>]]]]]\n");
 #endif
+    }
+  else 
+    setup_count++;
 }
 
 /*
    Test, if port_base is valid.
  */
-static int aha152x_porttest(int port_base)
+static int aha152x_porttest(int io_port)
 {
   int i;
 
-  if(check_region(port_base, 0x20))
+  if(check_region(io_port, IO_RANGE))
     return 0;
 
-  SETPORT( DMACNTRL1, 0 );          /* reset stack pointer */
+  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
   for(i=0; i<16; i++)
-    SETPORT( STACK, i );
+    SETPORT(io_port+O_STACK, i);
 
-  SETPORT( DMACNTRL1, 0 );          /* reset stack pointer */
-  for(i=0; i<16 && GETPORT(STACK)==i; 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);
 }
 
+int aha152x_checksetup(struct aha152x_setup *setup)
+{
+  int i;
+  
+#ifndef PCMCIA
+  for(i=0; i<PORT_COUNT && (setup->io_port != ports[i]); i++)
+    ;
+  
+  if(i==PORT_COUNT)
+    return 0;
+#endif
+  
+  if(!aha152x_porttest(setup->io_port))
+    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;
+  
+  return 1;
+}
+
+
 int aha152x_detect(Scsi_Host_Template * tpnt)
 {
-  int                 i, ok;
+  int                 i, j, ok;
 #if defined(AUTOCONF)
   aha152x_config      conf;
 #endif
-  int                 interrupt_level;
-  struct Scsi_Host    *hreg;
   
   tpnt->proc_dir = &proc_scsi_aha152x;
 
-  if(setup_called)
+  for(i=0; i<IRQS; i++)
+    aha152x_host[i] = (struct Scsi_Host *) NULL;
+  
+  if(setup_count)
     {
       printk("aha152x: processing commandline: ");
    
-#ifdef DEBUG_AHA152X
-      if(setup_called>6)
-#else
-      if(setup_called>5)
-#endif
+      for(i=0; i<setup_count; i++)
+        if(!aha152x_checksetup(&setup[i]))
 	{
-	  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__);
+                printk("\naha152x: %s\n", setup[i].conf);
+                printk("aha152x: invalid line (controller=%d)\n", i+1);
 	}
 
-      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
-
-#ifndef PCMCIA
-      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__);
+      printk("ok\n");
 	}
-#endif
 
-      if(!aha152x_porttest(port_base))
+#ifdef SETUP0
+  if(setup_count<2)
 	{
-	  printk("portbase 0x%03x fails probe\n", port_base);
-#ifdef PCMCIA
-	  return 0;
-#else
-	  panic("aha152x panics in line %d", __LINE__);
-#endif
-	}
+      struct aha152x_setup override = SETUP0;
 
-#ifndef PCMCIA
-      i=0;
-      while(irqs[i] && (interrupt_level!=irqs[i]))
-	i++;
-      if(!irqs[i])
+      if(setup_count==0 || (override.io_port != setup[0].io_port))
+        if(!aha152x_checksetup(&override))
 	{
-	  printk("illegal IRQ %d\n", interrupt_level);
-	  panic("aha152x panics in line %d", __LINE__);
+                printk("\naha152x: SETUP0 (0x%x, %d, %d, %d, %d, %d) invalid\n",
+        	      override.io_port,
+        	      override.irq,
+        	      override.scsiid,
+        	      override.reconnect,
+        	      override.parity,
+        	      override.synchronous);
 	}
-#endif
-      
-      if( (this_host < 0) || (this_host > 7) )
-	{
-	  printk("illegal SCSI ID %d\n", this_host);
-	  panic("aha152x panics in line %d", __LINE__);
+        else
+          setup[setup_count++] = override;
 	}
+#endif
 
-      if( (can_disconnect < 0) || (can_disconnect > 1) )
+#ifdef SETUP1
+  if(setup_count<2)
 	{
-	  printk("reconnect %d should be 0 or 1\n", can_disconnect);
-	  panic("aha152x panics in line %d", __LINE__);
-	}
+      struct aha152x_setup override = SETUP1;
 
-      if( (can_doparity < 0) || (can_doparity > 1) )
+      if(setup_count==0 || (override.io_port != setup[0].io_port))
+        if(!aha152x_checksetup(&override))
 	{
-	  printk("parity %d should be 0 or 1\n", can_doparity);
-	  panic("aha152x panics in line %d", __LINE__);
-	}
-      printk("ok\n");
+                printk("\naha152x: SETUP1 (0x%x, %d, %d, %d, %d, %d) invalid\n",
+        	       override.io_port,
+        	       override.irq,
+        	       override.scsiid,
+        	       override.reconnect,
+        	       override.parity,
+        	       override.synchronous);
     }
   else
+          setup[setup_count++] = override;
+    }
+#endif
+  
+#if defined(AUTOCONF)
+  if(setup_count<2)
     {
 #if !defined(SKIP_BIOSTEST)
-      int j;
-
       ok=0;
-      for( i=0; i < ADDRESS_COUNT && !ok; i++)
-	for( j=0; (j < SIGNATURE_COUNT) && !ok; j++)
+      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)
+      if(!ok && setup_count==0)
 	return 0;
 
       printk("aha152x: BIOS test: passed, ");
@@ -680,137 +718,149 @@
       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;
+      for(i=0; i<PORT_COUNT && setup_count<2; i++)
+            {
+              if((setup_count==1) && (setup[0].io_port == ports[i]))
+                continue;
+
+              if(aha152x_porttest(ports[i]))
+	{
+                  setup[setup_count].io_port = ports[i];
+              
+                  conf.cf_port =
+        	        (GETPORT(ports[i]+O_PORTA)<<8) + GETPORT(ports[i]+O_PORTB);
+              
+                  setup[setup_count].irq         = IRQ_MIN + conf.cf_irq;
+                  setup[setup_count].scsiid      = conf.cf_id;
+                  setup[setup_count].reconnect   = conf.cf_tardisc;
+                  setup[setup_count].parity      = !conf.cf_parity;
+                  setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */;
+                  setup[setup_count].debug       = DEBUG_DEFAULT;
+                  setup_count++;
+                }
 	}
-      else
-	port_base=ports[i];
-      printk("ok, ");
-#else
-      port_base=PORTBASE;
-#endif /* !PORTBASE */
 
-#if defined(AUTOCONF)
+      printk("auto configuration: ok, ");
+    }
+#endif
 
-      conf.cf_port = (GETPORT(PORTA)<<8) + GETPORT(PORTB);
+  printk("detection complete\n");
 
-      interrupt_level = irqs[conf.cf_irq];
-      this_host       = conf.cf_id;
-      can_disconnect  = conf.cf_tardisc;
-      can_doparity    = !conf.cf_parity;
+  for(i=0; i<setup_count; i++)
+    {
+      struct Scsi_Host        *shpnt;
 
-      printk("auto configuration: ok, ");
+      shpnt = aha152x_host[setup[i].irq-IRQ_MIN] =
+        scsi_register(tpnt, sizeof(struct aha152x_hostdata));
 
-#endif /* AUTOCONF */
+      shpnt->io_port                     = setup[i].io_port;
+      shpnt->n_io_port                   = IO_RANGE;
+      shpnt->irq                         = setup[i].irq;
 
-#if defined(IRQ)
-      interrupt_level = IRQ; 
-#endif
+      ISSUE_SC                           = (Scsi_Cmnd *) NULL;
+      CURRENT_SC                         = (Scsi_Cmnd *) NULL;
+      DISCONNECTED_SC                    = (Scsi_Cmnd *) NULL;
 
-#if defined(SCSI_ID)
-      this_host = SCSI_ID;
-#endif
+      HOSTDATA(shpnt)->reconnect         = setup[i].reconnect;
+      HOSTDATA(shpnt)->parity            = setup[i].parity;
+      HOSTDATA(shpnt)->synchronous       = setup[i].synchronous;
+      HOSTDATA(shpnt)->debug             = setup[i].debug;
 
-#if defined(RECONNECT)
-      can_disconnect=RECONNECT;
-#endif
+      HOSTDATA(shpnt)->aborting          = 0;
+      HOSTDATA(shpnt)->abortion_complete = 0;
+      HOSTDATA(shpnt)->abort_result      = 0;
+      HOSTDATA(shpnt)->commands          = 0;
 
-#if defined(PARITY)
-      can_doparity=PARITY;
-#endif
-    }
+      HOSTDATA(shpnt)->message_len       = 0;
 
-  printk("detection complete\n");
+      for(j=0; j<8; j++)
+        HOSTDATA(shpnt)->syncrate[j] = 0;
  
-  ok = request_irq(interrupt_level, aha152x_intr, SA_INTERRUPT, "aha152x");
+      ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x");
   
   if(ok<0)
     {
       if(ok == -EINVAL)
 	{
-	   printk("aha152x: bad IRQ %d.\n", interrupt_level);
+              printk("aha152x%d: bad IRQ %d.\n", i, setup[i].irq);
 	   printk("         Contact author.\n");
 	}
       else
-	if( ok == -EBUSY)
-	  printk( "aha152x: IRQ %d already in use. Configure another.\n",
-		  interrupt_level);
+            if(ok == -EBUSY)
+              printk("aha152x%d: IRQ %d already in use. Configure another.\n",
+        	     i, setup[i].irq);
 	else
 	  {
-	    printk( "\naha152x: Unexpected error code on requesting IRQ %d.\n",
-		    interrupt_level);
+                printk("\naha152x%d: Unexpected error code on"
+        	       " requesting IRQ %d.\n", i, setup[i].irq);
 	    printk("         Contact author.\n");
 	  }
-      panic("aha152x: driver needs an IRQ.\n");
+          printk("aha152x: driver needs an IRQ.\n");
+          continue;
     }
 
-  SETPORT( SCSIID, this_host << 4 );
-  tpnt->this_id=this_host;
+      SETPORT(SCSIID, setup[i].scsiid << 4);
+      shpnt->this_id=setup[i].scsiid;
   
-  if(can_disconnect)
-    tpnt->can_queue=AHA152X_MAXQUEUE;
+      if(setup[i].reconnect)
+        shpnt->hostt->can_queue=AHA152X_MAXQUEUE;
 
   /* RESET OUT */
-  SETBITS(SCSISEQ, SCSIRSTO );
+      SETBITS(SCSISEQ, SCSIRSTO);
   do_pause(30);
-  CLRBITS(SCSISEQ, SCSIRSTO );
+      CLRBITS(SCSISEQ, SCSIRSTO);
   do_pause(60);
 
-  aha152x_reset(NULL);
+      aha152x_reset_ports(shpnt);
+      
+      printk("aha152x%d: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d,"
+             " reconnect=%s, parity=%s, synchronous=%s\n",
+      	     i,
+             shpnt->io_port,
+             shpnt->irq,
+             shpnt->this_id,
+             HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled",
+             HOSTDATA(shpnt)->parity ? "enabled" : "disabled",
+             HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
 
-  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, 0x20, "aha152x");        /* Register */
-
-  hreg = scsi_register(tpnt, 0);
-  hreg->io_port = port_base;
-  hreg->n_io_port = 0x20;
-  hreg->irq = interrupt_level;
+      request_region(shpnt->io_port, IO_RANGE, "aha152x");  /* Register */
   
   /* not expecting any interrupts */
   SETPORT(SIMODE0, 0);
   SETPORT(SIMODE1, 0);
 
-  SETBITS( DMACNTRL0, INTEN);
-  return 1;
+      SETBITS(DMACNTRL0, INTEN);
+    }
+  
+  return (setup_count>0);
 }
 
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
-int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
 
 #if defined(DEBUG_RACE)
   enter_driver("queue");
 #else
 #if defined(DEBUG_QUEUE)
-  if(aha152x_debug & debug_queue)
+  if(HOSTDATA(shpnt)->debug & debug_queue)
     printk("aha152x: queue(), ");
 #endif
 #endif
 
 #if defined(DEBUG_QUEUE)
-  if(aha152x_debug & debug_queue)
+  if(HOSTDATA(shpnt)->debug & debug_queue)
   {
-    printk( "SCpnt (target = %d lun = %d cmnd = ", SCpnt->target, SCpnt->lun);
+      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();
+      printk(", cmd_len=%d, pieces = %d size = %u), ",
+             SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
+      disp_ports(shpnt);
   }
 #endif
 
@@ -825,7 +875,8 @@
   SCpnt->SCp.phase = not_issued;
   if (SCpnt->use_sg)
     {
-      SCpnt->SCp.buffer           = (struct scatterlist *)SCpnt->request_buffer;
+      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;
@@ -846,21 +897,21 @@
   /* Turn led on, when this is the first command. */
   save_flags(flags);
   cli();
-  commands++;
-  if(commands==1)
-    SETPORT( PORTA, 1 );
+  HOSTDATA(shpnt)->commands++;
+  if(HOSTDATA(shpnt)->commands==1)
+    SETPORT(PORTA, 1);
 
 #if defined(DEBUG_QUEUES)
-  if(aha152x_debug & debug_queues)
-    printk("i+ (%d), ", commands );
+  if(HOSTDATA(shpnt)->debug & debug_queues)
+    printk("i+ (%d), ", HOSTDATA(shpnt)->commands);
 #endif
-  append_SC( &issue_SC, SCpnt);
+  append_SC(&ISSUE_SC, SCpnt);
   
   /* Enable bus free interrupt, when we aren't currently on the bus */
-  if(!current_SC)
+  if(!CURRENT_SC)
     {
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
     }
   restore_flags(flags);
 
@@ -872,11 +923,11 @@
 }
 
 /*
- *  We only support command in interrupt-driven fashion
+ *  We only support commands in interrupt-driven fashion
  */
-int aha152x_command( Scsi_Cmnd *SCpnt )
+int aha152x_command(Scsi_Cmnd *SCpnt)
 {
-  printk( "aha152x: interrupt driven driver; use aha152x_queue()\n" );
+  printk("aha152x: interrupt driven driver; use aha152x_queue()\n");
   return -1;
 }
 
@@ -884,8 +935,9 @@
  *  Abort a queued command
  *  (commands that are on the bus can't be aborted easily)
  */
-int aha152x_abort( Scsi_Cmnd *SCpnt)
+int aha152x_abort(Scsi_Cmnd *SCpnt)
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
   Scsi_Cmnd *ptr, *prev;
 
@@ -893,16 +945,15 @@
   cli();
 
 #if defined(DEBUG_ABORT)
-  if(aha152x_debug & debug_abort)
+  if(HOSTDATA(shpnt)->debug & debug_abort)
   { 
-    printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt );
-
-    show_queues();
+      printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt);
+      show_queues(shpnt);
   }
 #endif
 
   /* look for command in issue queue */
-  for( ptr=issue_SC, prev=NULL;
+  for(ptr=ISSUE_SC, prev=NULL;
        ptr && ptr!=SCpnt;
        prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
     ;
@@ -913,7 +964,7 @@
       if(prev)
 	prev->host_scribble = ptr->host_scribble;
       else
-	issue_SC = (Scsi_Cmnd *) ptr->host_scribble;
+        ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble;
       restore_flags(flags);
 
       ptr->host_scribble = NULL;
@@ -924,11 +975,11 @@
 
   /* 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))
+  if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt))
     {
       /* fail abortion, if bus is busy */
 
-      if(!current_SC)
+      if(!CURRENT_SC)
 	printk("bus busy w/o current command, ");
  
       restore_flags(flags);
@@ -937,56 +988,58 @@
 
   /* bus is free */
 
-  if(current_SC)
+  if(CURRENT_SC)
   { 
     /* target entered bus free before COMMAND COMPLETE, nothing to abort */
     restore_flags(flags);
-    current_SC->result = DID_ERROR << 16;
-    current_SC->scsi_done(current_SC);
-    current_SC = (Scsi_Cmnd *) NULL;
+      CURRENT_SC->result = DID_ERROR << 16;
+      CURRENT_SC->scsi_done(CURRENT_SC);
+      CURRENT_SC = (Scsi_Cmnd *) NULL;
     return SCSI_ABORT_SUCCESS;
   }
 
   /* look for command in disconnected queue */
-  for( ptr=disconnected_SC, prev=NULL;
+  for(ptr=DISCONNECTED_SC, prev=NULL;
        ptr && ptr!=SCpnt;
        prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
     ;
 
   if(ptr)
-    if(!aborting)
+    if(!HOSTDATA(shpnt)->aborting)
       {
 	/* dequeue */
 	if(prev)
 	  prev->host_scribble = ptr->host_scribble;
 	else
-	  disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
+          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;
+        CURRENT_SC     = ptr;
 	ptr->SCp.phase = in_selection|aborted;
-	SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
+        SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
+        
+        ADDMSG(ABORT);
   
 	/* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-	SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
-	SETPORT( SIMODE1, ENSELTIMO );
+        SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+        SETPORT(SIMODE1, ENSELTIMO);
   
 	/* Enable SELECTION OUT sequence */
-	SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
+        SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
   
-	SETBITS( DMACNTRL0, INTEN );
-	abort_result=SCSI_ABORT_SUCCESS;
-	aborting++;
-	abortion_complete=0;
+        SETBITS(DMACNTRL0, INTEN);
+        HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
+        HOSTDATA(shpnt)->aborting++;
+        HOSTDATA(shpnt)->abortion_complete=0;
 
 	sti();  /* Hi Eric, guess what ;-) */
   
 	/* sleep until the abortion is complete */
-	while(!abortion_complete)
+        while(!HOSTDATA(shpnt)->abortion_complete)
 	  barrier();
-	aborting=0;
-	return abort_result;
+        HOSTDATA(shpnt)->aborting=0;
+        return HOSTDATA(shpnt)->abort_result;
       }
     else
       {
@@ -1004,7 +1057,7 @@
 /*
  *  Restore default values to the AIC-6260 registers and reset the fifos
  */
-static void aha152x_reset_ports(void)
+static void aha152x_reset_ports(struct Scsi_Host *shpnt)
 {
   /* disable interrupts */
   SETPORT(DMACNTRL0, RSTFIFO);
@@ -1012,7 +1065,7 @@
   SETPORT(SCSISEQ, 0);
 
   SETPORT(SXFRCTL1, 0);
-  SETPORT( SCSISIG, 0);
+  SETPORT(SCSISIG, 0);
   SETPORT(SCSIRATE, 0);
 
   /* clear all interrupt conditions */
@@ -1031,45 +1084,47 @@
   SETPORT(SXFRCTL0, CH1);
 
   /* enable interrupts */
-  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+  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)
+int aha152x_reset(Scsi_Cmnd *SCpnt)
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
   Scsi_Cmnd *ptr, *prev, *next;
 
-  aha152x_reset_ports();
+  aha152x_reset_ports(shpnt);
 
   /* Reset, if bus hangs */
-  if( TESTLO( SSTAT1, BUSFREE ) )
+  if(TESTLO(SSTAT1, BUSFREE))
     {
-       CLRBITS( DMACNTRL0, INTEN );
+       CLRBITS(DMACNTRL0, INTEN);
 
 #if defined(DEBUG_RESET)
-  if(aha152x_debug & debug_reset)
+       if(HOSTDATA(shpnt)->debug & debug_reset)
   {
        printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");
-       show_queues();
+           show_queues(shpnt);
   }
 #endif
 
-       if(current_SC && !current_SC->device->soft_reset)
+       ptr=CURRENT_SC;
+       if(ptr && !ptr->device->soft_reset)
 	 {
-	   current_SC->host_scribble = NULL;
-	   current_SC->result = DID_RESET << 16;
-	   current_SC->scsi_done(current_SC);
-	   current_SC=NULL;
+           ptr->host_scribble = NULL;
+           ptr->result = DID_RESET << 16;
+           ptr->scsi_done(CURRENT_SC);
+           CURRENT_SC=NULL;
 	 }
 
        save_flags(flags);
        cli();
-       prev=NULL; ptr=disconnected_SC;
+       prev=NULL; ptr=DISCONNECTED_SC;
        while(ptr)
 	 {
 	   if(!ptr->device->soft_reset)
@@ -1077,13 +1132,13 @@
 	       if(prev)
 		 prev->host_scribble = ptr->host_scribble;
 	       else
-		 disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
+        	 DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
 
 	       next = (Scsi_Cmnd *) ptr->host_scribble;
   
 	       ptr->host_scribble = NULL;
 	       ptr->result        = DID_RESET << 16;
-	       ptr->scsi_done(ptr);
+               ptr->scsi_done(ptr);
   
 	       ptr = next; 
 	     }
@@ -1095,11 +1150,11 @@
 	 }
        restore_flags(flags);
 
-#if defined( DEBUG_RESET )
-       if(aha152x_debug & debug_reset)
+#if defined(DEBUG_RESET)
+       if(HOSTDATA(shpnt)->debug & debug_reset)
        {
 	 printk("commands on targets w/ soft-resets:\n");
-	 show_queues();
+           show_queues(shpnt);
        }
 #endif
 
@@ -1109,10 +1164,10 @@
        SETPORT(SCSISEQ, 0);
        do_pause(60);
 
-       SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-       SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+       SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+       SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-       SETPORT( DMACNTRL0, INTEN );
+       SETPORT(DMACNTRL0, INTEN);
     }
 
   return SCSI_RESET_SUCCESS;
@@ -1121,14 +1176,13 @@
 /*
  * Return the "logical geometry"
  */
-int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array )
+int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
 {
   int size = disk->capacity;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(aha152x_debug & debug_biosparam)
-    printk("aha152x_biosparam: dev=%s, size=%d, ",
-	   kdevname(dev), size);
+  if(HOSTDATA(shpnt)->debug & debug_biosparam)
+    printk("aha152x_biosparam: dev=%s, size=%d, ", kdevname(dev), size);
 #endif
   
 /* I took this from other SCSI drivers, since it provides
@@ -1138,7 +1192,7 @@
   info_array[2]=size>>11;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(aha152x_debug & debug_biosparam)
+  if(HOSTDATA(shpnt)->debug & debug_biosparam)
   {
     printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
 	   info_array[0], info_array[1], info_array[2]);
@@ -1152,54 +1206,54 @@
 /*
  *  Internal done function
  */
-void aha152x_done( int error )
+void aha152x_done(struct Scsi_Host *shpnt, int error)
 {
   unsigned long flags;
   Scsi_Cmnd *done_SC;
 
 #if defined(DEBUG_DONE)
-  if(aha152x_debug & debug_done)
+  if(HOSTDATA(shpnt)->debug & debug_done)
   {
     printk("\naha152x: done(), ");
-    disp_ports();
+    disp_ports(shpnt);
   }
 #endif
 
-  if (current_SC)
+  if (CURRENT_SC)
     {
 #if defined(DEBUG_DONE)
-      if(aha152x_debug & debug_done)
+      if(HOSTDATA(shpnt)->debug & debug_done)
 	printk("done(%x), ", error);
 #endif
 
       save_flags(flags);
       cli();
 
-      done_SC = current_SC;
-      current_SC = NULL;
+      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 */
+      HOSTDATA(shpnt)->commands--;
+      if(!HOSTDATA(shpnt)->commands)
+        SETPORT(PORTA, 0);                                  /* turn led off */
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues) 
-	printk("ok (%d), ", commands);
+      if(HOSTDATA(shpnt)->debug & debug_queues) 
+        printk("ok (%d), ", HOSTDATA(shpnt)->commands);
 #endif
       restore_flags(flags);
 
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
 	printk("BUS FREE loop, ");
 #endif
-      while( TESTLO( SSTAT1, BUSFREE ) )
+      while(TESTLO(SSTAT1, BUSFREE))
 	;
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
 	printk("BUS FREE\n");
 #endif
 
@@ -1207,27 +1261,28 @@
       if(done_SC->scsi_done)
 	{
 #if defined(DEBUG_DONE)
-	  if(aha152x_debug & debug_done)
+          if(HOSTDATA(shpnt)->debug & debug_done)
 	    printk("calling scsi_done, ");
 #endif
-	  done_SC->scsi_done( done_SC );
+          done_SC->scsi_done(done_SC);
 #if defined(DEBUG_DONE)
-	  if(aha152x_debug & debug_done)
+          if(HOSTDATA(shpnt)->debug & debug_done)
 	    printk("done returned, ");
 #endif
 	}
       else
-	panic( "aha152x: current_SC->scsi_done() == NULL" );
+        panic("aha152x: current_SC->scsi_done() == NULL");
     }
   else
-    aha152x_panic( "done() called outside of command" );
+    aha152x_panic(shpnt, "done() called outside of command");
 }
 
 /*
  * Interrupts handler (main routine of the driver)
  */
-void aha152x_intr( int irqno, struct pt_regs * regs )
+void aha152x_intr(int irqno, struct pt_regs * regs)
 {
+  struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
   unsigned int flags;
   int done=0, phase;
 
@@ -1235,7 +1290,7 @@
   enter_driver("intr");
 #else
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
+  if(HOSTDATA(shpnt)->debug & debug_intr)
     printk("\naha152x: intr(), ");
 #endif
 #endif
@@ -1244,74 +1299,76 @@
      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);
+  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 ) )
+  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(CURRENT_SC)
 	{
 #if defined(DEBUG_QUEUES)
-	  if(aha152x_debug & debug_queues)
+          if(HOSTDATA(shpnt)->debug & debug_queues)
 	  printk("i+, ");
 #endif
 	  save_flags(flags);
 	  cli();
-	  append_SC( &issue_SC, current_SC);
-	  current_SC=NULL;
+          append_SC(&ISSUE_SC, CURRENT_SC);
+          CURRENT_SC=NULL;
 	  restore_flags(flags);
 	}
 
       /* disable sequences */
-      SETPORT( SCSISEQ, 0 );
-      SETPORT( SSTAT0, CLRSELDI );
-      SETPORT( SSTAT1, CLRBUSFREE );
+      SETPORT(SCSISEQ, 0);
+      SETPORT(SSTAT0, CLRSELDI);
+      SETPORT(SSTAT1, CLRBUSFREE);
 
 #if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_queues|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases))
 	printk("reselected, ");
 #endif
 
-      i = GETPORT(SELID) & ~(1 << this_host);
+      i = GETPORT(SELID) & ~(1 << shpnt->this_id);
       target=0;
       if(i)
-	for( ; (i & 1)==0; target++, i>>=1)
+        for(; (i & 1)==0; target++, i>>=1)
 	  ;
       else
-	aha152x_panic("reconnecting target unknown");
+        aha152x_panic(shpnt, "reconnecting target unknown");
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
-	printk("SELID=%02x, target=%d, ", GETPORT(SELID), target );
+      if(HOSTDATA(shpnt)->debug & debug_queues)
+        printk("SELID=%02x, target=%d, ", GETPORT(SELID), target);
 #endif
-      SETPORT( SCSIID, (this_host << OID_) | target );
-      SETPORT( SCSISEQ, ENRESELI );
+      SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
+      SETPORT(SCSISEQ, ENRESELI);
+
+      if(TESTLO(SSTAT0, SELDI))
+        aha152x_panic(shpnt, "RESELI failed");
 
-      if(TESTLO( SSTAT0, SELDI ))
-	aha152x_panic("RESELI failed");
+      SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f);
 
-      SETPORT( SCSISIG, P_MSGI );
+      SETPORT(SCSISIG, P_MSGI);
 
       /* Get identify message */
-      if((i=getphase())!=P_MSGI)
+      if((i=getphase(shpnt))!=P_MSGI)
 	{
 	  printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
-	  aha152x_panic("unknown lun");
+          aha152x_panic(shpnt, "unknown lun");
 	}
-      SETPORT( SCSISEQ, 0 );
+      SETPORT(SCSISEQ, 0);
 
-      SETPORT( SXFRCTL0, CH1);
+      SETPORT(SXFRCTL0, CH1);
 
       identify_msg = GETPORT(SCSIBUS);
 
@@ -1319,87 +1376,87 @@
 	{
 	  printk("target=%d, inbound message (%02x) != IDENTIFY\n",
 		 target, identify_msg);
-	  aha152x_panic("unknown lun");
+          aha152x_panic(shpnt, "unknown lun");
 	}
 
-      make_acklow();
-      getphase();
+      make_acklow(shpnt);
+      getphase(shpnt);
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
-	printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f );
+      if(HOSTDATA(shpnt)->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)
+      if(HOSTDATA(shpnt)->debug & debug_queues)
 	printk("d-, ");
 #endif
-      current_SC = remove_SC( &disconnected_SC,
+      CURRENT_SC = remove_SC(&DISCONNECTED_SC,
 			      target,
-			      identify_msg & 0x3f );
+        		     identify_msg & 0x3f);
 
-      if(!current_SC)
+      if(!CURRENT_SC)
 	{
-	  printk("lun=%d, ", identify_msg & 0x3f );
-	  aha152x_panic("no disconnected command for that lun");
+          printk("lun=%d, ", identify_msg & 0x3f);
+          aha152x_panic(shpnt, "no disconnected command for that lun");
 	}
 
-      current_SC->SCp.phase &= ~disconnected;
+      CURRENT_SC->SCp.phase &= ~disconnected;
       restore_flags(flags);
 
-      SETPORT( SIMODE0, 0 );
-      SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+      SETPORT(SIMODE0, 0);
+      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 #if defined(DEBUG_RACE)
       leave_driver("(reselected) intr");
 #endif
-      SETBITS( DMACNTRL0, INTEN);
+      SETBITS(DMACNTRL0, INTEN);
       return;
     }
   
   /* Check, if we aren't busy with a command */
-  if(!current_SC)
+  if(!CURRENT_SC)
     {
       /* bus is free to issue a queued command */
-      if(TESTHI( SSTAT1, BUSFREE) && issue_SC)
+      if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC)
 	{
 	  save_flags(flags);
 	  cli();
 #if defined(DEBUG_QUEUES)
-	  if(aha152x_debug & debug_queues)
+          if(HOSTDATA(shpnt)->debug & debug_queues)
 	    printk("i-, ");
 #endif
-	  current_SC = remove_first_SC( &issue_SC );
+          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))
+          if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
 	    printk("issuing command, ");
 #endif
-	  current_SC->SCp.phase = in_selection;
+          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 );
+#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
+          if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
+            printk("selecting %d, ", CURRENT_SC->target); 
+#endif
+          SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
 
 	  /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
-	  SETPORT( SXFRCTL1, can_doparity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
+          SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
 
 	  /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-	  SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
-	  SETPORT( SIMODE1, ENSELTIMO );
+          SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+          SETPORT(SIMODE1, ENSELTIMO);
 
 	  /* Enable SELECTION OUT sequence */
-	  SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
+          SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
 	
-  #if defined(DEBUG_RACE)
+#if defined(DEBUG_RACE)
 	  leave_driver("(selecting) intr");
-  #endif
-	  SETBITS( DMACNTRL0, INTEN );
+#endif
+          SETBITS(DMACNTRL0, INTEN);
 	  return;
 	}
 
@@ -1411,200 +1468,229 @@
   /* the bus is busy with something */
 
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
-    disp_ports();
+  if(HOSTDATA(shpnt)->debug & debug_intr)
+    disp_ports(shpnt);
 #endif
 
   /* we are waiting for the result of a selection attempt */
-  if(current_SC->SCp.phase & in_selection)
+  if(CURRENT_SC->SCp.phase & in_selection)
     {
-      if( TESTLO( SSTAT1, SELTO ) )
+      if(TESTLO(SSTAT1, SELTO))
 	/* no timeout */
-	if( TESTHI( SSTAT0, SELDO ) )
+        if(TESTHI(SSTAT0, SELDO))
 	  {
 	    /* clear BUS FREE interrupt */
-	    SETPORT( SSTAT1, CLRBUSFREE);
+            SETPORT(SSTAT1, CLRBUSFREE);
 
 	    /* Disable SELECTION OUT sequence */
-	    CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
+            CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
 
 	    /* Disable SELECTION OUT DONE interrupt */
 	    CLRBITS(SIMODE0, ENSELDO);
 	    CLRBITS(SIMODE1, ENSELTIMO);
 
-	    if( TESTLO(SSTAT0, SELDO) )
+            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);
+        	SETBITS(DMACNTRL0, INTEN);
 
-		if(current_SC->SCp.phase & aborted)
+        	if(CURRENT_SC->SCp.phase & aborted)
 		  {
-		    abort_result=SCSI_ABORT_ERROR;
-		    abortion_complete++;
+        	    HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
+        	    HOSTDATA(shpnt)->abortion_complete++;
 		  }
 
-		aha152x_done( DID_NO_CONNECT << 16 );
+        	aha152x_done(shpnt, DID_NO_CONNECT << 16);
 		return;
 	      }
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-	    if(aha152x_debug & (debug_selection|debug_phases))
+            if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
 	      printk("SELDO (SELID=%x), ", GETPORT(SELID));
 #endif
 
 	    /* selection was done */
-	    SETPORT( SSTAT0, CLRSELDO );
+            SETPORT(SSTAT0, CLRSELDO);
 
 #if defined(DEBUG_ABORT)
-	    if((aha152x_debug & debug_abort) && (current_SC->SCp.phase & aborted))
+            if((HOSTDATA(shpnt)->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;
+            CURRENT_SC->SCp.phase &= ~in_selection;
+            CURRENT_SC->SCp.phase |= in_other;
+
+            ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun));
+
+            if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous)
+              {
+                ADDMSG(EXTENDED_MESSAGE);
+                ADDMSG(3);
+                ADDMSG(EXTENDED_SDTR);
+        	ADDMSG(50);
+                ADDMSG(8);
+
+                printk("outbound SDTR: ");
+                print_msg(&MSG(MSGLEN-5));
+
+        	SYNCRATE=0x80;
+                CURRENT_SC->SCp.phase |= in_sync;
+              }
 
 #if defined(DEBUG_RACE)
 	    leave_driver("(SELDO) intr");
 #endif
+            SETPORT(SCSIRATE, SYNCRATE&0x7f);
 
-	    SETPORT( SCSISIG, P_MSGO );
+            SETPORT(SCSISIG, P_MSGO);
 
-	    SETPORT( SIMODE0, 0 );
-	    SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
-	    SETBITS( DMACNTRL0, INTEN);
+            SETPORT(SIMODE0, 0);
+            SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
+            SETBITS(DMACNTRL0, INTEN);
 	    return;
 	  }
 	else
-	  aha152x_panic("neither timeout nor selection\007");
+          aha152x_panic(shpnt, "neither timeout nor selection\007");
       else
 	{
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-	  if(aha152x_debug & (debug_selection|debug_phases))
+          if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
 	  printk("SELTO, ");
 #endif
 	  /* end selection attempt */
-	  CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
+          CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
 
 	  /* timeout */
-	  SETPORT( SSTAT1, CLRSELTIMO );
+          SETPORT(SSTAT1, CLRSELTIMO);
 
-	  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-	  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-	  SETBITS( DMACNTRL0, INTEN );
+          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(CURRENT_SC->SCp.phase & aborted)
 	    {
 #if defined(DEBUG_ABORT)
-	      if(aha152x_debug & debug_abort)
+              if(HOSTDATA(shpnt)->debug & debug_abort)
 		printk("(ABORT) selection timeout, ");
 #endif
-	      abort_result=SCSI_ABORT_ERROR;
-	      abortion_complete++;
+              HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
+              HOSTDATA(shpnt)->abortion_complete++;
 	    }
 
-	  if( TESTLO( SSTAT0, SELINGO ) )
+          if(TESTLO(SSTAT0, SELINGO))
 	    /* ARBITRATION not won */
-	    aha152x_done( DID_BUS_BUSY << 16 );
+            aha152x_done(shpnt, DID_BUS_BUSY << 16);
 	  else
 	    /* ARBITRATION won, but SELECTION failed */
-	    aha152x_done( DID_NO_CONNECT << 16 );
+            aha152x_done(shpnt, DID_NO_CONNECT << 16);
+
 	  return;
 	}
     }
 
   /* enable interrupt, when target leaves current phase */
-  phase = getphase();
+  phase = getphase(shpnt);
   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 );
+  CURRENT_SC->SCp.phase =
+    (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16);
 
   /* information transfer phase */
-  switch( phase )
+  switch(phase)
     {
     case P_MSGO:                                               /* MESSAGE OUT */
       {
-	unsigned char message;
+        int i, identify=0, abort=0;
 
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES)
-	if(aha152x_debug & (debug_intr|debug_msgo|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases))
 	  printk("MESSAGE OUT, ");
 #endif
-
-	if( current_SC->SCp.phase & aborted )
+        if(MSGLEN==0)
 	  {
-#if defined(DEBUG_MSGO) || defined(DEBUG_ABORT)
-	    if(aha152x_debug & (debug_msgo|debug_abort))
-	      printk("ABORT, ");
+            ADDMSG(MESSAGE_REJECT);
+#if defined(DEBUG_MSGO)
+            if(HOSTDATA(shpnt)->debug & debug_msgo)
+              printk("unexpected MSGO; rejecting, ");
 #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);
+        
+        
+        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 defined(DEBUG_MSGO)
-	      if(aha152x_debug & debug_msgo)
-		printk("IDENTIFY (reconnect=%s;lun=%d), ", 
-			can_disconnect ? "enabled" : "disabled", current_SC->lun);
-#endif
+        if(HOSTDATA(shpnt)->debug & debug_msgo)
+          {
+            int i;
+            
+            printk("messages (");
+            for(i=0; i<MSGLEN; i+=print_msg(&MSG(i)), printk(" "))
+              ;
+            printk("), ");
 	    }
-	  else
+#endif
+        
+        for(i=0; i<MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++)
 	    {
-	      message=MESSAGE_REJECT;
 #if defined(DEBUG_MSGO)
-	      if(aha152x_debug & debug_msgo)
-		printk("REJECT, ");
+            if(HOSTDATA(shpnt)->debug & debug_msgo)
+              printk("%x ", MSG(i));
 #endif
+            if(i==MSGLEN-1)
+              {
+                /* Leave MESSAGE OUT after transfer */
+                SETPORT(SSTAT1, CLRATNO);
 	    }
 	  
-	CLRBITS( SXFRCTL0, ENDMA);
+            SETPORT(SCSIDAT, MSG(i));
 
-	SETPORT( SIMODE0, 0 );
-	SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE );
+            make_acklow(shpnt);
+            getphase(shpnt);
 
-	/* wait for data latch to become ready or a phase change */
-	while( TESTLO( DMASTAT, INTSTAT ) )
-	  ;
+            if(MSG(i)==IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun))
+              identify++;
 
-	if( TESTHI( SSTAT1, PHASEMIS ) )
-	  aha152x_panic("unable to send message");
+            if(MSG(i)==ABORT)
+              abort++;
 
-	/* Leave MESSAGE OUT after transfer */
-	SETPORT( SSTAT1, CLRATNO);
+          }
 
-	SETPORT( SCSIDAT, message );
+        MSGLEN=0;
 
-	make_acklow();
-	getphase();
+        if(MSGLEN>0)
+          aha152x_panic(shpnt, "oops, MSGLEN>0 !?");
 
-	if(message==IDENTIFY(can_disconnect,current_SC->lun))
-	  current_SC->SCp.phase |= sent_ident;
+        if(identify)
+          CURRENT_SC->SCp.phase |= sent_ident;
 
-	if(message==ABORT)
+        if(abort)
 	  {
 	    /* revive abort(); abort() enables interrupts */
-	    abort_result=SCSI_ABORT_SUCCESS;
-	    abortion_complete++;
+            HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
+            HOSTDATA(shpnt)->abortion_complete++;
 
-	    current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+            CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
 	    /* exit */
-	    SETBITS( DMACNTRL0, INTEN );
+            SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
 	    leave_driver("(ABORT) intr");
 #endif
-	    aha152x_done(DID_ABORT<<16);
+            aha152x_done(shpnt, DID_ABORT<<16);
 	    return;
 	  }
       }
@@ -1612,291 +1698,263 @@
 
     case P_CMD:                                          /* COMMAND phase */
 #if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_intr|debug_cmd|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_cmd|debug_phases))
 	printk("COMMAND, ");
 #endif
-      if( !(current_SC->SCp.sent_command) )
+      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 ) )
+          int i;
+
+          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("target left COMMAND phase");
-
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
+          for(i=0; i<CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++)
 	  {
-	    printk("DFIFOEMP, outsw (%d bytes, %d words), ",
-		   current_SC->cmd_len, current_SC->cmd_len >> 1 );
-	    disp_ports();
-	  }
-#endif
-  
-	  outsw( DATAPORT, &current_SC->cmnd, current_SC->cmd_len >> 1 );
+              SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]);
 
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
-	  {
-	    printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() );
-	    disp_ports();
+              make_acklow(shpnt);
+              getphase(shpnt);
 	  }
-#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
+          if(i<CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS))
+            aha152x_panic(shpnt, "target left COMMAND");
 
+          CURRENT_SC->SCp.sent_command++;
 	}
       else
-	aha152x_panic("Nothing to sent while in COMMAND OUT");
+        aha152x_panic(shpnt, "Nothing to send while in COMMAND");
       break;
 
     case P_MSGI:                                          /* MESSAGE IN phase */
+      {
+        int start_sync=0;
+        
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_intr|debug_msgi|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgi|debug_phases))
 	printk("MESSAGE IN, ");
 #endif
-      SETPORT( SXFRCTL0, CH1);
+        SETPORT(SXFRCTL0, CH1);
 
-      SETPORT( SIMODE0, 0);
-      SETPORT( SIMODE1, ENBUSFREE);
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENBUSFREE);
   
-      while( phase == P_MSGI ) 
+        while(phase == P_MSGI) 
 	{
-	  current_SC->SCp.Message = GETPORT( SCSIBUS );
-	  switch(current_SC->SCp.Message)
+            CURRENT_SC->SCp.Message = GETPORT(SCSIDAT);
+            switch(CURRENT_SC->SCp.Message)
 	    {
 	    case DISCONNECT:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-	      if(aha152x_debug & (debug_msgi|debug_phases))
+        	if(HOSTDATA(shpnt)->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");
+        	CURRENT_SC->SCp.Message = 0;
+        	CURRENT_SC->SCp.phase   |= disconnected;
+        	if(!HOSTDATA(shpnt)->reconnect)
+        	  aha152x_panic(shpnt, "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 ), ");
+        	if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
+        	  printk("inbound message (COMMAND COMPLETE), ");
 #endif
 	      done++;
 	      break;
 
 	    case MESSAGE_REJECT:
+        	if(CURRENT_SC->SCp.phase & in_sync)
+        	  { 
+        	    CURRENT_SC->SCp.phase &= ~in_sync;
+        	    SYNCRATE=0x80;
+        	    printk("synchronous rejected, ");
+        	  }
+        	else
+        	  printk("inbound message (MESSAGE REJECT), ");
 #if defined(DEBUG_MSGI)
-	      if(aha152x_debug & debug_msgi)
-		printk("inbound message ( MESSAGE REJECT ), ");
+        	if(HOSTDATA(shpnt)->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 ), ");
+        	if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	  printk("inbound message (SAVE DATA POINTERS), ");
 #endif
 	      break;
 
 	    case EXTENDED_MESSAGE:
 	      { 
-		int           i, code;
+        	  char buffer[16];
+        	  int  i;
 
 #if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk("inbound message ( EXTENDED MESSAGE ), ");
+        	  if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	    printk("inbound message (EXTENDED MESSAGE), ");
 #endif
-		make_acklow();
-		if(getphase()!=P_MSGI)
+        	  make_acklow(shpnt);
+        	  if(getphase(shpnt)!=P_MSGI)
 		  break;
   
-		i=GETPORT(SCSIBUS);
+        	  buffer[0]=EXTENDED_MESSAGE;
+        	  buffer[1]=GETPORT(SCSIDAT);
+        	  
+        	  for(i=0; i<buffer[1] &&
+        	      (make_acklow(shpnt), getphase(shpnt)==P_MSGI); i++)
+        	    buffer[2+i]=GETPORT(SCSIDAT);
 
 #if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk("length (%d), code ( ", i);
+        	  if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	    print_msg(buffer);
 #endif
 
-		make_acklow();
-		if(getphase()!=P_MSGI)
+        	  switch(buffer [2])
+        	    {
+        	    case EXTENDED_SDTR:
+        	      {
+        		long ticks;
+        		
+        		if(buffer[1]!=3)
+        		  aha152x_panic(shpnt, "SDTR message length != 3");
+        		
+        		if(!HOSTDATA(shpnt)->synchronous)
 		  break;
 
-		code = GETPORT(SCSIBUS);
+        		printk("inbound SDTR: "); print_msg(buffer);
+        		
+        		ticks=(buffer[3]*4+49)/50;
 
-		switch( code )
+        		if(CURRENT_SC->SCp.phase & in_sync)
 		  {
-		  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 );
+        		    /* we initiated SDTR */
+        		    if(ticks>9 || buffer[4]<1 || buffer[4]>8)
+        		      aha152x_panic(shpnt, "received SDTR invalid");
+        		    
+        		    SYNCRATE |= ((ticks-2)<<4) + buffer[4];
+        		  }
+        		else if(ticks<=9 && buffer[4]>=1)
+        		  {
+        		    if(buffer[4]>8)
+        		      buffer[4]=8;
+        		    
+        		    ADDMSG(EXTENDED_MESSAGE);
+        		    ADDMSG(3);
+        		    ADDMSG(EXTENDED_SDTR);
+        		    if(ticks<4)
+        		      {
+        			    ticks=4;
+        			    ADDMSG(50);
+        		      }
 		      else
-			printk("vendor specific (%d) ", code);
-#endif
-		    SETPORT(SCSISIG, P_MSGI|ATNO);
-		    break;
+        		      ADDMSG(buffer[3]);
+        		    
+        		    ADDMSG(buffer[4]);
+        		    
+        		    printk("outbound SDTR: ");
+                            print_msg(&MSG(MSGLEN-5));
+        		    
+        		    CURRENT_SC->SCp.phase |= in_sync;
+        		    
+                            SYNCRATE |= ((ticks-2)<<4) + buffer[4];
+        		    
+        		    start_sync++;
 		  }
-#if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk(" ), data ( ");
-#endif
-		while( --i && (make_acklow(), getphase()==P_MSGI))
+        		else
 		  {
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      printk("%x ", GETPORT(SCSIBUS) );
-#else
-		    GETPORT(SCSIBUS);
-#endif
+        		    /* request SDTR is to slow, do it asynchronously */
+        		    ADDMSG(MESSAGE_REJECT);
+                            SYNCRATE = 0;
+        		  } 
+        		
+        		SETPORT(SCSIRATE, SYNCRATE&0x7f);
+        	      }
+        	      break;
+        	      
+        	    case EXTENDED_MODIFY_DATA_POINTER:
+        	    case EXTENDED_EXTENDED_IDENTIFY:
+        	    case EXTENDED_WDTR:
+        	    default:
+        	      ADDMSG(MESSAGE_REJECT);
+        	      break;
 		  }
-#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);
+        	printk("unsupported inbound message %x, ", 
+        	       CURRENT_SC->SCp.Message);
 	      break;
 
 	    }
 
-	  make_acklow();
-	  phase=getphase();
+            make_acklow(shpnt);
+            phase=getphase(shpnt);
 	} 
 
+        if(start_sync)
+          CURRENT_SC->SCp.phase |= in_sync;
+        else
+          CURRENT_SC->SCp.phase &= ~in_sync;
+        
+        if(MSGLEN>0)
+          SETPORT(SCSISIG, P_MSGI|ATNO);
+        
       /* clear SCSI fifo on BUSFREE */
       if(phase==P_BUSFREE)
 	SETPORT(SXFRCTL0, CH1|CLRCH1);
 
-      if(current_SC->SCp.phase & disconnected)
+        if(CURRENT_SC->SCp.phase & disconnected)
 	{
 	  save_flags(flags);
 	  cli();
 #if defined(DEBUG_QUEUES)
-	  if(aha152x_debug & debug_queues)
+            if(HOSTDATA(shpnt)->debug & debug_queues)
 	    printk("d+, ");
 #endif
-	  append_SC( &disconnected_SC, current_SC);
-	  current_SC = NULL;
+            append_SC(&DISCONNECTED_SC, CURRENT_SC);
+            CURRENT_SC = NULL;
 	  restore_flags(flags);
 
-	  SETBITS( SCSISEQ, ENRESELI );
+            SETBITS(SCSISEQ, ENRESELI);
 
-	  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-	  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+            SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+            SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-	  SETBITS( DMACNTRL0, INTEN );
+            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))
+      if(HOSTDATA(shpnt)->debug & (debug_status|debug_intr|debug_phases))
 	printk("STATUS, ");
 #endif
-      SETPORT( SXFRCTL0, CH1);
+      SETPORT(SXFRCTL0, CH1);
 
-      SETPORT( SIMODE0, 0 );
-      SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
+      SETPORT(SIMODE0, 0);
+      SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
 
-      if( TESTHI( SSTAT1, PHASEMIS ) )
+      if(TESTHI(SSTAT1, PHASEMIS))
 	printk("aha152x: passing STATUS phase");
 	
-      current_SC->SCp.Status = GETPORT( SCSIBUS );
-      make_acklow();
-      getphase();
+      CURRENT_SC->SCp.Status = GETPORT(SCSIBUS);
+      make_acklow(shpnt);
+      getphase(shpnt);
 
 #if defined(DEBUG_STATUS)
-      if(aha152x_debug & debug_status)
+      if(HOSTDATA(shpnt)->debug & debug_status)
       {
 	printk("inbound status ");
-	print_status( current_SC->SCp.Status );
+          print_status(CURRENT_SC->SCp.Status);
 	printk(", ");
       }
 #endif
@@ -1907,117 +1965,130 @@
 	int fifodata, data_count, done;
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-	if(aha152x_debug & (debug_datai|debug_intr|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr|debug_phases))
 	  printk("DATA IN, ");
 #endif
 
+#if 0
 	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));
+#endif
 
 	/* reset host fifo */
 	SETPORT(DMACNTRL0, RSTFIFO);
 	SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
 
-	SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN );
+        SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
 
-	SETPORT( SIMODE0, 0 );
-	SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+        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 ) 
+        while (!done) 
 	  {
 #if defined(DEBUG_DATAI)
-	    if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
 	      printk("expecting data, ");
 #endif
 	    /* wait for PHASEMIS or full FIFO */
-	    while( TESTLO ( DMASTAT, DFIFOFULL|INTSTAT ) )
+            while(TESTLO (DMASTAT, DFIFOFULL|INTSTAT))
 	      ;
 
-	    if( TESTHI( DMASTAT, DFIFOFULL ) )
+#if defined(DEBUG_DATAI)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
+              printk("ok, ");
+#endif
+            
+            if(TESTHI(DMASTAT, DFIFOFULL))
 	      fifodata=GETPORT(FIFOSTAT);
 	    else
 	      {
 		/* wait for SCSI fifo to get empty */
-		while( TESTLO( SSTAT2, SEMPTY ) )
+        	while(TESTLO(SSTAT2, SEMPTY))
 		  ;
 
 		/* rest of data in FIFO */
 		fifodata=GETPORT(FIFOSTAT);
 #if defined(DEBUG_DATAI)
-		if(aha152x_debug & debug_datai)
+        	if(HOSTDATA(shpnt)->debug & debug_datai)
 		  printk("last transfer, ");
 #endif
 		done=1;
 	      }
   
 #if defined(DEBUG_DATAI)
-	    if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
 	      printk("fifodata=%d, ", fifodata);
 #endif
 
-	    while( fifodata && current_SC->SCp.this_residual )
+            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;
+        	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)
+        	if(HOSTDATA(shpnt)->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--;
+        	    SETBITS(DMACNTRL0, _8BIT);
+        	    *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
+        	    CURRENT_SC->SCp.this_residual--;
 		  }
 		if(data_count>1)
 		  {
-		    CLRBITS(DMACNTRL0, _8BIT );
+        	    CLRBITS(DMACNTRL0, _8BIT);
 		    data_count >>= 1; /* Number of words */
-		    insw( DATAPORT, current_SC->SCp.ptr, data_count );
+        	    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(HOSTDATA(shpnt)->debug & debug_datai)
+        	      /* show what comes with the last transfer */
 		      if(done)
 			{
+#ifdef 0
 			  int           i;
 			  unsigned char *data;
+#endif
   
+        		  printk("data on last transfer (%d bytes) ",
+        			 2*data_count);
+#ifdef 0
 			  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++)
+        		  data = (unsigned char *) CURRENT_SC->SCp.ptr;
+        		  for(i=0; i<2*data_count; i++)
 			    printk("%2x ", *data++);
 			  printk("), ");
+#endif
 			}
 #endif
-		    current_SC->SCp.ptr           += 2 * data_count;
-		    current_SC->SCp.this_residual -= 2 * data_count;
+        	    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)
+        	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;
+        	    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;
 		  } 
 	      }
  
@@ -2028,15 +2099,15 @@
 	      {
 		printk("aha152x: more data than expected (%d bytes)\n",
 		       GETPORT(FIFOSTAT));
-		SETBITS(DMACNTRL0, _8BIT );
-		printk("aha152x: data ( ");
+        	SETBITS(DMACNTRL0, _8BIT);
+        	printk("aha152x: data (");
 		while(fifodata--)
-		  printk("%2x ", GETPORT( DATAPORT ));
+        	  printk("%2x ", GETPORT(DATAPORT));
 		printk(")\n");
 	      }
 
 #if defined(DEBUG_DATAI)
-	    if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
 	      if(!fifodata)
 		printk("fifo empty, ");
 	      else
@@ -2045,23 +2116,25 @@
 	  }
 
 #if defined(DEBUG_DATAI)
-	if((aha152x_debug & debug_datai) && (current_SC->SCp.buffers_residual || current_SC->SCp.this_residual))
+        if((HOSTDATA(shpnt)->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);
+        	 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 ) )
+        while(TESTHI(SXFRCTL0, SCSIEN))
 	  ;
-	CLRBITS(DMACNTRL0, ENDMA );
+        CLRBITS(DMACNTRL0, ENDMA);
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR)
-	if(aha152x_debug & (debug_datai|debug_intr))
+        if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr))
 	  printk("got %d bytes, ", GETSTCNT());
 #endif
 
-	current_SC->SCp.have_data_in++;
+        CURRENT_SC->SCp.have_data_in++;
       }
       break;
 
@@ -2070,95 +2143,96 @@
 	int data_count;
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-	if(aha152x_debug & (debug_datao|debug_intr|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr|debug_phases))
 	  printk("DATA OUT, ");
 #endif
 #if defined(DEBUG_DATAO)
-	if(aha152x_debug & debug_datao)
+        if(HOSTDATA(shpnt)->debug & debug_datao)
 	  printk("got data to send (bytes=%d, buffers=%d), ",
-		 current_SC->SCp.this_residual,
-		 current_SC->SCp.buffers_residual );
+        	 CURRENT_SC->SCp.this_residual,
+        	 CURRENT_SC->SCp.buffers_residual);
 #endif
 
-	if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT) )
+        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");
+            printk("%d(%d) left in FIFO, ",
+        	   GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+            aha152x_panic(shpnt, "FIFO should be empty");
 	  }
 
+        SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1);
+        SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
+        
 	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 );
+        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) )
+        while(TESTLO(SSTAT1, PHASEMIS) &&
+              (CURRENT_SC->SCp.this_residual ||
+               CURRENT_SC->SCp.buffers_residual))
 	  {
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
-		     current_SC->SCp.this_residual,
-		     current_SC->SCp.buffers_residual);
+        	     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 ;
+            data_count =
+              CURRENT_SC->SCp.this_residual > 128 ?
+              128 : CURRENT_SC->SCp.this_residual ;
 
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->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--;
+        	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;
+        	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 ) )
+            while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT))
 	      ;
 
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("fifo (%d bytes), transfered (%d bytes), ",
-		     GETPORT(FIFOSTAT), GETSTCNT() );
+        	     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)
+            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;
+        	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 )
+        if (CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual)
 	  {
 	    /* target leaves DATA OUT for an other phase
 	       (perhaps disconnect) */
@@ -2167,46 +2241,47 @@
 	    data_count = GETPORT(SSTAT2) & (SFULL|SFCNT);
 
 	    data_count += GETPORT(FIFOSTAT) ;
-	    current_SC->SCp.ptr           -= data_count;
-	    current_SC->SCp.this_residual += data_count;
+            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 );
+            if(HOSTDATA(shpnt)->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(SXFRCTL0, SCSIEN|DMAEN);
 	    CLRBITS(DMACNTRL0, ENDMA);
 	  }
 	else
 	  {
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("waiting for SCSI fifo to get empty, ");
 #endif
 	    /* wait for SCSI fifo to get empty */
-	    while( TESTLO( SSTAT2, SEMPTY ) )
+            while(TESTLO(SSTAT2, SEMPTY))
 	      ;
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("ok, left data (bytes=%d, buffers=%d) ",
-		     current_SC->SCp.this_residual,
-		     current_SC->SCp.buffers_residual);
+        	     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 ) )
+            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() );
+        if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr))
+          printk("sent %d data bytes, ", GETSTCNT());
 #endif
       }
       break;
@@ -2216,12 +2291,12 @@
       leave_driver("(BUSFREE) intr");
 #endif
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
 	printk("unexpected BUS FREE, ");
 #endif
-      current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+      CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
-      aha152x_done( DID_ERROR << 16 );               /* Don't know any better */
+      aha152x_done(shpnt, DID_ERROR << 16);         /* Don't know any better */
       return;
       break;
 
@@ -2231,10 +2306,10 @@
 #endif
       printk("PARITY error in DATA phase, ");
 
-      current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+      CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
-      SETBITS( DMACNTRL0, INTEN );
-      aha152x_done( DID_PARITY << 16 );
+      SETBITS(DMACNTRL0, INTEN);
+      aha152x_done(shpnt, DID_PARITY << 16);
       return;
       break;
 
@@ -2246,85 +2321,86 @@
   if(done)
     {
 #if defined(DEBUG_INTR)
-      if(aha152x_debug & debug_intr)
+      if(HOSTDATA(shpnt)->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) );
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+      SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
+      
+      SETBITS(DMACNTRL0, INTEN);
+      
+      aha152x_done(shpnt,
+        	   (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);
+             CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message);
 #endif
       return;
     }
 
-  if(current_SC)
-    current_SC->SCp.phase |= 1<<16 ;
+  if(CURRENT_SC)
+    CURRENT_SC->SCp.phase |= 1<<16 ;
 
-  SETPORT( SIMODE0, 0 );
-  SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+  SETPORT(SIMODE0, 0);
+  SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
-    disp_enintr();
+  if(HOSTDATA(shpnt)->debug & debug_intr)
+    disp_enintr(shpnt);
 #endif
 #if defined(DEBUG_RACE)
   leave_driver("(PHASEEND) intr");
 #endif
 
-  SETBITS( DMACNTRL0, INTEN);
+  SETBITS(DMACNTRL0, INTEN);
   return;
 }
 
 /* 
  * Dump the current driver status and panic...
  */
-static void aha152x_panic(const char *msg)
+static void aha152x_panic(struct Scsi_Host *shpnt, char *msg)
 {
-  printk("\naha152x_panic: %s\n", msg);
-  show_queues();
+  printk("\naha152x: %s\n", msg);
+  show_queues(shpnt);
   panic("aha152x panic");
 }
 
 /*
  * Display registers of AIC-6260
  */
-static void disp_ports(void)
+static void disp_ports(struct Scsi_Host *shpnt)
 {
 #ifdef DEBUG_AHA152X
   int s;
 
 #ifdef SKIP_PORTS
-  if(aha152x_debug & debug_skipports)
+  if(HOSTDATA(shpnt)->debug & debug_skipports)
 	return;
 #endif
 
-  printk("\n%s: ", current_SC ? "on bus" : "waiting");
+  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("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 ( ");
+  printk(" SCSISIG (");
   s=GETPORT(SCSISIG);
   switch(s & P_MASK)
     {
@@ -2351,132 +2427,131 @@
       break;
     }
   
-  printk(" ); ");
+  printk("); ");
 
-  printk("INTSTAT ( %s ); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
+  printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
 
-  printk("SSTAT ( ");
+  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 ");
+  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 ");
+  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 ( ");
+  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 ");
+  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 ");
+  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 ( ");
+  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 ");
+  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 ( ");
+  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 ");
+  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("SELID (%02x), ", GETPORT(SELID));
 
-  printk("SSTAT2 ( ");
+  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(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(SSTAT3);
+  printk("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f);
+  
+  printk("SSTAT4 (");
   s=GETPORT(SSTAT4);
-  if( s & SYNCERR)   printk("SYNCERR ");
-  if( s & FWERR)     printk("FWERR ");
-  if( s & FRERR)     printk("FRERR ");
+  if(s & SYNCERR)   printk("SYNCERR ");
+  if(s & FWERR)     printk("FWERR ");
+  if(s & FRERR)     printk("FRERR ");
   printk("); ");
-#endif
-
-  printk("FCNT ( %d ); ", GETPORT(FIFOSTAT) );
 
-  printk("DMACNTRL0 ( ");
+  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("%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 ( ");
+  printk("DMACNTRL1 (");
 
   s=GETPORT(DMACNTRL1);
-  if( s & PWRDWN )    printk("PWRDN ");
+  if(s & PWRDWN)    printk("PWRDN ");
   printk("); ");
 
 
-  printk("STK ( %d ); ", s & 0xf);
+  printk("STK (%d); ", s & 0xf);
+  
+#endif
 
   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 ");
+  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
 }
@@ -2484,29 +2559,29 @@
 /*
  * display enabled interrupts
  */
-static void disp_enintr(void)
+static void disp_enintr(struct Scsi_Host *shpnt)
 {
   int s;
 
-  printk("enabled interrupts ( ");
+  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 ");
+  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 ");
+  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");
 }
 
@@ -2560,7 +2635,7 @@
  */
 static void show_command(Scsi_Cmnd *ptr)
 {
-  printk("0x%08x: target=%d; lun=%d; cmnd=( ",
+  printk("0x%08x: target=%d; lun=%d; cmnd=(",
 	 (unsigned int) ptr, ptr->target, ptr->lun);
   
   print_command(ptr->cmnd);
@@ -2568,15 +2643,15 @@
   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 )
+  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 )
+      switch((ptr->SCp.phase >> 16) & P_MASK)
 	{
 	case P_DATAO:
 	  printk("DATA OUT");
@@ -2610,7 +2685,7 @@
 /*
  * Dump the queued data
  */
-static void show_queues(void)
+static void show_queues(struct Scsi_Host *shpnt)
 {
   unsigned long flags;
   Scsi_Cmnd *ptr;
@@ -2618,22 +2693,241 @@
   save_flags(flags);
   cli();
   printk("QUEUE STATUS:\nissue_SC:\n");
-  for(ptr=issue_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
+  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);
+  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 )
+  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
     show_command(ptr);
 
-  disp_ports();
-  disp_enintr();
+  disp_ports(shpnt);
+  disp_enintr(shpnt);
+  restore_flags(flags);
+}
+
+int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
+{
+  return(-ENOSYS);  /* Currently this is a no-op */
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) pos += sprintf(pos, ## args)
+
+static int get_command(char *pos, Scsi_Cmnd *ptr)
+{
+  char *start = pos;
+  int i;
+  
+  SPRINTF("0x%08x: target=%d; lun=%d; cmnd=(",
+          (unsigned int) ptr, ptr->target, ptr->lun);
+  
+  for(i=0; i<COMMAND_SIZE(ptr->cmnd[0]); i++)
+    SPRINTF("0x%02x", ptr->cmnd[i]);
+  
+  SPRINTF("); residual=%d; buffers=%d; phase |",
+          ptr->SCp.this_residual, ptr->SCp.buffers_residual);
+  
+  if(ptr->SCp.phase & not_issued  )  SPRINTF("not issued|");
+  if(ptr->SCp.phase & in_selection)  SPRINTF("in selection|");
+  if(ptr->SCp.phase & disconnected)  SPRINTF("disconnected|");
+  if(ptr->SCp.phase & aborted     )  SPRINTF("aborted|");
+  if(ptr->SCp.phase & sent_ident  )  SPRINTF("send_ident|");
+  if(ptr->SCp.phase & in_other)
+    { 
+      SPRINTF("; in other(");
+      switch((ptr->SCp.phase >> 16) & P_MASK)
+        {
+        case P_DATAO:
+          SPRINTF("DATA OUT");
+          break;
+        case P_DATAI:
+          SPRINTF("DATA IN");
+          break;
+        case P_CMD:
+          SPRINTF("COMMAND");
+          break;
+        case P_STATUS:
+          SPRINTF("STATUS");
+          break;
+        case P_MSGO:
+          SPRINTF("MESSAGE OUT");
+          break;
+        case P_MSGI:
+          SPRINTF("MESSAGE IN");
+          break;
+        default: 
+          SPRINTF("*illegal*");
+          break;
+        }
+      SPRINTF(")");
+      if(ptr->SCp.phase & (1<<16))
+        SPRINTF("; phaseend");
+    }
+  SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
+  
+  return(pos-start);
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
+
+int aha152x_proc_info(
+        	      char *buffer,
+        	      char **start,
+        	      off_t offset,
+        	      int length,
+        	      int hostno,
+        	      int inout
+        	      )
+{
+  int i;
+  char *pos = buffer;
+  Scsi_Device *scd;
+  struct Scsi_Host *shpnt;
+  unsigned long flags;
+  Scsi_Cmnd *ptr;
+  
+  for(i=0, shpnt= (struct Scsi_Host *) NULL; i<IRQS; i++)
+    if(aha152x_host[i] && aha152x_host[i]->host_no == hostno)
+      shpnt=aha152x_host[i];
+  
+  if(!shpnt)
+    return(-ESRCH);
+  
+  if(inout) /* Has data been written to the file ? */ 
+    return(aha152x_set_info(buffer, length, shpnt));
+  
+  SPRINTF(AHA152X_REVID "\n");
+  
+  save_flags(flags);
+  cli();
+  
+  SPRINTF("vital data:\nioports 0x%04x to 0x%04x\n",
+          shpnt->io_port, shpnt->io_port+shpnt->n_io_port-1);
+  SPRINTF("interrupt 0x%02x\n", shpnt->irq);
+  SPRINTF("disconnection/reconnection %s\n", 
+          HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled");
+  SPRINTF("parity checking %s\n", 
+          HOSTDATA(shpnt)->parity ? "enabled" : "disabled");
+  SPRINTF("synchronous transfers %s\n", 
+          HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
+  SPRINTF("current queued %d commands\n",
+          HOSTDATA(shpnt)->commands);
+  
+#if 0
+  SPRINTF("synchronously operating targets (tick=%ld ns):\n",
+          250000000/loops_per_sec);
+  for(i=0; i<8; i++)
+    if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
+      SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n",
+              i,
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
+        	       (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*
+        		 250000000/loops_per_sec,
+        	       HOSTDATA(shpnt)->syncrate[i]&0x0f);
+#else
+  SPRINTF("synchronously operating targets (tick=50 ns):\n");
+  for(i=0; i<8; i++)
+    if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
+      SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
+              i,
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*50,
+              HOSTDATA(shpnt)->syncrate[i]&0x0f);
+#endif
+  
+#ifdef DEBUG_AHA152X
+#define PDEBUG(flags,txt) if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
+  
+  SPRINTF("enabled debugging options:\n");
+  
+  PDEBUG(debug_skipports, "skip ports");
+  PDEBUG(debug_queue, "queue");
+  PDEBUG(debug_intr, "interrupt");
+  PDEBUG(debug_selection, "selection");
+  PDEBUG(debug_msgo, "message out");
+  PDEBUG(debug_msgi, "message in");
+  PDEBUG(debug_status, "status");
+  PDEBUG(debug_cmd, "command");
+  PDEBUG(debug_datai, "data in");
+  PDEBUG(debug_datao, "data out");
+  PDEBUG(debug_abort, "abort");
+  PDEBUG(debug_done, "done");
+  PDEBUG(debug_biosparam, "bios parameters");
+  PDEBUG(debug_phases, "phases");
+  PDEBUG(debug_queues, "queues");
+  PDEBUG(debug_reset, "reset");
+  
+  SPRINTF("\n");
+#endif
+  
+  SPRINTF("queue status:\nnot yet issued commands:\n");
+  for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+    pos += get_command(pos, ptr);
+  
+  if(CURRENT_SC)
+    {
+      SPRINTF("current command:\n");
+      pos += get_command(pos, CURRENT_SC);
+    }
+  
+  SPRINTF("disconnected commands:\n");
+  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+    pos += get_command(pos, ptr);
+  
   restore_flags(flags);
+  
+  scd = scsi_devices;
+  
+  SPRINTF("Attached devices: %s\n", (scd)?"":"none");
+  
+  while (scd) {
+    if (scd->host == shpnt) {
+      
+      SPRINTF("Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
+              scd->channel, scd->id, scd->lun);
+      for (i=0; i<8; i++) {
+        if (scd->vendor[i] >= 0x20)
+          SPRINTF("%c", scd->vendor[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF(" Model: ");
+      for (i = 0; i < 16; i++) {
+        if (scd->model[i] >= 0x20)
+          SPRINTF("%c", scd->model[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF(" Rev: ");
+      for (i = 0; i < 4; i++) {
+        if (scd->rev[i] >= 0x20)
+          SPRINTF("%c", scd->rev[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF("\n");
+      
+      SPRINTF("  Type:   %d ", scd->type);
+      SPRINTF("               ANSI SCSI revision: %02x",
+              (scd->scsi_level < 3)?1:2);
+      
+      if (scd->scsi_level == 2)
+        SPRINTF(" CCS\n");
+      else
+        SPRINTF("\n");
+    }
+    scd = scd->next;
+  }
+  
+  *start=buffer;
+  return (pos-buffer < length ? pos-buffer : length);     
 }
 
 #ifdef MODULE

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this