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

📄 cpqfctsworker.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  }}static void ProcessELS_Reply( 		CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs){  PTACHYON fcChip = &cpqfcHBAdata->fcChip;  FC_EXCHANGES *Exchanges = fcChip->Exchanges;  ULONG ox_id = (fchs->ox_rx_id >>16);  ULONG ls_reject_code;  PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;    // If this is a valid reply, then we MUST have sent a request.  // Verify that we can find a valid request OX_ID corresponding to  // this reply    if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0)  {    printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ", 		    ox_id, fchs->ox_rx_id & 0xffff);    goto Quit;  // exit this routine  }  // Is the reply a RJT (reject)?  if( (fchs->pl[0] & 0xFFFFL) == 0x01) // Reject reply?  {//  ******  REJECT REPLY  ********    switch( Exchanges->fcExchange[ox_id].type )    {	      case ELS_FDISC:  // we sent out Fabric Discovery    case ELS_FLOGI:  // we sent out FLOGI      printk("RJT received on Fabric Login from %Xh, reason %Xh\n",         fchs->s_id, fchs->pl[1]);        break;    default:    break;    }          goto Done;  }  // OK, we have an ACCept...  // What's the ACC type? (according to what we sent)  switch( Exchanges->fcExchange[ox_id].type )  {	    case ELS_PLOGI:  // we sent out PLOGI    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) )    {      LOGIN_PAYLOAD logi;       // FC-PH Port Login            // login ACC payload acceptable; search for WWN in our list      // of fcPorts            BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));         pLoggedInPort = fcFindLoggedInPort(              fcChip, 	     NULL,     // don't search Scsi Nexus	     0,        // don't search linked list for port_id             &logi.port_name[0],     // search linked list for WWN             &pLastLoggedInPort);  // must return non-NULL; when a port_id                                   // is not found, this pointer marks the                                   // end of the singly linked list          if( pLoggedInPort == NULL)         // WWN not found - new port      {	pLoggedInPort = CreateFcPort( 			  cpqfcHBAdata, 			  pLastLoggedInPort, 			  fchs,			  &logi);        if( pLoggedInPort == NULL )        {          printk(" cpqfcTS: New port allocation failed - lost FC device!\n");          // Now Q a LOGOut Request, since we won't be talking to that device	          goto Done;  // exit with error! dropped login frame	}      }      else      // WWN was already known.  Ensure that any open	        // exchanges for this WWN are terminated.      	// NOTE: It's possible that a device can change its 	// 24-bit port_id after a Link init or Fabric change 	// (e.g. LIP or Fabric RSCN).  In that case, the old	// 24-bit port_id may be duplicated, or no longer exist.      {        cpqfcTSTerminateExchange( cpqfcHBAdata,           &pLoggedInPort->ScsiNexus, PORTID_CHANGED);      }      // We have an fcPort struct - set fields accordingly                                    // not PDISC, originator       SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE);			      // We just set a "port_id"; is it duplicated?      TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort);      // For Fabric operation, we issued PLOGI to 0xFFFFFC      // so we can send SCR (State Change Registration)       // Check for this special case...      if( fchs->s_id == 0xFFFFFC )       {        // PLOGI ACC was a Fabric response... issue SCR	fchs->s_id = 0xFFFFFD;  // address for SCR        cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_SCR, fchs);      }      else      {      // Now we need a PRLI to enable FCP-SCSI operation      // set flags and Q up a ELS_PRLI        cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PRLI, fchs);      }    }    else    {      // login payload unacceptable - reason in ls_reject_code      // Q up a Logout Request      printk("Login Payload unacceptable\n");    }    break;  // PDISC logic very similar to PLOGI, except we never want  // to allocate mem for "new" port, and we set flags differently  // (might combine later with PLOGI logic for efficiency)    case ELS_PDISC:  // we sent out PDISC    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) )    {      LOGIN_PAYLOAD logi;       // FC-PH Port Login      BOOLEAN NeedLogin = FALSE;            // login payload acceptable; search for WWN in our list      // of (previously seen) fcPorts            BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));         pLoggedInPort = fcFindLoggedInPort(              fcChip, 	     NULL,     // don't search Scsi Nexus	     0,        // don't search linked list for port_id             &logi.port_name[0],     // search linked list for WWN             &pLastLoggedInPort);  // must return non-NULL; when a port_id                                   // is not found, this pointer marks the                                   // end of the singly linked list          if( pLoggedInPort != NULL)   // WWN found?      {        // WWN has same port_id as last login?  (Of course, a properly	// working FC device should NEVER ACCept a PDISC if it's	// port_id changed, but check just in case...)	if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id)	{          // Yes.  We were expecting PDISC?          if( pLoggedInPort->pdisc )	  {            int i;	    	    	    // PDISC expected -- set fields.  (PDISC, Originator)            SetLoginFields( pLoggedInPort, fchs, TRUE, TRUE);	    // We are ready to resume FCP-SCSI to this device...            // Do we need to start anything that was Queued?            for( i=0; i< TACH_SEST_LEN; i++)            {              // see if any exchange for this PDISC'd port was queued              if( ((fchs->s_id &0xFFFFFF) ==                    (Exchanges->fcExchange[i].fchs.d_id & 0xFFFFFF))                      &&                  (Exchanges->fcExchange[i].status & EXCHANGE_QUEUED))              {                fchs->reserved = i; // copy ExchangeID//                printk(" *Q x_ID %Xh after PDISC* ",i);                cpqfcTSPutLinkQue( cpqfcHBAdata, EXCHANGE_QUEUED, fchs );              }            }	    // Complete commands Q'd while we were waiting for Login	    UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort);	  }	  else	  {	    printk("Not expecting PDISC (pdisc=FALSE)\n");	    NeedLogin = TRUE;	  }	}	else	{	  printk("PDISC PortID change: old %Xh, new %Xh\n",            pLoggedInPort->port_id, fchs->s_id &0xFFFFFF);          NeedLogin = TRUE;		  	}      }      else      {	printk("PDISC ACC from unknown WWN\n");        NeedLogin = TRUE;      }      if( NeedLogin)      {	        // The PDISC failed.  Set login struct flags accordingly,	// terminate any I/O to this port, and Q a PLOGI	if( pLoggedInPort )  // FC device previously known?	{          cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_LOGO, // Q Type                    fchs );   // has port_id to send to 	  // There are a variety of error scenarios which can result  	  // in PDISC failure, so as a catchall, add the check for	  // duplicate port_id.	  TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort);//    TriggerHBA( fcChip->Registers.ReMapMemBase, 0);          pLoggedInPort->pdisc = FALSE;          pLoggedInPort->prli = FALSE;          pLoggedInPort->plogi = FALSE;	          cpqfcTSTerminateExchange( cpqfcHBAdata, 	    &pLoggedInPort->ScsiNexus, PORTID_CHANGED);        }        cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI, fchs );      }    }    else    {      // login payload unacceptable - reason in ls_reject_code      // Q up a Logout Request      printk("ERROR: Login Payload unacceptable!\n");    }       break;      case ELS_PRLI:  // we sent out PRLI    pLoggedInPort = fcFindLoggedInPort(            fcChip,            NULL,       // don't search Scsi Nexus	   (fchs->s_id & 0xFFFFFF),  // search linked list for port_id           NULL,     // DON'T search linked list for WWN           NULL);    // don't care          if( pLoggedInPort == NULL )     {      // huh?      printk(" Unexpected PRLI ACCept frame!\n");      // Q a LOGOut here?      goto Done;    }    // verify the PRLI ACC payload    if( !verify_PRLI( fchs, &ls_reject_code) )    {      // PRLI Reply is acceptable; were we expecting it?      if( pLoggedInPort->plogi )       { 	// yes, we expected the PRLI ACC  (not PDISC; Originator)	SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE);        // OK, let's send a REPORT_LUNS command to determine	// whether VSA or PDA FCP-LUN addressing is used.	        cpqfcTSPutLinkQue( cpqfcHBAdata, SCSI_REPORT_LUNS, fchs );		// It's possible that a device we were talking to changed 	// port_id, and has logged back in.  This function ensures	// that I/O will resume.        UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort);      }      else      {        // huh?        printk(" (unexpected) PRLI ACCept with plogi FALSE\n");        // Q a LOGOut here?        goto Done;      }    }    else    {      printk(" PRLI ACCept payload failed verify\n");      // Q a LOGOut here?    }    break;   case ELS_FLOGI:  // we sent out FLOGI (Fabric Login)    // update the upper 16 bits of our port_id in Tachyon    // the switch adds those upper 16 bits when responding    // to us (i.e. we are the destination_id)    fcChip->Registers.my_al_pa = (fchs->d_id & 0xFFFFFF);    writel( fcChip->Registers.my_al_pa,        fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);    // now send out a PLOGI to the well known port_id 0xFFFFFC    fchs->s_id = 0xFFFFFC;    cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI, fchs);     break;   case ELS_FDISC:  // we sent out FDISC (Fabric Discovery (Login))   printk( " ELS_FDISC success ");   break;     case ELS_SCR:  // we sent out State Change Registration    // now we can issue Name Service Request to find any    // Fabric-connected devices we might want to login to.   	    fchs->s_id = 0xFFFFFC;  // Name Server Address    cpqfcTSPutLinkQue( cpqfcHBAdata, FCS_NSR, fchs);        break;      default:    printk(" *Discarding unknown ACC frame, xID %04X/%04X* ",    		    ox_id, fchs->ox_rx_id & 0xffff);    break;  }  Done:  // Regardless of whether the Reply is valid or not, the  // the exchange is done - complete  cpqfcTSCompleteExchange( fcChip, (fchs->ox_rx_id >>16)); // complete	  Quit:      return;}// ****************  Fibre Channel Services  **************// This is where we process the Directory (Name) Service Reply// to know which devices are on the Fabricstatic void ProcessFCS_Reply( 	CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs){  PTACHYON fcChip = &cpqfcHBAdata->fcChip;  FC_EXCHANGES *Exchanges = fcChip->Exchanges;  ULONG ox_id = (fchs->ox_rx_id >>16);//  ULONG ls_reject_code;//  PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;    // If this is a valid reply, then we MUST have sent a request.  // Verify that we can find a valid request OX_ID corresponding to  // this reply  if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0)  {    printk(" *Discarding Reply frame, xID %04X/%04X* ", 		    ox_id, fchs->ox_rx_id & 0xffff);    goto Quit;  // exit this routine  }  // OK, we were expecting it.  Now check to see if it's a  // "Name Service" Reply, and if so force a re-validation of  // Fabric device logins (i.e. Start the login timeout and  // send PDISC or PLOGI)  // (Endianess Byte Swap?)  if( fchs->pl[1] == 0x02FC )  // Name Service  {    // got a new (or NULL) list of Fabric attach devices...     // Invalidate current logins        PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;    while( pLoggedInPort ) // for all ports which are expecting                           // PDISC after the next LIP, set the                           // logoutTimer    {      if( (pLoggedInPort->port_id & 0xFFFF00)  // Fabric device?		      &&          (pLoggedInPort->port_id != 0xFFFFFC) ) // NOT the F_Port      {        pLoggedInPort->LOGO_timer = 6;  // what's the Fabric timeout??                                // suspend any I/O in progress until                                // PDISC received...        pLoggedInPort->prli = FALSE;   // block FCP-SCSI commands      }	          pLoggedInPort = pLoggedInPort->pNextPort;    }        if( fchs->pl[2] == 0x

⌨️ 快捷键说明

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