patch-2.4.8 linux/drivers/scsi/cpqfcTSinit.c

Next file: linux/drivers/scsi/cpqfcTSstructs.h
Previous file: linux/drivers/scsi/cpqfcTScontrol.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.7/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c
@@ -49,11 +49,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>   // ioctl related
 #include <asm/irq.h>
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
-#include <asm/spinlock.h>
-#else
 #include <linux/spinlock.h>
-#endif
 #include "sd.h"
 #include <scsi/scsi_ioctl.h>
 #include "hosts.h"
@@ -62,10 +58,15 @@
 
 #include "cpqfcTS.h"
 
+#include <linux/config.h>  
 #include <linux/module.h>
+#include <linux/version.h> 
+
 /* Embedded module documentation macros - see module.h */
 MODULE_AUTHOR("Compaq Computer Corporation");
 MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA");
+  
+int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, unsigned int reset_flags);
 
 // This struct was originally defined in 
 // /usr/src/linux/include/linux/proc_fs.h
@@ -104,24 +105,24 @@
 
   // since x86 port space is 64k, we only need the lower 16 bits
   cpqfcHBAdata->fcChip.Registers.IOBaseL = 
-    PciDev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+    PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
   
   cpqfcHBAdata->fcChip.Registers.IOBaseU = 
-    PciDev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
+    PciDev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
   
   // 32-bit memory addresses
   cpqfcHBAdata->fcChip.Registers.MemBase = 
-    PciDev->base_address[3] & PCI_BASE_ADDRESS_MEM_MASK;
+    PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK;
 
   cpqfcHBAdata->fcChip.Registers.ReMapMemBase = 
-    ioremap( PciDev->base_address[3] & PCI_BASE_ADDRESS_MEM_MASK,
+    ioremap( PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK,
              0x200);
   
   cpqfcHBAdata->fcChip.Registers.RAMBase = 
-    PciDev->base_address[4];
+    PciDev->resource[4].start;
   
   cpqfcHBAdata->fcChip.Registers.SROMBase =  // NULL for HP TS adapter
-    PciDev->base_address[5];
+    PciDev->resource[5].start;
   
   // now the Tachlite chip registers
   // the REGISTER struct holds both the physical address & last
@@ -296,10 +297,14 @@
       	continue;
       DEBUG_PCI( printk("  HBA found!\n"));
       DEBUG_PCI( printk("  HostAdapter->PciDev->irq = %u\n", PciDev->irq) );
-      DEBUG_PCI(printk("  PciDev->baseaddress[]= %lx\n", PciDev->base_address[0]));
-      DEBUG_PCI(printk("  PciDev->baseaddress[]= %lx\n", PciDev->base_address[1]));
-      DEBUG_PCI(printk("  PciDev->baseaddress[]= %lx\n", PciDev->base_address[2]));
-      DEBUG_PCI(printk("  PciDev->baseaddress[]= %lx\n", PciDev->base_address[3]));
+      DEBUG_PCI(printk("  PciDev->baseaddress[0]= %lx\n", 
+				PciDev->resource[0].start));
+      DEBUG_PCI(printk("  PciDev->baseaddress[1]= %lx\n", 
+				PciDev->resource[1].start));
+      DEBUG_PCI(printk("  PciDev->baseaddress[2]= %lx\n", 
+				PciDev->resource[2].start));
+      DEBUG_PCI(printk("  PciDev->baseaddress[3]= %lx\n", 
+				PciDev->resource[3].start));
 
       scsi_set_pci_device(HostAdapter, PciDev);      
       HostAdapter->irq = PciDev->irq;  // copy for Scsi layers
@@ -308,7 +313,7 @@
       // for a total I/O port address space of 512 bytes.
       // mask out the I/O port address (lower) & record
       HostAdapter->io_port = (unsigned int)
-	     PciDev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+	     PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
       HostAdapter->n_io_port = 0xff;
       
       // i.e., expect 128 targets (arbitrary number), while the
@@ -316,7 +321,6 @@
       HostAdapter->max_id =  0;   // incremented as devices log in    
       HostAdapter->max_lun = CPQFCTS_MAX_LUN;         // LUNs per FC device
       HostAdapter->max_channel = CPQFCTS_MAX_CHANNEL; // multiple busses?
-      HostAdapter->hostt->use_new_eh_code = 1; // new error handling
       
       // get the pointer to our HBA specific data... (one for
       // each HBA on the PCI bus(ses)).
@@ -333,7 +337,7 @@
       Cpqfc_initHBAdata( cpqfcHBAdata, PciDev ); // fill MOST fields
      
       cpqfcHBAdata->HBAnum = NumberOfAdapters;
-
+      cpqfcHBAdata->hba_spinlock = SPIN_LOCK_UNLOCKED;
 
       // request necessary resources and check for conflicts
       if( request_irq( HostAdapter->irq,
@@ -414,9 +418,12 @@
 	// slowest(worst) case, measured on 1Gb Finisar GT analyzer
 	
 	int wait_time;
+	unsigned long flags=0;
+ 
+        spin_unlock_irqrestore(&io_request_lock, flags);
         for( wait_time = jiffies + 4*HZ; wait_time > jiffies; )
 	  schedule();  // (our worker task needs to run)
-
+	spin_lock_irqsave(&io_request_lock, flags);
       }
       
       NumberOfAdapters++; 
@@ -458,7 +465,7 @@
   Scsi_Cmnd *ScsiPassThruCmnd;
   unsigned long flags;
 
-  ENTER("cpqfcTS_ioctl");
+  ENTER("cpqfcTS_ioctl ");
   
   // can we find an FC device mapping to this SCSI target?
   DumCmnd.channel = ScsiDev->channel;		// For searching
@@ -476,6 +483,7 @@
  
   else  // we know what FC device to operate on...
   {
+	// printk("ioctl CMND %d", Cmnd);
     switch (Cmnd) 
     {
       // Passthrough provides a mechanism to bypass the RAID
@@ -496,8 +504,8 @@
 	  return -EPERM;
 
 	// copy the caller's struct to our space.
-        copy_from_user_ret( &ioc, arg, 
-			  sizeof( VENDOR_IOCTL_REQ), -EFAULT);
+        if( copy_from_user( &ioc, arg, sizeof( VENDOR_IOCTL_REQ)))
+		return( -EFAULT);
 
 	vendor_cmd = ioc.argp;  // i.e., CPQ specific command struct
 
@@ -512,13 +520,14 @@
         // Now build a SCSI_CMND to pass down...
 	// This function allocates and sets Scsi_Cmnd ptrs such as
 	//  ->channel, ->target, ->host
-        ScsiPassThruCmnd = scsi_allocate_device(NULL, ScsiDev, 1);
+        ScsiPassThruCmnd = scsi_allocate_device(ScsiDev, 1, 1);
 
         // Need data from user?
 	// make sure caller's buffer is in kernel space.
 	if( (vendor_cmd->rw_flag == VENDOR_WRITE_OPCODE) &&
 	    vendor_cmd->len)
-          copy_from_user_ret( buf, vendor_cmd->bufp, vendor_cmd->len, -EFAULT);
+        if(  copy_from_user( buf, vendor_cmd->bufp, vendor_cmd->len))
+		return( -EFAULT);
 	    
 	// copy the CDB (if/when MAX_COMMAND_SIZE is 16, remove copy below)
         memcpy( &ScsiPassThruCmnd->cmnd[0], 
@@ -590,16 +599,17 @@
         scsi_release_command(ScsiPassThruCmnd); // "de-allocate"
         ScsiPassThruCmnd = NULL;
 
-        if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
-          (*SDpnt->scsi_request_fn)();
+        // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
+        //  (*SDpnt->scsi_request_fn)();
 
-        wake_up(&SDpnt->device_wait);
+        wake_up(&SDpnt->scpnt_wait);
         spin_unlock_irqrestore(&io_request_lock, flags);
 
 	// need to pass data back to user (space)?
 	if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) &&
 	     vendor_cmd->len )
-          copy_to_user_ret( vendor_cmd->bufp, buf, vendor_cmd->len, -EFAULT);
+        if(  copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
+		return( -EFAULT);
 
         if( buf) 
 	  kfree( buf);
@@ -621,8 +631,8 @@
 	pciinfo.board_id = cpqfcHBAdata->PciDev->device |
 			  (cpqfcHBAdata->PciDev->vendor <<16); 
 	      
-        copy_to_user_ret( arg, &pciinfo, 
-			  sizeof(cpqfc_pci_info_struct), -EFAULT);
+        if(copy_to_user( arg, &pciinfo, sizeof(cpqfc_pci_info_struct)))
+		return( -EFAULT);
         return 0;
       }
 
@@ -634,8 +644,8 @@
 	if( !arg)
 	  return -EINVAL;
 
-        copy_to_user_ret( arg, &DriverVer, 
-			  sizeof(DriverVer), -EFAULT);
+        if(copy_to_user( arg, &DriverVer, sizeof(DriverVer)))
+		return( -EFAULT);
         return 0;
       }
 
@@ -657,6 +667,17 @@
         put_user(pLoggedInPort->u.ucWWN[i], 
 		&((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
         break;
+
+
+      case SCSI_IOCTL_FC_TDR:
+          
+        result = cpqfcTS_TargetDeviceReset( ScsiDev, 0);
+
+        break;
+
+
+
+
     default:
       result = -EINVAL;
       break;
@@ -1351,13 +1372,20 @@
 
 int cpqfcTS_abort(Scsi_Cmnd *Cmnd)
 {
+//	printk(" cpqfcTS_abort called?? \n");
+ 	return 0;
+}
+ 
+int cpqfcTS_eh_abort(Scsi_Cmnd *Cmnd)
+{
+
   struct Scsi_Host *HostAdapter = Cmnd->host;
   // get the pointer to our Scsi layer HBA buffer  
   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
   int i;
-  ENTER("cpqfcTS_abort");
+  ENTER("cpqfcTS_eh_abort");
 
   Cmnd->result = DID_ABORT <<16;  // assume we'll find it
 
@@ -1443,28 +1471,117 @@
 Done:
   
 //    panic("_abort");
-  LEAVE("cpqfcTS_abort");
+  LEAVE("cpqfcTS_eh_abort");
   return 0;  // (see scsi.h)
 }    
 
 
+// FCP-SCSI Target Device Reset
+// See dpANS Fibre Channel Protocol for SCSI
+// X3.269-199X revision 12, pg 25
+
+int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, 
+                               unsigned int reset_flags)
+{
+  int timeout = 10*HZ;
+  int retries = 1;
+  char scsi_cdb[12];
+  unsigned long flags;
+  int result;
+  Scsi_Cmnd * SCpnt;
+  Scsi_Device * SDpnt;
 
 
-// To be done...	
-int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
-{
-  int return_status = SUCCESS;
+  // printk("   ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags);
 
-  ENTER("cpqfcTS_reset");
+  if (ScsiDev->host->eh_active) return FAILED;
 
+  memset( scsi_cdb, 0, sizeof( scsi_cdb));
 
-            
+  scsi_cdb[0] = RELEASE;
 
-  LEAVE("cpqfcTS_reset");
-  return return_status;
-}    
+  spin_lock_irqsave(&io_request_lock, flags);
 
+  // allocate with wait = true, interruptible = false 
+  SCpnt = scsi_allocate_device(ScsiDev, 1, 0);
+  {
+    DECLARE_COMPLETION(wait);
+        
+    SCpnt->SCp.buffers_residual = FCP_TARGET_RESET;
+
+	SCpnt->request.waiting = &wait;
+	scsi_do_cmd(SCpnt,  scsi_cdb, NULL,  0, my_ioctl_done,  timeout, retries);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	wait_for_completion(&wait);
+    spin_lock_irqsave(&io_request_lock, flags);
+    SCpnt->request.waiting = NULL;
+  }
+    
+/*
+      if(driver_byte(SCpnt->result) != 0)
+	  switch(SCpnt->sense_buffer[2] & 0xf) {
+	case ILLEGAL_REQUEST:
+	    if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0;
+	    else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
+	    break;
+	case NOT_READY: // This happens if there is no disc in drive 
+	    if(dev->removable && (cmd[0] != TEST_UNIT_READY)){
+		printk(KERN_INFO "Device not ready.  Make sure there is a disc in the drive.\n");
+		break;
+	    }
+	case UNIT_ATTENTION:
+	    if (dev->removable){
+		dev->changed = 1;
+		SCpnt->result = 0; // This is no longer considered an error
+		// gag this error, VFS will log it anyway /axboe 
+		// printk(KERN_INFO "Disc change detected.\n"); 
+		break;
+	    };
+	default: // Fall through for non-removable media
+	    printk("SCSI error: host %d id %d lun %d return code = %x\n",
+		   dev->host->host_no,
+		   dev->id,
+		   dev->lun,
+		   SCpnt->result);
+	    printk("\tSense class %x, sense error %x, extended sense %x\n",
+		   sense_class(SCpnt->sense_buffer[0]),
+		   sense_error(SCpnt->sense_buffer[0]),
+		   SCpnt->sense_buffer[2] & 0xf);
+	    
+      };
+*/    
+  result = SCpnt->result;
+
+  SDpnt = SCpnt->device;
+  scsi_release_command(SCpnt);
+  SCpnt = NULL;
+
+  // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
+  // 	(*SDpnt->scsi_request_fn)();
+
+  wake_up(&SDpnt->scpnt_wait);
+  spin_unlock_irqrestore(&io_request_lock, flags);
+  // printk("   LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS \n");
+  return SUCCESS;
+}
+
+
+int cpqfcTS_eh_device_reset(Scsi_Cmnd *Cmnd)
+{
+  Scsi_Device *SDpnt = Cmnd->device;
+  // printk("   ENTERING cpqfcTS_eh_device_reset() \n");
+  return cpqfcTS_TargetDeviceReset( SDpnt, 0);
+}
+
+	
+int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
+{
 
+  ENTER("cpqfcTS_reset");
+
+  LEAVE("cpqfcTS_reset");
+  return SCSI_RESET_ERROR;      /* Bus Reset Not supported */
+}
 
 /* This function determines the bios parameters for a given
    harddisk. These tend to be numbers that are made up by the
@@ -1805,15 +1922,7 @@
 }
 
 
-
-
-#ifdef MODULE
-
 static Scsi_Host_Template driver_template = CPQFCTS;
 
 #include "scsi_module.c"
-
-
-#endif
-
 

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