📄 sym895lib.c
字号:
/* * Note : SCSI ATN Interrupt is used (in target mode) to signal the * assetion of the ATN signal. In initiator mode, it is the phase mismatch * interrupt. In target mode, this interrupt is not handled. This is * enabled only in Initiator mode. */ SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN0, (SYM895_B_SGE | SYM895_B_UDC | SYM895_B_RST | SYM895_B_PAR)); SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN1, (SYM895_B_STO | SYM895_B_HTH | SYM895_B_SBMC | SYM895_B_GEN)); SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN, (SYM895_B_BF | SYM895_B_ABT | SYM895_B_SIR | SYM895_B_IID)); /* Clear DMA FIFO */ SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3, SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) | SYM895_CTEST3_CLF); /* * Copy scripts to the on chip script RAM. * Each 895 instruction is 2 longs wide */ if ((pSiop->isScriptsCopy == TRUE) && (pSiop->siopRamBaseAddress != NULL)) { nLongs = SYM895_INSTRUCTIONS * 2; /* Check whether scripts exceed the size of SCRIPT RAM (4K for 895) */ if (SYM895_SCRIPT_RAM_SIZE < nLongs * sizeof (ULONG)) { SCSI_MSG (" sym895HwInit: Total Scripts length exceeded \n", 0, 0, 0, 0, 0, 0); return (ERROR); } dst = (ULONG *)pSiop->siopRamBaseAddress; src = (char *)sym895Wait; /* Now Copy the scripts and validate the copying after checking */ bcopyLongs ((char *)sym895Wait, (char *)pSiop->siopRamBaseAddress, nLongs); status = bcmp ((char *) sym895Wait, (char *)pSiop->siopRamBaseAddress, nLongs*4); if (status != 0) { SCSI_MSG (" Copy to Scripts Ram Failed \n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* Fill in the script Entries */ sym895ScriptEntry [SYM895_SCRIPT_WAIT] = (ULONG *) ((UINT) dst); sym895ScriptEntry [SYM895_SCRIPT_INIT_START] = (ULONG *) ((UINT)sym895InitStart - (UINT)sym895Wait + (UINT)dst); sym895ScriptEntry [SYM895_SCRIPT_INIT_CONTINUE] = (ULONG *) ((UINT)sym895InitContinue - (UINT)sym895Wait + (UINT)dst); sym895ScriptEntry [SYM895_SCRIPT_TGT_DISCONNECT] = (ULONG *) ((UINT)sym895TgtDisconnect - (UINT)sym895Wait + (UINT)dst); sym895ScriptEntry [SYM895_SCRIPT_DIAG] = (ULONG *) ((UINT)sym895Diag - (UINT)sym895Wait + (UINT)dst); } else { sym895ScriptEntry [SYM895_SCRIPT_WAIT] = (ULONG *) (sym895Wait); sym895ScriptEntry [SYM895_SCRIPT_INIT_START] = (ULONG *)((UINT)sym895InitStart); sym895ScriptEntry [SYM895_SCRIPT_INIT_CONTINUE] = (ULONG *) ((UINT) sym895InitContinue); sym895ScriptEntry [SYM895_SCRIPT_TGT_DISCONNECT] = (ULONG *) ((UINT) sym895TgtDisconnect); sym895ScriptEntry [SYM895_SCRIPT_DIAG] = (ULONG *) ((UINT) sym895Diag); } /* HwInit Successful */ return (OK); }/********************************************************************************* sym895SetHwOptions - sets the Sym895 chip Options.* * This function sets optional bits required for tweaking the performance* of 895 to the Ultra2 SCSI. The routine should be called with SYM895_HW_OPTIONS* structure as defined in sym895.h file. ** The input parameters are** .IP <pSiop> * pointer to the SIOP structure* .IP <pHwOptions>* pointer to the a SYM895_HW_OPTIONS structure.* * .CS* struct sym895HWOptions* {* int SCLK : 1; /@ STEST1:b7,if false, uses PCI Clock for SCSI @/* int SCE : 1; /@ STEST2:b7, enable assertion of SCSI thro SOCL@/* /@ and SODL registers @/* int DIF : 1; /@ STEST2:b5, enable differential SCSI @/* int AWS : 1; /@ STEST2:b2, Always Wide SCSI @/* int EWS : 1; /@ SCNTL3:b3, Enable Wide SCSI @/* int EXT : 1; /@ STEST2:b1, Extend SREQ/SACK filtering @/* int TE : 1; /@ STEST3:b7, TolerANT Enable @/* int BL : 3; /@ DMODE:b7,b6, CTEST5:b2 : Burst length @/ * /@ when set to any of 32/64/128 burst length @/* /@ transfers, requires the DMA Fifo size to be @/* /@ 816 bytes (ctest5:b5 = 1). @/ * int SIOM : 1; /@ DMODE:b5, Source I/O Memory Enable @/* int DIOM : 1; /@ DMODE:b4, Destination I/O Memory Enable @/* int EXC : 1; /@ SCNTL1:b7, Slow Cable Mode @/* int ULTRA : 1; /@ SCNTL3:b7, Ultra Enable @/* int DFS : 1; /@ CTEST5:b5, DMA Fifo size 112/816 bytes @/* } SYM895_HW_OPTIONS;* .CE** This routine should not be called when there is SCSI Bus Activity as * this modifies the SIOP Registers.** RETURNS: OK or ERROR if any of the input parameters is not valid.** ERRORS: N/A** SEE ALSO: sym895.h, sym895CtrlCreate()**/STATUS sym895SetHwOptions ( FAST SIOP * pSiop, /* pointer to the SIOP structure */ SYM895_HW_OPTIONS * pHwOptions /* pointer to the Options Structure */ ) { /* temporary store to hold current register values */ UINT8 dmode; UINT8 stest2; UINT8 scntl3; UINT8 ctest5; UINT8 stest1; UINT8 stest3; UINT8 scntl1; /* validate input parameters */ if ((pSiop == (SIOP *)NULL) || (pHwOptions == (SYM895_HW_OPTIONS *)NULL)) return (ERROR); /* Fill in the SIOP structure with new HwOptions */ memcpy ((char *)&(pSiop->hwOptions), (char *)pHwOptions, sizeof(SYM895_HW_OPTIONS)); /* store the current values */ dmode = SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE); stest1 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST1); stest2 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2); stest3 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST3); scntl1 = SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL1); scntl3 = SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3); ctest5 = SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST5); /* Manipulate according to the options set */ (pHwOptions->DIOM)? (dmode |= SYM895_DMODE_DIOM):(dmode &= ~SYM895_DMODE_DIOM); (pHwOptions->SIOM)? (dmode |= SYM895_DMODE_SIOM):(dmode &= ~SYM895_DMODE_SIOM); (pHwOptions->SCLK)? (stest1 |= SYM895_STEST1_SCLK):(stest1 &= ~SYM895_STEST1_SCLK); (pHwOptions->DIF)? (stest2 |= SYM895_STEST2_DIF):(stest2 &= ~SYM895_STEST2_DIF); (pHwOptions->SCE)? (stest2 |= SYM895_STEST2_SCE):(stest2 &= ~SYM895_STEST2_SCE); (pHwOptions->AWS)? (stest2 |= SYM895_STEST2_AWS):(stest2 &= ~SYM895_STEST2_AWS); (pHwOptions->EXTEND)? (stest2 |= SYM895_STEST2_EXT):(stest2 &= ~SYM895_STEST2_EXT); (pHwOptions->TE)? (stest3 |= SYM895_STEST3_TE):(stest3 &= ~SYM895_STEST3_TE); (pHwOptions->EXC)? (scntl1 |= SYM895_SCNTL1_EXC):(scntl1 &= ~SYM895_SCNTL1_EXC); (pHwOptions->ULTRA)? (scntl3 |= SYM895_SCNTL3_ULTRA):(scntl3 &= ~SYM895_SCNTL3_ULTRA); (pHwOptions->EWS)? (scntl3 |= SYM895_SCNTL3_EWS):(scntl3 &= ~SYM895_SCNTL3_EWS); (pHwOptions->DFS)? (ctest5 |= SYM895_CTEST5_DFS):(ctest5 &= ~SYM895_CTEST5_DFS); /* * The Burst lengths 32,64 and 128 transfers are valid only if FIFO * size is set to 816 bytes. Avoid setting CTEST5:BL2 when DMA FIFO * is set to 112 byes (CTEST5:DFS == 0). */ if (!(pHwOptions->DFS)) { if ((pHwOptions->BL) & 0x04) { SCSI_MSG("sym895SetHwOptions: Erroneous Burstlength size for \ 112 byte FIFO \n", 0, 0, 0, 0, 0, 0); } /* Forcing the burst length to a lesser value */ ctest5 &= ~SYM895_CTEST5_BL2; } else { ((pHwOptions->BL) & 0x4)? (ctest5 |= SYM895_CTEST5_BL2):(ctest5 &= ~SYM895_CTEST5_BL2); } ((pHwOptions->BL) & 0x1)? (dmode |= SYM895_DMODE_BL0):(dmode &= ~SYM895_DMODE_BL0); ((pHwOptions->BL) & 0x2)? (dmode |= SYM895_DMODE_BL1):(dmode &= ~SYM895_DMODE_BL1); /* Now Update the Registers with user Options */ SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE, dmode); SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, stest1); SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2, stest2); SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST3, stest3); SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL1, scntl1); SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL3, scntl3); SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST5, ctest5); /* * Note that the SCLK bit needs to be reset if Quadrapler is to be * enabled. */ if ((pHwOptions->QEN) && !(stest1 & SYM895_STEST1_SCLK)) { stest1 |= SYM895_STEST1_QEN; SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, stest1); /* Poll STEST4:LOCK to ensure that the chip is locked to 160MHz.*/ while (!(SYM895_REG8_READ (pSiop, SYM895_OFF_STEST4) & SYM895_STEST4_LOCK)) ; /* Halt the SCSI Clock */ stest3 |= SYM895_STEST3_HSC; SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST3, stest3); /* * Set the CCF and SCF bits. Now since the SCF is dependent on the * target, a default value is set which can be changed later by * sym895ThreadActivate() */ SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL3, SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) | pSiop->clkDiv); /* Set the SCLK Quadrapler select bit */ stest1 |= SYM895_STEST1_QSEL; SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST1, stest1); /* Clear the halt on SCSI Clock */ stest3 &= ~SYM895_STEST3_HSC; SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST3, stest3); } return (OK); }/********************************************************************************* sym895Intr - interrupt service routine for the SCSI Controller.** The first thing to determine is whether the device is generating an interrupt* If not, then this routine must exit as quickly as possible.** Find the event type corresponding to this interrupt, and carry out any* actions which must be done before the SCSI Controller is re-started. * Determine whether or not the SCSI Controller is connected to the bus * (depending on the event type - see note below). If not, start a client * script if possible or else just make the SCSI Controller wait for something * else to happen.** The "connected" variable, at the end of switch statement, reflects the status* of the currently executing thread. If it is TRUE it means that the thread is* suspended and must be processed at the task level. Set the state of * SIOP to IDLE and leave the control to the SCSI Manager. The SCSI Manager, * in turn invokes the driver through a "resume" call.** Notify the SCSI manager of a controller event.** RETURNS N/A*/void sym895Intr ( SIOP * pSiop /* pointer to the SIOP structure */ ) { SYM895_EVENT event; SCSI_EVENT * pScsiEvent = (SCSI_EVENT *)&event.scsiEvent; SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *)pSiop; SYM895_THREAD * pThread = (SYM895_THREAD *)pSiop->pCurThread; BOOL connected = FALSE; BOOL notify = TRUE; SYM895_STATE oldState = (int)(pSiop->state); static UINT32 curBusMode = SYM895_BUSMODE_LVD; UINT8 tempBusMode; UINT8 stime1; CACHE_PIPE_FLUSH(); /* Save (partial) Controller register context in current thread */ pThread->nHostFlags = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA0); pThread->msgOutStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA1); pThread->msgInStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA2); pThread->targetId = SYM895_REG8_READ (pSiop, SYM895_OFF_SSID); pThread->busPhase = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHA3); pThread->sxfer = SYM895_REG8_READ (pSiop, SYM895_OFF_SXFER); pThread->scntl3 = SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3);#ifdef SCATTER_GATHER /* support for scatter gather memory */ pThread->isScatTransfer = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHC0); pThread->totalScatElements = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHC1); pThread->noRemaining = SYM895_REG8_READ (pSiop, SYM895_OFF_SCRATCHC2); #endif if ((pScsiEvent->type = sym895EventTypeGet (pSiop)) == ERROR) return; SYM895_SCSI_DEBUG_MSG ("sym895Intr: DSA=0x%08x, DSP=0x%08x, type = %d. \n", SYM895_REG32_READ(pSiop, SYM895_OFF_DSA), SYM895_REG32_READ(pSiop, SYM895_OFF_DSP), pScsiEvent->type,0,0,0); /* Synchronise with single-step routine, if enabled. */ if (pSiop->isSingleStep) semGive (pSiop->singleStepSem); if (pScsiEvent->type == SYM895_SINGLE_STEP) return; /* Process the events */ switch (pScsiEvent->type) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -