📄 sym895lib.c
字号:
* SYM895_50MHZ 2000 50Mhz chip * SYM895_66MHZ 1515 66Mhz chip * SYM895_6666MHZ 1500 66Mhz chip * SYM895_75MHZ 1333 75Mhz chip * SYM895_80MHZ 1250 80Mhz chip * SYM895_160MHZ 625 40Mhz chip with Quadrupler * .CE** .IP <devType>* SCSI sym8xx device type * .IP <siopRamBaseAdrs>* base address of the internal scripts RAM* .IP <flags>* various device/debug options for the driver. Commonly used values are** .CS* SYM895_ENABLE_PARITY_CHECK 0x01* SYM895_ENABLE_SINGLE_STEP 0x02* SYM895_COPY_SCRIPTS 0x04* .CE** RETURNS: A pointer to SYM895_SCSI_CTRL structure, or NULL if memory * is unavailable or there are invalid parameters.** ERRORS: N/A**/SYM895_SCSI_CTRL * sym895CtrlCreate ( UINT8 * siopBaseAdrs, /* base address of the SCSI Controller */ UINT clkPeriod, /* clock controller period (nsec*100) */ UINT16 devType, /* SCSI device type */ UINT8 * siopRamBaseAdrs, /* on Chip Ram Address */ UINT16 flags /* options */ ) { FAST SIOP * pSiop; /* pointer to SCSI Controller info */ SCSI_CTRL * pScsiCtrl; UINT nBytes; /* Required memory */ static SYM895_HW_OPTIONS sym895Options = SYM895_FAST_SCSI_OPTIONS; /* Verify parameters */ if ((siopBaseAdrs == NULL) || (siopRamBaseAdrs == NULL)) return ((SIOP *)NULL); if ((clkPeriod > SYM895_1667MHZ) || (clkPeriod < SYM895_160MHZ)) return ((SIOP *)NULL); /* Check that the DM Buffers are cache coherent */ if (!CACHE_DMA_IS_WRITE_COHERENT () || !CACHE_DMA_IS_READ_COHERENT ()) { SCSI_MSG ("sym895CtrlCreate : Shared memory not cache coherent. \n", 0, 0, 0, 0, 0, 0); return ((SIOP *)NULL); } switch (devType) { case NCR810_DEVICE_ID : case NCR825_DEVICE_ID : case NCR875_DEVICE_ID : case SYM895_DEVICE_ID : case NCR895A_DEVICE_ID : break; default : SCSI_MSG (" sym895CtrlCreate : Invalid Device type %x\n", devType, 0, 0, 0, 0, 0); return ((SIOP *)NULL); } /* cacheDmaMalloc the controller struct and the two shared data areas */ nBytes = sizeof (SIOP) + 2 * sizeof (SYM895_SHARED); if ((pSiop = (SIOP *) cacheDmaMalloc (nBytes)) == (SIOP *) NULL) return ((SIOP *) NULL); memset ((char *) pSiop, 0, nBytes); pSiop->pIdentShMem = (SYM895_SHARED *) (pSiop + 1); pSiop->pClientShMem = pSiop->pIdentShMem + 1; pScsiCtrl = &(pSiop->scsiCtrl); /* fill in generic SCSI info for this controller */ pScsiCtrl->eventSize = sizeof (SYM895_EVENT); pScsiCtrl->threadSize = sizeof (SYM895_THREAD); pScsiCtrl->maxBytesPerXfer = SYM895_MAX_XFER_LENGTH; pScsiCtrl->scsiTransact = (FUNCPTR) scsiTransact; pScsiCtrl->scsiEventProc = (VOIDFUNCPTR) sym895Event; pScsiCtrl->scsiThreadInit = (FUNCPTR) sym895ThreadInit; pScsiCtrl->scsiThreadActivate = (FUNCPTR) sym895ThreadActivate; pScsiCtrl->scsiThreadAbort = (FUNCPTR) sym895ThreadAbort; pScsiCtrl->scsiBusControl = (FUNCPTR) sym895ScsiBusControl; pScsiCtrl->scsiXferParamsQuery = (FUNCPTR) sym895XferParamsQuery; pScsiCtrl->scsiXferParamsSet = (FUNCPTR) sym895XferParamsSet; pScsiCtrl->scsiWideXferParamsQuery = (FUNCPTR) sym895WideXferParamsQuery; pScsiCtrl->scsiWideXferParamsSet = (FUNCPTR) sym895WideXferParamsSet; pScsiCtrl->wideXfer = TRUE; /* for 895 and above */ scsiCtrlInit (&(pSiop->scsiCtrl)); pSiop->baseAddress = siopBaseAdrs; pSiop->devType = devType; pSiop->clkPeriod = clkPeriod; pSiop->siopRamBaseAddress = siopRamBaseAdrs; memcpy (&(pSiop->hwOptions), &(sym895Options), sizeof (SYM895_HW_OPTIONS)); /* Create synchronisation semaphore for single-step support */ if (flags & SYM895_ENABLE_SINGLE_STEP) { pSiop->singleStepSem = semBCreate (sym895SingleStepSemOptions, SEM_EMPTY); if(pSiop->singleStepSem == NULL) { SCSI_MSG ("sym895CtrlCreate: Error Creating Single step semaphore\n", 0, 0, 0, 0, 0, 0); (void) cacheDmaFree ((char *)pSiop); return (NULL); } } else pSiop->singleStepSem = NULL; pSiop->state = SYM895_STATE_IDLE; pSiop->isCmdPending = FALSE; /* Set the user chosen options */ pSiop->isParityCheck = (flags & SYM895_ENABLE_PARITY_CHECK)? TRUE:FALSE; pSiop->isSingleStep = (flags & SYM895_ENABLE_SINGLE_STEP)? TRUE:FALSE; pSiop->isScriptsCopy = (flags & SYM895_COPY_SCRIPTS)? TRUE:FALSE; /* Initialize fields in client shared data area */ sym895SharedMemInit (pSiop,pSiop->pClientShMem); /* Initialize the Identification Thread */ sym895IdentThreadInit ((SYM895_THREAD *)pScsiCtrl->pIdentThread); /* spawn SCSI manager - use generic code from "scsiLib.c" */ pScsiCtrl->scsiMgrId = taskSpawn (sym895ScsiTaskName, sym895ScsiTaskPriority, sym895ScsiTaskOptions, sym895ScsiTaskStackSize*2, (FUNCPTR) scsiMgr, (int) pSiop, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (pScsiCtrl->scsiMgrId != ERROR) { return (pSiop); } SCSI_MSG ("sym895CtrlCreate: can't spawn SCSI Manager \n", 0, 0, 0, 0, 0, 0); if (pSiop->singleStepSem != NULL) (void) semDelete (pSiop->singleStepSem); (void) cacheDmaFree ((char *)pSiop); return (NULL); }/********************************************************************************* sym895CtrlInit - initialize a SCSI Controller Structure.** This routine initializes an SCSI Controller structure, after the structure* is created with sym895CtrlCreate(). This structure must be initialized* before the SCSI Controller can be used. It may be called more than once* if needed; however, it should only be called while there is no activity on* the SCSI interface.** A Detailed description of parameters follows.** .IP <pSiop>* pointer to the SCSI controller structure created with sym895CtrlCreate()* .IP <scsiCtrlBusId>* SCSI Bus Id of the SIOP. ** RETURNS OK, or ERROR if parameters are out of range.** ERRORS: N/A*/STATUS sym895CtrlInit ( FAST SIOP * pSiop, /* pointer to SCSI Controller structure */ UINT scsiCtrlBusId /* SCSI bus ID of this SCSI Controller */ ) { volatile int delay; SCSI_CTRL * pScsiCtrl = &pSiop->scsiCtrl; /* validate parameters */ if (pSiop == (SIOP *)NULL) return (ERROR); if ((scsiCtrlBusId < SCSI_MIN_BUS_ID) || (scsiCtrlBusId > SCSI_MAX_BUS_ID)) return (ERROR); pScsiCtrl->scsiCtrlBusId = scsiCtrlBusId; /* Initialise and reset the SCSI Controller */ if (sym895HwInit (pSiop) == ERROR) { SCSI_MSG ("Error in sym895HwInit()\n", 0, 0, 0, 0, 0, 0); return (ERROR); } delay = sym895DelayCount; sym895DelayCount *= 35; /* First delay must be longer */ sym895ScriptStart (pSiop, (SYM895_THREAD *)pScsiCtrl->pIdentThread, SYM895_SCRIPT_WAIT); sym895DelayCount = delay; pSiop->state = SYM895_STATE_PASSIVE; return (OK); }/********************************************************************************* sym895HwInit - hardware initialization for the 895 Chip.** This function puts the SIOP in a known quiescent state. Also, if copying of * SCSI scripts is enabled, this routine copies entire SCRIPTS code from host * memory to On-Chip SCRIPTS RAM. This routine does not modify any of the * registers that are set by sym895SetHwOptions(). ** For details of the register bits initialised here, refer to SYM53C895 data * manual Version 3.0.** .IP <pSiop>* pointer to the SIOP structure** RETURNS: OK, or ERROR if parameters are out of range.** ERRORS: N/A*/STATUS sym895HwInit ( FAST SIOP * pSiop /* pointer to the SIOP structure */ ) { /* local variables for the copy of SCRIPTs */ ULONG * dst; /* pointer for SCRIPTS destination */ ULONG nLongs; /* number of longs to copy across SCRIPTS RAM */ int status; /* status of copying SCRIPTS */ char * src; /* pointer for SCRIPTS source */ UINT8 curScid; /* store for current chip's SCSI ID */ /* validate the parameters */ if (pSiop == (SIOP *)NULL) return (ERROR); /* Soft-Reset the SIOP */ SYM895_REG8_WRITE (pSiop,SYM895_OFF_ISTAT, SYM895_ISTAT_SOFTRST); taskDelay (2); SYM895_REG8_WRITE (pSiop,SYM895_OFF_ISTAT,0); /* Initialize the Driver default Options for the Chip */ if (sym895SetHwOptions (pSiop,&pSiop->hwOptions) != OK) { SCSI_MSG ("sym895SetHwOptions failed\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* DMA Manual Mode. Automatic Fetching of scripts disabled */ SYM895_REG8_WRITE (pSiop,SYM895_OFF_DMODE, SYM895_REG8_READ (pSiop,SYM895_OFF_DMODE) | SYM895_DMODE_MAN); /* SYM (NCR)700 compatibility mode turned off */ SYM895_REG8_WRITE (pSiop,SYM895_OFF_DCNTL, SYM895_REG8_READ (pSiop,SYM895_OFF_DCNTL)| SYM895_DCNTL_COM); /* Check clock period and get the clock division factor */ if (pSiop->clkPeriod >= SYM895_25MHZ) /* 16.67 - 25 MHz */ { pSiop->clkDiv = SYM895_16MHZ_ASYNC_DIV; } else if (pSiop->clkPeriod >= SYM895_3750MHZ) /* 25.01 MHz - 37.5MHz */ { pSiop->clkDiv = SYM895_25MHZ_ASYNC_DIV; } else if (pSiop->clkPeriod >= SYM895_50MHZ) /* 37.51 MHz - 50 MHz */ { pSiop->clkDiv = SYM895_3750MHZ_ASYNC_DIV; } else if (pSiop->clkPeriod >= SYM895_75MHZ) /* 50.01MHz - 75 MHz */ { pSiop->clkDiv = SYM895_50MHZ_ASYNC_DIV; } else if (pSiop->clkPeriod >= SYM895_80MHZ) /* 75.01MHz - 80 MHz */ { pSiop->clkDiv = SYM895_75MHZ_ASYNC_DIV; } else /* 75.01 Mhz - 160 Mhz (Quadrapler) */ { pSiop->clkDiv = SYM895_160MHZ_ASYNC_DIV; } SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL3, SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL3) | pSiop->clkDiv); /* * If disconect/reconnect is enabled, use full arbitration. * Always generate parity, check for parity if enabled. */ if ( pSiop->scsiCtrl.disconnect) { SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL0, SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL0)| (SYM895_SCNTL0_ARB1 | SYM895_SCNTL0_ARB0)); } /* Enable Select with ATN signal asserted */ SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL0, SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL0)| (SYM895_SCNTL0_WATN)); /* Enable parity Checking if enabled*/ if ( pSiop->isParityCheck) /* if parity Check enabled */ { SYM895_REG8_WRITE (pSiop,SYM895_OFF_SCNTL0, SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL0) | (SYM895_B_PAR)); } /* Set Bus Id */ curScid = SYM895_REG8_READ (pSiop,SYM895_OFF_SCID) & 0xf0; SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCID, curScid | pSiop->scsiCtrl.scsiCtrlBusId); SYM895_REG16_WRITE (pSiop, SYM895_OFF_RESPID0, 1<<pSiop->scsiCtrl.scsiCtrlBusId); /* Enable Response to Bus Initiated Selection/Reselection */ SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCID, SYM895_REG8_READ (pSiop,SYM895_OFF_SCID)| (SYM895_SCID_RRE | SYM895_SCID_SRE)); /* Enable Interrupts - SCSI and DMA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -