📄 mb87030lib.c
字号:
return (ERROR); } while (!(*pSpc->pPsnsReg & SPC_PSNS_REQ) && (pScsiCtrl->scsiBusPhase != SCSI_BUS_FREE_PHASE)) { if ((maxCycles > 0) && (ix++ == maxCycles)) { if (scsiDebug) logMsg ("spcBusPhaseGet: timed-out waiting for REQ\n", 0, 0, 0, 0, 0, 0); spcScsiBusReset (pSpc); /* the bus is hung(?), reset it */ return (ERROR); } } if (pScsiCtrl->scsiBusPhase == SCSI_BUS_FREE_PHASE) { *pBusPhase = SCSI_BUS_FREE_PHASE; pScsiCtrl->scsiBusPhase = NONE; return (OK); } *pBusPhase = pScsiCtrl->scsiBusPhase = (int) (*pSpc->pPsnsReg & SPC_PSNS_PHASE_MASK); SCSI_DEBUG_MSG ("scsiPhase = %x\n", *pBusPhase, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* byteParityGet - return the parity of a given byte** RETURNS: 1 for odd parity, 0 for even parity.*/LOCAL int byteParityGet ( FAST UINT8 byte /* byte for which to report parity */ ) { FAST int result = 0; /* cumulative parity of byte */ FAST int ix; /* loop variable */ for (ix = 0; ix < 8; ix++) { if (byte & ((UINT8) (1 << ix))) result ^= 0x1; } return (result); }/********************************************************************************* spcSelTimeOutCvt - convert a select time-out in microseconds to its* equivalent SPC setting** The conversion formula is given on p. 4-8 of the 1988 Fujitsu SCSI Product* Profiles manual. The additive constant 15 has been omitted here since it is* trivial. Note that 0 translates to the standard setting of 250 usec. Also,* the SPC accepts up to a 16 bit time-out, so a maximum value of 0xffff is* returned in *pTimeOutSetting.*/LOCAL void spcSelTimeOutCvt ( FAST SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ FAST UINT timeOutInUsec, /* time-out in microsecs */ FAST UINT *pTimeOutSetting /* time-out equivalent setting */ ) { FAST SPC *pSpc = (SPC *) pScsiCtrl; /* ptr to SPC info */ FAST UINT tempSelTimeOut; /* temp. select time-out setting */ int msbParity; /* parity of MSB of tempSelTimeOut */ int lsbParity; /* parity of LSB of tempSelTimeOut */ if (timeOutInUsec == 0) timeOutInUsec = SCSI_DEF_SELECT_TIMEOUT; tempSelTimeOut = (((timeOutInUsec * 1000) >> 9) / pScsiCtrl->clkPeriod) + 1; if (tempSelTimeOut > 0xffff) tempSelTimeOut = 0xffff; if (pSpc->spcDataParity != SPC_DATA_PARITY_VALID) { msbParity = byteParityGet ((UINT8) MSB(tempSelTimeOut)); lsbParity = byteParityGet ((UINT8) LSB(tempSelTimeOut)); if (msbParity == pSpc->spcDataParity) tempSelTimeOut ^= 0x100; if (lsbParity == pSpc->spcDataParity) tempSelTimeOut ^= 0x1; } *pTimeOutSetting = tempSelTimeOut; }/********************************************************************************* spcBusIdGet - get the current SCSI bus ID of the SPC.** Copies the bus ID to <pBusId>.** RETURNS:* OK if Bus ID register holds a legal value, otherwise ERROR.*/LOCAL STATUS spcBusIdGet ( FAST SPC *pSpc, /* ptr to SPC info */ FAST int *pBusId /* ptr to returned bus ID */ ) { FAST UINT8 tempReg; /* local copy of bus device ID register */ FAST int ix; /* count index */ tempReg = *pSpc->pBdidReg; for (ix = SCSI_MIN_BUS_ID; ix <= SCSI_MAX_BUS_ID; ix++) { if (tempReg == (UINT8) (1 << ix)) { *pBusId = ix; return (OK); } } *pBusId = NONE; return (ERROR); }/********************************************************************************* spcXferCountSet - load the SPC transfer counter with the specified count** RETURNS:* OK if count is in range 0 - 0xffffff, otherwise ERROR.** NOMANUAL*/STATUS spcXferCountSet ( FAST SPC *pSpc, /* ptr to SPC info */ FAST int count /* count value to load */ ) { if (count < 0 || count > SPC_MAX_XFER_LENGTH) return (ERROR); else { *pSpc->pTchReg = (UINT8) ((count >> 16) & 0xff); *pSpc->pTcmReg = (UINT8) ((count >> 8) & 0xff); *pSpc->pTclReg = (UINT8) (count & 0xff); return (OK); } }/********************************************************************************* spcXferCountGet - fetch the SPC transfer count** RETURNS: The value of the transfer counter is returned in *pCount.** NOMANUAL*/void spcXferCountGet ( FAST SPC *pSpc, /* ptr to SPC info */ FAST int *pCount /* ptr to returned value */ ) { FAST UINT tempCount = 0; tempCount |= (UINT) *pSpc->pTclReg; tempCount |= ((UINT) *pSpc->pTcmReg) << 8; tempCount |= ((UINT) *pSpc->pTchReg) << 16; *pCount = tempCount; }/********************************************************************************* spcIntsEnable - enable the SPC to assert interrupts** This routine sets the INT Enable bit in the SPC Control register.*/LOCAL void spcIntsEnable ( FAST SPC *pSpc /* ptr to SPC info */ ) { *pSpc->pSctlReg |= SPC_SCTL_INT_ENBL; }/********************************************************************************* spcIntsDisable - disable the SPC to assert interrupts** This routine resets the INT Enable bit in the SPC Control register.*/LOCAL void spcIntsDisable ( FAST SPC *pSpc /* ptr to SPC info */ ) { *pSpc->pSctlReg &= ~SPC_SCTL_INT_ENBL; }/********************************************************************************* spcScmdSet - write to the SPC Command Register** Provides maximum flexibility in controlling the options of the Command Reg.* The passed parameter for each bit should be set to SPC_RESET_BIT (0),* SPC_SET_BIT (1), or SPC_PRESERVE_BIT (-1). In the case of the command code,* either the desired command code or SPC_PRESERVE_FIELD (0xff) should be passed.*/LOCAL void spcScmdSet ( FAST SPC *pSpc, /* ptr to SPC info */ FAST UINT8 cmdCode, /* new command code or SPC_PRESERVE_FIELD */ int resetOutBit, /* set, reset, or preserve "reset out" bit */ int interceptXferBit, /* set, reset, or preserve "intercept xfer" bit */ int prgXferBit, /* set, reset, or preserve "program transfer" bit */ int termModeBit /* set, reset, or preserve "termination mode" bit */ ) { FAST UINT8 tempScmd; /* temporary copy of SPC Command register */ tempScmd = *pSpc->pScmdReg; if (cmdCode != SPC_PRESERVE_FIELD) { tempScmd &= ~SPC_SCMD_CMD_MASK; /* clear existing command code */ /* fill in the desired command */ tempScmd |= (cmdCode & SPC_SCMD_CMD_MASK); } switch (resetOutBit) { case SPC_PRESERVE_BIT: break; case SPC_SET_BIT: tempScmd |= SPC_SCMD_RESET_OUT; break; case SPC_RESET_BIT: tempScmd &= ~SPC_SCMD_RESET_OUT; break; } switch (interceptXferBit) { case SPC_PRESERVE_BIT: break; case SPC_SET_BIT: tempScmd |= SPC_SCMD_INTERCEPT_XFER; break; case SPC_RESET_BIT: tempScmd &= ~SPC_SCMD_INTERCEPT_XFER; break; } switch (prgXferBit) { case SPC_PRESERVE_BIT: break; case SPC_SET_BIT: tempScmd |= SPC_SCMD_PRG_XFER; break; case SPC_RESET_BIT: tempScmd &= ~SPC_SCMD_PRG_XFER; break; } switch (termModeBit) { case SPC_PRESERVE_BIT: break; case SPC_SET_BIT: tempScmd |= SPC_SCMD_TERM_MODE; break; case SPC_RESET_BIT: tempScmd &= ~SPC_SCMD_TERM_MODE; break; } *pSpc->pScmdReg = tempScmd; }/********************************************************************************* spcCommand - write a command code to the SPC Command Register** NOMANUAL*/void spcCommand ( FAST SPC *pSpc, /* ptr to SPC info */ FAST UINT8 cmdCode /* new command code */ ) { FAST UINT8 tempScmd; /* temporary copy of SPC Command register */ tempScmd = *pSpc->pScmdReg; tempScmd &= ~SPC_SCMD_CMD_MASK; /* clear existing command code */ tempScmd |= (cmdCode & SPC_SCMD_CMD_MASK); /* fill in the desired command */ *pSpc->pScmdReg = tempScmd; }/********************************************************************************* spcTmodSet - write to the SPC Transfer Mode Register** Used to set up SPC for synchronous or asynchronous data transfers. maxOffset* and minPeriod parameters may be specified as legal values:* maxOffset: 1 - 8 (see Fujitsu documentation)* minPerMinusOne: 0 - 3 (see Fujitsu documentation)* or as SPC_PRESERVE_FIELD (0xff). They will be ignored if syncXfer is FALSE,* since they are only relevant to synchronous transfer mode. Illegal values* will merely be masked into legality.*/LOCAL void spcTmodSet ( FAST SPC *pSpc, /* ptr to SPC info */ BOOL syncXfer, /* TRUE for synch. xfer, FALSE for asynch. */ FAST int maxOffset, /* maximum transfer offset */ FAST int minPerMinusOne /* minimum transfer period minus one */ ) { FAST UINT8 tempTmod; /* temporary copy of SPC Transfer Mode register */ tempTmod = *pSpc->pTmodReg; if (syncXfer == FALSE) tempTmod &= ~SPC_TMOD_SYNC_XFER; else { tempTmod |= SPC_TMOD_SYNC_XFER; if (maxOffset != SPC_PRESERVE_FIELD) { tempTmod &= ~SPC_TMOD_MAX_OFFSET_MASK; /* clear existing offset */ /* set the desired offset */ tempTmod |= ((maxOffset << 4) & SPC_TMOD_MAX_OFFSET_MASK); } if (minPerMinusOne != SPC_PRESERVE_FIELD) { tempTmod &= ~SPC_TMOD_MIN_PERIOD_MASK; /* clear existing period */ /* set the desired period */ tempTmod |= ((minPerMinusOne << 2) & SPC_TMOD_MIN_PERIOD_MASK); } } *pSpc->pTmodReg = tempTmod; }/********************************************************************************* spcPctlSet - write to the SPC Phase Control Register** Provides flexibility in controlling the options of the Phase Control Reg.* The passed parameter for the busFreeIntEnbl bit should be set to* SPC_RESET_BIT (0), SPC_SET_BIT (1), or SPC_PRESERVE_BIT (-1). In the case* of the transfer phase, either the desired phase or SPC_PRESERVE_FIELD* (0xff) should be passed.*/LOCAL void spcPctlSet ( FAST SPC *pSpc, /* ptr to SPC info */ int busFreeIntEnblBit, /* set, reset, or preserve "bus free int." bit */ FAST UINT8 xferPhase /* new transfer phase or SPC_PRESERVE_FIELD */ ) { FAST UINT8 tempPctl; /* temporary copy of SPC Pctl register */ tempPctl = *pSpc->pPctlReg; switch (busFreeIntEnblBit) { case SPC_PRESERVE_BIT: break; case SPC_SET_BIT: tempPctl |= SPC_PCTL_BF_INT_ENBL; break; case SPC_RESET_BIT: tempPctl &= ~SPC_PCTL_BF_INT_ENBL; break; } if (xferPhase != SPC_PRESERVE_FIELD) { tempPctl &= ~SPC_PCTL_PHASE_MASK; /* clear existing xfer phase */ /* fill in the new phase */ tempPctl |= (xferPhase & SPC_PCTL_PHASE_MASK); } *pSpc->pPctlReg = tempPctl; }/********************************************************************************* spcScsiBusReset - assert the RST line on the SCSI bus** Asserts the RST line on SCSI which should cause all connected devices to* return to a quiescent state.* JCC Timing delays should be made prettier and more precise.*/LOCAL void spcScsiBusReset ( FAST SPC *pSpc /* ptr to SPC info */ ) { int delayVar; /* delay loop counter */ spcScmdSet (pSpc, SPC_SCMD_BUS_RELEASE, SPC_SET_BIT, SPC_PRESERVE_BIT, SPC_PRESERVE_BIT, SPC_PRESERVE_BIT); for (delayVar = 0; delayVar < 0x1000; delayVar++) ; spcScmdSet (pSpc, SPC_PRESERVE_FIELD, SPC_RESET_BIT, SPC_PRESERVE_BIT, SPC_PRESERVE_BIT, SPC_PRESERVE_BIT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -