i91uscsi.c

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

C
2,185
字号
				sgp->SG_Len -= (U32) xcnt;	/* new len to be xfer */				pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);				/* new SG table ptr */				pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);				/* new SG table len */				pCurScb->SCB_SGIdx = (WORD) i;				/* for next disc and come in this loop */				return (4);	/* Go to state 4                */			}			/* else (xcnt >= 0 , i.e. this sgp already xferred */		}		/* for */		return (6);	/* Go to state 6                */	} else {		pCurScb->SCB_BufPtr += (U32) xcnt;	}	return (4);		/* Go to state 4                */}/***************************************************************************//* state after Data phase */int tul_state_6(HCS * pCurHcb){	SCB *pCurScb = pCurHcb->HCS_ActScb;#if DEBUG_STATE	printk("-s6-");#endif	for (;;) {		switch (pCurHcb->HCS_Phase) {		case STATUS_IN:	/* Status phase                 */			if ((tul_status_msg(pCurHcb)) == -1)				return (-1);			break;		case MSG_IN:	/* Message in phase             */			pCurScb->SCB_NxtStat = 6;			if ((tul_msgin(pCurHcb)) == -1)				return (-1);			break;		case MSG_OUT:	/* Message out phase            */			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);			if (wait_tulip(pCurHcb) == -1)				return (-1);			break;		case DATA_IN:	/* Data in phase                */			return (tul_xpad_in(pCurHcb));		case DATA_OUT:	/* Data out phase               */			return (tul_xpad_out(pCurHcb));		default:			return (tul_bad_seq(pCurHcb));		}	}}/***************************************************************************/int tul_state_7(HCS * pCurHcb){	int cnt, i;#if DEBUG_STATE	printk("-s7-");#endif	/* flush SCSI FIFO */	cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;	if (cnt) {		for (i = 0; i < cnt; i++)			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	}	switch (pCurHcb->HCS_Phase) {	case DATA_IN:		/* Data in phase                */	case DATA_OUT:		/* Data out phase               */		return (tul_bad_seq(pCurHcb));	default:		return (6);	/* Go to state 6                */	}}/***************************************************************************/int tul_xfer_data_in(HCS * pCurHcb){	SCB *pCurScb = pCurHcb->HCS_ActScb;	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {		return (6);	/* wrong direction */	}	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);	/* 7/25/95 */	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);	} else {		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);	}	pCurScb->SCB_NxtStat = 0x5;	return (0);		/* return to OS, wait xfer done , let jas_isr come in */}/***************************************************************************/int tul_xfer_data_out(HCS * pCurHcb){	SCB *pCurScb = pCurHcb->HCS_ActScb;	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {		return (6);	/* wrong direction */	}	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);	} else {		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);	}	pCurScb->SCB_NxtStat = 0x5;	return (0);		/* return to OS, wait xfer done , let jas_isr come in */}/***************************************************************************/int tul_xpad_in(HCS * pCurHcb){	SCB *pCurScb = pCurHcb->HCS_ActScb;	TCS *pCurTcb = pCurHcb->HCS_ActTcs;	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */	}	for (;;) {		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);		else			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);		if ((wait_tulip(pCurHcb)) == -1) {			return (-1);		}		if (pCurHcb->HCS_Phase != DATA_IN) {			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);			return (6);		}		TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	}}int tul_xpad_out(HCS * pCurHcb){	SCB *pCurScb = pCurHcb->HCS_ActScb;	TCS *pCurTcb = pCurHcb->HCS_ActTcs;	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */	}	for (;;) {		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);		else			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);		if ((wait_tulip(pCurHcb)) == -1) {			return (-1);		}		if (pCurHcb->HCS_Phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);			return (6);		}	}}/***************************************************************************/int tul_status_msg(HCS * pCurHcb){				/* status & MSG_IN */	SCB *pCurScb = pCurHcb->HCS_ActScb;	BYTE msg;	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);	if ((wait_tulip(pCurHcb)) == -1) {		return (-1);	}	/* get status */	pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	if (pCurHcb->HCS_Phase == MSG_OUT) {		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);		} else {			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		}		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);		return (wait_tulip(pCurHcb));	}	if (pCurHcb->HCS_Phase == MSG_IN) {		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {	/* Parity error                 */			if ((tul_msgin_accept(pCurHcb)) == -1)				return (-1);			if (pCurHcb->HCS_Phase != MSG_OUT)				return (tul_bad_seq(pCurHcb));			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);			return (wait_tulip(pCurHcb));		}		if (msg == 0) {	/* Command complete             */			if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {	/* No link support              */				return (tul_bad_seq(pCurHcb));			}			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);			return tul_wait_done_disc(pCurHcb);		}		if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {			if ((pCurScb->SCB_TaStat & 0x18) == 0x10)				return (tul_msgin_accept(pCurHcb));		}	}	return (tul_bad_seq(pCurHcb));}/***************************************************************************//* scsi bus free */int int_tul_busfree(HCS * pCurHcb){	SCB *pCurScb = pCurHcb->HCS_ActScb;	if (pCurScb != NULL) {		if (pCurScb->SCB_Status & SCB_SELECT) {		/* selection timeout */			tul_unlink_pend_scb(pCurHcb, pCurScb);			pCurScb->SCB_HaStat = HOST_SEL_TOUT;			tul_append_done_scb(pCurHcb, pCurScb);		} else {	/* Unexpected bus free          */			tul_unlink_busy_scb(pCurHcb, pCurScb);			pCurScb->SCB_HaStat = HOST_BUS_FREE;			tul_append_done_scb(pCurHcb, pCurScb);		}		pCurHcb->HCS_ActScb = NULL;		pCurHcb->HCS_ActTcs = NULL;	}	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */	return (-1);}/***************************************************************************//* scsi bus reset */int int_tul_scsi_rst(HCS * pCurHcb){	SCB *pCurScb;	int i;	/* if DMA xfer is pending, abort DMA xfer */	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);		/* wait Abort DMA xfer done */		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);	}	/* Abort all active & disconnected scb */	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {		pCurScb->SCB_HaStat = HOST_BAD_PHAS;		tul_append_done_scb(pCurHcb, pCurScb);	}	pCurHcb->HCS_ActScb = NULL;	pCurHcb->HCS_ActTcs = NULL;	/* clr sync nego. done flag */	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);	}	return (-1);}/***************************************************************************//* scsi reselection */int int_tul_resel(HCS * pCurHcb){	SCB *pCurScb;	TCS *pCurTcb;	BYTE tag, msg = 0;	BYTE tar, lun;	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {		if (pCurScb->SCB_Status & SCB_SELECT) {		/* if waiting for selection complete */			pCurScb->SCB_Status &= ~SCB_SELECT;		}		pCurHcb->HCS_ActScb = NULL;	}	/* --------- get target id---------------------- */	tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);	/* ------ get LUN from Identify message----------- */	lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;	/* 07/22/98 from 0x1F -> 0x0F */	pCurTcb = &pCurHcb->HCS_Tcs[tar];	pCurHcb->HCS_ActTcs = pCurTcb;	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);	/* ------------- tag queueing ? ------------------- */	if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {		if ((tul_msgin_accept(pCurHcb)) == -1)			return (-1);		if (pCurHcb->HCS_Phase != MSG_IN)			goto no_tag;		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);		if ((wait_tulip(pCurHcb)) == -1)			return (-1);		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag Message    */		if ((msg < MSG_STAG) || (msg > MSG_OTAG))	/* Is simple Tag      */			goto no_tag;		if ((tul_msgin_accept(pCurHcb)) == -1)			return (-1);		if (pCurHcb->HCS_Phase != MSG_IN)			goto no_tag;		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);		if ((wait_tulip(pCurHcb)) == -1)			return (-1);		tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag ID       */		pCurScb = pCurHcb->HCS_Scb + tag;		if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {			return tul_msgout_abort_tag(pCurHcb);		}		if (pCurScb->SCB_Status != SCB_BUSY) {	/* 03/24/95             */			return tul_msgout_abort_tag(pCurHcb);		}		pCurHcb->HCS_ActScb = pCurScb;		if ((tul_msgin_accept(pCurHcb)) == -1)			return (-1);	} else {		/* No tag               */	      no_tag:		if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {			return tul_msgout_abort_targ(pCurHcb);		}		pCurHcb->HCS_ActScb = pCurScb;		if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {			if ((tul_msgin_accept(pCurHcb)) == -1)				return (-1);		}	}	return 0;}/***************************************************************************/int int_tul_bad_seq(HCS * pCurHcb){				/* target wrong phase           */	SCB *pCurScb;	int i;	tul_reset_scsi(pCurHcb, 10);	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {		pCurScb->SCB_HaStat = HOST_BAD_PHAS;		tul_append_done_scb(pCurHcb, pCurScb);	}	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);	}	return (-1);}/***************************************************************************/int tul_msgout_abort_targ(HCS * pCurHcb){	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));	if (tul_msgin_accept(pCurHcb) == -1)		return (-1);	if (pCurHcb->HCS_Phase != MSG_OUT)		return (tul_bad_seq(pCurHcb));	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);	return tul_wait_disc(pCurHcb);}/***************************************************************************/int tul_msgout_abort_tag(HCS * pCurHcb){	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));	if (tul_msgin_accept(pCurHcb) == -1)		return (-1);	if (pCurHcb->HCS_Phase != MSG_OUT)		return (tul_bad_seq(pCurHcb));	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);	return tul_wait_disc(pCurHcb);}/***************************************************************************/int tul_msgin(HCS * pCurHcb){	TCS *pCurTcb;	for (;;) {		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);

⌨️ 快捷键说明

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