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

📄 scsictrllib.c

📁 the vxworks system kernel souce packeg.there may be something you need .
💻 C
📖 第 1 页 / 共 4 页
字号:
    return ((xferCount == pThread->statusLength) ? OK : ERROR);    }/******************************************************************************** scsiCtrlMsgOutAction - respond to a request to send a SCSI message** This routine handles a SCSI message out transfer request.  If there is no* message available to send to the target, a SCSI NO-OP message is sent.* If there is a message which has already been sent, ATN is asserted (this is* a requirement imposed by the SCSI specification).** Data is output from the message-out buffer in a single transfer.  The* controller hardware must keep ATN asserted until just before ACK is* asserted during the last byte of the outgoing message, per SCSI 5.2.1.** Assuming the information transfer does not fail altogether, there are two* "successful" outcomes:** 1)    the entire message is transferred - in this case the message state*   	is set to SENT.	 However, the target is not deemed to have accepted*   	the message until it requests a different phase - this is detected*   	and acted upon in "scsiCtrlNormalXfer()".  (If the target continues*   	to request a MSG OUT transfer, it wants the current message to be*   	re-sent.)** 2)	the message is only partially transferred - most likely because the*   	target has changed phase (e.g., to send a Reject message) before*   	all the message out bytes have been transferred.  In this case the*   	message state remains PENDING.  If the target is about to reject it,*   	the state will be reset then, otherwise we will try to send it again*   	when the target next requests a message out transfer.** Note: it is assumed that the length of the message never exceeds the* maximum byte count the controller can handle.** RETURNS: OK, or ERROR if information transfer phase fails.*/LOCAL STATUS scsiCtrlMsgOutAction    (    SCSI_CTRL   *pScsiCtrl,		/* ptr to SCSI controller info */    SCSI_THREAD *pThread		/* ptr to thread info */    )    {    UINT xferCount;			/* number of bytes transferred */        if ((pScsiCtrl->msgOutState == SCSI_MSG_OUT_SENT) &&	(pScsiCtrl->msgOutLength > 1))	{	/* target is retrying: need to assert ATN (SCSI 5.1.9.2) */		if ((*pScsiCtrl->scsiBusControl) (pScsiCtrl,				          SCSI_BUS_ASSERT_ATN) != OK)	    {	    SCSI_ERROR_MSG ("scsiCtrlMsgOutAction: can't assert ATN.\n",			    0, 0, 0, 0, 0, 0);	    return (ERROR);	    }	}        if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_NONE)	{	pScsiCtrl->msgOutBuf[0] = SCSI_MSG_NO_OP;	pScsiCtrl->msgOutLength = 1;	}    xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,					    SCSI_MSG_OUT_PHASE,                                            pScsiCtrl->msgOutBuf,                                            pScsiCtrl->msgOutLength);    if (xferCount == ERROR)	return (ERROR);    if (xferCount == pScsiCtrl->msgOutLength)	pScsiCtrl->msgOutState =  SCSI_MSG_OUT_SENT;    return (OK);    }/******************************************************************************** scsiCtrlMsgInAction - respond to an incoming SCSI message** Read and handle an incoming message from the target.** Note that if the incoming message is a SCSI Extended Message, it needs to* be read in three chunks (the message type, the additional length and the* extended message itself).  This is achieved by using a finite state machine* which cycles through the chunks, returning to the phase sequencing code* until the message is complete.** RETURNS: OK, or ERROR if information transfer phase fails.*/LOCAL STATUS scsiCtrlMsgInAction    (    SCSI_CTRL   *pScsiCtrl,		/* ptr to SCSI controller info */    SCSI_THREAD *pThread		/* ptr to thread info */    )    {    /*     *	Handle (possibly partial) message transfer     */    if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)	SCSI_DEBUG_MSG ("scsiCtrlMsgInAction: msg in while msg out pending\n",			0, 0, 0, 0, 0, 0);    if (scsiCtrlMsgInXfer (pScsiCtrl) != OK)	return (ERROR);    /*     *  If we have a complete message, parse it and respond appropriately     */    if (pScsiCtrl->msgInState == SCSI_MSG_IN_NONE)        (void) scsiMsgInComplete (pScsiCtrl, pThread);    /*     *	Negate ACK to allow target to continue; if rejecting message,     *	also assert ATN.     */    if (scsiCtrlMsgInAck (pScsiCtrl) != OK)	{	SCSI_ERROR_MSG ("scsiCtrlMsgInAction: scsiCtrlMsgInAck failed.\n",			0, 0, 0, 0, 0, 0);	return (ERROR);	}    return (OK);    }/******************************************************************************** scsiCtrlMsgInXfer - handle MSG IN information transfer** Note: does not necessarily read a complete message.** Note: it is assumed that a message in transfer must be completed fully, i.e.* the target cannot disconnect.  It is also assumed that the length of the* message (fragment) does not exceed the maximum byte count the controller* can handle.** RETURNS: OK, or ERROR if transfer fails.*/LOCAL STATUS scsiCtrlMsgInXfer    (    SCSI_CTRL *pScsiCtrl		/* ptr to SCSI controller info */    )    {    UINT xferCount;			/* number of bytes transferred */    UINT maxBytes;			/* max number of bytes to read */    SCSI_MSG_IN_STATE state = pScsiCtrl->msgInState;    switch (state)        {    	case SCSI_MSG_IN_NONE:	    pScsiCtrl->msgInLength = 0;	    maxBytes = 1;	    break;	case SCSI_MSG_IN_SECOND_BYTE:	    maxBytes = 1;	    break;	    	case SCSI_MSG_IN_EXT_MSG_LEN:	    maxBytes = 1;	    break;	case SCSI_MSG_IN_EXT_MSG_DATA:	    if ((maxBytes = pScsiCtrl->msgInBuf[SCSI_EXT_MSG_LENGTH_BYTE]) == 0)		maxBytes = SCSI_EXT_MSG_MAX_LENGTH;	    break;	default:            SCSI_MSG ("scsiCtrlMsgInXfer: invalid state (%d)\n", state,		      0, 0, 0, 0, 0);	    pScsiCtrl->msgInState = SCSI_MSG_IN_NONE;            return (ERROR);	}	        xferCount = (*pScsiCtrl->scsiInfoXfer) (pScsiCtrl,					    SCSI_MSG_IN_PHASE,					    pScsiCtrl->msgInBuf +					        pScsiCtrl->msgInLength,					    maxBytes);        if (xferCount != maxBytes)	{	SCSI_ERROR_MSG ("scsiCtrlMsgInXfer: transfer failed\n",			0, 0, 0, 0, 0, 0);		if (xferCount != ERROR)	    errnoSet (S_scsiLib_HARDWARE_ERROR);		return (ERROR);	}    switch (state)	{        case SCSI_MSG_IN_NONE:            if (pScsiCtrl->msgInBuf[0] == SCSI_MSG_EXTENDED_MESSAGE)                state = SCSI_MSG_IN_EXT_MSG_LEN;	    else if (SCSI_IS_TWO_BYTE_MSG (pScsiCtrl->msgInBuf[0]))		state = SCSI_MSG_IN_SECOND_BYTE;	    else                state = SCSI_MSG_IN_NONE;            break;	case SCSI_MSG_IN_SECOND_BYTE:	    state = SCSI_MSG_IN_NONE;	    break;        case SCSI_MSG_IN_EXT_MSG_LEN:            state = SCSI_MSG_IN_EXT_MSG_DATA;            break;        case SCSI_MSG_IN_EXT_MSG_DATA:            state = SCSI_MSG_IN_NONE;            break;        default:            SCSI_MSG ("scsiCtrlMsgInXfer: invalid state (%d)\n", state,		      0, 0, 0, 0, 0);	    pScsiCtrl->msgInState = SCSI_MSG_IN_NONE;            return (ERROR);        }    pScsiCtrl->msgInState   = state;    pScsiCtrl->msgInLength += xferCount;        return (OK);    }/********************************************************************************* scsiCtrlThreadComplete - complete execution of a client thread** Set the thread status and errno appropriately, depending on whether or* not the thread has been aborted.  Set the thread inactive, and notify* the SCSI manager of the completion.** RETURNS: N/A*/LOCAL void scsiCtrlThreadComplete    (    SCSI_THREAD * pThread    )    {    SCSI_DEBUG_MSG ("scsiCtrlThreadComplete: thread 0x%08x completed\n",		    (int) pThread, 0, 0, 0, 0, 0);    if (pThread->state == SCSI_THREAD_WAIT_ABORT)	{	pThread->status = ERROR;	pThread->errNum = S_scsiLib_ABORTED;	}    else	{    	pThread->status = OK;    	pThread->errNum = 0;    	}        scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);    scsiCacheSynchronize (pThread, SCSI_CACHE_POST_COMMAND);    scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_COMPLETED);    }/********************************************************************************* scsiCtrlThreadDefer - defer execution of a thread** Set the thread's state to INACTIVE and notify the SCSI manager of the* deferral event.** RETURNS: N/A*/LOCAL void scsiCtrlThreadDefer    (    SCSI_THREAD * pThread    )    {    SCSI_DEBUG_MSG ("scsiCtrlThreadDefer: thread 0x%08x deferred\n",		    (int) pThread, 0, 0, 0, 0, 0);    scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);    scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_DEFERRED);    }    	/********************************************************************************* scsiCtrlThreadFail - complete execution of a thread, with error status** Set the thread's status and errno according to the type of error.  Set* the thread's state to INACTIVE, and notify the SCSI manager of the* completion event.** RETURNS: N/A*/LOCAL void scsiCtrlThreadFail    (    SCSI_THREAD * pThread,    int           errNum    )    {    SCSI_DEBUG_MSG ("scsiCtrlThreadFail: thread 0x%08x failed (errno = %d)\n",		    (int) pThread, errNum, 0, 0, 0, 0);    pThread->status = ERROR;    if (pThread->state == SCSI_THREAD_WAIT_ABORT)	pThread->errNum = S_scsiLib_ABORTED;    else    	pThread->errNum = errNum;        scsiCtrlThreadStateSet (pThread, SCSI_THREAD_INACTIVE);    scsiMgrThreadEvent (pThread, SCSI_THREAD_EVENT_COMPLETED);    }    	/********************************************************************************* scsiCtrlThreadStateSet - set the state of a thread** This is really just a place-holder for debugging and possible future* enhancements such as state-change logging.** RETURNS: N/A*/LOCAL void scsiCtrlThreadStateSet    (    SCSI_THREAD *     pThread,		/* ptr to thread info */    SCSI_THREAD_STATE state    )    {    SCSI_DEBUG_MSG ("scsiCtrlThreadStateSet: thread 0x%08x: %d -> %d\n",		    (int) pThread, pThread->state, state, 0, 0, 0);    pThread->state = state;    }/********************************************************************************* scsiCtrlXferParamsSet - set transfer parameters for a thread** Call the controller-specific routine to set transfer parameters to the* values required by this thread's target device.** RETURNS: OK, or ERROR if transfer parameters cannot be set*/LOCAL STATUS scsiCtrlXferParamsSet    (    SCSI_THREAD * pThread    )    {    SCSI_TARGET * pScsiTarget = pThread->pScsiTarget;    SCSI_CTRL *   pScsiCtrl   = pThread->pScsiCtrl;        /*     *	Set transfer parameters for thread's target device     */    if ((*pScsiCtrl->scsiXferParamsSet) (pScsiCtrl,					 pScsiTarget->xferOffset,					 pScsiTarget->xferPeriod) != OK)	{	SCSI_ERROR_MSG ("scsiCtrlXferParamsSet: can't set transfer parameters.\n",			0, 0, 0, 0, 0, 0);	return (ERROR);	}    return (OK);    }/********************************************************************************* scsiCtrlMsgInAck - acknowledge an incoming message byte** Call the controller-specific routine to negate the SCSI ACK signal, and* assert the ATN signal if there is a pending message out.  Note that the* controller driver must ensure that ATN is asserted, if necessary, before* ACK is negated.** RETURNS: OK, or ERROR if the signals could not be driven as required*/LOCAL STATUS scsiCtrlMsgInAck    (    SCSI_CTRL * pScsiCtrl    )    {    UINT busCommand = SCSI_BUS_NEGATE_ACK;    if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING)	{	busCommand |= SCSI_BUS_ASSERT_ATN;	}        if ((*pScsiCtrl->scsiBusControl) (pScsiCtrl, busCommand) != OK)	{	SCSI_ERROR_MSG ("scsiCtrlMsgInAck: scsiBusControl failed.\n",			0, 0, 0, 0, 0, 0);	return (ERROR);	}    return (OK);    }

⌨️ 快捷键说明

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