summaryrefslogtreecommitdiffstats
path: root/private/ntos/miniport/scsiwdl/ncrcam/ncrsdms.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/miniport/scsiwdl/ncrcam/ncrsdms.c1640
1 files changed, 1640 insertions, 0 deletions
diff --git a/private/ntos/miniport/scsiwdl/ncrcam/ncrsdms.c b/private/ntos/miniport/scsiwdl/ncrcam/ncrsdms.c
new file mode 100644
index 000000000..c2e2d0ca2
--- /dev/null
+++ b/private/ntos/miniport/scsiwdl/ncrcam/ncrsdms.c
@@ -0,0 +1,1640 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 1992 NCR Corporation
+//
+// NCRSDMS.C
+//
+// This is the Windows NT NCR MiniPort driver for all NCR CAMcores.
+//
+// Revisions:
+//
+//
+// Note: Search for the word "future" for things that may need to
+// be upgraded for SDMS 3.0 or to support other enhanced
+// features.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// NT include files
+
+#include "miniport.h" // MiniPort structure definitions
+#include "scsi.h" // SRB & SCSI structure definitions and others
+
+#ifdef i386
+
+// NCR SDMS include files
+
+#include "typedefs.h" // Defines for uchar,ushort,ulong etc.
+#include "camcore.h" // CAMCore ROM header structure definition
+#include "camglbls.h" // Globals structure definitions
+#include "intercam.h" // ROMCCB structure definitions, additional
+ // fields used in ROM appended to end of
+ // CAM CCB. Also, includes cam.h which
+ // defines CAM CCB structures.
+
+
+#include "ncrsdms.h" // Specific info for the miniport driver.
+
+// Noncached Extension - Guarantees to be below the 16MB 24 bit addressing
+// limitation of AT cards. Need this for CoreGlobals which contain
+// SCRIPT instructions for the C700 family. Must fetch below the
+// 16MB limit for AT cards. Note: Fujitsu EISA board also has this
+// limitation.
+
+typedef struct _NONCACHED_EXTENSION{
+
+ CAMGlobals CoreGlobals; // CAMGlobals structure defined in CAMGLBLS.H
+
+ UCHAR SCSICoreGlobals[4096];
+ // This is to make room for the globals
+ // defined in SCSICORE for each chip.
+ // For example, C700 SCRIPTS and misc.
+ // other globals. Defined in SCSIcore.h
+ // for each chips camcore.
+
+} NONCACHED_EXTENSION, *PNONCACHED_EXTENSION;
+
+// Hardware device extension.
+// This structure is initialized in the FindCore routine.
+
+
+typedef struct _HW_DEVICE_EXTENSION {
+
+ // Pointer to noncached extension
+
+ PNONCACHED_EXTENSION NoncachedExtension;
+
+ // The next set of functions MUST be defined as type "_cdecl".
+ // These functions are in the CAMcore and have been previously
+ // compiled as "_cdecl" type functions, while NT assumes all
+ // functions are "_stdcall". The difference is in which type of
+ // function adjusts the stack - caller adjusts when using _cdecl
+ // while callee adjusts stack when using _stdcall.
+
+ // Pointer to CAMInit in 32-bit CAMcore code.
+ ULONG (__cdecl *initPtr)(PVOID CoreGlobalsPtr);
+
+ // Pointer to CAMStart in 32-bit CAMcore code.
+ ULONG (__cdecl *startPtr)(PVOID CoreGlobalsPtr, PVOID CCBPtr);
+
+ // Pointer to CAMInterrupt in 32-bit CAMcore code.
+ ULONG (__cdecl *interruptPtr)(PVOID CoreGlobalsPtr);
+
+ // Pointer to chsMap routine in stdport 32 bit CAMcore code.
+ VOID (__cdecl *chsPtr)(PVOID CoreGlobalsPtr, PVOID CCBPtr);
+
+ // SDMS Version number.
+ ULONG SdmsVersion;
+
+ // Path id of this device extension.
+ ULONG scsiBusId;
+
+ // Storage area for REX code.
+ UCHAR base32BitCode[MAX_32BIT_SIZE];
+
+} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
+
+// Logical unit extension derived from the SRB
+
+typedef struct _HW_LU_EXTENSION {
+
+ PSCSI_REQUEST_BLOCK CurrentSrb; // Current SRB
+
+} HW_LU_EXTENSION, *PHW_LU_EXTENSION;
+
+ULONG
+DriverEntry(
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ );
+
+ULONG
+NCRFindAdapter(
+ IN PVOID DeviceExtension,
+ IN PVOID HwContext,
+ IN PVOID BusInformation,
+ IN PCHAR ArgumentString,
+ IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ OUT PBOOLEAN Again
+ );
+
+BOOLEAN
+NCRHwInitialize(
+ IN PVOID DeviceExtension
+ );
+
+BOOLEAN
+NCRStartIo(
+ IN PVOID DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ );
+
+BOOLEAN
+NCRInterrupt(
+ IN PVOID DeviceExtension
+ );
+
+BOOLEAN
+NCRResetBus(
+ IN PVOID DeviceExtension,
+ IN ULONG PathId
+ );
+
+ULONG
+FindCore(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ IN OUT PHWInfo hwInfo,
+ OUT PBOOLEAN Again
+ );
+
+VOID
+InitPath(
+ IN PHW_DEVICE_EXTENSION DeviceExtension
+ );
+
+VOID
+BuildCCBFromSRB(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ );
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DriverEntry
+//
+// Installable driver initialization entry point for system.
+// 1) Initialize hwInitializationData structure
+// 2) Call ScsiPortInitialize routine in PortDriver
+//
+// Arguments:
+// Argument1 - supplies a context value with
+// which the HBA miniport driver should call
+// ScsiPortInitialize.
+//
+// Argument2 - supplies a 2nd context value with
+// which the HBA miniport driver should call
+// ScsiPortInitialize.
+//
+// Return Value: status returned by ScsiPortInitialize
+//
+/////////////////////////////////////////////////////////////////////////////
+
+ULONG
+DriverEntry(
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ )
+{
+ HW_INITIALIZATION_DATA hwInitData;
+
+ HWInfo hwInfo;
+
+ ULONG isaStatus;
+ ULONG eisaStatus;
+ ULONG mcaStatus;
+ ULONG internalStatus;
+ ULONG busStatus;
+ ULONG i;
+
+ DebugPrint(( 1, "NCR SDMS: DriverEntry \n"));
+
+ // Zero out structure
+
+ for ( i = 0 ; i < sizeof(HW_INITIALIZATION_DATA); i++ ) {
+ ((PUCHAR)&hwInitData)[i] = 0;
+ }
+
+ // Set size of hwInitData
+
+ hwInitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
+
+ // Initialize entry points to MiniPort routines
+
+ hwInitData.HwInitialize = NCRHwInitialize;
+ hwInitData.HwStartIo = NCRStartIo;
+ hwInitData.HwInterrupt = NCRInterrupt;
+ hwInitData.HwFindAdapter = NCRFindAdapter;
+ hwInitData.HwResetBus = NCRResetBus;
+
+ // Following MiniPort routines not supported.
+ hwInitData.HwDmaStarted = NULL;
+
+ // Size in bytes required to hold per adapter information.
+ hwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
+
+ // Specify size (bytes) of per logical unit storage.
+ hwInitData.SpecificLuExtensionSize = 0;
+
+ // Specify size (bytes) of the per request storage.
+ // Setting extension size to zero causes a crash in FindCore when
+ // ScsiPortGetUncachedExtension is called. Why????
+
+ hwInitData.SrbExtensionSize = sizeof( ROMscsiCCB );
+
+ // Initialize access range from CAMcore ROM header
+ // (I/O and/or memory mapped locations) normally 2 for now.
+ // Future: We have to allow for I/O, Memory-mapped,
+ // or both because we do not know anything about the
+ // adapter at this point.
+ hwInitData.NumberOfAccessRanges = 2;
+
+ hwInitData.MapBuffers = FALSE;
+
+ hwInitData.NeedPhysicalAddresses = TRUE;
+
+ // Initial release does not support tagged queing.
+ hwInitData.TaggedQueuing = FALSE;
+
+ // Auto request sense not enabled. The SRB will still attempt to
+ // enable this function, so auto request sense must also be disabled
+ // at the CCB level.
+ hwInitData.AutoRequestSense = FALSE;
+
+ hwInitData.MultipleRequestPerLu = FALSE;
+
+ hwInitData.ReceiveEvent = FALSE;
+
+ // Reset the HBA count.
+ hwInfo.hbaCount = 0;
+
+ // Track how many adapter addresses have been checked for validity.
+ // This variable also referred to as "HwContext" or "Context" in
+ // the FindAdapter routine.
+
+ // Try to configure for EISA.
+
+ DebugPrint(( 2, "NCR SDMS: DriverEntry *** EISA *** \n" ));
+
+ hwInfo.romAddrSpace = 0;
+ hwInfo.currentVirtAddr = 0;
+ hwInfo.currentRomAddr = FIRST_ROM_ADDRESS;
+ hwInfo.scsiBusId = 0;
+ hwInitData.AdapterInterfaceType = Eisa;
+
+ eisaStatus = ScsiPortInitialize(DriverObject, Argument2,
+ &hwInitData, &hwInfo);
+
+ DebugPrint(( 3, "NCR SDMS: DriverEntry ...eisaStatus = 0x%x \n",
+ eisaStatus ));
+
+ if ( hwInfo.hbaCount < MAX_NT_HBAS && eisaStatus != 0 )
+ {
+ DebugPrint(( 2, "NCR SDMS: DriverEntry *** ISA *** \n" ));
+
+ hwInfo.romAddrSpace = 0;
+ hwInfo.currentVirtAddr = 0;
+ hwInfo.currentRomAddr = FIRST_ROM_ADDRESS;
+ hwInfo.scsiBusId = 0;
+ hwInitData.AdapterInterfaceType = Isa;
+
+ isaStatus = ScsiPortInitialize(DriverObject, Argument2,
+ &hwInitData, &hwInfo);
+
+ DebugPrint(( 3, "NCR SDMS: DriverEntry ...isaStatus = 0x%x \n",
+ isaStatus ));
+
+ }
+
+
+ // Try to configure for internal (what is Internal???)
+
+ if ( hwInfo.hbaCount < MAX_NT_HBAS )
+ {
+ DebugPrint(( 2, "NCR SDMS: DriverEntry *** Internal *** \n" ));
+
+ hwInfo.romAddrSpace = 0;
+ hwInfo.currentVirtAddr = 0;
+ hwInfo.currentRomAddr = FIRST_ROM_ADDRESS;
+ hwInfo.scsiBusId = 0;
+ hwInitData.AdapterInterfaceType = Internal;
+
+ internalStatus = ScsiPortInitialize(DriverObject, Argument2,
+ &hwInitData, &hwInfo);
+
+ DebugPrint(( 3, "NCR SDMS: DriverEntry ...internalStatus = 0x%x \n",
+ internalStatus ));
+ }
+
+ // Try to configure for Microchannel.
+
+ if ( hwInfo.hbaCount < MAX_NT_HBAS )
+ {
+ DebugPrint(( 2, "NCR SDMS: DriverEntry *** Microchannel *** \n"));
+
+ hwInfo.romAddrSpace = 0;
+ hwInfo.currentVirtAddr = 0;
+ hwInfo.currentRomAddr = FIRST_ROM_ADDRESS;
+ hwInfo.scsiBusId = 0;
+ hwInitData.AdapterInterfaceType = MicroChannel;
+
+ mcaStatus = ScsiPortInitialize(DriverObject, Argument2,
+ &hwInitData, &hwInfo);
+
+ DebugPrint(( 3, "NCR SDMS: DriverEntry ...mcaStatus = 0x%x \n",
+ mcaStatus ));
+ }
+
+ // Return the minimum value.
+ if ( eisaStatus < isaStatus )
+ busStatus = eisaStatus;
+ else
+ busStatus = isaStatus;
+
+ if (internalStatus < busStatus )
+ busStatus = internalStatus;
+
+ if ( mcaStatus < busStatus )
+ busStatus = mcaStatus;
+
+ // Return the smallest status.
+
+ DebugPrint(( 1, "NCR SDMS: DriverEntry ...exiting\n"));
+
+ return( busStatus );
+
+} // End NCREntry
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NCRFindAdapter
+//
+// 1). Relocate 32 bit CAMcore code.
+// 2). Allocate noncachedExtension.
+//
+// Return:
+// ROMBase - base address of where CAMCore ROM was located.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+ULONG
+NCRFindAdapter(
+ IN PVOID HwDeviceExtension, // CAMGlobals
+ IN PVOID HwContext,
+ IN PVOID BusInformation,
+ IN PCHAR ArgumentString,
+ IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ OUT PBOOLEAN Again
+ )
+{
+ PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
+ PNONCACHED_EXTENSION noncachedExtension;
+ ULONG FCReturnValue;
+ PHWInfo hwInfo;
+
+
+ DebugPrint(( 1, "NCR SDMS: NCRFindAdapter \n" ));
+
+ // Need to get some information about previous calls.
+ hwInfo = (PHWInfo)HwContext;
+
+ // Check if the ROM address space has been mapped yet.
+ // If not, map the entire ROM address space in one call --
+ // this is to prevent a problem with NTLoader running out
+ // of page frame entries.
+ if (hwInfo->romAddrSpace == 0 )
+ {
+ // Get the entire ROM address space.
+ hwInfo->romAddrSpace = ScsiPortGetDeviceBase(
+ DeviceExtension,
+ ConfigInfo->AdapterInterfaceType, // Bus type
+ ConfigInfo->SystemIoBusNumber, // Bus number
+ ScsiPortConvertUlongToPhysicalAddress(
+ FIRST_ROM_ADDRESS ),
+ ROM_ADDRESS_SPACE_SIZE, // Map entire ROM region
+ // from C0000 - FFFFF
+ FALSE ); // Memory mapped
+
+ // If GetDeviceBase returned a zero, there was some
+ // error -- return to NT.
+ if ( hwInfo->romAddrSpace == 0 )
+ {
+ DebugPrint(( 3, "NCR SDMS: NCRFindAdapter ...Null pointer for ROM space \n"));
+ return( SP_RETURN_ERROR );
+ }
+
+ // Setup a pointer to the current virtual address we will
+ // be checking form SDMS ROMs.
+ hwInfo->currentVirtAddr = hwInfo->romAddrSpace;
+ }
+
+
+ // Check if maximum number of HBAs found. If so, clear the
+ // device base (if it exists), tell NT not to call FindAdapter
+ // anymore, and return to NT.
+
+ if ( hwInfo->hbaCount >= MAX_NT_HBAS )
+ {
+ DebugPrint(( 3, "NCR SDMS: NCRFindAdapter ...maximum HBA count exceeded \n" ));
+ if ( hwInfo->romAddrSpace != 0 )
+ ScsiPortFreeDeviceBase( DeviceExtension, hwInfo->romAddrSpace );
+
+ *Again = FALSE;
+
+ return( SP_RETURN_NOT_FOUND );
+ }
+
+ DebugPrint(( 2, "NCR SDMS: NCRFindAdapter ...before FindCore \n"));
+
+ FCReturnValue = FindCore( DeviceExtension,
+ ConfigInfo,
+ HwContext,
+ Again );
+
+ DebugPrint(( 2, "NCR SDMS: NCRFindAdapter ...after FindCore \n"));
+
+ // If no adapter found, return status to NT.
+ if ( FCReturnValue != SP_RETURN_FOUND )
+ return ( FCReturnValue );
+
+ // Initialize CAMcore and CoreGlobals. Call CAMinit in CAMcore
+ // with CoreInitialized = 0 .
+
+ // Noncached Extension was allocated in FindCore. Initialize the
+ // extension so the ConfigInfo data structure can be set up.
+ noncachedExtension = DeviceExtension->NoncachedExtension;
+
+ noncachedExtension->CoreGlobals.CoreInitialized = 0;
+
+ // Call CAMInit. Delays for hardware to reset are in the CAMcore.
+ (*DeviceExtension->initPtr)(&noncachedExtension->CoreGlobals);
+
+ // Initialize PORT_CONFIGURATION_INFORMATION
+
+ ConfigInfo->BusInterruptLevel = noncachedExtension->CoreGlobals.IRQNum;
+
+
+ // Update the DMA information if changed by CAMInit.
+ if ( noncachedExtension->CoreGlobals.DMAChannel == 0xFF ||
+ noncachedExtension->CoreGlobals.DMAChannel == 0x00 )
+ ConfigInfo->DmaChannel = 0xFFFFFFFF;
+ else
+ ConfigInfo->DmaChannel = noncachedExtension->CoreGlobals.DMAChannel;
+
+
+ // ConfigInfo->MaximumTransferLength = noncachedExtension->CoreGlobals.;
+
+ // Since we are doing the DMA programming (not NT), do not have to
+ // set DmaWidth.
+ // ConfigInfo->DmaWidth = xxx;
+
+ // Currently unused:
+ // ConfigInfo->DmaSpeed = xxx;
+
+ // Future: possibly need to get this info from CAMcore globals to
+ // accomodate dual SCSI channel or more.
+ ConfigInfo->NumberOfBuses = 1;
+ ConfigInfo->InitiatorBusId[0] = noncachedExtension->CoreGlobals.HASCSIID;
+
+ // Currently unused.
+ // ConfigInfo->AtdiskPrimaryClaimed
+ // ConfigInfo->AtdiskSecondaryClaimed
+
+ // Check whether we are I/O mapped or memory mapped.
+ if ( noncachedExtension->CoreGlobals.BasePort )
+ {
+ // IO mapped SCSI chip.
+ (*ConfigInfo->AccessRanges)
+ [AccessRangeChipIndex].RangeInMemory = FALSE;
+
+ (*ConfigInfo->AccessRanges)[AccessRangeChipIndex].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(
+ noncachedExtension->CoreGlobals.BasePort );
+ }
+
+ // Return SP_RETURN_FOUND, SP_RETURN_NOT_FOUND,
+ // SP_RETURN_ERROR or SP_RETURN_BAD_CONFIG.
+
+ return SP_RETURN_FOUND;
+
+} // End NCRFindAdapter
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// FindCore
+//
+// Locates CAMcore in the ROM BIOS address space from
+// 0xC0000 to 0x100000. Initializes global values for ROM address
+// (HAPhysAddr, HAVirtAddr, HARAMVirtAddr), chip addresses
+// (ChipVirtAddr) and address of globals (GlobalPhysAddr).
+// Allocates noncachedExtension.
+//
+// Arguments: HwDeviceExtension -
+//
+// Returns: Address of CAMcore or SP_RETURN_ERROR if it could not
+// allocate noncachedExtension.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+ULONG
+FindCore(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ IN OUT PHWInfo hwInfo,
+ OUT PBOOLEAN Again
+ )
+{
+ PNONCACHED_EXTENSION noncachedExtension;
+ ROMCAMcoreFields * ROMHeader;
+ PUCHAR basePtr;
+ REXHeader * rp;
+ CAM32Header * cp;
+ ULONG fileSize;
+ PULONG relocTable;
+ ULONG i;
+ PCHAR src;
+ ULONG Length;
+
+ BOOLEAN NoSdmsRom;
+ PULONG itemPtr;
+ ULONG foundRomAddr;
+
+ CONST UCHAR magicStr1[] = MAGIC_STR_1 ;
+
+ DebugPrint(( 1, "NCR SDMS: FindCore \n"));
+
+ DeviceExtension->initPtr = 0;
+
+ // Set up virtual address pointer.
+ basePtr = hwInfo->currentVirtAddr;
+
+ // Check the ROM address space every 2K for SDMS CAMcore.
+ for ( ; hwInfo->currentRomAddr < LAST_ROM_ADDRESS;
+ basePtr += ROM_CHECK_STEP,
+ hwInfo->currentRomAddr += ROM_CHECK_STEP )
+ {
+
+ DebugPrint(( 3, "NCR SDMS: FindCore ...VirtAddr = 0x%x RomAddr = 0x%x \n",
+ basePtr, hwInfo->currentRomAddr ));
+
+
+ // Check for ROM identifier.
+ if ( gByte(basePtr,MARK_55) != 0x55
+ || gByte(basePtr,MARK_AA) != 0xAA )
+ {
+ continue; // Check next ROM address space.
+ }
+
+ // Search for ROM SIM string present in all CAMCores.
+ NoSdmsRom = FALSE;
+
+ // Check for the identifying string in the ROM.
+ for (i = 0; i < sizeof(magicStr1) - 1; i++)
+ {
+
+ if ( gByte(basePtr,ROM_SIM_STR+i) != magicStr1[i] )
+ {
+ NoSdmsRom = TRUE;
+ break; // Not SDMS ROM -- stop checking identifying
+ // string.
+ }
+ } // End for loop
+
+ if ( NoSdmsRom )
+ continue; // Check next ROM address location
+
+ // At this point, we apparently have found a SDMS CAMcore.
+
+ // Store SDMS CAMcore version.
+ DeviceExtension->SdmsVersion = gWord(basePtr, CORE_VERSION);
+
+ DebugPrint(( 1, "NCR SDMS: FindCore ...SDMS Version = %d \n",
+ DeviceExtension->SdmsVersion ));
+
+ // If V1.6 or newer CAMcore, set up pointer to REX header.
+ // If not at least V1.6, continue searching ROM address space.
+ if ( DeviceExtension->SdmsVersion >= SDMS_V16 )
+ {
+ if (gWord(basePtr,REX_OFFSET) != 0)
+ rp = (REXHeader *)(basePtr + gWord(basePtr,REX_OFFSET));
+
+ // Look for the REX header signature of "MQ" and end of the
+ // REX header = 0x0001. This should be the SDMS CAMcore.
+ // If this is true break out of the loop checking the
+ // ROM address space. If REX header not found, fall
+ // through to bottom of FOR loop, clear device base
+ // and continue checking ROM address space.
+
+ if ( ( rp->sig == 0x514D ) && (rp->ooo1 == 1) )
+ break;
+ }
+
+ // Not at SDMS V1.6 or above, so clear the saved version number.
+ DeviceExtension->SdmsVersion = 0;
+
+ } // End of For loop checking ROM address space.
+
+
+ // Check if we searched outside of ROM address space. If outside of
+ // ROM address space, return to caller indicating no CAMcore found.
+ if ( hwInfo->currentRomAddr >= LAST_ROM_ADDRESS )
+ {
+ ScsiPortFreeDeviceBase( DeviceExtension, hwInfo->romAddrSpace );
+
+ hwInfo->currentVirtAddr = 0;
+ hwInfo->romAddrSpace = 0;
+
+ // Entire ROM address space has been searched.
+ *Again = FALSE;
+
+ return( SP_RETURN_NOT_FOUND );
+ }
+
+ // Set found ROM address.
+ foundRomAddr = hwInfo->currentRomAddr;
+
+ // Increment current ROM address so next time in FindCore, search
+ // will start at the proper location.
+ hwInfo->currentRomAddr += ROM_CHECK_STEP;
+
+ // Increment current virtual pointer to next possible ROM location.
+ hwInfo->currentVirtAddr = basePtr + ROM_CHECK_STEP;
+
+ // Allocate a smaller device base that only includes the 32K
+ // ROM that we have found.
+ basePtr = ScsiPortGetDeviceBase(
+ DeviceExtension,
+ ConfigInfo->AdapterInterfaceType, // bus type
+ ConfigInfo->SystemIoBusNumber, // bus number
+ ScsiPortConvertUlongToPhysicalAddress( foundRomAddr ),
+ ROM_SIZE, // 32K allocated, must allocate
+ // enough to be able to access
+ // all of the 32 bit code.
+ FALSE); // Memory mapped
+
+ // Tell NT that we should be called again.
+ *Again = TRUE;
+
+ // At this point, we have located a SDMS V1.6 (or above) CAMcore
+ // and identified the REX section of the CAMcore.
+
+ // Now "basePtr" points to the ROM header and "rp" points to the REX
+ // header in the ROM structure, and "foundRomAddr" is the
+ // physical address of the ROM.
+
+ DebugPrint(( 1, "NCR SDMS: FindCore ...CAMcore found at 0x%x \n",
+ foundRomAddr ));
+
+ // Get information from ROM header so that we can call
+ // GetUncachedExtension to initialize our CoreGlobals.
+ // GetUncachedExtension needs DmaChannel, DmaPort, DmaSpeed,
+ // MaximumLength, ScatterGather, Master and NumberOfPageBreaks
+ // (if scatter/gather is supported) initialized in the ConfigInfo
+ // data structure.
+
+ // Setup pointer to ROMHeader.
+
+ ROMHeader = (ROMCAMcoreFields *)basePtr;
+
+ // Save path id in device extension (for ScsiPortNotification).
+ DeviceExtension->scsiBusId = hwInfo->scsiBusId;
+
+ // Save DMA channel.
+ if ( ROMHeader->dmachannel == 0xFF || ROMHeader->dmachannel == 0x00 )
+ ConfigInfo->DmaChannel = 0xFFFFFFFF;
+ else
+ ConfigInfo->DmaChannel = ROMHeader->dmachannel;
+
+ // Master is always true because the CAMcore already programs
+ // the DMA channel not NT.
+ ConfigInfo->Master = TRUE;
+
+ // Initialize maximum transfer length if maxdma is not zero.
+ // If maxdma is zero there is no limit so leave MaximumTransferLength
+ // to its default of 0xffffffff which means no limit to NT.
+
+ if ( ROMHeader->maxdma )
+ ConfigInfo->MaximumTransferLength = ROMHeader->maxdma;
+
+ // Do not support scatter/gather with this release of the
+ // driver.
+ ConfigInfo->ScatterGather = FALSE;
+
+ // Only one break without scatter/gather. However, changing
+ // this to one causes run time errors -- so leave at 16 for now.
+ ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_BRKS;
+
+ // In future to support caching adapters (CachesData=TRUE)
+ // we need this info in CAMcore globals or ROM header.
+ ConfigInfo->CachesData = FALSE;
+ ConfigInfo->Length = sizeof( PORT_CONFIGURATION_INFORMATION );
+
+ if ( ( gByte( basePtr, ROM_TYPE_1 ) == 'A' ) &&
+ ( gByte( basePtr, ROM_TYPE_2 ) == 'T' ) )
+ {
+ // Insure that data buffers are below 16MB.
+ ConfigInfo->InterruptMode = Latched;
+ ConfigInfo->Dma32BitAddresses = FALSE;
+ }
+ else
+ {
+ ConfigInfo->InterruptMode = LevelSensitive;
+ ConfigInfo->Dma32BitAddresses = TRUE;
+ }
+
+ // Allocate a Noncached Extension to use for CoreGlobals.
+
+ DeviceExtension->NoncachedExtension = ScsiPortGetUncachedExtension(
+ DeviceExtension,
+ ConfigInfo,
+ sizeof(NONCACHED_EXTENSION));
+
+ noncachedExtension = DeviceExtension->NoncachedExtension;
+
+ // If Noncached extension could not be allocated, log error.
+ if (DeviceExtension->NoncachedExtension == NULL)
+ {
+ ScsiPortLogError( DeviceExtension,
+ NULL,
+ 0,
+ 0,
+ 0,
+ SP_INTERNAL_ADAPTER_ERROR,
+ 7 << 8
+ );
+
+ return(SP_RETURN_ERROR);
+ }
+
+ // Zero out noncachedExtension which contains the CoreGlobals.
+ for ( i = 0; i < sizeof(NONCACHED_EXTENSION); i++)
+ ((PUCHAR)noncachedExtension)[i] = 0;
+
+ // Address of host adapter.
+ noncachedExtension->CoreGlobals.HAOrigPhysAddr = foundRomAddr;
+
+ // Address of ROM image.
+ noncachedExtension->CoreGlobals.HAPhysAddr = foundRomAddr;
+
+ // Get Virtual address space for the HBA ROM from basePtr pointer.
+ noncachedExtension->CoreGlobals.HAVirtAddr = (ULONG)basePtr;
+
+ noncachedExtension->CoreGlobals.GlobalPhysAddr =
+ ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(
+ DeviceExtension,
+ NULL,
+ &DeviceExtension->NoncachedExtension->CoreGlobals,
+ &Length));
+
+ // CHIP_PHYS is the physical address of a memory mapped SCSI chip
+ // on the mother board. This value is in the ROM header of the
+ // CAMcore.
+
+ if ( gLong(basePtr,CHIP_PHYS) )
+ noncachedExtension->CoreGlobals.ChipVirtAddr =
+ noncachedExtension->CoreGlobals.HAVirtAddr + gLong(basePtr,CHIP_PHYS);
+
+ // CHIP_OFFSET is the offset from the beginning of the ROM for
+ // a memory mapped SCSI chip on an HBA. This is also in the
+ // ROM header of the CAMcore initialized from the .RSP file
+ // when the CAMcore is built.
+
+ else
+ noncachedExtension->CoreGlobals.ChipVirtAddr =
+ noncachedExtension->CoreGlobals.HAVirtAddr + gWord(basePtr,CHIP_OFFSET);
+
+ if ( gWord(basePtr,RAM_OFFSET) )
+ noncachedExtension->CoreGlobals.HARAMVirtAddr =
+ noncachedExtension->CoreGlobals.HAVirtAddr + gWord(basePtr,RAM_OFFSET);
+
+ ConfigInfo->NumberOfAccessRanges = 2;
+
+ // Initialize AccessRanges in the ConfigInfo data structure
+ // for the ROM CAMcore and the SCSI chip on HBA.
+
+ (*ConfigInfo->AccessRanges)[AccessRangeROMIndex].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(
+ noncachedExtension->CoreGlobals.HAPhysAddr );
+
+ // Length of ROM in 3rd byte of ROMHeader.
+
+ (*ConfigInfo->AccessRanges)[AccessRangeROMIndex].RangeLength =
+ ROMHeader->ROMlen * 512;
+
+ (*ConfigInfo->AccessRanges)[AccessRangeROMIndex].RangeInMemory = TRUE;
+
+ // Initialize AccessRanges for Chip on HBA.
+ // Number of chip ports is set to 200 -- 53C720 is 92 bytes (0x5c).
+
+ (*ConfigInfo->AccessRanges)[AccessRangeChipIndex].RangeLength = 200;
+
+ // Check whether we are I/O mapped or memory mapped.
+ if ( noncachedExtension->CoreGlobals.BasePort )
+ {
+ // IO mapped SCSI chip.
+ (*ConfigInfo->AccessRanges)
+ [AccessRangeChipIndex].RangeInMemory = FALSE;
+
+ (*ConfigInfo->AccessRanges)[AccessRangeChipIndex].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(
+ noncachedExtension->CoreGlobals.BasePort );
+ }
+ else
+ {
+ // Memory mapped SCSI chip
+ (*ConfigInfo->AccessRanges)
+ [AccessRangeChipIndex].RangeInMemory = TRUE;
+
+ if ( gLong(basePtr,CHIP_PHYS) )
+ (*ConfigInfo->AccessRanges)[AccessRangeChipIndex].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(
+ noncachedExtension->CoreGlobals.HAPhysAddr + gLong(basePtr,CHIP_PHYS) );
+ else
+ (*ConfigInfo->AccessRanges)[AccessRangeChipIndex].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(
+ noncachedExtension->CoreGlobals.HAPhysAddr + gWord(basePtr,CHIP_OFFSET) );
+ }
+
+ // Now extract information from the REX header
+
+ // Size of the 32-bit code.
+
+ fileSize = rp->sizeQuo * 512 + rp->sizeRem - 512;
+ fileSize -= rp->headSize * 16;
+
+ DebugPrint((1, "NCR SDMS: FindCore ...REX file size = %d \n", fileSize));
+
+ // Point "src" to beginning of the 32-bit code. Have to skip
+ // around the REX header information.
+
+ src = (char *)((long)rp + rp->headSize * 16);
+
+ // Copy the 32-bit code from the ROM into the Device Extension.
+
+ for ( i = 0; i < fileSize; i++ )
+ DeviceExtension->base32BitCode[i] = src[i];
+
+ // Perform relocation.
+
+ // Set "relocTable" to first item to be relocated.
+
+ relocTable = (ulong *)( (long)rp + rp->relocOffset );
+
+ // Relocate all items in relocation table. Insure that each
+ // item has the high bit set before relocation.
+ for ( i = 0; i < rp->numReloc; i++ )
+ {
+ // The high bit of the values in the relocation table is
+ // set if 32 bits wide so, it should be set since
+ // this is 32 bit code. If it is not set, free device
+ // extension and return to caller.
+ if ( (relocTable[i] & 0x80000000) == 0 )
+ {
+ ScsiPortFreeDeviceBase( DeviceExtension, basePtr );
+ return( SP_RETURN_ERROR );
+ }
+ itemPtr = (ulong *)(DeviceExtension->base32BitCode +
+ (relocTable[i] & 0x7fffffff));
+
+ *itemPtr += (long)DeviceExtension->base32BitCode;
+ }
+
+ // Setup pointer to relocated 32-bit code. Note, must use "src"
+ // rather than base32BitCode because relocation changes
+ // CAM32Header.
+
+ cp = (CAM32Header *)src;
+
+ // Pointer to CAMInit.
+
+ DeviceExtension->initPtr =
+ (PVOID)(DeviceExtension->base32BitCode +
+ cp->initOffset);
+
+ // Pointer to CAMStart.
+
+ DeviceExtension->startPtr =
+ (PVOID)(DeviceExtension->base32BitCode +
+ cp->startOffset);
+
+ // Pointer to CAMInterrupt.
+
+ DeviceExtension->interruptPtr =
+ (PVOID)(DeviceExtension->base32BitCode +
+ cp->interruptOffset);
+
+ // Pointer to chsMap.
+
+ DeviceExtension->chsPtr =
+ (PVOID)(DeviceExtension->base32BitCode +
+ cp->chsOffset);
+
+ // Increment HBA count.
+ hwInfo->hbaCount++;
+
+ return SP_RETURN_FOUND;
+
+} // End FindCore
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// InitPath
+//
+// Initializes the CAMCore after it is found by FindCore.
+// Sets up CAMCore globals.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+VOID
+InitPath(
+ IN PHW_DEVICE_EXTENSION DeviceExtension
+ )
+{
+ PNONCACHED_EXTENSION noncachedExtension = DeviceExtension->NoncachedExtension;
+
+ DebugPrint(( 1, "NCR SDMS: InitPath \n"));
+
+ noncachedExtension->CoreGlobals.CoreInitialized = 0;
+
+ // Call CAMInit. Delays for hardware to reset are in the CAMcore.
+ (*DeviceExtension->initPtr)(&noncachedExtension->CoreGlobals);
+
+ // Tell the port driver the bus has been reset.
+ ScsiPortNotification( ResetDetected, DeviceExtension, DeviceExtension->scsiBusId );
+
+ DebugPrint(( 1, "NCR SDMS: InitPath ...after CAMInit \n"));
+
+} // End InitPath
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NCRHwInitialize
+//
+// This routine is called by the OS specific port driver
+// when the host bus adapter needs to be initialized
+// after a boot or a power failure. This routine only
+// needs to initialize the hardware host bus adapter
+// but should avoid resetting the SCSI bus.
+//
+// Arguments:
+//
+// DeviceExtension - supplies the HBA miniport driver's
+// storage for adapter data.
+//
+// Returns TRUE or FALSE.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+BOOLEAN
+NCRHwInitialize(
+ IN PVOID HwDeviceExtension
+ )
+{
+ PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
+ PNONCACHED_EXTENSION noncachedExtension = DeviceExtension->NoncachedExtension;
+
+ DebugPrint(( 1, "NCR SDMS: NCRHwInitialize \n"));
+
+ // Don't reset SCSI bus.
+ noncachedExtension->CoreGlobals.config_info |=
+ CORHDR_DO_NOT_RESET_SCSI_BUS;
+
+ // Call CAMInit in CAMcore to reset and initialize the SCSI chip
+ // and CoreGlobals. Delays for hardware to reset are in the CAMcore.
+ InitPath( DeviceExtension );
+
+ noncachedExtension->CoreGlobals.config_info &=
+ !(CORHDR_DO_NOT_RESET_SCSI_BUS);
+
+ DebugPrint(( 1, "NCR SDMS: NCRHwInitialize ...exiting\n"));
+
+ return TRUE;
+
+} // End NCRHwInitialize
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NCRResetBus
+//
+/////////////////////////////////////////////////////////////////////////////
+
+BOOLEAN
+NCRResetBus(
+ IN PVOID HwDeviceExtension,
+ IN ULONG PathId
+ )
+{
+ PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
+ PNONCACHED_EXTENSION noncachedExtension = DeviceExtension->NoncachedExtension;
+
+ DebugPrint(( 1, "NCR SDMS: NCRResetBus \n" ));
+
+ // Calls CAMInit routine in CAMcore to Reset SCSI Bus
+ // and initialize CoreGlobals.
+ noncachedExtension->CoreGlobals.config_info &=
+ !(CORHDR_DO_NOT_RESET_SCSI_BUS);
+
+
+ DebugPrint(( 2, "NCR SDMS: NCRResetBus ...entering InitPath\n"));
+
+ // Call CAMInit. Delays for hardware to reset are in the CAMcore.
+ InitPath( DeviceExtension );
+
+ DebugPrint(( 2, "NCR SDMS: NCRResetBus ...after InitPath\n"));
+
+ // Complete all outstanding requests with SRB_STATUS_BUS_RESET
+ ScsiPortCompleteRequest( DeviceExtension,
+ (UCHAR)PathId,
+ 0xFF,
+ 0xFF,
+ SRB_STATUS_BUS_RESET );
+
+ DebugPrint(( 2, "NCR SDMS: NCRResetBus ...complete\n"));
+
+ return TRUE;
+
+} // End NCRResetBus
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NCRStartIo
+//
+////////////////////////////////////////////////////////////////////////////
+
+BOOLEAN
+NCRStartIo(
+ IN PVOID HwDeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+ PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
+ PNONCACHED_EXTENSION noncachedExtension = DeviceExtension->NoncachedExtension;
+ PROMscsiCCB pROMCcb = Srb->SrbExtension;
+
+ DebugPrint(( 1, "NCR SDMS: NCRStartIo \n"));
+
+ switch ( Srb->Function )
+ {
+ case SRB_FUNCTION_EXECUTE_SCSI:
+
+ // For SDMS V1.6, reject all LUNs except zero. The
+ // version cannot handle the LUNs.
+ if ( ( DeviceExtension->SdmsVersion == SDMS_V16 ) &&
+ ( Srb->Lun != 0x00 ) )
+ {
+ Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
+
+ DebugPrint((3, "NCR SDMS: StartIO ...LUN %d aborted\n",
+ Srb->Lun ));
+
+ ScsiPortNotification( RequestComplete,
+ DeviceExtension,
+ Srb);
+
+ ScsiPortNotification( NextRequest,
+ DeviceExtension,
+ NULL);
+ return TRUE;
+ }
+
+ BuildCCBFromSRB( DeviceExtension, Srb );
+
+ // If BuildCCBFromSRB was unsuccessful, it will set the
+ // SRB Status field to indicate that the I/O request should
+ // be aborted.
+ if ( Srb->SrbStatus == SRB_STATUS_ABORTED)
+ {
+ DebugPrint(( 3, "NCR SDMS: StartIO ...abort request\n"));
+
+ ScsiPortNotification( RequestComplete,
+ DeviceExtension,
+ Srb);
+
+ ScsiPortNotification( NextRequest,
+ DeviceExtension,
+ NULL);
+ return TRUE;
+ }
+
+ DebugPrint(( 2, "NCR SDMS: StartIO ...call CAMStart \n"));
+
+ // Call CAMstart
+ ( *DeviceExtension->startPtr )
+ ( &noncachedExtension->CoreGlobals,
+ Srb->SrbExtension );
+
+ DebugPrint(( 2, "NCR SDMS: StartIO ...back from CAMStart \n"));
+
+ break;
+
+ case SRB_FUNCTION_ABORT_COMMAND:
+
+ DebugPrint(( 3, "NCR SDMS: NCRStartIo ...Abort command received \n"));
+
+ // Abort not supported --- once CAMstart is called with a valid
+ // CCB it can't be aborted unless a reset is done.
+ Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
+
+ ScsiPortNotification( RequestComplete,
+ DeviceExtension,
+ Srb);
+
+ ScsiPortNotification( NextRequest,
+ DeviceExtension,
+ NULL);
+ return TRUE;
+
+ case SRB_FUNCTION_RESET_BUS:
+
+ if ( !NCRResetBus( DeviceExtension, Srb->PathId) )
+ {
+
+ DebugPrint(( 3, "NCR SDMS: NCRStartIo ...Reset Bus failed \n"));
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ }
+ else
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+
+ ScsiPortNotification( RequestComplete,
+ DeviceExtension,
+ Srb);
+
+ ScsiPortNotification( NextRequest,
+ DeviceExtension,
+ NULL);
+ return TRUE;
+
+ case SRB_FUNCTION_RESET_DEVICE:
+
+ DebugPrint(( 3, "NCR SDMS: NCRStartIo ...Reset device not supported. \n"));
+
+ // Reset device not supported. drop through to default.
+
+ // Return bad function SRB status for unsupported functions.
+ default:
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ ScsiPortNotification( RequestComplete,
+ DeviceExtension,
+ Srb);
+
+ ScsiPortNotification( NextRequest,
+ DeviceExtension,
+ NULL);
+ return TRUE;
+ break;
+
+ } // End switch
+
+ return TRUE;
+
+} // End NCRStartIo
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// BuildCCBFromSRB
+//
+// Translates the NT I/O request data structure (Srb) into a
+// SDMS CAMcore I/O data structure (CCB).
+//
+/////////////////////////////////////////////////////////////////////////////
+
+VOID
+BuildCCBFromSRB(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+{
+
+ PROMscsiCCB pROMCcb = Srb->SrbExtension;
+ ULONG i;
+ ULONG Length;
+
+ DebugPrint(( 1, "NCR SDMS: BuildCCBFromSRB \n"));
+
+ // Zero out the CCB storage area.
+ for ( i = 0; i < sizeof(ROMscsiCCB); i++)
+ ((PUCHAR)pROMCcb)[i] = 0;
+
+ // Save the SRB address in the CCB
+ pROMCcb->SCSIReq.PeripheralPtr = (ULONG)Srb;
+
+ pROMCcb->SCSIReq.Header.CCBLength = sizeof( SCSIRequestCCB );
+ pROMCcb->SCSIReq.Header.FunctionCode = FUNC_EXECUTE_SCSI_IO;
+ pROMCcb->SCSIReq.Header.CAMStatus = STAT_REQUEST_IN_PROGRESS;
+ pROMCcb->SCSIReq.Header.SCSIStatus = 0;
+ pROMCcb->SCSIReq.Header.PathID = Srb->PathId;
+
+ if ( Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE )
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_QUEUE_ACTION_SPECIFIED;
+
+ if ( Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT )
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DO_NOT_ALLOW_DISCONNECT;
+
+ if ( Srb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER )
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DISABLE_SYNC_TRAN;
+
+ // Disable auto request sense
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DISABLE_AUTOSENSE;
+
+ // Don't check this now because we don't currently support autosense.
+ // if ( Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE )
+ // pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DISABLE_AUTOSENSE;
+
+ if ( Srb->SrbFlags & SRB_FLAGS_DATA_IN )
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DIR_DATA_IN;
+ else if ( Srb->SrbFlags & SRB_FLAGS_DATA_OUT )
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DIR_DATA_OUT;
+ else
+ pROMCcb->SCSIReq.Header.CAMFlags |= CAM_DIR_NO_DATA;
+
+ // SRB_FLAGS not supported
+ //
+ // SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010
+ // SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100
+ // SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200
+ // SRB_FLAGS_IS_ACTIVE 0x00010000
+ // SRB_FLAGS_ALLOCATED_FROM_ZONE 0x00020000
+
+ pROMCcb->SCSIReq.TargetID = Srb->TargetId;
+ pROMCcb->SCSIReq.LUN = Srb->Lun;
+ pROMCcb->SCSIReq.Queue_Action = Srb->QueueAction;
+
+ // Following field has no SRB equivalent.
+ // pROMCcb->SCSIReq.VendorFlags = xxx;
+
+ (UCHAR)pROMCcb->SCSIReq.CDBLength = Srb->CdbLength;
+ (UCHAR)pROMCcb->ROMFields.CDBLength = Srb->CdbLength;
+ (UCHAR)pROMCcb->SCSIReq.SenseLength = Srb->SenseInfoBufferLength;
+
+ // No SRB equivalent -- already set to zero.
+ // pROMCcb->SCSIReq.MessageLength = 0;
+
+ // Set Scatter/Gather list length to zero.
+ pROMCcb->SCSIReq.SGListLength = 0;
+
+ // Set data length to SRB data length.
+ pROMCcb->SCSIReq.DataLength = Srb->DataTransferLength;
+
+ pROMCcb->SCSIReq.TimeOut = Srb->TimeOutValue;
+
+ // Unique fields added to end of CAM CCB for CAMcore code.
+ // This is here probably because some core at some time
+ // under a specific operating system needed physical as
+ // well as virtual addresses.
+ // This should be removed from SDMS 3.0.
+
+ pROMCcb->SCSIReq.DataPtr = ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress( DeviceExtension,
+ Srb,
+ Srb->DataBuffer,
+ &Length));
+
+ // If available memory not enough for data buffer, set the
+ // Srb Status field to ABORT and NCRStartIo will handle
+ // aborting the request.
+ if ( Length < Srb->DataTransferLength )
+ {
+ DebugPrint(( 2, "NCR SDMS: BuildCCBFromSrb ...Phys buffer length < SRB->DataTransferLength \n" ));
+ DebugPrint(( 2, " Physical Buffer Length = 0x%lx\n",
+ Length));
+ DebugPrint(( 2, " SRB Data Transfer Length = 0x%lx\n",
+ Srb->DataTransferLength));
+
+ Srb->SrbStatus = SRB_STATUS_ABORTED;
+
+ return;
+ }
+
+ pROMCcb->ROMFields.DataPhys = pROMCcb->SCSIReq.DataPtr;
+
+ // Setup data buffer virtual address.
+
+ pROMCcb->ROMFields.DataVirt = (ULONG)Srb->DataBuffer;
+
+ // Since AutoSense is disabled, set the sense buffers to zero.
+ pROMCcb->SCSIReq.SensePtr = 0;
+ pROMCcb->ROMFields.SensePhys = 0;
+
+ // Setup virtual address of Sense buffer.
+ pROMCcb->ROMFields.SenseVirt = (ULONG)Srb->SenseInfoBuffer;
+
+ // Following fields have already been cleared when CCB zeroed.
+ // They have no SRB equivalent.
+
+ // pROMCcb->SCSIReq.MessagePtr = 0;
+ // pROMCcb->SCSIReq.LinkPtr = 0;
+ // pROMCcb->SCSIReq.PeripheralPtr = 0;
+ // pROMCcb->SCSIReq.CallBackPtr[0] = 0;
+ // pROMCcb->SCSIReq.CallBackPtr[1] = 0;
+ // pROMCcb->SCSIReq.CallBackPtr[2] = 0;
+
+ // Copy the SRB CDB to the CCB CDB (and ROMFields CCB)
+ for ( i=0; i<Srb->CdbLength; i++) {
+ pROMCcb->SCSIReq.CDB[i] = Srb->Cdb[i];
+ pROMCcb->ROMFields.CDB[i] = Srb->Cdb[i];
+ }
+
+ DebugPrint(( 2, "NCR SDMS: BuildCCBFromSRB ...return \n"));
+
+} // End BuildCCBFromSRB
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NCRInterrupt
+//
+// Return value:
+// TRUE -- interrupt belonged to this HBA.
+// FALSE -- interrupt did not belong to this HBA.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+BOOLEAN
+NCRInterrupt(
+ IN PVOID HwDeviceExtension
+ )
+{
+ PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension;
+ PNONCACHED_EXTENSION noncachedExtension = DeviceExtension->NoncachedExtension;
+
+ ULONG returnValue; // Return value from CAMInterrupt
+ ULONG newReturnValue;
+
+ PSCSI_REQUEST_BLOCK Srb;
+ PSCSIRequestCCB pScsiRequestCcb;
+
+ // Leave the debug level at 3 in case we have to debug the
+ // NTLDR program.
+ DebugPrint(( 3, "NCR SDMS: NCRInterrupt \n"));
+
+ // Tell the Core that this was a true interrupt from NT.
+ noncachedExtension->CoreGlobals.GlobalFlags |= GLOBAL_FLAGS_TRUE_INT;
+
+ // Call CAMInterrupt
+
+ returnValue = ( *DeviceExtension->interruptPtr )(&noncachedExtension->CoreGlobals);
+
+ // Set the flag to tell the Core the driver is calling again
+ // for interrupt servicing.
+ noncachedExtension->CoreGlobals.GlobalFlags &= ~GLOBAL_FLAGS_TRUE_INT;
+
+ // Leave the debug level at 3 in case we have to debug the
+ // NTLDR program.
+ DebugPrint(( 3, "NCR SDMS: NCRInterrupt ...after CAMInterrupt\n"));
+
+ // If CAMInterrupt returns 0, interrupt was not ours. Signal
+ // this fact to NT. If CAMInterrupt returns any other value,
+ // the interrupt was ours.
+ if (returnValue == 0)
+ {
+ // Leave the debug level at 3 in case we have to debug
+ // the NTLDR program.
+ DebugPrint(( 3, "NCR SDMS: NCRInterrupt ...not our interrupt \n"));
+ return FALSE;
+ }
+
+ // Return value of "1" or "2" indicates the interrupt was ours, but
+ // no other action occurred (i.e. the CCB is still outstanding).
+ // Poll CAMInterrupt until the CCB is complete.
+
+ // Return value of "1" indicates the interrupt was ours, but we
+ // must wait for NT to call us again.
+ if( returnValue == 1 )
+ return TRUE;
+
+ // Save the original return value from CAMInterrupt.
+ newReturnValue = returnValue;
+
+ while ( newReturnValue >= 2 )
+ {
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...return value >= 2 \n"));
+ newReturnValue = ( *DeviceExtension->interruptPtr )(&noncachedExtension->CoreGlobals);
+
+ // If return value is greater than "2", this is a pointer
+ // to our CCB.
+ if ( newReturnValue > 2 )
+ returnValue = newReturnValue;
+ }
+
+ // If return value greater than "2", we tell NT that the
+ // interrupt was ours and wait for NT to call us again.
+ // If the inner loop (above) returned a "1" or "2", then the
+ // orignal value will still be "2".
+ if( returnValue == 2 )
+ return TRUE;
+
+ // CAMInterrupt returns the CCB that was serviced.
+ pScsiRequestCcb = (PSCSIRequestCCB)returnValue;
+
+ // Get the SRB from the CCB.
+ Srb = (PSCSI_REQUEST_BLOCK)pScsiRequestCcb->PeripheralPtr;
+
+ // Translate the CAM Status Flag to a SRB Status Flag.
+
+ // Update SCSI status (only if it is equal to 0x02).
+ if ( (UCHAR)pScsiRequestCcb->Header.SCSIStatus == 0x02 )
+ Srb->ScsiStatus = (UCHAR)pScsiRequestCcb->Header.SCSIStatus;
+
+ // Print the Data Length information.
+ DebugPrint(( 3, "NCR SDMS: NCRInterrupt ...CCB Data Length = 0x%lx\n",
+ (ULONG)pScsiRequestCcb->DataLength));
+
+ DebugPrint(( 3, "NCR SDMS: NCRInterrupt ...SRB Data Length = 0x%lx\n",
+ (ULONG)Srb->DataTransferLength));
+
+ switch ( (UCHAR)pScsiRequestCcb->Header.CAMStatus )
+ {
+
+ case STAT_REQUEST_IN_PROGRESS:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_PENDING;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_PENDING\n"));
+ return TRUE; // Current SRB is not completed.
+ break;
+
+ case STAT_REQUEST_DONE_NO_ERROR:
+
+ // Update the data length -- SDMS 1.6 only. SDMS 3.0 uses
+ // a different data field for residual count. The CCB
+ // data length will be zero if all data transferred.
+ // If the value is non-zero, this is the number of bytes
+ // NOT transferred.
+
+ if ((ULONG)pScsiRequestCcb->DataLength > 0)
+ {
+ Srb->DataTransferLength = (ULONG)pScsiRequestCcb->DataLength;
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_DATA_OVERRUN;
+ }
+ else
+ {
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_SUCCESS;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_SUCCESS\n"));
+ }
+
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...Adjusted SRB Data Length = 0x%x\n",
+ (ULONG)Srb->DataTransferLength));
+ break;
+
+ case STAT_ABORTED_BY_HOST:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_ABORTED;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_ABORTED\n"));
+ break;
+
+ case STAT_UNABLE_TO_ABORT:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_ABORT_FAILED;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_ABORT_FAILED\n"));
+ break;
+
+ case STAT_COMPLETE_WITH_ERROR:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_ERROR;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_ERROR\n"));
+ break;
+
+ // Ask for another SRB???
+ case STAT_CAM_BUSY:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_BUSY;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_BUSY\n"));
+ break;
+
+ case STAT_INVALID_REQUEST:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_INVALID_REQUEST;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_INVALID REQUEST\n"));
+ break;
+
+ case STAT_INVALID_PATH_ID:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_INVALID_PATH_ID;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_INVALID_PATH_ID\n"));
+ break;
+
+ case STAT_SCSI_DEVICE_NOT_INSTALLED:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_NO_DEVICE;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_NO_DEVICE\n"));
+ break;
+
+ case STAT_WAIT_FOR_TIMEOUT:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_TIMEOUT;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_TIMEOUT\n"));
+ break;
+
+ case STAT_SELECTION_TIMEOUT:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_SELECTION_TIMEOUT;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_SELECTION_TIMEOUT\n"));
+ break;
+
+ case STAT_COMMAND_TIMEOUT:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_COMMAND_TIMEOUT;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_COMMAND_TIMEOUT \n"));
+ break;
+
+ // Ask for another SRB ??
+ case STAT_SCSI_BUS_BUSY: // No equivalent SRB Flag
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_BUSY;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_BUSY \n"));
+ return TRUE; // Current SRB not complete
+ break;
+
+ case STAT_MESSAGE_REJECT_RECIEVED:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_MESSAGE_REJECTED;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_MESSAGE_REJECTED \n"));
+ break;
+
+ case STAT_SCSI_BUS_RESET:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_BUS_RESET;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_BUS_RESET \n"));
+ // Notify port driver of SCSI Reset
+ ScsiPortNotification( ResetDetected,
+ DeviceExtension,
+ Srb->PathId);
+ return TRUE;
+
+ break;
+
+ case STAT_UNCORRECTED_PARITY_ERROR:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_PARITY_ERROR;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_PARITY_ERROR \n"));
+ break;
+
+ case STAT_REQUEST_SENSE_FAILED:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_REQUEST_SENSE_FAILED;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_SENSE_FAILED \n"));
+ break;
+
+ case STAT_NO_HBA_DETECTED_ERROR:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_NO_HBA;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_NO_HBA \n"));
+ break;
+
+ case STAT_DATA_OVERRUN_OR_UNDERRUN:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_DATA_OVERRUN;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_DATA_OVERRUN \n"));
+ break;
+
+ case STAT_UNEXPECTED_BUS_FREE:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_UNEXPECTED_BUS_FREE;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_UNEXPECTED_BUS_FREE \n"));
+ break;
+
+ case STAT_PHASE_SEQUENCE_FAILURE:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_PHASE_SEQUENCE_FAILURE;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_PHASE_SEQUENCE_FAILURE \n"));
+ break;
+
+ case STAT_CCB_LENGTH_INADEQUATE:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_BAD_SRB_BLOCK_LENGTH \n"));
+ break;
+
+ case STAT_CANNOT_PROVIDE_CAPABILITY: // No equivalent SRB Flag
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_ERROR;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_ERROR \n"));
+ break;
+
+ case STAT_INVALID_LUN:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_INVALID_LUN;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_INVALID_LEN \n"));
+ break;
+
+ case STAT_INVALID_TARGET_ID:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_INVALID_TARGET_ID;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_INALID_TARGET_ID \n"));
+ break;
+
+ case STAT_FUNCTION_NOT_IMPLEMENTED:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_BAD_FUNCTION;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_BAD_FUNCTION \n"));
+ break;
+
+ // The following CAM Status flags have no SRB equivalent.
+
+ case STAT_NEXUS_NOT_ESTABLISHED:
+ case STAT_INVALID_INTIATOR_ID:
+ case STAT_INVALID_DATA_BUFFER:
+ case STAT_NO_CAM_PRESENT:
+ case STAT_GENERAL_FAILURE:
+ default:
+ Srb->SrbStatus = (UCHAR)SRB_STATUS_ERROR;
+ DebugPrint(( 2, "NCR SDMS: NCRInterrupt ...SRB_STATUS_ERROR \n"));
+ break;
+
+ } // End CAMStatus switch
+
+ // Notify the SCSI Port driver that this SRB is complete.
+ ScsiPortNotification( RequestComplete,
+ DeviceExtension,
+ Srb );
+
+ ScsiPortNotification( NextRequest,
+ DeviceExtension,
+ NULL );
+
+ // Indicate that the interrupt was ours.
+ return TRUE;
+
+} // End NCRInterrupt
+
+#else // not i386
+
+ULONG
+DriverEntry(
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ )
+{
+ return SP_RETURN_NOT_FOUND;
+} // DriverEntry
+
+#endif // i386
+