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

📄 ncr710lib2.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
* IDLE, and the SCSI system would become deadlocked.  (I've seen it happen !)** One disadvantage is that the ISR has to know a little too much about the* semantics of the interrupt codes - an improvement might be to have a* distinguishing feature (e.g. bit set) in the interrupt code to indicate* whether or not to start a new script.** RETURNS: N/A** NOMANUAL*/void ncr710IntrScsi2     (    SIOP *pSiop    )    {    NCR710_EVENT    event;    SCSI_EVENT *    pScsiEvent = (SCSI_EVENT *) &event;    SCSI_CTRL *     pScsiCtrl  = (SCSI_CTRL *)  pSiop;    NCR710_THREAD * pThread    = (NCR710_THREAD *) pSiop->pHwThread;    BOOL connected = FALSE;    BOOL notify    = TRUE;    int  oldState  = (int) pSiop->state;    /*     *	Save (partial) SIOP register context in current thread     */    pThread->scratch0 = *pSiop->pScratch0;    pThread->scratch1 = *pSiop->pScratch1;    pThread->scratch2 = *pSiop->pScratch2;    pThread->scratch3 = *pSiop->pScratch3;    pScsiEvent->type = ncr710EventTypeGet (pSiop);        SCSI_INT_DEBUG_MSG ("ncr710Intr: DSA = 0x%08x, DSP = 0x%08x, type = %d.\n",			*pSiop->pDsa, *pSiop->pDsp, pScsiEvent->type, 0, 0, 0);    /*     *  Synchronise with single-step routine, if enabled.     */    if (pSiop->singleStep)    	semGive (pSiop->singleStepSem);    if (pScsiEvent->type == NCR710_SINGLE_STEP)	return;        /*     *	Handle interrupt according to type.     */    switch (pScsiEvent->type)	{	/*	 *  Following cases result from completion of a script run.	 */	case NCR710_CMD_COMPLETE:	case NCR710_DISCONNECTED:	    connected = FALSE;	    break;    	case NCR710_MESSAGE_OUT_SENT:    	case NCR710_MESSAGE_IN_RECVD:	case NCR710_EXT_MESSAGE_SIZE:	case NCR710_NO_MSG_OUT:	case NCR710_SCRIPT_ABORTED:	    connected = TRUE;	    break;	case NCR710_PHASE_MISMATCH:	    event.remCount = ncr710RemainderGet (pSiop, pThread->nBusPhase);	    	    connected = TRUE;	    break;	/*	 *  Following cases are asynchronous conditions, i.e. not resulting	 *  directly from running a script.	 */    	case NCR710_READY:	    connected = FALSE;	    notify    = FALSE;	    break;	        	case NCR710_SELECTED:    	case NCR710_RESELECTED:	    pScsiEvent->busId = ncr710BusIdGet (pSiop, pThread->nBusIdBits);	    pScsiEvent->nBytesIdent =		(pThread->nHostFlags & FLAGS_IDENTIFY) ? 1 : 0;	    connected = TRUE;	    break;	case NCR710_SCSI_BUS_RESET:	    connected = FALSE;	    break;	/*	 *  Following cases are error conditions (mixture of synchronous	 *  and asynchronous).	 */	case NCR710_SCSI_TIMEOUT:	    connected = FALSE;	    break;	case NCR710_ILLEGAL_PHASE:	    connected = TRUE;	    break;	case NCR710_UNEXPECTED_DISCON:	    connected = FALSE;	    break;    	case NCR710_NO_IDENTIFY:	    logMsg ("ncr710Intr: no valid IDENTIFY message at (re)select.\n",		    0, 0, 0, 0, 0, 0);	    connected = TRUE;	    break;	        	case NCR710_SPURIOUS_CMD:	    logMsg ("ncr710Intr: spurious command interrupt.\n",		    0, 0, 0, 0, 0, 0);	    connected = FALSE;	    break;	case NCR710_FATAL_ERROR:	    logMsg ("ncr710Intr: unrecoverable error - re-starting SIOP.\n",		    0, 0, 0, 0, 0, 0);	    ncr710HwInit (pSiop);	    connected = FALSE;	    break;	default:	    logMsg ("ncr710Intr: unexpected interrupt status (%d).\n",		    pScsiEvent->type, 0, 0, 0, 0, 0);	    break;	}    /*     *  Controller is now idle: if possible, make it run a script.     *     *	If a SCSI thread is suspended and must be processed at task-level,     *	leave the SIOP idle.  It will be re-started by the SCSI manager     *	calling "ncr710Resume()".     *     *	Otherwise, if there's a new SCSI thread to start (i.e., the SCSI     *	manager has called "ncr710Activate()"), start the appropriate script.     *     *	Otherwise, start a script which puts the SIOP into passive mode     *	waiting for re-selection, selection or a host command.     *     *	In all cases, clear any request to start a new thread.  The only     *	tricky case is when there was a request pending and the SIOP is     *	left IDLE.  This should only ever occur when the current event is     *	selection or reselection, in which case the SCSI manager will retry     *	the activation request.  (Also see "ncr710Activate ()".)     */    if (connected)	{    	pSiop->state = NCR710_STATE_IDLE;	}    else if (pSiop->cmdPending)	{	ncr710ScriptStart (pSiop,			   (NCR710_THREAD *) pSiop->pNewThread,			   NCR710_SCRIPT_INIT_START);	pSiop->state = NCR710_STATE_ACTIVE;	}    else	{	ncr710ScriptStart (pSiop,			   (NCR710_THREAD *) pScsiCtrl->pIdentThread,			   NCR710_SCRIPT_WAIT);		pSiop->state = NCR710_STATE_PASSIVE;	}    pSiop->cmdPending = FALSE;    SCSI_INT_DEBUG_MSG ("ncr710Intr: state %d -> %d\n",			oldState, pSiop->state, 0, 0, 0, 0);    /*     *	Send the event to the SCSI manager to be processed.     */    if (notify)    	scsiMgrEventNotify ((SCSI_CTRL *) pSiop, pScsiEvent, sizeof (event));    }/********************************************************************************* ncr710BusIdGet - find bus ID of device which selected/reselected the SIOP.** Calculate bus ID of SCSI peer which (re)selected the SIOP; "busIdBits"* contains a copy of the LCRC register, i.e. an image of the data bits* asserted on the SCSI bus during (re)selection.  Extract the peer's ID* by masking out the bit corresponding to our bus ID then shifting until* we find a bit set.* * RETURNS: bus ID of connected peer device** NOTE: This routine is called at interrupt level.** NOMANUAL*/LOCAL int ncr710BusIdGet    (    SIOP * pSiop,			/* ptr to controller info       */    UINT   busIdBits			/* bits corresponding to bus ID */    )    {    UINT8 devBusId;    busIdBits &= ~(*pSiop->pScid);        for (devBusId = 0; devBusId <= SCSI_MAX_BUS_ID; ++devBusId)	{	if (busIdBits & (1 << devBusId))	    break;	}    return (devBusId);    }/********************************************************************************* ncr710RemainderGet - get remaining xfer count and clean up after mismatch** Clean up the SIOP's data path and calculate the number of bytes which* were expected to be, but have not been transferred.** The information transfer phase which halted because of the mismatch has* been saved as part of the SIOP's register context.** RETURNS: number of bytes not transferred** NOTE: This routine is called at interrupt level.** NOMANUAL*/LOCAL UINT ncr710RemainderGet    (    SIOP *pSiop,			/* pointer to controller info     */    UINT  phase				/* phase terminated by mismatch   */    )    {    UINT  remCount;    UINT8 tmpCount;    UINT8 countFifo;    /*     *	Find remaining byte count (may be corrected later).  For a fuller     *	explanation, see Chapter 2 of the NCR 53C710 Data Manual.     */    remCount = *pSiop->pDbc & NCR710_COUNT_MASK;    switch (phase)        {        case PHASE_DATA_IN:        case PHASE_MSG_IN:	case PHASE_STATUS:	    /*	     *	Input phases: check for pending byte to store, update	     *	buffer if there is one.	     */            if (*pSiop->pSstat1 & B_ILF)                {                *((UINT8 *)pSiop->pDnad) = *pSiop->pSidl;                remCount--;                }    	    break;        case PHASE_DATA_OUT:        case PHASE_MSG_OUT:	case PHASE_COMMAND:            /*	     *  Output phases: check for data in fifo and output registers	     *	(SODR & SODL), count from DBC minus DFIFO count and 0x7f	     *	(see NCR 53C710 Data Manual).	     */            tmpCount  = (UINT8)(remCount & 0x7f);            countFifo = *pSiop->pDfifo & 0x7f;            tmpCount  = (countFifo - tmpCount) & 0x7f;                if (*pSiop->pSstat1 & B_OLF)                tmpCount++;            if (*pSiop->pSstat1 & B_ORF)                tmpCount++;                remCount += tmpCount;	    break;            default:            logMsg ("ncr710RemainderGet: invalid phase.\n", 0, 0, 0, 0, 0, 0);	    break;        }    /*     *	Clear data FIFOs     */    *pSiop->pCtest8 |= B_CLF;    return (remCount);    }/******************************************************************************** ncr710EventTypeGet - parse SCSI and DMA status registers at interrupt time** NOTE*   Only status bits which have corresponding interrupts enabled are checked !** RETURNS: an interrupt (event) type code** NOMANUAL*/LOCAL int ncr710EventTypeGet    (    SIOP * pSiop    )    {    UINT  intrRegs;    UINT8 scsiStatus;    UINT8 dmaStatus;    /*     *	Read interrupt status registers     *     *	Note: read as a long word to avoid requirement for a delay when     *	SCSI status and DMA status registers are read individually.     */    scsiStatus = dmaStatus = 0;    *pSiop->pIstat &= ~B_ABORT;        while ((*pSiop->pIstat & (B_SIP | B_DIP)) != 0)        {#if _BYTE_ORDER==_BIG_ENDIAN        intrRegs = *((UINT *)pSiop->pSstat2);        scsiStatus |= (UINT8)((intrRegs >> 8) & 0x0FF);        dmaStatus  |= (UINT8)( intrRegs       & 0x0FF);#else        intrRegs = *((UINT *)pSiop->pDstat);        scsiStatus |= (UINT8)((intrRegs >> 16) & 0x0FF);        dmaStatus  |= (UINT8)((intrRegs >> 24) & 0x0FF);#endif        }	SCSI_INT_DEBUG_MSG ("ncr710EventTypeGet: SCSI status = 0x%02x, "			    "DMA status = 0x%02x\n",		    	    scsiStatus, dmaStatus, 0, 0, 0, 0);    /*     *	Check for fatal errors (first !)     */    if  (scsiStatus & B_SGE)        {	logMsg ("ncr710: SCSI bus gross error.\n", 0, 0, 0, 0, 0, 0);	return (NCR710_FATAL_ERROR);        }    if  (scsiStatus & B_PAR)        {	logMsg ("ncr710: parity error.\n", 0, 0, 0, 0, 0, 0);	return (NCR710_FATAL_ERROR);        }    if (dmaStatus & B_IID)        {	logMsg ("ncr710: illegal instruction (DSP = 0x%08x).\n",		*pSiop->pDsp, 0, 0, 0, 0, 0);	return (NCR710_FATAL_ERROR);        }    if (dmaStatus & B_BF)        {	logMsg ("ncr710: bus fault (DSP = 0x%08x).\n",		*pSiop->pDsp, 0, 0, 0, 0, 0);	return (NCR710_FATAL_ERROR);        }    if (dmaStatus & B_WTD)        {	logMsg ("ncr710: watchdog timeout (DSP = 0x%08x).\n",		*pSiop->pDsp, 0, 0, 0, 0, 0);	return (NCR710_FATAL_ERROR);        }    /*     *	No fatal errors; try the rest (NB order of tests is important !)     */    if  (scsiStatus & B_RSTE)        {	SCSI_INT_DEBUG_MSG ("ncr710EventTypeGet: SCSI bus reset.\n",			    0, 0, 0, 0, 0, 0);	*pSiop->pCtest8 |= B_CLF;	/* clear FIFOs */		return (NCR710_SCSI_BUS_RESET);        }         if  (scsiStatus & B_UDC)        {	SCSI_INT_DEBUG_MSG ("ncr710EventTypeGet: unexpected disconnection.\n",			    0, 0, 0, 0, 0, 0);	*pSiop->pCtest8 |= B_CLF;	/* clear FIFOs */		return (NCR710_UNEXPECTED_DISCON);        }

⌨️ 快捷键说明

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