reactos操作系统实现(103)

REACTOS 专栏收录该内容
193 篇文章 2 订阅

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  

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值