scsiport.c

来自「一个类似windows」· C语言 代码 · 共 2,184 行 · 第 1/5 页

C
2,184
字号
      InitializeListHead (&DeviceExtension->PendingIrpListHead);
      DeviceExtension->NextIrp = NULL;
      DeviceExtension->PendingIrpCount = 0;
      DeviceExtension->ActiveIrpCount = 0;

      /* Initialize LUN-Extension list */
      InitializeListHead (&DeviceExtension->LunExtensionListHead);

      /* Initialize the spin lock in the controller extension */
      KeInitializeSpinLock (&DeviceExtension->Lock);

      /* Initialize the DPC object */
      IoInitializeDpcRequest (PortDeviceObject,
			      ScsiPortDpc);

      /* Initialize the device timer */
      DeviceExtension->TimerState = IDETimerIdle;
      DeviceExtension->TimerCount = 0;
      IoInitializeTimer (PortDeviceObject,
			 ScsiPortIoTimer,
			 DeviceExtension);

      /* Allocate and initialize port configuration info */
      DeviceExtension->PortConfig = ExAllocatePool (NonPagedPool,
						    PortConfigSize);
      if (DeviceExtension->PortConfig == NULL)
	{
	  Status = STATUS_INSUFFICIENT_RESOURCES;
	  goto ByeBye;
	}
      RtlZeroMemory (DeviceExtension->PortConfig,
		     PortConfigSize);

      PortConfig = DeviceExtension->PortConfig;
      PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
      PortConfig->SystemIoBusNumber = BusNumber;
      PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
      PortConfig->InterruptMode =
	(PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
      PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
      PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
      PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
      PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
      PortConfig->DmaWidth = 0;
      PortConfig->DmaSpeed = Compatible;
      PortConfig->AlignmentMask = 0;
      PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
      PortConfig->NumberOfBuses = 0;

      for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
	PortConfig->InitiatorBusId[i] = 255;

      PortConfig->ScatterGather = FALSE;
      PortConfig->Master = FALSE;
      PortConfig->CachesData = FALSE;
      PortConfig->AdapterScansDown = FALSE;
      PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
      PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
      PortConfig->Dma32BitAddresses = FALSE;
      PortConfig->DemandMode = FALSE;
      PortConfig->MapBuffers = HwInitializationData->MapBuffers;
      PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
      PortConfig->TaggedQueuing = HwInitializationData->TaggedQueuing;
      PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
      PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
      PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
      PortConfig->RealModeInitialized = FALSE;
      PortConfig->BufferAccessScsiPortControlled = FALSE;
      PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
//      PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;

      PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
      PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;

      PortConfig->AccessRanges = (ACCESS_RANGE(*)[])(PortConfig + 1);

      /* Search for matching PCI device */
      if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
	  (HwInitializationData->VendorIdLength > 0) &&
	  (HwInitializationData->VendorId != NULL) &&
	  (HwInitializationData->DeviceIdLength > 0) &&
	  (HwInitializationData->DeviceId != NULL))
	{
	  /* Get PCI device data */
	  DPRINT("VendorId '%.*s'  DeviceId '%.*s'\n",
		 HwInitializationData->VendorIdLength,
		 HwInitializationData->VendorId,
		 HwInitializationData->DeviceIdLength,
		 HwInitializationData->DeviceId);

	  if (!SpiGetPciConfigData (HwInitializationData,
				    PortConfig,
				    BusNumber,
				    &SlotNumber))
	    {
	      Status = STATUS_UNSUCCESSFUL;
	      goto ByeBye;
	    }
	}

      /* Note: HwFindAdapter is called once for each bus */
      Again = FALSE;
      DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
      Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,
						     HwContext,
						     0,  /* BusInformation */
						     "", /* ArgumentString */
						     PortConfig,
						     &Again);
      DPRINT("HwFindAdapter() Result: %lu  Again: %s\n",
	     Result, (Again) ? "True" : "False");

      if (Result == SP_RETURN_FOUND)
	{
	  DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);

#if 0
	  DPRINT1("SystemIoBusNumber:               %x\n", PortConfig->SystemIoBusNumber);
	  DPRINT1("AdapterInterfaceType:            %x\n", PortConfig->AdapterInterfaceType);
	  DPRINT1("BusInterruptLevel:               %x\n", PortConfig->BusInterruptLevel);
	  DPRINT1("BusInterruptVector:              %x\n", PortConfig->BusInterruptVector);
	  DPRINT1("InterruptMode:                   %x\n", PortConfig->InterruptMode);
	  DPRINT1("MaximumTransferLength:           %x\n", PortConfig->MaximumTransferLength);
	  DPRINT1("NumberOfPhysicalBreaks:          %x\n", PortConfig->NumberOfPhysicalBreaks);
	  DPRINT1("DmaChannel:                      %x\n", PortConfig->DmaChannel);
	  DPRINT1("DmaPort:                         %d\n", PortConfig->DmaPort);
	  DPRINT1("DmaWidth:                        %d\n", PortConfig->DmaWidth);
	  DPRINT1("DmaSpeed:                        %d\n", PortConfig->DmaSpeed);
	  DPRINT1("AlignmentMask:                   %d\n", PortConfig->AlignmentMask);
	  DPRINT1("NumberOfAccessRanges:            %d\n", PortConfig->NumberOfAccessRanges);
	  DPRINT1("NumberOfBuses:                   %d\n", PortConfig->NumberOfBuses);
	  DPRINT1("ScatterGather:                   %d\n", PortConfig->ScatterGather);
	  DPRINT1("Master:                          %d\n", PortConfig->Master);
	  DPRINT1("CachesData:                      %d\n", PortConfig->CachesData);
	  DPRINT1("AdapterScansDown:                %d\n", PortConfig->AdapterScansDown);
	  DPRINT1("AtdiskPrimaryClaimed:            %d\n", PortConfig->AtdiskPrimaryClaimed);
	  DPRINT1("AtdiskSecondaryClaimed:          %d\n", PortConfig->AtdiskSecondaryClaimed);
	  DPRINT1("Dma32BitAddresses:               %d\n", PortConfig->Dma32BitAddresses);
	  DPRINT1("DemandMode:                      %d\n", PortConfig->DemandMode);
	  DPRINT1("MapBuffers:                      %d\n", PortConfig->MapBuffers);
	  DPRINT1("NeedPhysicalAddresses:           %d\n", PortConfig->NeedPhysicalAddresses);
	  DPRINT1("TaggedQueuing:                   %d\n", PortConfig->TaggedQueuing);
	  DPRINT1("AutoRequestSense:                %d\n", PortConfig->AutoRequestSense);
	  DPRINT1("MultipleRequestPerLu:            %d\n", PortConfig->MultipleRequestPerLu);
	  DPRINT1("ReceiveEvent:                    %d\n", PortConfig->ReceiveEvent);
	  DPRINT1("RealModeInitialized:             %d\n", PortConfig->RealModeInitialized);
	  DPRINT1("BufferAccessScsiPortControlled:  %d\n", PortConfig->BufferAccessScsiPortControlled);
	  DPRINT1("MaximumNumberOfTargets:          %d\n", PortConfig->MaximumNumberOfTargets);
	  DPRINT1("SlotNumber:                      %d\n", PortConfig->SlotNumber);
	  DPRINT1("BusInterruptLevel2:              %x\n", PortConfig->BusInterruptLevel2);
	  DPRINT1("BusInterruptVector2:             %x\n", PortConfig->BusInterruptVector2);
	  DPRINT1("InterruptMode2:                  %x\n", PortConfig->InterruptMode2);
	  DPRINT1("DmaChannel2:                     %d\n", PortConfig->DmaChannel2);
	  DPRINT1("DmaPort2:                        %d\n", PortConfig->DmaPort2);
	  DPRINT1("DmaWidth2:                       %d\n", PortConfig->DmaWidth2);
	  DPRINT1("DmaSpeed2:                       %d\n", PortConfig->DmaSpeed2);
	  DPRINT1("DeviceExtensionSize:             %d\n", PortConfig->DeviceExtensionSize);
	  DPRINT1("SpecificLuExtensionSize:         %d\n", PortConfig->SpecificLuExtensionSize);
	  DPRINT1("SrbExtensionSize:                %d\n", PortConfig->SrbExtensionSize);

#endif

          if (DeviceExtension->VirtualAddress == NULL && DeviceExtension->SrbExtensionSize)
	    {
	      ScsiPortGetUncachedExtension(&DeviceExtension->MiniPortDeviceExtension,
		                           PortConfig,
					   0);
	    }

	  /* Register an interrupt handler for this device */
	  MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
					    PortConfig->SystemIoBusNumber,
					    PortConfig->BusInterruptLevel,
#if 1
/*
 * FIXME:
 *   Something is wrong in our interrupt conecting code.
 *   The promise Ultra100TX driver returns 0 for BusInterruptVector
 *   and a nonzero value for BusInterruptLevel. The driver does only
 *   work with this fix.
 */
					    PortConfig->BusInterruptLevel,
#else
					    PortConfig->BusInterruptVector,
#endif
					    &Dirql,
					    &Affinity);
	  DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
	          PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
		  PortConfig->BusInterruptLevel, PortConfig->BusInterruptVector);
	  Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
				      ScsiPortIsr,
				      DeviceExtension,
				      NULL,
				      MappedIrq,
				      Dirql,
				      Dirql,
				      PortConfig->InterruptMode,
				      TRUE,
				      Affinity,
				      FALSE);
	  if (!NT_SUCCESS(Status))
	    {
	      DbgPrint("Could not connect interrupt %d\n",
		       PortConfig->BusInterruptVector);
	      goto ByeBye;
	    }

	  if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
	    {
	      DbgPrint("HwInitialize() failed!");
	      Status = STATUS_UNSUCCESSFUL;
	      goto ByeBye;
	    }

	  /* Initialize port capabilities */
	  DeviceExtension->PortCapabilities = ExAllocatePool(NonPagedPool,
							     sizeof(IO_SCSI_CAPABILITIES));
	  if (DeviceExtension->PortCapabilities == NULL)
	    {
	      DbgPrint("Failed to allocate port capabilities!\n");
	      Status = STATUS_INSUFFICIENT_RESOURCES;
	      goto ByeBye;
	    }

	  PortCapabilities = DeviceExtension->PortCapabilities;
	  PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
          if (PortConfig->ScatterGather == FALSE ||
	      PortConfig->NumberOfPhysicalBreaks >= (0x100000000LL >> PAGE_SHIFT) ||
	      PortConfig->MaximumTransferLength < PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE)
	    {
	      PortCapabilities->MaximumTransferLength =
	        PortConfig->MaximumTransferLength;
	    }
	  else
	    {
	      PortCapabilities->MaximumTransferLength =
	        PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE;
	    }

	  PortCapabilities->MaximumPhysicalPages =
	    PortCapabilities->MaximumTransferLength / PAGE_SIZE;
	  PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
	  PortCapabilities->AlignmentMask =
	    PortConfig->AlignmentMask;
	  PortCapabilities->TaggedQueuing =
	    PortConfig->TaggedQueuing;
	  PortCapabilities->AdapterScansDown =
	    PortConfig->AdapterScansDown;
	  PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */

	  /* Scan the adapter for devices */
	  SpiScanAdapter (DeviceExtension);

	  /* Build the registry device map */
	  SpiBuildDeviceMap (DeviceExtension,
			     (PUNICODE_STRING)Argument2);

	  /* Create the dos device link */
	  swprintf(DosNameBuffer,
		   L"\\??\\Scsi%lu:",
		   SystemConfig->ScsiPortCount);
	  RtlInitUnicodeString(&DosDeviceName,
			       DosNameBuffer);
	  IoCreateSymbolicLink(&DosDeviceName,
			       &DeviceName);

	  /* Update the system configuration info */
	  if (PortConfig->AtdiskPrimaryClaimed == TRUE)
	    SystemConfig->AtDiskPrimaryAddressClaimed = TRUE;
	  if (PortConfig->AtdiskSecondaryClaimed == TRUE)
	    SystemConfig->AtDiskSecondaryAddressClaimed = TRUE;

	  SystemConfig->ScsiPortCount++;
	  PortDeviceObject = NULL;
	  DeviceFound = TRUE;
	}
      else
	{
	  DPRINT("HwFindAdapter() Result: %lu\n", Result);

	  ExFreePool (PortConfig);
	  IoDeleteDevice (PortDeviceObject);
	  PortDeviceObject = NULL;
	}

      DPRINT("Bus: %lu  MaxBus: %lu\n", BusNumber, MaxBus);
      if (BusNumber >= MaxBus)
	{
	  DPRINT("Scanned all buses!\n");
	  Status = STATUS_SUCCESS;
	  goto ByeBye;
	}

      if (Again == FALSE)
	{
	  BusNumber++;
	  SlotNumber.u.AsULONG = 0;
	}
    }

ByeBye:
  /* Clean up the mess */
  if (PortDeviceObject != NULL)
    {
      DPRINT("Delete device: %p\n", PortDeviceObject);

      DeviceExtension = PortDeviceObject->DeviceExtension;

      if (DeviceExtension->PortCapabilities != NULL)
	{
	  IoDisconnectInterrupt (DeviceExtension->Interrupt);
	  ExFreePool (DeviceExtension->PortCapabilities);
	}

      if (DeviceExtension->PortConfig != NULL)
	{
	  ExFreePool (DeviceExtension->PortConfig);
	}

      IoDeleteDevice (PortDeviceObject);
    }

  DPRINT("ScsiPortInitialize() done!\n");

  return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
}


/*
 * @unimplemented
 */
VOID STDCALL
ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
		      IN PSCSI_REQUEST_BLOCK Srb,
		      IN ULONG 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");
  DPRINT1("Srb %x, PathId %d, TargetId %d, Lun %d, ErrorCode %x, UniqueId %x\n",
          Srb, PathId, TargetId, Lun, ErrorCode, UniqueId);

  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;

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

	  DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
	  DeviceExtension->Flags |= IRP_FLAG_COMPLETE;
	  Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
	}
	break;

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

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

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

	  DPRINT ("Notify: NextLuRequest(PathId %u  TargetId %u  Lun %u)\n",
		   PathId, TargetId, Lun);

⌨️ 快捷键说明

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