📄 ncr710lib.c
字号:
/* cacheDmaMalloc the data share info structure; return ERROR if unable */ pNcrCtxt = (NCR_CTL_CTXT *) cacheDmaMalloc (sizeof (NCR_CTL_CTXT)); if (pNcrCtxt == (NCR_CTL_CTXT *) NULL) { printErr("ncr710CtrlCreate :malloc NCR_CTL_CTXT context failed\n"); (void) cacheDmaFree ((char *) pSiop); return((SIOP *) NULL); } bzero ((char *) pNcrCtxt, sizeof (NCR_CTL_CTXT)); /* fill in generic SCSI info for this controller */ scsiCtrlInit (&pSiop->scsiCtrl); /* Init NcrCtxt pointer in siop structure */ pSiop->pNcrCtxt = pNcrCtxt; /* fill in SIOP specific data for this controller */ pSiop->pSien = baseAdrs + OFF_SIEN; pSiop->pSdid = baseAdrs + OFF_SDID; pSiop->pScntl1 = baseAdrs + OFF_SCNTL1; pSiop->pScntl0 = baseAdrs + OFF_SCNTL0; pSiop->pSocl = baseAdrs + OFF_SOCL; pSiop->pSodl = baseAdrs + OFF_SODL; pSiop->pSxfer = baseAdrs + OFF_SXFER; pSiop->pScid = baseAdrs + OFF_SCID; pSiop->pSbcl = baseAdrs + OFF_SBCL; pSiop->pSbdl = baseAdrs + OFF_SBDL; pSiop->pSidl = baseAdrs + OFF_SIDL; pSiop->pSfbr = baseAdrs + OFF_SFBR; pSiop->pSstat2 = baseAdrs + OFF_SSTAT2; pSiop->pSstat1 = baseAdrs + OFF_SSTAT1; pSiop->pSstat0 = baseAdrs + OFF_SSTAT0; pSiop->pDstat = baseAdrs + OFF_DSTAT; pSiop->pDsa = (UINT *) (baseAdrs + OFF_DSA); pSiop->pCtest3 = baseAdrs + OFF_CTEST3; pSiop->pCtest2 = baseAdrs + OFF_CTEST2; pSiop->pCtest1 = baseAdrs + OFF_CTEST1; pSiop->pCtest0 = baseAdrs + OFF_CTEST0; pSiop->pCtest7 = baseAdrs + OFF_CTEST7; pSiop->pCtest6 = baseAdrs + OFF_CTEST6; pSiop->pCtest5 = baseAdrs + OFF_CTEST5; pSiop->pCtest4 = baseAdrs + OFF_CTEST4; pSiop->pTemp = (UINT *) (baseAdrs + (OFF_TEMP)); pSiop->pLcrc = baseAdrs + OFF_LCRC; pSiop->pCtest8 = baseAdrs + OFF_CTEST8; pSiop->pIstat = baseAdrs + OFF_ISTAT; pSiop->pDfifo = baseAdrs + OFF_DFIFO; pSiop->pDcmd = baseAdrs + OFF_DCMD; pSiop->pDbc = (UINT *) (baseAdrs + (OFF_DBC)); pSiop->pDnad = (UINT *) (baseAdrs + (OFF_DNAD)); pSiop->pDsp = (UINT *) (baseAdrs + (OFF_DSP)); pSiop->pDsps = (UINT *) (baseAdrs + (OFF_DSPS)); pSiop->pScratch0 = baseAdrs + OFF_SCRATCH0; pSiop->pScratch1 = baseAdrs + OFF_SCRATCH1; pSiop->pScratch2 = baseAdrs + OFF_SCRATCH2; pSiop->pScratch3 = baseAdrs + OFF_SCRATCH3; pSiop->pDcntl = baseAdrs + OFF_DCNTL; pSiop->pDwt = baseAdrs + OFF_DWT; pSiop->pDien = baseAdrs + OFF_DIEN; pSiop->pDmode = baseAdrs + OFF_DMODE; pSiop->pAdder = (UINT *) (baseAdrs + (OFF_ADDER)); pSiop->scsiCtrl.clkPeriod = freqValue; pSiop->scsiCtrl.maxBytesPerXfer = SIOP_MAX_XFER_LENGTH; pSiop->scsiCtrl.scsiBusReset = (VOIDFUNCPTR) ncr710ScsiBusReset; pSiop->scsiCtrl.scsiTransact = (FUNCPTR) ncr710ScsiTransact; pSiop->scsiCtrl.scsiSyncMsgConvert = (FUNCPTR) ncr710SyncMsgConvert; /* no longer needed with this kind of chip */ pSiop->scsiCtrl.scsiDevSelect = NULL; pSiop->scsiCtrl.scsiBytesIn = NULL; pSiop->scsiCtrl.scsiBytesOut = NULL; pSiop->scsiCtrl.scsiDmaBytesIn = NULL; pSiop->scsiCtrl.scsiDmaBytesOut = NULL; pSiop->scsiCtrl.scsiBusPhaseGet = NULL; pSiop->scsiCtrl.scsiMsgInAck = NULL; pSiop->scsiCtrl.scsiSetAtn = NULL; /* Fill the siop structure with the default value for some hardware dependant registers */ bcopy ((char *)&hwRegs,(char *)&pSiop->hwRegs,sizeof (NCR710_HW_REGS)); /* Just here to avoid a bus error in scsiAutoConfig the chip can't be programming for an another value (0 or 250ms) */ pSiop->scsiCtrl.scsiSelTimeOutCvt = (VOIDFUNCPTR)ncr710SelTimeOutCvt; pSiop->pDevToSelect = (SCSI_PHYS_DEV *) NULL; /* create the mutex siop data semaphore */ pSiop->pMutexData = semBCreate(SEM_Q_FIFO,SEM_FULL); if (pSiop->pMutexData == (SEM_ID)NULL) { (void) cacheDmaFree ((char *) pSiop); (void) cacheDmaFree ((char *) pNcrCtxt); return((SIOP *)NULL); } #ifdef NCR710_INT_LOG_MEM pNcr710Deb = (UINT *)malloc(LOG_SIZE_MEM); pLogMemShow = pNcr710Deb;#endif return (pSiop); }/********************************************************************************* ncr710CtrlInit - initialize a control structure for an NCR 53C710 SIOP** This routine initializes an SIOP structure, after the structure is created* with ncr710CtrlCreate(). This structure must be initialized before the* SIOP can be used. It may be called more than once; however,* it should be called only while there is no activity on the SCSI interface.** Before returning, this routine pulses RST (reset) on the SCSI bus, thus* resetting all attached devices.** The input parameters are as follows:* .iP <pSiop> 4* a pointer to the NCR_710_SCSI_CTRL structure created with* ncr710CtrlCreate().* .iP <scsiCtrlBusId>* the SCSI bus ID of the SIOP, in the range 0 - 7. The ID is somewhat * arbitrary; the value 7, or highest priority, is conventional.* .iP <scsiPriority>* the priority to which a task is set when performing a SCSI transaction.* Valid priorities are 0 to 255. Alternatively, the value -1 specifies that * the priority should not be altered during SCSI transactions. ** RETURNS: OK, or ERROR if parameters are out of range.*/STATUS ncr710CtrlInit ( FAST NCR_710_SCSI_CTRL *pSiop, /* ptr to SIOP struct */ FAST int scsiCtrlBusId, /* SCSI bus ID of this SIOP */ int scsiPriority /* priority of task when doing SCSI I/O */ ) { int ix; int jx; NCR_CTL *pNcrCtl; /* Check if pSiop not NULL */ if (pSiop == (SIOP *)NULL) return (ERROR); pNcrCtl = &pSiop->pNcrCtxt->ncrCtl[0][0]; pSiop->pNcrCtl = (NCR_CTL *) NULL; /* verify scsiCtrlBusId and enter legal value in SIOP structure */ if (scsiCtrlBusId < SCSI_MIN_BUS_ID || scsiCtrlBusId > SCSI_MAX_BUS_ID) return (ERROR); pSiop->scsiCtrl.scsiCtrlBusId = (UINT8) scsiCtrlBusId; /* translate id 0-7 in power of 2 (1000000 = 7).It's for saving time * at interrupt level in a reconnection scheme. */ pSiop->ctrlIdPow2 = (UINT8) (0x1 << pSiop->scsiCtrl.scsiCtrlBusId); /* verify scsiPriority and enter legal value in SIOP structure */ if (scsiPriority < NONE || scsiPriority > 0xff) return (ERROR); pSiop->scsiCtrl.scsiPriority = scsiPriority; /* disconnect is supported for now,but this feature is not included * in this revision. */ pSiop->scsiCtrl.disconnect = FALSE; /* TRUE to enable disconnect */ ncr710ScsiBusReset (pSiop); /* initialize the SIOP hardware */ ncr710HwInit (pSiop); /* Fill fixed values in the SIOP nexus */ for (ix = 0; ix<= SCSI_MAX_BUS_ID; ix++) { for (jx = 0; jx <= SCSI_MAX_LUN; jx++) { /* Init fixed count */ pNcrCtl->msgInCount = 1; pNcrCtl->extMsgInCount = 4; pNcrCtl->statusCount = 1; pNcrCtl->pIdentMsg = CACHE_DMA_VIRT_TO_PHYS ( &pSiop->saveIdentMsg); pNcrCtl->identCount = 1; pNcrCtl++; } } return (OK); }/********************************************************************************* ncr710ScsiBusReset - assert the RST line on the SCSI bus ** Issue a SCSI Bus Reset command to the NCR 710. This should put all devices* on the SCSI bus in an initial quiescent state.* This routine also clears the interrupt status by reading all status* registers. Because the chip has an interrupt stack, it is necessary to* loop on the status registers to clear any pending interrupts.** RETURNS: N/A** NOMANUAL*/LOCAL void ncr710ScsiBusReset ( FAST SIOP *pSiop /* ptr to SIOP info */ ) { UINT8 tempReg; *pSiop->pScntl1 |= (UINT8) (B_RST); taskDelay (2); *pSiop->pScntl1 &= ~B_RST; /* Check for interrupt pending after scsi reset */ tempReg = ((*pSiop->pIstat) & (B_DIP | B_SIP)); while (tempReg != 0) { /* Read scsi Status interrupt */ tempReg = *pSiop->pSstat0; taskDelay (2); tempReg = *pSiop->pDstat; taskDelay (2); tempReg = ((*pSiop->pIstat) & (B_DIP | B_SIP)); } }/********************************************************************************* ncr710Intr - interrupt service routine for the SIOP** This interrupt routine just performs a clear of interrupt * conditions and copies all of the interrupt status of the SIOP* (status registers and script instruction interrupt values). * A check of the interrupt issued is done at the task level in* ncr710ScsiPhase function except for a phase mismatch, a new command to * start, and a reconnect process.** RETURNS: N/A** NOMANUAL*/void ncr710Intr ( SIOP *pSiop /* ptr to SIOP info */ ) { UINT8 tmpReg; UINT8 phaseReqReg; TBOOL scriptIntr; /* used to detect true end in single step Mode */ UINT8 tmpLun; /* used to extract lun from ident msgin */ UINT8 tmp; SCSI_PHYS_DEV *pScsiPhysDev; /* Used when reconnected occur */ UINT *localStart; /* Used to restart Script */ UINT intrRegs; /* local 32bit read of interrupt status */ ncr710CountIntr++; /* Clear previous values */ pSiop->saveSstat0 = 0; pSiop->saveDstat = 0; pSiop->saveScriptIntrStat=0; /* Update phase requested for this nexus */ phaseReqReg = *pSiop->pScratch0; /* Read interrupt status registers with a long acces to avoid any * potential timing problem. The ncr710 Data manuel specify that a * 12BCLK period must be insert beetwen two 8bit read of SSTAT0 * and DSTAT. This limitation does not exist for a 32bit access. */ while ((tmpReg = (*pSiop->pIstat & (B_SIP | B_DIP))) != 0) {#if _BYTE_ORDER==_BIG_ENDIAN intrRegs = *((UINT *)pSiop->pSstat2); pSiop->saveSstat0 |= (UINT8)((intrRegs >> 8) & 0x0FF); pSiop->saveDstat |= (UINT8)(intrRegs & 0x0FF);#else intrRegs = *((UINT *)pSiop->pDstat); pSiop->saveSstat0 |= (UINT8)((intrRegs >> 16) & 0x0FF); pSiop->saveDstat |= (UINT8)((intrRegs >> 24) & 0x0FF);#endif } /* check for Single Step interrupt */ if (pSiop->saveDstat & B_SSI) SCSI_INT_DEBUG_MSG("Single Step interrupt\n", 0, 0, 0, 0, 0, 0); if (pSiop->saveDstat & B_SIR) { scriptIntr = TRUE; } /* read the result value of int script instruction */ pSiop->saveScriptIntrStat = *pSiop->pDsps; /* Process new command / disconnect / reconnected for exclusive * access data part */ switch (pSiop->saveScriptIntrStat) { case NEW_COMMAND_PROCESS: SCSI_INT_DEBUG_MSG("ncr710Intr:start new cmd \n", 0, 0, 0, 0, 0, 0); /* Initialize global nexus pointer */ pSiop->pNcrCtl = pSiop->pNcrCtlCmd; #ifdef NCR710_INT_LOG_MEM LOG_MEM_INTR;#endif /* NCR710_INT_LOG_MEM */ /* Flush all data involve in a transaction. */ ncr710FlushCache(pSiop, pSiop->pNcrCtl); ncr710StartScript (pSiop,pSiop->pNcrCtl, (SCSI_PHYS_DEV *)pSiop->pNcrCtl->pScsiPhysDev, (UINT *)pSiop->pNcrCtl->scriptAddr); return; case RECONNECT_PROCESS: SCSI_INT_DEBUG_MSG("ncr710Intr:reconnect\n", 0, 0, 0, 0, 0, 0); if ((pSiop->saveIdentMsg & SCSI_MSG_IDENTIFY) == 0) { /* It's a bogus reconnect continue */ logMsg ("ncr710Intr:bogus reselect msgIn = 0x%02x\n", pSiop->saveIdentMsg, 0, 0, 0, 0, 0);#ifdef NCR710_INT_LOG_MEM LOG_MEM_INTR;#endif /* NCR710_INT_LOG_MEM */ ncr710StartScript(pSiop,pSiop->pNcrCtl, (SCSI_PHYS_DEV *)pSiop->pNcrCtl->pScsiPhysDev, &ackMsg1); return; } tmpLun = pSiop->saveIdentMsg & SCSI_MAX_LUN; /* Get scsi Id : we 've got the power of 2 both for * own controller id and target id,xor first to get * the target id 10000100 (ctr = 7 ,target = 2). */ tmp = (pSiop->ctrlIdPow2) ^ (*pSiop->pScratch3); /* extract number from power of 2 picture for indexing */ for (tmpReg=0;!(tmp & 0x1);tmpReg++) tmp = (tmp >> 1); /* Give devSyncSem for reconnected target by indexing ncrCtl * device array. */ pScsiPhysDev =(SCSI_PHYS_DEV *)pSiop->pNcrCtxt-> ncrCtl[tmpReg][tmpLun].pScsiPhysDev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -