i91uscsi.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,185 行 · 第 1/5 页

C
2,185
字号
			pCurHcb->HCS_LastBusy = NULL;		pTmpScb->SCB_NxtScb = NULL;		if (pTmpScb->SCB_TagMsg)			pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;		else			pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;	}#if DEBUG_QUEUE	printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);#endif	return (pTmpScb);}/***************************************************************************/void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb){	SCB *pTmpScb, *pPrevScb;#if DEBUG_QUEUE	printk("unlink busy SCB %lx; ", (ULONG) pCurScb);#endif	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	while (pTmpScb != NULL) {		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */			if (pTmpScb == pCurHcb->HCS_FirstBusy) {				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)					pCurHcb->HCS_LastBusy = NULL;			} else {				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;				if (pTmpScb == pCurHcb->HCS_LastBusy)					pCurHcb->HCS_LastBusy = pPrevScb;			}			pTmpScb->SCB_NxtScb = NULL;			if (pTmpScb->SCB_TagMsg)				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;			else				pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;			break;		}		pPrevScb = pTmpScb;		pTmpScb = pTmpScb->SCB_NxtScb;	}	return;}/***************************************************************************/SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun){	SCB *pTmpScb, *pPrevScb;	WORD scbp_tarlun;	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	while (pTmpScb != NULL) {		scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);		if (scbp_tarlun == tarlun) {	/* Unlink this SCB              */			break;		}		pPrevScb = pTmpScb;		pTmpScb = pTmpScb->SCB_NxtScb;	}#if DEBUG_QUEUE	printk("find busy SCB %lx; ", (ULONG) pTmpScb);#endif	return (pTmpScb);}/***************************************************************************/void tul_append_done_scb(HCS * pCurHcb, SCB * scbp){#if DEBUG_QUEUE	printk("append done SCB %lx; ", (ULONG) scbp);#endif	scbp->SCB_Status = SCB_DONE;	scbp->SCB_NxtScb = NULL;	if (pCurHcb->HCS_LastDone != NULL) {		pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;		pCurHcb->HCS_LastDone = scbp;	} else {		pCurHcb->HCS_FirstDone = scbp;		pCurHcb->HCS_LastDone = scbp;	}}/***************************************************************************/SCB *tul_find_done_scb(HCS * pCurHcb){	SCB *pTmpScb;	if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {		if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)			pCurHcb->HCS_LastDone = NULL;		pTmpScb->SCB_NxtScb = NULL;	}#if DEBUG_QUEUE	printk("find done SCB %lx; ", (ULONG) pTmpScb);#endif	return (pTmpScb);}/***************************************************************************/int tul_abort_srb(HCS * pCurHcb, ULONG srbp){	ULONG flags;	SCB *pTmpScb, *pPrevScb;	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);	if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);		/* disable Jasmin SCSI Int        */                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);		tulip_main(pCurHcb);        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);		pCurHcb->HCS_Semaph = 1;		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);		return SCSI_ABORT_SNOOZE;	}	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;	/* Check Pend queue */	while (pTmpScb != NULL) {		/* 07/27/98 */		if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {			if (pTmpScb == pCurHcb->HCS_ActScb) {				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);				return SCSI_ABORT_BUSY;			} else if (pTmpScb == pCurHcb->HCS_FirstPend) {				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)					pCurHcb->HCS_LastPend = NULL;			} else {				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;				if (pTmpScb == pCurHcb->HCS_LastPend)					pCurHcb->HCS_LastPend = pPrevScb;			}			pTmpScb->SCB_HaStat = HOST_ABORTED;			pTmpScb->SCB_Flags |= SCF_DONE;			if (pTmpScb->SCB_Flags & SCF_POST)				(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);			return SCSI_ABORT_SUCCESS;		}		pPrevScb = pTmpScb;		pTmpScb = pTmpScb->SCB_NxtScb;	}	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */	while (pTmpScb != NULL) {		if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {			if (pTmpScb == pCurHcb->HCS_ActScb) {				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);				return SCSI_ABORT_BUSY;			} else if (pTmpScb->SCB_TagMsg == 0) {				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);				return SCSI_ABORT_BUSY;			} else {				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;				if (pTmpScb == pCurHcb->HCS_FirstBusy) {					if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)						pCurHcb->HCS_LastBusy = NULL;				} else {					pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;					if (pTmpScb == pCurHcb->HCS_LastBusy)						pCurHcb->HCS_LastBusy = pPrevScb;				}				pTmpScb->SCB_NxtScb = NULL;				pTmpScb->SCB_HaStat = HOST_ABORTED;				pTmpScb->SCB_Flags |= SCF_DONE;				if (pTmpScb->SCB_Flags & SCF_POST)					(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);				return SCSI_ABORT_SUCCESS;			}		}		pPrevScb = pTmpScb;		pTmpScb = pTmpScb->SCB_NxtScb;	}	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);	return (SCSI_ABORT_NOT_RUNNING);}/***************************************************************************/int tul_bad_seq(HCS * pCurHcb){	SCB *pCurScb;	printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {		tul_unlink_busy_scb(pCurHcb, pCurScb);		pCurScb->SCB_HaStat = HOST_BAD_PHAS;		pCurScb->SCB_TaStat = 0;		tul_append_done_scb(pCurHcb, pCurScb);	}	tul_stop_bm(pCurHcb);	tul_reset_scsi(pCurHcb, 8);	/* 7/29/98 */	return (tul_post_scsi_rst(pCurHcb));}/************************************************************************/int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags){	ULONG flags;	SCB *pScb;	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);	if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {		if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);			/* disable Jasmin SCSI Int        */        		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);			tulip_main(pCurHcb);        		spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);			pCurHcb->HCS_Semaph = 1;			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);			return SCSI_RESET_SNOOZE;		}		pScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */		while (pScb != NULL) {			if (pScb->SCB_Srb == (unsigned char *) pSrb)				break;			pScb = pScb->SCB_NxtScb;		}		if (pScb == NULL) {			printk("Unable to Reset - No SCB Found\n");			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);			return SCSI_RESET_NOT_RUNNING;		}	}	if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);		return SCSI_RESET_NOT_RUNNING;	}	pScb->SCB_Opcode = BusDevRst;	pScb->SCB_Flags = SCF_POST;	pScb->SCB_Target = target;	pScb->SCB_Mode = 0;	pScb->SCB_Srb = 0;	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {		pScb->SCB_Srb = (unsigned char *) pSrb;	}	tul_push_pend_scb(pCurHcb, pScb);	/* push this SCB to Pending queue */	if (pCurHcb->HCS_Semaph == 1) {		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);		/* disable Jasmin SCSI Int        */		pCurHcb->HCS_Semaph = 0;        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);		tulip_main(pCurHcb);                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);		pCurHcb->HCS_Semaph = 1;		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);	}	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);	return SCSI_RESET_PENDING;}int tul_reset_scsi_bus(HCS * pCurHcb){	ULONG flags;	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);	pCurHcb->HCS_Semaph = 0;	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);	tul_stop_bm(pCurHcb);	tul_reset_scsi(pCurHcb, 2);	/* 7/29/98 */	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);	tul_post_scsi_rst(pCurHcb);        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);	tulip_main(pCurHcb);        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);	pCurHcb->HCS_Semaph = 1;	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);	return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);}/************************************************************************/void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb){	ULONG flags;	pCurScb->SCB_Mode = 0;	pCurScb->SCB_SGIdx = 0;	pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);	tul_append_pend_scb(pCurHcb, pCurScb);	/* Append this SCB to Pending queue *//* VVVVV 07/21/98 */	if (pCurHcb->HCS_Semaph == 1) {		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);		/* disable Jasmin SCSI Int        */		pCurHcb->HCS_Semaph = 0;        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);		tulip_main(pCurHcb);        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);		pCurHcb->HCS_Semaph = 1;		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);	}	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);	return;}/***************************************************************************/int tul_isr(HCS * pCurHcb){	/* Enter critical section       */	if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {		if (pCurHcb->HCS_Semaph == 1) {			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);			/* Disable Tulip SCSI Int */			pCurHcb->HCS_Semaph = 0;			tulip_main(pCurHcb);			pCurHcb->HCS_Semaph = 1;			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);			return (1);		}	}	return (0);}/***************************************************************************/int tulip_main(HCS * pCurHcb){	SCB *pCurScb;	for (;;) {		tulip_scsi(pCurHcb);	/* Call tulip_scsi              */		while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {	/* find done entry */			if (pCurScb->SCB_TaStat == QUEUE_FULL) {				pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =				    pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;				pCurScb->SCB_TaStat = 0;				tul_append_pend_scb(pCurHcb, pCurScb);				continue;			}			if (!(pCurScb->SCB_Mode & SCM_RSENS)) {		/* not in auto req. sense mode */				if (pCurScb->SCB_TaStat == 2) {					/* clr sync. nego flag */					if (pCurScb->SCB_Flags & SCF_SENSE) {						BYTE len;						len = pCurScb->SCB_SenseLen;						if (len == 0)							len = 1;						pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;						pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;						pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in *//*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */						/* so, we won't report worng direction in xfer_data_in,						   and won't report HOST_DO_DU in state_6 */						pCurScb->SCB_Mode = SCM_RSENS;						pCurScb->SCB_Ident &= 0xBF;	/* Disable Disconnect */						pCurScb->SCB_TagMsg = 0;						pCurScb->SCB_TaStat = 0;						pCurScb->SCB_CDBLen = 6;						pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;						pCurScb->SCB_CDB[1] = 0;						pCurScb->SCB_CDB[2] = 0;						pCurScb->SCB_CDB[3] = 0;						pCurScb->SCB_CDB[4] = len;						pCurScb->SCB_CDB[5] = 0;						tul_push_pend_scb(pCurHcb, pCurScb);						break;					}				}			} else {	/* in request sense mode */				if (pCurScb->SCB_TaStat == 2) {		/* check contition status again after sending									   requset sense cmd 0x3 */					pCurScb->SCB_HaStat = HOST_BAD_PHAS;				}				pCurScb->SCB_TaStat = 2;			}			pCurScb->SCB_Flags |= SCF_DONE;			if (pCurScb->SCB_Flags & SCF_POST) {				(*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);			}		}		/* while */		/* find_active: */		if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)			continue;		if (pCurHcb->HCS_ActScb) {	/* return to OS and wait for xfer_done_ISR/Selected_ISR */			return 1;	/* return to OS, enable interrupt */

⌨️ 快捷键说明

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