📄 wd33c93lib2.c
字号:
} *pOffset = offset; *pPeriod = period; *pXferParams = xferParams; return (inRange); }/********************************************************************************* sbicXferCountSet - load the SBIC transfer counter with the specified count ** RETURNS: OK if count is in range 0 - 0xffffff, otherwise ERROR.** NOMANUAL*/LOCAL STATUS sbicXferCountSet ( FAST SBIC *pSbic, /* ptr to SBIC info */ FAST UINT count /* count value to load */ ) { if (count > WD_33C93_MAX_BYTES_PER_XFER) return (ERROR); *pSbic->pAdrsReg = SBIC_REG_XFER_COUNT_MSB; *pSbic->pRegFile = (UINT8) ((count >> 16) & 0xff); *pSbic->pRegFile = (UINT8) ((count >> 8) & 0xff); *pSbic->pRegFile = (UINT8) ( count & 0xff); return (OK); }/********************************************************************************* sbicXferCountGet - fetch the SBIC transfer count ** The value of the transfer counter is copied to *pCount.** NOMANUAL*/LOCAL void sbicXferCountGet ( FAST SBIC *pSbic, /* ptr to SBIC info */ FAST UINT *pCount /* ptr to returned value */ ) { FAST UINT tempCount; *pSbic->pAdrsReg = SBIC_REG_XFER_COUNT_MSB; tempCount = ((UINT) *pSbic->pRegFile) << 16; tempCount |= ((UINT) *pSbic->pRegFile) << 8; tempCount |= (UINT) *pSbic->pRegFile; *pCount = (int) tempCount; }/********************************************************************************* sbicCommand - write a command code to the SBIC Command Register** NOMANUAL*/LOCAL void sbicCommand ( SBIC *pSbic, /* ptr to SBIC info */ UINT8 cmdCode /* new command code */ ) { while (*pSbic->pAuxStatReg & SBIC_AUX_STAT_CMD_IN_PROG) ; *pSbic->pAdrsReg = SBIC_REG_COMMAND; *pSbic->pRegFile = cmdCode; }/********************************************************************************* sbicIntr - interrupt service routine for the SBIC** NOMANUAL*/LOCAL void sbicIntr ( SBIC *pSbic /* ptr to SBIC info */ ) { UINT8 scsiStatus; int targetId; SBIC_STATE state; SCSI_EVENT event; int busPhase = NONE; /* init. to prevent a warning */ BOOL initComplete = FALSE; BOOL xferComplete = FALSE; event.type = NONE; /* * Read SCSI status register and "decode" into state transitions etc. */ *pSbic->pAdrsReg = SBIC_REG_SCSI_STATUS; scsiStatus = *pSbic->pRegFile; state = pSbic->state; SCSI_INT_DEBUG_MSG ("SBIC Interrupt: code = 0x%02x (state = %d)\n", scsiStatus, state, 0, 0, 0, 0); /* * Parse SBIC SCSI status; generate state info (don't change state yet !) */ if (scsiStatus & STAT_PHASE_REQ) { busPhase = (int) (scsiStatus & STAT_MCI_BITS); scsiStatus |= STAT_MCI_BITS; } /* * If the target disconnects after an info transfer but before a new * phase has been requested, the 33C93 appears to generate a normal * disconnect interrupt rather than an unexpected disconnect. To keep * the ISR logic clean, we convert this to an unexpected disconnect. */ if ((scsiStatus == STAT_SERV_REQ_DISCON) && pSbic->xferPending) { scsiStatus = STAT_TERM_UNEXP_DISCON; } switch (scsiStatus) { /* Group: Reset */ case STAT_SUCC_RESET: initComplete = TRUE; state = SBIC_STATE_IDLE; break; /* Group: Successful Completion */ case STAT_SUCC_SELECT: /* assert (state == SBIC_STATE_SELECT_PENDING); */ /* Select command completed successfully */ sbicRegRead (pSbic, SBIC_REG_DEST_ID, &targetId); event.type = SCSI_EVENT_CONNECTED; event.busId = targetId & 0x07; event.nBytesIdent = 0; state = SBIC_STATE_CONNECTED; break; case STAT_SUCC_XFER_MCI: /* assert (state == SBIC_STATE_CONNECTED); */ /* current transfer completed: req for new phase */ event.type = SCSI_EVENT_XFER_REQUEST; event.phase = busPhase; xferComplete = TRUE; break; /* Group: Paused/Aborted */ case STAT_PAUSE_MSG_IN: /* assert (state == SBIC_STATE_CONNECTED); */ /* current msg in transfer completed: ack asserted */ xferComplete = TRUE; break; /* Group: Terminated */ case STAT_TERM_UNEXP_DISCON: /* assert (state == SBIC_STATE_CONNECTED); */ /* current transfer terminated due to disconnection */ event.type = SCSI_EVENT_DISCONNECTED; xferComplete = TRUE; state = SBIC_STATE_IDLE; break; case STAT_TERM_TIMEOUT: /* assert (pSbic->state == SBIC_STATE_SELECT_PENDING); */ /* Select command timed out */ event.type = SCSI_EVENT_TIMEOUT; state = SBIC_STATE_IDLE; break; case STAT_TERM_UNX_PHASE: /* assert (state == SBIC_STATE_CONNECTED); */ /* current transfer terminated by req for new phase */ event.type = SCSI_EVENT_XFER_REQUEST; event.phase = busPhase; xferComplete = TRUE; break; /* Group: Service Required */ case STAT_SERV_REQ_RESELECT: sbicRegRead (pSbic, SBIC_REG_SOURCE_ID, &targetId); event.type = SCSI_EVENT_RESELECTED; event.busId = targetId & 0x07; event.nBytesIdent = 0; state = SBIC_STATE_CONNECTED; break; case STAT_SERV_REQ_DISCON: /* assert (state == SBIC_STATE_CONNECTED); */ event.type = SCSI_EVENT_DISCONNECTED; state = SBIC_STATE_IDLE; break; case STAT_SERV_REQ_ASSERTED: /* assert (state == SBIC_STATE_CONNECTED); */ event.type = SCSI_EVENT_XFER_REQUEST; event.phase = busPhase; break; default: logMsg ("Unexpected SBIC Interrupt, Code = 0x%02x (state = %d)\n", scsiStatus, state, 0, 0, 0, 0); break; } /* * Handle state transition, if any */ if (state != pSbic->state) { SCSI_INT_DEBUG_MSG ("SBIC state transition: %d -> %d\n", pSbic->state, state, 0, 0, 0, 0); pSbic->state = state; } /* * Synchronize with task-level code */ if (initComplete && pSbic->initPending) { pSbic->initPending = FALSE; sbicPostResetInit (pSbic); } if (xferComplete && pSbic->xferPending) { pSbic->xferPending = FALSE; semGive (&pSbic->xferDoneSem); } /* * Post event to SCSI manager for further processing */ if (event.type != NONE) scsiMgrEventNotify ((SCSI_CTRL *)pSbic, &event, sizeof (event)); }/********************************************************************************* sbicHwInit - initialize the SBIC to a known state** This routine puts the SBIC into a known quiescent state. It does *not** reset the SCSI bus (and any other devices thereon).** The reselection interrupt is enabled iff the "disconnect" flag is set in* the SCSI controller data structure. DMA transfers are enabled iff there is* a DMA transfer function in the SCSI controller data structure.** NOTE: the SBIC does not preserve its entire register context over a software* reset so the initialisation is completed in the reset interrupt handler.* If the routine is called at task level, it waits until this processing has* been completed (a busy wait, as it's only a few microseconds). If it is* called from interrupt level, it does *not* wait for the reset to complete.* Be warned !*/LOCAL void sbicHwInit ( SBIC *pSbic /* ptr to an SBIC structure */ ) { pSbic->initPending = TRUE; sbicRegWrite (pSbic, SBIC_REG_OWN_ID, (UINT8) pSbic->scsiCtrl.scsiCtrlBusId); sbicCommand (pSbic, SBIC_CMD_RESET); if (!intContext ()) { /* * Wait for "reset" command to finish. Busy wait on flag set by * reset interrupt handler - shouldn't be more than a few microsecs, * but don't wait more than SBIC_MAX_RESET_WAIT clock ticks in any * case. */ ULONG timeOut = tickGet () + SBIC_MAX_RESET_WAIT; while (pSbic->initPending && (tickGet () < timeOut)) ; if (pSbic->initPending) logMsg ("sbicHwInit: initialisation command not completed !\n", 0, 0, 0, 0, 0, 0); } }/******************************************************************************** sbicPostResetInit - SBIC post-reset initialisation** This routine completes the SBIC initialisation started in "sbicHwInit ()".* It is called at interrupt level after the software reset command has* completed.*/LOCAL void sbicPostResetInit ( FAST SBIC *pSbic /* ptr to SBIC info */ ) { UINT8 srcIdVal = pSbic->scsiCtrl.disconnect ? SBIC_SRC_ID_RESEL_ENABLE : 0x00; UINT8 ctrlVal = (pSbic->sysScsiDmaStart != NULL) ? SBIC_CONTROL_DMA_ENABLE : 0x00; sbicRegWrite (pSbic, SBIC_REG_SOURCE_ID, srcIdVal); sbicRegWrite (pSbic, SBIC_REG_CONTROL, ctrlVal); }/********************************************************************************* sbicRegRead - Get the contents of a specified SBIC register*/LOCAL void sbicRegRead ( SBIC *pSbic, /* ptr to an SBIC structure */ UINT8 regAdrs, /* address of register to read */ int *pDatum /* buffer for return value */ ) { *pSbic->pAdrsReg = regAdrs; *pDatum = (int) *pSbic->pRegFile; }/********************************************************************************* sbicRegWrite - write a value to a specified SBIC register** NOMANUAL*/LOCAL void sbicRegWrite ( SBIC *pSbic, /* ptr to an SBIC structure */ UINT8 regAdrs, /* address of register to write */ UINT8 datum /* value to be written */ ) { *pSbic->pAdrsReg = regAdrs; *pSbic->pRegFile = datum; }/********************************************************************************* wd33c93Show - Display values of all readable wd33c93 chip registers** Only for use during debugging.** RETURNS: OK | ERROR.*/LOCAL STATUS wd33c93Show ( FAST SCSI_CTRL *pScsiCtrl /* ptr to SCSI controller info */ ) { FAST int ix; FAST SBIC *pSbic; /* ptr to SBIC info */ if (pScsiCtrl == NULL) { if (pSysScsiCtrl != NULL) pScsiCtrl = pSysScsiCtrl; else { printErr ("No SCSI controller specified.\n"); return (ERROR); } } pSbic = (SBIC *) pScsiCtrl; for (ix = SBIC_REG_OWN_ID; ix <= SBIC_REG_COMMAND; ix++) { *pSbic->pAdrsReg = (UINT8) ix; printf ("REG #%02x = 0x%02x\n", ix, *pSbic->pRegFile); } return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -