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

📄 cpqfctscontrol.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    // NOTE: according to TL/TS UG, the     // "host must return completion messages in sequential order".    // Does this mean one at a time, in the order received?  We    // presume so.    writel( fcChip->IMQ->consumerIndex,      (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));		    #if IMQ_DEBUG    printk("Process IMQ: writing consumer ndx %d\n ",       fcChip->IMQ->consumerIndex);    printk("PI %X, CI %X\n",     fcChip->IMQ->producerIndex,fcChip->IMQ->consumerIndex );#endif    }  else  {   // hmmm... why did we get interrupted/called with no message?    iStatus = -1;               // nothing to process#if IMQ_DEBUG    printk("Process IMQ: no message PI %Xh  CI %Xh",       fcChip->IMQ->producerIndex,      fcChip->IMQ->consumerIndex);#endif  }  LEAVE("ProcessIMQEntry");    return iStatus;}// This routine initializes Tachyon according to the following// options (opcode1):// 1 - RESTART Tachyon, simulate power on condition by shutting//     down laser, resetting the hardware, de-allocating all buffers;//     continue// 2 - Config Tachyon / PCI registers;//     continue// 3 - Allocating memory and setting Tachyon queues (write Tachyon regs);//     continue// 4 - Config frame manager registers, initialize, turn on laser//// Returns://  -1 on fatal error//   0 on successint CpqTsInitializeTachLite( void *pHBA, int opcode1, int opcode2){  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;  PTACHYON fcChip = &cpqfcHBAdata->fcChip;  ULONG ulBuff;  UCHAR bBuff;  int iStatus=-1;  // assume failure  ENTER("InitializeTachLite");  // verify board's base address (sanity check)  if( !fcChip->Registers.ReMapMemBase)                // NULL address for card?    return -1;                         // FATAL error!  switch( opcode1 )  {    case 1:       // restore hardware to power-on (hard) restart      iStatus = fcChip->ResetTachyon( 		  cpqfcHBAdata, opcode2); // laser off, reset hardware				      // de-allocate aligned buffers/* TBD      // reset FC link Q (producer and consumer = 0)      fcLinkQReset(cpqfcHBAdata); */      if( iStatus )        break;    case 2:       // Config PCI/Tachyon registers      // NOTE: For Tach TL/TS, bit 31 must be set to 1.  For TS chips, a read      // of bit 31 indicates state of M66EN signal; if 1, chip may run at       // 33-66MHz  (see TL/TS UG, pg 159)      ulBuff = 0x80000000;  // TachLite Configuration Register      writel( ulBuff, fcChip->Registers.TYconfig.address);//      ulBuff = 0x0147L;  // CpqTs PCI CFGCMD register//      WritePCIConfiguration( fcChip->Backplane.bus,//                           fcChip->Backplane.slot, TLCFGCMD, ulBuff, 4);//      ulBuff = 0x0L;  // test!//      ReadPCIConfiguration( fcChip->Backplane.bus,//                           fcChip->Backplane.slot, TLCFGCMD, &ulBuff, 4);      // read back for reference...      fcChip->Registers.TYconfig.value =          readl( fcChip->Registers.TYconfig.address );      // what is the PCI bus width?      pci_read_config_byte( cpqfcHBAdata->PciDev,                                0x43, // PCIMCTR offset                                &bBuff);            fcChip->Registers.PCIMCTR = bBuff;      // set string identifying the chip on the circuit board      fcChip->Registers.TYstatus.value =        readl( fcChip->Registers.TYstatus.address);            {// Now that we are supporting multiple boards, we need to change// this logic to check for PCI vendor/device IDs...// for now, quick & dirty is simply checking Chip rev		ULONG RevId = (fcChip->Registers.TYstatus.value &0x3E0)>>5;	UCHAR Minor = (UCHAR)(RevId & 0x3);	UCHAR Major = (UCHAR)((RevId & 0x1C) >>2);          printk("  HBA Tachyon RevId %d.%d\n", Major, Minor);  	if( (Major == 1) && (Minor == 2) )        {	  sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS12);	}	else if( (Major == 1) && (Minor == 3) )        {	  sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS13);	}	else if( (Major == 2) && (Minor == 1) )        {	  sprintf( cpqfcHBAdata->fcChip.Name, SAGILENT_XL2_21);	}	else	  sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE_UNKNOWN);      }    case 3:       // allocate mem, set Tachyon Que registers      iStatus = CpqTsCreateTachLiteQues( cpqfcHBAdata, opcode2);      // now that the Queues exist, Tach can DMA to them, so      // we can begin processing INTs      // INTEN register - enable INT (TachLite interrupt)      writeb( 0x1F, fcChip->Registers.ReMapMemBase + IINTEN);      if( iStatus )        break;    case 4:       // Config Fame Manager, Init Loop Command, laser on                 // L_PORT or loopback                 // depending on Options      iStatus = CpqTsInitializeFrameManager( fcChip,0 );      if( iStatus )      {           // failed to initialize Frame Manager	      break;      }    default:      break;  }  LEAVE("InitializeTachLite");    return iStatus;}// Depending on the type of platform memory allocation (e.g. dynamic),// it's probably best to free memory in opposite order as it was allocated.// Order of allocation: see other functionint CpqTsDestroyTachLiteQues( void *pHBA, int opcode){  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;  PTACHYON fcChip = &cpqfcHBAdata->fcChip;  USHORT i, j, iStatus=0;  void* vPtr;  // mem Align manager sets this to the freed address on success  unsigned long ulPtr;  // for 64-bit pointer cast (e.g. Alpa machine)  ENTER("DestroyTachLiteQues");  if( fcChip->SEST )  {                // search out and free Pool for Extended S/G list pages    for( i=0, j=0; i < TACH_SEST_LEN; i++, j=0)  // for each exchange    {      // It's possible that extended S/G pages were allocated and      // not cleared due to error conditions or O/S driver termination.      // Make sure they're all gone.      while( fcChip->SEST->sgPages[i].PoolPage[j] &&        (j < TL_MAX_SGPAGES))        kfree( fcChip->SEST->sgPages[i].PoolPage[j++]);    }    ulPtr = (unsigned long)fcChip->SEST;    vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],		    0,0, (ULONG)ulPtr ); // 'free' mem    fcChip->SEST = 0L;  // null invalid ptr    if( !vPtr )    {      printk("SEST mem not freed\n");      iStatus = -1;    }  }  if( fcChip->SFQ )  {    ulPtr = (unsigned long)fcChip->SFQ;    vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],		    0,0, (ULONG)ulPtr ); // 'free' mem    fcChip->SFQ = 0L;  // null invalid ptr    if( !vPtr )    {      printk("SFQ mem not freed\n");      iStatus = -2;    }  }  if( fcChip->IMQ )  {      // clear Indexes to show empty Queue    fcChip->IMQ->producerIndex = 0;    fcChip->IMQ->consumerIndex = 0;    ulPtr = (unsigned long)fcChip->IMQ;    vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],		    0,0, (ULONG)ulPtr ); // 'free' mem    fcChip->IMQ = 0L;  // null invalid ptr    if( !vPtr )    {      printk("IMQ mem not freed\n");      iStatus = -3;    }  }  if( fcChip->ERQ )         // release memory blocks used by the queues  {    ulPtr = (unsigned long)fcChip->ERQ;    vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],		    0,0, (ULONG)ulPtr ); // 'free' mem    fcChip->ERQ = 0L;  // null invalid ptr    if( !vPtr )    {      printk("ERQ mem not freed\n");      iStatus = -4;    }  }      // free up the primary EXCHANGES struct  if( fcChip->Exchanges != NULL)  {//    printk("kfree() on Exchanges @%p\n", fcChip->Exchanges);    kfree( fcChip->Exchanges);  }  // free up Link Q  if( cpqfcHBAdata->fcLQ != NULL )  {//    printk("kfree() on LinkQ @%p\n", fcChip->fcLQ);    kfree( cpqfcHBAdata->fcLQ);  }    LEAVE("DestroyTachLiteQues");    return iStatus;     // non-zero (failed) if any memory not freed}// The SFQ is an array with SFQ_LEN length, each element (QEntry)// with eight 32-bit words.  TachLite places incoming FC frames (i.e.// a valid FC frame with our AL_PA ) in contiguous SFQ entries// and sends a completion message telling the host where the frame is// in the que.// This function copies the current (or oldest not-yet-processed) QEntry to// a caller's contiguous buffer and updates the Tachyon chip's consumer index//// NOTE://   An FC frame may consume one or many SFQ entries.  We know the total//   length from the completion message.  The caller passes a buffer large//   enough for the complete message (max 2k).static void CpqTsGetSFQEntry(         PTACHYON fcChip,         USHORT producerNdx,         ULONG *ulDestPtr,            // contiguous destination buffer	 BOOLEAN UpdateChip){  ULONG total_bytes=0;  ULONG consumerIndex = fcChip->SFQ->consumerIndex;  				// check passed copy of SFQ producer index -				// is a new message waiting for us?				// equal indexes means SFS is copied  while( producerNdx != consumerIndex )  {                             // need to process message    total_bytes += 64;   // maintain count to prevent writing past buffer                   // don't allow copies over Fibre Channel defined length!    if( total_bytes <= 2048 )    {      memcpy( ulDestPtr,               &fcChip->SFQ->QEntry[consumerIndex],              64 );  // each SFQ entry is 64 bytes      ulDestPtr += 16;   // advance pointer to next 64 byte block    }		         // Tachyon is producing,                         // and we are consuming    if( ++consumerIndex >= SFQ_LEN)// check for rollover      consumerIndex = 0L;        // reset it  }  // if specified, update the Tachlite chip ConsumerIndex...  if( UpdateChip )  {    fcChip->SFQ->consumerIndex = consumerIndex;    writel( fcChip->SFQ->consumerIndex,      fcChip->Registers.SFQconsumerIndex.address);  }}// TachLite routinely freezes it's core ques - Outbound FIFO, Inbound FIFO,// and Exchange Request Queue (ERQ) on error recover - // (e.g. whenever a LIP occurs).  Here// we routinely RESUME by clearing these bits, but only if the loop is up// to avoid ERROR IDLE messages forever.void CpqTsUnFreezeTachlite( void *pChip, int type ){  PTACHYON fcChip = (PTACHYON)pChip;  fcChip->Registers.TYcontrol.value =     readl(fcChip->Registers.TYcontrol.address);              // (bit 4 of value is GBIC LASER)  // if we 'unfreeze' the core machines before the loop is healthy  // (i.e. FLT, OS, LS failure bits set in FMstatus)  // we can get 'error idle' messages forever.  Verify that  // FMstatus (Link Status) is OK before unfreezing.  if( !(fcChip->Registers.FMstatus.value & 0x07000000L) && // bits clear?      !(fcChip->Registers.FMstatus.value & 0x80  ))  // Active LPSM?  {    fcChip->Registers.TYcontrol.value &=  ~0x300L; // clear FEQ, FFA    if( type == 1 )  // unfreeze ERQ only    {//      printk("Unfreezing ERQ\n");      fcChip->Registers.TYcontrol.value |= 0x10000L; // set REQ    }    else             // unfreeze both ERQ and FCP-ASSIST (SEST)    {//      printk("Unfreezing ERQ & FCP-ASSIST\n");                     // set ROF, RIF, REQ - resume Outbound FCP, Inbnd FCP, ERQ      fcChip->Registers.TYcontrol.value |= 0x70000L; // set ROF, RIF, REQ    }    writel( fcChip->Registers.TYcontrol.value,      fcChip->Registers.TYcontrol.address);                }          // readback for verify (TachLite still frozen?)  fcChip->Register

⌨️ 快捷键说明

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