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 {
#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