⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wd33c93lib2.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* reject attempts to select self */        if (devBusId == pScsiCtrl->scsiCtrlBusId)	{	errnoSet (S_scsiLib_ILLEGAL_BUS_ID);        return (ERROR);	}    /* convert timeout period to SBIC units, in place */        sbicSelTimeOutCvt (pSbic, selTimeOut, &selTimeOut);    selectCmd = (msgLen != 0) ? SBIC_CMD_SEL_ATN : SBIC_CMD_SELECT;        /*     *	Check SBIC is IDLE, then issue SELECT command.  Must be done with     *	interrupts locked to avoid races with the reselection ISR.     *     *	If the controller is not IDLE, do not issue a select command.  Just     *	return - there must be a (re)selection event pending which will be     *	handled exactly as if it occurred just after the select command was     *	issued.     */    lockKey = intLock ();    switch (pSbic->state)	{	case SBIC_STATE_IDLE:	    pSbic->state = SBIC_STATE_SELECT_PENDING;	    sbicRegWrite (pSbic, SBIC_REG_DEST_ID,   (UINT8) devBusId);	    sbicRegWrite (pSbic, SBIC_REG_TO_PERIOD, (UINT8) selTimeOut);	    sbicCommand  (pSbic, selectCmd);	    status = OK;	    break;	case SBIC_STATE_CONNECTED:	    status = OK;	    break;	case SBIC_STATE_SELECT_PENDING:	default:	    status = ERROR;	    break;	}    intUnlock (lockKey);    if (status != OK)	{	SCSI_DEBUG_MSG ("sbicDevSelect: invalid controller state (%d)\n",		    	pSbic->state, 0, 0, 0, 0, 0);	}    return (status);    }/********************************************************************************* sbicBusControl - miscellaneous low-level SCSI bus control operations** Allows the caller to:-**   - assert the SCSI ATN signal (indicating a message out is available)*   - negate the SCSI ACK signal (indicating a message in has been read)** The "operation" parameter is a bitmask which allows any combination of these* functions to be carried out with a single call.  Note that the order in* which things are done is important: ATN is asserted (if specified) before* ACK is negated.  (This allows an incoming SCSI message to be rejected.)** NOTE: since the SBIC is not connected to the SCSI bus RST signal, a board-* specific function is used to implement the BUS_RESET command.  As a result* of calling this function, something must notify the SCSI manager task that* a bus reset has occurred ...** RETURNS: OK (no error conditions)*/LOCAL STATUS sbicBusControl    (    SCSI_CTRL *pScsiCtrl,	/* ptr to SBIC info                         */    int        operation	/* bitmask for operation(s) to be performed */    )    {    FAST SBIC *pSbic = (SBIC *) pScsiCtrl;    if (operation & SCSI_BUS_RESET)	(*pSbic->sysScsiBusReset) (pSbic->sysScsiResetArg);    if (operation & SCSI_BUS_ASSERT_ATN)	sbicCommand (pSbic, SBIC_CMD_SET_ATN);    if (operation & SCSI_BUS_NEGATE_ACK)    	sbicCommand (pSbic, SBIC_CMD_NEG_ACK);    return (OK);    }/********************************************************************************* sbicXferParamsQuery - get (synchronous) transfer parameters** Updates the synchronous transfer parameters suggested in the call to match* the SBIC's capabilities.  Transfer period is in SCSI units (multiples of* 4 ns).** Note: the transfer period is made longer and the offset is made smaller if* the SBIC cannot handle the specified values.** RETURNS: OK*/LOCAL STATUS sbicXferParamsQuery    (    SCSI_CTRL *pScsiCtrl,		/* ptr to SBIC info             */    UINT8     *pOffset,			/* max REQ/ACK offset  [in/out] */    UINT8     *pPeriod			/* min transfer period [in/out] */    )    {    UINT8 unused;    (void) sbicXferParamsCvt ((SBIC *) pScsiCtrl, pOffset, pPeriod, &unused);        return (OK);    }    /********************************************************************************* sbicXferParamsSet - set transfer parameters** Programs the SBIC to use the specified transfer parameters.  An offset* of zero specifies asynchronous transfer (period is then irrelevant).* Transfer period is in SCSI units (multiples of 4 ns).** RETURNS: OK if transfer parameters are OK, else ERROR.*/LOCAL STATUS sbicXferParamsSet    (    SCSI_CTRL *pScsiCtrl,		/* ptr to SBIC info       */    UINT8      offset,			/* max REQ/ACK offset     */    UINT8      period			/* min transfer period    */    )    {    FAST SBIC *pSbic = (SBIC *) pScsiCtrl;    UINT8      xferParams;        if (!sbicXferParamsCvt (pSbic, &offset, &period, &xferParams))	{				/* should never happen */	errnoSet (S_scsiLib_ILLEGAL_PARAMETER);	return (ERROR);	}    sbicRegWrite (pSbic, SBIC_REG_SYNC_XFER, xferParams);    return (OK);    }/********************************************************************************* sbicInfoXfer - transfer information bytes to/from target via SCSI bus** Executes a "Transfer Info" command to read (write) bytes from (to) the* SCSI bus.  If the transfer phase is DATA IN or DATA OUT and there is a* DMA routine available, DMA is used - otherwise it's a tight programmed* i/o loop.** Returns when the transfer has completed; i.e., the last byte has been* received (sent) and ACK is still asserted in the case of MESSAGE IN* transfers, or a request for a new information transfer has occurred (for* all other types of transfer).** The returned value is the number of bytes actually transferred across the* SCSI bus.  In the case of DATA phases, this may be less than the requested* transfer length because the target may change the information phase "early"* (to send a message in, for example).  For non-DATA transfers, if the byte* count transferred is not what was asked for, it is probably an error* condition (left to the caller's discretion).** RETURNS: Number of bytes transferred across SCSI bus, or ERROR.*/LOCAL int sbicInfoXfer    (    FAST SCSI_CTRL *pScsiCtrl,      	/* ptr to SCSI controller info       */    int             phase,  	    	/* SCSI phase being transferred      */    FAST UINT8     *pBuf,		/* ptr to byte buffer for i/o        */    UINT            bufLength		/* number of bytes to be transferred */    )    {    FAST SBIC  *pSbic;			/* ptr to SBIC info                  */    FAST UINT8  auxStatus;		/* SBIC auxiliary status             */    UINT        bytesLeft;		/* bytes not transferred across bus  */    int         direction;		/* input (READ) or output (WRITE)    */    BOOL        usingDMA;		/* using DMA for this transfer ?     */    pSbic = (SBIC *) pScsiCtrl;    SCSI_DEBUG_MSG ("sbicInfoXfer: phase = %d, buf = 0x%x, length = %d\n",		    phase, (int) pBuf, bufLength, 0, 0, 0);    /*     *	Set transfer count, issue Transfer Info command     */    if (sbicXferCountSet (pSbic, (UINT) bufLength) != OK)	{    	errnoSet (S_scsiLib_ILLEGAL_PARAMETER);	return (ERROR);	}    sbicCommand (pSbic, SBIC_CMD_XFER_INFO);    /*     *	Identify phase, set transfer mode accordingly     */    switch (phase)	{    	case SCSI_DATA_OUT_PHASE:	    direction = WRITE;	    usingDMA  = (pSbic->sysScsiDmaStart != NULL);	    break;	        	case SCSI_DATA_IN_PHASE:	    direction = READ;	    usingDMA  = (pSbic->sysScsiDmaStart != NULL);	    break;	case SCSI_COMMAND_PHASE:    	case SCSI_MSG_OUT_PHASE:	    direction = WRITE;	    usingDMA  = FALSE;	    break;	    	case SCSI_STATUS_PHASE:    	case SCSI_MSG_IN_PHASE:	    direction = READ;	    usingDMA  = FALSE;	    break;        default:	    SCSI_MSG ("sbicInfoXfer: invalid bus phase (%d)\n",		      phase, 0, 0, 0, 0, 0);	    return (ERROR);	}        /*     *	Start DMA, if used, or programmed i/o loop to transfer data     */    pSbic->xferPending = TRUE;        if (usingDMA)	{        if ((*pSbic->sysScsiDmaStart) (pSbic->sysScsiDmaArg,				       pBuf,				       bufLength,				       direction) != OK)	    {	    SCSI_MSG ("sbicInfoXfer: unable to start DMA transfer\n",		      0, 0, 0, 0, 0, 0);	    return (ERROR);	    }	}    else if (direction == READ)	{    	*pSbic->pAdrsReg = SBIC_REG_DATA;    	while ((auxStatus = *pSbic->pAuxStatReg) & SBIC_AUX_STAT_BUSY)	    {	    if (auxStatus & SBIC_AUX_STAT_DBUF_READY)	    	*pBuf++ = *pSbic->pRegFile;	    }	}    else /* (direction == WRITE) */	{    	*pSbic->pAdrsReg = SBIC_REG_DATA;    	while ((auxStatus = *pSbic->pAuxStatReg) & SBIC_AUX_STAT_BUSY)	    {	    if (auxStatus & SBIC_AUX_STAT_DBUF_READY)	    	*pSbic->pRegFile = *pBuf++;	    }	}    /*     *	Wait for transfer to complete: find out how many bytes transferred,     *  abort DMA transfer if necessary.     */    semTake (&pSbic->xferDoneSem, WAIT_FOREVER);        sbicXferCountGet (pSbic, &bytesLeft);        if (bytesLeft > bufLength)	{	SCSI_MSG ("sbicInfoXfer: invalid count (len = 0x%0x, left = 0x%0x)\n",		bufLength, bytesLeft, 0, 0, 0, 0);	return (ERROR);	}    if (usingDMA && (bytesLeft > 0))	(*pSbic->sysScsiDmaAbort) (pSbic->sysScsiDmaArg);    SCSI_DEBUG_MSG ("sbicInfoXfer: transferred %d of %d byte(s)\n",		    bufLength - bytesLeft, bufLength, 0, 0, 0, 0);        return (bufLength - bytesLeft);    }/********************************************************************************* 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.*/LOCAL void sbicSelTimeOutCvt    (    SBIC      *pSbic,		    	/* ptr to SBIC 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 = pSbic->defSelTimeOut;    tempSelTimeOut = (timeOutInUsec / (80 * pSbic->clkPeriod)) + 1;     if (tempSelTimeOut > 0xff)	tempSelTimeOut = 0xff;    *pTimeOutSetting = tempSelTimeOut;    }/******************************************************************************** sbicXferParamsCvt - convert transfer period from SCSI to SBIC units** Given a "suggested" REQ/ACK offset and transfer period (in SCSI units of* 4 ns), return the nearest offset and transfer period the SBIC is capable of* using.  Also return the corresponding value of the SBIC's Synchronous* Transfer register.** An offset of zero specifies asynchronous transfer, in which case the period* is irrelevant.  Otherwise, the offset may be clipped to be within the* maximum limit the SBIC is capable of.** The transfer period is normally rounded towards longer periods if the SBIC* is not capable of using the exact specified value.  The period may also be* clipped to be within the SBIC's maximum and minimum limits according to its* clock period.** If either the offset or period need to be clipped, the value FALSE is* retuned as this may reflect an error condition.** Currently assumes that the SBIC is a 33C93, not a 33C93A (i.e. fixed clock* divider of 2) - see 33C93A data sheet pp 9, 13 and 14 for further details.** RETURNS: TRUE if input period is within SBIC's range, else FALSE*/LOCAL BOOL sbicXferParamsCvt    (    FAST SBIC  *pSbic,			/* ptr to SBIC info                  */    FAST UINT8 *pOffset,		/* REQ/ACK offset                    */    FAST UINT8 *pPeriod,		/* xfer period, SCSI units (x 4 ns)  */    FAST UINT8 *pXferParams		/* corresponding Sync Xfer Reg value */    )    {    UINT8 offset  = *pOffset;    UINT8 period  = *pPeriod;    BOOL  inRange = TRUE;    UINT8 xferParams;        if (offset == SCSI_SYNC_XFER_ASYNC_OFFSET)	xferParams = SBIC_SYNC_XFER_PARAMS_ASYNC;    else	{	UINT clkCycles;		/*	 *  Round (and perhaps clip) transfer period to suit SBIC	 *	 *  Note: split into two stages to avoid associativity problems,	 *  	and careful to round up rather than truncate result.	 */	clkCycles  = (period * 4) + (pSbic->clkPeriod - 1);	clkCycles /= pSbic->clkPeriod;		if (clkCycles < SBIC_MIN_XFER_PERIOD)	    {	    clkCycles = SBIC_MIN_XFER_PERIOD;	    inRange   = FALSE;	    }		else if (clkCycles > SBIC_MAX_XFER_PERIOD)  /* very unlikely ! */	    {	    clkCycles = SBIC_MAX_XFER_PERIOD;	    inRange   = FALSE;	    }		period = (clkCycles * pSbic->clkPeriod) / 4;	/*	 *  Clip offset (if necessary) to suit SBIC	 */    	if (offset > SBIC_MAX_REQ_ACK_OFFSET)	    {	    offset  = SBIC_MAX_REQ_ACK_OFFSET;	    inRange = FALSE;	    }	/*	 *  Merge offset and cycles to form Sync. Transfer Reg. contents	 */	if (clkCycles == SBIC_MAX_XFER_PERIOD)	    clkCycles = 0;		xferParams = (clkCycles << SBIC_SYNC_XFER_PERIOD_SHIFT) | offset;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -