reactos操作系统实现(103)

ScsiPortInitialize函数用来初始化总线上设备,并查找每个总线上所有出现的设备,主要是SCSI相关的设备,当然这里SCSI设备是包括IDE控制器。找到每个设备之后,就会创建这个设备的设备对象,并且设置每个设备的参数、中断相关函数

#001 ULONG NTAPI

#002 ScsiPortInitialize(IN PVOID Argument1,

#003 IN PVOID Argument2,

#004 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,

#005 IN PVOID HwContext)

#006 {

驱动程序对象。

#007 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;

驱动程序里注册表路径。

#008 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;

#009 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;

#010 PCONFIGURATION_INFORMATION SystemConfig;

#011 PPORT_CONFIGURATION_INFORMATION PortConfig;

#012 PORT_CONFIGURATION_INFORMATION InitialPortConfig;

#013 CONFIGURATION_INFO ConfigInfo;

#014 ULONG DeviceExtensionSize;

#015 ULONG PortConfigSize;

#016 BOOLEAN Again;

#017 BOOLEAN DeviceFound = FALSE;

#018 BOOLEAN FirstConfigCall = TRUE;

#019 ULONG Result;

#020 NTSTATUS Status;

#021 ULONG MaxBus;

#022 ULONG BusNumber = 0;

#023 PCI_SLOT_NUMBER SlotNumber;

#024

#025 PDEVICE_OBJECT PortDeviceObject;

#026 WCHAR NameBuffer[80];

#027 UNICODE_STRING DeviceName;

#028 WCHAR DosNameBuffer[80];

#029 UNICODE_STRING DosDeviceName;

#030 PIO_SCSI_CAPABILITIES PortCapabilities;

#031 ULONG MappedIrq;

#032 KIRQL Dirql;

#033 KAFFINITY Affinity;

#034

#035 PCM_RESOURCE_LIST ResourceList;

#036 BOOLEAN Conflict;

#037

#038

#039 DPRINT ("ScsiPortInitialize() called!/n");

#040

检查初始化硬件的参数是否有效。

#041 /* Check params for validity */

#042 if ((HwInitializationData->HwInitialize == NULL) ||

#043 (HwInitializationData->HwStartIo == NULL) ||

#044 (HwInitializationData->HwInterrupt == NULL) ||

#045 (HwInitializationData->HwFindAdapter == NULL) ||

#046 (HwInitializationData->HwResetBus == NULL))

#047 {

#048 return STATUS_INVALID_PARAMETER;

#049 }

#050

设置驱动程序处理的功能函数

#051 /* Set handlers */

#052 DriverObject->DriverStartIo = ScsiPortStartIo;

#053 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;

#054 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;

#055 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;

#056 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ScsiPortDeviceControl;

#057 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;

#058

获取系统配置信息,比如获取磁盘的个数。

#059 /* Obtain configuration information */

#060 SystemConfig = IoGetConfigurationInformation();

#061

清空当前配置信息结构。

#062 /* Zero the internal configuration info structure */

#063 RtlZeroMemory(&ConfigInfo,sizeof(CONFIGURATION_INFO));

#064

从第一个插槽开始枚举设备。一台PC电脑最多只能有32个插槽,每个插槽上的设备只能有8功能,因此逻辑设备最多为256个。

#065 /* Zero starting slot number */

#066 SlotNumber.u.AsULONG = 0;

#067

分配访问的空间,如果分配失败就返回。

#068 /* Allocate space for access ranges */

#069 if (HwInitializationData->NumberOfAccessRanges)

#070 {

#071 ConfigInfo.AccessRanges =

#072 ExAllocatePoolWithTag(PagedPool,

#073 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE),TAG_SCSIPORT);

#074

#075 /* Fail if Failed */

#076 if (ConfigInfo.AccessRanges == NULL)

#077 return STATUS_INSUFFICIENT_RESOURCES;

#078 }

#079

打开注册表键,并且读取相应参数。

#080 /* Open registry keys */

#081 SpiInitOpenKeys(&ConfigInfo,(PUNICODE_STRING)Argument2);

#082

设置最后一个结束标志。

#083 /* Last adapter number = not known */

#084 ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE;

#085

计算设备扩展大小。

#086 /* Calculate sizes of DeviceExtension and PortConfig */

#087 DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +

#088 HwInitializationData->DeviceExtensionSize;

#089

判断是否PCI总线,还是其它总线,如果是PCI总线,就设置最多为8个设备,其它类型只设置为一个设备。

#090 MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;

#091 DPRINT("MaxBus: %lu/n",MaxBus);

#092

开始循环查找相应的设备。

#093 while (TRUE)

#094 {

创建设备名称

#095 /* Create a unicode device name */

#096 swprintf(NameBuffer,

#097 L"//Device//ScsiPort%lu",

#098 SystemConfig->ScsiPortCount);

转换UNICODE字符串。

#099 RtlInitUnicodeString(&DeviceName,NameBuffer);

#100

显示设备名称

#101 DPRINT("Creating device: %wZ/n",&DeviceName);

#102

调用函数IoCreateDevice来创建一个端口设备,创建的设备为文件控制设备。

#103 /* Create the port device */

#104 Status = IoCreateDevice(DriverObject,

#105 DeviceExtensionSize,

#106 &DeviceName,

#107 FILE_DEVICE_CONTROLLER,

#108 0,

#109 FALSE,

#110 &PortDeviceObject);

#111

#112 if (!NT_SUCCESS(Status))

#113 {

#114 DPRINT1("IoCreateDevice call Failed! (Status 0x%lX)/n",Status);

#115 PortDeviceObject = NULL;

#116 break;

#117 }

#118

#119 DPRINT ("Created device: %wZ (%p)/n",&DeviceName,PortDeviceObject);

#120

设置设备对象的属性

#121 /* Set the buffering strategy here... */

设置设备访问IO属性为直接访问方式。

#122 PortDeviceObject->Flags |= DO_DIRECT_IO;

数据对齐的方式为按两个字节对齐。

#123 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; /* FIXME: Is this really needed? */

#124

填写设备对象的扩展属性

#125 /* Fill Device Extension */

#126 DeviceExtension = PortDeviceObject->DeviceExtension;

#127 DeviceExtension->Length = DeviceExtensionSize;

#128 DeviceExtension->DeviceObject = PortDeviceObject;

#129 DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;

#130

设置设备的功能处理函数

#131 /* Driver's routines... */

#132 DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;

#133 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;

#134 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;

#135 DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;

#136 DeviceExtension->HwDmaStarted = HwInitializationData->HwDmaStarted;

#137

#138 /* Extensions sizes */

#139 DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;

#140 DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;

#141 DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;

#142

计算SRB4字节对齐。

#143 /* Round Srb extension size to the quadword */

#144 DeviceExtension->SrbExtensionSize =

#145 ~(sizeof(LONGLONG) - 1) & (DeviceExtension->SrbExtensionSize +

#146 sizeof(LONGLONG) - 1);

#147

#148 /* Fill some numbers (bus count,lun count,etc) */

#149 DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;

#150 DeviceExtension->RequestsNumber = 16;

#151

初始化控制器的自旋锁。

#152 /* Initialize the spin lock in the controller extension */

#153 KeInitializeSpinLock(&DeviceExtension->IrqLock);

#154 KeInitializeSpinLock(&DeviceExtension->SpinLock);

#155

初始化DPC对象。

#156 /* Initialize the DPC object */

#157 IoInitializeDpcRequest(PortDeviceObject,

#158 ScsiPortDpcForIsr);

#159

初始化定时器。

#160 /* Initialize the device timer */

#161 DeviceExtension->TimerCount = -1;

#162 IoInitializeTimer(PortDeviceObject,

#163 ScsiPortIoTimer,

#164 DeviceExtension);

#165

初始化小端口的定时器和DPC对象。

#166 /* Initialize miniport timer */

#167 KeInitializeTimer(&DeviceExtension->MiniportTimer);

#168 KeInitializeDpc(&DeviceExtension->MiniportTimerDpc,

#169 SpiMiniportTimerDpc,

#170 PortDeviceObject);

#171

#172 CreatePortConfig:

#173

调用函数SpiCreatePortConfig来创建端配置参数,包括注册表里读取相应参数。

#174 Status = SpiCreatePortConfig(DeviceExtension,

#175 HwInitializationData,

#176 &ConfigInfo,

#177 &InitialPortConfig,

#178 FirstConfigCall);

#179

创建端口的配置失败,就返回出错。

#180 if (!NT_SUCCESS(Status))

#181 {

#182 DPRINT("SpiCreatePortConfig() Failed with Status 0x%08X/n",Status);

#183 break;

#184 }

#185

分配设备扩展的配置信息大小。

#186 /* Allocate and initialize port configuration info */

#187 PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +

#188 HwInitializationData->NumberOfAccessRanges *

#189 sizeof(ACCESS_RANGE) + 7) & ~7;

#190 DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool,PortConfigSize,TAG_SCSIPORT);

#191

#192 /* Fail if Failed */

#193 if (DeviceExtension->PortConfig == NULL)

#194 {

#195 Status = STATUS_INSUFFICIENT_RESOURCES;

#196 break;

#197 }

#198

指向扩展的设备信息。

#199 PortConfig = DeviceExtension->PortConfig;

#200

从初始化的配置信息拷贝到扩展设备信息里。

#201 /* Copy information here */

#202 RtlCopyMemory(PortConfig,

#203 &InitialPortConfig,

#204 sizeof(PORT_CONFIGURATION_INFORMATION));

#205

#206

设置扩展信息大小。

#207 /* Copy extension sizes into the PortConfig */

#208 PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;

#209 PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize;

#210

初始化访问范围。

#211 /* Initialize Access ranges */

#212 if (HwInitializationData->NumberOfAccessRanges != 0)

#213 {

#214 PortConfig->AccessRanges = (PVOID)(PortConfig+1);

#215

#216 /* Align to LONGLONG */

#217 PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) + 7);

#218 PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) & ~7);

#219

#220 /* Copy the data */

#221 RtlCopyMemory(PortConfig->AccessRanges,

#222 ConfigInfo.AccessRanges,

#223 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE));

#224 }

#225

搜索匹配的PCI设备。

#226 /* Search for matching PCI device */

#227 if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&

#228 (HwInitializationData->VendorIdLength > 0) &&

#229 (HwInitializationData->VendorId != NULL) &&

#230 (HwInitializationData->DeviceIdLength > 0) &&

#231 (HwInitializationData->DeviceId != NULL))

#232 {

设置配置中断级别。

#233 PortConfig->BusInterruptLevel = 0;

#234

获取PCI的设备信息。

#235 /* Get PCI device data */

#236 DPRINT("VendorId '%.*s' DeviceId '%.*s'/n",

#237 HwInitializationData->VendorIdLength,

#238 HwInitializationData->VendorId,

#239 HwInitializationData->DeviceIdLength,

#240 HwInitializationData->DeviceId);

#241

读取PCI的设备配置信息,并且保存到PortConfig参数里。

#242 if (!SpiGetPciConfigData(DriverObject,

#243 PortDeviceObject,

#244 HwInitializationData,

#245 PortConfig,

#246 RegistryPath,

#247 ConfigInfo.BusNumber,

#248 &SlotNumber))

#249 {

如果获取PCI的设备信息不成功,就重新获取下一个设备。

#250 /* Continue to the next bus,nothing here */

#251 ConfigInfo.BusNumber++;

#252 DeviceExtension->PortConfig = NULL;

#253 ExFreePool(PortConfig);

#254 Again = FALSE;

#255 goto CreatePortConfig;

#256 }

#257

如果创建中断级别还为0,说明创建参数有问题,创建设备失败。

#258 if (!PortConfig->BusInterruptLevel)

#259 {

#260 /* Bypass this slot,because no interrupt was assigned */

#261 DeviceExtension->PortConfig = NULL;

#262 ExFreePool(PortConfig);

#263 goto CreatePortConfig;

#264 }

#265 }

#266 else

#267 {

#268 DPRINT("Non-pci bus/n");

#269 }

#270

到这里已经找到PCI设备,调用函数AtapiFindNativeModeController函数查找ATAPI设备。

#271 /* Note: HwFindAdapter is called once for each bus */

#272 Again = FALSE;

#273 DPRINT("Calling HwFindAdapter() for Bus %lu/n",PortConfig->SystemIoBusNumber);

#274 Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,

#275 HwContext,

#276 0, /* BusInformation */

#277 ConfigInfo.Parameter,/* ArgumentString */

#278 PortConfig,

#279 &Again);

#280

#281 DPRINT("HwFindAdapter() Result: %lu Again: %s/n",

#282 Result,(Again) ? "True" : "False");

#283

删除映射的基地址内存。

#284 /* Free MapRegisterBase,it's not needed anymore */

#285 if (DeviceExtension->MapRegisterBase != NULL)

#286 {

#287 ExFreePool(DeviceExtension->MapRegisterBase);

#288 DeviceExtension->MapRegisterBase = NULL;

#289 }

#290

如果没有到相应的ATAPI设备,就返回重新创建设备。

#291 /* If result is nothing good... */

#292 if (Result != SP_RETURN_FOUND)

#293 {

#294 DPRINT("HwFindAdapter() Result: %lu/n",Result);

#295

#296 if (Result == SP_RETURN_NOT_FOUND)

#297 {

#298 /* We can continue on the next bus */

#299 ConfigInfo.BusNumber++;

#300 Again = FALSE;

#301

#302 DeviceExtension->PortConfig = NULL;

#303 ExFreePool(PortConfig);

#304 goto CreatePortConfig;

#305 }

#306

#307 /* Otherwise,break */

#308 Status = STATUS_INTERNAL_ERROR;

#309 break;

#310 }

#311

到这里已经发现了一个HBA设备。HBA就是主机总线适配器。

#312 DPRINT("ScsiPortInitialize(): Found HBA! (%x),adapter Id %d/n",

#313 PortConfig->BusInterruptVector,PortConfig->InitiatorBusId[0]);

#314

#315 /* If the SRB extension size was updated */

#316 if (!DeviceExtension->NonCachedExtension &&

#317 (PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize))

#318 {

#319 /* Set it (rounding to LONGLONG again) */

#320 DeviceExtension->SrbExtensionSize =

#321 (PortConfig->SrbExtensionSize +

#322 sizeof(LONGLONG)) & ~(sizeof(LONGLONG) - 1);

#323 }

#324

#325 /* The same with LUN extension size */

#326 if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)

#327 DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;

#328

#329

如果不是PCI总线,或者设备资源没有分配,就需要分配合适的资源。

#330 if (!((HwInitializationData->AdapterInterfaceType == PCIBus) &&

#331 (HwInitializationData->VendorIdLength > 0) &&

#332 (HwInitializationData->VendorId != NULL) &&

#333 (HwInitializationData->DeviceIdLength > 0) &&

#334 (HwInitializationData->DeviceId != NULL)))

#335 {

#336 /* Construct a resource list */

#337 ResourceList = SpiConfigToResource(DeviceExtension,

#338 PortConfig);

#339

#340 if (ResourceList)

#341 {

#342 UNICODE_STRING UnicodeString;

#343 RtlInitUnicodeString(&UnicodeString,L"ScsiAdapter");

#344 DPRINT("Reporting resources/n");

#345 Status = IoReportResourceUsage(&UnicodeString,

#346 DriverObject,

#347 NULL,

#348 0,

#349 PortDeviceObject,

#350 ResourceList,

#351 FIELD_OFFSET(CM_RESOURCE_LIST,

#352 List[0].PartialResourceList.PartialDescriptors) +

#353 ResourceList->List[0].PartialResourceList.Count

#354 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),

#355 FALSE,

#356 &Conflict);

#357 ExFreePool(ResourceList);

#358

#359 /* In case of a failure or a conflict,break */

#360 if (Conflict || (!NT_SUCCESS(Status)))

#361 {

#362 if (Conflict)

#363 Status = STATUS_CONFLICTING_ADDRESSES;

#364 break;

#365 }

#366 }

#367 }

#368

#369 /* Reset the Conflict var */

#370 Conflict = FALSE;

#371

拷贝所有端口配置的资源到设备扩展里。

#372 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */

#373 if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)

#374 DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS;

#375 else

#376 DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;

#377

#378 DeviceExtension->BusNum = PortConfig->NumberOfBuses;

#379 DeviceExtension->CachesData = PortConfig->CachesData;

#380 DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent;

#381 DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing;

#382 DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu;

#383

#384 /* If something was disabled via registry - apply it */

#385 if (ConfigInfo.DisableMultipleLun)

#386 DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE;

#387

#388 if (ConfigInfo.DisableTaggedQueueing)

#389 DeviceExtension->SupportsTaggedQueuing = PortConfig->MultipleRequestPerLu = FALSE;

#390

检查是否需要分配SRB数据。

#391 /* Check if we need to alloc SRB data */

#392 if (DeviceExtension->SupportsTaggedQueuing ||

#393 DeviceExtension->MultipleReqsPerLun)

#394 {

#395 DeviceExtension->NeedSrbDataAlloc = TRUE;

#396 }

#397 else

#398 {

#399 DeviceExtension->NeedSrbDataAlloc = FALSE;

#400 }

#401

#402 /* Get a pointer to the port capabilities */

#403 PortCapabilities = &DeviceExtension->PortCapabilities;

#404

#405 /* Copy one field there */

#406 DeviceExtension->MapBuffers = PortConfig->MapBuffers;

#407 PortCapabilities->AdapterUsesPio = PortConfig->MapBuffers;

#408

#409 if (DeviceExtension->AdapterObject == NULL &&

#410 (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || PortConfig->Master))

#411 {

#412 DPRINT1("DMA is not supported yet/n");

#413 ASSERT(FALSE);

#414 }

#415

#416 if (DeviceExtension->SrbExtensionBuffer == NULL &&

#417 (DeviceExtension->SrbExtensionSize != 0 ||

#418 PortConfig->AutoRequestSense))

#419 {

#420 DeviceExtension->SupportsAutoSense = PortConfig->AutoRequestSense;

#421 DeviceExtension->NeedSrbExtensionAlloc = TRUE;

#422

#423 /* Allocate common buffer */

#424 Status = SpiAllocateCommonBuffer(DeviceExtension,0);

#425

#426 /* Check for failure */

#427 if (!NT_SUCCESS(Status))

#428 break;

#429 }

#430

如果需要分配SRB,就进行分配SRB的动作。

#431 /* Allocate SrbData,if needed */

#432 if (DeviceExtension->NeedSrbDataAlloc)

#433 {

#434 ULONG Count;

#435 PSCSI_REQUEST_BLOCK_INFO SrbData;

#436

#437 if (DeviceExtension->SrbDataCount != 0)

#438 Count = DeviceExtension->SrbDataCount;

#439 else

#440 Count = DeviceExtension->RequestsNumber * 2;

#441

#442 /* Allocate the data */

#443 SrbData = ExAllocatePoolWithTag(NonPagedPool,Count * sizeof(SCSI_REQUEST_BLOCK_INFO),TAG_SCSIPORT);

#444 if (SrbData == NULL)

#445 return STATUS_INSUFFICIENT_RESOURCES;

#446

#447 RtlZeroMemory(SrbData,Count * sizeof(SCSI_REQUEST_BLOCK_INFO));

#448

#449 DeviceExtension->SrbInfo = SrbData;

#450 DeviceExtension->FreeSrbInfo = SrbData;

#451 DeviceExtension->SrbDataCount = Count;

#452

#453 /* Link it to the list */

#454 while (Count > 0)

#455 {

#456 SrbData->Requests.Flink = (PLIST_ENTRY)(SrbData + 1);

#457 SrbData++;

#458 Count--;

#459 }

#460

#461 /* Mark the last entry of the list */

#462 SrbData--;

#463 SrbData->Requests.Flink = NULL;

#464 }

#465

初始化端口的兼容性。

#466 /* Initialize port capabilities */

#467 PortCapabilities = &DeviceExtension->PortCapabilities;

#468 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);

#469 PortCapabilities->MaximumTransferLength = PortConfig->MaximumTransferLength;

#470

#471 if (PortConfig->ReceiveEvent)

#472 PortCapabilities->SupportedAsynchronousEvents |= SRBEV_SCSI_ASYNC_NOTIFICATION;

#473

#474 PortCapabilities->TaggedQueuing = DeviceExtension->SupportsTaggedQueuing;

#475 PortCapabilities->AdapterScansDown = PortConfig->AdapterScansDown;

#476

#477 if (PortConfig->AlignmentMask > PortDeviceObject->AlignmentRequirement)

#478 PortDeviceObject->AlignmentRequirement = PortConfig->AlignmentMask;

#479

#480 PortCapabilities->AlignmentMask = PortDeviceObject->AlignmentRequirement;

#481

#482 if (PortCapabilities->MaximumPhysicalPages == 0)

#483 {

#484 PortCapabilities->MaximumPhysicalPages =

#485 BYTES_TO_PAGES(PortCapabilities->MaximumTransferLength);

#486

#487 /* Apply miniport's limits */

#488 if (PortConfig->NumberOfPhysicalBreaks < PortCapabilities->MaximumPhysicalPages)

#489 {

#490 PortCapabilities->MaximumPhysicalPages = PortConfig->NumberOfPhysicalBreaks;

#491 }

#492 }

#493

处理中断相关内容

#494 /* Deal with interrupts */

#495 if (DeviceExtension->HwInterrupt == NULL ||

#496 (PortConfig->BusInterruptLevel == 0 && PortConfig->BusInterruptVector == 0))

#497 {

#498 /* No interrupts */

#499 KeInitializeSpinLock(&DeviceExtension->IrqLock);

#500

#501 /* FIXME: Use synchronization routine */

#502 ASSERT("No interrupts branch requires changes in synchronization/n");

#503

#504 DeviceExtension->Interrupt = (PVOID)DeviceExtension;

#505 DPRINT("No interrupts/n");

#506

#507 }

#508 else

#509 {

#510 /* Are 2 interrupts needed? */

#511 if (DeviceExtension->HwInterrupt != NULL &&

#512 (PortConfig->BusInterruptLevel != 0 || PortConfig->BusInterruptVector != 0) &&

#513 (PortConfig->BusInterruptLevel2 != 0 || PortConfig->BusInterruptVector2 != 0))

#514 {

#515 DPRINT1("2 interrupts requested! Not yet supported/n");

#516 ASSERT(FALSE);

#517 }

#518 else

#519 {

#520 BOOLEAN InterruptShareable;

#521

#522 /* No,only 1 interrupt */

#523 DPRINT("1 interrupt,IRQ is %d/n",PortConfig->BusInterruptLevel);

#524

#525 DeviceExtension->InterruptLevel = PortConfig->BusInterruptLevel;

#526

#527 /* Register an interrupt handler for this device */

#528 MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,

#529 PortConfig->SystemIoBusNumber,

#530 PortConfig->BusInterruptLevel,

#531 PortConfig->BusInterruptVector,

#532 &Dirql,

#533 &Affinity);

#534

#535 /* Determing IRQ sharability as usual */

#536 if (PortConfig->AdapterInterfaceType == MicroChannel ||

#537 PortConfig->InterruptMode == LevelSensitive)

#538 {

#539 InterruptShareable = TRUE;

#540 }

#541 else

#542 {

#543 InterruptShareable = FALSE;

#544 }

#545

设置这个小端口对象的中断函数

#546 Status = IoConnectInterrupt(&DeviceExtension->Interrupt,

#547 (PKSERVICE_ROUTINE)ScsiPortIsr,

#548 DeviceExtension,

#549 NULL,

#550 MappedIrq,

#551 Dirql,

#552 Dirql,

#553 PortConfig->InterruptMode,

#554 InterruptShareable,

#555 Affinity,

#556 FALSE);

#557

#558 if (!(NT_SUCCESS(Status)))

#559 {

#560 DPRINT1("Could not connect interrupt %d/n",

#561 PortConfig->BusInterruptVector);

#562 DeviceExtension->Interrupt = NULL;

#563 break;

#564 }

#565

#566 }

#567 }

#568

保存端口对象所有IO地址。

#569 /* Save IoAddress (from access ranges) */

#570 if (HwInitializationData->NumberOfAccessRanges != 0)

#571 {

#572 DeviceExtension->IoAddress =

#573 ((*(PortConfig->AccessRanges))[0]).RangeStart.LowPart;

#574

#575 DPRINT("Io Address %x/n",DeviceExtension->IoAddress);

#576 }

#577

#578 /* Set flag that it's allowed to disconnect during this command */

#579 DeviceExtension->Flags |= SCSI_PORT_DISCONNECT_ALLOWED;

#580

#581 /* Initialize counter of active requests (-1 means there are none) */

#582 DeviceExtension->ActiveRequestCounter = -1;

#583

设置跟DMA相关的配置。

#584 /* Analyze what we have about DMA */

#585 if (DeviceExtension->AdapterObject != NULL &&

#586 PortConfig->Master &&

#587 PortConfig->NeedPhysicalAddresses)

#588 {

#589 DeviceExtension->MapRegisters = TRUE;

#590 }

#591 else

#592 {

#593 DeviceExtension->MapRegisters = FALSE;

#594 }

#595

#596 /* Call HwInitialize at DISPATCH_LEVEL */

#597 KeRaiseIrql(DISPATCH_LEVEL,&Dirql);

#598

#599 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,

#600 DeviceExtension->HwInitialize,

#601 DeviceExtension->MiniPortDeviceExtension))

#602 {

#603 DPRINT1("HwInitialize() Failed!/n");

#604 KeLowerIrql(Dirql);

#605 Status = STATUS_ADAPTER_HARDWARE_ERROR;

#606 break;

#607 }

#608

设置中断通知函数

#609 /* Check if a notification is needed */

#610 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)

#611 {

#612 /* Call DPC right away,because we're already at DISPATCH_LEVEL */

#613 ScsiPortDpcForIsr(NULL,

#614 DeviceExtension->DeviceObject,

#615 NULL,

#616 NULL);

#617 }

#618

#619 /* Lower irql back to what it was */

#620 KeLowerIrql(Dirql);

#621

启动端口定时器。

#622 /* Start our timer */

#623 IoStartTimer(PortDeviceObject);

#624

设置总线信息。

#625 /* Initialize bus scanning information */

#626 DeviceExtension->BusesConfig = ExAllocatePoolWithTag(PagedPool,

#627 sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses

#628 + sizeof(ULONG),TAG_SCSIPORT);

#629

#630 if (!DeviceExtension->BusesConfig)

#631 {

#632 DPRINT1("Out of resources!/n");

#633 Status = STATUS_INSUFFICIENT_RESOURCES;

#634 break;

#635 }

#636

#637 /* Zero it */

#638 RtlZeroMemory(DeviceExtension->BusesConfig,

#639 sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses

#640 + sizeof(ULONG));

#641

#642 /* Store number of buses there */

#643 DeviceExtension->BusesConfig->NumberOfBuses = (UCHAR)DeviceExtension->BusNum;

#644

#645 /* Scan the adapter for devices */

#646 SpiScanAdapter(DeviceExtension);

#647

#648 /* Build the registry device map */

#649 SpiBuildDeviceMap(DeviceExtension,

#650 (PUNICODE_STRING)Argument2);

#651

创建DOS方式访问的符号连接。

#652 /* Create the dos device link */

#653 swprintf(DosNameBuffer,

#654 L"//??//Scsi%lu:",

#655 SystemConfig->ScsiPortCount);

#656 RtlInitUnicodeString(&DosDeviceName,DosNameBuffer);

#657 IoCreateSymbolicLink(&DosDeviceName,&DeviceName);

#658

增加端口计数,也就是下一个端口设备的名称

#659 /* Increase the port count */

#660 SystemConfig->ScsiPortCount++;

#661 FirstConfigCall = FALSE;

#662

查找下一个插槽的设备。

#663 /* Increase adapter number and bus number respectively */

#664 ConfigInfo.AdapterNumber++;

#665

#666 if (!Again)

#667 ConfigInfo.BusNumber++;

#668

#669 DPRINT("Bus: %lu MaxBus: %lu/n",BusNumber,MaxBus);

#670

#671 DeviceFound = TRUE;

#672 }

#673

清空所有相关资源。

#674 /* Clean up the mess */

#675 SpiCleanupAfterInit(DeviceExtension);

#676

#677 /* Close registry keys */

#678 if (ConfigInfo.ServiceKey != NULL)

#679 ZwClose(ConfigInfo.ServiceKey);

#680

#681 if (ConfigInfo.DeviceKey != NULL)

#682 ZwClose(ConfigInfo.DeviceKey);

#683

#684 if (ConfigInfo.BusKey != NULL)

#685 ZwClose(ConfigInfo.BusKey);

#686

#687 if (ConfigInfo.AccessRanges != NULL)

#688 ExFreePool(ConfigInfo.AccessRanges);

#689

#690 if (ConfigInfo.Parameter != NULL)

#691 ExFreePool(ConfigInfo.Parameter);

#692

#693 DPRINT("ScsiPortInitialize() done,Status = 0x%08X,DeviceFound = %d!/n",

#694 Status,DeviceFound);

#695

查找到设备了,就返回成功。

#696 return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;

#697 }

#698

相关文章

导入moment 使用方式 年月日,时分秒 星期几 相对时间 7天后 2小时后 明天 将毫秒转换成年月日
@ 一、前言 为什么介绍redux-actions呢? 第一次见到主要是接手公司原有的项目,发现有之前的大佬在处理...
十大React Hook库 原文地址:https://dev.to/bornfightcompany/top-10-react-hook-libraries-4065 原文...
React生命周期 React的生命周期从广义上分为挂载、渲染、卸载三个阶段,在React的整个生命周期中提供很...
React虚拟DOM的理解 Virtual DOM是一棵以JavaScript对象作为基础的树,每一个节点可以将其称为VNode,用...
React中JSX的理解 JSX是快速生成react元素的一种语法,实际是React.createElement(component, props, ....