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

📄 cpqfctscontrol.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        // clear the soft reset      for( i=0; i<8; i++)  	writel( 0, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));               			       // clear out our copy of Tach regs,			       // because they must be invalid now,			       // since TachLite reset all his regs.      CpqTsDestroyTachLiteQues(cpqfcHBAdata,0); // remove Host-based Que structs      cpqfcTSClearLinkStatusCounters(fcChip);  // clear our s/w accumulators                               // lower bits give GBIC info      fcChip->Registers.TYstatus.value = 	              readl( fcChip->Registers.TYstatus.address );      break;/*    case 2:                   // freeze SCSI    case 3:                   // reset Outbound command que (ERQ)    case 4:                   // unfreeze OSM (Outbound Seq. Man.) 'er'    case 5:                   // report status    break;*/    default:      ret_status = -1;  // invalid option passed to RESET function      break;  }  LEAVE("ResetTach");  return ret_status;}// 'addrBase' is IOBaseU for both TachLite and (older) Tachyonint CpqTsLaserControl( void* addrBase, int opcode ){  ULONG dwBuff;  dwBuff = readl((addrBase + TL_MEM_TACH_CONTROL) ); // read TL Control reg                                                    // (change only bit 4)  if( opcode == 1)    dwBuff |= ~0xffffffefL; // set - ON  else    dwBuff &= 0xffffffefL;  // clear - OFF  writel( dwBuff, (addrBase + TL_MEM_TACH_CONTROL)); // write TL Control reg  return 0;}// Use controller's "Options" field to determine loopback mode (if any)//   internal loopback (silicon - no GBIC)//   external loopback (GBIC - no FC loop)//   no loopback: L_PORT, external cable from GBIC requiredint CpqTsInitializeFrameManager( void *pChip, int opcode){  PTACHYON fcChip;  int iStatus;  ULONG wwnLo, wwnHi; // for readback verification  ENTER("InitializeFrameManager");  fcChip = (PTACHYON)pChip;  if( !fcChip->Registers.ReMapMemBase )   // undefined controller?    return -1;  // TL/TS UG, pg. 184  // 0x0065 = 100ms for RT_TOV  // 0x01f5 = 500ms for ED_TOV  // 0x07D1 = 2000ms   fcChip->Registers.ed_tov.value = 0x006507D1;   writel( fcChip->Registers.ed_tov.value,    (fcChip->Registers.ed_tov.address));        // Set LP_TOV to the FC-AL2 specified 2 secs.  // TL/TS UG, pg. 185  writel( 0x07d00010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);  // Now try to read the WWN from the adapter's NVRAM  iStatus = CpqTsReadWriteWWN( fcChip, 1); // '1' for READ  if( iStatus )   // NVRAM read failed?  {    printk(" WARNING! HBA NVRAM WWN read failed - make alias\n");    // make up a WWN.  If NULL or duplicated on loop, FC loop may hang!    fcChip->Registers.wwn_hi = (__u32)jiffies;    fcChip->Registers.wwn_hi |= 0x50000000L;    fcChip->Registers.wwn_lo = 0x44556677L;  }    writel( fcChip->Registers.wwn_hi, 	  fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI);    writel( fcChip->Registers.wwn_lo, 	  fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);	    // readback for verification:  wwnHi = readl( fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI );             wwnLo = readl( fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);  // test for correct chip register WRITE/READ  DEBUG_PCI( printk("  WWN %08X%08X\n",    fcChip->Registers.wwn_hi, fcChip->Registers.wwn_lo ) );      if( wwnHi != fcChip->Registers.wwn_hi ||      wwnLo != fcChip->Registers.wwn_lo )  {    printk( "cpqfcTS: WorldWideName register load failed\n");    return -1; // FAILED!  }			// set Frame Manager Initialize command  fcChip->Registers.FMcontrol.value = 0x06;  // Note: for test/debug purposes, we may use "Hard" address,  // but we completely support "soft" addressing, including  // dynamically changing our address.  if( fcChip->Options.intLoopback == 1 )            // internal loopback    fcChip->Registers.FMconfig.value = 0x0f002080L;  else if( fcChip->Options.extLoopback == 1 )            // internal loopback    fcChip->Registers.FMconfig.value = 0x0f004080L;  else                  // L_Port    fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start)//    fcChip->Registers.FMconfig.value = 0x01000080L; // soft address (can't pick)//    fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start)		  // write config to FM  if( !fcChip->Options.intLoopback && !fcChip->Options.extLoopback )                               // (also need LASER for real LOOP)    fcChip->LaserControl( fcChip->Registers.ReMapMemBase, 1); // turn on LASER  writel( fcChip->Registers.FMconfig.value,    fcChip->Registers.FMconfig.address);    			       // issue INITIALIZE command to FM - ACTION!  writel( fcChip->Registers.FMcontrol.value,    fcChip->Registers.FMcontrol.address);      LEAVE("InitializeFrameManager");    return 0;}// This "look ahead" function examines the IMQ for occurence of// "type".  Returns 1 if found, 0 if not.static int PeekIMQEntry( PTACHYON fcChip, ULONG type){  ULONG CI = fcChip->IMQ->consumerIndex;  ULONG PI = fcChip->IMQ->producerIndex; // snapshot of IMQ indexes    while( CI != PI )  {                             // proceed with search    if( (++CI) >= IMQ_LEN ) CI = 0; // rollover check        switch( type )    {      case ELS_LILP_FRAME:      {      // first, we need to find an Inbound Completion message,      // If we find it, check the incoming frame payload (1st word)      // for LILP frame        if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x104 )        {           TachFCHDR_GCMND* fchs;          ULONG ulFibreFrame[2048/4];  // max DWORDS in incoming FC Frame	  USHORT SFQpi = (USHORT)(fcChip->IMQ->QEntry[CI].word[0] & 0x0fffL);	  CpqTsGetSFQEntry( fcChip,            SFQpi,        // SFQ producer ndx         	    ulFibreFrame, // contiguous dest. buffer	    FALSE);       // DON'T update chip--this is a "lookahead"          	  fchs = (TachFCHDR_GCMND*)&ulFibreFrame;          if( fchs->pl[0] == ELS_LILP_FRAME)	  {            return 1; // found the LILP frame!	  }	  else	  {	    // keep looking...	  }	}        }      break;      case OUTBOUND_COMPLETION:        if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x00 )	{          // any OCM errors?          if( fcChip->IMQ->QEntry[CI].word[2] & 0x7a000000L )            return 1;   	    // found OCM error	}      break;            default:      break;    }  }  return 0; // failed to find "type"}			static void SetTachTOV( CPQFCHBA* cpqfcHBAdata){  PTACHYON fcChip = &cpqfcHBAdata->fcChip;     // TL/TS UG, pg. 184  // 0x0065 = 100ms for RT_TOV  // 0x01f5 = 500ms for ED_TOV  // 0x07d1 = 2000ms for ED_TOV  // SANMark Level 1 requires an "initialization backoff"  // (See "SANMark Test Suite Level 1":  // initialization_timeout.fcal.SANMark-1.fc)  // We have to use 2sec, 24sec, then 128sec when login/  // port discovery processes fail to complete.    // when port discovery completes (logins done), we set  // ED_TOV to 500ms -- this is the normal operational case  // On the first Link Down, we'll move to 2 secs (7D1 ms)  if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x1f5)    fcChip->Registers.ed_tov.value = 0x006507D1;     // If we get another LST after we moved TOV to 2 sec,  // increase to 24 seconds (5DC1 ms) per SANMark!  else if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x7D1)    fcChip->Registers.ed_tov.value = 0x00655DC1;   // If we get still another LST, set the max TOV (Tachyon  // has only 16 bits for ms timer, so the max is 65.5 sec)  else if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x5DC1)    fcChip->Registers.ed_tov.value = 0x0065FFFF;   writel( fcChip->Registers.ed_tov.value,    (fcChip->Registers.ed_tov.address));  // keep the same 2sec LP_TOV   writel( 0x07D00010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);}	// The IMQ is an array with IMQ_LEN length, each element (QEntry)// with eight 32-bit words.  Tachyon PRODUCES a QEntry with each// message it wants to send to the host.  The host CONSUMES IMQ entries// This function copies the current// (or oldest not-yet-processed) QEntry to// the caller, clears/ re-enables the interrupt, and updates the// (Host) Consumer Index.// Return value://  0   message processed, none remain (producer and consumer//        indexes match)//  1   message processed, more messages remain// -1   no message processed - none were available to process// Remarks://   TL/TS UG specifices that the following actions for//   INTA_L handling://   1. read PCI Interrupt Status register (0xff)//   2. all IMQ messages should be processed before writing the//      IMQ consumer index.int CpqTsProcessIMQEntry(void *host){  struct Scsi_Host *HostAdapter = (struct Scsi_Host *)host;  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;  PTACHYON fcChip = &cpqfcHBAdata->fcChip;   FC_EXCHANGES *Exchanges = fcChip->Exchanges;  int iStatus;  USHORT i, RPCset, DPCset;  ULONG x_ID;  ULONG ulBuff, dwStatus;  TachFCHDR_GCMND* fchs;  ULONG ulFibreFrame[2048/4];  // max number of DWORDS in incoming Fibre Frame  UCHAR ucInboundMessageType;  // Inbound CM, dword 3 "type" field  ENTER("ProcessIMQEntry");   				// check TachLite's IMQ producer index -				// is a new message waiting for us?				// equal indexes means empty que  if( fcChip->IMQ->producerIndex != fcChip->IMQ->consumerIndex )  {                             // need to process message#ifdef IMQ_DEBUG    printk("PI %X, CI %X  type: %X\n",       fcChip->IMQ->producerIndex,fcChip->IMQ->consumerIndex,      fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type);#endif                                    // Examine Completion Messages in IMQ    // what CM_Type?    switch( (UCHAR)(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type                    & 0xffL) )    {    case OUTBOUND_COMPLETION:      // Remarks:      // x_IDs (OX_ID, RX_ID) are partitioned by SEST entries      // (starting at 0), and SFS entries (starting at      // SEST_LEN -- outside the SEST space).      // Psuedo code:      // x_ID (OX_ID or RX_ID) from message is Trans_ID or SEST index      // range check - x_ID      //   if x_ID outside 'Transactions' length, error - exit      // if any OCM error, copy error status to Exchange slot      // if FCP ASSIST transaction (x_ID within SEST),      //   call fcComplete (to App)      // ...      ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1];      x_ID = ulBuff & 0x7fffL;     // lower 14 bits SEST_Index/Trans_ID                                     // Range check CM OX/RX_ID value...      if( x_ID < TACH_MAX_XID )   // don't go beyond array space      {	if( ulBuff & 0x20000000L ) // RPC -Response Phase Complete?          RPCset = 1;              // (SEST transactions only)        else          RPCset = 0;        if( ulBuff & 0x40000000L ) // DPC -Data Phase Complete?          DPCset = 1;              // (SEST transactions only)        else          DPCset = 0;                // set the status for this Outbound transaction's ID        dwStatus = 0L;        if( ulBuff & 0x10000000L ) // SPE? (SEST Programming Error)            dwStatus |= SESTPROG_ERR;        ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2];        if( ulBuff & 0x7a000000L ) // any other errs?        {          if( ulBuff & 0x40000000L )            dwStatus |= INV_ENTRY;          if( ulBuff & 0x20000000L )            dwStatus |= FRAME_TO;        // FTO          if( ulBuff & 0x10000000L )            dwStatus |= HOSTPROG_ERR;          if( ulBuff & 0x08000000L )            dwStatus |= LINKFAIL_TX;          if( ulBuff & 0x02000000L )            dwStatus |= ABORTSEQ_NOTIFY;  // ASN        }	  	if( dwStatus )          // any errors?        {                  // set the Outbound Completion status          Exchanges->fcExchange[ x_ID ].status |= dwStatus;          // if this Outbound frame was for a SEST entry, automatically          // reque it in the case of LINKFAIL (it will restart on PDISC)          if( x_ID < TACH_SEST_LEN )          {            printk(" #OCM error %Xh x_ID %X# ", 		    dwStatus, x_ID);	    Exchanges->fcExchange[x_ID].timeOut = 30000; // seconds default                                                 	    // We Q ABTS for each exchange.	    // NOTE: We can get FRAME_TO on bad alpa (device gone).  Since

⌨️ 快捷键说明

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