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