📄 wd33c93lib1.c
字号:
if (sbicBusId == pScsiPhysDev->scsiDevBusId) { errnoSet (S_scsiLib_ILLEGAL_BUS_ID); return (ERROR); } sbicRegWrite (pSbic, SBIC_REG_DEST_ID, (UINT8) pScsiPhysDev->scsiDevBusId); sbicRegWrite (pSbic, SBIC_REG_TO_PERIOD, (UINT8) pScsiPhysDev->selTimeOut); pSbic->pDevToSelect = pScsiPhysDev; sbicCommand (pSbic, pScsiPhysDev->useIdentify ? SBIC_CMD_SEL_ATN : SBIC_CMD_SELECT); semTake (&pScsiPhysDev->devSyncSem, WAIT_FOREVER); if (pScsiPhysDev->devStatus == SELECT_SUCCESSFUL) { if (pScsiPhysDev->useIdentify) /* send an identify message */ { if ((sbicBusPhaseGet (&pSbic->scsiCtrl, 0, &scsiPhase) == ERROR) || (scsiPhase != SCSI_MSG_OUT_PHASE)) return (ERROR); identMsg = SCSI_MSG_IDENTIFY | (pSbic->scsiCtrl.disconnect ? SCSI_MSG_IDENT_DISCONNECT : 0) | (UINT8) pScsiPhysDev->scsiDevLUN; status = sbicProgBytesOut (pScsiPhysDev, &identMsg, sizeof (identMsg), SCSI_MSG_OUT_PHASE); if (status == ERROR) return (ERROR); } return (OK); } if (pScsiPhysDev->devStatus == SELECT_TIMEOUT) errnoSet (S_scsiLib_SELECT_TIMEOUT); return (ERROR); }/********************************************************************************* sbicMsgInAck - issue a NEG_ACK command thereby accepting an incoming message** This routine should be called when an incoming message has been read and* accepted. If the incoming message did not imply an impending disconnect,* give the synchronization semaphore, so that subsequent phase can be detected.** RETURNS: OK.*/LOCAL STATUS sbicMsgInAck ( FAST SCSI_CTRL *pScsiCtrl, /* ptr to SBIC info */ BOOL expectDisconn /* whether a disconnect is expected */ ) { sbicCommand ((SBIC *) pScsiCtrl, SBIC_CMD_NEG_ACK); if (!expectDisconn) semGive (&pScsiCtrl->ctrlSyncSem); return (OK); }/********************************************************************************* sbicProgBytesOut - output data bytes to SCSI using 'program' transfer** This routine transfers the data from the data buffer into the* chip's data register.** RETURNS: OK, or ERROR if <bufLength> is out of range.** NOMANUAL*/STATUS sbicProgBytesOut ( SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to drive info in SBIC */ FAST UINT8 *pBuffer, /* pointer to the data buffer */ FAST int bufLength, /* number of bytes to be transferred */ int scsiPhase /* phase of the transfer */ ) { FAST SBIC *pSbic; /* ptr to SBIC info */ SCSI_DEBUG_MSG ("sbicProgBytesOut: bufLength = %d, scsiPhase = %d\n", bufLength, scsiPhase, 0, 0, 0, 0); pSbic = (SBIC *) pScsiPhysDev->pScsiCtrl; if (bufLength != 1) { if (sbicXferCountSet (pSbic, (UINT) bufLength) == ERROR) return (ERROR); sbicCommand (pSbic, SBIC_CMD_XFER_INFO); } else sbicCommand (pSbic, SBIC_CMD_XFER_INFO | SBIC_CMD_SING_BYTE_XFER); *pSbic->pAdrsReg = SBIC_REG_DATA; while (bufLength-- > 0) { while (!(*pSbic->pAuxStatReg & SBIC_AUX_STAT_DBUF_READY)) ; *pSbic->pRegFile = *pBuffer++; } return (OK); }/********************************************************************************* sbicProgBytesIn - input data bytes from SCSI using 'program' transfer** This routine transfers data into the data buffer from the chip's* data register.** RETURNS: OK, or ERROR if <bufLength> is out of range.** NOMANUAL*/STATUS sbicProgBytesIn ( SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to drive info in SBIC */ FAST UINT8 *pBuffer, /* pointer to the data buffer */ FAST int bufLength, /* number of bytes to be transferred */ int scsiPhase /* phase of the transfer */ ) { FAST SBIC *pSbic; /* ptr to SBIC info */ SCSI_DEBUG_MSG ("sbicProgBytesIn: bufLength = %d, scsiPhase = %d\n", bufLength, scsiPhase, 0, 0, 0, 0); pSbic = (SBIC *) pScsiPhysDev->pScsiCtrl; if (bufLength != 1) { if (sbicXferCountSet (pSbic, (UINT) bufLength) == ERROR) return (ERROR); sbicCommand (pSbic, SBIC_CMD_XFER_INFO); } else sbicCommand (pSbic, SBIC_CMD_XFER_INFO | SBIC_CMD_SING_BYTE_XFER); *pSbic->pAdrsReg = SBIC_REG_DATA; while (bufLength-- > 0) { while (!(*pSbic->pAuxStatReg & SBIC_AUX_STAT_DBUF_READY)) ; *pBuffer++ = *pSbic->pRegFile; } if (scsiPhase == SCSI_MSG_IN_PHASE) { semTake (&pSbic->scsiCtrl.ctrlSyncSem, WAIT_FOREVER); sbicMsgInAck ((SCSI_CTRL *) pScsiPhysDev->pScsiCtrl, TRUE); } return (OK); }/********************************************************************************* sbicBytesOut - switch to appropriate output routine** This routine executes the scsiDmaBytesOut() routine if not NULL, otherwise* sbicProgBytesOut() is run.** RETURNS: The return value from the called routine.*/LOCAL STATUS sbicBytesOut ( FAST SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to SCSI physical dev info */ FAST char *pBuffer, /* ptr to byte buffer for output */ int bufLength, /* number of bytes to be transferred */ int scsiPhase /* SCSI bus phase of the transfer */ ) { FAST SBIC *pSbic; /* ptr to SBIC info */ pSbic = (SBIC *) pScsiPhysDev->pScsiCtrl; if ((scsiPhase != SCSI_DATA_OUT_PHASE) || (pSbic->scsiCtrl.scsiDmaBytesOut == NULL)) { return (sbicProgBytesOut (pScsiPhysDev, (UINT8 *) pBuffer, bufLength, scsiPhase)); } else { return ((pSbic->scsiCtrl.scsiDmaBytesOut) (pScsiPhysDev, (UINT8 *) pBuffer, bufLength)); } }/********************************************************************************* sbicBytesIn - switch to appropriate input routine** This routine executes the scsiDmaBytesIn() routine if not NULL, otherwise* sbicPorgBytesIn() is run.** RETURNS: The return value from the called routine.*/LOCAL STATUS sbicBytesIn ( FAST SCSI_PHYS_DEV *pScsiPhysDev, /* ptr to SCSI physical dev info */ FAST char *pBuffer, /* ptr to byte buffer for output */ int bufLength, /* number of bytes to be transferred */ int scsiPhase /* SCSI bus phase of the transfer */ ) { FAST SBIC *pSbic; /* ptr to SBIC info */ pSbic = (SBIC *) pScsiPhysDev->pScsiCtrl; if ((scsiPhase != SCSI_DATA_IN_PHASE) || (pSbic->scsiCtrl.scsiDmaBytesIn == NULL)) { return (sbicProgBytesIn (pScsiPhysDev, (UINT8 *) pBuffer, bufLength, scsiPhase)); } else { return ((pSbic->scsiCtrl.scsiDmaBytesIn) (pScsiPhysDev, (UINT8 *) pBuffer, bufLength)); } }/********************************************************************************* sbicBusPhaseGet - return the current SCSI bus phase in *pBusPhase** This routine gets the value of the current SCSI bus phase.** RETURNS: OK, or ERROR if no phase is detected.*/LOCAL STATUS sbicBusPhaseGet ( FAST SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ int timeOutInUsec, /* timeout in usec (0 == infinity) */ FAST int *pBusPhase /* ptr to returned bus phase */ ) { FAST SBIC * pSbic; /* ptr to SBIC info */ int timeOut; pSbic = (SBIC *) pScsiCtrl; if (timeOutInUsec > SCSI_TIMEOUT_5SEC) timeOut = ((timeOutInUsec / SCSI_TIMEOUT_1SEC) * sysClkRateGet ()); else timeOut = ((timeOutInUsec * sysClkRateGet()) / SCSI_TIMEOUT_1SEC); if (timeOut == 0) timeOut = WAIT_FOREVER; if (semTake (&pScsiCtrl->ctrlSyncSem, timeOut) == ERROR) { sbicScsiBusReset (pSbic); /* the bus is hung(?), reset it */ return (ERROR); } if (pSbic->scsiCtrl.scsiBusPhase == NONE) return (ERROR); *pBusPhase = pSbic->scsiCtrl.scsiBusPhase; return (OK); }/********************************************************************************* sbicSelTimeOutCvt - convert a select timeout from usec to SBIC units** The conversion formula is given on p. 11 of the Western Digital WD33C93* manual. Note that 0 specifies the default setting of 250 usec. Also,* the SBIC accepts up to a 8-bit timeout, so a maximum value of 0xff is* returned in *pTimeOutSetting.** RETURNS: N/A.*/LOCAL void sbicSelTimeOutCvt ( FAST SCSI_CTRL *pScsiCtrl, /* ptr to SCSI controller info */ FAST UINT timeOutInUsec, /* timeout in microsecs */ FAST UINT *pTimeOutSetting /* ptr to result */ ) { FAST UINT tempSelTimeOut; /* temp. select timeout setting */ if (timeOutInUsec == (UINT) 0) timeOutInUsec = SCSI_DEF_SELECT_TIMEOUT; tempSelTimeOut = (timeOutInUsec / (80 * pScsiCtrl->clkPeriod)) + 1; if (tempSelTimeOut > 0xff) tempSelTimeOut = 0xff; *pTimeOutSetting = tempSelTimeOut; }/********************************************************************************* sbicXferCountSet - load the SBIC transfer counter with the specified count** RETURNS: OK, or ERROR if <count> is not in the* range 0 - WD_33C93_MAX_BYTES_PER_XFER.** NOMANUAL*/STATUS sbicXferCountSet ( FAST SBIC *pSbic, /* ptr to SBIC info */ FAST UINT count /* count value to load */ ) { int nbits = 24; if (count > WD_33C93_MAX_BYTES_PER_XFER) return (ERROR); *pSbic->pAdrsReg = (SBIC_REG_XFER_COUNT_MSB); while (nbits) { *pSbic->pRegFile = (UINT8) ((count >> (nbits - 8)) & 0xff); nbits -= 8; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -