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

📄 scsiport.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
                LunInfo = Ptr;
            }

            ExFreePool(DeviceExtension->BusesConfig->BusScanInfo[Bus]);
        }

        ExFreePool(DeviceExtension->BusesConfig);
    }

    /* Free PortConfig */
    if (DeviceExtension->PortConfig)
        ExFreePool(DeviceExtension->PortConfig);

    /* Free LUNs*/
    for(Lun = 0; Lun < LUS_NUMBER; Lun++)
    {
        while (DeviceExtension->LunExtensionList[Lun])
        {
            Ptr = DeviceExtension->LunExtensionList[Lun];
            DeviceExtension->LunExtensionList[Lun] = DeviceExtension->LunExtensionList[Lun]->Next;

            ExFreePool(Ptr);
        }
    }

    /* Free common buffer (if it exists) */
    if (DeviceExtension->SrbExtensionBuffer != NULL &&
        DeviceExtension->CommonBufferLength != 0)
    {
            if (!DeviceExtension->AdapterObject)
            {
                ExFreePool(DeviceExtension->SrbExtensionBuffer);
            }
            else
            {
#if 0
                HalFreeCommonBuffer(DeviceExtension->AdapterObject,
                                    DeviceExtension->CommonBufferLength,
                                    DeviceExtension->PhysicalCommonBuffer,
                                    DeviceExtension->SrbExtensionBuffer,
                                    FALSE);
#endif
            }
    }

    /* Free SRB info */
    if (DeviceExtension->SrbInfo != NULL)
        ExFreePool(DeviceExtension->SrbInfo);

    /* Unmap mapped addresses */
    while (DeviceExtension->MappedAddressList != NULL)
    {
        MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
                       DeviceExtension->MappedAddressList->NumberOfBytes);

        Ptr = DeviceExtension->MappedAddressList;
        DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;

        ExFreePool(Ptr);
    }

    /* Finally delete the device object */
    DPRINT("Deleting device %p\n", DeviceExtension->DeviceObject);
    IoDeleteDevice(DeviceExtension->DeviceObject);
}



/*
 * @unimplemented
 */
VOID STDCALL
ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
		      IN PSCSI_REQUEST_BLOCK Srb,
		      IN PVOID LogicalAddress,
		      IN ULONG Length)
{
  DPRINT1("ScsiPortIoMapTransfer()\n");
  UNIMPLEMENTED;
}


/*
 * @unimplemented
 */
VOID STDCALL
ScsiPortLogError(IN PVOID HwDeviceExtension,
		 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
		 IN UCHAR PathId,
		 IN UCHAR TargetId,
		 IN UCHAR Lun,
		 IN ULONG ErrorCode,
		 IN ULONG UniqueId)
{
  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;

  DPRINT1("ScsiPortLogError() called\n");

  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
				      SCSI_PORT_DEVICE_EXTENSION,
				      MiniPortDeviceExtension);


  DPRINT("ScsiPortLogError() done\n");
}


/*
 * @implemented
 */
VOID STDCALL
ScsiPortMoveMemory(OUT PVOID Destination,
		   IN PVOID Source,
		   IN ULONG Length)
{
  RtlMoveMemory(Destination,
		Source,
		Length);
}


/*
 * @implemented
 */
VOID
ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
		     IN PVOID HwDeviceExtension,
		     ...)
{
    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
    va_list ap;

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

    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
        SCSI_PORT_DEVICE_EXTENSION,
        MiniPortDeviceExtension);

    DPRINT("DeviceExtension %p\n", DeviceExtension);

    va_start(ap, HwDeviceExtension);

    switch (NotificationType)
    {
    case RequestComplete:
        {
            PSCSI_REQUEST_BLOCK Srb;
            PSCSI_REQUEST_BLOCK_INFO SrbData;

            Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);

            DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);

            /* Make sure Srb is allright */
            ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING);
            ASSERT(Srb->Function != SRB_FUNCTION_EXECUTE_SCSI || Srb->SrbStatus != SRB_STATUS_SUCCESS || Srb->ScsiStatus == SCSISTAT_GOOD);

            if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
            {
                /* It's been already completed */
                va_end(ap);
                return;
            }

            /* It's not active anymore */
            Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;

            if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
            {
                /* TODO: Treat it specially */
                ASSERT(FALSE);
            }
            else
            {
                /* Get the SRB data */
                SrbData = SpiGetSrbData(DeviceExtension,
                                        Srb->PathId,
                                        Srb->TargetId,
                                        Srb->Lun,
                                        Srb->QueueTag);

                /* Make sure there are no CompletedRequests and there is a Srb */
                ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL);

                /* If it's a read/write request, make sure it has data inside it */
                if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
                    ((Srb->Cdb[0] == SCSIOP_READ) || (Srb->Cdb[0] == SCSIOP_WRITE)))
                {
                        ASSERT(Srb->DataTransferLength);
                }

                SrbData->CompletedRequests = DeviceExtension->InterruptData.CompletedRequests;
                DeviceExtension->InterruptData.CompletedRequests = SrbData;
            }
        }
        break;

    case NextRequest:
        DPRINT("Notify: NextRequest\n");
        DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
        break;

      case NextLuRequest:
	{
	  UCHAR PathId;
	  UCHAR TargetId;
	  UCHAR Lun;

	  PathId = (UCHAR) va_arg (ap, int);
	  TargetId = (UCHAR) va_arg (ap, int);
	  Lun = (UCHAR) va_arg (ap, int);

	  DPRINT1 ("Notify: NextLuRequest(PathId %u  TargetId %u  Lun %u)\n",
		   PathId, TargetId, Lun);
	  /* FIXME: Implement it! */
          ASSERT(FALSE);

//	  DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
//	  DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;

	  /* Hack! */
//	  DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
	}
	break;

      case ResetDetected:
	DPRINT1("Notify: ResetDetected\n");
	/* FIXME: ??? */
	break;

      default:
	DPRINT1 ("Unsupported notification %lu\n", NotificationType);
	break;
    }

  va_end(ap);

    /* Request a DPC after we're done with the interrupt */
    DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED;
}


/*
 * @implemented
 */
ULONG STDCALL
ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
			   IN ULONG BusDataType,
			   IN ULONG SystemIoBusNumber,
			   IN ULONG SlotNumber,
			   IN PVOID Buffer,
			   IN ULONG Offset,
			   IN ULONG Length)
{
  DPRINT("ScsiPortSetBusDataByOffset()\n");
  return(HalSetBusDataByOffset(BusDataType,
			       SystemIoBusNumber,
			       SlotNumber,
			       Buffer,
			       Offset,
			       Length));
}


/*
 * @implemented
 */
BOOLEAN STDCALL
ScsiPortValidateRange(IN PVOID HwDeviceExtension,
		      IN INTERFACE_TYPE BusType,
		      IN ULONG SystemIoBusNumber,
		      IN SCSI_PHYSICAL_ADDRESS IoAddress,
		      IN ULONG NumberOfBytes,
		      IN BOOLEAN InIoSpace)
{
  DPRINT("ScsiPortValidateRange()\n");
  return(TRUE);
}


/* INTERNAL FUNCTIONS ********************************************************/

static VOID
SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
                    IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
                    IN PPORT_CONFIGURATION_INFORMATION PortConfig)
{
    PACCESS_RANGE AccessRange;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData;
    ULONG RangeNumber;
    ULONG Index;

    RangeNumber = 0;

    /* Loop through all entries */
    for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++)
    {
        PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index];

        switch (PartialData->Type)
        {
        case CmResourceTypePort:
            /* Copy access ranges */
            if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
            {
                AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);

                AccessRange->RangeStart = PartialData->u.Port.Start;
                AccessRange->RangeLength = PartialData->u.Port.Length;

                AccessRange->RangeInMemory = FALSE;
                RangeNumber++;
            }
            break;

        case CmResourceTypeMemory:
            /* Copy access ranges */
            if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
            {
                AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);

                AccessRange->RangeStart = PartialData->u.Memory.Start;
                AccessRange->RangeLength = PartialData->u.Memory.Length;

                AccessRange->RangeInMemory = TRUE;
                RangeNumber++;
            }
            break;

        case CmResourceTypeInterrupt:
            /* Copy interrupt data */
            PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level;
            PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector;

            /* Set interrupt mode accordingly to the resource */
            if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
            {
                PortConfig->InterruptMode = Latched;
            }
            else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
            {
                PortConfig->InterruptMode = LevelSensitive;
            }
            break;

        case CmResourceTypeDma:
            PortConfig->DmaChannel = PartialData->u.Dma.Channel;
            PortConfig->DmaPort = PartialData->u.Dma.Port;
            break;
        }
    }
}

static PCM_RESOURCE_LIST
SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
                    PPORT_CONFIGURATION_INFORMATION PortConfig)
{
    PCONFIGURATION_INFORMATION ConfigInfo;
    PCM_RESOURCE_LIST ResourceList;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
    PACCESS_RANGE AccessRange;
    BOOLEAN Dma;
    ULONG ListLength = 0, i, FullSize;
    ULONG Interrupt;

    /* Get current Atdisk usage from the system */
    ConfigInfo = IoGetConfigurationInformation();

    if (PortConfig->AtdiskPrimaryClaimed)
        ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;

    if (PortConfig->AtdiskSecondaryClaimed)
        ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE;

    /* Do we use DMA? */
    if (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE ||
        PortConfig->DmaPort != SP_UNINITIALIZED_VALUE)
    {
        Dma = TRUE;
        ListLength++;
    }
    else
    {
        Dma = FALSE;
    }

    /* How many interrupts to we have? */
    if (DeviceExtension->HwInterrupt == NULL ||
        (PortConfig->BusInterruptLevel == 0 &&
        PortConfig->BusInterruptVector == 0))
    {
        Interrupt = 0;
    }
    else
    {
        Interrupt = 1;
        ListLength++;
    }

    if (DeviceExtension->HwInterrupt != NULL &&
   

⌨️ 快捷键说明

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