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

📄 ncr810lib.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 5 页
字号:
    ((pHwRegs->scntl1Bit7) ?     (NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) |		      SCNTL1_EXC)) :     (NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) &		      ~SCNTL1_EXC)));    return (OK);    }/********************************************************************************* ncr810ScsiBusControl - miscellaneous low-level SCSI bus control operations** Currently supports only the SCSI_BUS_RESET operation; other operations are* not used explicitly by the driver because they are carried out automatically* by the script program.** NOTE: after the SCSI bus has been reset, the SIOP generates an interrupt* which causes an NCR810_BUS_RESET event to be sent to the SCSI manager.* See "ncr810Intr()".** RETURNS: OK, or ERROR if an invalid operation is requested.** NOMANUAL*/LOCAL STATUS ncr810ScsiBusControl    (    SIOP * pSiop,   	    /* ptr to controller info                   */    int    operation	    /* bitmask for operation(s) to be performed */    )    {    if ((operation & ~SCSI_BUS_RESET) != 0)	return (ERROR);	    if (operation & SCSI_BUS_RESET)	ncr810ScsiBusReset (pSiop);    return (OK);    }/********************************************************************************* ncr810ScsiBusReset - assert the RST line on the SCSI bus ** Issue a SCSI Bus Reset command to the NCR 810. This should put all devices* on the SCSI bus in an initial quiescent state.** The bus reset will generate an interrupt which is handled by the normal* ISR (see "ncr810Intr()").** RETURNS: N/A** NOMANUAL*/LOCAL void ncr810ScsiBusReset    (    FAST SIOP *pSiop	/* ptr to SIOP info */    )    {    NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) |		    SCNTL1_RST);    taskDelay (2);			/* pause for at least 250 us */    NCR810_OUT_BYTE(pSiop->pScntl1, NCR810_IN_BYTE(pSiop->pScntl1) &		    ~SCNTL1_RST);    }/********************************************************************************* ncr810Intr - interrupt service routine for the SIOP** Find the event type corresponding to this interrupt, and carry out any* actions which must be done before the SIOP is re-started.  Determine* whether or not the SIOP is connected to the bus (depending on the event* type - see note below).  If not, start a client script if possible or* else just make the SIOP wait for something else to happen.** Notify the SCSI manager of a controller event.** NOTE:* The "connected" Boolean tells whether there is a SCSI thread in progress* which must be continued before any other SCSI activity can occur.  In* principle, it might seem that reading the appropriate bit in the SIOP's* SCNTL1 register would be better than inferring the value from the interrupt* code.** However, the SCNTL1 register may change between the time the script* completes (generates the interrupt) and the time it is read - for example,* if the SIOP is reselected immediately after generating a DISCONNECTED* interrupt.** Because the action taken by the ISR depends critically on what will happen* in software as a result of the current interrupt, and _not_ on the current* state of the SIOP hardware, if the hardware "connected" bit were used, the* above scenario would cause the ISR to fail to re-start a script when in* fact it should do.  The result would be that the SIOP would forever remain* 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 ncr810Intr    (    SIOP *pSiop    )    {    NCR810_EVENT    event;    SCSI_EVENT *    pScsiEvent = (SCSI_EVENT *) &event;    SCSI_CTRL *     pScsiCtrl  = (SCSI_CTRL *)  pSiop;    NCR810_THREAD * pThread    = (NCR810_THREAD *) pSiop->pHwThread;    BOOL connected = FALSE;    BOOL notify    = TRUE;    int  oldState  = (int) pSiop->state;    CACHE_PIPE_FLUSH();    /*     *	Save (partial) SIOP register context in current thread     */    pThread->scratcha0 = NCR810_IN_BYTE(pSiop->pScratcha0);    pThread->scratcha1 = NCR810_IN_BYTE(pSiop->pScratcha1);    pThread->scratcha2 = NCR810_IN_BYTE(pSiop->pScratcha2);    pThread->scratcha3 = NCR810_IN_BYTE(pSiop->pScratcha3);    if ((pScsiEvent->type = ncr810EventTypeGet (pSiop)) == ERROR)	return;    SCSI_INT_DEBUG_MSG ("ncr810Intr: DSA = 0x%08x, DSP = 0x%08x, type = %d.\n",			NCR810_IN_32(pSiop->pDsa), 			NCR810_IN_32(pSiop->pDsp), 			pScsiEvent->type, 0, 0, 0);    /*     *  Synchronise with single-step routine, if enabled.     */    if (pSiop->singleStep)    	semGive (pSiop->singleStepSem);    if (pScsiEvent->type == NCR810_SINGLE_STEP)	return;        /*     *	Handle interrupt according to type.     */    switch (pScsiEvent->type)	{	/*	 *  Following cases result from completion of a script run.	 */	case NCR810_CMD_COMPLETE:	case NCR810_DISCONNECTED:	    connected = FALSE;	    break;    	case NCR810_MESSAGE_OUT_SENT:    	case NCR810_MESSAGE_IN_RECVD:	case NCR810_EXT_MESSAGE_SIZE:	case NCR810_NO_MSG_OUT:	case NCR810_SCRIPT_ABORTED:	    connected = TRUE;	    break;	case NCR810_PHASE_MISMATCH:	    event.remCount = ncr810RemainderGet (pSiop, pThread->nBusPhase);	    	    connected = TRUE;	    break;	/*	 *  Following cases are asynchronous conditions, i.e. not resulting	 *  directly from running a script.	 */    	case NCR810_READY:	    connected = FALSE;	    notify    = FALSE;	    break;	        	case NCR810_SELECTED:    	case NCR810_RESELECTED:	    pScsiEvent->busId = ncr810BusIdGet (pSiop, pThread->nBusIdBits);	    pScsiEvent->nBytesIdent =		(pThread->nHostFlags & FLAGS_IDENTIFY) ? 1 : 0;	    connected = TRUE;	    break;	case NCR810_SCSI_BUS_RESET:	    connected = FALSE;	    break;	/*	 *  Following cases are error conditions (mixture of synchronous	 *  and asynchronous).	 */	case NCR810_SCSI_TIMEOUT:	case NCR810_HANDSHAKE_TIMEOUT:	    connected = FALSE;	    break;	case NCR810_ILLEGAL_PHASE:	    connected = TRUE;	    break;	case NCR810_UNEXPECTED_DISCON:	    connected = FALSE;	    break;    	case NCR810_NO_IDENTIFY:	    logMsg ("ncr810Intr: no valid IDENTIFY message at (re)select.\n",		    0, 0, 0, 0, 0, 0);	    connected = TRUE;	    break;	        	case NCR810_SPURIOUS_CMD:	    logMsg ("ncr810Intr: spurious command interrupt.\n",		    0, 0, 0, 0, 0, 0);	    connected = FALSE;	    break;	case NCR810_FATAL_ERROR:	    logMsg ("ncr810Intr: unrecoverable error - re-starting SIOP.\n",		    0, 0, 0, 0, 0, 0);	    ncr810HwInit (pSiop);	    connected = FALSE;	    break;	default:	    SCSI_INT_DEBUG_MSG ("ncr810Intr: unexpected interrupt (%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 "ncr810Resume()".     *     *	Otherwise, if there's a new SCSI thread to start (i.e., the SCSI     *	manager has called "ncr810Activate()"), 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 "ncr810Activate ()".)     */    if (connected)	{    	pSiop->state = NCR810_STATE_IDLE;	}    else if (pSiop->cmdPending)	{	ncr810ScriptStart (pSiop,			   (NCR810_THREAD *) pSiop->pNewThread,			   NCR810_SCRIPT_INIT_START);	pSiop->state = NCR810_STATE_ACTIVE;	}    else	{	ncr810ScriptStart (pSiop,			   (NCR810_THREAD *) pScsiCtrl->pIdentThread,			   NCR810_SCRIPT_WAIT);		pSiop->state = NCR810_STATE_PASSIVE;	}    pSiop->cmdPending = FALSE;    SCSI_INT_DEBUG_MSG ("ncr810Intr: 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));    }/********************************************************************************* ncr810BusIdGet - find bus ID of device which selected/reselected the SIOP.** Get the Bus ID of the selecting/reselecting device by looking at SSID* * RETURNS: bus ID of connected peer device** NOTE: This routine is called at interrupt level.** NOMANUAL*/LOCAL int ncr810BusIdGet    (    SIOP * pSiop,			/* ptr to controller info       */    UINT   busIdBits			/* bits corresponding to bus ID */    )    {    UINT8 devBusId;    devBusId = NCR810_IN_BYTE(pSiop->pSsid) & ((UINT8) SSID_ENC_MASK);        return (devBusId);    }/********************************************************************************* ncr810RemainderGet - 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 ncr810RemainderGet    (    SIOP *pSiop,			/* pointer to controller info     */    UINT  phase				/* phase terminated by mismatch   */    )    {    UINT  remCount;    UINT8 tmpCount;    UINT  tmpCountWord;    UINT8 countFifo;    UINT8 syncMode;    /* determine xfer mode */    syncMode = NCR810_IN_BYTE(pSiop->pSxfer) & SXFER_OFFSET;    /*     *	Find remaining byte count (may be corrected later).  For a fuller     *	explanation, see Chapter 2 of the NCR 53C810 Data Manual.     */    remCount = NCR810_IN_32(pSiop->pDbc) & NCR810_COUNT_MASK;    /*     *   check for data in fifo and output registers     *	(SODR & SODL), count from DBC minus DFIFO count and 0x7f     *	(see NCR 53C810 Data Manual).     */    /* look for deep fifo mode on 825/875 */    tmpCount = 0;    tmpCountWord = 0;    if ( ((pSiop->devType == NCR825_DEVICE_ID)  ||	  (pSiop->devType == NCR875_DEVICE_ID)) &&	 (NCR810_IN_BYTE(pSiop->pCtest5) & CTEST5_DFS) ) 	{	tmpCountWord = ((((UINT)NCR810_IN_BYTE(pSiop->pCtest5)) & 0x0003) << 8);	tmpCountWord += (UINT)NCR810_IN_BYTE(pSiop->pDfifo);	tmpCountWord -= (remCount & 0x03FF);	}    else	{	tmpCount  = (UINT8)(remCount & 0x7f);	countFifo = NCR810_IN_BYTE(pSiop->pDfifo) & 0x7f;	tmpCount  = (countFifo - tmpCount) & 0x7f;	}    switch (phase)        {        case PHASE_DATA_IN:        case PHASE_MSG_IN:	case PHASE_STATUS:	    if (!syncMode)		{		/* Asynchronous Read */		if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_ILF)		    tmpCount++;				/* 825/875 Extensions */		if ((pSiop->devType == NCR825_DEVICE_ID) ||		    (pSiop->devType == NCR875_DEVICE_ID))		    {		    if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_ILF)			tmpCount++;		    if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_ILF)			tmpCount++;				    }		}	    else		{		/* Synchronous Read */		countFifo = (NCR810_IN_BYTE(pSiop->pSstat1) & FIFO_MASK)			    >> 4;		countFifo &= 0x0f;		    

⌨️ 快捷键说明

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