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

📄 scsimgrlib.c

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
** NOTE:* The thread must be a valid initiator thread (from a client request) and* must not be on either a device wait queue or a device active queue.** RETURNS: N/A*/LOCAL void scsiMgrThreadComplete    (    SCSI_THREAD * pThread  	    	/* ptr to thread info */    )    {    SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev;    SCSI_DEBUG_MSG ("scsiMgrThreadComplete: thread 0x%08x\n",		    (int) pThread, 0, 0, 0, 0, 0);    /*     *	Check for contingent allegiance condition on physical device     */    if (pThread->status == OK)	{	UINT scsiStatus = *pThread->statusAddress;	switch (scsiStatus & SCSI_STATUS_MASK)	    {	    case SCSI_STATUS_CHECK_CONDITION:	    case SCSI_STATUS_CMD_TERMINATED:	    	SCSI_DEBUG_MSG ("scsiMgrThreadComplete: device 0x%08x: "				"contingent allegiance detected\n",			    	(int) pScsiPhysDev, 0, 0, 0, 0, 0);	    	pScsiPhysDev->pendingCA = TRUE;		break;	    default:		if (pScsiPhysDev->pendingCA)		    {		    SCSI_DEBUG_MSG ("scsiMgrThreadComplete: device 0x%08x: "				    "contingent allegiance cleared\n",			    	(int) pScsiPhysDev, 0, 0, 0, 0, 0);		    pScsiPhysDev->pendingCA = FALSE;		    }		break;	    }	}    /*     *	Finish processing the client's request     */    scsiMgrRequestComplete (pThread);    }/******************************************************************************** scsiMgrThreadDefer - defer execution of an initiator thread** (This routine is called if a thread "loses arbitration" to reselection* during an attempt to select a target device.)** Remove the thread from its physical device's active queue and re-insert it* onto the wait queue to be re-despatched at the next opportunity.** NOTE:* The check that the thread actually was on the active queue avoids any* possibility of races with the transaction timeout mechanism.** RETURNS: N/A*/LOCAL void scsiMgrThreadDefer    (    SCSI_THREAD * pThread  	    	/* ptr to thread info */    )    {    SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev;    SCSI_DEBUG_MSG ("scsiMgrThreadDefer: thread 0x%08x\n",		    (int) pThread, 0, 0, 0, 0, 0);    if (scsiMgrPhysDevActiveQRemove (pScsiPhysDev, pThread) == OK)	{	scsiMgrPhysDevWaitQAdd (pScsiPhysDev, pThread);	pThread->state = SCSI_THREAD_WAITING;	}    }/********************************************************************************* scsiMgrThreadActivate - start running the specified thread** Allocate a tag number (if required) for the target physical device, build* a corresponding identification message, and call the controller-specific* thread activation routine.  Notify the controller and the thread of the* activation event.** RETURNS: OK, or ERROR if activation failed.*/LOCAL STATUS scsiMgrThreadActivate    (    SCSI_THREAD * pThread    )    {    SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev;    SCSI_CTRL     * pScsiCtrl    = pThread->pScsiCtrl;    /*     *	Allocate a tag number according to required type     */    if (pThread->tagType == SCSI_TAG_DEFAULT)	pThread->tagType = pScsiPhysDev->tagType;    if (scsiMgrPhysDevTagAllocate (pScsiPhysDev, pThread->tagType,					        &pThread->tagNumber) != OK)	{	SCSI_DEBUG_MSG ("scsiMgrThreadActivate: thread 0x%08x: "			"can't allocate tag\n",		    	(int) pThread, 0, 0, 0, 0, 0);	return (ERROR);	}    /*     *	Build identification message using this tag     */    pThread->identMsgLength = scsiIdentMsgBuild (pThread->identMsg,						 pScsiPhysDev,						 pThread->tagType,						 pThread->tagNumber);    /*     *	Initialise active and saved data pointers     */    pThread->activeDataLength  = pThread->dataLength;    pThread->activeDataAddress = pThread->dataAddress;    pThread->savedDataLength   = pThread->dataLength;    pThread->savedDataAddress  = pThread->dataAddress;    /*     *	Activate the thread using the controller driver     */    if ((*pScsiCtrl->scsiThreadActivate) (pScsiCtrl, pThread) != OK)	{	SCSI_DEBUG_MSG ("scsiMgrThreadActivate: thread 0x%08x: "			"controller activation failed\n",			(int) pThread, 0, 0, 0, 0, 0);	return (ERROR);	}    scsiMgrCtrlEvent   (pScsiCtrl, SCSI_EVENT_CONNECTED);    scsiMgrThreadEvent (pThread,   SCSI_THREAD_EVENT_ACTIVATED);    return (OK);    }/********************************************************************************* scsiMgrCtrlEvent - send an event to the SCSI controller state machine** This routine is called by the thread driver whenever selection,* reselection, or disconnection occurs or when a thread is activated.* It manages a simple finite-state machine for the SCSI controller.** NOTE:* This function should not be called by application programs.** RETURNS: N/A*/void scsiMgrCtrlEvent    (    SCSI_CTRL *     pScsiCtrl,    SCSI_EVENT_TYPE eventType    )    {    switch (eventType)	{	case SCSI_EVENT_CONNECTED:	    pScsiCtrl->active = TRUE;    	    break;	case SCSI_EVENT_DISCONNECTED:    	    pScsiCtrl->active = FALSE;	    break;	default:	    logMsg ("scsiMgrCtrlEvent: invalid event type (%d)\n",		    eventType, 0, 0, 0, 0, 0);	    break;	}    }/********************************************************************************* scsiMgrThreadEvent - send an event to the thread state machine** This routine forwards an event to the thread's physical device.  If the * event is completion or deferral, it frees up the tag which was allocated * when the thread was activated and either completes or defers the thread.** NOTE:* This function should not be called by application programs.** The thread passed into this function does not have to be an active client* thread (it may be an identification thread).** If the thread has no corresponding physical device, this routine does* nothing.  (This occassionally occurs if an unexpected disconnection* or bus reset happens when an identification thread has not yet identified* which physical device it corresponds to.** RETURNS: N/A*/void scsiMgrThreadEvent    (    SCSI_THREAD * pThread,    SCSI_THREAD_EVENT_TYPE eventType    )    {    SCSI_PHYS_DEV * pScsiPhysDev = pThread->pScsiPhysDev;    SCSI_TAG        tagNum       = pThread->tagNumber;    /*     *	Check for threads with no associated physical device.  In this case,     *	there is nothing to be done.     */    if (pScsiPhysDev == 0)	return;    switch (eventType)	{	case SCSI_THREAD_EVENT_ACTIVATED:	    scsiMgrPhysDevEvent (pScsiPhysDev, tagNum, SCSI_DEV_ACTIVATED);	    break;	    	case SCSI_THREAD_EVENT_DISCONNECTED:	    scsiMgrPhysDevEvent (pScsiPhysDev, tagNum, SCSI_DEV_DISCONNECTED);	    break;	    	case SCSI_THREAD_EVENT_RECONNECTED:	    scsiMgrPhysDevEvent (pScsiPhysDev, tagNum, SCSI_DEV_RECONNECTED);	    break;	    	case SCSI_THREAD_EVENT_COMPLETED:	    scsiMgrPhysDevEvent   (pScsiPhysDev, tagNum, SCSI_DEV_COMPLETED);	    scsiMgrPhysDevTagFree (pScsiPhysDev, tagNum);	    if (scsiMgrPhysDevActiveQRemove (pScsiPhysDev, pThread) == OK)	    	scsiMgrThreadComplete (pThread);	    break;	    	case SCSI_THREAD_EVENT_DEFERRED:	    scsiMgrPhysDevEvent   (pScsiPhysDev, tagNum, SCSI_DEV_COMPLETED);	    scsiMgrPhysDevTagFree (pScsiPhysDev, tagNum);	    scsiMgrThreadDefer (pThread);	    break;	default:	    logMsg ("scsiMgrThreadEvent: invalid event type (%d)\n",		    eventType, 0, 0, 0, 0, 0);	    break;	}    }/********************************************************************************* scsiMgrPhysDevReset - reset a physical device** Clean up all threads currently in progress on the device, failing them* with an error code corresponding to SCSI bus reset.** Clean up any state variables associated with the device.** Any threads waiting for the device to become available are not affected,* and will continue to be executed normally.** NOTE: all threads are assumed to be physically disconnected (not to be* reconnected) by the target device before this routine is called.** RETURNS: N/A*/LOCAL void scsiMgrPhysDevReset    (    SCSI_PHYS_DEV *pScsiPhysDev    )    {    SCSI_THREAD * pThread;    /*     *	Clean up all active threads: none are connected after a reset     */    while ((pThread = (SCSI_THREAD *) lstGet (&pScsiPhysDev->activeThreads))									!= 0)	{	pThread->status = ERROR;	pThread->errNum = S_scsiLib_BUS_RESET;    	scsiMgrThreadComplete (pThread);	}    /*     *	Re-initialise tag system     */    scsiMgrPhysDevTagInit (pScsiPhysDev);        /*     *	Reset miscellaneous state variables     */    pScsiPhysDev->connected = FALSE;    pScsiPhysDev->pendingCA = FALSE;    pScsiPhysDev->nexus  = SCSI_NEXUS_NONE;    pScsiPhysDev->curTag = SCSI_TAG_NONE;        pScsiPhysDev->nTaggedNexus = 0;    }/********************************************************************************* scsiMgrPhysDevEvent - notify the physical device of an event** Maintain the physical device's state variables according to the type of* event and the tag involved.  These state variables affect the scheduling* of new threads on the device (see "scsiMgrPhysDevRunnableThreadGet ()").** RETURNS: N/A*/LOCAL void scsiMgrPhysDevEvent    (    SCSI_PHYS_DEV *     pScsiPhysDev,    SCSI_TAG            tagNum,    SCSI_DEV_EVENT_TYPE eventType    )    {    /*     *	Validate tag number     */    if ((tagNum != SCSI_TAG_NONE) && (tagNum >= pScsiPhysDev->nTags))	{	logMsg ("scsiMgrPhysDevEvent: device 0x%08x: invalid tag (%d)\n",		(int) pScsiPhysDev, tagNum, 0, 0, 0, 0);	return;	}    /*     *	Handle the event for this tag (and the device as a whole)     */    switch (eventType)	{	case SCSI_DEV_ACTIVATED:	    pScsiPhysDev->curTag    = tagNum;	    pScsiPhysDev->connected = TRUE;	    if (tagNum == SCSI_TAG_NONE)		{		if (pScsiPhysDev->pendingCA)		    pScsiPhysDev->savedNexus = pScsiPhysDev->nexus;		pScsiPhysDev->nexus = SCSI_NEXUS_ITL;    	    	}	    else		{		pScsiPhysDev->nexus = SCSI_NEXUS_ITLQ;				++pScsiPhysDev->nTaggedNexus;		}	    break;	case SCSI_DEV_DISCONNECTED:	    pScsiPhysDev->curTag    = SCSI_TAG_NONE;	    pScsiPhysDev->connected = FALSE;	    break;	case SCSI_DEV_RECONNECTED:	    pScsiPhysDev->curTag    = tagNum;	    pScsiPhysDev->connected = TRUE;	    break;	    	case SCSI_DEV_COMPLETED:	    pScsiPhysDev->curTag    = NONE;	    pScsiPhysDev->connected = FALSE;	    if (tagNum == SCSI_TAG_NONE)		{		pScsiPhysDev->nexus = (pScsiPhysDev->pendingCA)		    	    	    ? pScsiPhysDev->savedNexus		    	    	    : SCSI_NEXUS_NONE;		}	    	    else if (--pScsiPhysDev->nTaggedNexus == 0)		pScsiPhysDev->nexus = SCSI_NEXUS_NONE;	    break;	default:	    logMsg ("scsiMgrPhysDevEvent: device 0x%08x: "		    "invalid event type (%d)\n",		    (int) pScsiPhysDev, eventType, 0, 0, 0, 0);	    break;	}    }/********************************************************************************* scsiMgrPhysDevWaitQAdd - add a thread to a physical device's wait queue** Insert a thread into the priority-ordered queue of pending requests for* a physical device.  Requests of the same priority are queued in FIFO* order.  Threads which are recovering from contingent allegiance condition* (i.e. have tag type SENSE_RECOVERY) are considered to have higher priority* than all other threads waiting for the device.** The wait queue is examined to determine the next thread that may be* despatched on the device - see "scsiMgrPhysDevRunnableThreadGet()".** NOTE:* Treating the SENSE_RECOVERY tag type as an extra-high priority is a* debatable design.  It may be better to just queue it in correct priority* order and have "scsiMgrPhysDevRunnableThreadGet()" scan the wait queue for* the first thread with this tag type, when the device has a contingent* allegiance condition.** RETURNS: N/A*/LOCAL void scsiMgrPhysDevWaitQAdd    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_THREAD   * pThread    )    {    NODE * pPrev = 0;    if (pThread->tagType != SCSI_TAG_SENSE_RECOVERY)	{	SCSI_THREAD * pCur;	for (pCur  = (SCSI_THREAD *) lstFirst (&pScsiPhysDev->waitingThreads);	     pCur != 0;	     pCur  = (SCSI_THREAD *) lstNext ((NODE *) pCur))	    {	    if ((pCur->tagType != SCSI_TAG_SENSE_RECOVERY) &&		SCSI_IS_HIGHER_PRIORITY (pThread->priority, pCur->priority))		break;		 	    pPrev = (NODE *) pCur;	    }	}    lstInsert (&pScsiPhysDev->waitingThreads, pPrev, (NODE *) pThread);    }/********************************************************************************* scsiMgrPhysDevWaitQRemove - remove a thread from a phys dev's wait queue** NOTE:* It would be nice if "lstDelete()" told you whether or not the target node* was on the list - then three would be no need to have the "lstFind" first.** RETURNS: OK, or ERROR if the thread was not on the queue.*/LOCAL STATUS scsiMgrPhysDevWaitQRemove    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_THREAD   * pThread    )    {    if (lstFind (&pScsiPhysDev->waitingThreads, (NODE *) pThread) == ERROR)	return (ERROR);        lstDelete (&pScsiPhysDev->waitingThreads, (NODE *) pThread);    return (OK);

⌨️ 快捷键说明

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