patch-2.2.15 linux/drivers/scsi/megaraid.c

Next file: linux/drivers/scsi/megaraid.h
Previous file: linux/drivers/scsi/hosts.h
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
@@ -2,14 +2,14 @@
  *
  *                    Linux MegaRAID device driver
  *
- * Copyright 1998 American Megatrends Inc.
+ * Copyright 1999 American Megatrends Inc.
  *
  *              This program is free software; you can redistribute it and/or
  *              modify it under the terms of the GNU General Public License
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Version : 1.05
+ * Version : 1.07b
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
@@ -120,6 +120,14 @@
  *      also enables the driver to handle large amount of I/O requests for
  *      long duration of time.
  *
+ * Version 1.07
+ *    Removed the usage of uaccess.h file for kernel versions less than
+ *    2.0.36, as this file is not present in those versions.
+ *
+ * Version 1.07b
+ *    The MegaRAID 466 cards with 3.00 firmware lockup and seem to very
+ *    occasionally hang. We check such cards and report them. You can
+ *    get firmware upgrades to flash the board to 3.10 for free.
  *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
@@ -135,7 +143,7 @@
 #define CRLFSTR "\n"
 #define IOCTL_CMD_NEW  0x81
 
-#define MEGARAID_VERSION "v1.05 (October 27, 1999)"
+#define MEGARAID_VERSION "v107 (December 22, 1999)"
 
 
 #include <linux/config.h>
@@ -178,7 +186,9 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#if LINUX_VERSION_CODE > 0x020024
 #include <asm/uaccess.h>
+#endif
 
 #include "sd.h"
 #include "scsi.h"
@@ -265,7 +275,6 @@
 
 
 
-
 #if LINUX_VERSION_CODE > 0x020100
 #  include <asm/spinlock.h>
 #  include <linux/smp.h>
@@ -304,6 +313,7 @@
        cli();
 #  define DRIVER_UNLOCK(p) \
        restore_flags(cpu_flags);
+#  define IO_LOCK_T unsigned long io_flags = 0;
 #  define IO_LOCK(p)   DRIVER_LOCK(p)
 #  define IO_UNLOCK(p) DRIVER_UNLOCK(p)
 #  define le32_to_cpu(x) (x)
@@ -329,6 +339,7 @@
 /*  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
@@ -350,7 +361,6 @@
 #if SERDEBUG
 volatile static spinlock_t serial_lock;
 #endif
-//volatile static spinlock_t mega_lock;
 
 struct proc_dir_entry proc_scsi_megaraid =
 {
@@ -593,7 +603,6 @@
   }
 
   SCpnt = pScb->SCpnt;
-  /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
   pthru = &pScb->pthru;
   mbox = (mega_mailbox *) &pScb->mboxData;
 
@@ -708,13 +717,11 @@
 
   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
   }
   /*-----------------------------------------------------
    *
@@ -878,7 +885,6 @@
     return NULL;
   }
 
-
   mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
   mailbox = (mega_mailbox *) & pScb->mboxData;
@@ -913,6 +919,14 @@
   }
   /* else normal (nonpassthru) command */
 
+#if LINUX_VERSION_CODE > 0x020024
+/*
+ * usage of the function copy from user is used in case of data more than
+ * 4KB.  This is used only with adapters which supports more than 8 logical
+ * drives.  This feature is disabled on kernels earlier or same as 2.0.36
+ * as the uaccess.h file is not available with those kernels.
+ */
+
   if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) { 
             /* use external data area for large xfers  */
      /* If cmnd[0] is set to IOCTL_CMD_NEW then *
@@ -938,6 +952,7 @@
       copy_from_user(kern_area,user_area,xfer_size);
       pScb->kern_area = kern_area;
   }
+#endif
 
   mbox->cmd = data[0];
   mbox->channel = data[1];
@@ -998,7 +1013,9 @@
  *--------------------------------------------------------------------*/
 static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
+#if LINUX_VERSION_CODE >= 0x20100
   IO_LOCK_T
+#endif
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
   u32 dword=0;
@@ -1011,7 +1028,6 @@
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-
   if (megaCfg->host->irq == irq) {
 
     if (megaCfg->flag & IN_ISR) {
@@ -1031,10 +1047,6 @@
       if (dword != 0x10001234) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-//#if LINUX_VERSION_CODE >= 0x20100
-//        IO_UNLOCK;
-//#endif
-//	break;
 	return;
       }
     }
@@ -1043,10 +1055,6 @@
       if ((byte & VALID_INTR_BYTE) == 0) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-//#if LINUX_VERSION_CODE >= 0x20100
-//	IO_UNLOCK;
-//#endif
-//	break;
 	return;
       }
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
@@ -1110,9 +1118,6 @@
  */
 	if (pScb->state == SCB_ABORTED) {
           SCpnt = pScb->SCpnt;
-#if DEBUG
-printk("megaraid_isr:fcnt=%d, pcnt=%d, qcnt=%d\n",megaCfg->qFcnt, megaCfg->qPcnt, megaCfg->qCcnt); 
-#endif
 	}
 	if (pScb->state == SCB_RESET) {
           SCpnt = pScb->SCpnt;
@@ -1211,9 +1216,6 @@
 #endif
 
   /* Wait until mailbox is free */
-#if 0
-  while (mega_busyWaitMbox (megaCfg))
-#endif
   if (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox......!!\n");
     udelay(1000);
@@ -1266,7 +1268,6 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-//	mega_rundoneq (megaCfg);
       }
 
       WRINDOOR (megaCfg, phys_mbox | 0x2);
@@ -1285,7 +1286,6 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-//	mega_rundoneq (megaCfg);
       }
       else {
 	TRACE (("Error: NULL pScb!\n"));
@@ -1424,7 +1424,6 @@
   u32 paddr;
   u8 retval;
 
-
   /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
   mbox = (mega_mailbox *) mboxData;
@@ -1496,25 +1495,6 @@
     megaCfg->host->can_queue = MAX_COMMANDS-1;
   }
 
-#if 0 
-  int i;
-  printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
-  for (i = 0; i < megaCfg->numldrv; 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 < FC_MAX_PHYSICAL_DEVICES; i++) {
-    if (i && !(i % 8))
-      printk ("\n");
-    printk ("%d: %x   ", i, enquiry3Pnt->pDrvState[i]);
-  }
-  printk ("\n");
-#endif
-
 #ifdef HP			/* use HP firmware and bios version encoding */
   sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
 	   megaCfg->productInfo.FwVer[2],
@@ -1573,10 +1553,6 @@
 
 #if LINUX_VERSION_CODE < 0x20100
   while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
-
-#if 0
-  } /* keep auto-indenters happy */
-#endif
 #else
   
   struct pci_dev *pdev = pci_devices;
@@ -1587,10 +1563,14 @@
 #endif
     if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
       u16 magic;
+#if LINUX_VERSION_CODE < 0x20100
       pcibios_read_config_word (pciBus, pciDevFun,
 				PCI_CONF_AMISIG,
 				&magic);
-      if (magic != AMI_SIGNATURE) {
+#else
+      pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic);
+#endif
+      if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
         pciIdx++;
 	continue;		/* not an AMI board */
       }
@@ -1673,10 +1653,43 @@
 
     mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox64));
     mega_i_query_adapter (megaCfg);
-    
+   
+    if (flag == BOARD_QUARTZ) {
+      /* Check to see if this is a Dell PERC RAID controller model 466 */
+      u16 subsysid, subsysvid;
+#if LINUX_VERSION_CODE < 0x20100
+      pcibios_read_config_word (pciBus, pciDevFun,
+				PCI_SUBSYSTEM_VENDOR_ID,
+				&subsysvid);
+      pcibios_read_config_word (pciBus, pciDevFun,
+				PCI_SUBSYSTEM_ID,
+				&subsysid);
+#else
+      pci_read_config_word (pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
+      pci_read_config_word (pdev, PCI_SUBSYSTEM_ID, &subsysid);
+#endif
+      if ( (subsysid == 0x1111) && (subsysvid == 0x1111) &&
+           (!strcmp(megaCfg->fwVer,"3.00") || !strcmp(megaCfg->fwVer,"3.01"))) {
+	printk(KERN_WARNING
+"megaraid: Your card is a Dell PERC 2/SC RAID controller with firmware\n"
+"megaraid: 3.00 or 3.01.  This driver is known to have corruption issues\n"
+"megaraid: with those firmware versions on this specific card.  In order\n"
+"megaraid: to protect your data, please upgrade your firmware to version\n"
+"megaraid: 3.10 or later, available from the Dell Technical Support web\n"
+"megaraid: site at\n"
+"http://support.dell.com/us/en/filelib/download/index.asp?fileid=2489\n");
+	megaraid_release (host);
+#ifdef MODULE	
+	continue;
+#else
+	while(1) schedule_timeout(1 * HZ);
+#endif	
+      }
+    }
+
     /* Initialize SCBs */
     if (mega_initSCB (megaCfg)) {
-      scsi_unregister (host);
+      megaraid_release (host);
       continue;
     }
 
@@ -1824,9 +1837,6 @@
 
   /* If driver in abort or reset.. cancel this command */
   if (megaCfg->flag & IN_ABORT) {
-#if DEBUG
-printk("mq: got a request while in abort\n");
-#endif
     SCpnt->result = (DID_ABORT << 16);
     /* Add Scsi_Command to end of completed queue */
     if( megaCfg->qCompletedH == NULL ) {
@@ -1843,9 +1853,6 @@
     return 0;
   }
   else if (megaCfg->flag & IN_RESET) {
-#if DEBUG
-printk("mq: got a request while in reset\n");
-#endif
     SCpnt->result = (DID_RESET << 16);
     /* Add Scsi_Command to end of completed queue */
     if( megaCfg->qCompletedH == NULL ) {
@@ -1878,16 +1885,9 @@
     megaCfg->qPendingT->next = NULL;
     megaCfg->qPcnt++;
 
-
-    /* Issue any pending command to the card if not in ISR */
-//    if (!(megaCfg->flag & IN_ISR)) {
       mega_runpendq(megaCfg);
-//    }
-/* 
- * try running the pend queue, irrespective of the driver's context.
- * -cn 
- */
 
+#if LINUX_VERSION_CODE > 0x020024
     if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
     {  /* user data from external user buffer */
           char *user_area;
@@ -1905,6 +1905,7 @@
 
           mega_freeSCB(megaCfg, pScb);
     }
+#endif
   }
 
   megaCfg->flag &= ~IN_QUEUE;
@@ -1959,9 +1960,6 @@
 
   megaCfg->flag |= IN_ABORT;
 
-#if DEBUG
-printk("ma:fcnt=%d, pcnt=%d, qcnt=%d\n",megaCfg->qFcnt, megaCfg->qPcnt, megaCfg->qCcnt); 
-#endif
   for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
     if (pScb->SCpnt == SCpnt) {
       /* Found an aborting command */
@@ -2013,20 +2011,6 @@
     }
   }
 
-#if 0
-  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
-	  SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
-	  SCpnt->lun));
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
-    if (pScb->SCpnt == SCpnt) { 
-      ser_printk("** %d<%x>  %c\n", pScb->SCpnt->pid, pScb->idx+1,
-		 pScb->state == SCB_ACTIVE ? 'A' : 'I');
-#if DEBUG
-      showMbox(pScb);
-#endif
-    }
-  }
-#endif
   megaCfg->flag &= ~IN_ABORT;
 
 #if DEBUG
@@ -2044,12 +2028,11 @@
   megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
   megaCfg->qCcnt--;
 
-  SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
+  SCpnt->host_scribble = (unsigned char *) NULL ;
   /* Callback */
   callDone (SCpnt);
 }
   mega_rundoneq(megaCfg);
-
 
   return rc;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)