]> git.neil.brown.name Git - history.git/commitdiff
Import 2.0.23 2.0.23
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:21 +0000 (15:11 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:21 +0000 (15:11 -0500)
15 files changed:
Documentation/Changes
Makefile
drivers/cdrom/cdu31a.c
drivers/net/ppp.c
drivers/net/tulip.c
drivers/pci/pci.c
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx.seq
drivers/scsi/aic7xxx_proc.c
drivers/scsi/aic7xxx_reg.h
include/asm-i386/semaphore.h
include/linux/pci.h
net/ipv4/af_inet.c
net/ipv4/ip_forward.c
net/ipv4/tcp.c

index 9485b79b69ab9c8fadc9a4b3a5fcdf595295ae4f..63c6dc1290c4125db834c2fd1d2fcd16d2806051 100644 (file)
@@ -1,7 +1,7 @@
 Intro
 =====
 
-This document contains a list of the latest releases of the most
+This document contains a list of the latest stable releases of the most
 important packages for Linux as well as instructions for newcomers to
 the 2.0.x series of kernels.  By glancing through it, you should be
 able to find out what you need to upgrade in order to successfully run
@@ -28,13 +28,13 @@ http://www.datanet.hu/generations/linux/newkernel.html (Hungarian
 translation).
 
    Tamas also maintains a version of this file at
-http://www.datanet.hu/generations/linux/Changes.html (English).
+http://www.datanet.hu/generations/linux/Changes.html (English version).
 
    For people who prefer Japanese (thanks to Mitsuhiro Kojima): Kono
 bunshou no nihongo ban wa
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
-Last updated: September 10, 1996.
+Last updated: October 12, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -44,8 +44,8 @@ Current Releases
 - PPP daemon            2.2.0f
 - Dynamic linker (ld.so) 1.7.14
 - GNU CC                2.7.2
-- Binutils              2.6.0.14
-- Linux C Library       Stable:  5.2.18, Beta:  5.3.12
+- Binutils              2.7.0.3
+- Linux C Library       Stable:  5.2.18, Beta:  5.3.12 / 5.4.7
 - Linux C++ Library     2.7.1.4
 - Termcap               2.0.8
 - Procps                1.01
@@ -73,6 +73,7 @@ add -net 127.0.0.0'.
 distributions like Caldera).  If you're running one of these, edit
 /etc/sysconfig/network-scripts/ifup-lo, changing the line `route add
 -net $(IPADDR)' to `route add -net 127.0.0.0' and you should be fine.
+The new Red Hat 4.0 (Colgate) distribution does not have this problem.
 
    People have also reported problems due to the naming of the dummy
 network interface driver.  If the dummy driver is compiled into the
@@ -103,6 +104,14 @@ option is present.  Many older distributions (mainly Slackware) have
 this option in their lilo.config file.  Comment it out and re-run lilo
 if you need ramdisks.
 
+   The definition of SIOCSARP in /usr/include/linux/sockios.h was
+changed.  This means bootpd has to be re-compiled in order to work.
+
+   The kernel reboot method is now, by default, a cold reboot so that
+the kernel will work on systems that don't support other methods.  If
+you want to be able to do a warm reboot, add a reboot=warm option to
+lilo.conf.
+
 The Linux C Library
 ===================
 
@@ -125,7 +134,9 @@ binary is at the end of this file).
 
    Also, the libc-5.3.x line has a known security hole relating to
 rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.
+experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.7 is
+currently available as well, but it has a few problems of its own (a
+few missing symbols, for example, that will break existing apps).
 
    If you're getting an error message that is something to the effect of
 
@@ -567,7 +578,7 @@ E2fsprogs
    e2fsprogs 1.02 will work with the latest kernels, but it cannot be
 compiled on them.  If you need (or want) to compile your own copy,
 you'll need to get the latest version, currently available at
-ftp://tsx-11.mit.edu/pub/linux/packages/ext2fs/e2fsprogs-1.04.tar.gz.
+ftp://tsx-11.mit.edu/pub/linux/packages/ext2fs/e2fsprogs-1.06.tar.gz.
 
 How to know the version of the installed programs
 *************************************************
@@ -591,9 +602,9 @@ Where to get the files
 Binutils
 ========
 
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.6.0.14.bin.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.7.0.3.bin.tar.gz
 Installation notes:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.6.0.14
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.7.0.3
 
 GNU CC
 ======
index 589b30e27c3a73e68b31544d2f85d821ad6344c4..2065282230982eb1ed2f53071bd6bbc05c8a3647 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 22
+SUBLEVEL = 23
 
 ARCH = i386
 
index 5db4d7f5938c588402dfec994af00e14b3ad6c4a..55d2257169f8e61f363838ea62b07e80fdbacb8b 100644 (file)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
+ *
+ * Credits:
+ *    Heiko Eissfeldt <heiko@colossus.escape.de>
+ *         For finding abug in the return of the track numbers.
  */
 
 /*
@@ -2482,8 +2486,8 @@ static int scd_ioctl(struct inode *inode,
          i=verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
          if(i<0)
                return i;
-         loc_hdr.cdth_trk0 = bcd_to_int(sony_toc.first_track_num);
-         loc_hdr.cdth_trk1 = bcd_to_int(sony_toc.last_track_num);
+         loc_hdr.cdth_trk0 = sony_toc.first_track_num;
+         loc_hdr.cdth_trk1 = sony_toc.last_track_num;
          memcpy_tofs(hdr, &loc_hdr, sizeof(*hdr));
       }
       return 0;
@@ -2583,7 +2587,7 @@ static int scd_ioctl(struct inode *inode,
           * If we want to stop after the last track, use the lead-out
           * MSF to do that.
           */
-         if (ti.cdti_trk1 >= bcd_to_int(sony_toc.last_track_num))
+         if (ti.cdti_trk1 >= sony_toc.last_track_num)
          {
             log_to_msf(msf_to_log(sony_toc.lead_out_start_msf)-1,
                        &(params[4]));
index ca6a789e94d6dd20c052c79a57f84496ed912734..7f2b1583eaa5f3a22181cc04597d1dfdb5f535c4 100644 (file)
@@ -3080,6 +3080,14 @@ ppp_dev_xmit (sk_buff *skb, struct device *dev)
  */
        len   = skb->len;
        data  = skb_data(skb);
+/*
+ * Bug trap for null data. Release the skb and bail out.
+ */
+       if(data == NULL) {
+               printk("ppp_dev_xmit: data=NULL before ppp_dev_xmit_ip.\n");
+               dev_kfree_skb (skb, FREE_WRITE);
+               return 0;
+       }
 /*
  * Look at the protocol in the skb to determine the difference between
  * an IP frame and an IPX frame.
index 6ba513daeb3dd05d85579bbe089cd64a0e9b6012..822bf129e79fae8df374e8468749d0df8a889252 100644 (file)
@@ -1096,7 +1096,7 @@ static void set_multicast_list(struct device *dev)
                /* Log any net taps. */
                printk("%s: Promiscuous mode enabled.\n", dev->name);
        }
-       else if (dev->mc_count > 15 || (dev->flags&IFF_ALLMULTI)) 
+       else if (dev->mc_count > 14 || (dev->flags&IFF_ALLMULTI)) 
        {
                /* Too many to filter perfectly -- accept all multicasts. */
                tio_write(csr6 | TCMOD_ALLMCAST, CSR6);
@@ -1109,7 +1109,7 @@ static void set_multicast_list(struct device *dev)
                unsigned short *eaddrs;
                int i;
 
-               /* We have <= 15 addresses that we can use the wonderful
+               /* We have < 15 addresses that we can use the wonderful
                   16 address perfect filtering of the Tulip.  Note that only
                   the low shortword of setup_frame[] is valid. */
                tio_write(csr6 | 0x0000, CSR6);
@@ -1122,11 +1122,15 @@ static void set_multicast_list(struct device *dev)
                }
                /* Fill the rest of the table with our physical address. */
                eaddrs = (unsigned short *)dev->dev_addr;
+               /* Always accept broadcast packets */
+               *setup_frm++ = 0xffff;
+               *setup_frm++ = 0xffff;
+               *setup_frm++ = 0xffff;
                do {
                        *setup_frm++ = eaddrs[0];
                        *setup_frm++ = eaddrs[1];
                        *setup_frm++ = eaddrs[2];
-               } while (++i < 16);
+               } while (++i < 15);
 
                /* Now add this frame to the Tx list. */
        }
index b09f5234bc91bde1bd85dc16a1856c5092ab5424..38089be8dcd74e93751f96e367732066994be6f7 100644 (file)
@@ -239,6 +239,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( ADAPTEC,        ADAPTEC_7850,   "AIC-7850"),
        DEVICE( ADAPTEC,        ADAPTEC_7855,   "AIC-7855"),
        DEVICE( ADAPTEC,        ADAPTEC_7860,   "AIC-7860"),
+       DEVICE( ADAPTEC,        ADAPTEC_7861,   "AIC-7861"),
        DEVICE( ADAPTEC,        ADAPTEC_7870,   "AIC-7870"),
        DEVICE( ADAPTEC,        ADAPTEC_7871,   "AIC-7871"),
        DEVICE( ADAPTEC,        ADAPTEC_7872,   "AIC-7872"),
index a8ed062c2b522abf663f4a71f1a1f667eb42bdce..195eaa1f501b05404821cf389bda1104b0347e5f 100644 (file)
@@ -41,7 +41,7 @@
  *
  *    -- Daniel M. Eischen, deischen@iworks.InterWorks.org, 07/07/96
  *
- *  $Id: aic7xxx.c,v 3.4 1996/08/09 15:56:31 deang Exp $
+ *  $Id: aic7xxx.c,v 4.0 1996/10/13 08:23:42 deang Exp $
  *-M*************************************************************************/
 
 #ifdef MODULE
@@ -50,6 +50,7 @@
 
 #include <stdarg.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include "aic7xxx.h"
 #include "aic7xxx_reg.h"
 #include <linux/stat.h>
+#include <linux/malloc.h>      /* for kmalloc() */
 
 #include <linux/config.h>      /* for CONFIG_PCI */
 
+/*
+ * To generate the correct addresses for the controller to issue
+ * on the bus.  Originally added for DEC Alpha support.
+ */
+#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))
+
 struct proc_dir_entry proc_scsi_aic7xxx = {
     PROC_SCSI_AIC7XXX, 7, "aic7xxx",
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
-#define AIC7XXX_C_VERSION  "$Revision: 3.4 $"
+#define AIC7XXX_C_VERSION  "$Revision: 4.0 $"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        ((a < b) ? a : b)
@@ -133,12 +141,13 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
  *   o 3985 support - The 3985 adapter is much like the 3940, but
  *     has three 7870 controllers as opposed to two for the 3940.
  *     It will get probed and recognized as three different adapters,
- *     but all three controllers share the same bank of 255 SCBs
- *     instead of each controller having their own bank (like the
- *     controllers on the 3940).  For this reason, it is important
- *     that all devices be resident on just one channel of the 3985.
- *     In the near future, we'll modify the driver to reserve 1/3
- *     of the SCBs for each controller.
+ *     but all three controllers can share the same external bank of
+ *     255 SCBs.  If you enable AIC7XXX_SHARE_SCBS, then the driver
+ *     will attempt to share the common bank of SCBs between the three
+ *     controllers of the 3985.  This is experimental and hasn't
+ *     been tested.  By default, we do not share the bank of SCBs,
+ *     and force the controllers to use their own internal bank of
+ *     16 SCBs.  Please let us know if sharing the SCB array works.
  *
  *   o SCB paging support - SCB paging is enabled by defining
  *     AIC7XXX_PAGE_ENABLE.  Support for this was taken from the
@@ -173,6 +182,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
  * Uncomment the following define for collection of SCSI transfer statistics
  * for the /proc filesystem.
  *
+ * NOTE: Do NOT enable this when running on kernels version 1.2.x and below.
  * NOTE: This does affect performance since it has to maintain statistics.
  */
 /* #define AIC7XXX_PROC_STATS */
@@ -182,6 +192,12 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
  */
 /* #define AIC7XXX_PAGE_ENABLE */
 
+/*
+ * Uncomment the following to enable sharing of the external bank
+ * of 255 SCBs for the 3985.
+ */
+#define AIC7XXX_SHARE_SCBS
+
 /*
  * For debugging the abort/reset code.
  */
@@ -203,6 +219,7 @@ typedef enum {
   AIC_7850,    /* PCI  aic7850 */
   AIC_7855,    /* PCI  aic7855 */
   AIC_7860,    /* PCI  aic7860 (7850 Ultra) */
+  AIC_7861,     /* PCI  aic7861 on 2940AU */
   AIC_7870,    /* PCI  aic7870 on motherboard */
   AIC_7871,    /* PCI  aic7871 on 294x */
   AIC_7872,    /* PCI  aic7872 on 3940 */
@@ -257,6 +274,7 @@ static const char *board_names[] = {
   "AIC-7850",                  /* AIC_7850 */
   "AIC-7855",                  /* AIC_7855 */
   "AIC-7850 Ultra",            /* AIC_7860 */
+  "AHA-2940A Ultra",           /* AIC_7861 */
   "AIC-7870",                  /* AIC_7870 */
   "AHA-2940",                  /* AIC_7871 */
   "AHA-3940",                  /* AIC_7872 */
@@ -296,7 +314,6 @@ static const char *board_names[] = {
 #define MINSLOT                1
 #define MAXSLOT                15
 #define SLOTBASE(x)    ((x) << 12)
-#define MAXIRQ         15
 
 /*
  * Standard EISA Host ID regs  (Offset from slot base)
@@ -348,6 +365,18 @@ static const char *board_names[] = {
 #define                STPWLEVEL       0x00000002ul
 #define                DIFACTNEGEN     0x00000001ul    /* aic7870 only */
 
+
+/*
+ * Define the different types of SEEPROMs on aic7xxx adapters
+ * and make it also represent the address size used in accessing
+ * its registers.  The 93C46 chips have 1024 bits organized into
+ * 64 16-bit words, while the 93C56 chips have 2048 bits organized
+ * into 128 16-bit words.  The C46 chips use 6 bits to address
+ * each word, while the C56 and C66 (4096 bits) use 8 bits to
+ * address each word.
+ */
+typedef enum {c46 = 6, c56_66 = 8} seeprom_chip_type;
+
 /*
  *
  * Define the format of the SEEPROM registers (16 bits).
@@ -465,18 +494,6 @@ struct seeprom_config {
  */
 #define aic7xxx_position(cmd)  ((cmd)->SCp.have_data_in)
 
-/*
- * Since the sequencer code DMAs the scatter-gather structures
- * directly from memory, we use this macro to assert that the
- * kernel structure hasn't changed.
- */
-#define SG_STRUCT_CHECK(sg) \
-  ((char *) &(sg).address - (char *) &(sg) != 0 ||  \
-   (char *) &(sg).length  - (char *) &(sg) != 8 ||  \
-   sizeof((sg).address) != 4 ||                   \
-   sizeof((sg).length)  != 4 ||                   \
-   sizeof(sg)           != 12)
-
 /*
  * "Static" structures. Note that these are NOT initialized
  * to zero inside the kernel - we have to initialize them all
@@ -487,7 +504,7 @@ struct seeprom_config {
  * use the IRQ as an index into aic7xxx_boards[] to locate the card
  * information.
  */
-static struct Scsi_Host *aic7xxx_boards[MAXIRQ + 1];
+static struct Scsi_Host *aic7xxx_boards[NR_IRQS + 1];
 
 /*
  * When we detect and register the card, it is possible to
@@ -526,6 +543,21 @@ static int aic7xxx_spurious_count;
  * for driver level bookkeeping.
  */
 
+/*
+ * As of Linux 2.1, the mid-level SCSI code uses virtual addresses
+ * in the scatter-gather lists.  We need to convert the virtual
+ * addresses to physical addresses.
+ */
+struct hw_scatterlist {
+  unsigned int address;
+  unsigned int length;
+};
+
+/*
+ * Maximum number of SG segments these cards can support.
+ */
+#define        MAX_SG 256
+
 struct aic7xxx_scb {
 /* ------------    Begin hardware supported fields    ---------------- */
 /* 0*/  unsigned char control;
@@ -534,9 +566,9 @@ struct aic7xxx_scb {
 /* 3*/  unsigned char SG_segment_count;
 /* 4*/  unsigned char SG_list_pointer[4] __attribute__ ((packed));
 /* 8*/  unsigned char residual_SG_segment_count;
-/* 9*/  unsigned char residual_data_count[3];
+/* 9*/  unsigned char residual_data_count[3] __attribute__ ((packed));
 /*12*/  unsigned char data_pointer[4] __attribute__ ((packed));
-/*16*/  unsigned long data_count;
+/*16*/  unsigned int  data_count __attribute__ ((packed)); /* must be 32 bits */
 /*20*/  unsigned char SCSI_cmd_pointer[4] __attribute__ ((packed));
 /*24*/  unsigned char SCSI_cmd_length;
 /*25*/ u_char tag;                     /* Index into our kernel SCB array.
@@ -566,8 +598,7 @@ struct aic7xxx_scb {
                                 SCB_WAITINGQ | SCB_ASSIGNEDQ)
        int                 state;          /* current state of scb */
        unsigned int        position;       /* Position in scb array */
-       struct scatterlist  sg;
-       struct scatterlist  sense_sg;
+       struct hw_scatterlist  sg_list[MAX_SG]; /* SG list in adapter format */
        unsigned char       sense_cmd[6];   /* Allocate 6 characters for sense command */
 };
 
@@ -592,6 +623,15 @@ static struct {
 static unsigned char
 generic_sense[] = { REQUEST_SENSE, 0, 0, 0, 255, 0 };
 
+typedef struct {
+  scb_queue_type free_scbs;        /*
+                                    * SCBs assigned to free slot on
+                                    * card (no paging required)
+                                    */
+  int            numscbs;          /* current number of scbs */
+  int            activescbs;       /* active scbs */
+} scb_usage_type;
+
 /*
  * The maximum number of SCBs we could have for ANY type
  * of card. DON'T FORGET TO CHANGE THE SCB MASK IN THE
@@ -608,8 +648,6 @@ struct aic7xxx_host {
   int                      base;             /* card base address */
   int                      maxhscbs;         /* hardware SCBs */
   int                      maxscbs;          /* max SCBs (including pageable) */
-  int                      numscbs;          /* current number of scbs */
-  int                      activescbs;       /* active scbs */
 #define A_SCANNED              0x0001
 #define B_SCANNED              0x0002
 #define EXTENDED_TRANSLATION   0x0004
@@ -638,15 +676,11 @@ struct aic7xxx_host {
   unsigned char            qcntmask;
   struct seeprom_config    seeprom;
   struct Scsi_Host        *next;             /* allow for multiple IRQs */
-  struct aic7xxx_scb       scb_array[AIC7XXX_MAXSCB];  /* active commands */
+  struct aic7xxx_scb      *scb_array[AIC7XXX_MAXSCB];  /* active commands */
   struct aic7xxx_scb      *pagedout_ntscbs[16];  /*
                                                   * paged-out, non-tagged scbs
                                                   * indexed by target.
                                                   */
-  scb_queue_type           free_scbs;        /*
-                                              * SCBs assigned to free slot on
-                                              * card (no paging required)
-                                              */
   scb_queue_type           page_scbs;        /*
                                               * SCBs that will require paging
                                               * before use (no assigned slot)
@@ -660,6 +694,9 @@ struct aic7xxx_host {
                                               * have now been assigned a slot
                                               * by aic7xxx_free_scb
                                               */
+  scb_usage_type           scb_usage;
+  scb_usage_type          *scb_link;
+
   struct aic7xxx_cmd_queue {
     Scsi_Cmnd *head;
     Scsi_Cmnd *tail;
@@ -750,6 +787,9 @@ static int num_aic7xxx_syncrates =
 #ifdef CONFIG_PCI
 static int number_of_3940s = 0;
 static int number_of_3985s = 0;
+#ifdef AIC7XXX_SHARE_SCBS
+static scb_usage_type *shared_3985_scbs = NULL;
+#endif
 #endif CONFIG_PCI
 
 #ifdef AIC7XXX_DEBUG
@@ -802,6 +842,7 @@ debug_config(struct aic7xxx_host_config *p)
     case AIC_7850:
     case AIC_7855:
     case AIC_7860:
+    case AIC_7861:
     case AIC_7870:
     case AIC_7871:
     case AIC_7872:
@@ -877,7 +918,10 @@ debug_scb(struct aic7xxx_scb *scb)
          scb->SCSI_cmd_length);
   printk("reserved 0x%x, target status 0x%x, resid SG count %d, resid data count %d\n",
          (scb->RESERVED[1] << 8) | scb->RESERVED[0], scb->target_status,
-         scb->residual_SG_segment_count, scb->residual_data_count);
+         scb->residual_SG_segment_count,
+         ((scb->residual_data_count[2] << 16) |
+          (scb->residual_data_count[1] <<  8) |
+          (scb->residual_data_count[0]));
   printk("data ptr 0x%x, data count %d, next waiting %d\n",
          (scb->data_pointer[3] << 24) | (scb->data_pointer[2] << 16) |
          (scb->data_pointer[1] << 8) | scb->data_pointer[0],
@@ -911,6 +955,8 @@ static int aic7xxx_irq_trigger = -1;         /*
                                               *  0 use edge triggered
                                               *  1 use level triggered
                                               */
+static int aic7xxx_enable_ultra = 0;         /* enable ultra SCSI speeds */
+
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_setup
@@ -933,6 +979,7 @@ aic7xxx_setup(char *s, int *dummy)
     { "extended",    &aic7xxx_extended },
     { "no_reset",    &aic7xxx_no_reset },
     { "irq_trigger", &aic7xxx_irq_trigger },
+    { "ultra",       &aic7xxx_enable_ultra },
     { NULL,          NULL }
   };
 
@@ -1123,7 +1170,7 @@ aic7xxx_length(Scsi_Cmnd *cmd, int sg_last)
   struct scatterlist *sg;
 
   segments = cmd->use_sg - sg_last;
-  sg = (struct scatterlist *) cmd->buffer;
+  sg = (struct scatterlist *) cmd->request_buffer;
 
   if (cmd->use_sg)
   {
@@ -1155,53 +1202,60 @@ aic7xxx_scsirate(struct aic7xxx_host *p, unsigned char *scsirate,
   unsigned long ultra_enb_addr;
   unsigned char ultra_enb, sxfrctl0;
 
-  for (i = 0; i < num_aic7xxx_syncrates; i++)
+  /*
+   * If the offset is 0, then the device is requesting asynchronous
+   * transfers.
+   */
+  if (offset != 0)
   {
-    if ((aic7xxx_syncrates[i].period - period) >= 0)
+    for (i = 0; i < num_aic7xxx_syncrates; i++)
     {
-      /*
-       * Watch out for Ultra speeds when ultra is not enabled and
-       * vice-versa.
-       */
-      if (!(p->flags & ULTRA_ENABLED) &&
-          (aic7xxx_syncrates[i].rate & ULTRA_SXFR))
+      if ((aic7xxx_syncrates[i].period - period) >= 0)
       {
         /*
-         * This should only happen if the drive is the first to negotiate
-         * and chooses a high rate.   We'll just move down the table until
-         * we hit a non ultra speed.
+         * Watch out for Ultra speeds when ultra is not enabled and
+         * vice-versa.
          */
-        continue;
-      }
-      *scsirate = (aic7xxx_syncrates[i].rate) | (offset & 0x0F);
+        if (!(p->flags & ULTRA_ENABLED) &&
+            (aic7xxx_syncrates[i].rate & ULTRA_SXFR))
+        {
+          /*
+           * This should only happen if the drive is the first to negotiate
+           * and chooses a high rate.   We'll just move down the table until
+           * we hit a non ultra speed.
+           */
+          continue;
+        }
+        *scsirate = (aic7xxx_syncrates[i].rate) | (offset & 0x0F);
 
-      /*
-       * Ensure Ultra mode is set properly for this target.
-       */
-      ultra_enb_addr = ULTRA_ENB;
-      if ((channel == 'B') || (target > 7))
-      {
-        ultra_enb_addr++;
-      }
-      ultra_enb = inb(p->base + ultra_enb_addr);
-      sxfrctl0 = inb(p->base + SXFRCTL0);
-      if (aic7xxx_syncrates[i].rate & ULTRA_SXFR)
-      {
-        ultra_enb |= 0x01 << (target & 0x07);
-        sxfrctl0 |= ULTRAEN;
-      }
-      else
-      {
-        ultra_enb &= ~(0x01 << (target & 0x07));
-        sxfrctl0 &= ~ULTRAEN;
-      }
-      outb(ultra_enb, p->base + ultra_enb_addr);
-      outb(sxfrctl0, p->base + SXFRCTL0);
+        /*
+         * Ensure Ultra mode is set properly for this target.
+         */
+        ultra_enb_addr = ULTRA_ENB;
+        if ((channel == 'B') || (target > 7))
+        {
+          ultra_enb_addr++;
+        }
+        ultra_enb = inb(p->base + ultra_enb_addr);
+        sxfrctl0 = inb(p->base + SXFRCTL0);
+        if (aic7xxx_syncrates[i].rate & ULTRA_SXFR)
+        {
+          ultra_enb |= 0x01 << (target & 0x07);
+          sxfrctl0 |= ULTRAEN;
+        }
+        else
+        {
+          ultra_enb &= ~(0x01 << (target & 0x07));
+          sxfrctl0 &= ~ULTRAEN;
+        }
+        outb(ultra_enb, p->base + ultra_enb_addr);
+        outb(sxfrctl0, p->base + SXFRCTL0);
 
-      printk("scsi%d: Target %d, channel %c, now synchronous at %sMHz, "
-             "offset %d.\n", p->host_no, target, channel,
-            aic7xxx_syncrates[i].english, offset);
-      return;
+        printk("scsi%d: Target %d, channel %c, now synchronous at %sMHz, "
+               "offset %d.\n", p->host_no, target, channel,
+               aic7xxx_syncrates[i].english, offset);
+        return;
+      }
     }
   }
 
@@ -1433,10 +1487,10 @@ aic7xxx_allocate_scb(struct aic7xxx_host *p)
   struct aic7xxx_scb *scbp = NULL;
   int maxscbs;
 
-  scbp = p->free_scbs.head;
+  scbp = p->scb_link->free_scbs.head;
   if (scbp != NULL)
   {
-    scbq_remove_head(&p->free_scbs);
+    scbq_remove_head(&p->scb_link->free_scbs);
   }
   else
   {
@@ -1459,23 +1513,30 @@ aic7xxx_allocate_scb(struct aic7xxx_host *p)
         maxscbs = p->maxscbs;
       else
         maxscbs = p->maxhscbs;
-      if (p->numscbs < maxscbs)
+      if (p->scb_link->numscbs < maxscbs)
       {
-        scbp = &(p->scb_array[p->numscbs]);
-        memset(scbp, 0, sizeof(*scbp));
-        scbp->tag = p->numscbs;
-        if (p->numscbs < p->maxhscbs)
-         scbp->position = p->numscbs;
-        else
-         scbp->position = SCB_LIST_NULL;
-        p->numscbs++;
+        int scb_index = p->scb_link->numscbs;
+        int scb_size = sizeof(struct aic7xxx_scb);
+
+        p->scb_array[scb_index] = kmalloc(scb_size, GFP_ATOMIC | GFP_DMA);
+        scbp = (p->scb_array[scb_index]);
+        if (scbp != NULL)
+        {
+          memset(scbp, 0, sizeof(*scbp));
+          scbp->tag = scb_index;
+          if (scb_index < p->maxhscbs)
+            scbp->position = scb_index;
+          else
+           scbp->position = SCB_LIST_NULL;
+          p->scb_link->numscbs++;
+        }
       }
     }
   }
   if (scbp != NULL)
   {
 #ifdef AIC7XXX_DEBUG
-    p->activescbs++;
+    p->scb_link->activescbs++;
 #endif
   }
   return (scbp);
@@ -1568,10 +1629,10 @@ aic7xxx_free_scb(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
     }
     else
     {
-      scbq_insert_head(&p->free_scbs, scb);
+      scbq_insert_head(&p->scb_link->free_scbs, scb);
     }
 #ifdef AIC7XXX_DEBUG
-    p->activescbs--;  /* For debugging purposes. */
+    p->scb_link->activescbs--;  /* For debugging purposes. */
 #endif
   }
 }
@@ -1608,9 +1669,9 @@ aic7xxx_done_aborted_scbs(struct aic7xxx_host *p)
   struct aic7xxx_scb *scb;
   int i;
 
-  for (i = 0; i < p->numscbs; i++)
+  for (i = 0; i < p->scb_link->numscbs; i++)
   {
-    scb = &(p->scb_array[i]);
+    scb = (p->scb_array[i]);
     if (scb->state & SCB_QUEUED_FOR_DONE)
     {
 #ifdef AIC7XXX_DEBUG_ABORT
@@ -1749,7 +1810,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, char channel)
     {
       saved_queue[i] = inb(QINFIFO + base);
       outb(saved_queue[i], SCBPTR + base);
-      scb = &(p->scb_array[inb(SCB_TAG + base)]);
+      scb = (p->scb_array[inb(SCB_TAG + base)]);
       if (aic7xxx_match_scb(scb, target, channel))
       {
         /*
@@ -1787,7 +1848,7 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, char channel)
     while (next != SCB_LIST_NULL)
     {
       outb(next, SCBPTR + base);
-      scb = &(p->scb_array[inb(SCB_TAG + base)]);
+      scb = (p->scb_array[inb(SCB_TAG + base)]);
       /*
        * Select the SCB.
        */
@@ -1809,9 +1870,9 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, char channel)
    * for this target that are active.  These are other (most likely
    * tagged) commands that were disconnected when the reset occurred.
    */
-  for (i = 0; i < p->numscbs; i++)
+  for (i = 0; i < p->scb_link->numscbs; i++)
   {
-    scb = &(p->scb_array[i]);
+    scb = (p->scb_array[i]);
     if ((scb->state & SCB_ACTIVE) && aic7xxx_match_scb(scb, target, channel))
     {
       /*
@@ -1964,9 +2025,10 @@ aic7xxx_reset_channel(struct aic7xxx_host *p, char channel, int initiate_reset)
   }
 
   /*
-   * Delay by the bus settle time.
+   * Cause the mid-level SCSI code to delay any further 
+   * queueing by the bus settle time for us.
    */
-  aic7xxx_delay(AIC7XXX_RESET_DELAY);
+  p->host->last_reset = (jiffies + (AIC7XXX_RESET_DELAY * HZ));
 
   /*
    * Now loop through all the SCBs that have been marked for abortion,
@@ -2028,7 +2090,7 @@ static inline void
 aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
 {
   struct aic7xxx_scb *scb;
-  u_char cur_scb;
+  u_char cur_scb, intstat;
   u_long base = p->base;
   long flags;
 
@@ -2040,6 +2102,7 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
 
   PAUSE_SEQUENCER(p);
   cur_scb = inb(SCBPTR + base);
+  intstat = inb(INTSTAT + base);
 
   /*
    * First handle SCBs that are waiting but have been assigned a slot.
@@ -2097,7 +2160,7 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
          * Find the in-core SCB for the one we're paging out.
          */
         out_scbi = inb(SCB_TAG + base); 
-        out_scbp = &(p->scb_array[out_scbi]);
+        out_scbp = (p->scb_array[out_scbi]);
 
         /* Do the page out and mark the paged in SCB as active. */
         aic7xxx_page_scb(p, out_scbp, scb);
@@ -2132,7 +2195,15 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
   }
   /* Restore old position */
   outb(cur_scb, SCBPTR + base);
-  UNPAUSE_SEQUENCER(p);
+
+  /*
+   * Guard against unpausing the sequencer if there is an interrupt
+   * waiting to happen.
+   */
+  if (!(intstat & (BRKADRINT | SEQINT | SCSIINT)))
+  {
+    UNPAUSE_SEQUENCER(p);
+  }
 
   restore_flags(flags);
 }
@@ -2159,7 +2230,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
   unsigned char max_offset, rej_byte;
   unsigned short target_mask;
   char channel;
-  void *addr;
+  unsigned int addr; /* must be 32 bits */
   Scsi_Cmnd *cmd;
 
   p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata;
@@ -2278,7 +2349,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
            scb = p->pagedout_ntscbs[index];
          }
          else
-           scb = &(p->scb_array[arg_1]);
+           scb = (p->scb_array[arg_1]);
 
           if (!(scb->state & SCB_PAGED_OUT))
           {
@@ -2296,10 +2367,10 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
            * assigned SCB, an SCB that just completed, or the first one
            * on the disconnected SCB list.
           */
-         if (p->free_scbs.head != NULL)
+         if (p->scb_link->free_scbs.head != NULL)
           {
-           outscb = p->free_scbs.head;
-           scbq_remove_head(&p->free_scbs);
+           outscb = p->scb_link->free_scbs.head;
+           scbq_remove_head(&p->scb_link->free_scbs);
            scb->position = outscb->position;
            outscb->position = SCB_LIST_NULL;
            scbq_insert_head(&p->page_scbs, outscb);
@@ -2329,7 +2400,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
             {
               intstat &= ~CMDCMPLT;
             }
-            outscb = &(p->scb_array[scb_index]);
+            outscb = (p->scb_array[scb_index]);
             if (!(outscb->state & SCB_ACTIVE))
             {
              printk(KERN_WARNING "scsi%d: No command for completed SCB %d "
@@ -2370,7 +2441,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
             {
              outb(disc_scb, SCBPTR + base);
              tag = inb(SCB_TAG + base);
-             outscb = &(p->scb_array[tag]);
+             outscb = (p->scb_array[tag]);
              next = inb(SCB_NEXT + base);
              if (next != SCB_LIST_NULL)
               {
@@ -2387,7 +2458,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
               disc_scb = inb(QINFIFO + base);
               outb(disc_scb, SCBPTR + base);
               tag = inb(SCB_TAG + base);
-              outscb = &p->scb_array[tag];
+              outscb = (p->scb_array[tag]);
               if ((outscb->control & 0x23) != TAG_ENB)
               {
                 /*
@@ -2418,7 +2489,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 
                 outb(saved_queue[queued], SCBPTR + base);
                 tag = inb(SCB_TAG + base);
-                outscb = &p->scb_array[tag];
+                outscb = (p->scb_array[tag]);
               }
               scb->position = outscb->position;
               outscb->position = SCB_LIST_NULL;
@@ -2459,7 +2530,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
         if ((rej_byte & 0xF0) == 0x20)
         {
           scb_index = inb(SCB_TAG + base);
-          scb = &(p->scb_array[scb_index]);
+          scb = (p->scb_array[scb_index]);
           printk(KERN_WARNING "scsi%d: Tagged message received without identify."
                  "Disabling tagged commands for target %d channel %c.\n",
                   p->host_no, scsi_id, channel);
@@ -2511,13 +2582,39 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
        outb(scratch, TARG_SCRATCH + base + scratch_offset);
        outb(scratch, SCSIRATE + base);
        if ((scratch & 0x0F) == 0)
-       { /*
-          * The requested rate was so low that asynchronous transfers
-          * are faster (not to mention the controller won't support
-          * them), so we issue a reject to ensure we go to asynchronous
-          * transfers.
-          */
-          outb(SEND_REJ, RETURN_1 + base);
+       {
+          /*
+           * One of two things happened.  Either the device requested
+           * asynchronous data transfers, or it requested a synchronous
+           * data transfer rate that was so low that asynchronous
+           * transfers are faster (not to mention the controller won't
+           * support them).  In both cases the synchronous data transfer
+           * rate and the offset are set to 0 indicating asynchronous
+           * transfers.
+           *
+           * If the device requested an asynchronous transfer, then
+           * accept the request.  If the device is being forced to
+           * asynchronous data transfers and this is the first time
+           * we've seen the request, accept the request.  If we've
+           * already seen the request, then attempt to force
+           * asynchronous data transfers by rejecting the message.
+           */
+          if ((offset == 0) || (p->sdtr_pending & target_mask))
+          {
+            /*
+             * Device requested asynchronous transfers or we're
+             * forcing asynchronous transfers for the first time.
+             */
+            outb(0, RETURN_1 + base);
+          }
+          else
+          {
+            /*
+            * The first time in forcing asynchronous transfers
+             * failed, so we try sending a reject message.
+            */
+           outb(SEND_REJ, RETURN_1 + base);
+          }
        }
        else
        {
@@ -2667,13 +2764,13 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
          */
 
        scb_index = inb(SCB_TAG + base);
-       scb = &(p->scb_array[scb_index]);
+       scb = (p->scb_array[scb_index]);
        outb(0, RETURN_1 + base);   /* CHECK_CONDITION may change this */
        if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
        {
          printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x.\n", p->host_no,
-                intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx.\n", p->host_no,
+                intstat, scb_index, scb->state, (unsigned long) scb->cmd);
        }
        else
        {
@@ -2693,7 +2790,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
              if ((aic7xxx_error(cmd) == 0) && !(cmd->flags & WAS_SENSE))
              {
                 unsigned char tcl;
-               void         *req_buf;
+               unsigned int  req_buf; /* must be 32 bits */
 
                 tcl = scb->target_channel_lun;
 
@@ -2707,22 +2804,23 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
                scb->sense_cmd[1] = (cmd->lun << 5);
                scb->sense_cmd[4] = sizeof(cmd->sense_buffer);
 
-               scb->sense_sg.address = (char *) &cmd->sense_buffer;
-               scb->sense_sg.length = sizeof(cmd->sense_buffer);
-               req_buf = &scb->sense_sg;
+               scb->sg_list[0].address = VIRT_TO_BUS(&cmd->sense_buffer);
+               scb->sg_list[0].length = sizeof(cmd->sense_buffer);
+               req_buf = VIRT_TO_BUS(&scb->sg_list[0]);
                cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
 
                 scb->control = scb->control & DISCENB;
                scb->target_channel_lun = tcl;
-               addr = scb->sense_cmd;
+               addr = VIRT_TO_BUS(scb->sense_cmd);
                scb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
                memcpy(scb->SCSI_cmd_pointer, &addr,
                       sizeof(scb->SCSI_cmd_pointer));
                scb->SG_segment_count = 1;
                memcpy(scb->SG_list_pointer, &req_buf,
-                       sizeof(scb->SG_list_pointer));
-                scb->data_count = scb->sense_sg.length;
-               memcpy(scb->data_pointer, &(scb->sense_sg.address), 4);
+                      sizeof(scb->SG_list_pointer));
+                scb->data_count = scb->sg_list[0].length;
+               memcpy(scb->data_pointer, &(scb->sg_list[0].address),
+                      sizeof(scb->data_pointer));
 
                 aic7xxx_putscb(p, scb);
                 /*
@@ -2749,7 +2847,17 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
                      p->host_no, scb->target_channel_lun);
              if (!aic7xxx_error(cmd))
              {
-               aic7xxx_error(cmd) = DID_BUS_BUSY;
+                /* The error code here used to be DID_BUS_BUSY,
+                 * but after extensive testing, it has been determined
+                 * that a DID_BUS_BUSY return is a waste of time.  If
+                 * the problem is something that will go away, then it
+                 * will, if it isn't, then you don't want the endless
+                 * looping that you get with a DID_BUS_BUSY.  Better
+                 * to be on the safe side and specify an error condition
+                 * that will eventually lead to a reset or abort of some
+                 * sort instead of an endless loop.
+                 */
+               aic7xxx_error(cmd) = DID_RETRY_COMMAND;
              }
              break;
 
@@ -2773,12 +2881,12 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 
       case RESIDUAL:
        scb_index = inb(SCB_TAG + base);
-       scb = &(p->scb_array[scb_index]);
+       scb = (p->scb_array[scb_index]);
        if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
        {
          printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x.\n", p->host_no,
-                intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx.\n", p->host_no,
+                intstat, scb_index, scb->state, (unsigned long) scb->cmd);
        }
        else
        {
@@ -2816,12 +2924,12 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 
       case ABORT_TAG:
        scb_index = inb(SCB_TAG + base);
-       scb = &(p->scb_array[scb_index]);
+       scb = (p->scb_array[scb_index]);
        if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
        {
          printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x\n", p->host_no,
-                intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx\n", p->host_no,
+                intstat, scb_index, scb->state, (unsigned long) scb->cmd);
        }
        else
        {
@@ -2841,12 +2949,12 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 
       case AWAITING_MSG:
        scb_index = inb(SCB_TAG + base);
-       scb = &(p->scb_array[scb_index]);
+       scb = (p->scb_array[scb_index]);
        if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
        {
          printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x.\n", p->host_no,
-                intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+                "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx.\n", p->host_no,
+                intstat, scb_index, scb->state, (unsigned long) scb->cmd);
        }
        else
        {
@@ -2874,7 +2982,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
 
       case IMMEDDONE:
         scb_index = inb(SCB_TAG + base);
-       scb = &(p->scb_array[scb_index]);
+       scb = (p->scb_array[scb_index]);
 #ifdef AIC7XXX_DEBUG_ABORT
   printk("aic7xxx: received IMMEDDONE for target %d, scb %d, state %d\n",
          scsi_id, scb_index, scb->state);
@@ -2911,7 +3019,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
       {
         unsigned int overrun;
 
-        scb = &p->scb_array[inb(base + SCB_TAG)];
+        scb = (p->scb_array[inb(base + SCB_TAG)]);
         overrun = inb(base + STCNT0) | (inb(base + STCNT1) << 8) |
                   (inb(base + STCNT2) << 16);
         overrun =0x00FFFFFF - overrun;
@@ -2953,7 +3061,7 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
     }
 
     scb_index = inb(SCB_TAG + base);
-    scb = &(p->scb_array[scb_index]);
+    scb = (p->scb_array[scb_index]);
     if (status & SCSIRSTI)
     {
       PAUSE_SEQUENCER(p);
@@ -3103,13 +3211,13 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
     do {
       complete = inb(QOUTFIFO + base);
 
-      scb = &(p->scb_array[complete]);
+      scb = (p->scb_array[complete]);
       if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
       {
        printk(KERN_WARNING "scsi%d: CMDCMPLT without command for SCB %d.\n"
-              "       QOUTCNT %d, QINCNT %d, SCB state 0x%x, cmd 0x%x, "
+              "       QOUTCNT %d, QINCNT %d, SCB state 0x%x, cmd 0x%lx, "
                "pos(%d).\n", p->host_no, complete, inb(QOUTCNT + base),
-               inb(QINCNT + base), scb->state, (unsigned int) scb->cmd,
+               inb(QINCNT + base), scb->state, (unsigned long) scb->cmd,
                scb->position);
        outb(CLRCMDINT, CLRINT + base);
        continue;
@@ -3201,13 +3309,12 @@ static void aic7xxx_select_queue_depth(struct Scsi_Host *host,
 {
   Scsi_Device *device = scsi_devs;
   int tq_depth = 2;
+  struct aic7xxx_host *p = (struct aic7xxx_host *) host->hostdata;
 
 #ifdef AIC7XXX_CMDS_PER_LUN
   tq_depth = AIC7XXX_CMDS_PER_LUN;
 #else
   {
-    struct aic7xxx_host *p = (struct aic7xxx_host *) host->hostdata;
-
     if (p->maxhscbs <= 4)
     {
       tq_depth = 4;  /* Not many SCBs to work with. */
@@ -3227,14 +3334,26 @@ static void aic7xxx_select_queue_depth(struct Scsi_Host *host,
 #ifdef AIC7XXX_TAGGED_QUEUEING
       if (device->tagged_supported)
       {
-        device->queue_depth = tq_depth;
-        if (device->tagged_queue == 0)
+        unsigned short target_mask = (1 << device->id) | device->channel;
+
+        if (!(p->discenable & target_mask))
+        {
+          printk(KERN_INFO "scsi%d: Disconnection disabled, unable to enable "
+                 "tagged queueing for target %d, channel %d, LUN %d.\n",
+                 host->host_no, device->id, device->channel, device->lun);
+        }
+        else
         {
-          printk(KERN_INFO "scsi%d: Enabled tagged queuing for target %d, "
-                "channel %d, LUN %d, queue depth %d.\n", host->host_no,
-                 device->id, device->channel, device->lun, device->queue_depth);
-          device->tagged_queue = 1;
-          device->current_tag = SCB_LIST_NULL;
+          device->queue_depth = tq_depth;
+          if (device->tagged_queue == 0)
+          {
+            printk(KERN_INFO "scsi%d: Enabled tagged queuing for target %d, "
+                  "channel %d, LUN %d, queue depth %d.\n", host->host_no,
+                   device->id, device->channel, device->lun,
+                   device->queue_depth);
+            device->tagged_queue = 1;
+            device->current_tag = SCB_LIST_NULL;
+          }
         }
       }
 #endif
@@ -3473,7 +3592,7 @@ read_2840_seeprom(int base, struct seeprom_config *sc)
  *   Reads the serial EEPROM and returns 1 if successful and 0 if
  *   not successful.
  *
- *   The instruction set of the 93C46 chip is as follows:
+ *   The instruction set of the 93C46/56/66 chips is as follows:
  *
  *               Start  OP
  *     Function   Bit  Code  Address    Data     Description
@@ -3489,6 +3608,8 @@ read_2840_seeprom(int base, struct seeprom_config *sc)
  *     EWDS        1    00   00XXXX              Disables all programming
  *                                               instructions
  *     *Note: A value of X for address is a don't care condition.
+ *     *Note: The 93C56 and 93C66 have 8 address bits.
+ * 
  *
  *   The 93C46 has a four wire interface: clock, chip select, data in, and
  *   data out.  In order to perform one of the above functions, you need
@@ -3515,7 +3636,8 @@ read_2840_seeprom(int base, struct seeprom_config *sc)
  *
  *-F*************************************************************************/
 static int
-read_seeprom(int base, int offset, struct seeprom_config *sc)
+read_seeprom(int base, int offset, struct seeprom_config *sc,
+    seeprom_chip_type chip)
 {
   int i = 0, k;
   unsigned long timeout;
@@ -3583,7 +3705,7 @@ read_seeprom(int base, int offset, struct seeprom_config *sc)
     /*
      * Send the 6 bit address (MSB first, LSB last).
      */
-    for (i = 5; i >= 0; i--)
+    for (i = ((int) chip - 1); i >= 0; i--)
     {
       temp = k + offset;
       temp = (temp >> i) & 1;  /* Mask out all but lower bit. */
@@ -3925,6 +4047,7 @@ aic7xxx_register(Scsi_Host_Template *template,
       break;
 
     case AIC_7860:
+    case AIC_7861:
     case AIC_7880:
     case AIC_7881:
     case AIC_7882:
@@ -3934,7 +4057,7 @@ aic7xxx_register(Scsi_Host_Template *template,
        * Remember if Ultra was enabled in case there is no SEEPROM.
        * Fall through to the rest of the AIC_78xx code.
        */
-      if (inb(SXFRCTL0 + base) & ULTRAEN)
+      if ((inb(SXFRCTL0 + base) & ULTRAEN) || aic7xxx_enable_ultra)
         config->flags |= ULTRA_ENABLED;
 
     case AIC_7850:
@@ -3957,7 +4080,16 @@ aic7xxx_register(Scsi_Host_Template *template,
       config->parity = AIC_ENABLED;
 
       printk(KERN_INFO "aic7xxx: Reading SEEPROM...");
-      have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2), &sc);
+      if ((config->type == AIC_7873) || (config->type == AIC_7883))
+      {
+        have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2),
+                                    &sc, c56_66);
+      }
+      else
+      {
+        have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2),
+                                    &sc, c46);
+      }
       if (!have_seeprom)
       {
         for (sram = base + TARG_SCRATCH; sram < base + 0x60; sram++)
@@ -4141,25 +4273,6 @@ aic7xxx_register(Scsi_Host_Template *template,
    */
   debug_config(config);
 
-  /*
-   * Before registry, make sure that the offsets of the
-   * struct scatterlist are what the sequencer will expect,
-   * otherwise disable scatter-gather altogether until someone
-   * can fix it. This is important since the sequencer will
-   * DMA elements of the SG array in while executing commands.
-   */
-  if (template->sg_tablesize != SG_NONE)
-  {
-    struct scatterlist sg;
-
-    if (SG_STRUCT_CHECK(sg))
-    {
-      printk(KERN_WARNING "aic7xxx: Warning - Kernel scatter-gather structures "
-             "changed, disabling it.\n");
-      template->sg_tablesize = SG_NONE;
-    }
-  }
-
   /*
    * Register each "host" and fill in the returned Scsi_Host
    * structure as best we can. Some of the parameters aren't
@@ -4175,7 +4288,7 @@ aic7xxx_register(Scsi_Host_Template *template,
   host->this_id = config->scsi_id;
   host->io_port = config->base;
   host->n_io_port = 0xFF;
-  host->base = (char *)config->mbase;
+  host->base = (unsigned char *)config->mbase;
   host->irq = config->irq;
   if (config->bus_type == AIC_WIDE)
   {
@@ -4195,18 +4308,26 @@ aic7xxx_register(Scsi_Host_Template *template,
   p->maxscbs = config->maxscbs;
   p->maxhscbs = config->maxhscbs;
   p->qcntmask = config->qcntmask;
-  p->numscbs = 0;
   p->mbase = (char *)config->mbase;
   p->type = config->type;
   p->chip_type = config->chip_type;
   p->flags = config->flags;
   p->chan_num = config->chan_num;
+  p->scb_link = &(p->scb_usage);
+#ifdef AIC7XXX_SHARE_SCBS
+  if ((p->chan_num == 0) && ((p->type == AIC_7873) | (p->type == AIC_7883)))
+  {
+    shared_3985_scbs = &(p->scb_usage);
+    p->scb_link = &(p->scb_usage);
+  }
+#endif
+  p->scb_link->numscbs = 0;
   p->bus_type = config->bus_type;
   p->seeprom = sc;
   p->next = NULL;
   p->completeq.head = NULL;
   p->completeq.tail = NULL;
-  scbq_init(&p->free_scbs);
+  scbq_init(&p->scb_link->free_scbs);
   scbq_init(&p->page_scbs);
   scbq_init(&p->waiting_scbs);
   scbq_init(&p->assigned_scbs);
@@ -4567,7 +4688,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
    * a NULL entry to indicate that no prior hosts have
    * been found/registered for that IRQ.
    */
-  for (i = 0; i <= MAXIRQ; i++)
+  for (i = 0; i <= NUMBER(aic7xxx_boards); i++)
   {
     aic7xxx_boards[i] = NULL;
   }
@@ -4643,6 +4764,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7850, AIC_7850, AIC_785x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7855, AIC_7855, AIC_785x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AIC_7860, AIC_785x},
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7861, AIC_7861, AIC_785x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AIC_7870, AIC_787x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AIC_7871, AIC_787x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7872, AIC_7872, AIC_787x},
@@ -4690,6 +4812,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
             case AIC_7850:
             case AIC_7855:
             case AIC_7860:
+            case AIC_7861:
               config.bios = AIC_DISABLED;
               config.flags |= USE_DEFAULTS;
               config.bus_speed = DFTHRSH_100;
@@ -4703,7 +4826,7 @@ aic7xxx_detect(Scsi_Host_Template *template)
 
             case AIC_7873:  /* 3985 */
             case AIC_7883:  /* 3985-Ultra */
-              config.chan_num = number_of_3985s & 0x3;  /* Has 3 controllers */
+              config.chan_num = number_of_3985s;  /* Has 3 controllers */
               number_of_3985s++;
               if (number_of_3985s == 3)
               {
@@ -4773,7 +4896,12 @@ aic7xxx_detect(Scsi_Host_Template *template)
           config.high_term = AIC_UNKNOWN;
           if (aic7xxx_extended)
             config.flags |= EXTENDED_TRANSLATION;
+#ifdef AIC7XXX_SHARE_SCBs
           if (devconfig & RAMPSM)
+#else
+          if ((devconfig & RAMPSM) && (config.type != AIC_7873) &&
+              (config.type != AIC_7883))
+#endif
           {
             /*
              * External SRAM present.  The probe will walk the SCBs to see
@@ -4827,9 +4955,8 @@ static void
 aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
     struct aic7xxx_scb *scb)
 {
-  void *addr;
+  unsigned int addr; /* must be 32 bits */
   unsigned short mask;
-  struct scatterlist *sg;
 
   mask = (0x01 << TARGET_INDEX(cmd));
   /*
@@ -4900,27 +5027,43 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
    * XXX - this relies on the host data being stored in a
    *       little-endian format.
    */
-  addr = cmd->cmnd;
+  addr = VIRT_TO_BUS(cmd->cmnd);
   scb->SCSI_cmd_length = cmd->cmd_len;
   memcpy(scb->SCSI_cmd_pointer, &addr, sizeof(scb->SCSI_cmd_pointer));
 
   if (cmd->use_sg)
   {
+    struct scatterlist *sg;  /* Must be mid-level SCSI code scatterlist */
+
+    /*
+     * We must build an SG list in adapter format, as the kernel's SG list
+     * cannot be used directly because of data field size (__alpha__)
+     * differences and the kernel SG list uses virtual addresses where
+     * we need physical addresses.
+     */
+    int i;
+
+    sg = (struct scatterlist *)cmd->request_buffer;
+    for (i = 0; i < cmd->use_sg; i++)
+    {
+      scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
+      scb->sg_list[i].length = (unsigned int) sg[i].length;
+    }
     scb->SG_segment_count = cmd->use_sg;
-    memcpy(scb->SG_list_pointer, &cmd->request_buffer,
-          sizeof(scb->SG_list_pointer));
-    memcpy(&sg, &cmd->request_buffer, sizeof(sg));
-    memcpy(scb->data_pointer, &(sg[0].address), sizeof(scb->data_pointer));
-    scb->data_count = sg[0].length;
+    addr = VIRT_TO_BUS(scb->sg_list);
+    memcpy(scb->SG_list_pointer, &addr, sizeof(scb->SG_list_pointer));
+    memcpy(scb->data_pointer, &(scb->sg_list[0].address),
+           sizeof(scb->data_pointer));
+    scb->data_count = scb->sg_list[0].length;
 #if 0
-    debug("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
+    printk("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
            cmd->use_sg, aic7xxx_length(cmd, 0), scb->data_count);
 #endif
   }
   else
   {
 #if 0
-  debug("aic7xxx: (build_scb) Creating scatterlist, addr(0x%lx) length(%d).\n",
+  printk("aic7xxx: (build_scb) Creating scatterlist, addr(0x%lx) length(%d).\n",
        (unsigned long) cmd->request_buffer, cmd->request_bufflen);
 #endif
     if (cmd->request_bufflen == 0)
@@ -4938,12 +5081,13 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
     else
     {
       scb->SG_segment_count = 1;
-      scb->sg.address = (char *) cmd->request_buffer;
-      scb->sg.length = cmd->request_bufflen;
-      addr = &scb->sg;
+      scb->sg_list[0].address = VIRT_TO_BUS(cmd->request_buffer);
+      scb->sg_list[0].length = cmd->request_bufflen;
+      addr = VIRT_TO_BUS(&scb->sg_list[0]);
       memcpy(scb->SG_list_pointer, &addr, sizeof(scb->SG_list_pointer));
-      scb->data_count = scb->sg.length;
-      memcpy(scb->data_pointer, &cmd->request_buffer, sizeof(scb->data_pointer));
+      scb->data_count = scb->sg_list[0].length;
+      addr = VIRT_TO_BUS(cmd->request_buffer);
+      memcpy(scb->data_pointer, &addr, sizeof(scb->data_pointer));
     }
   }
 }
@@ -4958,12 +5102,17 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
 int
 aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
 {
-  long flags;
+  long processor_flags;
   struct aic7xxx_host *p;
   struct aic7xxx_scb *scb;
-  u_char curscb;
+  u_char curscb, intstat;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
+  if (p->host != cmd->host)
+  {
+    printk(KERN_INFO "scsi%d: Internal host structure != scsi.c host "
+      "structure.\n", p->host_no);
+  }
 
   /*
    * Check to see if channel was scanned.
@@ -4983,19 +5132,28 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
   }
 
 #if 0
-  debug("aic7xxx: (queue) cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n",
+  printk("aic7xxx: (queue) cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n",
        cmd->cmnd[0], cmd->cmd_len, cmd->target, cmd->channel,
        cmd->lun & 0x07);
 #endif
 
   /*
-   * This is a critical section, since we don't want the
-   * interrupt routine mucking with the host data or the
-   * card. Since the kernel documentation is vague on
-   * whether or not we are in a cli/sti pair already, save
-   * the flags to be on the safe side.
+   * This is a critical section, since we don't want the interrupt
+   * routine mucking with the host data or the card.  For this reason
+   * it is nice to know that this function can only be called in one
+   * of two ways from scsi.c  First, as part of a routine queue command,
+   * in which case, the irq for our card is disabled before this
+   * function is called.  This doesn't help us if there is more than
+   * one card using more than one IRQ in our system, therefore, we
+   * should disable all interrupts on these grounds alone.  Second,
+   * this can be called as part of the scsi_done routine, in which case
+   * we are in the aic7xxx_isr routine already and interrupts are
+   * disabled, therefore we should saveflags first, then disable the
+   * interrupts, do our work, then restore the CPU flags. If it weren't
+   * for the possibility of more than one card using more than one IRQ
+   * in our system, we wouldn't have to touch the interrupt flags at all.
    */
-  save_flags(flags);
+  save_flags(processor_flags);
   cli();
 
   scb = aic7xxx_allocate_scb(p);
@@ -5018,7 +5176,7 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
     aic7xxx_buildscb(p, cmd, scb);
 
 #if 0
-    if (scb != &p->scb_array[scb->position])
+    if (scb != (p->scb_array[scb->position]))
     {
       printk("aic7xxx: (queue) Address of SCB by position does not match SCB "
              "address.\n");
@@ -5057,6 +5215,7 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
          * XXX - should the interrupts be left on while doing this?
          */
         PAUSE_SEQUENCER(p);
+        intstat = inb(INTSTAT + p->base);
 
         /*
          * Save the SCB pointer and put our own pointer in - this
@@ -5071,7 +5230,14 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
         outb(scb->position, QINFIFO + p->base);
         scb->state |= SCB_ACTIVE;
 
-        UNPAUSE_SEQUENCER(p);
+        /*
+         * Guard against unpausing the sequencer if there is an interrupt
+         * waiting to happen.
+         */
+        if (!(intstat & (BRKADRINT | SEQINT | SCSIINT)))
+        {
+          UNPAUSE_SEQUENCER(p);
+        }
       }
     }
     else
@@ -5088,7 +5254,7 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
     printk("aic7xxx: (queue) After - cmd(0x%lx) scb->cmd(0x%lx) pos(%d).\n",
            (long) cmd, (long) scb->cmd, scb->position);
 #endif;
-    restore_flags(flags);
+    restore_flags(processor_flags);
   }
   return (0);
 }
@@ -5108,21 +5274,17 @@ static int
 aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
 {
   struct aic7xxx_scb  *scb;
-  long flags;
   unsigned char bus_state;
   int base, result = -1;
   char channel;
 
-  scb = &(p->scb_array[aic7xxx_position(cmd)]);
+  scb = (p->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
 
   channel = scb->target_channel_lun & SELBUSB ? 'B': 'A';
   if ((cmd == scb->cmd) && (scb->state & SCB_IN_PROGRESS))
   {
 
-    save_flags(flags);
-    cli();
-
     if (scb->state & SCB_IN_PROGRESS)
     {
       /*
@@ -5203,7 +5365,7 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
         * too much time, so we try the bus device reset there first.
         */
        active_scb = inb(SCBPTR + base);
-       active_scbp = &(p->scb_array[inb(SCB_TAG + base)]);
+       active_scbp = (p->scb_array[inb(SCB_TAG + base)]);
        control = inb(SCB_CONTROL + base);
 
        /*
@@ -5303,7 +5465,11 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
        }
       }
     }
-    restore_flags(flags);
+  }
+  /* Make sure the sequencer is unpaused upon return. */
+  if (result == -1)
+  {
+    UNPAUSE_SEQUENCER(p);
   }
   return (result);
 }
@@ -5324,7 +5490,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
   int    base, result;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
-  scb = &(p->scb_array[aic7xxx_position(cmd)]);
+  scb = (p->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
 
 #ifdef AIC7XXX_DEBUG_ABORT
@@ -5369,9 +5535,10 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
   struct aic7xxx_host *p;
   int    base, found, tindex, min_target, max_target, result = -1;
   char   channel = 'A';
+  unsigned long processor_flags;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
-  scb = &(p->scb_array[aic7xxx_position(cmd)]);
+  scb = (p->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
   channel = cmd->channel ? 'B': 'A';
   tindex = (cmd->channel << 4) | cmd->target;
@@ -5380,10 +5547,20 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
   printk("aic7xxx: (reset) target/channel %d/%d\n", cmd->target, cmd->channel);
 #endif
 
+  /* 
+   * This routine is called by scsi.c, in which case the interrupts
+   * very well may be on when we are called.  As such, we need to save
+   * the flags to be sure, then turn interrupts off, and then call our
+   * various method funtions which all assume interrupts are off.
+   */
+  save_flags(processor_flags);
+  cli();
+
   if (scb->cmd != cmd)
     scb = NULL;
 
-  if (!(flags & SCSI_RESET_SUGGEST_HOST_RESET) && (scb != NULL))
+  if (!(flags & (SCSI_RESET_SUGGEST_HOST_RESET | SCSI_RESET_SUGGEST_BUS_RESET)) 
+      && (scb != NULL))
   {
     /*
      * Attempt a bus device reset if commands have completed successfully
@@ -5439,7 +5616,8 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
     /*
      * The bus device reset failed; try resetting the channel.
      */
-    if (flags & SCSI_RESET_ASYNCHRONOUS)
+    if (!(flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
+        && (flags & SCSI_RESET_ASYNCHRONOUS))
     {
       if (scb == NULL)
       {
@@ -5458,6 +5636,10 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
 
     if (result == -1)
     {
+      /*
+       * The reset channel function assumes that the sequencer is paused.
+       */
+      PAUSE_SEQUENCER(p);
       found = aic7xxx_reset_channel(p, channel, TRUE);
 
       /*
@@ -5506,6 +5688,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
       result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
     }
   }
+  restore_flags(processor_flags);
   return (result);
 }
 
index 77cfc988e67c7db5fc74b6b3abc8ee39ca0e3430..98d4b95459380769c90bacf214a6998935fb2dee 100644 (file)
@@ -28,7 +28,7 @@
  *
  *-M*************************************************************************/
 
-VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 3.1 1996/07/23 03:37:26 deang Exp $"
+VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 4.0 1996/10/13 08:23:42 deang Exp $"
 
 #ifdef linux
 #include "aic7xxx_reg.h"
@@ -402,18 +402,8 @@ dma_finish2:
        test    DFCNTRL,HDMAENACK jnz dma_finish2
 
 /*
- * Copy data from FIFO into SCB data pointer and data count.  This assumes
- * that the struct scatterlist has this structure (this and sizeof(struct
- * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
- *
- *     struct scatterlist {
- *             char *address;          four bytes, little-endian order
- *             ...                     four bytes, ignored
- *             unsigned short length;  two bytes, little-endian order
- *     }
- *
- *
- * In FreeBSD, the scatter list entry is only 8 bytes.
+ * Copy data from FIFO into SCB data pointer and data count.  In
+ * both FreeBSD and Linux, the scatter list entry is 8 bytes.
  * 
  * struct ahc_dma_seg {
  *       physaddr addr;                  four bytes, little-endian order
@@ -425,16 +415,6 @@ dma_finish2:
        mov     HADDR1,DFDAT
        mov     HADDR2,DFDAT
        mov     HADDR3,DFDAT
-/*
- * For Linux, we must throw away four bytes since there is a 32bit gap
- * in the middle of a struct scatterlist.
- */
-#ifdef linux
-       mov     NONE,DFDAT
-       mov     NONE,DFDAT
-       mov     NONE,DFDAT
-       mov     NONE,DFDAT
-#endif
        mov     HCNT0,DFDAT
        mov     HCNT1,DFDAT
        mov     HCNT2,DFDAT
index a18888c8b3965d55f7136618d3354471cc38e665..a968c324f929cb264b23cc8e76a1cc880eb29ec1 100644 (file)
@@ -24,7 +24,7 @@
  *
  *  Dean W. Gehnert, deang@teleport.com, 05/01/96
  *
- *  $Id: aic7xxx_proc.c,v 3.2 1996/07/23 03:37:26 deang Exp $
+ *  $Id: aic7xxx_proc.c,v 4.0 1996/10/13 08:23:42 deang Exp $
  *-M*************************************************************************/
 
 #define BLS buffer + len + size
@@ -172,7 +172,7 @@ aic7xxx_proc_info(char *buffer, char **start, off_t offset, int length,
   size += sprintf(BLS, "               Base IO: %#.4x\n", p->base);
   size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
   size += sprintf(BLS, "                  SCBs: Used %d, HW %d, Page %d\n",
-      p->numscbs, p->maxhscbs, p->maxscbs);
+      p->scb_link->numscbs, p->maxhscbs, p->maxscbs);
   size += sprintf(BLS, "            Interrupts: %d", p->isr_count);
   if (p->chip_type == AIC_777x)
   {
index 99c80dcf2bacb54c546e1d7d53af2e8d124f49a4..d26a0c20e6749ee694a76dc1703639b8c437e03c 100644 (file)
@@ -20,7 +20,7 @@
  *
  * This version corresponds to version 1.12 of FreeBSDs aic7xxx_reg.h
  *
- * $Id: aic7xxx_reg.h,v 3.1 1996/07/23 03:37:26 deang Exp $
+ * $Id: aic7xxx_reg.h,v 4.0 1996/10/13 08:23:42 deang Exp $
  *-M*************************************************************************/
 
 /*
 #define        SCB_NEXT                0x0ba
 #define        SCB_PREV                0x0bb
 
-#ifdef linux
-#define        SG_SIZEOF               0x0c            /* sizeof(struct scatterlist) */
-#else
 #define        SG_SIZEOF               0x08            /* sizeof(struct ahc_dma) */
-#endif
 
 /* --------------------- AHA-2840-only definitions -------------------- */
 
index 3a28581c3987f36d7203ad5d68d8237be731f2a2..40ebe5fc470cdac22682c2b794b18a937fbcd3b4 100644 (file)
@@ -38,10 +38,10 @@ extern inline void down(struct semaphore * sem)
 #ifdef __SMP__
                "lock ; "
 #endif
-               "decl %0\n\t"
+               "decl 0(%0)\n\t"
                "js " SYMBOL_NAME_STR(down_failed)
                :/* no outputs */
-               :"m" (sem->count), "c" (sem)
+               :"c" (sem)
                :"ax","dx","memory");
 }
 
@@ -59,11 +59,11 @@ extern inline void up(struct semaphore * sem)
 #ifdef __SMP__
                "lock ; "
 #endif
-               "incl %0\n\t"
+               "incl 0(%0)\n\t"
                "jle " SYMBOL_NAME_STR(up_wakeup)
                "\n1:"
                :/* no outputs */
-               :"m" (sem->count), "c" (sem)
+               :"c" (sem)
                :"ax", "dx", "memory");
 }
 
index 32ddeeb653320b557175f9bd21d75664935c9f62..0cf05e266e33ded43261ff4fe116efb0432674e6 100644 (file)
 #define PCI_DEVICE_ID_ADAPTEC_7850     0x5078
 #define PCI_DEVICE_ID_ADAPTEC_7855     0x5578
 #define PCI_DEVICE_ID_ADAPTEC_7860     0x6078
+#define PCI_DEVICE_ID_ADAPTEC_7861     0x6178
 #define PCI_DEVICE_ID_ADAPTEC_7870     0x7078
 #define PCI_DEVICE_ID_ADAPTEC_7871     0x7178
 #define PCI_DEVICE_ID_ADAPTEC_7872     0x7278
index 4dd4be0552a85c6c2eea17a272c03414922a343c..cdf78b14a6a3aa83e5f1c650d3e7eaef3755ea51 100644 (file)
@@ -673,6 +673,7 @@ static int inet_create(struct socket *sock, int protocol)
        sk->rcvbuf = SK_RMEM_MAX;
        sk->rto = TCP_TIMEOUT_INIT;             /*TCP_WRITE_TIME*/
        sk->cong_window = 1; /* start with only sending one packet at a time. */
+       sk->ssthresh = 0x7fffffff;
        sk->priority = 1;
        sk->state = TCP_CLOSE;
 
index 1d53c61678d20772180d030aac262dbbd567cede..eaa74a6387d62ded61bc2d09ec75d0ec414a5327 100644 (file)
@@ -264,8 +264,12 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
                if (iph->protocol == IPPROTO_ICMP)
                {
                        if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0)
+                       {
+                               if (rt)
+                                       ip_rt_put(rt);
                                /* Problem - ie bad checksum */
                                return -1;
+                       }
 
                        if (fw_res)
                                /* ICMP matched - skip firewall */
index 393d0241c8fa7780cf936c5c14ab5c3dd49b0c8f..e27ae0c8384e70d8e36d0fcac70facacadd32ebb 100644 (file)
@@ -873,6 +873,8 @@ static void wait_for_tcp_memory(struct sock * sk)
                sk->socket->flags &= ~SO_NOSPACE;
                add_wait_queue(sk->sleep, &wait);
                for (;;) {
+                       if (current->signal & ~current->blocked)
+                               break;
                        current->state = TASK_INTERRUPTIBLE;
                        if (tcp_memory_free(sk))
                                break;