⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsiport.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
		      IN BOOLEAN InIoSpace)
{
    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
    PHYSICAL_ADDRESS TranslatedAddress;
    PMAPPED_ADDRESS DeviceBase;
    ULONG AddressSpace;
    PVOID MappedAddress;

    //DPRINT ("ScsiPortGetDeviceBase() called\n");

    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
                                        SCSI_PORT_DEVICE_EXTENSION,
                                        MiniPortDeviceExtension);

    AddressSpace = (ULONG)InIoSpace;
    if (HalTranslateBusAddress(BusType,
                               SystemIoBusNumber,
                               IoAddress,
                               &AddressSpace,
                               &TranslatedAddress) == FALSE)
    {
        return NULL;
    }

    /* i/o space */
    if (AddressSpace != 0)
        return((PVOID)TranslatedAddress.u.LowPart);

    MappedAddress = MmMapIoSpace(TranslatedAddress,
                                 NumberOfBytes,
                                 FALSE);

    DeviceBase = ExAllocatePoolWithTag(NonPagedPool,
                                sizeof(MAPPED_ADDRESS), TAG_SCSIPORT);

    if (DeviceBase == NULL)
        return MappedAddress;

    DeviceBase->MappedAddress = MappedAddress;
    DeviceBase->NumberOfBytes = NumberOfBytes;
    DeviceBase->IoAddress = IoAddress;
    DeviceBase->BusNumber = SystemIoBusNumber;

    /* Link it to the Device Extension list */
    DeviceBase->NextMappedAddress = DeviceExtension->MappedAddressList;
    DeviceExtension->MappedAddressList = DeviceBase;

    return MappedAddress;
}

/*
 * @implemented
 */
PVOID STDCALL
ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
		       IN UCHAR PathId,
		       IN UCHAR TargetId,
		       IN UCHAR Lun)
{
    UNIMPLEMENTED;
#if 0
  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
  PSCSI_PORT_LUN_EXTENSION LunExtension;
  PLIST_ENTRY Entry;

  DPRINT("ScsiPortGetLogicalUnit() called\n");

  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
				      SCSI_PORT_DEVICE_EXTENSION,
				      MiniPortDeviceExtension);
  if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
    return NULL;

  Entry = DeviceExtension->LunExtensionListHead.Flink;
  while (Entry != &DeviceExtension->LunExtensionListHead)
    {
      LunExtension = CONTAINING_RECORD(Entry,
				       SCSI_PORT_LUN_EXTENSION,
				       List);
      if (LunExtension->PathId == PathId &&
	  LunExtension->TargetId == TargetId &&
	  LunExtension->Lun == Lun)
	{
	  return (PVOID)&LunExtension->MiniportLunExtension;
	}

      Entry = Entry->Flink;
    }
#endif
  return NULL;
}


/*
 * @unimplemented
 */
SCSI_PHYSICAL_ADDRESS STDCALL
ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
                           IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
                           IN PVOID VirtualAddress,
                           OUT ULONG *Length)
{
    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
    SCSI_PHYSICAL_ADDRESS PhysicalAddress;
    ULONG BufferLength = 0;
    ULONG Offset;
    PSCSI_SG_ADDRESS SGList;
    PSCSI_REQUEST_BLOCK_INFO SrbInfo;

    DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
        HwDeviceExtension, Srb, VirtualAddress, Length);

    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
                                        SCSI_PORT_DEVICE_EXTENSION,
                                        MiniPortDeviceExtension);

    if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
    {
        /* Simply look it up in the allocated common buffer */
        Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;

        BufferLength = DeviceExtension->CommonBufferLength - Offset;
        PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
    }
    else if (DeviceExtension->MapRegisters)
    {
        /* Scatter-gather list must be used */
        SrbInfo = SpiGetSrbData(DeviceExtension,
                               Srb->PathId,
                               Srb->TargetId,
                               Srb->Lun,
                               Srb->QueueTag);

        SGList = SrbInfo->ScatterGather;

        /* Find needed item in the SG list */
        Offset = (PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer;
        while (Offset >= SGList->Length)
        {
            Offset -= SGList->Length;
            SGList++;
        }

        /* We're done, store length and physical address */
        BufferLength = SGList->Length - Offset;
        PhysicalAddress.QuadPart = SGList->PhysicalAddress.QuadPart + Offset;
    }
    else
    {
        /* Nothing */
        *Length = 0;
        PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
    }

    *Length = BufferLength;
    return PhysicalAddress;
}


/*
 * @unimplemented
 */
PSCSI_REQUEST_BLOCK STDCALL
ScsiPortGetSrb(IN PVOID DeviceExtension,
	       IN UCHAR PathId,
	       IN UCHAR TargetId,
	       IN UCHAR Lun,
	       IN LONG QueueTag)
{
  DPRINT1("ScsiPortGetSrb() unimplemented\n");
  UNIMPLEMENTED;
  return NULL;
}


/*
 * @implemented
 */
PVOID STDCALL
ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
			     IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
			     IN ULONG NumberOfBytes)
{
    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
    DEVICE_DESCRIPTION DeviceDescription;
    ULONG MapRegistersCount;
    NTSTATUS Status;

    DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
        HwDeviceExtension, ConfigInfo, NumberOfBytes);

    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
                                        SCSI_PORT_DEVICE_EXTENSION,
                                        MiniPortDeviceExtension);

    /* Check for allocated common DMA buffer */
    if (DeviceExtension->SrbExtensionBuffer != NULL)
    {
        DPRINT1("The HBA has already got a common DMA buffer!\n");
        return NULL;
    }

    /* Check for DMA adapter object */
    if (DeviceExtension->AdapterObject == NULL)
    {
        /* Initialize DMA adapter description */
        RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));

        DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
        DeviceDescription.Master = ConfigInfo->Master;
        DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
        DeviceDescription.DemandMode = ConfigInfo->DemandMode;
        DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
        DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
        DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
        DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
        DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
        DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
        DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
        DeviceDescription.DmaPort = ConfigInfo->DmaPort;

        /* Get a DMA adapter object */
        DeviceExtension->AdapterObject =
            HalGetAdapter(&DeviceDescription, &MapRegistersCount);

        /* Fail in case of error */
        if (DeviceExtension->AdapterObject == NULL)
        {
            DPRINT1("HalGetAdapter() failed\n");
            return NULL;
        }

        /* Set number of physical breaks */
        if (ConfigInfo->NumberOfPhysicalBreaks != 0 &&
            MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks)
        {
            DeviceExtension->PortCapabilities.MaximumPhysicalPages =
                ConfigInfo->NumberOfPhysicalBreaks;
        }
        else
        {
            DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount;
        }
    }

    /* Update auto request sense feature */
    DeviceExtension->SupportsAutoSense = ConfigInfo->AutoRequestSense;

    /* Update Srb extension size */
    if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize)
        DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize;

    /* Update Srb extension alloc flag */
    if (ConfigInfo->AutoRequestSense || DeviceExtension->SrbExtensionSize)
        DeviceExtension->NeedSrbExtensionAlloc = TRUE;

    /* Allocate a common DMA buffer */
    Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status);
        return NULL;
    }

    return DeviceExtension->NonCachedExtension;
}

static NTSTATUS
SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize)
{
    PVOID *SrbExtension, CommonBuffer;
    ULONG CommonBufferLength, BufSize;

    /* If size is 0, set it to 16 */
    if (!DeviceExtension->SrbExtensionSize)
        DeviceExtension->SrbExtensionSize = 16;

    /* Calculate size */
    BufSize = DeviceExtension->SrbExtensionSize;

    /* Add autosense data size if needed */
    if (DeviceExtension->SupportsAutoSense)
        BufSize += sizeof(SENSE_DATA);


    /* Round it */
    BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);

    /* Sum up into the total common buffer length, and round it to page size */
    CommonBufferLength =
        ROUND_TO_PAGES(NonCachedSize + BufSize * DeviceExtension->RequestsNumber);

    /* Allocate it */
    if (!DeviceExtension->AdapterObject)
    {
        /* From nonpaged pool if there is no DMA */
        CommonBuffer = ExAllocatePoolWithTag(NonPagedPool, CommonBufferLength, TAG_SCSIPORT);
    }
    else
    {
        /* Perform a full request since we have a DMA adapter*/
        CommonBuffer = HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
            CommonBufferLength,
            &DeviceExtension->PhysicalAddress,
            FALSE );
    }

    /* Fail in case of error */
    if (!CommonBuffer)
        return STATUS_INSUFFICIENT_RESOURCES;

    /* Zero it */
    RtlZeroMemory(CommonBuffer, CommonBufferLength);

    /* Store its size in Device Extension */
    DeviceExtension->CommonBufferLength = CommonBufferLength;

    /* SrbExtension buffer is located at the beginning of the buffer */
    DeviceExtension->SrbExtensionBuffer = CommonBuffer;

    /* Non-cached extension buffer is located at the end of
       the common buffer */
    if (NonCachedSize)
    {
        CommonBufferLength -=  NonCachedSize;
        DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength;
    }
    else
    {
        DeviceExtension->NonCachedExtension = NULL;
    }

    if (DeviceExtension->NeedSrbExtensionAlloc)
    {
        /* Look up how many SRB data structures we need */
        DeviceExtension->SrbDataCount = CommonBufferLength / BufSize;

        /* Initialize the free SRB extensions list */
        SrbExtension = (PVOID *)CommonBuffer;
        DeviceExtension->FreeSrbExtensions = SrbExtension;

        /* Fill the remainding pointers (if we have more than 1 SRB) */
        while (CommonBufferLength >= 2 * BufSize)
        {
            *SrbExtension = (PVOID*)((PCHAR)SrbExtension + BufSize);
            SrbExtension = *SrbExtension;

            CommonBufferLength -= BufSize;
        }
    }

    return STATUS_SUCCESS;
}



/*
 * @implemented
 */
PVOID STDCALL
ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
                          IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
{
    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
    ULONG Offset;

    DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
        HwDeviceExtension, PhysicalAddress.QuadPart);

    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
                                        SCSI_PORT_DEVICE_EXTENSION,
                                        MiniPortDeviceExtension);

    if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
        return NULL;

    Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);

    if (Offset >= DeviceExtension->CommonBufferLength)
        return NULL;

    return (PVOID)((ULONG_PTR)DeviceExtension->SrbExtensionBuffer + Offset);
}

static VOID
SpiInitOpenKeys(PCONFIGURATION_INFO ConfigInfo, PUNICODE_STRING RegistryPath)
{
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING KeyName;
    NTSTATUS Status;

    /* Open the service key */
    InitializeObjectAttributes(&ObjectAttributes,
                               RegistryPath,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);

    Status = ZwOpenKey(&ConfigInfo->ServiceKey,
                       KEY_READ,
                       &ObjectAttributes);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -