⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpqfctsinit.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
  copy_info( &info, "  TACH RxEOFa      %9u     TACH Elastic Store  %u\n",    fcChip->fcStats.Rx_EOFa, fcChip->fcStats.e_stores);  copy_info( &info, "  BufferCreditWait %9uus   TACH FM Inits %u\n",    fcChip->fcStats.BB0_Timer*10, fcChip->fcStats.FMinits );	  copy_info( &info, "  FC-2 Timeouts    %9u     FC-2 Logouts  %u\n",    fcChip->fcStats.timeouts, fcChip->fcStats.logouts);           copy_info( &info, "  FC-2 Aborts      %9u     FC-4 Aborts   %u\n",    fcChip->fcStats.FC2aborted, fcChip->fcStats.FC4aborted);     // clear the counters  cpqfcTSClearLinkStatusCounters( fcChip);#endif	  return info.buffillen;}#if DEBUG_CMNDUCHAR *ScsiToAscii( UCHAR ScsiCommand){/*++Routine Description:   Converts a SCSI command to a text string for debugging purposes.Arguments:   ScsiCommand -- hex value SCSI CommandReturn Value:   An ASCII, null-terminated string if found, else returns NULL.Original code from M. McGowen, Compaq--*/   switch (ScsiCommand)   {      case 0x00:         return( "Test Unit Ready" );      case 0x01:         return( "Rezero Unit or Rewind" );      case 0x02:         return( "Request Block Address" );      case 0x03:         return( "Requese Sense" );      case 0x04:         return( "Format Unit" );      case 0x05:         return( "Read Block Limits" );      case 0x07:         return( "Reassign Blocks" );      case 0x08:         return( "Read (6)" );      case 0x0a:         return( "Write (6)" );      case 0x0b:         return( "Seek (6)" );      case 0x12:         return( "Inquiry" );      case 0x15:         return( "Mode Select (6)" );      case 0x16:         return( "Reserve" );      case 0x17:         return( "Release" );      case 0x1a:         return( "ModeSen(6)" );      case 0x1b:         return( "Start/Stop Unit" );      case 0x1c:         return( "Receive Diagnostic Results" );      case 0x1d:         return( "Send Diagnostic" );      case 0x25:         return( "Read Capacity" );      case 0x28:         return( "Read (10)" );      case 0x2a:         return( "Write (10)" );      case 0x2b:         return( "Seek (10)" );      case 0x2e:         return( "Write and Verify" );      case 0x2f:         return( "Verify" );      case 0x34:         return( "Pre-Fetch" );      case 0x35:         return( "Synchronize Cache" );      case 0x37:         return( "Read Defect Data (10)" );      case 0x3b:         return( "Write Buffer" );      case 0x3c:         return( "Read Buffer" );      case 0x3e:         return( "Read Long" );      case 0x3f:         return( "Write Long" );      case 0x41:         return( "Write Same" );      case 0x4c:         return( "Log Select" );      case 0x4d:         return( "Log Sense" );      case 0x56:         return( "Reserve (10)" );      case 0x57:         return( "Release (10)" );      case 0xa0:         return( "ReportLuns" );      case 0xb7:         return( "Read Defect Data (12)" );      case 0xca:         return( "Peripheral Device Addressing SCSI Passthrough" );      case 0xcb:         return( "Compaq Array Firmware Passthrough" );      default:         return( NULL );   }} // end ScsiToAscii()void cpqfcTS_print_scsi_cmd(Scsi_Cmnd * cmd){printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",     ScsiToAscii( cmd->cmnd[0]), cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);if( cmd->cmnd[0] == 0)   // Test Unit Ready?{  int i;  printk("Cmnd->request_bufflen = 0x%X, ->use_sg = %d, ->bufflen = %d\n",    cmd->request_bufflen, cmd->use_sg, cmd->bufflen);  printk("Cmnd->request_buffer = %p, ->sglist_len = %d, ->buffer = %p\n",    cmd->request_buffer, cmd->sglist_len, cmd->buffer);  for (i = 0; i < cmd->cmd_len; i++)    printk("0x%02x ", cmd->cmnd[i]);  printk("\n");}}#endif				/* DEBUG_CMND */static void QueCmndOnBoardLock( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd){  int i;  for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++)  {    // find spare slot    if( cpqfcHBAdata->BoardLockCmnd[i] == NULL )    {      cpqfcHBAdata->BoardLockCmnd[i] = Cmnd;//      printk(" BoardLockCmnd[%d] %p Queued, chnl/target/lun %d/%d/%d\n",//        i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);      break;    }  }  if( i >= CPQFCTS_REQ_QUEUE_LEN)  {    printk(" cpqfcTS WARNING: Lost Cmnd %p on BoardLock Q full!", Cmnd);  }}static void QueLinkDownCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd){  int indx;  // Remember the command ptr so we can return; we'll complete when  // the device comes back, causing immediate retry  for( indx=0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++)//, SCptr++)  {    if( cpqfcHBAdata->LinkDnCmnd[indx] == NULL ) // available?    {#ifdef DUMMYCMND_DBG      printk(" @add Cmnd %p to LnkDnCmnd[%d]@ ", Cmnd,indx);#endif      cpqfcHBAdata->LinkDnCmnd[indx] = Cmnd;      break;    }  }  if( indx >= CPQFCTS_REQ_QUEUE_LEN ) // no space for Cmnd??  {    // this will result in an _abort call later (with possible trouble)    printk("no buffer for LinkDnCmnd!! %p\n", Cmnd);  }}// The file "hosts.h" says not to call scsi_done from// inside _queuecommand, so we'll do it from the heartbeat timerstatic void QueBadTargetCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd){  int i;    //    printk(" can't find target %d\n", Cmnd->target);  for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)  {    // find spare slot    if( cpqfcHBAdata->BadTargetCmnd[i] == NULL )    {      cpqfcHBAdata->BadTargetCmnd[i] = Cmnd;//      printk(" BadTargetCmnd[%d] %p Queued, chnl/target/lun %d/%d/%d\n",//          i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);      break;    }  }}// This is the "main" entry point for Linux Scsi commands --// it all starts here.int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd, void (* done)(Scsi_Cmnd *)){  struct Scsi_Host *HostAdapter = Cmnd->host;  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;  PTACHYON fcChip = &cpqfcHBAdata->fcChip;  TachFCHDR_GCMND fchs;  // only use for FC destination id field    PFC_LOGGEDIN_PORT pLoggedInPort;  ULONG ulStatus, SESTtype;  LONG ExchangeID;  ENTER("cpqfcTS_queuecommand");        PCI_TRACEO( (ULONG)Cmnd, 0x98)          Cmnd->scsi_done = done;#ifdef DEBUG_CMND    cpqfcTS_print_scsi_cmd( Cmnd);#endif  // prevent board contention with kernel thread...       if( cpqfcHBAdata->BoardLock )  {//    printk(" @BrdLck Hld@ ");    QueCmndOnBoardLock( cpqfcHBAdata, Cmnd);  }    else  {    // in the current system (2.2.12), this routine is called    // after spin_lock_irqsave(), so INTs are disabled. However,    // we might have something pending in the LinkQ, which    // might cause the WorkerTask to run.  In case that    // happens, make sure we lock it out.                PCI_TRACE( 0x98)     CPQ_SPINLOCK_HBA( cpqfcHBAdata)    PCI_TRACE( 0x98) 	      // can we find an FC device mapping to this SCSI target?    pLoggedInPort = fcFindLoggedInPort( fcChip,      Cmnd,     // search Scsi Nexus      0,        // DON'T search linked list for FC port id      NULL,     // DON'T search linked list for FC WWN      NULL);    // DON'T care about end of list     if( pLoggedInPort == NULL )      // not found!    {//    printk(" @Q bad targ cmnd %p@ ", Cmnd);      QueBadTargetCmnd( cpqfcHBAdata, Cmnd);    }    else  // we know what FC device to send to...    {      // does this device support FCP target functions?      // (determined by PRLI field)      if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) )      {        printk(" Doesn't support TARGET functions port_id %Xh\n",          pLoggedInPort->port_id );        QueBadTargetCmnd( cpqfcHBAdata, Cmnd);      }    // In this case (previous login OK), the device is temporarily    // unavailable waiting for re-login, in which case we expect it    // to be back in between 25 - 500ms.      // If the FC port doesn't log back in within several seconds    // (i.e. implicit "logout"), or we get an explicit logout,    // we set "device_blocked" in Scsi_Device struct; in this    // case 30 seconds will elapse before Linux/Scsi sends another    // command to the device.      else if( pLoggedInPort->prli != TRUE )      {//      printk("Device (Chnl/Target %d/%d) invalid PRLI, port_id %06lXh\n",//        Cmnd->channel, Cmnd->target, pLoggedInPort->port_id);        QueLinkDownCmnd( cpqfcHBAdata, Cmnd);//    Need to use "blocked" flag??   	//	Cmnd->device->device_blocked = TRUE; // just let it timeout      }      else  // device supports TARGET functions, and is logged in...      {      // (context of fchs is to "reply" to...)        fchs.s_id = pLoggedInPort->port_id; // destination FC address      // what is the data direction?  For data TO the device,      // we need IWE (Intiator Write Entry).  Otherwise, IRE.        if( Cmnd->cmnd[0] == WRITE_10 ||  	  Cmnd->cmnd[0] == WRITE_6 ||	  Cmnd->cmnd[0] == WRITE_BUFFER ||      	  Cmnd->cmnd[0] == VENDOR_WRITE_OPCODE ||  // CPQ specific 	  Cmnd->cmnd[0] == MODE_SELECT )        {          SESTtype = SCSI_IWE; // data from HBA to Device        }        else          SESTtype = SCSI_IRE; // data from Device to HBA    	          ulStatus = cpqfcTSBuildExchange(          cpqfcHBAdata,          SESTtype,     // e.g. Initiator Read Entry (IRE)          &fchs,        // we are originator; only use d_id          Cmnd,         // Linux SCSI command (with scatter/gather list)          &ExchangeID );// fcController->fcExchanges index, -1 if failed        if( !ulStatus ) // Exchange setup?           {          if( cpqfcHBAdata->BoardLock )          {    TriggerHBA( fcChip->Registers.ReMapMemBase, 0);	    printk(" @bl! %d, xID %Xh@ ", current->pid, ExchangeID);          }	  ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );	  if( !ulStatus )          {            PCI_TRACEO( ExchangeID, 0xB8)           // submitted to Tach's Outbound Que (ERQ PI incremented)          // waited for completion for ELS type (Login frames issued          // synchronously)	  }          else            // check reason for Exchange not being started - we might            // want to Queue and start later, or fail with error          {            printk("quecommand: cpqfcTSStartExchange failed: %Xh\n", ulStatus );          }        }            // end good BuildExchange status                else  // SEST table probably full  -- why? hardware hang?        {	  printk("quecommand: cpqfcTSBuildExchange faild: %Xh\n", ulStatus);        }      }  // end can't do FCP-SCSI target functions    } // end can't find target (FC device)    CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)  }	  PCI_TRACEO( (ULONG)Cmnd, 0x9C)   LEAVE("cpqfcTS_queuecommand");  return 0;}    // Entry point for upper Scsi layer intiated abort.  Typically// this is called if the command (for hard disk) fails to complete// in 30 seconds.  This driver intends to complete all disk commands// within Exchange ".timeOut" seconds (now 7) with target status, or// in case of ".timeOut" expiration, a DID_SOFT_ERROR which causes// immediate retry.// If any disk commands get the _abort call, except for the case that// the physical device was removed or unavailable due to hardware// errors, it should be considered a driver error and reported to// the author.int cpqfcTS_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");  Cmnd->result = DID_ABORT <<16;  // assume we'll find it  printk(" @Linux _abort Scsi_Cmnd %p ", Cmnd);  // See if we can find a Cmnd pointer that matches...  // The most likely case is we accepted the command

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -