AtapiFindPCIController函数是用来发现PCI总线上所有的IDE控制器,并发现相关的IDE设备。具体实现代码如下:
#001 ULONG
#002 NTAPI
#003 AtapiFindPCIController(
#004 IN PVOID HwDeviceExtension,
#005 IN PVOID Context,
#006 IN PVOID BusInformation,
#007 IN PCHAR ArgumentString,
#008 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
#009 OUT PBOOLEAN Again
#010 )
#011 /*++
#012
#013 Routine Description:
#014
#015 This function is called by the OS-specific port driver after
#016 the necessary storage has been allocated,to gather information
#017 about the adapter's configuration.
#018
#019 Arguments:
#020
#021 HwDeviceExtension - HBA miniport driver's adapter data storage
#022 Context - Address of adapter count
#023 BusInformation -
#024 ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
#025 ConfigInfo - Configuration information structure describing HBA
#026 Again - Indicates search for adapters to continue
#027
#028 Return Value:
#029
#030 ULONG
#031
#032 --*/
#033
#034 {
#035 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
#036 PULONG adapterCount = (PULONG)Context;
#037 ULONG channel = 0;
#038 static ULONG functionNumber,
#039 slotNumber,
#040 controllers;
#041 ULONG i,j;
#042 PUCHAR ioSpace;
#043 BOOLEAN atapiOnly,
#044 lastSlot,
#045 controllerFound = FALSE,
#046 deviceFound = FALSE;
#047 UCHAR statusByte;
#048
#049 //
#050 // The following table specifies the ports to be checked when searching for
#051 // an IDE controller. A zero entry terminates the search.
#052 //
#053
这里设置IDE控制器的几个控制端口。
#054 CONST ULONG AdapterAddresses[5] = {0x1F0,0x170,0x1e8,0x168,0};
#055
#056 //
#057 // The following table specifies interrupt levels corresponding to the
#058 // port addresses in the prevIoUs table.
#059 //
#060
设置相应的IDE控制器的中断号。
#061 CONST ULONG InterruptLevels[5] = {14,15,11,10,0};
#062
检查设备对象扩展是否分配,如果没有分配,就返回失败。
#063 if (!deviceExtension) {
#064 return SP_RETURN_ERROR;
#065 }
#066
#067 //
#068 // Since scsiport will call this function first before it calls AtapiFindController
#069 // we need to bypass it if we have data installed in ConfigInfo,by the pcmcia driver.
#070 // In that case atapifindcontroller should be called first.
#071 // Instead of modifying atapi driverEntry to search of PCIBus first (now its ISA)
#072 // the check is put here.
#073 //
#074
当总线0上的设备配置不为空时,就进入进找相应的IDE控制器。
#075 if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
#076
下面调用函数AtapiFindController来发现相应的IDE控制器。
#077 return AtapiFindController(HwDeviceExtension,
#078 Context,
#079 BusInformation,
#080 ArgumentString,
#081 ConfigInfo,
#082 Again);
#083 }
#084
#085
#086 //
#087 // Gronk PCI config space looking for the broken PCI IDE controllers that have only
#088 // one FIFO for both channels.
#089 // Don't do this. It's incorrect and nasty. It has to be done to work around these
#090 // broken parts,no other reason can justify this.
#091 //
#092
下面查找分离的PCI设备配置空间。
#093 for (i = controllers; i < BROKEN_ADAPTERS; i++) {
#094
#095 //
#096 // Determine if both channels are enabled and have devices.
#097 //
#098
#099 lastSlot = FALSE;
#100
#101 if (FindBrokenController(deviceExtension,
#102 (PUCHAR)BrokenAdapters[i].VendorId,
#103 BrokenAdapters[i].VendorIdLength,
#104 (PUCHAR)BrokenAdapters[i].DeviceId,
#105 BrokenAdapters[i].DeviceIdLength,
#106 &functionNumber,
#107 &slotNumber,
#108 ConfigInfo->SystemIoBusNumber,
#109 &lastSlot)) {
#110
#111 slotNumber++;
#112 functionNumber = 0;
#113 controllerFound = TRUE;
#114
#115 DebugPrint((1,
#116 "Found broken PCI IDE controller: VendorId %s,DeviceId %s/n",
#117 BrokenAdapters[i].VendorId,
#118 BrokenAdapters[i].DeviceId));
#119
#120 if (AdapterAddresses[*adapterCount] != 0) {
#121
#122 for (j = 0; j < 2; j++) {
#123
#124 //
#125 // Get the system physical address for this IO range.
#126 //
#127
#128 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
#129 ConfigInfo->AdapterInterfaceType,
#130 ConfigInfo->SystemIoBusNumber,
#131 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount]),
#132 8,
#133 TRUE);
#134
#135 //
#136 // Update the adapter count.
#137 //
#138
增加IDE控制器的个数。
#139 (*adapterCount)++;
#140
#141 //
#142 // Check if ioSpace accessible.
#143 //
#144
#145 if (!ioSpace) {
#146 continue;
#147 }
#148
#149 //
#150 // Select master.
#151 //
#152
#153 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect,0xA0);
#154
#155 //
#156 // Check if card at this address.
#157 //
#158
#159 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow,0xAA);
#160
#161 //
#162 // Check if indentifier can be read back.
#163 //
#164
#165 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
#166
#167 DebugPrint((2,
#168 "AtapiFindPciController: Identifier read back from Master (%x)/n",
#169 statusByte));
#170
#171
#172 //
#173 // Select slave.
#174 //
#175
#176 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect,0xB0);
#177
#178 //
#179 // See if slave is present.
#180 //
#181
#182 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow,0xAA);
#183
#184 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
#185
#186 DebugPrint((2,
#187 "AtapiFindPciController: Identifier read back from Slave (%x)/n",
#188 statusByte));
#189
#190 //
#191 //
#192 // No controller at this base address.
#193 //
#194
#195 ScsiPortFreeDeviceBase(HwDeviceExtension,
#196 ioSpace);
#197
继续查找第二个通道是否IDE控制器。
#198 //
#199 // If the chip is there,but we couldn't find the primary channel,try the secondary.
#200 // If we couldn't find a secondary,who cares.
#201 //
#202
#203 if (j == 1) {
#204
#205 goto setStatusAndExit;
#206
#207 } else {
#208 continue;
#209 }
#210 }
#211 }
#212
如果发现了IDE控制器,就保存相应的配置参数。
#213 if (controllerFound) {
#214
#215 //
#216 // Record base IO address.
#217 //
#218
#219 deviceExtension->BaseIoAddress1[channel] = (PIDE_REGISTERS_1)(ioSpace);
#220
#221 //
#222 // Fill in the access array information.
#223 //
#224
#225 (*ConfigInfo->AccessRanges)[channel].RangeStart =
#226 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1]);
#227
#228 (*ConfigInfo->AccessRanges)[channel].RangeLength = 8;
#229 (*ConfigInfo->AccessRanges)[channel].RangeInMemory = FALSE;
#230
#231 //
#232 // Indicate the interrupt level corresponding to this IO range.
#233 //
#234
根据不同的通道进行保存中断号和中断方式。
#235 if (channel == 0) {
#236 ConfigInfo->BusInterruptLevel = InterruptLevels[*adapterCount - 1];
#237 ConfigInfo->InterruptMode = Latched;
#238 } else {
#239 ConfigInfo->BusInterruptLevel2 = InterruptLevels[*adapterCount - 1];
#240 ConfigInfo->InterruptMode2 = Latched;
#241 }
#242
#243 //
#244 // Get the system physical address for the second IO range.
#245 //
#246
#247 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
#248 ConfigInfo->AdapterInterfaceType,
#249 ConfigInfo->SystemIoBusNumber,
#250 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1] + 0x206),
#251 1,
#252 TRUE);
#253
#254 deviceExtension->BaseIoAddress2[channel] = (PIDE_REGISTERS_2)(ioSpace);
#255
#256 deviceExtension->NumberChannels = 2;
#257
#258 //
#259 // Indicate only one bus.
#260 //
#261
#262 ConfigInfo->NumberOfBuses = 1;
#263
#264 //
#265 // Indicate four devices can be attached to the adapter,since we
#266 // have to serialize access to the two channels.
#267 //
#268
#269 ConfigInfo->MaximumNumberOfTargets = 4;
#270
#271 //
#272 // Indicate maximum transfer length is 64k.
#273 //
#274
#275 ConfigInfo->MaximumTransferLength = 0x10000;
#276
#277 DebugPrint((1,
#278 "AtapiFindPciController: Found broken IDE at %x/n",
#279 deviceExtension->BaseIoAddress1[channel]));
#280
#281 //
#282 // Since we will always pick up this part,and not atdisk,so indicate.
#283 //
#284
#285 atapiOnly = FALSE;
#286
保存中断模式。
#287 //
#288 // Save the Interrupe Mode for later use
#289 //
#290 deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
#291
查找这个IDE控制器上所有的设备。
#292 //
#293 // Search for devices on this controller.
#294 //
#295
#296 if (FindDevices(HwDeviceExtension,
#297 atapiOnly,
#298 channel++)){
#299 deviceFound = TRUE;
#300 }
#301
判断是主IDE设备,还第二个IDE设备。
#302 //
#303 // Claim primary or secondary ATA IO range.
#304 //
#305
#306 if (*adapterCount == 1) {
#307 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
#308 deviceExtension->PrimaryAddress = TRUE;
#309
#310 } else if (*adapterCount == 2) {
#311 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
#312 deviceExtension->PrimaryAddress = FALSE;
#313 }
#314 }
#315 }
#316 }
#317 }
#318
#319 setStatusAndExit:
#320
#321 if (lastSlot) {
#322 slotNumber = 0;
#323 functionNumber = 0;
#324 }
#325
#326 controllers = i;
#327
#328 if (controllerFound && deviceFound) {
#329
返回已经搜索到设备。
#330 *Again = TRUE;
#331 return SP_RETURN_FOUND;
#332 }
#333 }
#334
#335
已经搜索完成,没有任设备发现。
#336 //
#337 // The entire table has been searched and no adapters have been found.
#338 //
#339
#340 *Again = FALSE;
#341
#342 return SP_RETURN_NOT_FOUND;
#343
#344} // end AtapiFindPCIController()