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

📄 templatescsi1.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* templateScsi1.c - template SCSI-1 driver *//* Copyright 1989-1997 Wind River Systems, Inc. *//*modification history--------------------TODO -	Remove the template modification history and begin a new history	starting with version 01a and growing the history upward with	each revision.01d,24sep97,dat  changed args to TEMPLATE_READ macro01c,20aug97,dat  code review comments from Dinesh01b,11aug97,dat  fixed compilation bugs01a,07apr97,dat  written from ncr5390Lib1.c, ver 01j*//*DESCRIPTIONTODO - Describe the entire chip completely.  If this device is a part ofa larger ASIC, describe the complete device in a single paragraph.TODO - Describe the device completely.  Describe all operating modes andcapabilties, whether used or not.TODO - Describe the modes and limitations of this driver.  Describe howthis driver interacts with the chip and any limitations imposed by thesoftware.  If this driver interacts with other drivers, describe thatinteraction.USER-CALLABLE ROUTINESThe primary user routines for this driver library are templateCtrlCreate()and templateCtrlInit().TemplateCtrlCreate() is used to create a device driver structure that willrepresent and control the physical controller device.  TemplateCtrlInit() is used to setup the device resetting the chip and theSCSI bus.  See the synopsis for arguments.DRIVER CUSTOMIZATIONTODO - Describe all macros and constants that the user can change thatwill effect the behaviour of this driver.This template driver presumes that the device is memory mapped, and that the<regOffset> argument to templateCtrlCreate() indicates the interval betweenregisters, usually 1, 2 or 4 bytes.  If the base address for the device is0x1000 and the regOffset is 4, then the CPU address of register number 3is (0x1000 + (4 * 3)) = 0x100C.The macro TEMPLATE_REG_READ(pDev, reg,result) is used to read abyte from a specified register.  The three arguments are the device structurepointer, the register id (element of the dev structure), and the variable (not a pointer) to receive the register contents.(If the third argument were a pointer, then it would affect compileroptimization and could lead to inefficient code generation).The macro TEMPLATE_REG_WRITE(pDev, reg,data) is used to write data to thespecified register address.  These macros presume memory mapped i/o bydefault.  Both macros can be redefined to tailor the driver to some otheri/o model.The macro SCSI_DEBUG_MSG(format,...) can be used to insert debuggingmessages anywhere in the code.  The debug messages will appear only whenthe global variable scsiDebug is set to a non-zero value.INCLUDE FILEStemplateScsi1.hSEE ALSO: scsiLib,.pG "I/O System"*/#include "vxWorks.h"#include "memLib.h"#include "errnoLib.h"#include "logLib.h"#include "scsiLib.h"#include "stdlib.h"#include "stdio.h"#include "taskLib.h"#include "sysLib.h"/* defines */#define TEMPLATE_MAX_XFER_LENGTH ((UINT) (0xffff)) /* max data xfer length */#define TEMPLATE_MAX_BUS_ID	(0x7)/* Dummy command codes */#define TEMPLATE_ATN_SELECT	(0x1)#define TEMPLATE_STOP_SELECT	(0x2)#define TEMPLATE_SELECT		(0x3)#ifndef TEMPLATE_REG_READ#   define TEMPLATE_REG_READ(pDev, reg,result) \	((result) = *pDev->reg)#endif  /*TEMPLATE_REG_READ*/#ifndef TEMPLATE_REG_WRITE#   define TEMPLATE_REG_WRITE(pDev, reg, data) \	(*pDev->reg = data)#endif  /*TEMPLATE_REG_WRITE*/typedef struct { /* TEMPLATE_DEV */    SCSI_CTRL scsiCtrl;         /* generic SCSI controller info */    SEM_ID pMutexData;          /* use to protect global siop data */    SCSI_PHYS_DEV *pDevToSelect;/* device to select at intr. level or NULL */    } TEMPLATE_DEV;/* globals */IMPORT BOOL	scsiDebug;IMPORT BOOL	scsiIntsDebug;/* forward declarations */      STATUS	templateCtrlInit (TEMPLATE_DEV *, int , UINT, int);      void	templateIntr (TEMPLATE_DEV *);LOCAL void	templateCommand (TEMPLATE_DEV *, int);LOCAL STATUS	templateDevSelect (SCSI_PHYS_DEV *, SCSI_TRANSACTION *);LOCAL STATUS	templateMsgInAck (SCSI_CTRL *, BOOL);LOCAL STATUS	templateBytesOut (SCSI_PHYS_DEV *, char *, int, int);LOCAL STATUS	templateBytesIn (SCSI_PHYS_DEV *, char *, int, int);LOCAL STATUS	templateBusPhaseGet (SCSI_CTRL *, int, int *);LOCAL void	templateSelTimeOutCvt (SCSI_CTRL *, UINT , UINT *);LOCAL STATUS	templateBusIdGet (TEMPLATE_DEV *, int *);LOCAL void	templateScsiBusReset (TEMPLATE_DEV *);LOCAL void	templateHwInit (TEMPLATE_DEV *);/* * TODO - remove or replace these macros, they are just pseudo code to allow * this template driver to compile without warnings. */#define DEVICE_IS_DISCONNECTED	0#define NOT_EXPECTED_STATE	0#define DEVICE_IS_NOT_INTERRUPTING 0#define DMA_TERMINAL_COUNT_REACHED 0#define DEVICE_FUNC_COMPLETE 0/********************************************************************************* templateCtrlCreate - create a TEMPLATE_DEV device** This routine creates a data structure that must exist before the* TEMPLATE_DEV chip can be used.  This routine must be called exactly once* for a specified TEMPLATE_DEV, and must be the first routine called, since* it calloc's a structure needed by all other routines in the library.** TODO - The input arguments are device specific.  The argument list must* be updated.** The device specific input parameters are as follows:* .iP <baseAdrs> 4* the address at which the CPU would access the lowest * register of the TEMPLATE_DEV.* .iP <regOffset>* the address offset (bytes) to access consecutive registers.* (This must be a power of 2, for example, 1, 2, 4, etc.)* .iP <clkPeriod>* the period, in nanoseconds, of the signal to the TEMPLATE_DEV clock input (used only* for select command timeouts).* .iP "<templateDmaBytesIn> and <templateDmaBytesOut>"* board-specific parameters to handle DMA input and output.* If these are NULL (0), TEMPLATE_DEV program mode is used.* DMA is used only during SCSI data in/out phases.* The interface to these DMA routines must be of the form:* .CS* STATUS templateDmaBytes{In, Out}*     (*     TEMPLATE_DEV*  pScsiPhysDev,  /@ ptr to phys dev info    @/*     UINT8*         pBuffer,       /@ ptr to the data buffer  @/*     int            bufLength      /@ number of bytes to xfer @/*     )* .CE* .LP** After creating a device, the user will usually then initialize the* device by calling templateCtrlInit().** RETURNS: A pointer to an TEMPLATE_DEV structure,* or NULL if memory is insufficient or the parameters are invalid.*/TEMPLATE_DEV * templateCtrlCreate    (    /* TODO - this argument list is device specific, change as needed */    UINT8 *baseAdrs,		/* base address of TEMPLATE_DEV */    int regOffset,		/* addr offset between consecutive regs. */    UINT clkPeriod,		/* period of controller clock (nsec) */    FUNCPTR templateDmaBytesIn, /* SCSI DMA input function */    FUNCPTR templateDmaBytesOut /* SCSI DMA output function */    )    {    TEMPLATE_DEV *pDev;		/* ptr to TEMPLATE_DEV info */    /* TODO - verify parameters, return NULL if necessary */    /* calloc the controller info structure; return NULL if unable */    pDev = (TEMPLATE_DEV *) calloc (1, sizeof (TEMPLATE_DEV));    if (pDev == (TEMPLATE_DEV *) NULL)        return ((TEMPLATE_DEV *) NULL);    /* fill in generic SCSI info for this controller */    scsiCtrlInit (&pDev->scsiCtrl);    /* fill in remainder of scsiCtrl structure */    pDev->scsiCtrl.clkPeriod		= clkPeriod;    pDev->scsiCtrl.maxBytesPerXfer	= TEMPLATE_MAX_XFER_LENGTH;    pDev->scsiCtrl.scsiBusReset		= (VOIDFUNCPTR) templateScsiBusReset;    pDev->scsiCtrl.scsiTransact		= (FUNCPTR) scsiTransact;    pDev->scsiCtrl.scsiDevSelect	= (FUNCPTR) templateDevSelect;    pDev->scsiCtrl.scsiBytesIn		= (FUNCPTR) templateBytesIn;    pDev->scsiCtrl.scsiBytesOut		= (FUNCPTR) templateBytesOut;    pDev->scsiCtrl.scsiDmaBytesIn	= (FUNCPTR) templateDmaBytesIn;    pDev->scsiCtrl.scsiDmaBytesOut	= (FUNCPTR) templateDmaBytesOut;    pDev->scsiCtrl.scsiBusPhaseGet	= (FUNCPTR) templateBusPhaseGet;    pDev->scsiCtrl.scsiMsgInAck		= (FUNCPTR) templateMsgInAck;    pDev->scsiCtrl.scsiSelTimeOutCvt	= (VOIDFUNCPTR) templateSelTimeOutCvt;    /* initialize other template_dev fields */    pDev->pDevToSelect = (SCSI_PHYS_DEV *) NULL;    /* TODO - fill in device specific data for this controller */    return (pDev);    }/********************************************************************************* templateCtrlInit - initialize a TEMPLATE_DEV** This routine initializes an TEMPLATE_DEV structure created by * templateCtrlCreate(). It must be called before the TEMPLATE_DEV is used.* This routine can be called more than once; however, it should be called* only while there is no activity on the SCSI interface, since the specified* configuration is written to the TEMPLATE_DEV.** Before returning, this routine pulses RST (reset) on the SCSI bus, thus* resetting all attached devices.** The input parameters are as follows:* .iP <pDev> 4* a pointer to an TEMPLATE_DEV structure created with templateCtrlCreate().* .iP <scsiCtrlBusId>* the SCSI bus ID of the TEMPLATE_DEV, in the range 0 - 7.  The ID is* somewhat arbitrary; the value 7, or highest priority, is conventional.* .iP <defaultSelTimeOut>* the timeout, in microseconds, for selecting a SCSI device attached to this* controller.  This value is used as a default if no timeout is specified in * scsiPhysDevCreate()).  The recommended value zero (0)* specifies SCSI_DEF_SELECT_TIMEOUT (250 millisec).  The maximum timeout* possible is approximately 3 seconds.  Values exceeding this revert to the* maximum.  For more information about chip timeouts, see the device manual.* .iP <scsiPriority>* the priority to which a task is set when performing a SCSI transaction.* Valid priorities are 0 to 255.  Alternatively, the value -1 specifies * that the priority should not be altered during SCSI transactions.** RETURNS: OK, or ERROR if a parameter is out of range.** SEE ALSO: scsiPhysDevCreate(),*/STATUS templateCtrlInit    (    TEMPLATE_DEV* pDev,		/* ptr to TEMPLATE_DEV struct */    int scsiCtrlBusId,		/* SCSI bus ID of this TEMPLATE_DEV */    UINT defaultSelTimeOut,	/* default dev sel timeout (microsec) */    int scsiPriority		/* priority of task doing SCSI I/O */    )    {    /* verify scsiCtrlBusId and enter legal value in TEMPLATE_DEV structure */    if (scsiCtrlBusId < SCSI_MIN_BUS_ID || scsiCtrlBusId > TEMPLATE_MAX_BUS_ID)	return (ERROR);    pDev->scsiCtrl.scsiCtrlBusId = (UINT8) scsiCtrlBusId;    /* verify scsiPriority and enter legal value in TEMPLATE_DEV structure */    if (scsiPriority < NONE || scsiPriority > 0xff)	return (ERROR);    pDev->scsiCtrl.scsiPriority = scsiPriority;    /* TODO - if needed, issue NO-OP (required by some devices) */    /* TODO - if needed, compute and set device clocking information */    /*     * TODO - verify defaultSelTimeOut, convert it from usec to TEMPLATE_DEV     * register values, and enter value in TEMPLATE_DEV structure or registers.     */    /* disconnect is not supported with SCSI-1, for now */    pDev->scsiCtrl.disconnect = (TBOOL) FALSE;    templateHwInit (pDev); 	/* initialize the TEMPLATE_DEV hardware */    return (OK);    }/********************************************************************************* templateDevSelect - attempt to select a SCSI physical device** This routine is called from scsiLib to select a physical device.* The driver selects the device and sends the initial MSG_OUT and CMD* bytes.** RETURNS: OK if device was successfully selected, otherwise ERROR.*/LOCAL STATUS templateDevSelect    (    SCSI_PHYS_DEV *pScsiPhysDev,   /* ptr to SCSI physical device info */    SCSI_TRANSACTION *pScsiXaction /* ptr to SCSI transaction info     */    )    {    TEMPLATE_DEV *pDev;		/* ptr to TEMPLATE_DEV info */    int templateBusId;          /* SCSI bus ID of the TEMPLATE_DEV */    UINT8 identMsg;		/* for construction of the IDENTIFY message */    int ix;			/* loop index */    UINT8 *pCmdByte;		/* ptr to a command byte */    UINT8 templateOpcode;	/* TEMPLATE_DEV opcode byte */    pDev = (TEMPLATE_DEV *) pScsiPhysDev->pScsiCtrl;    /* Return ERROR, if trying to select device's own id */    if ((templateBusIdGet (pDev, &templateBusId) == ERROR) ||        (templateBusId == pScsiPhysDev->scsiDevBusId))	{        return (ERROR);	}    pDev->pDevToSelect  = pScsiPhysDev;    pScsiPhysDev->devStatus = SELECT_REQUESTED;    /* TODO - issue device select command sequence */    if (pScsiPhysDev->useIdentify)		/* send an identify message */	{	identMsg = SCSI_MSG_IDENTIFY |	(pDev->scsiCtrl.disconnect ?	SCSI_MSG_IDENT_DISCONNECT : 0) |	(UINT8) pScsiPhysDev->scsiDevLUN;	/* TODO - send identMsg in MSG_OUT phase */	}    pCmdByte = pScsiXaction->cmdAddress;    for (ix = 0; ix < pScsiXaction->cmdLength; ix++)	{	/* TODO - send other command bytes */	;	}    if (pScsiPhysDev->useIdentify)	{	if (pScsiPhysDev->msgLength == 0)	    templateOpcode = (UINT8) TEMPLATE_ATN_SELECT;	else	    templateOpcode = (UINT8) TEMPLATE_STOP_SELECT;	}    else	templateOpcode = (UINT8) TEMPLATE_SELECT;    /* Send proper SELECT command code */    templateCommand (pDev, templateOpcode);    if (semTake (&pDev->scsiCtrl.ctrlSyncSem,		 ((pScsiXaction->cmdTimeout / SCSI_TIMEOUT_1SEC) + 1) *		 sysClkRateGet())		 == ERROR)	{	/* timeout on semaphore, didn't get an interrupt */	printErr ("templateDevSelect: No interrupt received.\n");errorRecovery:	/* TODO - flush device FIFOs, if needed */	/* reset bus, delay 3 seconds to allow devices to reset */	templateScsiBusReset (pDev);	taskDelay (3 * sysClkRateGet ()); /* 3 seconds */	return (ERROR);	}    if (!(DEVICE_IS_DISCONNECTED))	{	if (NOT_EXPECTED_STATE)	    {	    printErr ("templateDevSelect: Unknown chip state.\n");	    /* TODO - print error statistics */	    goto errorRecovery;	    }	else	    {	    /* TODO - flush FIFOs, if needed */	    return (OK);	    }	}    else	{	/* simple device select timeout */	/* TODO - Flush FIFOs, if needed */	errnoSet (S_scsiLib_SELECT_TIMEOUT);        return (ERROR);	}    }/********************************************************************************* templateMsgInAck - de-assert the ACK line to accept message** This routine should be called when an incoming message has been read and* accepted.  If the incoming message did not imply an impending disconnect,* give the synchronization semaphore, so that subsequent phase can be* detected.** RETURNS: OK.*/LOCAL STATUS templateMsgInAck    (    SCSI_CTRL* pScsiCtrl,	/* ptr to TEMPLATE_DEV info		*/    BOOL expectDisconn		/* whether a disconnect is expected	*/    )    {    /* TODO - Send MSG_ACCEPTED to terminate MSG_IN phase, wait for new phase */    return (OK);

⌨️ 快捷键说明

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