📄 ncr810lib.c
字号:
/* ncr810Lib.c - NCR 53C8xx PCI SCSI I/O Processor (SIOP) library (SCSI-2) *//* Copyright 1989-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02a,26apr02,pmr SPR 76029: using intLock/intUnlock instead of ncr810IntDisable/Restore.01z,29oct01,pmr modified ncr810XferParamsCvt() to update the period parameter with the correct value (SPR 71337).01y,24oct01,dat merge from ae 1.1, lint removal using diab01x,20sep01,rcs Added ncr810IntDisable() and ncr810IntRestore() and used them to replace intLock() / intUnlock() pairs in ncr810Abort(), ncr810Activate(), ncr810Resume(), and ncr810EventTypeGet(). Also, added CACHE_PIPE_FLUSH() calls where nedded. SPR# 29734 01w,21nov00,jkf Fixed SPR#35801/35403, no NULL pointers if WIDE selected.01v,03dec98,ihw Modified handling of ident message for new thread: add normal message out (if any) - e.g. sync/wide xfer. Removed incorrect code in ncr810Activate() (used to fudge controller state if reselection race occurred). (SPR 24089) Added several CACHE_PIPE_FLUSH calls at strategic points.01u,06oct98,dat Fixed illegal device accesses, SPR 22597. Provided by luke.01t,24aug98,sut fixed SPR 2126001s,18aug98,tpr added PowerPC EC 603 support.01r,23apr98,tm, SPR 8384, 9025: Augmented ncr810RemainderGet() to support dds 825/875. inOrderExecute() changed to CACHE_PIPE_FLUSH01q,14oct97,dds SPR 9543, modified "ncr810Intr" to return immediately if a spurious interrupt is detected.01p,28jul97,dds SPR#9015: replaced logMsg with SCSI_INT_DEBUG_MSG.01o,10jul97,mas removed dependency on BSP-specific byte I/O routines.01n,09jul97,mas macros for all I/O; first delay count increased (SPR 8842).01m,09jul97,dgp doc: correct fonts per SPR 785301l,08may97,dat temp fix for SPR 8540, VIRT_TO_PHYS problem01k,10mar97,dds SPR 7766: added changes for ncr875 SCSI adapter.01j,06mar97,dds SPR 7996/8091: added a delay to configure scsi devices when used with a fast processor.01i,20nov96,myz added CACHE_DMA_VIRT_TO_PHYS for those missing01h,29oct96,dgp doc: editing for newly published SCSI libraries01g,19aug96,dds modified to generate man pages.01f,29jul96,jds added inOrderExecute() to resolve erratic behaviour when instruction cache is turned on.01e,25jul96,dds SPR 6818: documentation correction.01d,01may96,jds more doc tweaks01c,22apr96,jds doc tweaks.01b,22apr96,jds made to work with multiple NCR 8XX controllers. 01a,28jun95,jds Created. Adapted from ncr710Lib.c*//*DESCRIPTIONThis is the I/O driver for the NCR 53C8xx PCI SCSI I/O Processors (SIOP),supporting the NCR 53C810 and the NCR 53C825 SCSI controllers.It is designed to work with scsiLib and scsi2Lib. This driver runs in conjunction with a script program for the NCR 53C8xx controllers.These scripts use DMA transfers for all data, messages, and status.This driver supports cache functions through cacheLib.USER-CALLABLE ROUTINESMost of the routines in this driver are accessible only through the I/Osystem. Three routines, however, must be called directly. ncr810CtrlCreate()creates a controller structure and ncr810CtrlInit() initializes it.The NCR 53C8xx hardware registers need to be configured according tothe hardware implementation. If the default configuration is not correct,the routine ncr810SetHwRegister() must be used to properly configurethe registers.PCI MEMORY ADDRESSINGThe global variable ncr810PciMemOffset was created to provide the BSPwith a means of changing the VIRT_TO_PHYS mapping without changing thefunctions in the cacheFuncs structures. In generating physical addressesfor DMA on the PCI bus, local addresses are passed through the functionCACHE_DMA_VIRT_TO_PHYS and then the value of ncr810PciMemOffset is added.For backward compatibility, the initial value of ncr810PciMemOffset comesfrom the macro PCI_TO_MEM_OFFSET defined in ncr810.h.I/O MACROSAll device access for input and output is done via macros which can becustomized for each BSP. These routines are NCR810_IN_BYTE, NCR810_OUT_BYTE,NCR810_IN_16, NCR810_OUT_16, NCR810_IN_32 and NCR810_OUT_32.By default, these are defined as generic memory references.INTERNALThis driver supports multiple initiators, disconnect/reconnect, taggedcommand queueing and synchronous data transfer protocol. In general, theSCSI system and this driver will automatically choose the best combinationof these features to suit the target devices used. However, the defaultchoices may be over-ridden by using the function "scsiTargetOptionsSet()"(see scsiLib).There are debug variables to trace events in the driver.<scsiDebug> scsiLib debug variable, trace event in scsiLib, ncr810ScsiPhase(),and ncr810Transact().<scsiIntsDebug> prints interrupt informations.INCLUDE FILESncr810.h, ncr810Script.h and scsiLib.hSEE ALSO: scsiLib, scsi2Lib, cacheLib, .I "SYM53C825 PCI-SCSI I/O Processor Data Manual,".I "SYM53C810 PCI-SCSI I/O Processor Data Manual," .I "NCR 53C8XX Family PCI-SCSI I/O Processors Programming Guide,".pG "I/O System"*/#define INCLUDE_SCSI2#include "vxWorks.h"#include "memLib.h"#include "ctype.h"#include "stdlib.h"#include "string.h"#include "stdio.h"#include "logLib.h"#include "semLib.h"#include "intLib.h"#include "errnoLib.h"#include "cacheLib.h"#include "taskLib.h"#include "drv/scsi/ncr810.h"#include "drv/scsi/ncr810Script.h"/* defines */#define SIOP_MAX_XFER_LENGTH ((UINT) (0x00ffffff)) /* max data xfer length *//* I/O macros */#if ((CPU==PPC603) || (CPU == PPCEC603) || (CPU==PPC604))# undef CACHE_PIPE_FLUSHextern void vxEieio (void);# define CACHE_PIPE_FLUSH() vxEieio()#endif#ifndef NCR810_IN_BYTE# define NCR810_IN_BYTE(adr) (*(volatile UINT8 *)(adr))#endif#ifndef NCR810_OUT_BYTE# define NCR810_OUT_BYTE(adr,val) (*(volatile UINT8 *)(adr)) = ((UINT8)(val))#endif#ifndef NCR810_IN_16# define NCR810_IN_16(adr) (NCR810_SWAP_16(*(volatile UINT16 *)(adr)))#endif#ifndef NCR810_OUT_16# define NCR810_OUT_16(adr,val) (*(volatile UINT16 *)(adr)) = NCR810_SWAP_16((UINT)(val))#endif#ifndef NCR810_IN_32# define NCR810_IN_32(adr) (NCR810_SWAP_32(*(UINT *)(adr)))#endif#ifndef NCR810_OUT_32# define NCR810_OUT_32(adr,val) (*(volatile UINT *)(adr)) = NCR810_SWAP_32((UINT)(val))#endif#define NCR810_VIRT_TO_PHYS(x) \ ((UINT)CACHE_DMA_VIRT_TO_PHYS(x) + (UINT)ncr810PciMemOffset)/* Data stream swapping macros */#if (_BYTE_ORDER == _BIG_ENDIAN)# define NCR810_SWAP_32(x) LONGSWAP((UINT)x)# define NCR810_SWAP_16(x) ((LSB(x) << 8) | MSB(x))#else# define NCR810_SWAP_32(x) (x)# define NCR810_SWAP_16(x) (x)#endif /* typedefs */typedef NCR_810_SCSI_CTRL SIOP;/* External */IMPORT BOOL scsiDebug;IMPORT BOOL scsiErrors;IMPORT BOOL scsiIntsDebug;/* Global variables */int delayCount=0;int ncr810DelayCount = 10;int ncr810PciMemOffset = (int)PCI_TO_MEM_OFFSET;/* * Configurable options */int ncr810SingleStepSemOptions = SEM_Q_PRIORITY;char* ncr810ScsiTaskName = SCSI_DEF_TASK_NAME;int ncr810ScsiTaskOptions = SCSI_DEF_TASK_OPTIONS;int ncr810ScsiTaskPriority = SCSI_DEF_TASK_PRIORITY;int ncr810ScsiTaskStackSize = SCSI_DEF_TASK_STACK_SIZE;/* forward declarations */LOCAL void ncr810HwInit (SIOP *pSiop);LOCAL int ncr810BusIdGet (SIOP *pSiop, UINT busIdBits);LOCAL UINT ncr810RemainderGet (SIOP *pSiop, UINT phase);LOCAL int ncr810EventTypeGet (SIOP *pSiop);LOCAL STATUS ncr810PhaseMismatch (NCR810_THREAD * pThread, int phase, UINT remCount);LOCAL STATUS ncr810ScsiBusControl (SIOP *pSiop, int operation);LOCAL void ncr810ScsiBusReset (SIOP *pSiop);LOCAL STATUS ncr810ThreadActivate (SIOP *pSiop, NCR810_THREAD *pThread);LOCAL BOOL ncr810ThreadAbort (SIOP *pSiop, NCR810_THREAD *pThread);LOCAL void ncr810Event (SIOP *pSiop, NCR810_EVENT *pEvent);LOCAL void ncr810ThreadEvent (NCR810_THREAD *pThread, NCR810_EVENT *pEvent);LOCAL void ncr810InitEvent (NCR810_THREAD *pThread, NCR810_EVENT *pEvent);LOCAL void ncr810InitIdentEvent(NCR810_THREAD *pThread, NCR810_EVENT *pEvent);LOCAL void ncr810TargIdentEvent(NCR810_THREAD *pThread, NCR810_EVENT *pEvent);LOCAL void ncr810IdentInContinue (NCR810_THREAD *pThread);LOCAL void ncr810ThreadReconnect (NCR810_THREAD *pThread);LOCAL void ncr810SharedMemInit (SIOP *pSiop, NCR810_SHARED *pShMem);LOCAL STATUS ncr810ThreadInit (SIOP *pSiop, NCR810_THREAD *pThread);LOCAL STATUS ncr810IdentThreadInit (NCR810_THREAD *pThread);LOCAL void ncr810ThreadUpdate (NCR810_THREAD *pThread);LOCAL void ncr810ThreadComplete (NCR810_THREAD *pThread);LOCAL void ncr810ThreadDefer (NCR810_THREAD *pThread);LOCAL void ncr810ThreadFail (NCR810_THREAD *pThread, int errNum);LOCAL void ncr810ThreadStateSet (NCR810_THREAD *pThread, SCSI_THREAD_STATE state);LOCAL STATUS ncr810Activate (SIOP *pSiop, NCR810_THREAD *pThread);LOCAL STATUS ncr810Resume (SIOP *pSiop, NCR810_THREAD *pThread, NCR810_SCRIPT_ENTRY entryId);LOCAL void ncr810Abort (SIOP *pSiop);LOCAL void ncr810ScriptStart (SIOP *pSiop, NCR810_THREAD *pThread, NCR810_SCRIPT_ENTRY entryId);LOCAL STATUS ncr810ThreadParamsSet (NCR810_THREAD * pThread, UINT8 offset, UINT8 period);LOCAL STATUS ncr810XferParamsQuery (SCSI_CTRL *pScsiCtrl, UINT8 *pOffset, UINT8 *pPeriod);LOCAL STATUS ncr810WideXferParamsQuery (SCSI_CTRL *pScsiCtrl, UINT8 *xferWidth);LOCAL STATUS ncr810XferParamsSet (SCSI_CTRL *pScsiCtrl, UINT8 offset, UINT8 period);LOCAL STATUS ncr810WideXferParamsSet (SCSI_CTRL *pScsiCtrl, UINT8 wideXfer);LOCAL BOOL ncr810XferParamsCvt (SIOP *pSiop, UINT8 *pOffset, UINT8 *pPeriod, UINT8 *pXferParams, UINT8 *pClockDiv);LOCAL void ncr810Delay (void);LOCAL void ncr810ResetAtn (SCSI_CTRL *pScsiCtrl);/********************************************************************************* ncr810CtrlCreate - create a control structure for the NCR 53C8xx SIOP** This routine creates an SIOP data structure and must be called before* using an SIOP chip. It must be called exactly once for a * specified SIOP controller. Since it allocates memory for a structure needed * by all routines in ncr810Lib, it must be called before any other * routines in the library. After calling this routine, ncr810CtrlInit() * must be called at least once before any SCSI transactions are * initiated using the SIOP.** A detailed description of the input parameters follows:* .iP <baseAdrs>* the address at which the CPU accesses the lowest (SCNTL0/SIEN)* register of the SIOP.* .iP <clkPeriod>* the period of the SIOP SCSI clock input, in nanoseconds, multiplied* by 100. This is used to determine the clock period for the* SCSI core of the chip and affects the timing of both asynchronous* and synchronous transfers.* Several commonly-used values are defined in ncr810.h as follows:*.CS* NCR810_1667MHZ 6000 /@ 16.67Mhz chip @/* NCR810_20MHZ 5000 /@ 20Mhz chip @/* NCR810_25MHZ 4000 /@ 25Mhz chip @/* NCR810_3750MHZ 2667 /@ 37.50Mhz chip @/* NCR810_40MHZ 2500 /@ 40Mhz chip @/* NCR810_50MHZ 2000 /@ 50Mhz chip @/* NCR810_66MHZ 1515 /@ 66Mhz chip @/* NCR810_6666MHZ 1500 /@ 66.66Mhz chip @/*.CE* .iP <devType>* the specific NCR 8xx device type. Current device types* are defined in the header file ncr810.h.** RETURNS: A pointer to the NCR_810_SCSI_CTRL structure, or NULL if memory * is unavailable or there are invalid parameters.*/NCR_810_SCSI_CTRL *ncr810CtrlCreate ( UINT8 *baseAdrs, /* base address of the SIOP */ UINT clkPeriod, /* clock controller period (nsec*100) */ UINT16 devType /* NCR8XX SCSI device type */ ) { FAST SIOP *pSiop; /* ptr to SIOP info */ int nBytes; /* total amount of cache-coherent memory */ SCSI_CTRL *pScsiCtrl; BOOL wideXfer; static NCR810_HW_REGS ncr810HwRegs = DEFAULT_810_HW_REGS; /* verify parameters */ if (baseAdrs == ((UINT8 *) NULL)) return ((SIOP *) NULL); if ((clkPeriod > NCR810_1667MHZ) || (clkPeriod < NCR810_6666MHZ)) return ((SIOP *) NULL); /* check that dma buffers are cache-coherent */ if (!CACHE_DMA_IS_WRITE_COHERENT () || !CACHE_DMA_IS_READ_COHERENT ()) { SCSI_MSG ("ncr810CtrlCreate: shared memory not cache coherent.\n", 0, 0, 0, 0, 0, 0); return ((SIOP *) NULL); } /* check to see if it is a supported NCR8XX device type */ switch (devType) { case NCR810_DEVICE_ID : wideXfer = FALSE; break; case NCR825_DEVICE_ID : wideXfer = TRUE; break; case NCR875_DEVICE_ID : wideXfer = TRUE; break; default: logMsg ("Invalid NCR8XX device type. Not supported.\n", 0, 0, 0, 0, 0, 0); return ((SIOP *) NULL); } /* cacheDmaMalloc the controller info structure and two shared data areas */ nBytes = sizeof (SIOP) + 2 * sizeof (NCR810_SHARED); if ((pSiop = (SIOP *) cacheDmaMalloc (nBytes)) == (SIOP *) NULL) return ((SIOP *) NULL); bzero ((char *) pSiop, nBytes); pSiop->pIdentShMem = (NCR810_SHARED *) (pSiop + 1); pSiop->pClientShMem = pSiop->pIdentShMem + 1; /* set up configuration variables */ pScsiCtrl = (SCSI_CTRL *) pSiop; pScsiCtrl->eventSize = sizeof (NCR810_EVENT); pScsiCtrl->threadSize = sizeof (NCR810_THREAD); /* fill in virtual functions used by SCSI library */ pScsiCtrl->maxBytesPerXfer = SIOP_MAX_XFER_LENGTH; pScsiCtrl->scsiTransact = (FUNCPTR) scsiTransact; pScsiCtrl->scsiEventProc = (VOIDFUNCPTR) ncr810Event; pScsiCtrl->scsiThreadInit = (FUNCPTR) ncr810ThreadInit; pScsiCtrl->scsiThreadActivate = (FUNCPTR) ncr810ThreadActivate; pScsiCtrl->scsiThreadAbort = (FUNCPTR) ncr810ThreadAbort; pScsiCtrl->scsiBusControl = (FUNCPTR) ncr810ScsiBusControl; pScsiCtrl->scsiXferParamsQuery = (FUNCPTR) ncr810XferParamsQuery; pScsiCtrl->scsiXferParamsSet = (FUNCPTR) ncr810XferParamsSet; pScsiCtrl->scsiWideXferParamsQuery = (FUNCPTR) ncr810WideXferParamsQuery; pScsiCtrl->scsiWideXferParamsSet = (FUNCPTR) ncr810WideXferParamsSet; /* the following virtual functions are not used with the NCR 53C810 */ pScsiCtrl->scsiDevSelect = NULL; pScsiCtrl->scsiInfoXfer = NULL; /* * The default scsiLib behaviour is to turn wide transfers off. However * for the NCR825, the default behaviour should be to turn wide transfers * on. It is still possible to turn off / on wide transfers for individual * physical devices via the scsiTargetOptionsSet() routine defined * by scsiLib. */ pScsiCtrl->wideXfer = wideXfer; /* fill in generic SCSI info for this controller */ scsiCtrlInit (&pSiop->scsiCtrl); /* fill in SIOP specific data for this controller */ pSiop->pScntl0 = baseAdrs + OFF_SCNTL0; pSiop->pScntl1 = baseAdrs + OFF_SCNTL1; pSiop->pScntl2 = baseAdrs + OFF_SCNTL2; pSiop->pScntl3 = baseAdrs + OFF_SCNTL3; pSiop->pScid = baseAdrs + OFF_SCID; pSiop->pSxfer = baseAdrs + OFF_SXFER; pSiop->pSdid = baseAdrs + OFF_SDID; pSiop->pGpreg = baseAdrs + OFF_GPREG; pSiop->pSfbr = baseAdrs + OFF_SFBR; pSiop->pSocl = baseAdrs + OFF_SOCL; pSiop->pSsid = baseAdrs + OFF_SSID; pSiop->pSbcl = baseAdrs + OFF_SBCL; pSiop->pDstat = baseAdrs + OFF_DSTAT; pSiop->pSstat0 = baseAdrs + OFF_SSTAT0; pSiop->pSstat1 = baseAdrs + OFF_SSTAT1; pSiop->pSstat2 = baseAdrs + OFF_SSTAT2; pSiop->pDsa = (UINT *) (baseAdrs + OFF_DSA); pSiop->pIstat = baseAdrs + OFF_ISTAT; pSiop->pCtest0 = baseAdrs + OFF_CTEST0; pSiop->pCtest1 = baseAdrs + OFF_CTEST1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -