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

📄 cpqfctsworker.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      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 (prior login OK)      {             	if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id)	{          // Yes.  We were expecting PDISC?          if( pLoggedInPort->pdisc )	  {	    // Yes; set fields accordingly.     (PDISC, not Originator)            SetLoginFields( pLoggedInPort, fchs, TRUE, FALSE);                   // send 'ACC' reply             cpqfcTSPutLinkQue( cpqfcHBAdata,                           ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC)                          fchs );	    // OK to resume I/O...	  }	  else 	  {	    printk("Not expecting PDISC (pdisc=FALSE)\n");	    NeedReject = TRUE;	    // set reject reason code             ls_reject_code =               LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);	  }	}	else	{	  if( pLoggedInPort->port_id != 0)	  {  	    printk("PDISC PortID change: old %Xh, new %Xh\n",              pLoggedInPort->port_id, fchs->s_id &0xFFFFFF);	  }          NeedReject = TRUE;          // set reject reason code           ls_reject_code = 	    LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);		  	}      }      else      {	printk("PDISC Request from unknown WWN\n");        NeedReject = TRUE;          	// set reject reason code         ls_reject_code =           LS_RJT_REASON( LOGICAL_ERROR, INVALID_PORT_NAME);      }    }    else // Payload unacceptable    {      printk("payload unacceptable\n");      NeedReject = TRUE;  // reject code already set          }    if( NeedReject)    {      ULONG port_id;      // The PDISC failed.  Set login struct flags accordingly,      // terminate any I/O to this port, and Q a PLOGI      if( pLoggedInPort )      {        pLoggedInPort->pdisc = FALSE;        pLoggedInPort->prli = FALSE;        pLoggedInPort->plogi = FALSE;	        cpqfcTSTerminateExchange( cpqfcHBAdata,           &pLoggedInPort->ScsiNexus, PORTID_CHANGED);	port_id = pLoggedInPort->port_id;      }      else      {	port_id = fchs->s_id &0xFFFFFF;      }      fchs->reserved = ls_reject_code; // borrow this (unused) field      cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_RJT, fchs );    }       break;  case 0x0003: //  PLOGI?    // Payload for PLOGI and PDISC is identical (request & reply)    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) // valid payload?    {      LOGIN_PAYLOAD logi;       // FC-PH Port Login      BOOLEAN NeedReject = FALSE;            // PDISC payload OK. If critical login fields      // (e.g. WWN) matches last login for this port_id,      // we may resume any prior exchanges      // with the other port            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	          NeedReject = TRUE;  	            // set reject reason code           ls_reject_code =             LS_RJT_REASON( LOGICAL_ERROR, NO_LOGIN_RESOURCES);	    	}      }      if( !NeedReject )      {              // OK - we have valid fcPort ptr; set fields accordingly.   	//                         (not PDISC, not Originator)        SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);         // send 'ACC' reply         cpqfcTSPutLinkQue( cpqfcHBAdata,                       ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC)                      fchs );      }    }    else // Payload unacceptable    {      printk("payload unacceptable\n");      NeedReject = TRUE;  // reject code already set    }    if( NeedReject)    {      // The PDISC failed.  Set login struct flags accordingly,      // terminate any I/O to this port, and Q a PLOGI      pLoggedInPort->pdisc = FALSE;      pLoggedInPort->prli = FALSE;      pLoggedInPort->plogi = FALSE;	      fchs->reserved = ls_reject_code; // borrow this (unused) field      // send 'RJT' reply       cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_RJT, fchs );    }       // terminate any exchanges with this device...    if( pLoggedInPort )    {      cpqfcTSTerminateExchange( cpqfcHBAdata,         &pLoggedInPort->ScsiNexus, PORTID_CHANGED);    }    break;  case 0x1020:  // PRLI?  {    BOOLEAN NeedReject = TRUE;    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 Request -not logged in!\n");      // set reject reason code       ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);            // Q a LOGOut here?    }    else    {      // 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; not Originator)          SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);          // Q an ACCept Reply	  cpqfcTSPutLinkQue( cpqfcHBAdata,                        ELS_PRLI_ACC,                         fchs );   	  	  NeedReject = FALSE;	}        else        {          // huh?          printk(" (unexpected) PRLI REQEST with plogi FALSE\n");          // set reject reason code           ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);        	  // Q a LOGOut here?	          }      }      else      {        printk(" PRLI REQUEST payload failed verify\n");        // (reject code set by "verify")        // Q a LOGOut here?      }    }    if( NeedReject )    {      // Q a ReJecT Reply with reason code      fchs->reserved = ls_reject_code;      cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_RJT, // Q Type                    fchs );      }  }    break;       case  0x0005:  // LOGOut?  {  // was this LOGOUT because we sent a ELS_PDISC to an FC device  // with changed (or new) port_id, or does the port refuse   // to communicate to us?  // We maintain a logout counter - if we get 3 consecutive LOGOuts,  // give up!    LOGOUT_PAYLOAD logo;    BOOLEAN GiveUpOnDevice = FALSE;    ULONG ls_reject_code = 0;        BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logo, sizeof(logo));    pLoggedInPort = fcFindLoggedInPort(            fcChip,            NULL,     // don't search Scsi Nexus	   0,        // don't search linked list for port_id           &logo.port_name[0],     // search linked list for WWN           NULL);    // don't care about end of list        if( pLoggedInPort ) // found the device?    {      // Q an ACC reply       cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_LOGO_ACC, // Q Type                    fchs );       // device to respond to      // set login struct fields (LOGO_counter increment)      SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);            // are we an Initiator?      if( fcChip->Options.initiator)        {        // we're an Initiator, so check if we should 	// try (another?) login	// Fabrics routinely log out from us after	// getting device info - don't try to log them	// back in.	if( (fchs->s_id & 0xFFF000) == 0xFFF000 )	{	  ; // do nothing	}	else if( pLoggedInPort->LOGO_counter <= 3)	{	  // try (another) login (PLOGI request)	            cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_PLOGI, // Q Type                    fchs );  		  // Terminate I/O with "retry" potential	  cpqfcTSTerminateExchange( cpqfcHBAdata, 			            &pLoggedInPort->ScsiNexus,				    PORTID_CHANGED);	}	else	{	  printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n",			  fchs->s_id &&0xFFFFFF);	  GiveUpOnDevice = TRUE;	}      }      else      {	GiveUpOnDevice = TRUE;      }      if( GiveUpOnDevice == TRUE )      {        cpqfcTSTerminateExchange( cpqfcHBAdata, 	                          &pLoggedInPort->ScsiNexus,		                  DEVICE_REMOVED);      }    }      else  // we don't know this WWN!    {      // Q a ReJecT Reply with reason code      fchs->reserved = ls_reject_code;      cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_RJT, // Q Type                    fchs );      }  }    break;  // FABRIC only case  case 0x0461:  // ELS RSCN (Registered State Change Notification)?  {    int Ports;    int i;    __u32 Buff;    // Typically, one or more devices have been added to or dropped    // from the Fabric.    // The format of this frame is defined in FC-FLA (Rev 2.7, Aug 1997)    // The first 32-bit word has a 2-byte Payload Length, which    // includes the 4 bytes of the first word.  Consequently,    // this PL len must never be less than 4, must be a multiple of 4,    // and has a specified max value 256.    // (Endianess!)    Ports = ((fchs->pl[0] >>24) - 4) / 4;    Ports = Ports > 63 ? 63 : Ports;        printk(" RSCN ports: %d\n", Ports);    if( Ports <= 0 )  // huh?    {      // ReJecT the command      fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, 0);          cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_RJT, // Q Type                    fchs );             break;    }    else  // Accept the command    {       cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_ACC, // Q Type                    fchs );     }          // Check the "address format" to determine action.      // We have 3 cases:      // 0 = Port Address; 24-bit address of affected device      // 1 = Area Address; MS 16 bits valid      // 2 = Domain Address; MS 8 bits valid    for( i=0; i<Ports; i++)    {       BigEndianSwap( (UCHAR*)&fchs->pl[i+1],(UCHAR*)&Buff, 4);      switch( Buff & 0xFF000000)      {      case 0:  // Port Address?	      case 0x01000000: // Area Domain?      case 0x02000000: // Domain Address        // For example, "port_id" 0x201300 	// OK, let's try a Name Service Request (Query)      fchs->s_id = 0xFFFFFC;  // Name Server Address      cpqfcTSPutLinkQue( cpqfcHBAdata, FCS_NSR, fchs);      break;		      default:  // huh? new value on version change?      break;      }    }  }      break;          default:  // don't support this request (yet)    // set reject reason code     fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, 		                    REQUEST_NOT_SUPPORTED);        cpqfcTSPutLinkQue( cpqfcHBAdata,                    ELS_RJT, // Q Type                    fchs );         break;  

⌨️ 快捷键说明

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