]> git.neil.brown.name Git - history.git/commitdiff
Import 2.2.12pre8 2.2.12pre8
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:19:33 +0000 (15:19 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:19:33 +0000 (15:19 -0500)
Documentation/Configure.help
Documentation/sound/solo1 [new file with mode: 0644]
arch/alpha/kernel/alpha_ksyms.c
drivers/scsi/Config.in
drivers/scsi/megaraid.c
drivers/scsi/megaraid.h
include/net/ip_masq.h
net/ipv4/ip_masq.c
net/ipv4/ip_vs.c
sound/solo1 [new file with mode: 0644]

index 0707cacf2cb06e3500e6730c1c4def8a161b488a..0efe43182e959b60000a47a78311bb4a66e585a2 100644 (file)
@@ -4704,8 +4704,8 @@ CONFIG_SCSI_AM53C974
 
 AMI MegaRAID support
 CONFIG_SCSI_MEGARAID
-  This driver supports the AMI MegaRAID 428 and 438 (and maybe 466)
-  SCSI host adapters. 
+  This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490
+  and 467 SCSI host adapters. 
 
   If you want to compile this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -9936,6 +9936,15 @@ CONFIG_SOUND_ES1371_GAMEPORT
   Leave the default 200 unless you have a joystick not attached
   to your sound card.
 
+ESS Solo1 based PCI sound cards (eg. SC1938)
+CONFIG_SOUND_ESSSOLO1
+  Say Y or M if you have a PCI sound card utilizing the ESS Technology
+  Solo1 chip. To find out if your sound card uses a
+  Solo1 chip without removing your computer's cover, use
+  lspci -n and look for the PCI ID 125D:1969. This driver 
+  differs slightly from OSS/Free, so PLEASE READ
+  Documentation/sound/solo1.
+
 S3 SonicVibes based PCI sound cards
 CONFIG_SOUND_SONICVIBES
   Say Y or M if you have a PCI sound card utilizing the S3
diff --git a/Documentation/sound/solo1 b/Documentation/sound/solo1
new file mode 100644 (file)
index 0000000..1c0a641
--- /dev/null
@@ -0,0 +1,48 @@
+ALaw/uLaw sample formats
+------------------------
+
+This driver does not support the ALaw/uLaw sample formats.
+ALaw is the default mode when opening a sound device
+using OSS/Free. The reason for the lack of support is
+that the hardware does not support these formats, and adding
+conversion routines to the kernel would lead to very ugly
+code in the presence of the mmap interface to the driver.
+And since xquake uses mmap, mmap is considered important :-)
+and no sane application uses ALaw/uLaw these days anyway.
+In short, playing a Sun .au file as follows:
+
+cat my_file.au > /dev/dsp
+
+does not work. Instead, you may use the play script from
+Chris Bagwell's sox-12.14 package (or later, available from the URL
+below) to play many different audio file formats.
+The script automatically determines the audio format
+and does do audio conversions if necessary.
+http://home.sprynet.com/sprynet/cbagwell/projects.html
+
+
+Blocking vs. nonblocking IO
+---------------------------
+
+Unlike OSS/Free this driver honours the O_NONBLOCK file flag
+not only during open, but also during read and write.
+This is an effort to make the sound driver interface more
+regular. Timidity has problems with this; a patch
+is available from http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html.
+(Timidity patched will also run on OSS/Free).
+
+
+MIDI UART
+---------
+
+The driver supports a simple MIDI UART interface, with
+no ioctl's supported.
+
+
+MIDI synthesizer
+----------------
+
+The card has an OPL compatible FM synthesizer.
+
+Thomas Sailer
+sailer@ife.ee.ethz.ch
index a2e4db1c681983ea441ba4beab310a16c59bcf9b..2c22c0c4bfd222fcabd6a60617023e14c01ac263 100644 (file)
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(_writew);
 EXPORT_SYMBOL(_writel);
 EXPORT_SYMBOL(_memcpy_fromio);
 EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_io);
+EXPORT_SYMBOL(_memset_c_io);
 EXPORT_SYMBOL(insb);
 EXPORT_SYMBOL(insw);
 EXPORT_SYMBOL(insl);
index e5c31c787e25ee8aeabb2b465d887f82e57d3836..7f6e73a2fbdb33da2b8719f6d93ef3fe654f6a0b 100644 (file)
@@ -34,9 +34,6 @@ dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
 dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
 dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
 dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI
-if [ "$CONFIG_SCSI_MEGARAID" != "n" ]; then
-    bool '   Concurrent IO commands on MegaRAID' CONFIG_MEGARAID_MULTI_IO
-fi
 
 dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
 if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
index 23ffc897094da9d873936d89e02d3ff7eafa64d3..5ccf0c8be8b6dfdb0d7fb6d76bd345bb6d86bb76 100644 (file)
@@ -9,14 +9,12 @@
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Version : 1.01
+ * Version : 1.04
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
- * Supported controllers: MegaRAID 418, 428, 438, 466, 762
+ * Supported controllers: MegaRAID 418, 428, 438, 466, 762, 467, 490
  * 
- * Maintainer: Jeff L Jones <jeffreyj@ami.com>
- *             Xi Shine Chen <xic@ami.com>
  * History:
  *
  * Version 0.90:
  *     Fixed bug in mega_cmd_done() for megamgr control commands,
  *       the host_byte in the result code from the scsi request to 
  *       scsi midlayer is set to DID_BAD_TARGET when adapter's 
- *       returned codes are 0xF0 and oxF4.  
+ *       returned codes are 0xF0 and 0xF4.  
+ *
+ * Version 1.02:
+ *     Fixed the tape drive bug by extending the adapter timeout value
+ *       for passthrough command to 60 seconds in mega_build_cmd(). 
+ *
+ * Version 1.03:
+ *    Fixed Madrona support.
+ *    Changed the adapter timeout value from 60 sec in 1.02 to 10 min
+ *      for bigger and slower tape drive.
+ *    Added driver version printout at driver loadup time
+ *
+ * Version 1.04
+ *    Added code for 40 ld FW support. 
+ *    Added new ioctl command 0x81 to support NEW_READ/WRITE_CONFIG with
+ *      data area greater than 4 KB, which is the upper bound for data
+ *      tranfer through scsi_ioctl interface.
+ *    The addtional 32 bit field for 64bit address in the newly defined
+ *      mailbox64 structure is set to 0 at this point.
  *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
  *
- *     Timeout period for mid scsi layer is too short for
- *     this controller.  Must be increased or Aborts will occur.
+ *     Timeout period for upper scsi layer, i.e. SD_TIMEOUT in
+ *     /drivers/scsi/sd.c, is too short for this controller. SD_TIMEOUT
+ *     value must be increased to (30 * HZ) otherwise false timeouts 
+ *     will occur in the upper layer.
  *
  *===================================================================*/
 
 #define CRLFSTR "\n"
+#define IOCTL_CMD_NEW  0x81
+
+#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -148,6 +169,7 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver");
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/uaccess.h>
 
 #include "sd.h"
 #include "scsi.h"
@@ -213,22 +235,22 @@ typedef struct {
   spin_unlock_irqrestore(&mega_lock,cpuflag);\
 };
 
-u_long RDINDOOR (mega_host_config * megaCfg)
+u32 RDINDOOR (mega_host_config * megaCfg)
 {
   return readl (megaCfg->base + 0x20);
 }
 
-void WRINDOOR (mega_host_config * megaCfg, u_long value)
+void WRINDOOR (mega_host_config * megaCfg, u32 value)
 {
   writel (value, megaCfg->base + 0x20);
 }
 
-u_long RDOUTDOOR (mega_host_config * megaCfg)
+u32 RDOUTDOOR (mega_host_config * megaCfg)
 {
   return readl (megaCfg->base + 0x2C);
 }
 
-void WROUTDOOR (mega_host_config * megaCfg, u_long value)
+void WROUTDOOR (mega_host_config * megaCfg, u32 value)
 {
   writel (value, megaCfg->base + 0x2C);
 }
@@ -244,7 +266,7 @@ static int megaIssueCmd (mega_host_config * megaCfg,
                         mega_scb * scb,
                         int intr);
 static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
-                        u_long * buffer, u_long * length);
+                        u32 * buffer, u32 * length);
 
 static int mega_busyWaitMbox(mega_host_config *);
 static void mega_runpendq (mega_host_config *);
@@ -252,6 +274,9 @@ static void mega_rundoneq (void);
 static void mega_cmd_done (mega_host_config *, mega_scb *, int);
 static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
 static inline void freeSgList(mega_host_config *megaCfg);
+static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,
+                                    mega_Enquiry3 *enquiry3,
+                                    megaRaidProductInfo *productInfo );
 
 /* set SERDEBUG to 1 to enable serial debugging */
 #define SERDEBUG 0
@@ -269,9 +294,9 @@ static int ser_printk (const char *fmt,...);
  *================================================================
  */
 
-/*  Use "megaraid=skipXX" to prohibit driver from scanning XX scsi id
-     on each channel.  Used for Madrona motherboard, where SAF_TE
-     processor id cannot be scanned */
+/*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
+    XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
+    processor id cannot be scanned */
 static char *megaraid;
 #if LINUX_VERSION_CODE > 0x20100
 #ifdef MODULE
@@ -281,10 +306,10 @@ MODULE_PARM(megaraid, "s");
 static int skip_id;
 
 static int numCtlrs = 0;
-static mega_host_config *megaCtlrs[12] = {0};
+static mega_host_config *megaCtlrs[FC_MAX_CHANNELS] = {0};
 
 #if DEBUG
-static u_long maxCmdTime = 0;
+static u32 maxCmdTime = 0;
 #endif
 
 static mega_scb *pLastScb = NULL;
@@ -512,8 +537,8 @@ static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
        while(1);
   }
 
-  islogical = (SCpnt->channel == megaCfg->host->max_channel &&
-              SCpnt->target == 0);
+  islogical = (SCpnt->channel == megaCfg->host->max_channel);
+
   if (SCpnt->cmnd[0] == INQUIRY &&
       ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
       !islogical) {
@@ -523,8 +548,7 @@ static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
 /* clear result; otherwise, success returns corrupt value */ 
  SCpnt->result = 0;  
 
-if (SCpnt->cmnd[0] & 0x80)     /* ioctl from megamgr */{
-    /*printk(KERN_WARNING "***megamgr cmnd status= %x h\n ", status); */
+if ((SCpnt->cmnd[0] & 0x80) ) {/* i.e. ioctl cmd such as 0x80, 0x81 of megamgr*/
     switch (status) {
       case 0xF0:
       case 0xF4:
@@ -556,11 +580,15 @@ else{
     SCpnt->result |= (DID_BUS_BUSY << 16)|status;
     break;
   default: 
-    SCpnt->result |= (DID_BAD_TARGET << 16);
+    SCpnt->result |= (DID_BAD_TARGET << 16)|status;
     break;
   }
  }
-  freeSCB(megaCfg, pScb);
+  if ( SCpnt->cmnd[0]!=IOCTL_CMD_NEW ) 
+  /* not IOCTL_CMD_NEW SCB, freeSCB()*/
+  /* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
+   * after copy data back to user space*/
+     freeSCB(megaCfg, pScb);
 
   /* Add Scsi_Command to end of completed queue */
   ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
@@ -582,18 +610,14 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
   mega_passthru *pthru;
   long seg;
   char islogical;
+  char lun = SCpnt->lun;
 
-  if (SCpnt == NULL) {
-       printk("NULL SCpnt in mega_build_cmd!\n");
-       while(1);
-  }
-
-  if (SCpnt->cmnd[0] & 0x80)   /* ioctl from megamgr */
+  if ((SCpnt->cmnd[0] == 0x80)  || (SCpnt->cmnd[0] == IOCTL_CMD_NEW) )  /* ioctl */
     return mega_ioctl (megaCfg, SCpnt);
+  islogical = (SCpnt->channel == megaCfg->host->max_channel);
 
-  islogical = (SCpnt->channel == megaCfg->host->max_channel && SCpnt->target == 0);
-
-  if (!islogical && SCpnt->lun != 0) {
+  if (!islogical && lun != 0) {
     SCpnt->result = (DID_BAD_TARGET << 16);
     callDone (SCpnt);
     return NULL;
@@ -605,6 +629,16 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
        return NULL;
   }
 
+  if ( islogical ) {
+       lun = (SCpnt->target * 8) + lun;
+#if 1
+        if ( lun > FC_MAX_LOGICAL_DRIVES ){
+            SCpnt->result = (DID_BAD_TARGET << 16);
+            callDone (SCpnt);
+            return NULL;
+        }
+#endif
+  }
   /*-----------------------------------------------------
    *
    *               Logical drive commands
@@ -641,7 +675,7 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
       pthru->ars = 1;
       pthru->reqsenselen = 14;
       pthru->islogical = 1;
-      pthru->logdrv = SCpnt->lun;
+      pthru->logdrv = lun;
       pthru->cdblen = SCpnt->cmd_len;
       pthru->dataxferaddr = virt_to_bus (SCpnt->request_buffer);
       pthru->dataxferlen = SCpnt->request_bufflen;
@@ -666,37 +700,37 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
       mbox = (mega_mailbox *) & pScb->mboxData;
 
       memset (mbox, 0, sizeof (pScb->mboxData));
-      mbox->logdrv = SCpnt->lun;
+      mbox->logdrv = lun;
       mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
        MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE;
 
       /* 6-byte */
       if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
        mbox->numsectors =
-         (u_long) SCpnt->cmnd[4];
+         (u32) SCpnt->cmnd[4];
        mbox->lba =
-         ((u_long) SCpnt->cmnd[1] << 16) |
-         ((u_long) SCpnt->cmnd[2] << 8) |
-         (u_long) SCpnt->cmnd[3];
+         ((u32) SCpnt->cmnd[1] << 16) |
+         ((u32) SCpnt->cmnd[2] << 8) |
+         (u32) SCpnt->cmnd[3];
        mbox->lba &= 0x1FFFFF;
       }
 
       /* 10-byte */
       if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
        mbox->numsectors =
-         (u_long) SCpnt->cmnd[8] |
-         ((u_long) SCpnt->cmnd[7] << 8);
+         (u32) SCpnt->cmnd[8] |
+         ((u32) SCpnt->cmnd[7] << 8);
        mbox->lba =
-         ((u_long) SCpnt->cmnd[2] << 24) |
-         ((u_long) SCpnt->cmnd[3] << 16) |
-         ((u_long) SCpnt->cmnd[4] << 8) |
-         (u_long) SCpnt->cmnd[5];
+         ((u32) SCpnt->cmnd[2] << 24) |
+         ((u32) SCpnt->cmnd[3] << 16) |
+         ((u32) SCpnt->cmnd[4] << 8) |
+         (u32) SCpnt->cmnd[5];
       }
 
       /* Calculate Scatter-Gather info */
       mbox->numsgelements = build_sglist (megaCfg, pScb,
-                                         (u_long *) & mbox->xferaddr,
-                                         (u_long *) & seg);
+                                         (u32 *) & mbox->xferaddr,
+                                         (u32 *) & seg);
 
       return pScb;
 
@@ -723,18 +757,20 @@ static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
 
     memset (mbox, 0, sizeof (pScb->mboxData));
     memset (pthru, 0, sizeof (mega_passthru));
-    pthru->timeout = 0;
+    pthru->timeout = 2; /*set adapter timeout value to 10 min. for tape drive*/
+                       /* 0=6sec/1=60sec/2=10min/3=3hrs */
     pthru->ars = 1;
     pthru->reqsenselen = 14;
     pthru->islogical = 0;
-    pthru->channel = SCpnt->channel;
-    pthru->target = SCpnt->target;
+    pthru->channel = (megaCfg->flag & BOARD_40LD) ? 0 : SCpnt->channel;
+    pthru->target = (megaCfg->flag & BOARD_40LD) ? /*BOARD_40LD*/
+                     (SCpnt->channel<<4)|SCpnt->target : SCpnt->target;
     pthru->cdblen = SCpnt->cmd_len;
     memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
     pthru->numsgelements = build_sglist (megaCfg, pScb,
-                                        (u_long *) & pthru->dataxferaddr,
-                                        (u_long *) & pthru->dataxferlen);
+                                        (u32 *) & pthru->dataxferaddr,
+                                        (u32 *) & pthru->dataxferlen);
 
     /* Initialize mailbox */
     mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
@@ -754,6 +790,7 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
   mega_ioctl_mbox *mbox;
   mega_mailbox *mailbox;
   mega_passthru *pthru;
+  u8 *mboxdata;
   long seg;
   unsigned char *data = (unsigned char *)SCpnt->request_buffer;
   int i;
@@ -772,6 +809,7 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
   printk("......\n");
 #endif
 
+  mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
   mailbox = (mega_mailbox *) & pScb->mboxData;
   memset (mailbox, 0, sizeof (pScb->mboxData));
@@ -793,10 +831,9 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
     mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
     mailbox->xferaddr = virt_to_bus (pthru);
 
-
     pthru->numsgelements = build_sglist (megaCfg, pScb,
-                                        (u_long *) & pthru->dataxferaddr,
-                                        (u_long *) & pthru->dataxferlen);
+                                        (u32 *) & pthru->dataxferaddr,
+                                        (u32 *) & pthru->dataxferlen);
 
     for (i=0;i<(SCpnt->request_bufflen-cdblen-7);i++) {
        data[i] = data[i+cdblen+7];
@@ -806,18 +843,60 @@ static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
   }
   /* else normal (nonpassthru) command */
 
+  if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) { 
+            /* use external data area for large xfers  */
+     /* If cmnd[0] is set to IOCTL_CMD_NEW then *
+      *   cmnd[4..7] = external user buffer     *
+      *   cmnd[8..11] = length of buffer        *
+      *                                         */
+      char *kern_area;
+      char *user_area = *((char **)&SCpnt->cmnd[4]);
+      u32 xfer_size = *((u32 *)&SCpnt->cmnd[8]);
+      if (verify_area(VERIFY_READ, user_area, xfer_size)) {
+          printk("megaraid: Got bad user address.\n");
+          SCpnt->result = (DID_ERROR << 16);
+          callDone (SCpnt);
+          return NULL;
+      }
+      kern_area = kmalloc(xfer_size, GFP_ATOMIC | GFP_DMA);
+      if (kern_area == NULL) {
+          printk("megaraid: Couldn't allocate kernel mem.\n");
+         SCpnt->result = (DID_ERROR << 16);
+         callDone (SCpnt);
+         return NULL;
+      }
+      copy_from_user(kern_area,user_area,xfer_size);
+      pScb->kern_area = kern_area;
+  }
+
   mbox->cmd = data[0];
   mbox->channel = data[1];
   mbox->param = data[2];
   mbox->pad[0] = data[3];
   mbox->logdrv = data[4];
 
-  mbox->numsgelements = build_sglist (megaCfg, pScb,
-                                     (u_long *) & mbox->xferaddr,
-                                     (u_long *) & seg);
+  if(SCpnt->cmnd[0] == IOCTL_CMD_NEW) {
+      if(data[0]==DCMD_FC_CMD){ /*i.e. 0xA1, then override some mbox data */
+          *(mboxdata+0) = data[0]; /*mailbox byte 0: DCMD_FC_CMD*/
+          *(mboxdata+2) = data[2]; /*sub command*/
+          *(mboxdata+3) = 0;       /*number of elements in SG list*/
+          mbox->xferaddr           /*i.e. mboxdata byte 0x8 to 0xb*/
+                        = virt_to_bus(pScb->kern_area);
+      }
+      else{
+         mbox->xferaddr = virt_to_bus(pScb->kern_area);
+         mbox->numsgelements = 0;
+      }
+  } 
+  else {
 
-  for (i=0;i<(SCpnt->request_bufflen-6);i++) {
-     data[i] = data[i+6];
+      mbox->numsgelements = build_sglist (megaCfg, pScb,
+                                     (u32 *) & mbox->xferaddr,
+                                     (u32 *) & seg);
+
+      for (i=0;i<(SCpnt->request_bufflen-6);i++) {
+          data[i] = data[i+6];
+      }
   }
 
   return (pScb);
@@ -846,7 +925,7 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
-  u_long dword;
+  u32 dword;
   mega_mailbox *mbox;
   mega_scb *pScb;
   long flags;
@@ -930,8 +1009,13 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
          printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
        }
 
+        if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW) 
+        {    /* external user buffer */
+           up(&pScb->sem);
+        }
        /* Mark command as completed */
        mega_cmd_done(megaCfg, pScb, qStatus);
+
       }
 
     }
@@ -945,6 +1029,7 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
     spin_lock_irqsave(&mega_lock, flags);
     mega_runpendq(megaCfg);
     spin_unlock_irqrestore(&mega_lock,flags);
+
   }
 
 #if LINUX_VERSION_CODE >= 0x20100
@@ -978,6 +1063,11 @@ static int mega_busyWaitMbox (mega_host_config * megaCfg)
  *   u_char *mboxData - Mailbox area, 16 bytes
  *   mega_scb *pScb   - SCB posting (or NULL if N/A)
  *   int intr         - if 1, interrupt, 0 is blocking
+ * Return Value: (added on 7/26 for 40ld/64bit)
+ *   -1: the command was not actually issued out
+ *   othercases:
+ *     intr==0, return ScsiStatus, i.e. mbox->status
+ *     intr==1, return 0 
  *=====================================================
  */
 static int megaIssueCmd (mega_host_config * megaCfg,
@@ -987,12 +1077,16 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 {
   mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
   u_char byte;
-  u_long cmdDone;
+  u32 cmdDone;
   Scsi_Cmnd *SCpnt;
+  u32 phys_mbox;
+  u8 retval=-1;
 
   mboxData[0x1] = (pScb ? pScb->idx + 1: 0x0);   /* Set cmdid */
   mboxData[0xF] = 1;           /* Set busy */
 
+  phys_mbox = virt_to_bus (megaCfg->mbox);
+
 #if 0
   if (intr && mbox->busy) {
     return 0;
@@ -1005,7 +1099,7 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 
   /* Wait until mailbox is free */
   while (mega_busyWaitMbox (megaCfg)) {
-    printk("Blocked mailbox!!\n");
+    printk("Blocked mailbox......!!\n");
     udelay(1000);
 
 #if DEBUG
@@ -1022,12 +1116,13 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 
     SCpnt->result = (DID_ABORT << 16);
     callDone(SCpnt);
-    return 0;
+    return -1;
   }
 
   pLastScb = pScb;
 
   /* Copy mailbox data into host structure */
+  megaCfg->mbox64->xferSegment = 0;
   memcpy (mbox, mboxData, 16);
 
   /* Kick IO */
@@ -1037,20 +1132,22 @@ static int megaIssueCmd (mega_host_config * megaCfg,
     if (megaCfg->flag & BOARD_QUARTZ) {
        mbox->mraid_poll = 0;
       mbox->mraid_ack = 0;
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
+      WRINDOOR (megaCfg, phys_mbox | 0x1);
     }
     else {
       ENABLE_INTR (megaCfg->host->io_port);
       ISSUE_COMMAND (megaCfg->host->io_port);
     }
     pScb->state = SCB_ISSUED;
+
+    retval=0;
   }
   else {                       /* Issue non-ISR (blocking) command */
     disable_irq(megaCfg->host->irq);
     if (megaCfg->flag & BOARD_QUARTZ) {
       mbox->mraid_poll = 0;
       mbox->mraid_ack = 0;
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
+      WRINDOOR (megaCfg, phys_mbox | 0x1);
 
       while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234);
       WROUTDOOR (megaCfg, cmdDone);
@@ -1060,7 +1157,7 @@ static int megaIssueCmd (mega_host_config * megaCfg,
        mega_rundoneq ();
       }
 
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      WRINDOOR (megaCfg, phys_mbox | 0x2);
       while (RDINDOOR (megaCfg) & 0x2);
 
     }
@@ -1085,20 +1182,21 @@ static int megaIssueCmd (mega_host_config * megaCfg,
 
     }
     enable_irq(megaCfg->host->irq);
+    retval=mbox->status;
   }
   while (mega_busyWaitMbox (megaCfg)) {
-    printk("Blocked mailbox on exit!\n");
+    printk("Blocked mailbox on exit......!\n");
     udelay(1000);
   }
 
-  return 0;
+  return retval;
 }
 
 /*-------------------------------------------------------------------
  * Copies data to SGLIST
  *-------------------------------------------------------------------*/
 static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
-             u_long * buffer, u_long * length)
+             u32 * buffer, u32 * length)
 {
   struct scatterlist *sgList;
   int idx;
@@ -1106,21 +1204,21 @@ static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
   /* Scatter-gather not used */
   if (scb->SCpnt->use_sg == 0) {
     *buffer = virt_to_bus (scb->SCpnt->request_buffer);
-    *length = (u_long) scb->SCpnt->request_bufflen;
+    *length = (u32) scb->SCpnt->request_bufflen;
     return 0;
   }
 
   sgList = (struct scatterlist *) scb->SCpnt->request_buffer;
   if (scb->SCpnt->use_sg == 1) {
     *buffer = virt_to_bus (sgList[0].address);
-    *length = (u_long) sgList[0].length;
+    *length = (u32) sgList[0].length;
     return 0;
   }
 
   /* Copy Scatter-Gather list info into controller structure */
   for (idx = 0; idx < scb->SCpnt->use_sg; idx++) {
     scb->sgList[idx].address = virt_to_bus (sgList[idx].address);
-    scb->sgList[idx].length = (u_long) sgList[idx].length;
+    scb->sgList[idx].length = (u32) sgList[idx].length;
   }
 
   /* Reset pointer and length fields */
@@ -1147,12 +1245,13 @@ static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
  *   10 01 numstatus byte
  *   11 01 status byte
  *--------------------------------------------------------------------*/
-static int mega_register_mailbox (mega_host_config * megaCfg, u_long paddr)
+static int mega_register_mailbox (mega_host_config * megaCfg, u32 paddr)
 {
   /* align on 16-byte boundry */
-  megaCfg->mbox = &megaCfg->mailbox;
-  megaCfg->mbox = (mega_mailbox *) ((((ulong) megaCfg->mbox) + 16) & 0xfffffff0);
-  paddr = (paddr + 16) & 0xfffffff0;
+  megaCfg->mbox = &megaCfg->mailbox64.mailbox;
+  megaCfg->mbox = (mega_mailbox *) ((((u32) megaCfg->mbox) + 16) & 0xfffffff0);
+  megaCfg->mbox64 = (mega_mailbox64 *) (megaCfg->mbox - 4);
+  paddr = (paddr + 4 + 16) & 0xfffffff0;
 
   /* Register mailbox area with the firmware */
   if (megaCfg->flag & BOARD_QUARTZ) {
@@ -1170,83 +1269,161 @@ static int mega_register_mailbox (mega_host_config * megaCfg, u_long paddr)
   return 0;
 }
 
+
+/*---------------------------------------------------------------------------
+ * mega_Convert8ldTo40ld() -- takes all info in AdapterInquiry structure and
+ * puts it into ProductInfo and Enquiry3 structures for later use
+ *---------------------------------------------------------------------------*/
+static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,
+                                    mega_Enquiry3 *enquiry3,
+                                    megaRaidProductInfo *productInfo )
+{
+        int i;
+
+        productInfo->MaxConcCmds = inquiry->AdpInfo.MaxConcCmds;
+        enquiry3->rbldRate = inquiry->AdpInfo.RbldRate;
+        productInfo->SCSIChanPresent = inquiry->AdpInfo.ChanPresent;
+        for (i=0;i<4;i++) {
+                productInfo->FwVer[i] = inquiry->AdpInfo.FwVer[i];
+                productInfo->BiosVer[i] = inquiry->AdpInfo.BiosVer[i];
+        }
+        enquiry3->cacheFlushInterval = inquiry->AdpInfo.CacheFlushInterval;
+        productInfo->DramSize = inquiry->AdpInfo.DramSize;
+
+        enquiry3->numLDrv = inquiry->LogdrvInfo.NumLDrv;
+        for (i=0;i<MAX_LOGICAL_DRIVES;i++) {
+                enquiry3->lDrvSize[i] = inquiry->LogdrvInfo.LDrvSize[i];
+                enquiry3->lDrvProp[i] = inquiry->LogdrvInfo.LDrvProp[i];
+                enquiry3->lDrvState[i] = inquiry->LogdrvInfo.LDrvState[i];
+        }
+
+        for (i=0;i<(MAX_PHYSICAL_DRIVES);i++) {
+                enquiry3->pDrvState[i] = inquiry->PhysdrvInfo.PDrvState[i];
+        }
+}
+
+
 /*-------------------------------------------------------------------
  * Issue an adapter info query to the controller
  *-------------------------------------------------------------------*/
 static int mega_i_query_adapter (mega_host_config * megaCfg)
 {
-  mega_RAIDINQ *adapterInfo;
+  mega_Enquiry3 *enquiry3Pnt;
   mega_mailbox *mbox;
   u_char mboxData[16];
-  u_long paddr;
+  u32 paddr;
+  u8 retval;
 
   spin_lock_init (&mega_lock);
 
-  /* Initialize adapter inquiry */
+  /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
   mbox = (mega_mailbox *) mboxData;
 
   memset ((void *) megaCfg->mega_buffer, 0, sizeof (megaCfg->mega_buffer));
   memset (mbox, 0, 16);
 
-  /* Initialize mailbox registers */
-  mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;
-  mbox->xferaddr = paddr;
+/*
+ * Try to issue Enquiry3 command 
+ * if not suceeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and 
+ * update enquiry3 structure
+ */
+  mbox->xferaddr = virt_to_bus ( (void*) megaCfg->mega_buffer); 
+             /* Initialize mailbox databuffer addr */
+  enquiry3Pnt = (mega_Enquiry3 *) megaCfg->mega_buffer; 
+             /* point mega_Enguiry3 to the data buf */
+
+  mboxData[0]=FC_NEW_CONFIG ;          /* i.e. mbox->cmd=0xA1 */
+  mboxData[2]=NC_SUBOP_ENQUIRY3;       /* i.e. 0x0F */
+  mboxData[3]=ENQ3_GET_SOLICITED_FULL; /* i.e. 0x02 */
 
   /* Issue a blocking command to the card */
-  megaIssueCmd (megaCfg, mboxData, NULL, 0);
+  if ( (retval=megaIssueCmd(megaCfg, mboxData, NULL, 0)) != 0 )
+  {  /* the adapter does not support 40ld*/
 
-  /* Initialize host/local structures with Adapter info */
-  adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
-  megaCfg->host->max_channel = adapterInfo->AdpInfo.ChanPresent;
-/*  megaCfg->host->max_id = adapterInfo->AdpInfo.MaxTargPerChan; */
-  megaCfg->host->max_id = 16; /* max targets/chan */
-  megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv;
+     mega_RAIDINQ adapterInquiryData;
+     mega_RAIDINQ *adapterInquiryPnt = &adapterInquiryData;
 
-#if 0
-  printk ("KERN_DEBUG ---- Logical drive info ----\n");
+     mbox->xferaddr = virt_to_bus ( (void*) adapterInquiryPnt);
+
+     mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;  /*issue old 0x05 command to adapter*/
+     /* Issue a blocking command to the card */;
+     retval=megaIssueCmd (megaCfg, mboxData, NULL, 0);
+
+     /*update Enquiry3 and ProductInfo structures with mega_RAIDINQ structure*/
+     mega_Convert8ldTo40ld(  adapterInquiryPnt, 
+                             enquiry3Pnt, 
+                             (megaRaidProductInfo * ) &megaCfg->productInfo );
+
+  }
+  else{ /* adapter supports 40ld */
+    megaCfg->flag |= BOARD_40LD;
+
+    /*get productInfo, which is static information and will be unchanged*/
+    mbox->xferaddr = virt_to_bus ( (void*) &megaCfg->productInfo );
+
+    mboxData[0]=FC_NEW_CONFIG ;         /* i.e. mbox->cmd=0xA1 */
+    mboxData[2]=NC_SUBOP_PRODUCT_INFO;  /* i.e. 0x0E */
+   
+    if( (retval=megaIssueCmd(megaCfg, mboxData, NULL, 0)) != 0  ) 
+        printk("ami:Product_info (0x0E) cmd failed with error: %d\n", retval);
+
+  }
+
+  megaCfg->host->max_channel = megaCfg->productInfo.SCSIChanPresent;
+  megaCfg->host->max_id = 16;              /* max targets per channel */
+    /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/ 
+  megaCfg->host->max_lun =              /* max lun */
+    (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; 
+
+  megaCfg->numldrv = enquiry3Pnt->numLDrv;
+  megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
+
+#if 0 
+  int i;
+  printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
   for (i = 0; i < megaCfg->numldrv; i++) {
-    printk ("%d: size: %ld prop: %x state: %x\n", i,
-           adapterInfo->LogdrvInfo.LDrvSize[i],
-           adapterInfo->LogdrvInfo.LDrvProp[i],
-           adapterInfo->LogdrvInfo.LDrvState[i]);
+    printk ("%d: size: %d prop: %x state: %x\n", i,
+           enquiry3Pnt->lDrvSize[i],
+           enquiry3Pnt->lDrvProp[i],
+           enquiry3Pnt->lDrvState[i]);
   }
+
   printk (KERN_DEBUG "---- Physical drive info ----\n");
-  for (i = 0; i < MAX_PHYSICAL_DRIVES; i++) {
+  for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
     if (i && !(i % 8))
       printk ("\n");
-    printk ("%d: %x   ", i, adapterInfo->PhysdrvInfo.PDrvState[i]);
+    printk ("%d: %x   ", i, enquiry3Pnt->pDrvState[i]);
   }
   printk ("\n");
 #endif
 
-  megaCfg->max_cmds = adapterInfo->AdpInfo.MaxConcCmds;
-
 #ifdef HP                      /* use HP firmware and bios version encoding */
   sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
-          adapterInfo->AdpInfo.FwVer[2],
-          adapterInfo->AdpInfo.FwVer[1] >> 8,
-          adapterInfo->AdpInfo.FwVer[1] & 0x0f,
-          adapterInfo->AdpInfo.FwVer[2] >> 8,
-          adapterInfo->AdpInfo.FwVer[2] & 0x0f);
+          megaCfg->productInfo.FwVer[2],
+          megaCfg->productInfo.FwVer[1] >> 8,
+          megaCfg->productInfo.FwVer[1] & 0x0f,
+          megaCfg->productInfo.FwVer[2] >> 8,
+          megaCfg->productInfo.FwVer[2] & 0x0f);
   sprintf (megaCfg->biosVer, "%c%d%d.%d%d",
-          adapterInfo->AdpInfo.BiosVer[2],
-          adapterInfo->AdpInfo.BiosVer[1] >> 8,
-          adapterInfo->AdpInfo.BiosVer[1] & 0x0f,
-          adapterInfo->AdpInfo.BiosVer[2] >> 8,
-          adapterInfo->AdpInfo.BiosVer[2] & 0x0f);
+          megaCfg->productInfo.BiosVer[2],
+          megaCfg->productInfo.BiosVer[1] >> 8,
+          megaCfg->productInfo.BiosVer[1] & 0x0f,
+          megaCfg->productInfo.BiosVer[2] >> 8,
+          megaCfg->productInfo.BiosVer[2] & 0x0f);
 #else
-  memcpy (megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
+  memcpy (megaCfg->fwVer, megaCfg->productInfo.FwVer, 4);
   megaCfg->fwVer[4] = 0;
 
-  memcpy (megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4);
+  memcpy (megaCfg->biosVer, megaCfg->productInfo.BiosVer, 4);
   megaCfg->biosVer[4] = 0;
 #endif
 
-  printk (KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
-         megaCfg->fwVer,
+  printk ("megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
+          megaCfg->fwVer,
          megaCfg->biosVer,
          megaCfg->numldrv);
+
   return 0;
 }
 
@@ -1267,15 +1444,15 @@ int megaraid_proc_info (char *buffer, char **start, off_t offset,
 }
 
 int findCard (Scsi_Host_Template * pHostTmpl,
-         u_short pciVendor, u_short pciDev,
+         u16 pciVendor, u16 pciDev,
          long flag)
 {
   mega_host_config *megaCfg;
   struct Scsi_Host *host;
   u_char pciBus, pciDevFun, megaIrq;
-  u_long megaBase;
-  u_short jdx,pciIdx = 0;
-  u_short numFound = 0;
+  u32 megaBase;
+  u16 pciIdx = 0;
+  u16 numFound = 0;
 
 #if LINUX_VERSION_CODE < 0x20100
   while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
@@ -1291,8 +1468,8 @@ int findCard (Scsi_Host_Template * pHostTmpl,
     pciBus = pdev->bus->number;
     pciDevFun = pdev->devfn;
 #endif
-    if (flag & BOARD_QUARTZ) {
-      u_short magic;
+    if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
+      u16 magic;
       pcibios_read_config_word (pciBus, pciDevFun,
                                PCI_CONF_AMISIG,
                                &magic);
@@ -1301,7 +1478,7 @@ int findCard (Scsi_Host_Template * pHostTmpl,
        continue;               /* not an AMI board */
       }
     }
-    printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
+    printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:func %d\n",
            pciVendor,
            pciDev,
            pciIdx, pciBus,
@@ -1323,6 +1500,7 @@ int findCard (Scsi_Host_Template * pHostTmpl,
     pciIdx++;
 
     if (flag & BOARD_QUARTZ) {
+
       megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
       megaBase = (long) ioremap (megaBase, 128);
     }
@@ -1336,7 +1514,7 @@ int findCard (Scsi_Host_Template * pHostTmpl,
     megaCfg = (mega_host_config *) host->hostdata;
     memset (megaCfg, 0, sizeof (mega_host_config));
 
-    printk (" scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
+    printk ("scsi%d : Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
            host->host_no, (u_int) megaBase, megaIrq);
 
     /* Copy resource info into structure */
@@ -1349,8 +1527,7 @@ int findCard (Scsi_Host_Template * pHostTmpl,
     megaCfg->host->io_port = megaBase;
     megaCfg->host->n_io_port = 16;
     megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
-    megaCtlrs[numCtlrs++] = megaCfg;
-
+    megaCtlrs[numCtlrs++] = megaCfg; 
     if (flag != BOARD_QUARTZ) {
       /* Request our IO Range */
       if (check_region (megaBase, 16)) {
@@ -1370,14 +1547,9 @@ int findCard (Scsi_Host_Template * pHostTmpl,
       continue;
     }
 
-    mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox));
+    mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox64));
     mega_i_query_adapter (megaCfg);
     
-    for(jdx=0; jdx<MAX_LOGICAL_DRIVES; jdx++) {
-      megaCfg->nReads[jdx] = 0;
-      megaCfg->nWrites[jdx] = 0;
-    }
-
     /* Initialize SCBs */
     if (initSCB (megaCfg)) {
       scsi_unregister (host);
@@ -1415,6 +1587,8 @@ int megaraid_detect (Scsi_Host_Template * pHostTmpl)
       skip_id = (skip_id > 15) ? -1 : skip_id;
   }
 
+  printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
+
   count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
   count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
   count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
@@ -1475,16 +1649,15 @@ const char * megaraid_info (struct Scsi_Host *pSHost)
 {
   static char buffer[512];
   mega_host_config *megaCfg;
-  mega_RAIDINQ *adapterInfo;
 
   megaCfg = (mega_host_config *) pSHost->hostdata;
-  adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
 
-  sprintf (buffer, "AMI MegaRAID %s %d commands %d targs %d chans",
+  sprintf (buffer, "AMI MegaRAID %s %d commands %d targs %d chans %d luns",
           megaCfg->fwVer,
-          adapterInfo->AdpInfo.MaxConcCmds,
+           megaCfg->productInfo.MaxConcCmds,
           megaCfg->host->max_id,
-          megaCfg->host->max_channel);
+          megaCfg->host->max_channel,
+           megaCfg->host->max_lun);
   return buffer;
 }
 
@@ -1514,9 +1687,13 @@ int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   if (!(megaCfg->flag & (1L << SCpnt->channel))) {
-    printk (KERN_INFO "scsi%d: scanning channel %c for devices.\n",
+    if (SCpnt->channel < SCpnt->host->max_channel)
+       printk (/*KERN_INFO*/ "scsi%d: scanning channel %c for devices.\n",
            megaCfg->host->host_no,
-           SCpnt->channel + 'A');
+           SCpnt->channel + '1');
+    else
+       printk(/*KERN_INFO*/ "scsi%d: scanning virtual channel for logical drives.\n", megaCfg->host->host_no);
+       
     megaCfg->flag |= (1L << SCpnt->channel);
   }
 
@@ -1540,6 +1717,7 @@ int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 
   /* Allocate and build a SCB request */
   if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
+              /*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
     /* Add SCB to the head of the pending queue */
     ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
 
@@ -1550,6 +1728,25 @@ int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
     else {
       printk("IRQ pend...\n");
     }
+
+    if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
+    {  /* user data from external user buffer */
+          char *user_area;
+          u32  xfer_size;
+
+          pScb->sem=MUTEX_LOCKED;
+          down(&pScb->sem);
+
+          user_area = *((char **)&pScb->SCpnt->cmnd[4]);
+          xfer_size = *((u32 *)&pScb->SCpnt->cmnd[8]);
+
+          copy_to_user(user_area,pScb->kern_area,xfer_size);
+
+          kfree(pScb->kern_area);
+
+          freeSCB(megaCfg, pScb);
+    }
+
   }
 
   spin_unlock_irqrestore(&mega_lock,flags);
@@ -1750,3 +1947,4 @@ Scsi_Host_Template driver_template = MEGARAID;
 
 #include "scsi_module.c"
 #endif
+
index 1e328a1558227afbd2032d3c1927f92a077a69c2..83fe02785b4719e92cd2f4d7f051ac69c4bb27ef 100644 (file)
@@ -9,6 +9,7 @@
 #define IN_ABORT                0x40000000L
 #define IN_RESET                0x20000000L
 #define BOARD_QUARTZ            0x08000000L
+#define BOARD_40LD              0x04000000L
 
 #define SCB_FREE     0x0
 #define SCB_ACTIVE   0x1
   }
 #endif
 
+
+/***********************************************************************
+ * Structure Declarations for the Firmware supporting 40 Logical Drives
+ * and 256 Physical Drives.
+ ***********************************************************************/
+
+#define FC_MAX_LOGICAL_DRIVES       40
+#define FC_MAX_LOG_DEVICES          FC_MAX_LOGICAL_DRIVES
+#define FC_MAX_SPAN_DEPTH           8
+#define FC_MAX_ROW_SIZE             32
+
+#define FC_MAX_CHANNELS             16
+#define FC_MAX_TARGETS_PER_CHANNEL  16
+#define FC_MAX_PHYSICAL_DEVICES     256
+
+#define FC_NEW_CONFIG               0xA1
+#define DCMD_FC_CMD                 0xA1
+  #define NC_SUBOP_PRODUCT_INFO       0x0E
+  #define NC_SUBOP_ENQUIRY3           0x0F
+       #define ENQ3_GET_SOLICITED_NOTIFY_ONLY  0x01
+       #define ENQ3_GET_SOLICITED_FULL         0x02
+       #define ENQ3_GET_UNSOLICITED            0x03
+
+
+/********************************************
+ * PRODUCT_INFO Strucure
+ ********************************************/
+
+#define SIG_40LOG_32STR_8SPN  0x00282008
+
+/* 
+ * Utilities declare this strcture size as 1024 bytes. So more fields can
+ * be added in future.
+ */
+
+struct MRaidProductInfo
+{
+   u32   DataSize; /* current size in bytes (not including resvd) */
+   u32   ConfigSignature;
+                         /* Current value is 0x00282008
+                          * 0x28=MAX_LOGICAL_DRIVES, 
+                          * 0x20=Number of stripes and 
+                          * 0x08=Number of spans */
+   u8   FwVer[16];         /* printable ASCI string */
+   u8   BiosVer[16];       /* printable ASCI string */
+   u8   ProductName[80];   /* printable ASCI string */
+
+   u8   MaxConcCmds;       /* Max. concurrent commands supported */
+   u8   SCSIChanPresent;   /* Number of SCSI Channels detected */
+   u8   FCLoopPresent;     /* Number of Fibre Loops detected */
+   u8   memType;           /* EDO, FPM, SDRAM etc */
+
+   u32   signature;
+   u16  DramSize;          /* In terms of MB */
+   u16  subSystemID;
+
+   u16  subSystemVendorID;
+   u8   numNotifyCounters;
+   u8   pad1k[889];       /* 135 + 889 resvd = 1024 total size */
+}__attribute__((packed));
+typedef struct MRaidProductInfo megaRaidProductInfo;
+
+/********************************************
+ * Standard ENQUIRY Strucure
+ ********************************************/
+struct FC_ADP_INFO
+{
+   u8  MaxConcCmds;         /* Max. concurrent commands supported. */
+   u8  RbldRate;            /* Rebuild Rate. Varies from 0%-100% */
+   u8  MaxTargPerChan;      /* Max. Targets supported per chan. */
+   u8  ChanPresent;         /* No. of Chans present on this adapter. */
+   u8  FwVer[4];            /* Firmware version. */
+   u16 AgeOfFlash;          /* No. of times FW has been downloaded. */
+   u8  ChipSetValue;        /* Contents of 0xC0000832 */
+   u8  DramSize;            /* In terms of MB */
+   u8  CacheFlushInterval;  /* In terms of Seconds */
+   u8  BiosVersion[4];
+   u8  BoardType;
+   u8  sense_alert;
+   u8  write_config_count;   /* Increase with evry configuration change */
+   u8  drive_inserted_count; /* Increase with every drive inserted */
+   u8  inserted_drive;       /* Channel: Id of inserted drive */
+   u8  battery_status;
+                           /*
+                              BIT 0 : battery module missing
+                              BIT 1 : VBAD
+                              BIT 2 : temp high
+                              BIT 3 : battery pack missing
+                              BIT 4,5 : 00 - charge complete
+                                        01 - fast charge in prog
+                                        10 - fast charge fail
+                                        11 - undefined
+                              BIt 6 : counter > 1000
+                              Bit 7 : undefined
+                           */
+   u8  dec_fault_bus_info;   /* was resvd */
+}__attribute__((packed));
+
+struct FC_LDRV_INFO
+{
+   u8  NumLDrv;      /* No. of Log. Drvs configured. */
+   u8  recon_state[FC_MAX_LOGICAL_DRIVES/8];    
+                                /* bit field for State of reconstruct */
+   u16 LDrvOpStatus[FC_MAX_LOGICAL_DRIVES/8];   
+                                /* bit field Status of Long Operations. */
+
+   u32  LDrvSize[FC_MAX_LOGICAL_DRIVES];   /* Size of each log. Drv. */
+   u8  LDrvProp[FC_MAX_LOGICAL_DRIVES];
+   u8  LDrvState[FC_MAX_LOGICAL_DRIVES];  /* State of Logical Drives. */
+}__attribute__((packed));
+
+#define PREVSTAT_MASK   0xf0
+#define CURRSTAT_MASK   0x0f
+
+struct FC_PDRV_INFO
+{
+   u8 PDrvState[FC_MAX_PHYSICAL_DEVICES]; /* State of Phys Drvs. */
+}__attribute__((packed));
+
+
+struct FC_AdapterInq
+{
+   struct FC_ADP_INFO    AdpInfo;
+   struct FC_LDRV_INFO   LogdrvInfo;
+   struct FC_PDRV_INFO   PhysdrvInfo;
+}__attribute__((packed));
+
+
+typedef struct FC_AdapterInq  mega_RAIDINQ_FC;
+
+/********************************************
+ * NOTIFICATION Strucure
+ ********************************************/
+
+#define MAX_NOTIFY_SIZE     0x80
+#define CUR_NOTIFY_SIZE     sizeof(struct MegaRAID_Notify)
+
+/* 
+ * Utilities declare this strcture size as ?? bytes. So more fields can
+ * be added in future.
+ */
+struct MegaRAID_Notify
+{
+    u32   globalCounter;  /* Any change increments this counter */
+
+    u8   paramCounter;   /* Indicates any params changed  */
+    u8   paramId;        /* Param modified - defined below */
+    u16  paramVal;       /* New val of last param modified */
+
+    u8   writeConfigCounter; /* write config occurred */
+    u8   writeConfigRsvd[3];
+
+    u8   ldrvOpCounter;  /* Indicates ldrv op started/completed */
+    u8   ldrvOpId;       /* ldrv num */
+    u8   ldrvOpCmd;      /* ldrv operation - defined below */
+    u8   ldrvOpStatus;   /* status of the operation */
+
+    u8   ldrvStateCounter;   /* Indicates change of ldrv state */
+    u8   ldrvStateId;    /* ldrv num */
+    u8   ldrvStateNew;   /* New state */
+    u8   ldrvStateOld;   /* old state */
+
+    u8   pdrvStateCounter;   /* Indicates change of ldrv state */
+    u8   pdrvStateId;    /* pdrv id */
+    u8   pdrvStateNew;   /* New state */
+    u8   pdrvStateOld;   /* old state */
+
+    u8   pdrvFmtCounter; /* Indicates pdrv format started/over */
+    u8   pdrvFmtId;      /* pdrv id */
+    u8   pdrvFmtVal;     /* format started/over */
+    u8   pdrvFmtRsvd;
+
+    u8   targXferCounter;    /* Indicates SCSI-2 Xfer rate change */
+    u8   targXferId;     /* pdrv Id  */
+    u8   targXferVal;    /* new Xfer params of last pdrv */
+    u8   targXferRsvd;
+
+    u8   fcLoopIdChgCounter; /* Indicates loopid changed */
+    u8   fcLoopIdPdrvId; /* pdrv id */
+    u8   fcLoopId0;      /* loopid on fc loop 0 */
+    u8   fcLoopId1;      /* loopid on fc loop 1 */
+
+    u8   fcLoopStateCounter; /* Indicates loop state changed */
+    u8   fcLoopState0;   /* state of fc loop 0 */
+    u8   fcLoopState1;   /* state of fc loop 1 */
+    u8   fcLoopStateRsvd;
+}__attribute__((packed));
+
+
+/********************************************
+ * PARAM IDs in Notify struct
+ ********************************************/
+#define PARAM_RBLD_RATE                 0x01
+    /*--------------------------------------
+     * Param val = 
+     *      byte 0: new rbld rate 
+     *--------------------------------------*/
+#define PARAM_CACHE_FLUSH_INTERVAL      0x02
+    /*--------------------------------------
+     * Param val = 
+     *      byte 0: new cache flush interval
+     *--------------------------------------*/
+#define PARAM_SENSE_ALERT               0x03
+    /*--------------------------------------
+     * Param val = 
+     *      byte 0: last pdrv id causing chkcond
+     *--------------------------------------*/
+#define PARAM_DRIVE_INSERTED            0x04
+    /*--------------------------------------
+     * Param val = 
+     *      byte 0: last pdrv id inserted
+     *--------------------------------------*/
+#define PARAM_BATTERY_STATUS            0x05
+    /*--------------------------------------
+     * Param val = 
+     *      byte 0: battery status
+     *--------------------------------------*/
+
+/********************************************
+ * Ldrv operation cmd in Notify struct
+ ********************************************/
+#define LDRV_CMD_CHKCONSISTANCY         0x01
+#define LDRV_CMD_INITIALIZE             0x02
+#define LDRV_CMD_RECONSTRUCTION         0x03
+
+/********************************************
+ * Ldrv operation status in Notify struct
+ ********************************************/
+#define        LDRV_OP_SUCCESS                 0x00
+#define        LDRV_OP_FAILED                  0x01
+#define        LDRV_OP_ABORTED                 0x02
+#define        LDRV_OP_CORRECTED               0x03
+#define        LDRV_OP_STARTED                 0x04
+
+
+/********************************************
+ * Raid Logical drive states.
+ ********************************************/
+#define     RDRV_OFFLINE                0
+#define     RDRV_DEGRADED               1
+#define     RDRV_OPTIMAL                2
+#define     RDRV_DELETED                3
+
+/*******************************************
+ * Physical drive states.
+ *******************************************/
+#define     PDRV_UNCNF                  0
+#define     PDRV_ONLINE                 3
+#define     PDRV_FAILED                 4
+#define     PDRV_RBLD                   5
+/* #define     PDRV_HOTSPARE               6 */
+
+/*******************************************
+ * Formal val in Notify struct
+ *******************************************/
+#define PDRV_FMT_START                  0x01
+#define PDRV_FMT_OVER                   0x02
+
+/********************************************
+ * FC Loop State in Notify Struct
+ ********************************************/
+#define ENQ_FCLOOP_FAILED               0
+#define ENQ_FCLOOP_ACTIVE               1
+#define ENQ_FCLOOP_TRANSIENT            2
+
+/********************************************
+ * ENQUIRY3 Strucure
+ ********************************************/
+/* 
+ * Utilities declare this strcture size as 1024 bytes. So more fields can
+ * be added in future.
+ */
+struct MegaRAID_Enquiry3
+{
+   u32   dataSize; /* current size in bytes (not including resvd) */
+
+   struct MegaRAID_Notify   notify;
+
+   u8   notifyRsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE];
+
+   u8   rbldRate;     /* Rebuild rate (0% - 100%) */
+   u8   cacheFlushInterval; /* In terms of Seconds */
+   u8   senseAlert;
+   u8   driveInsertedCount; /* drive insertion count */
+
+   u8   batteryStatus;
+   u8   numLDrv;              /* No. of Log Drives configured */
+   u8   reconState[FC_MAX_LOGICAL_DRIVES/8]; /* State of reconstruct */
+   u16  lDrvOpStatus[FC_MAX_LOGICAL_DRIVES/8]; /* log. Drv Status */
+
+   u32   lDrvSize[FC_MAX_LOGICAL_DRIVES];  /* Size of each log. Drv */
+   u8   lDrvProp[FC_MAX_LOGICAL_DRIVES];
+   u8   lDrvState[FC_MAX_LOGICAL_DRIVES]; /* State of Logical Drives */
+   u8   pDrvState[FC_MAX_PHYSICAL_DEVICES];  /* State of Phys. Drvs. */
+   u16  physDrvFormat[FC_MAX_PHYSICAL_DEVICES/16];
+
+   u8   targXfer[80];               /* phys device transfer rate */
+   u8   pad1k[263];          /* 761 + 263reserved = 1024 bytes total size */
+}__attribute__((packed));
+typedef struct MegaRAID_Enquiry3 mega_Enquiry3;
+
 /* Structures */
 typedef struct _mega_ADP_INFO {
-    u_char MaxConcCmds;
-    u_char RbldRate;
-    u_char MaxTargPerChan;
-    u_char ChanPresent;
-    u_char FwVer[4];
-    u_short AgeOfFlash;
-    u_char ChipSet;
-    u_char DRAMSize;
-    u_char CacheFlushInterval;
-    u_char BiosVer[4];
-    u_char resvd[7];
+    u8 MaxConcCmds;
+    u8 RbldRate;
+    u8 MaxTargPerChan;
+    u8 ChanPresent;
+    u8 FwVer[4];
+    u16 AgeOfFlash;
+    u8 ChipSetValue;
+    u8 DramSize;
+    u8 CacheFlushInterval;
+    u8 BiosVer[4];
+    u8 resvd[7];
 } mega_ADP_INFO;
 
 typedef struct _mega_LDRV_INFO {
-    u_char NumLDrv;
-    u_char resvd[3];
-    u_long LDrvSize[MAX_LOGICAL_DRIVES];
-    u_char LDrvProp[MAX_LOGICAL_DRIVES];
-    u_char LDrvState[MAX_LOGICAL_DRIVES];
+    u8 NumLDrv;
+    u8 resvd[3];
+    u32 LDrvSize[MAX_LOGICAL_DRIVES];
+    u8 LDrvProp[MAX_LOGICAL_DRIVES];
+    u8 LDrvState[MAX_LOGICAL_DRIVES];
 } mega_LDRV_INFO;
 
 typedef struct _mega_PDRV_INFO {
-    u_char PDrvState[MAX_PHYSICAL_DRIVES];
-    u_char resvd;
+    u8 PDrvState[MAX_PHYSICAL_DRIVES];
+    u8 resvd;
 } mega_PDRV_INFO;
 
 // RAID inquiry: Mailbox command 0x5
@@ -184,65 +486,70 @@ typedef struct _mega_RAIDINQ {
 
 // Passthrough command: Mailbox command 0x3
 typedef struct mega_passthru {
-    u_char timeout:3;          /* 0=6sec/1=60sec/2=10min/3=3hrs */
-    u_char ars:1;
-    u_char reserved:3;
-    u_char islogical:1;
-    u_char logdrv;             /* if islogical == 1 */
-    u_char channel;            /* if islogical == 0 */
-    u_char target;             /* if islogical == 0 */
-    u_char queuetag;           /* unused */
-    u_char queueaction;                /* unused */
-    u_char cdb[MAX_CDB_LEN];
-    u_char cdblen;
-    u_char reqsenselen;
-    u_char reqsensearea[MAX_REQ_SENSE_LEN];
-    u_char numsgelements;
-    u_char scsistatus;
-    u_long dataxferaddr;
-    u_long dataxferlen;
+    u8 timeout:3;              /* 0=6sec/1=60sec/2=10min/3=3hrs */
+    u8 ars:1;
+    u8 reserved:3;
+    u8 islogical:1;
+    u8 logdrv;         /* if islogical == 1 */
+    u8 channel;                /* if islogical == 0 */
+    u8 target;         /* if islogical == 0 */
+    u8 queuetag;               /* unused */
+    u8 queueaction;            /* unused */
+    u8 cdb[MAX_CDB_LEN];
+    u8 cdblen;
+    u8 reqsenselen;
+    u8 reqsensearea[MAX_REQ_SENSE_LEN];
+    u8 numsgelements;
+    u8 scsistatus;
+    u32 dataxferaddr;
+    u32 dataxferlen;
 } mega_passthru;
 
 typedef struct _mega_mailbox {
-    /* 0x0 */ u_char cmd;
-    /* 0x1 */ u_char cmdid;
-    /* 0x2 */ u_short numsectors;
-    /* 0x4 */ u_long lba;
-    /* 0x8 */ u_long xferaddr;
-    /* 0xC */ u_char logdrv;
-    /* 0xD */ u_char numsgelements;
-    /* 0xE */ u_char resvd;
-    /* 0xF */ u_char busy;
-    /* 0x10 */ u_char numstatus;
-    /* 0x11 */ u_char status;
-    /* 0x12 */ u_char completed[46];
-    u_char mraid_poll;
-    u_char mraid_ack;
-    u_char pad[16];
+    /* 0x0 */ u8 cmd;
+    /* 0x1 */ u8 cmdid;
+    /* 0x2 */ u16 numsectors;
+    /* 0x4 */ u32 lba;
+    /* 0x8 */ u32 xferaddr;
+    /* 0xC */ u8 logdrv;
+    /* 0xD */ u8 numsgelements;
+    /* 0xE */ u8 resvd;
+    /* 0xF */ u8 busy;
+    /* 0x10 */ u8 numstatus;
+    /* 0x11 */ u8 status;
+    /* 0x12 */ u8 completed[46];
+    u8 mraid_poll;
+    u8 mraid_ack;
+    u8 pad[16];
 } mega_mailbox;
 
+typedef struct {
+    u32 xferSegment;      /* for 64-bit controllers */
+    mega_mailbox mailbox;
+} mega_mailbox64;
+
 typedef struct _mega_ioctl_mbox {
-    /* 0x0 */ u_char cmd;
-    /* 0x1 */ u_char cmdid;
-    /* 0x2 */ u_char channel;
-    /* 0x3 */ u_char param;
-    /* 0x4 */ u_char pad[4];
-    /* 0x8 */ u_long xferaddr;
-    /* 0xC */ u_char logdrv;
-    /* 0xD */ u_char numsgelements;
-    /* 0xE */ u_char resvd;
-    /* 0xF */ u_char busy;
-    /* 0x10 */ u_char numstatus;
-    /* 0x11 */ u_char status;
-    /* 0x12 */ u_char completed[46];
-    u_char mraid_poll;
-    u_char mraid_ack;
-    u_char malign[16];
+    /* 0x0 */ u8 cmd;
+    /* 0x1 */ u8 cmdid;
+    /* 0x2 */ u8 channel;
+    /* 0x3 */ u8 param;
+    /* 0x4 */ u8 pad[4];
+    /* 0x8 */ u32 xferaddr;
+    /* 0xC */ u8 logdrv;
+    /* 0xD */ u8 numsgelements;
+    /* 0xE */ u8 resvd;
+    /* 0xF */ u8 busy;
+    /* 0x10 */ u8 numstatus;
+    /* 0x11 */ u8 status;
+    /* 0x12 */ u8 completed[46];
+    u8 mraid_poll;
+    u8 mraid_ack;
+    u8 malign[16];
 } mega_ioctl_mbox;
 
 typedef struct _mega_sglist {
-    u_long address;
-    u_long length;
+    u32 address;
+    u32 length;
 } mega_sglist;
 
 /* Queued command data */
@@ -250,39 +557,51 @@ typedef struct _mega_scb mega_scb;
 
 struct _mega_scb {
     int            idx;
-    u_long         state;
-    u_long         isrcount;
-    u_char         mboxData[16];
+    u32            state;
+    u32            isrcount;
+    u8         mboxData[16];
     mega_passthru  pthru;
     Scsi_Cmnd     *SCpnt;
     mega_sglist   *sgList;
+    char          *kern_area;  /* Only used for large ioctl xfers */
+    struct wait_queue  *ioctl_wait;
+    struct semaphore   sem;
     mega_scb      *next;
 };
 
 /* Per-controller data */
 typedef struct _mega_host_config {
-    u_char numldrv;
-    u_long flag;
-    u_long base;
+    u8 numldrv;
+    u32 flag;
+    u32 base;
  
     mega_scb *qFree;
     mega_scb *qPending;
 
-  u_long nReads[MAX_LOGICAL_DRIVES];
-  u_long nWrites[MAX_LOGICAL_DRIVES];
+    u32 nReads[FC_MAX_LOGICAL_DRIVES];
+    u32 nWrites[FC_MAX_LOGICAL_DRIVES];
 
     /* Host adapter parameters */
-    u_char fwVer[7];
-    u_char biosVer[7];
+    u8 fwVer[7];
+    u8 biosVer[7];
 
     struct Scsi_Host *host;
 
-    /* The following must be DMA-able!! */
-    volatile mega_mailbox *mbox;
-    volatile mega_mailbox mailbox;
-    volatile u_char mega_buffer[2 * 1024L];
+    volatile mega_mailbox64 *mbox64;  /* ptr to beginning of 64-bit mailbox */
+    volatile mega_mailbox *mbox;     /* ptr to beginning of standard mailbox */
+    volatile mega_mailbox64 mailbox64;
+#if 0
+    volatile union {
+         u8            generic_buffer[2 * 1024L];
+         mega_RAIDINQ  adapterInfoData;
+         mega_Enquiry3 enquiry3Data;
+    }mega_buffer;
+#else
+    volatile u8 mega_buffer[2*1024L];
+#endif
+    volatile megaRaidProductInfo productInfo;
 
-    u_char max_cmds;
+    u8 max_cmds;
     mega_scb scbList[MAX_COMMANDS];
 } mega_host_config;
 
index e3fcf65231125ec159c1ea28d9a139e863da14ae..8788eb27e162aa766718c1ff45ca0220bbaff78e 100644 (file)
@@ -74,6 +74,7 @@ struct ip_vs_dest;
 
 #ifdef __KERNEL__
 
+#define IP_MASQ_NTABLES                3
 #define IP_MASQ_TAB_SIZE       256
 
 /*
index 7c1902488847ada491b408ec75d7d653067b129d..69b31496c8135610f71fe1f76d3c6cf3a58aca26 100644 (file)
@@ -599,8 +599,6 @@ EXPORT_SYMBOL(ip_masq_d_table);
  *       1 for extra modules support (daddr)
  */
   
-#define IP_MASQ_NTABLES 3
-
 struct list_head ip_masq_m_table[IP_MASQ_TAB_SIZE];
 struct list_head ip_masq_s_table[IP_MASQ_TAB_SIZE];
 struct list_head ip_masq_d_table[IP_MASQ_TAB_SIZE];
index efee35a9442e059719aefadddff34ec0b51864c5..9e4973d45c92eb9d556bc3539e1e97c6628b96c9 100644 (file)
@@ -42,6 +42,7 @@
 #include <net/ip.h>
 #include <net/route.h>
 
+#include <net/ip_masq.h>
 #include <net/ip_vs.h>
 
 #ifdef CONFIG_KMOD
@@ -229,12 +230,12 @@ int ip_vs_hash(struct ip_masq *ms)
         hash = ip_vs_hash_key(ms->protocol, ms->daddr, ms->dport);
 
         /*
-         * Note: because ip_masq_put sets masq expire if its refcnt==2,
-         *       we have to increase counter two times, otherwise the
-         *       masq won't expire.
+         * Note: because ip_masq_put sets masq expire if its
+         *       refcnt==IP_MASQ_NTABLES, we have to increase
+         *       counter IP_MASQ_NTABLES times, otherwise the masq
+         *       won't expire.
          */
-       atomic_inc(&ms->refcnt);
-       atomic_inc(&ms->refcnt);
+       atomic_add(IP_MASQ_NTABLES, &ms->refcnt);
         list_add(&ms->m_list, &ip_vs_table[hash]);
 
         ms->flags |= IP_MASQ_F_HASHED;
@@ -250,7 +251,6 @@ int ip_vs_hash(struct ip_masq *ms)
 int ip_vs_unhash(struct ip_masq *ms)
 {
         unsigned int hash;
-        struct ip_masq ** ms_p;
 
         if (!(ms->flags & IP_MASQ_F_HASHED)) {
                 IP_VS_ERR("ip_vs_unhash(): request for unhash flagged, called from %p\n",
@@ -262,11 +262,10 @@ int ip_vs_unhash(struct ip_masq *ms)
          */
         hash = ip_vs_hash_key(ms->protocol, ms->daddr, ms->dport);
         /*
-         * Note: since we increase refcnt twice while hashing,
-         *       we have to decrease it twice while unhashing.
+         * Note: since we increase refcnt while hashing,
+         *       we have to decrease it while unhashing.
          */
-       atomic_dec(&ms->refcnt);
-       atomic_dec(&ms->refcnt);
+       atomic_sub(IP_MASQ_NTABLES, &ms->refcnt);
        list_del(&ms->m_list);
         ms->flags &= ~IP_MASQ_F_HASHED;
         return 1;
@@ -284,7 +283,7 @@ int ip_vs_unhash(struct ip_masq *ms)
 struct ip_masq * ip_vs_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
 {
         unsigned hash;
-        struct ip_masq *ms = NULL;
+        struct ip_masq *ms;
         struct list_head *l, *e;
 
         hash = ip_vs_hash_key(protocol, s_addr, s_port);
@@ -301,6 +300,7 @@ struct ip_masq * ip_vs_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_
                         goto out;
                }
         }
+       ms = NULL;
 
   out:
         return ms;
@@ -317,7 +317,7 @@ struct ip_masq * ip_vs_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_
 struct ip_masq * ip_vs_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
 {
         unsigned hash;
-        struct ip_masq *ms = NULL;
+        struct ip_masq *ms;
         struct list_head *l, *e;
 
        /*      
@@ -338,6 +338,7 @@ struct ip_masq * ip_vs_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d
                }
 
         }
+       ms = NULL;
 
   out:
         return ms;
@@ -1289,7 +1290,7 @@ __initfunc(int ip_vs_init(void))
 #ifdef CONFIG_IP_MASQUERADE_VS_WLC
         ip_vs_wlc_init();
 #endif
-#ifdef CONFIG_IP_MASQUERADE_VS_WLC
+#ifdef CONFIG_IP_MASQUERADE_VS_PCC
         ip_vs_pcc_init();
 #endif
         return 0;
diff --git a/sound/solo1 b/sound/solo1
new file mode 100644 (file)
index 0000000..1c0a641
--- /dev/null
@@ -0,0 +1,48 @@
+ALaw/uLaw sample formats
+------------------------
+
+This driver does not support the ALaw/uLaw sample formats.
+ALaw is the default mode when opening a sound device
+using OSS/Free. The reason for the lack of support is
+that the hardware does not support these formats, and adding
+conversion routines to the kernel would lead to very ugly
+code in the presence of the mmap interface to the driver.
+And since xquake uses mmap, mmap is considered important :-)
+and no sane application uses ALaw/uLaw these days anyway.
+In short, playing a Sun .au file as follows:
+
+cat my_file.au > /dev/dsp
+
+does not work. Instead, you may use the play script from
+Chris Bagwell's sox-12.14 package (or later, available from the URL
+below) to play many different audio file formats.
+The script automatically determines the audio format
+and does do audio conversions if necessary.
+http://home.sprynet.com/sprynet/cbagwell/projects.html
+
+
+Blocking vs. nonblocking IO
+---------------------------
+
+Unlike OSS/Free this driver honours the O_NONBLOCK file flag
+not only during open, but also during read and write.
+This is an effort to make the sound driver interface more
+regular. Timidity has problems with this; a patch
+is available from http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html.
+(Timidity patched will also run on OSS/Free).
+
+
+MIDI UART
+---------
+
+The driver supports a simple MIDI UART interface, with
+no ioctl's supported.
+
+
+MIDI synthesizer
+----------------
+
+The card has an OPL compatible FM synthesizer.
+
+Thomas Sailer
+sailer@ife.ee.ethz.ch