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

📄 scsimgrlib.c

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
    }/********************************************************************************* scsiMgrPhysDevRunnableThreadGet - find a runnable thread on this phys dev** If the physical device is connected, no new thread can be started.* Otherwise, the thread at the front of the wait queue is the only thread to* consider (it is the highest priority thread waiting for access to this* device).  If there is such a thread, consider its tag type and the current* nexus type on the physical device to determine whether or not the thread* can be started.** Essentially, if the device currently has an ITL nexus it cannot have any* new threads started.  If it has an ITLQ nexus, another tagged thread can be* started provided there is a tag available, or a sense recovery (untagged)* thread can be started.** RETURNS: the highest priority thread which can be started on this device,* or 0 if no threads are available or the device can't start a new thread.*/LOCAL SCSI_THREAD * scsiMgrPhysDevRunnableThreadGet    (    SCSI_PHYS_DEV * pScsiPhysDev    )    {    BOOL          canStart;    SCSI_THREAD * pThread;        if (pScsiPhysDev->connected)	return (NULL);    pThread = (SCSI_THREAD *) lstFirst (&pScsiPhysDev->waitingThreads);    if (pThread == 0)	return (NULL);        switch (pScsiPhysDev->nexus)	{	case SCSI_NEXUS_NONE:	    canStart = TRUE;	    break;	case SCSI_NEXUS_ITL:	    canStart = FALSE;	    break;	case SCSI_NEXUS_ITLQ:	    canStart = (pScsiPhysDev->nFreeTags != 0) ||		       (pThread->tagType == SCSI_TAG_SENSE_RECOVERY);	    break;	default:	    logMsg ("scsiMgrPhysDevRunnableThreadGet: device 0x%08x: "		    "invalid nexus (%d)\n",		    (int) pScsiPhysDev, pScsiPhysDev->nexus, 0, 0, 0, 0);	    canStart = FALSE;	    break;	}    return (canStart ? pThread : 0);    }/********************************************************************************* scsiMgrPhysDevActiveQAdd - add a thread to a phys dev's active queue** Simply insert the thread onto the list.  The list is unordered.** RETURNS: N/A*/LOCAL void scsiMgrPhysDevActiveQAdd    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_THREAD   * pThread    )    {    lstInsert (&pScsiPhysDev->activeThreads, 0, (NODE *) pThread);    }/********************************************************************************* scsiMgrPhysDevActiveQRemove - remove a thread from a phys dev's active 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 scsiMgrPhysDevActiveQRemove    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_THREAD   * pThread    )    {    if (lstFind (&pScsiPhysDev->activeThreads, (NODE *) pThread) == ERROR)	return (ERROR);        lstDelete (&pScsiPhysDev->activeThreads, (NODE *) pThread);    return (OK);    }/********************************************************************************* scsiMgrPhysDevActiveThreadFind - find thread corresponding to tag on phys dev** Search the physical device's active thread list to find one corresponding to* the given tag number.** NOTE:* This function should not be called by application programs.** RETURNS: thread ptr, or 0 if no active thread corresponding to this tag** NOMANUAL*/SCSI_THREAD * scsiMgrPhysDevActiveThreadFind    (    SCSI_PHYS_DEV * pScsiPhysDev,	/* physical device to search    */    SCSI_TAG        tagNum		/* tag number, or SCSI_TAG_NONE */    )    {    SCSI_THREAD * pThread;    for (pThread  = (SCSI_THREAD *) lstFirst (&pScsiPhysDev->activeThreads);	 pThread != 0;	 pThread  = (SCSI_THREAD *) lstNext ((NODE *) pThread))	{	if (pThread->tagNumber == tagNum)	    return (pThread);	}    return (0);    }/********************************************************************************* scsiMgrPhysDevTagInit - initialise tag table for a physical device** Set all tags not in use; reset the free tag count and next free tag number.** RETURNS: N/A** NOMANUAL*/VOID scsiMgrPhysDevTagInit    (    SCSI_PHYS_DEV * pScsiPhysDev    )    {    UINT     nTags = pScsiPhysDev->nTags;    SCSI_TAG tagNum;    /*     *	Initialise "dummy" tag used for untagged threads     */    pScsiPhysDev->untagged.inUse = FALSE;    /*     *	Set all real tags to "available"     */    for (tagNum = 0; tagNum < nTags; ++tagNum)	{	SCSI_TAG_INFO * pTag = pScsiPhysDev->pTagInfo + tagNum;	pTag->inUse = FALSE;	}    pScsiPhysDev->nFreeTags = nTags;    pScsiPhysDev->nextTag   = (nTags == 0) ? SCSI_TAG_NONE : 0;    }/********************************************************************************* scsiMgrPhysDevTagAllocate - allocate a tag number on the physical device** Validate the requested tag type; if it is tagged, allocate a tag number* on the physical device.** The actual tag number allocated has no significance other than that it* identifies an active thread on the physical device.  In particular, it has* no bearing on the order in which the target executes the command.  Thus the* choice of tag number is somewhat arbitrary; however, this routine attempts* to use tags in rotation rather than continually re-using the same tag* numbers.  (This is primarily because it makes debugging somewhat easier.)** NOTE:* An incorrect tag type can result from a bad choice by the client, however* unavailability of free tags can only result from software failure (the SCSI* manager should not be activating a thread on a device which has no tags* free !)** The search for a free tag could get quite slow when the device supports a* large number of tags and they are nearly all in use.  In practice this is* not likely to cause problems even with the simple scheme used currently.* A more sophisticated approach would be to store free tag numbers on a* list or queue, however this would use substantial amounts of memory (up to* 256 free tags per physical device).** RETURNS: OK, or ERROR if no tags available*/LOCAL STATUS scsiMgrPhysDevTagAllocate    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_TAG_TYPE   tagType,    SCSI_TAG      * pTagNum    )    {    BOOL     tagged;    SCSI_TAG tagNum;    SCSI_TAG_INFO * pTag = 0;		/* initialise to avoid warning */    if (scsiMgrPhysDevTagTypeValidate (pScsiPhysDev, tagType, &tagged) != OK)	return (ERROR);        if (!tagged)	{    	tagNum = SCSI_TAG_NONE;	pTag = &pScsiPhysDev->untagged;	}    else	{	int i;	if (pScsiPhysDev->nFreeTags == 0)	    {	    logMsg ("scsiMgrPhysDevTagAllocate: device 0x%08x: no free tags\n",		    (int) pScsiPhysDev, 0, 0, 0, 0, 0);	    errnoSet (S_scsiLib_SOFTWARE_ERROR);	    return (ERROR);	    }	--pScsiPhysDev->nFreeTags;	/*	 *  Search for a free tag; starting at one after we last used	 */    	tagNum = pScsiPhysDev->nextTag;	for (i = 0; i < pScsiPhysDev->nTags; ++i)	    {	    pTag = (pScsiPhysDev->pTagInfo + tagNum);	    if (!pTag->inUse)		break;	    if (++tagNum >= pScsiPhysDev->nTags)		tagNum = 0;	    }	if (i == pScsiPhysDev->nTags)	    {	    logMsg ("scsiMgrPhysDevTagAllocate: device 0x%08x: "		    "tag not found (%d free)\n",		    (int) pScsiPhysDev, pScsiPhysDev->nTags, 0, 0, 0, 0);	    errnoSet (S_scsiLib_SOFTWARE_ERROR);	    return (ERROR);	    }	if ((pScsiPhysDev->nextTag = tagNum + 1) == pScsiPhysDev->nTags)	    pScsiPhysDev->nextTag = 0;	}        pTag->inUse = TRUE;    *pTagNum = tagNum;    return (OK);    }/********************************************************************************* scsiMgrPhysDevTagFree - free a tag for the physical device.** Mark the specified tag not in use.** RETURNS: OK, or ERROR if no tags available*/LOCAL void scsiMgrPhysDevTagFree    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_TAG        tagNum    )    {    SCSI_TAG_INFO * pTag;    if (tagNum == SCSI_TAG_NONE)	{	pTag = &pScsiPhysDev->untagged;	}    else	{	++pScsiPhysDev->nFreeTags;    	pTag = (pScsiPhysDev->pTagInfo + tagNum);	}    pTag->inUse = FALSE;    }/********************************************************************************* scsiMgrPhysDevTagTypeValidate - validate requested tag type for phys dev** Check the requested tag type is valid given the current nexus type of the* device.  Note the special cases which allow an untagged sense recovery* command to be started when the device has tagged nexuses active, provided* it is in a contingent allegiance condition.** RETURNS: OK, or ERROR if the requested tag type is (currently) invalid*/LOCAL STATUS scsiMgrPhysDevTagTypeValidate    (    SCSI_PHYS_DEV * pScsiPhysDev,    SCSI_TAG_TYPE   tagType,    BOOL          * pTagged    )    {    BOOL valid;    BOOL tagged;        switch (tagType)	{    	case SCSI_TAG_UNTAGGED:	    valid  = (pScsiPhysDev->nexus != SCSI_NEXUS_ITLQ);	    tagged = FALSE;	    break;	case SCSI_TAG_SENSE_RECOVERY:	    valid  = (pScsiPhysDev->nexus != SCSI_NEXUS_ITLQ) ||		     pScsiPhysDev->pendingCA;	    tagged = FALSE;	    break;	case SCSI_TAG_SIMPLE:	case SCSI_TAG_ORDERED:	case SCSI_TAG_HEAD_OF_Q:	    valid  = (pScsiPhysDev->nexus   != SCSI_NEXUS_ITL) &&		     (pScsiPhysDev->tagType != SCSI_TAG_UNTAGGED);	    tagged = TRUE;	    break;	        	default:	    valid  = FALSE;	    tagged = FALSE;	    break;	}    if (!valid)	{	SCSI_DEBUG_MSG ("scsiPhysDevTagTypeValidate: invalid tag type (%d) "			"for device 0x%08x\n",			tagType, (int) pScsiPhysDev, 0, 0, 0, 0);	errnoSet (S_scsiLib_INVALID_TAG_TYPE);	return (ERROR);	}	    *pTagged = tagged;	    return (OK);    }/********************************************************************************* scsiMgrShow - show status information for the SCSI manager** This routine shows the current state of the SCSI manager for the specified* controller, including the total number of threads created and the number of* threads currently free.** Optionally, this routine also shows details for all created physical devices * on this controller and all threads for which SCSI requests are outstanding.* It also shows the IDs of all free threads.** NOTE: The information displayed is volatile; this routine is best used when* there is no activity on the SCSI bus.  Threads allocated by a client but* for which there are no outstanding SCSI requests are not shown.** RETURNS: N/A*/void scsiMgrShow    (    SCSI_CTRL * pScsiCtrl,		/* SCSI controller to use        */    BOOL        showPhysDevs,		/* TRUE => show phys dev details */    BOOL        showThreads,		/* TRUE => show thread details   */    BOOL        showFreeThreads		/* TRUE => show free thread IDs  */    )    {    char * state;    int    nFree;        if (pScsiCtrl == NULL)	pScsiCtrl = pSysScsiCtrl;        if (pScsiCtrl == NULL)	{	printf ("No SCSI controller specified.\n");	return;	}    state = pScsiCtrl->active ? "active" : "inactive";        nFree = lstCount (&pScsiCtrl->freeThreads);        printf ("Controller   State    # Threads (tot/free)\n");    printf ("----------  --------  --------------------\n");    printf ("0x%08x  %-8s        %3d  %3d\n",	    (int) pScsiCtrl,	    state,	    pScsiCtrl->nThreads,	    nFree);    if (showPhysDevs)	{	BOOL noHeader = FALSE;	int  i;	printf ("\n");	for (i = 0; i < SCSI_MAX_PHYS_DEVS; ++i)	    {	    SCSI_PHYS_DEV * pScsiPhysDev = pScsiCtrl->physDevArr[i];	    if (pScsiPhysDev != 0)		{		scsiPhysDevShow (pScsiPhysDev, FALSE, noHeader);		noHeader = TRUE;		}	    }	}    if (showThreads)	{	/*	 *  This is crude.  A better approach would be to collect all	 *  the thread IDs into a buffer, then sort by priority before	 *  calling "scsiThreadShow" for each thread.	 */	int i;	printf ("\n");	for (i = 0; i < SCSI_MAX_PHYS_DEVS; ++i)	    {	    SCSI_PHYS_DEV * pScsiPhysDev = pScsiCtrl->physDevArr[i];	    if (pScsiPhysDev != 0)		{		scsiThreadListShow (&pScsiPhysDev->activeThreads);		scsiThreadListShow (&pScsiPhysDev->waitingThreads);		}	    }	}    if (showFreeThreads && (nFree != 0))	{	printf ("\nFree threads:\n");	scsiThreadListIdShow (&pScsiCtrl->freeThreads);	}    }

⌨️ 快捷键说明

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