Ejemplo n.º 1
0
PVOID
ScsiPortGetVirtualAddress(
    IN PVOID HwDeviceExtension,
    IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)

/*++

Routine Description:

    This routine is returns a virtual address associated with a
    physical address, if the physical address was obtained by a
    call to ScsiPortGetPhysicalAddress.

Arguments:

    PhysicalAddress

Return Value:

    Virtual address

--*/

{
    PADAPTER_EXTENSION deviceExtension = GET_FDO_EXTENSION(HwDeviceExtension);
    PVOID address;
    ULONG smallphysicalBase;
    ULONG smallAddress;

    smallAddress = ScsiPortConvertPhysicalAddressToUlong(PhysicalAddress);

    smallphysicalBase = ScsiPortConvertPhysicalAddressToUlong(deviceExtension->PhysicalCommonBuffer);

    //
    // Check that the physical address is within the proper range.
    //

    if (smallAddress < smallphysicalBase ||
            smallAddress >= smallphysicalBase + deviceExtension->CommonBufferSize) {

        //
        // This is a bugous physical address return back NULL.
        //

        return(NULL);

    }

    address = smallAddress - smallphysicalBase +
              (PUCHAR) deviceExtension->SrbExtensionBuffer;

    return address;

} // end ScsiPortGetVirtualAddress()
Ejemplo n.º 2
0
void
GetXferSegment (const ADAPTER_PTR HA, IO_REQ_PTR Req, SegmentDescr *SGDescr,
    U32 Offset, BOOLEAN DemandPhysicalAddr)
{

  TRACE(4, ("GetXferSegment(): Offset = %d\n", Offset));
  TRACE(4, ("GetXferSegment(): Non-S/G request, ReqDataCount = %d\n", ReqDataCount(Req)));

  if (Offset < ReqDataCount(Req)) {              // Make sure we don't over run

    SGDescr->SegmentLength = ReqDataCount(Req) - Offset;
    SGDescr->SegmentPtr = (U32)ReqDataPtr(Req) + Offset;

  } else {

    SGDescr->SegmentLength = 0;               // No data left
    SGDescr->SegmentPtr = 0;
    BreakPoint(HA);

  }
  TRACE(4, ("GetXferSegment(): %d bytes remain in segment at %08x (offset %d)\n",
      SGDescr->SegmentLength, SGDescr->SegmentPtr, Offset));

  SGDescr->Flags.IsPhysical = FALSE;

  if (DemandPhysicalAddr) {

    if (ReqState(Req).InternalRequest) {

      TRACE(5, ("GetXferSegment(): Mapping internal request\n"));
      MapToPhysical(HA, SGDescr);

    } else {

      ULONG Size = SGDescr->SegmentLength;

      SGDescr->SegmentPtr = (U32)ScsiPortConvertPhysicalAddressToUlong(
	  ScsiPortGetPhysicalAddress(HA, Req,
	  (PVOID)((U32)ReqDataPtr(Req) + Offset) /*(SGDescr->SegmentPtr)*/,
	  &Size));

      if (Size < SGDescr->SegmentLength)
	SGDescr->SegmentLength = Size;

      DEBUG(5, {
	if (SGDescr->SegmentLength < (ReqDataCount(Req) - Offset))
	  DPrintf("Segment length is %d out of %d\n",
	      SGDescr->SegmentLength, ReqDataCount(Req) - Offset);});
	
      SGDescr->Flags.IsPhysical = TRUE;

      TRACE(5, ("GetXferSegment(): Mapped to 0x%lx for %lu bytes\n",
	  SGDescr->SegmentPtr, Size));

    }
  }
Ejemplo n.º 3
0
ULONG
FindAdapter (IN PVOID HAObject, IN PVOID PContext, IN PVOID BusInfo,
    IN PCHAR ArgString, IN OUT PPORT_CONFIGURATION_INFORMATION Config,
    OUT PBOOLEAN PAgain)
{
  ADAPTER_PTR HA = HAObject;

  TRACE(3, ("FindAdapter(): Adapter ptr = %x, Config ptr = %x, Len = 0x%x\n", HA, Config, sizeof(struct _PORT_CONFIGURATION_INFORMATION)));

  /* Hunt down and register the adapters in the system: */
  HA->IOBaseAddr = (U16)ScsiPortConvertPhysicalAddressToUlong(
      (*Config->AccessRanges)[0].RangeStart);

  if (Adapter_Init(HA, (unsigned *)PContext)) {

    // Set Again TRUE, only if we're being called with a non-sepcific access range
    *PAgain = ScsiPortConvertPhysicalAddressToUlong(
	(*Config->AccessRanges)[0].RangeStart) == 0;

    Config->BusInterruptLevel = HA->IRQNumber;

    Config->ScatterGather = HA->Supports.ScatterGather;
    Config->MaximumTransferLength =  0x400000;
    Config->NumberOfPhysicalBreaks = 0x400;
//    Config->NumberOfPhysicalBreaks = HA->MaxSGListLength;

    (*Config->AccessRanges)[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(HA->IOBaseAddr);
    (*Config->AccessRanges)[0].RangeLength = HA->IOAddrLen;
    (*Config->AccessRanges)[0].RangeInMemory = FALSE;

    Config->NumberOfBuses = 1;
    Config->InitiatorBusId[0] = HA->SCSI_ID;
    Config->Master = (HA->Physical.Xfermode == XM_MASTER) || (HA->Physical.Xfermode == XM_MASTER24);
    Config->Dma32BitAddresses = (HA->Physical.Xfermode == XM_MASTER);
    Config->DemandMode = (HA->Physical.Xfermode == XM_DMAD);
    Config->NeedPhysicalAddresses = XM_PHYSICAL(HA->Physical.Xfermode);
    Config->MapBuffers = TRUE;
    Config->CachesData = HA->Supports.Caching;
    Config->AlignmentMask = 0x3;

    Config->TaggedQueuing = FALSE;

#if defined(AUTOSENSE)
    Config->AutoRequestSense = TRUE;
#else
    Config->AutoRequestSense = FALSE;
#endif

    Config->MultipleRequestPerLu = Config->AutoRequestSense;

    Config->ReceiveEvent = FALSE;

    HA->Ext = ScsiPortGetUncachedExtension(HA, Config, sizeof(AdapterExtension));

    return SP_RETURN_FOUND;

  } else {

    *PAgain = FALSE;
    return SP_RETURN_NOT_FOUND;

  }
}
Ejemplo n.º 4
0
ULONG
Wd7000ExFindAdapter(
    IN PVOID HwDeviceExtension,
    IN PVOID Context,
    IN PVOID BusInformation,
    IN PCHAR ArgumentString,
    IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
    OUT PBOOLEAN Again
    )

/*++

Routine Description:

    This function is called by the OS-specific port driver after
    the necessary storage has been allocated, to gather information
    about the adapter's configuration.

Arguments:

    HwDeviceExtension - HBA miniport driver's adapter data storage
    ConfigInfo - Configuration information structure describing HBA

Return Value:

    TRUE if adapter present in system

--*/

{
    PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
    PEISA_CONTROLLER eisaController;
    PULONG adapterCount = Context;
    PNONCACHED_EXTENSION ncExtension;
    ULONG eisaSlotNumber;
    PICB icb;
    PADAPTER_INQUIRY adapterInquiry;
    ULONG physicalIcb;
    ULONG i;
    ULONG length;
    UCHAR status;

    //
    // Check to see if adapter present in system.
    //
    if (!AdapterPresent(deviceExtension, ConfigInfo, Context)) {
        DebugPrint((1,"Wd7000EX: SCSI adapter not present\n"));
        *Again = FALSE;
        return SP_RETURN_NOT_FOUND;
    }

    //
    // There is still more to look at.
    //

    *Again = FALSE;

    //
    // Fill in the access array information only if there are no
    // default parameters already there.
    //
    if (ScsiPortConvertPhysicalAddressToUlong(
            (*ConfigInfo->AccessRanges)[0].RangeStart) == 0) {

        *Again = TRUE;
        (*ConfigInfo->AccessRanges)[0].RangeStart =
            ScsiPortConvertUlongToPhysicalAddress(0x1000 * (*((PULONG) Context)) + EISA_ADDRESS_BASE);
        (*ConfigInfo->AccessRanges)[0].RangeLength = sizeof(EISA_CONTROLLER);
        (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;

        //
        // Indicate maximum transfer length in bytes.
        //
        ConfigInfo->MaximumTransferLength = MAXIMUM_TRANSFER_SIZE;

        //
        // Maximum number of physical segments is 32.
        //
        ConfigInfo->NumberOfPhysicalBreaks = MAXIMUM_SDL_SIZE;

        //
        // Set the configuration parameters for this card.
        //
    
        ConfigInfo->NumberOfBuses = 1;
        deviceExtension->NumberOfBuses = 1;
        ConfigInfo->ScatterGather = TRUE;
        ConfigInfo->Master = TRUE;
    
        //
        // Get a noncached extension for an adapter inquiry command.
        //
    
        ncExtension = ScsiPortGetUncachedExtension(
                                    deviceExtension,
                                    ConfigInfo,
                                    sizeof(NONCACHED_EXTENSION));
    
        if (ncExtension == NULL) {
    
            //
            // Log error.
            //
    
            ScsiPortLogError(
                deviceExtension,
                NULL,
                0,
                0,
                0,
                SP_INTERNAL_ADAPTER_ERROR,
                6 << 16
                );
    
            return SP_RETURN_ERROR;
        }
    
        length = sizeof(NONCACHED_EXTENSION);
    
        //
        // Convert virtual to physical address.
        //
    
        physicalIcb = ScsiPortConvertPhysicalAddressToUlong(
            ScsiPortGetPhysicalAddress(deviceExtension,
                                     NULL,
                                     ncExtension,
                                     &length));
    
        //
        // Initialize the pointers.
        //
    
        icb = &ncExtension->Icb;
        adapterInquiry = &ncExtension->AdapterInquiry;
    
        //
        // Create ICB for Adapter Inquiry Command.
        //
    
        icb->IcbFlags = 0;
        icb->CompletionStatus = 0;
        icb->Reserved = 0;
        icb->DataBufferAddress = ScsiPortConvertPhysicalAddressToUlong(
            ScsiPortGetPhysicalAddress(
                deviceExtension,
                NULL,
                adapterInquiry,
                &length));
    
        icb->TransferCount = sizeof(ADAPTER_INQUIRY);
    
        icb->OpCode = ADAPTER_INQUIRY_COMMAND;
    
        //
        // Get ICB physical address.
        //
    
        physicalIcb = ScsiPortConvertPhysicalAddressToUlong(
            ScsiPortGetPhysicalAddress(
                deviceExtension,
                NULL,
                icb,
                &length));
    
        //
        // Disable system interrupts.
        //
    
        ScsiPortWritePortUchar(&deviceExtension->EisaController->SystemInterruptEnable,
            SYSTEM_INTERRUPTS_DISABLE);
    
        //
        // Write ICB physical address and command to mailbox.
        //
    
        SendCommand(PROCESS_ICB,
                physicalIcb,
                deviceExtension);
    
        //
        // Poll for ICB completion.
        //
    
        i = 0;
        while ((status =
            ScsiPortReadPortUchar(
            &deviceExtension->EisaController->ResponseRegister)) == 0) {
    
            i++;
    
            if (i > 100000) {
    
                break;
            }
    
            ScsiPortStallExecution(10);
        }
    
        if (status == 0) {
    
            //
            // The request timed out. Log an error and return.
            //
    
            ScsiPortLogError(
                deviceExtension,
                NULL,
                0,
                0,
                0,
                SP_INTERNAL_ADAPTER_ERROR,
                7 << 16
                );
            return SP_RETURN_ERROR;
        }
    
        DebugPrint((1, "Wd7000ExFindAdapter: Get configuration request time = %d.\n", i * 10));
    
        //
        // Acknowledge interrupt.
        //
    
        ScsiPortWritePortUchar(&deviceExtension->EisaController->ResponseRegister, 0xFF);
    
        //
        // Enable system interrupts.
        //
    
        ScsiPortWritePortUchar(&deviceExtension->EisaController->SystemInterruptEnable,
            SYSTEM_INTERRUPTS_ENABLE);
    
        //
        // Check returned status for success.
        //
    
        if (status != COMPLETE_SUCCESS) {
    
            //
            // Give up.
            //
    
            DebugPrint((1,"Wd7000Ex: Response register %x\n", status));
            DebugPrint((1,"Wd7000Ex: Adapter inquiry failed\n"));
    
            //
            // Log error.
            //
    
            ScsiPortLogError(
                deviceExtension,
                NULL,
                0,
                0,
                0,
                SP_INTERNAL_ADAPTER_ERROR,
                8 << 16
                );
    
            return SP_RETURN_ERROR;
        }
    
        //
        // NOTE: Delay here. I don't understand this latency between
        //          when the device interrupts and the status of the ICB
        //          is success and when the data is actually available in
        //          the buffer.
        //
    
        ScsiPortStallExecution(300);
    
        if (adapterInquiry->AdapterInformation & DUAL_CHANNEL) {
    
            //
            // There are two buses on the adapter.
            //
    
            ConfigInfo->InitiatorBusId[1] =
                (adapterInquiry->ChannelInformation >> 4) & BUS_ID_MASK;
            ConfigInfo->NumberOfBuses = 2;
            deviceExtension->NumberOfBuses = 2;
        }
Ejemplo n.º 5
0
BOOLEAN
AdapterPresent(
    IN PVOID HwDeviceExtension,
    IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
    IN OUT PULONG AdapterCount
    )

/*++

Routine Description:

    Determine if WD7000EX SCSI adapter is installed in system
    by reading the EISA board configuration registers for each
    EISA slot looking for the correct signature.

Arguments:

    HwDeviceExtension - HBA miniport driver's adapter data storage

    ConfigInfo - Supplies the configuration information stucture.  If an
        adapter is found the access range is update.

    AdapterCount - Supplies the count of slots which have already been checked.

Return Value:

    TRUE if adapter present.

--*/

{
    PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
    ULONG eisaSlotNumber;
    PEISA_CONTROLLER eisaController;

    //
    // Check to see if adapter present in system.
    //


    for (eisaSlotNumber=*AdapterCount + 1; eisaSlotNumber<MAXIMUM_EISA_SLOTS; eisaSlotNumber++) {

        //
        // Update the adapter count.
        //

        (*AdapterCount)++;

        //
        // Get the system address for this card.  The card uses I/O space.
        // If ConfigInfo already has default information about this
        // controller, use it.  If not, then we derive our own.  This
        // is for Chicago compatibility.
        //
        if (ScsiPortConvertPhysicalAddressToUlong(
                (*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {

            eisaController = ScsiPortGetDeviceBase(
                                deviceExtension,
                                ConfigInfo->AdapterInterfaceType,
                                ConfigInfo->SystemIoBusNumber,
                                (*ConfigInfo->AccessRanges)[0].RangeStart,
                                (*ConfigInfo->AccessRanges)[0].RangeLength,
                                (BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
        } else {

            eisaController = ScsiPortGetDeviceBase(
                                deviceExtension,
                                ConfigInfo->AdapterInterfaceType,
                                ConfigInfo->SystemIoBusNumber,
                                ScsiPortConvertUlongToPhysicalAddress(0x1000 * eisaSlotNumber),
                                0x1000,
                                TRUE);
        }

        eisaController =
            (PEISA_CONTROLLER)((PUCHAR)eisaController + EISA_ADDRESS_BASE);

        if ((ScsiPortReadPortUchar(&eisaController->BoardId[0]) == 0x5C) &&
            (ScsiPortReadPortUchar(&eisaController->BoardId[1]) == 0x83) &&
            (ScsiPortReadPortUchar(&eisaController->BoardId[2]) == 0x20)) {

            deviceExtension->EisaController = eisaController;

            return TRUE;
        }

        //
        // The card is not here so clean up.
        //

        ScsiPortFreeDeviceBase(deviceExtension,
                               (PUCHAR)eisaController - EISA_ADDRESS_BASE);

    } // end for (eisaSlotNumber ...

    //
    // Clear the adapter count for the next bus.
    //

    *AdapterCount = 0;

    return FALSE;

} // end AdapterPresent()