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

📄 sym895lib.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        /*         * For events where the bus is not connected to a target,         * set connected=FALSE.         * For events where the Thread is disconnected / completed         * set isThreadRunning = FALSE else set it to TRUE         * For events not requiring scsi manager, set notify = FALSE.         */        /* The following are the events generated by the Scripts */		        case SYM895_CMD_COMPLETE       :        case SYM895_DISCONNECTED       :		             connected = FALSE;             break;        case SYM895_MESSAGE_OUT_SENT   :        case SYM895_MESSAGE_IN_RECVD   :        case SYM895_EXT_MESSAGE_SIZE   :        case SYM895_NO_MSG_OUT         :        case SYM895_SCRIPT_ABORTED     :             connected = TRUE;             break;        case SYM895_PHASE_MISMATCH     :             event.remCount = sym895RemainderGet (pSiop, pThread->busPhase);               connected = TRUE;             break;		        /*          * Folowing result from asynchronous conditions. Not directly from          * SCRIPTS          */        case SYM895_READY             :             connected = FALSE;             notify = FALSE;             break;		        case SYM895_SELECTED          :        case SYM895_RESELECTED        :		             pScsiEvent->busId = (pThread->targetId) & SYM895_SSID_ENC_MASK;             pScsiEvent->nBytesIdent =                         (pThread->nHostFlags & SYM895_FLAGS_IDENTIFY) ? 1 : 0;	             connected = TRUE;             break;        case SYM895_SCSI_BUS_RESET     :		             connected = FALSE;             break;        case SYM895_BUSMODE_CHANGED    :             /* Don't run the scripts until, Bus Mode is set properly */             connected = TRUE;             /*               * Wait for 100 ms before deciding that SCSI bus mode has              * really changed.It would have been ideal had it been implemented              * in Hardware.The GEN timer in STIME1 is used for 100ms.              */			             /* First, reset the timer */             stime1 = SYM895_REG8_READ (pSiop, SYM895_OFF_STIME1);             stime1 &= ~SYM895_STIME1_GEN_MASK;             SYM895_REG8_WRITE (pSiop,SYM895_OFF_STIME1, stime1);             /* Now, set the timer for 100 MS */             stime1 |= SYM895_GEN_128MS;             SYM895_REG8_WRITE (pSiop,SYM895_OFF_STIME1, stime1);             /* Now wait for the Timer interrupt */             /*               * If another Bus mode change interrupt occurs before               * the timer expires, re-initialize the timer .                            */			             notify = FALSE;             break;        case SYM895_GEN_TIMER_EXPIRED  :             /* Change the Bus mode. */			             tempBusMode = (SYM895_REG8_READ (pSiop, SYM895_OFF_STEST4) &                             SYM895_STEST4_SMODE_MASK)>>SYM895_BUSMODE_SHIFT;			             if (tempBusMode == SYM895_BUSMODE_HVD)                 SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2,                                    SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2) |                                    SYM895_STEST2_DIF);             else if( curBusMode == SYM895_BUSMODE_HVD)                 SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2,                                    SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2) &                                     ~SYM895_STEST2_DIF);		             curBusMode = tempBusMode;		             /* Please refer to page 2-16, 2-17 of data manual */             SYM895_REG8_WRITE( pSiop, SYM895_OFF_STEST0,                                SYM895_REG8_READ (pSiop, SYM895_OFF_STEST0) |                                (tempBusMode << SYM895_BUSMODE_SHIFT));             /* Now the Bus Mode is set properly.*/             /* reset the timer */             stime1 = SYM895_REG8_READ (pSiop, SYM895_OFF_STIME1);             stime1 &= ~SYM895_STIME1_GEN_MASK;             SYM895_REG8_WRITE (pSiop,SYM895_OFF_STIME1, stime1);             /*               * If curBusMode is Single-ended check for the register bits               * for Quadrupler, Ultra Enable . As these features are valid               * for LVD and HVD, these should be disabled for Single-Ended               * devices. Also, lower down the asynchronous              * transfer rate.              */             if (curBusMode == SYM895_BUSMODE_SE)                 {                 if ((SYM895_REG8_READ (pSiop, SYM895_OFF_STEST1) &                                         SYM895_STEST1_QEN))                      {                     /* Disable Clock Quadrupler */                     SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1,                                         SYM895_REG8_READ (pSiop,                                                           SYM895_OFF_STEST1) &                                        (~(SYM895_STEST1_QEN |                                         SYM895_STEST1_QSEL)));                     }				                 		                 /*                   * Ultra SCSI transfer rates are not possible with                  * single-ended devices. So lower the async. clock                  * conversion factor by hard coding to 40Mhz.                  */                 pSiop->clkPeriod = SYM895_40MHZ;                 pSiop->clkDiv = SYM895_3750MHZ_ASYNC_DIV;                 SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL3,                                    SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) |                                    pSiop->clkDiv);						                 } /* SYM895_BUSMODE_SE */		             /* If the current bus mode is HVD, Bit5 in STEST2 should be set */	             else if (curBusMode == SYM895_BUSMODE_HVD)                 {                 SYM895_REG8_WRITE (pSiop,SYM895_OFF_STEST2,                                    SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2)|                                    SYM895_STEST2_DIF);                 } 		            /* run the scripts now */            connected = FALSE;            notify = FALSE;            break;								        /* Following are error conditions, both asynchronous and synchronous */		        case SYM895_SCSI_TIMEOUT        :        case SYM895_HANDSHAKE_TIMEOUT   :             connected = FALSE;             break;        case SYM895_ILLEGAL_PHASE       :	             connected = TRUE;             break;        case SYM895_UNEXPECTED_DISCON   :	             connected = FALSE;             break;        case SYM895_NO_IDENTIFY         :             SCSI_MSG ("sym895Intr: No Valid Identify message at (re)select. \n",                       0, 0, 0, 0, 0, 0);             connected = TRUE;		             break;        case SYM895_SPURIOUS_CMD        :             SCSI_MSG(" sym895Intr: Spurious Command Interrupt. \n",                      0, 0, 0, 0, 0, 0);             connected = FALSE;		             break;			        case SYM895_FATAL_ERROR         :             SCSI_MSG (" sym895Intr: Fatal Error, Restarting SIOP... \n",                       0, 0, 0, 0, 0, 0);             sym895HwInit (pSiop);             connected = FALSE;		             break;				default	    :             SCSI_MSG ("sym895Intr: Un known interrupt (%d) \n",                       pScsiEvent->type, 0 ,0 ,0 ,0 ,0);             connected = FALSE;             break;	}    /*     *  Controller is now idle if possible, make it run a script.     *     *	If a SCSI thread is suspended and must be processed at task-level,     *	leave the device idle.  It will be re-started by the SCSI manager     *	calling "sym895Resume()".     *     *	Otherwise, if there's a new SCSI thread to start (i.e., the SCSI     *	manager has called "sym895Activate()"), start the appropriate script.     *     *	Otherwise, start a script which puts the device into passive mode     *	waiting for re-selection, selection or a host command.     *     *	In all cases, clear any request to start a new thread.  The only     *	tricky case is when there was a request pending and the device is     *	left IDLE.  This should only ever occur when the current event is     *	selection or reselection, in which case the SCSI manager will retry     *	the activation request.  (Also see "sym895Activate ()".)     */    if (connected)        {    	pSiop->state = SYM895_STATE_IDLE;        }    else if (pSiop->isCmdPending)        {        sym895ScriptStart (pSiop, pSiop->pNewThread,                           SYM895_SCRIPT_INIT_START);        pSiop->state = SYM895_STATE_ACTIVE;        }    else        {        sym895ScriptStart (pSiop, (SYM895_THREAD *) pScsiCtrl->pIdentThread,                           SYM895_SCRIPT_WAIT);	        pSiop->state = SYM895_STATE_PASSIVE;        }    pSiop->isCmdPending = FALSE;    SYM895_SCSI_DEBUG_MSG ("sym895Intr state %d -> %d\n",               oldState, pSiop->state, 0, 0, 0, 0);    /* Send the event to the SCSI manager to be processed. */    if (notify)    	scsiMgrEventNotify ((SCSI_CTRL *) pSiop, pScsiEvent, sizeof (event));    }/********************************************************************************* sym895RemainderGet - get the number of bytes remaining in "Data Path" because of* phase mismatch.** The Information transfer phase which halted because of the mismatch has been* saved as a part of the SIOP's register context.* * 895 has few registers helping us out in calculating how many bytes are * left not transferred because of some error condition.* The Registers are.. DFIFO, DBC, SSAT0, SSAT1, SIDx, SODx.** DFIFO register contains the number of bytes transferred between DMA core and* the SCSI Bus. The DBC register contains the number of bytes transferred * across the HostBus. The difference between these two will give the number of * bytes in the DMA Fifo....But hold on..There are more issues involved.* Please refer to chapter 2 of the 895 data manual.** RETURNS: number of bytes remained in the data path.** Note : This function is called at interrupt level.** NOMANUAL*/LOCAL UINT sym895RemainderGet     (    SIOP * pSiop,            /* pointer to controller information */    UINT   phase             /* phase, terminated by mismatch */    )    {    UINT      remCount;    UINT16    tmpCount;    UINT16    countFifo;    UINT16    fifoMask;    /* Read the Number of bytes transferred across the host bus */    remCount = SYM895_REG32_READ (pSiop,SYM895_OFF_DBC) & SYM895_COUNT_MASK;	    /*      * check if the dma fifo is 816 bytes or 112 bytes.      * accordingly the mask being applied will change      */     if (SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST5) & SYM895_CTEST5_BL2)        fifoMask = SYM895_FIFO_816_MASK;    else        fifoMask = SYM895_FIFO_112_MASK;    tmpCount  = (remCount & fifoMask);    countFifo = SYM895_REG8_READ (pSiop,SYM895_OFF_DFIFO);			    if (fifoMask == SYM895_FIFO_816_MASK)	/* Fifo size is 816 bytes */        {        /* Extract b0,b1 from CTEST5 and concatenate with countfifo.*/        countFifo |= ((UINT16)(SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST5) &                                0x03) << 8);        }	    countFifo &= fifoMask;	    /* Now DMA FIFO byte offset counter is in "countFifo" */    tmpCount = (countFifo - remCount) & fifoMask;    /* byte count is in "tmpCount" now */		    /*      * Now it depends on the direction of transfer. To know the direction     * of transfer, check the phase.     */	    switch (phase)        {        case PHASE_DATA_OUT     :        case PHASE_MSG_OUT      :        case PHASE_COMMAND      :            /* Output phases : Check for data in output registers (SODx) */			            /*              * check the SSTAT0 and SSTAT2 registers to check if any bytes             * are left in the SODL/SODR registers.             */            /* Check to see any data is there in SODL register */				            if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT0) & SYM895_SSTAT0_OLF)                tmpCount++;            if (SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2) & SYM895_SSTAT2_OLF1)                tmpCount++;            /*              * Check to see any data is there in SODR register              * Note that SODR reg. is bypassed for asynchronous transfers             */            /* if synchronous Send */

⌨️ 快捷键说明

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