NT4/private/ntos/miniport/scsiwdl/ncrcam/ncrsdms.c
2020-09-30 17:12:29 +02:00

1641 lines
49 KiB
C

/////////////////////////////////////////////////////////////////////////////
//
// 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