📄 ncr810lib.c
字号:
/* 825/875 Extensions */ if ((pSiop->devType == NCR825_DEVICE_ID) || (pSiop->devType == NCR875_DEVICE_ID)) { if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_FF4) countFifo |= 0x1f; } tmpCount += countFifo; } /* Check wide SCSI on 825/875 */ if ((pSiop->devType == NCR825_DEVICE_ID) || (pSiop->devType == NCR875_DEVICE_ID)) { if (NCR810_IN_BYTE(pSiop->pScntl2) & SCNTL2_WSR) tmpCount++; } remCount += tmpCount; break; case PHASE_DATA_OUT: case PHASE_MSG_OUT: case PHASE_COMMAND: /* Asynch/Synchronous write */ if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_OLF) tmpCount++; if ((pSiop->devType == NCR825_DEVICE_ID) || (pSiop->devType == NCR875_DEVICE_ID)) { if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_OLF) tmpCount++; } if (syncMode) { /* Synchronous write */ if (NCR810_IN_BYTE(pSiop->pSstat0) & SSTAT0_ORF) tmpCount++; /* 825/875 Extensions */ if ((pSiop->devType == NCR825_DEVICE_ID) || (pSiop->devType == NCR875_DEVICE_ID)) { if (NCR810_IN_BYTE(pSiop->pSstat2) & SSTAT2_ORF) tmpCount++; } /* 825/875 */ } remCount += tmpCount; break; default: logMsg ("ncr810RemainderGet: invalid phase.\n", 0, 0, 0, 0, 0, 0); break; } /* Add in any deep fifo adjustments; this is zero for 88-byte fifos */ remCount += tmpCountWord; /* Clear data FIFOs */ NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) | CTEST3_CLF); return (remCount); }/******************************************************************************** ncr810EventTypeGet - 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 ncr810EventTypeGet ( SIOP * pSiop ) { UINT8 istat; UINT8 dmaStatus; UINT8 sist0; UINT8 sist1; int key; /* * Read interrupt status registers * * Note: reading the interrupt status register as a long word * causes the status register to read as NULL. This should not * be the case, however, the workaround is to read the status * registers as 8 bit registers and insert 12 SCLK delays * in between successive reads, as explained in the data manual. */ dmaStatus = 0; istat = sist0 = sist1 = 0; /* * Interrupts need to be locked in interrupt context while the status * registers are being read so that there is no contention between * a synchronous thread and a bus initiated thread (reselect) */ key = intLock (); CACHE_PIPE_FLUSH (); istat = NCR810_IN_BYTE(pSiop->pIstat); if ((istat & (ISTAT_SIP | ISTAT_DIP)) != 0) { if (istat & ISTAT_ABRT) NCR810_OUT_BYTE(pSiop->pIstat, 0x00); if ((istat & ISTAT_SIP) && (istat & ISTAT_DIP)) { SCSI_INT_DEBUG_MSG ("Both SIP and DIP occurred simultaneously\n", 0,0,0,0,0,0); } CACHE_PIPE_FLUSH (); dmaStatus = NCR810_IN_BYTE(pSiop->pDstat); CACHE_PIPE_FLUSH (); ncr810Delay (); sist0 = NCR810_IN_BYTE(pSiop->pSist0); CACHE_PIPE_FLUSH (); ncr810Delay (); sist1 = NCR810_IN_BYTE(pSiop->pSist1); intUnlock (key); } else { intUnlock (key); return (ERROR); } SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet:" "Interrupt status istat = 0x%02x, " "SCSI status0 = 0x%02x, " "SCSI status1 = 0x%02x" "DMA status = 0x%02x\n", istat, sist0, sist1, dmaStatus, 0, 0); /* * Check for fatal errors (first !) */ if (sist0 & B_SGE) { logMsg ("ncr810: SCSI bus gross error.\n", 0, 0, 0, 0, 0, 0); return (NCR810_FATAL_ERROR); } if (sist0 & B_PAR) { logMsg ("ncr810: parity error.\n", 0, 0, 0, 0, 0, 0); return (NCR810_FATAL_ERROR); } if (dmaStatus & B_IID) { logMsg ("ncr810: illegal instruction (DSP = 0x%08x).\n", NCR810_IN_32(pSiop->pDsp), 0, 0, 0, 0, 0); return (NCR810_FATAL_ERROR); } if (dmaStatus & B_BF) { logMsg ("ncr810: bus fault (DSPS = 0x%08x) DBC = (0x%08x).\n", NCR810_IN_32(pSiop->pDsps), NCR810_IN_32(pSiop->pDbc) & 0xffffff, 0, 0, 0, 0); return (NCR810_FATAL_ERROR); } /* * No fatal errors; try the rest (NB order of tests is important !) */ if (sist0 & B_RST) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: SCSI bus reset.\n", 0, 0, 0, 0, 0, 0); NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) | CTEST3_CLF); /* clear FIFOs */ return (NCR810_SCSI_BUS_RESET); } if (sist0 & B_UDC) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: unexpected disconnection.\n", 0, 0, 0, 0, 0, 0); /* clear FIFOs */ NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) | CTEST3_CLF); return (NCR810_UNEXPECTED_DISCON); } if (sist1 & B_STO) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: SCSI bus timeout.\n", 0, 0, 0, 0, 0, 0); /* clear FIFOs */ NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) | CTEST3_CLF); return (NCR810_SCSI_TIMEOUT); } if (sist1 & B_HTH) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: SCSI handshake timeout.\n", 0, 0, 0, 0, 0, 0); /* clear FIFOs */ NCR810_OUT_BYTE(pSiop->pCtest3, NCR810_IN_BYTE(pSiop->pCtest3) | CTEST3_CLF); return (NCR810_HANDSHAKE_TIMEOUT); } if (sist0 & B_MA) { /* * The "phase mismatch" interrupt is used to indicate assertion of * ATN in target mode. This interrupt should have been disabled * by the script when in target mode, because the current code does * not know how to handle it. */ if (NCR810_IN_BYTE(pSiop->pScntl0) & SCNTL0_TRG) { if (NCR810_IN_BYTE(pSiop->pSien0) & B_MA) { logMsg ("ncr810EventTypeGet: enabled ATN interrupt!\n", 0, 0, 0, 0, 0, 0); return (NCR810_FATAL_ERROR); } } else { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: phase mismatch.\n", 0, 0, 0, 0, 0, 0); return (NCR810_PHASE_MISMATCH); } } if (dmaStatus & B_ABT) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: script aborted.\n", 0, 0, 0, 0, 0, 0); return (NCR810_SCRIPT_ABORTED); } if (dmaStatus & B_SIR) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: script completed.\n", 0, 0, 0, 0, 0, 0); return ( NCR810_IN_32(pSiop->pDsps) ); } if (dmaStatus & B_SSI) { SCSI_INT_DEBUG_MSG ("ncr810EventTypeGet: single-step.\n", 0, 0, 0, 0, 0, 0); return (NCR810_SINGLE_STEP); } /* * No (expected) reason for the interrupt ! */ logMsg ("ncr810EventTypeGet: spurious interrupt !\n", 0, 0, 0, 0, 0, 0); logMsg ("\tistat: (0x%x) dstat: (0x%x)\n", istat, dmaStatus, 0, 0, 0, 0); logMsg ("\tsist0: (0x%x) sist1: (0x%x)\n", sist0, sist1, 0, 0, 0, 0); return (NCR810_FATAL_ERROR); }/********************************************************************************* ncr810ThreadActivate - activate a SCSI connection for an initiator thread** Set whatever thread/controller state variables need to be set. Ensure that* all buffers used by the thread are coherent with the contents of the* system caches (if any).** Set transfer parameters for the thread based on what its target device* last negotiated.** Update the thread context (including shared memory area) and note that* there is a new client script to be activated (see "ncr810Activate()").** Set the thread's state to ESTABLISHED. This is strictly a bit premature,* but there is no distinction as far as this driver is concerned between a* thread which is connecting and one which has connected (i.e., the script* just runs to completion and we have to examine its exit status to determine* how far through the process the thread got).** Do not wait for the script to be activated. Completion of the script will* be signalled by an event which is handled by "ncr810Event()".** RETURNS: OK or ERROR** NOMANUAL*/LOCAL STATUS ncr810ThreadActivate ( SIOP * pSiop, /* ptr to controller info */ NCR810_THREAD * pThread /* ptr to thread info */ ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SCSI_TARGET * pScsiTarget = pScsiThread->pScsiTarget; SCSI_DEBUG_MSG ("ncr810ThreadActivate: thread 0x%08x: activating\n", (int) pThread, 0, 0, 0, 0, 0); scsiCacheSynchronize (pScsiThread, SCSI_CACHE_PRE_COMMAND); /* * Reset controller state variables: set sync xfer parameters */ pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; pScsiCtrl->msgInState = SCSI_MSG_IN_NONE; /* * A wide transfer is initiated before a synchronous transfer. However, * when a wide transfer has been done the next activation causes the * synchronous transfer to be activated. Another possible but more * complicated way to implement this would be to have both wide and * synchronous negotiations in the same activation or thread i.e. * the same SCSI transaction. */ scsiWideXferNegotiate (pScsiCtrl, pScsiTarget, WIDE_XFER_NEW_THREAD); scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD); if (ncr810ThreadParamsSet (pThread, pScsiTarget->xferOffset, pScsiTarget->xferPeriod) != OK) { SCSI_ERROR_MSG ("ncr810ThreadActivate: failed to set thread params.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* * Concatenate the ident message with a pending 'normal' message out, * if possible. This allows the script to send the first message out * within the same MSG OUT phase as the IDENTIFY message - needed on * some target systems (e.g. DG Clariion RAID) to avoid the message * being rejected(!). */ pSiop->identMsgLength = 0; bcopy (pScsiThread->identMsg, pSiop->identMsg, pScsiThread->identMsgLength); pSiop->identMsgLength += pScsiThread->identMsgLength; if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_PENDING) { bcopy (pScsiCtrl->msgOutBuf, pSiop->identMsg + pSiop->identMsgLength, pScsiCtrl->msgOutLength); pSiop->identMsgLength += pScsiCtrl->msgOutLength; } /* * Update thread context; activate the thread */ ncr810ThreadUpdate (pThread); if (ncr810Activate (pSiop, pThread) != OK) { SCSI_ERROR_MSG ("ncr810ThreadActivate: failed to activate thread.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } pScsiCtrl->pThread = pScsiThread; ncr810ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED); return (OK); }/*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -