📄 aic7880lib.c
字号:
/* aic7880Lib.c - Adaptec 7880 SCSI Host Adapter Library File *//* Copyright 1984-2001 Wind River Systems, Inc. *//*modification history--------------------01i,09nov01,pai added memPartLib header file for Veloce KMEM_ALLOC definition.01h,12oct01,dat merge from ae 1.101g,21nov00,jkf SPR#62266 T3 doc update01f,20jul00,jkf use KMEM_ALLOC, added a AIC_7880_VIRT_TO_PHYS macro, stop logging shared INTs as spurious,log valid INT only. SPR#31810, 32101,32102.01e,08feb99,fle doc : removed some .IPs that were wrong here01d,19aug98,fle doc : removed the routine word from the aic7880ReadConfig title line01c,14oct97,dds changed aic7880dFif0ThresholdSet to aic7880dFifoThresholdSet.01b,11jul97,dds added aic7880.h header file.01a,10jul97,dds written.*//*DESCRIPTION:This is the I/O driver for the Adaptec AIC 7880 PCI Bus Master Single Chip SCSI Host Adapter. It is designed to work with scsi2Lib. This driver runs in conjunction with the HIM (Hardware Interface Module) supplied by Adaptec. The AIC 7880 SCSI Host Adapter driver supports the following features.iPFast, Double Speed 20 MHz data transfers..iP16 bit Wide Synchronous Data transfers..iPTagged Command Queueing..iPData FIFO threshold selection..iPDisconnect / Reconnect support..iPMultiple Initiator support..iPMultiple Controller support..lEIn general, the SCSI system and this driver will automatically choose the best combination of these features to suit the target devices used. However, the default choices may be over-ridden by using the function "scsiTargetOptionsSet()" (see scsiLib).To use this driver, enable the INCLUDE_AIC7880_SCSI component. (VxAE)OPERATIONS OVERVIEWThe host processor initiates a SCSI I/O operation by programming a datastructure called SCB (SCSI Command Block). The SCB contains all therelevant information needed by the Host Adapter to carry out the requestedSCSI operation. SCSI SCB's are passed to the HIM by this module which arethen sent to the AIC-7880 for execution. The AIC-7880 Sequencer or PhaseEnginecomprises the on-chip intelligence that allows the AIC-7880 to execute SCBcommands. The Sequencer is programmable and uses its own microcode program which is downloaded to AIC-7880 by the host at initialization.The following is an example of how an SCB is delivered to the AIC-7880.iPMemory is allocated for the SCB structure and it is programmed with the necessary information required to execute a SCSI transaction..iPThe SCB is then sent to HIM..iPThe HIM pauses the Sequencer..iPThe Sequencer has internal registers that point to the area in system memory where the SCB resides..iPThe HIM unpauses the Sequencer..iPThe AIC-7880 Sequencer uses DMA to transfer the SCB into its internal memory..iPThe AIC-7880 executes the SCB..iPUpon completion of the SCB command, the AIC-7880 Sequencer posts the pointer of the completed SCB into system memory..iPThe AIC-7880 generates an interupt..iPThe status of the completed SCB is then read by the host.SCB PROCESSINGThe AIC-7880 Sequencer uses DMA to transfer the SCB into its internal memory.The Sequencer processes SCB's in the order they are received with new SCB's being started when older SCB operations are idle due to wait for selection or a SCSI bus disconnect. When operations for an Idle SCB reactivate, the sequencer scans the SCB array for the SCB corresponding to the Target/LUN reactivating. The Sequencer then restarts the SCB found until the next disconnect or SCB completion..SS "MAXIMUM NUMBER OF TAGGED SCB's"The number of tagged SCB's per SCSI target that is handled by the Sequencer,range from 1-32. The HIM supports only the External SCB Access mode. Thedefault number of tags handled by the Sequencer in this mode is 32. Changingthe field "Cf_MaxTagScbs" in the cfp_struct changes the maximum number of tagged SCB's..SS "MAXIMUM NUMBER OF SCB's"The number of SCB's that can be queued to the Sequencer, range from 1-254.This value can be changed before calling the HIM routine "PH_GetConfig ()".Changing the field "Cf_NumberScbs" in "cfp_struct" changes the maximum numberof SCB's to be used. The default max number of SCB's is 254. SYNCHRONOUS TRANSFER SUPPORTIf double speed SCSI mode is enabled, this driver supports transfer periodsof 50, 64 and 76 ns. In standard fast SCSI mode transfer periods of 100, 125,150, 175, 200, 225, 250 and 275 are supported. Synchronous transfer parametersfor a target can be set using the SCSI library function "scsiTargetOptionsSet".DOUBLE SPEED SCSI MODETo enable/disable double speed SCSI mode the routine "aic7880EnableFast20" needs to be invoked with the followingtwo parameters:.IP "(1)" 4A pointer to the appropriate SCSI Controller structure .IP "(2)"A BOOLEAN value which enables or disable double speed SCSI mode..LPWith double speed SCSI mode enabled the host adapter may be capable of transferring data at theoritcal transfer rates of 20 MB/s for an 8-bit device and 40 MB/s for a 16-bit device. Double Speed SCSI is disabledby default.DATA FIFO THRESHOLDTo set the data FIFO threshold the routine "aic7880dFifoThresholdSet"needs to be invoked with the following two parameters:.IP "(1)" 4A pointer to the appropriate SCSI Controller structure.IP "(2)"The data FIFO threhold value..LPFor more information about the data FIFO threshold value refer the aic7880dFifoThresholdSet() routineIn order to initialize the driver from the BSP the following needs tobe done in the BSP specific routine sysScsiInit() in file sysScsi.c..iPFind the SCSI Host Adapter..iPCreate the SCSI Controller Structure..iPConnect the interrupt to Interupt Service Routine (ISR)..iPEnable the SCSI interupt.LPThe following example shows the SCSI initialization sequence that needto be done in the BSP..CSSTATUS sysScsiInit () { int busNo; /@ PCI bus number @/ int devNo; /@ PCI device number @/ UWORD found = FALSE; /@ host adapter found @/ int numHa = 0; /@ number of host adapters @/ for (busNo=0; busNo < MAX_NO_OF_PCI_BUSES && !found; busNo++) for (devNo = 0; devNo < MAX_NO_OF_PCI_DEVICES; devNo++) { if ((found = sysScsiHostAdapterFind (busNo, devNo)) == HA_FOUND) { numHa++; /@ Create the SCSI controller @/ if ((pSysScsiCtrl = (SCSI_CTRL *) aic7880CtrlCreate (busNo, devNo, SCSI_DEF_CTRL_BUS_ID)) == NULL) { logMsg ("Could not create SCSI controller\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /@ connect the SCSI controller's interrupt service routine @/ if ((pciIntConnect (INUM_TO_IVEC (SCSI_INT_VEC), aic7880Intr, (int) pSysScsiCtrl)) == ERROR) return (ERROR); /@ enable SCSI interupts @/ sysIntEnablePIC (SCSI_INT_LVL); } return (OK); }.CESEE ALSO: scsiLib, scsi2Lib, cacheLib,.I "AIC-7880 Design In Handbook,".I "AIC-7880 Data Book,".I "Adaptec Hardware Interface Module (HIM) Specification,".pG "I/O System"*/#include "vxWorks.h"#include "memLib.h"#include "memPartLib.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/him/him_scb.h"#include "drv/scsi/aic7880.h"#include "drv/scsi/him/him_equ.h"#include "drv/scsi/him/seq_off.h"#include "drv/scsi/him/sequence.h"#include "drv/scsi/him/him_rel.h"#include "him/him_init.c"#include "him/him.c"#include "him/himd.c"#include "him/himdinit.c"#include "him/himdiopt.c"#include "him/himdopt.c"#define SIOP_MAX_XFER_LENGTH ((UINT) (0x00ffffff))#define AIC_7880_VIRT_TO_PHYS(x) \ ((UINT)CACHE_DMA_VIRT_TO_PHYS(x))typedef AIC_7880_SCSI_CTRL SIOP;int himDebug = 0;/* globals */AIC_7880_SCSI_CTRL * sysScsiCtrl;char * aic7880ScsiTaskName = SCSI_DEF_TASK_NAME;int aic7880ScsiTaskOptions = SCSI_DEF_TASK_OPTIONS;int aic7880ScsiTaskPriority = SCSI_DEF_TASK_PRIORITY;int aic7880ScsiTaskStackSize = SCSI_DEF_TASK_STACK_SIZE;IMPORT void PH_ScbSend (sp_struct *);IMPORT VOIDFUNCPTR intEOI; /* pointer to function sysIntEOI() *//* function declarations */VOID aic7880EnableFast20 (SCSI_CTRL * pScsiCtrl, BOOL enable);VOID aic7880ScbCompleted (sp_struct * pScb);STATUS aic7880dFifoThresholdSet (SCSI_CTRL * pScsiCtrl, UBYTE threshHold);DWORD aic7880ReadConfig (cfp_struct * configPtr, UBYTE busNo, UBYTE devNo, UBYTE regNo);DWORD aic7880WriteConfig (cfp_struct * configPtr, UBYTE busNo, UBYTE devNo, UBYTE regNo, DWORD regVal);DWORD aic7880GetNumOfBuses ();LOCAL STATUS aic7880ThreadInit (SIOP * pSiop, AIC_7880_THREAD * pThread);LOCAL BOOL aic7880ThreadAbort (SIOP * pSiop, AIC_7880_THREAD * pThread);LOCAL STATUS aic7880ThreadActivate (SIOP *pSiop, AIC_7880_THREAD * pThread);LOCAL VOID aic7880ThreadUpdate (SIOP *pSiop, AIC_7880_THREAD * pThread);LOCAL VOID aic7880Activate (AIC_7880_THREAD * pThread);LOCAL VOID aic7880ThreadComplete (AIC_7880_THREAD * pThread);LOCAL VOID aic7880ThreadFail (AIC_7880_THREAD * pThread, int errNum);LOCAL VOID aic7880Event (SIOP * pSiop, SCSI_EVENT * pScsiEvent);LOCAL VOID aic7880InitEvent (AIC_7880_THREAD * pThread, SCSI_EVENT * pScsiEvent);LOCAL VOID aic7880ThreadEvent (AIC_7880_THREAD * pThread, SCSI_EVENT * pScsiEvent);LOCAL VOID aic7880ThreadStateSet (AIC_7880_THREAD * pThread, SCSI_THREAD_STATE state);LOCAL VOID aic7880DummyHandler ();LOCAL STATUS aic7880ScsiBusControl (SIOP * pSiop, int operation);LOCAL VOID aic7880XferParamsCvt (SIOP * pSiop, UINT8 * pOffset, UINT8 * pPeriod, UINT8 * pXferRate);LOCAL STATUS aic7880XferParamsSet (SCSI_CTRL * pScsiCtrl, UINT8 offset, UINT8 period);LOCAL STATUS aic7880ThreadParamsSet (AIC_7880_THREAD * pThread, UINT8 offset, UINT8 period);LOCAL STATUS aic7880WideXferParamsSet (SCSI_CTRL * pScsiCtrl, UINT8 xferWidth);LOCAL STATUS aic7880XferParamsQuery (SCSI_CTRL * pScsiCtrl, UINT8 * pOffset, UINT8 *pPeriod);/********************************************************************************* aic7880CtrlCreate - create a control structure for the AIC 7880** This routine creates an AIC_7880_SCSI_CTRL structure and must be called * before using the SCSI Host Adapter chip. It must be called exactly once for * a specified Host Adapter. ** RETURNS: A pointer to the AIC_7880_SCSI_CTRL structure, or NULL if memory* is unavailable or there are invalid parameters.*/AIC_7880_SCSI_CTRL * aic7880CtrlCreate ( int busNo, /* PCI bus Number */ int devNo, /* PCI device Number */ int scsiBusId /* SCSI Host Adapter Bus Id */ ) { cfp_struct * pCfpStruct; /* ptr to HA confiuration struct */ AIC_7880_SCSI_CTRL * aic7880Ctrl; /* ptr to aic7880 Controller struct */ SCSI_CTRL * pScsiCtrl; /* ptr to generic SCSI Controller */ int nBytes; /* number of bytes */ int status; /* status information */ int i; /* create the generic SCSI controller structure */ if ((aic7880Ctrl = (AIC_7880_SCSI_CTRL *) \ KMEM_ALLOC((sizeof (AIC_7880_SCSI_CTRL)))) == NULL) { SCSI_DEBUG_MSG ("Could not allocate memory for SCSI controlle\n", 0, 0, 0, 0, 0, 0); return (NULL); } /* create the host adapter configuration structure */ if ((pCfpStruct = (cfp_struct *)KMEM_ALLOC(sizeof (cfp_struct))) == NULL) { SCSI_DEBUG_MSG ("Could not allocate HIM configuration structure\n", 0, 0, 0, 0, 0, 0); return (NULL); } nBytes = sizeof (cfp_struct); bzero ((char *) pCfpStruct, nBytes); /* * the bus number and the device number are required by the * HIM before the call to "PH_GetConfig". */ pCfpStruct->Cf_BusNumber = busNo; pCfpStruct->Cf_DeviceNumber = devNo; /* * Get host adapter configuration information for cfp struct. * Upon return the pCfpStruct contains the AIC-7880 host adapter * configuration information. (e.g. base address, Id, rev level etc.) */ PH_GetConfig (pCfpStruct); aic7880Ctrl->aic7880CfpStruct = pCfpStruct; sysScsiCtrl = aic7880Ctrl; /* allocate memory for the host adapter data structure */ nBytes = pCfpStruct->Cf_HimDataSize; if ((pCfpStruct->CFP_HaDataPtr = (hsp_struct *) KMEM_ALLOC(nBytes * sizeof (char))) == NULL) SCSI_DEBUG_MSG ("Could not allocate memory HIM data structure\n", 0, 0, 0, 0, 0, 0); /* * virtual and physical pointers to the host adapter data structure * are the same. */ pCfpStruct->Cf_HaDataPhy = \ AIC_7880_VIRT_TO_PHYS (pCfpStruct->CFP_HaDataPtr); /* * Initialize the SCSI Host adapter, by reseting the SCSI bus and * suppressing wide/sync data transfer negotiations initially. */ pCfpStruct->CFP_InitNeeded = TRUE; pCfpStruct->CFP_ResetBus = TRUE; pCfpStruct->CFP_SuppressNego = TRUE; pCfpStruct->Cf_ScsiId = scsiBusId; /* * "PH_InitHA" initializes the SCSI Host Adapter, pauses the sequencer * and downloads the sequencer code to sequencer RAM which resides on * the AIC-7880. The sequencer code is then un-paused and the AIC-7880 * Host Adapter interupt is enabled. */ if ((status = PH_InitHA (pCfpStruct)) == 0) SCSI_DEBUG_MSG ("Host Adapter Initialization Successful\n", 0, 0, 0, 0, 0, 0); /* initialize the negotiation options for each target */ for (i = 0; i < pCfpStruct->Cf_MaxTargets; i++) pCfpStruct->Cf_ScsiOption [i] = 0; pScsiCtrl = (SCSI_CTRL *) aic7880Ctrl; /* validate and set bus ID */ pScsiCtrl->scsiCtrlBusId = pCfpStruct->Cf_ScsiId; pScsiCtrl->eventSize = sizeof (SCSI_EVENT); pScsiCtrl->threadSize = sizeof (AIC_7880_THREAD); pScsiCtrl->maxBytesPerXfer = SIOP_MAX_XFER_LENGTH; /* fill in virtual functions used by SCSI library */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -