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
计算SRB的4字节对齐。 #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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |