Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2489 lines
77 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pmpcibus.c
  5. Abstract:
  6. Implements simplified PCI configuration
  7. read and write functions for use in
  8. an ACPI HAL.
  9. Author:
  10. Jake Oshins (jakeo) 1-Dec-1997
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "halp.h"
  16. #include "pci.h"
  17. #include "pcip.h"
  18. #include "cardbus.h"
  19. #define MAX(a, b) \
  20. ((a) > (b) ? (a) : (b))
  21. #define MIN(a, b) \
  22. ((a) < (b) ? (a) : (b))
  23. NTSTATUS
  24. HalpSearchForPciDebuggingDevice(
  25. IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice,
  26. IN ULONG StartBusNumber,
  27. IN ULONG EndBusNumber,
  28. IN ULONG MinMem,
  29. IN ULONG MaxMem,
  30. IN USHORT MinIo,
  31. IN USHORT MaxIo,
  32. IN BOOLEAN ConfigureBridges
  33. );
  34. PCIPBUSDATA HalpFakePciBusData = {
  35. {
  36. PCI_DATA_TAG,//Tag
  37. PCI_DATA_VERSION,//Version
  38. (PciReadWriteConfig)HalpReadPCIConfig,//ReadConfig
  39. (PciReadWriteConfig) HalpWritePCIConfig,//WriteConfig
  40. (PciPin2Line)HalpPCIPin2ISALine,//Pin2Line
  41. (PciLine2Pin)HalpPCIISALine2Pin,//Line2Pin
  42. {0},//ParentSlot
  43. NULL,NULL,NULL,NULL//Reserved[4]
  44. },
  45. {0},//Config
  46. PCI_MAX_DEVICES,//MaxDevice
  47. };
  48. BUS_HANDLER HalpFakePciBusHandler = {
  49. BUS_HANDLER_VERSION,//Version
  50. PCIBus,//InterfaceType
  51. PCIConfiguration,//ConfigurationType
  52. 0,//BusNumber
  53. NULL,//DeviceObject
  54. NULL,//ParentHandler
  55. (PPCIBUSDATA)&HalpFakePciBusData,//BusData
  56. 0,//DeviceControlExtensionSize
  57. NULL,//BusAddresses
  58. {0},//Reserved[4]
  59. (PGETSETBUSDATA)HalpGetPCIData,//GetBusData
  60. (PGETSETBUSDATA)HalpSetPCIData,//SetBusData
  61. NULL,//AdjustResourceList
  62. (PASSIGNSLOTRESOURCES)HalpAssignPCISlotResources,//AssignSlotResources
  63. NULL,//GetInterruptVector
  64. NULL,//TranslateBusAddress
  65. };
  66. ULONG HalpMinPciBus = 0;
  67. ULONG HalpMaxPciBus = 0;
  68. PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice[MAX_DEBUGGING_DEVICES_SUPPORTED] = {0};
  69. extern BOOLEAN HalpDoingCrashDump;
  70. PVOID
  71. HalpGetAcpiTablePhase0(
  72. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  73. IN ULONG Signature
  74. );
  75. VOID
  76. HalpFindFreeResourceLimits(
  77. IN ULONG Bus,
  78. IN OUT ULONG *MinIo,
  79. IN OUT ULONG *MaxIo,
  80. IN OUT ULONG *MinMem,
  81. IN OUT ULONG *MaxMem,
  82. IN OUT ULONG *MinBus,
  83. IN OUT ULONG *MaxBus
  84. );
  85. NTSTATUS
  86. HalpSetupUnconfiguredDebuggingDevice(
  87. IN ULONG Bus,
  88. IN ULONG Slot,
  89. IN ULONG IoMin,
  90. IN ULONG IoMax,
  91. IN ULONG MemMin,
  92. IN ULONG MemMax,
  93. IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
  94. );
  95. NTSTATUS
  96. HalpConfigurePciBridge(
  97. IN PDEBUG_DEVICE_DESCRIPTOR PciDevice,
  98. IN ULONG Bus,
  99. IN ULONG Slot,
  100. IN ULONG IoMin,
  101. IN ULONG IoMax,
  102. IN ULONG MemMin,
  103. IN ULONG MemMax,
  104. IN ULONG BusMin,
  105. IN ULONG BusMax,
  106. IN OUT PPCI_COMMON_CONFIG PciData
  107. );
  108. NTSTATUS
  109. HalpConfigureCardBusBridge(
  110. IN PDEBUG_DEVICE_DESCRIPTOR PciDevice,
  111. IN ULONG Bus,
  112. IN ULONG Slot,
  113. IN ULONG IoMin,
  114. IN ULONG IoMax,
  115. IN ULONG MemMin,
  116. IN ULONG MemMax,
  117. IN ULONG BusMin,
  118. IN ULONG BusMax,
  119. IN OUT PPCI_COMMON_CONFIG PciData
  120. );
  121. VOID
  122. HalpUnconfigurePciBridge(
  123. IN ULONG Bus,
  124. IN ULONG Slot
  125. );
  126. VOID
  127. HalpUnconfigureCardBusBridge(
  128. IN ULONG Bus,
  129. IN ULONG Slot
  130. );
  131. ULONG
  132. HalpKdStallExecution(
  133. ULONG LoopCount
  134. );
  135. #ifdef ALLOC_PRAGMA
  136. #pragma alloc_text(INIT,HalpInitializePciStubs)
  137. #pragma alloc_text(INIT,HalpRegisterKdSupportFunctions)
  138. #pragma alloc_text(INIT,HalpRegisterPciDebuggingDeviceInfo)
  139. #pragma alloc_text(PAGEKD,HalpConfigurePciBridge)
  140. #pragma alloc_text(PAGEKD,HalpConfigureCardBusBridge)
  141. #pragma alloc_text(PAGEKD,HalpFindFreeResourceLimits)
  142. #pragma alloc_text(PAGEKD,HalpPhase0GetPciDataByOffset)
  143. #pragma alloc_text(PAGEKD,HalpPhase0SetPciDataByOffset)
  144. #pragma alloc_text(PAGEKD,HalpReleasePciDeviceForDebugging)
  145. #pragma alloc_text(PAGEKD,HalpSearchForPciDebuggingDevice)
  146. #pragma alloc_text(PAGEKD,HalpSetupPciDeviceForDebugging)
  147. #pragma alloc_text(PAGEKD,HalpSetupUnconfiguredDebuggingDevice)
  148. #pragma alloc_text(PAGEKD,HalpUnconfigurePciBridge)
  149. #pragma alloc_text(PAGEKD,HalpUnconfigureCardBusBridge)
  150. #pragma alloc_text(PAGEKD,HalpKdStallExecution)
  151. #endif
  152. VOID
  153. HalpInitializePciStubs (
  154. VOID
  155. )
  156. {
  157. PPCI_REGISTRY_INFO_INTERNAL PCIRegInfo;
  158. PPCIPBUSDATA BusData;
  159. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
  160. ULONG HwType;
  161. ULONG BusNo = 0;
  162. ULONG Bytes;
  163. ULONG Slot;
  164. PCI_COMMON_CONFIG PciData;
  165. PCIRegInfo = HalpQueryPciRegistryInfo();
  166. if (PCIRegInfo) {
  167. //
  168. // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
  169. //
  170. HwType = PCIRegInfo->HardwareMechanism & 0xf;
  171. ExFreePool(PCIRegInfo);
  172. } else {
  173. //
  174. // no PCI bus information was gathered by NTDETECT,
  175. // assume type 1 access.
  176. //
  177. HwType = 1;
  178. }
  179. //
  180. // Initialize spinlock for synchronizing access to PCI space
  181. //
  182. KeInitializeSpinLock (&HalpPCIConfigLock);
  183. BusData = (PPCIPBUSDATA) HalpFakePciBusHandler.BusData;
  184. //
  185. // Set defaults
  186. //
  187. switch (HwType) {
  188. case 1:
  189. //
  190. // Initialize access port information for Type1 handlers
  191. //
  192. RtlCopyMemory (&PCIConfigHandler,
  193. &PCIConfigHandlerType1,
  194. sizeof (PCIConfigHandler));
  195. BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
  196. BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
  197. break;
  198. case 2:
  199. //
  200. // Initialize access port information for Type2 handlers
  201. //
  202. RtlCopyMemory (&PCIConfigHandler,
  203. &PCIConfigHandlerType2,
  204. sizeof (PCIConfigHandler));
  205. BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
  206. BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
  207. BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
  208. //
  209. // Early PCI machines didn't decode the last bit of
  210. // the device id. Shrink type 2 support max device.
  211. //
  212. BusData->MaxDevice = 0x10;
  213. break;
  214. default:
  215. // unsupport type
  216. DBGMSG ("HAL: Unkown PCI type\n");
  217. }
  218. //
  219. // Make a good guess about how many PCI busses are in the system
  220. // and initialize HalpMaxPciBus with this guess. When the PCI
  221. // driver starts, we will get a better answer here.
  222. //
  223. // Calling HaliPciInterfaceReadConfig has the side effect of
  224. // bumping up HalpMaxPciBus if it hits a populated device. So
  225. // the algorithm here is to just keep searching for devices until
  226. // we have searched 0x10 busses higher than the current maximum.
  227. //
  228. while (BusNo < 0x100) {
  229. //
  230. // Scan across this bus. As soon as we find a device,
  231. // then move on to another bus.
  232. //
  233. for (Slot = 0;
  234. Slot < PCI_MAX_DEVICES;
  235. Slot++) {
  236. Bytes = HaliPciInterfaceReadConfig(NULL,
  237. (UCHAR)BusNo,
  238. Slot,
  239. (PVOID)&PciData,
  240. 0,
  241. 4
  242. );
  243. if ((Bytes != 0) &&
  244. (PciData.VendorID != PCI_INVALID_VENDORID)) {
  245. //
  246. // This was a populated device. Bump up HalpMaxPciBus.
  247. //
  248. HalpMaxPciBus = BusNo;
  249. break;
  250. }
  251. }
  252. BusNo++;
  253. }
  254. }
  255. ULONG
  256. HaliPciInterfaceReadConfig(
  257. IN PVOID Context,
  258. IN UCHAR BusOffset,
  259. IN ULONG Slot,
  260. IN PVOID Buffer,
  261. IN ULONG Offset,
  262. IN ULONG Length
  263. )
  264. {
  265. PCI_SLOT_NUMBER slotNum;
  266. BUS_HANDLER busHand;
  267. UNREFERENCED_PARAMETER(Context);
  268. slotNum.u.AsULONG = Slot;
  269. //
  270. // Fake a bus handler.
  271. //
  272. RtlCopyMemory(&busHand, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
  273. //
  274. // Calculate the right bus number.
  275. //
  276. busHand.BusNumber = BusOffset;
  277. HalpReadPCIConfig(&busHand,
  278. slotNum,
  279. Buffer,
  280. Offset,
  281. Length
  282. );
  283. //
  284. // This is a hack. The legacy HAL interfaces need to be able
  285. // to distinguish between busses that exist and busses that
  286. // don't. And many users of the legacy interfaces implicitly
  287. // assume that PCI busses are tightly packed. (i.e. All busses
  288. // between the lowest numbered one and the highest numbered one
  289. // exist.) So here we are keeping track of the highest numbered
  290. // bus that we have seen so far.
  291. //
  292. if ((Length >= 2) &&
  293. (((PPCI_COMMON_CONFIG)Buffer)->VendorID != PCI_INVALID_VENDORID)) {
  294. //
  295. // This is a valid device.
  296. //
  297. if (busHand.BusNumber > HalpMaxPciBus) {
  298. //
  299. // This is the highest numbered bus we have
  300. // yet seen.
  301. //
  302. HalpMaxPciBus = busHand.BusNumber;
  303. }
  304. }
  305. return Length;
  306. }
  307. ULONG
  308. HaliPciInterfaceWriteConfig(
  309. IN PVOID Context,
  310. IN UCHAR BusOffset,
  311. IN ULONG Slot,
  312. IN PVOID Buffer,
  313. IN ULONG Offset,
  314. IN ULONG Length
  315. )
  316. {
  317. PCI_SLOT_NUMBER slotNum;
  318. BUS_HANDLER busHand;
  319. UNREFERENCED_PARAMETER(Context);
  320. slotNum.u.AsULONG = Slot;
  321. //
  322. // Fake a bus handler.
  323. //
  324. RtlCopyMemory(&busHand, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
  325. //
  326. // Calculate the right bus number.
  327. //
  328. busHand.BusNumber = BusOffset;
  329. HalpWritePCIConfig(&busHand,
  330. slotNum,
  331. Buffer,
  332. Offset,
  333. Length
  334. );
  335. return Length;
  336. }
  337. VOID
  338. HaliSetMaxLegacyPciBusNumber(
  339. IN ULONG BusNumber
  340. )
  341. /*++
  342. Routine Description:
  343. This routine bumps the Legacy PCI bus maximum up to whatever
  344. is passed in. This may be necessary because the ACPI driver
  345. needs to run a configuration cycle to a PCI device before the
  346. PCI driver loads. This happens mostly in the context of a
  347. _REG method.
  348. Arguments:
  349. BusNumber - max PCI bus number
  350. Return Value:
  351. none
  352. Notes:
  353. Caller is responsible for acquiring any necessary PCI config
  354. spinlocks.
  355. --*/
  356. {
  357. if (BusNumber > HalpMaxPciBus) {
  358. HalpMaxPciBus = BusNumber;
  359. }
  360. }
  361. ULONG
  362. HalpPhase0SetPciDataByOffset (
  363. ULONG BusNumber,
  364. ULONG SlotNumber,
  365. PVOID Buffer,
  366. ULONG Offset,
  367. ULONG Length
  368. )
  369. /*++
  370. Routine Description:
  371. This routine writes to PCI configuration space prior to bus handler
  372. installation.
  373. Arguments:
  374. BusNumber PCI Bus Number. This is the 8 bit BUS Number which is
  375. bits 23-16 of the Configuration Address. In support of
  376. multiple top level busses, the upper 24 bits of this
  377. argument will supply the index into the table of
  378. configuration address registers.
  379. SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device
  380. number (bits 15-11 of the configuration address) and
  381. the 3 bit function number (10-8).
  382. Buffer Address of source data.
  383. Offset Number of bytes to skip from base of PCI config area.
  384. Length Number of bytes to write
  385. Return Value:
  386. Returns length of data written.
  387. Notes:
  388. Caller is responsible for acquiring any necessary PCI config
  389. spinlocks.
  390. --*/
  391. {
  392. PCI_TYPE1_CFG_BITS ConfigAddress;
  393. ULONG ReturnLength;
  394. PCI_SLOT_NUMBER slot;
  395. PUCHAR Bfr = (PUCHAR)Buffer;
  396. ASSERT(!(Offset & ~0xff));
  397. ASSERT(Length);
  398. ASSERT((Offset + Length) <= 256);
  399. if ( Length + Offset > 256 ) {
  400. if ( Offset > 256 ) {
  401. return 0;
  402. }
  403. Length = 256 - Offset;
  404. }
  405. ReturnLength = Length;
  406. slot.u.AsULONG = SlotNumber;
  407. ConfigAddress.u.bits.BusNumber = BusNumber;
  408. ConfigAddress.u.bits.DeviceNumber = slot.u.bits.DeviceNumber;
  409. ConfigAddress.u.bits.FunctionNumber = slot.u.bits.FunctionNumber;
  410. ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2;
  411. ConfigAddress.u.bits.Enable = TRUE;
  412. if ( Offset & 0x3 ) {
  413. //
  414. // Access begins at a non-register boundary in the config
  415. // space. We need to read the register containing the data
  416. // and rewrite only the changed data. (I wonder if this
  417. // ever really happens?)
  418. //
  419. ULONG SubOffset = Offset & 0x3;
  420. ULONG SubLength = 4 - SubOffset;
  421. union {
  422. ULONG All;
  423. UCHAR Bytes[4];
  424. } Tmp;
  425. if ( SubLength > Length ) {
  426. SubLength = Length;
  427. }
  428. //
  429. // Adjust Length (remaining) and (new) Offset by amount covered
  430. // in this first word.
  431. //
  432. Length -= SubLength;
  433. Offset += SubLength;
  434. //
  435. // Get the first word (register), replace only those bytes that
  436. // need to be changed, then write the whole thing back out again.
  437. //
  438. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDR_PORT, ConfigAddress.u.AsULONG);
  439. Tmp.All = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT);
  440. while ( SubLength-- ) {
  441. Tmp.Bytes[SubOffset++] = *Bfr++;
  442. }
  443. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT, Tmp.All);
  444. //
  445. // Aim ConfigAddressRegister at the next word (register).
  446. //
  447. ConfigAddress.u.bits.RegisterNumber++;
  448. }
  449. //
  450. // Do the majority of the transfer 4 bytes at a time.
  451. //
  452. while ( Length > sizeof(ULONG) ) {
  453. ULONG Tmp = *(UNALIGNED PULONG)Bfr;
  454. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDR_PORT, ConfigAddress.u.AsULONG);
  455. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT, Tmp);
  456. ConfigAddress.u.bits.RegisterNumber++;
  457. Bfr += sizeof(ULONG);
  458. Length -= sizeof(ULONG);
  459. }
  460. //
  461. // Do bytes in last register.
  462. //
  463. if ( Length ) {
  464. union {
  465. ULONG All;
  466. UCHAR Bytes[4];
  467. } Tmp;
  468. ULONG i = 0;
  469. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDR_PORT, ConfigAddress.u.AsULONG);
  470. Tmp.All = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT);
  471. while ( Length-- ) {
  472. Tmp.Bytes[i++] = *(PUCHAR)Bfr++;
  473. }
  474. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT, Tmp.All);
  475. }
  476. return ReturnLength;
  477. }
  478. ULONG
  479. HalpPhase0GetPciDataByOffset (
  480. ULONG BusNumber,
  481. ULONG SlotNumber,
  482. PVOID Buffer,
  483. ULONG Offset,
  484. ULONG Length
  485. )
  486. /*++
  487. Routine Description:
  488. This routine reads PCI config space prior to bus handlder installation.
  489. Arguments:
  490. BusNumber PCI Bus Number. This is the 8 bit BUS Number which is
  491. bits 23-16 of the Configuration Address. In support of
  492. multiple top level busses, the upper 24 bits of this
  493. argument will supply the index into the table of
  494. configuration address registers.
  495. SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device
  496. number (bits 15-11 of the configuration address) and
  497. the 3 bit function number (10-8).
  498. Buffer Address of source data.
  499. Offset Number of bytes to skip from base of PCI config area.
  500. Length Number of bytes to write
  501. Return Value:
  502. Amount of data read.
  503. --*/
  504. {
  505. PCI_TYPE1_CFG_BITS ConfigAddress;
  506. PCI_TYPE1_CFG_BITS ConfigAddressTemp;
  507. ULONG ReturnLength;
  508. ULONG i;
  509. PCI_SLOT_NUMBER slot;
  510. union {
  511. ULONG All;
  512. UCHAR Bytes[4];
  513. } Tmp;
  514. ASSERT(!(Offset & ~0xff));
  515. ASSERT(Length);
  516. ASSERT((Offset + Length) <= 256);
  517. if ( Length + Offset > 256 ) {
  518. if ( Offset > 256 ) {
  519. return 0;
  520. }
  521. Length = 256 - Offset;
  522. }
  523. ReturnLength = Length;
  524. slot.u.AsULONG = SlotNumber;
  525. ConfigAddress.u.bits.BusNumber = BusNumber;
  526. ConfigAddress.u.bits.DeviceNumber = slot.u.bits.DeviceNumber;
  527. ConfigAddress.u.bits.FunctionNumber = slot.u.bits.FunctionNumber;
  528. ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2;
  529. ConfigAddress.u.bits.Enable = TRUE;
  530. //
  531. // If we are being asked to read data when function != 0, check
  532. // first to see if this device decares itself as a multi-function
  533. // device. If it doesn't, don't do this read.
  534. //
  535. if (ConfigAddress.u.bits.FunctionNumber != 0) {
  536. ConfigAddressTemp.u.bits.RegisterNumber = 3; // contains header type
  537. ConfigAddressTemp.u.bits.FunctionNumber = 0; // look at base package
  538. ConfigAddressTemp.u.bits.DeviceNumber = ConfigAddress.u.bits.DeviceNumber;
  539. ConfigAddressTemp.u.bits.BusNumber = ConfigAddress.u.bits.BusNumber;
  540. ConfigAddressTemp.u.bits.Enable = TRUE;
  541. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDR_PORT, ConfigAddressTemp.u.AsULONG);
  542. Tmp.All = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT);
  543. if (!(Tmp.Bytes[2] & 0x80)) { // if the Header type field's multi-function bit is not set
  544. for (i = 0; i < Length; i++) {
  545. *((PUCHAR)Buffer)++ = 0xff; // Make this read as if the device isn't populated
  546. }
  547. return Length;
  548. }
  549. }
  550. i = Offset & 0x3;
  551. while ( Length ) {
  552. WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDR_PORT, ConfigAddress.u.AsULONG);
  553. Tmp.All = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT);
  554. while ( (i < 4) && Length) {
  555. *((PUCHAR)Buffer)++ = Tmp.Bytes[i];
  556. i++;
  557. Length--;
  558. }
  559. i = 0;
  560. ConfigAddress.u.bits.RegisterNumber++;
  561. }
  562. return ReturnLength;
  563. }
  564. NTSTATUS
  565. HalpSetupPciDeviceForDebugging(
  566. IN PLOADER_PARAMETER_BLOCK LoaderBlock, OPTIONAL
  567. IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
  568. )
  569. /*++
  570. Routine Description:
  571. This routine finds and initializes a PCI device to be
  572. used for communicating with a debugger.
  573. The caller fills in as much of DEBUG_DEVICE_DESCRIPTOR
  574. as it cares to, filling unused fields with (-1).
  575. This routine attempts to find a matching PCI device. It
  576. matches first based on Bus and Slot, if the caller has
  577. provided them. Then it matches on VendorID/DeviceID, if
  578. the caller has provided them. Last, it matches on
  579. BaseClass/SubClass.
  580. This routine will fill in any unused fields in the structure
  581. so that the caller can know specifically which PCI
  582. device matched the criteria.
  583. If the matching PCI device is not enabled, or it is
  584. behind a PCI to PCI bridge that is not enabled, this
  585. routine makes a best-effort attempt to find a safe
  586. configuration that allows the device (and possibly bridges)
  587. to function, and enables them.
  588. If the PCI device implements memory mapped Base Address
  589. registers, this function will create a virtual to physical
  590. mapping for the memory ranges implied by the Base Address
  591. Registers and fill in the TranslatedAddress field with
  592. virtual pointers to the bases of the ranges. It will then
  593. fill in the Type field with CmResourceTypeMemory. And
  594. the Valid field with be TRUE.
  595. If the PCI device implements I/O port Base Address registers,
  596. this function will put the translated port address in
  597. TranslatedAddress, setting the Type field to CmResourceTypePort
  598. and the Valid field to TRUE.
  599. If the PCI device does not implement a specific Base Address
  600. Register, the Valid field will be FALSE.
  601. Arguments:
  602. PciDevice - Structure indicating the device
  603. Return Value:
  604. STATUS_SUCCESS if the device is configured and usable.
  605. STATUS_NO_MORE_MATCHES if no device matched the criteria.
  606. STATUS_INSUFFICIENT_RESOURCES if the memory requirements
  607. couldn't be met.
  608. STATUS_UNSUCCESSFUL if the routine failed for other reasons.
  609. --*/
  610. {
  611. NTSTATUS status;
  612. PCI_SLOT_NUMBER slot;
  613. ULONG i, j;
  614. ULONG maxPhys;
  615. status = HalpSearchForPciDebuggingDevice(
  616. PciDevice,
  617. 0,
  618. 0xff,
  619. 0x10000000,
  620. 0xfc000000,
  621. 0x1000,
  622. 0xffff,
  623. FALSE);
  624. if (!NT_SUCCESS(status)) {
  625. //
  626. // We didn't find the device using a conservative
  627. // search. Try a more invasive one.
  628. //
  629. status = HalpSearchForPciDebuggingDevice(
  630. PciDevice,
  631. 0,
  632. 0xff,
  633. 0x10000000,
  634. 0xfc000000,
  635. 0x1000,
  636. 0xffff,
  637. TRUE);
  638. }
  639. //
  640. // Record the Bus/Dev/Func so that we can stuff it in the
  641. // registry later.
  642. //
  643. if (NT_SUCCESS(status)) {
  644. if (PciDevice->Initialized) {
  645. //
  646. // Here we were just asked to reconfigure the bridges since
  647. // we already
  648. //
  649. return status;
  650. }
  651. slot.u.AsULONG = PciDevice->Slot;
  652. for (i = 0;
  653. i < MAX_DEBUGGING_DEVICES_SUPPORTED;
  654. i++) {
  655. if ((HalpPciDebuggingDevice[i].u.bits.Reserved1 == TRUE) &&
  656. (HalpPciDebuggingDevice[i].u.bits.FunctionNumber ==
  657. slot.u.bits.FunctionNumber) &&
  658. (HalpPciDebuggingDevice[i].u.bits.DeviceNumber ==
  659. slot.u.bits.DeviceNumber) &&
  660. (HalpPciDebuggingDevice[i].u.bits.BusNumber ==
  661. PciDevice->Bus)) {
  662. //
  663. // This device has already been set up for
  664. // debugging. Thus we should refuse to set
  665. // it up again.
  666. //
  667. return STATUS_UNSUCCESSFUL;
  668. }
  669. }
  670. for (i = 0;
  671. i < MAX_DEBUGGING_DEVICES_SUPPORTED;
  672. i++) {
  673. if (HalpPciDebuggingDevice[i].u.bits.Reserved1 == FALSE) {
  674. //
  675. // This slot is available.
  676. //
  677. HalpPciDebuggingDevice[i].u.bits.FunctionNumber =
  678. slot.u.bits.FunctionNumber;
  679. HalpPciDebuggingDevice[i].u.bits.DeviceNumber =
  680. slot.u.bits.DeviceNumber;
  681. HalpPciDebuggingDevice[i].u.bits.BusNumber = PciDevice->Bus;
  682. HalpPciDebuggingDevice[i].u.bits.Reserved1 = TRUE;
  683. PciDevice->Initialized = TRUE;
  684. break;
  685. }
  686. }
  687. //
  688. // Check to see if the caller wants any memory.
  689. //
  690. if (PciDevice->Memory.Length != 0) {
  691. if (!LoaderBlock) {
  692. return STATUS_INVALID_PARAMETER_1;
  693. }
  694. if (PciDevice->Memory.MaxEnd.QuadPart == 0) {
  695. PciDevice->Memory.MaxEnd.QuadPart = -1;
  696. }
  697. maxPhys = PciDevice->Memory.MaxEnd.HighPart ? 0xffffffff : PciDevice->Memory.MaxEnd.LowPart;
  698. maxPhys -= PciDevice->Memory.Length;
  699. //
  700. // The HAL APIs will always return page-aligned
  701. // memory. So ignore Aligned for now.
  702. //
  703. maxPhys = PtrToUlong(PAGE_ALIGN(maxPhys));
  704. maxPhys += ADDRESS_AND_SIZE_TO_SPAN_PAGES(maxPhys, PciDevice->Memory.Length);
  705. PciDevice->Memory.Start.HighPart = 0;
  706. PciDevice->Memory.Start.LowPart =
  707. HalpAllocPhysicalMemory(LoaderBlock,
  708. maxPhys,
  709. ADDRESS_AND_SIZE_TO_SPAN_PAGES(maxPhys, PciDevice->Memory.Length),
  710. FALSE);
  711. if (!PciDevice->Memory.Start.LowPart) {
  712. return STATUS_INSUFFICIENT_RESOURCES;
  713. }
  714. PciDevice->Memory.VirtualAddress =
  715. HalpMapPhysicalMemory64(PciDevice->Memory.Start,
  716. ADDRESS_AND_SIZE_TO_SPAN_PAGES(maxPhys, PciDevice->Memory.Length));
  717. }
  718. }
  719. return status;
  720. }
  721. VOID
  722. HalpFindFreeResourceLimits(
  723. IN ULONG Bus,
  724. IN OUT ULONG *MinIo,
  725. IN OUT ULONG *MaxIo,
  726. IN OUT ULONG *MinMem,
  727. IN OUT ULONG *MaxMem,
  728. IN OUT ULONG *MinBus,
  729. IN OUT ULONG *MaxBus
  730. )
  731. {
  732. UCHAR buffer[PCI_COMMON_HDR_LENGTH];
  733. PPCI_COMMON_CONFIG pciData;
  734. UCHAR bus, dev, func, bytesRead;
  735. PCI_SLOT_NUMBER pciSlot, targetSlot;
  736. ULONG newMinMem, newMaxMem;
  737. ULONG newMinIo, newMaxIo;
  738. ULONG newMinBus, newMaxBus;
  739. UCHAR barNo;
  740. pciData = (PPCI_COMMON_CONFIG)buffer;
  741. pciSlot.u.AsULONG = 0;
  742. newMinMem = *MinMem;
  743. newMaxMem = *MaxMem;
  744. newMinIo = *MinIo;
  745. newMaxIo = *MaxIo;
  746. newMinBus = *MinBus;
  747. newMaxBus = *MaxBus;
  748. for (dev = 0; dev < PCI_MAX_DEVICES; dev++) {
  749. for (func = 0; func < PCI_MAX_FUNCTION; func++) {
  750. pciSlot.u.bits.DeviceNumber = dev;
  751. pciSlot.u.bits.FunctionNumber = func;
  752. bytesRead = (UCHAR)HalpPhase0GetPciDataByOffset(Bus,
  753. pciSlot.u.AsULONG,
  754. pciData,
  755. 0,
  756. PCI_COMMON_HDR_LENGTH);
  757. if (bytesRead == 0) continue;
  758. if (pciData->VendorID != PCI_INVALID_VENDORID) {
  759. switch (PCI_CONFIGURATION_TYPE(pciData)) {
  760. case PCI_DEVICE_TYPE:
  761. //
  762. // While we scan across the bus, keep track
  763. // of the minimum decoder values that we've seen.
  764. // This will be used if we have to configure the
  765. // device. This relies on the fact that most BIOSes
  766. // assign addresses from the top down.
  767. //
  768. for (barNo = 0; barNo < PCI_TYPE0_ADDRESSES; barNo++) {
  769. if (pciData->u.type0.BaseAddresses[barNo] &
  770. PCI_ADDRESS_IO_SPACE) {
  771. if (pciData->u.type0.BaseAddresses[barNo] &
  772. PCI_ADDRESS_IO_ADDRESS_MASK) {
  773. //
  774. // This BAR is implemented
  775. //
  776. if ((pciData->u.type0.BaseAddresses[barNo] &
  777. PCI_ADDRESS_IO_ADDRESS_MASK) <
  778. ((newMaxIo / 2) + (newMinIo / 2))) {
  779. //
  780. // This BAR is at the bottom of the range.
  781. // Bump up the min.
  782. //
  783. newMinIo = (USHORT)MAX (newMinIo,
  784. (pciData->u.type0.BaseAddresses[barNo] &
  785. PCI_ADDRESS_IO_ADDRESS_MASK) + 0x100);
  786. } else {
  787. //
  788. // This BAR is not at the bottom of the range.
  789. // Bump down the max.
  790. //
  791. newMaxIo = (USHORT)MIN (newMaxIo,
  792. pciData->u.type0.BaseAddresses[barNo] &
  793. PCI_ADDRESS_IO_ADDRESS_MASK);
  794. }
  795. }
  796. } else {
  797. if (pciData->u.type0.BaseAddresses[barNo] &
  798. PCI_ADDRESS_MEMORY_ADDRESS_MASK) {
  799. //
  800. // The BAR is populated.
  801. //
  802. if ((pciData->u.type0.BaseAddresses[barNo] &
  803. PCI_ADDRESS_MEMORY_ADDRESS_MASK) <
  804. ((newMaxMem / 2) + (newMinMem / 2))) {
  805. //
  806. // This BAR is at the bottom of the range.
  807. // Bump up the min.
  808. //
  809. newMinMem = MAX (newMinMem,
  810. (pciData->u.type0.BaseAddresses[barNo] &
  811. PCI_ADDRESS_MEMORY_ADDRESS_MASK) + 0x10000);
  812. } else {
  813. //
  814. // This BAR is not at the bottom of the range.
  815. // Bump down the max.
  816. //
  817. newMaxMem = MIN (newMaxMem,
  818. (pciData->u.type0.BaseAddresses[barNo] &
  819. PCI_ADDRESS_MEMORY_ADDRESS_MASK));
  820. }
  821. }
  822. }
  823. }
  824. break;
  825. case PCI_CARDBUS_BRIDGE_TYPE:
  826. {
  827. ULONG bridgeMemMin = 0, bridgeMemMax = 0;
  828. USHORT bridgeIoMin, bridgeIoMax;
  829. ULONG LegacyBaseAddress;
  830. UCHAR bytesRead;
  831. bytesRead = (UCHAR) HalpPhase0GetPciDataByOffset(Bus,
  832. pciSlot.u.AsULONG,
  833. &LegacyBaseAddress,
  834. CARDBUS_LEGACY_MODE_BASE_ADDR,
  835. 4);
  836. if (bytesRead != 4) continue;
  837. if ((LegacyBaseAddress & ~1) &&
  838. (pciData->u.type2.SecondaryBus != 0) &&
  839. (pciData->u.type2.SubordinateBus !=0) &&
  840. (pciData->u.type2.Range[0].Base != 0) &&
  841. (pciData->u.type2.SocketRegistersBaseAddress != 0) &&
  842. (pciData->Command & PCI_ENABLE_MEMORY_SPACE) &&
  843. (pciData->Command & PCI_ENABLE_IO_SPACE)) {
  844. bridgeMemMin = pciData->u.type2.Range[0].Base;
  845. bridgeMemMax = pciData->u.type2.Range[0].Limit | 0xfff;
  846. bridgeIoMin = (USHORT)pciData->u.type2.Range[2].Base;
  847. bridgeIoMax = (USHORT)pciData->u.type2.Range[2].Limit | 0x3;
  848. //
  849. // Keep track of address space allocation.
  850. //
  851. if (bridgeIoMin > ((newMaxIo / 2) + (newMinIo / 2))) {
  852. newMaxIo = MIN(newMaxIo, bridgeIoMin);
  853. }
  854. if (bridgeIoMax < ((newMaxIo / 2) + (newMinIo / 2))) {
  855. newMinIo = MAX(newMinIo, bridgeIoMax) + 1;
  856. }
  857. if (bridgeMemMin > ((newMaxMem / 2) + (newMinMem / 2))) {
  858. newMaxMem = MIN(newMaxMem, bridgeMemMin);
  859. }
  860. if (bridgeMemMax < ((newMaxMem / 2) + (newMinMem / 2))) {
  861. newMinMem = MAX(newMinMem, bridgeMemMax) + 1;
  862. }
  863. //
  864. // Keep track of bus numbers.
  865. //
  866. if (pciData->u.type2.PrimaryBus > ((newMaxBus / 2) + (newMinBus / 2))) {
  867. newMaxBus = MIN(newMaxBus, pciData->u.type2.PrimaryBus);
  868. }
  869. if (pciData->u.type2.SubordinateBus < ((newMaxBus / 2) + (newMinBus / 2))) {
  870. newMinBus = MAX(newMinBus, pciData->u.type2.SubordinateBus) + 1;
  871. }
  872. }
  873. }
  874. break;
  875. case PCI_BRIDGE_TYPE:
  876. {
  877. ULONG bridgeMemMin = 0, bridgeMemMax = 0;
  878. USHORT bridgeIoMin, bridgeIoMax;
  879. if ((pciData->u.type1.SecondaryBus != 0) &&
  880. (pciData->u.type1.SubordinateBus !=0) &&
  881. (pciData->Command & PCI_ENABLE_MEMORY_SPACE) &&
  882. (pciData->Command & PCI_ENABLE_IO_SPACE)) {
  883. bridgeMemMin = PciBridgeMemory2Base(pciData->u.type1.MemoryBase);
  884. bridgeMemMax = PciBridgeMemory2Limit(pciData->u.type1.MemoryLimit);
  885. bridgeIoMin = (USHORT)PciBridgeIO2Base(pciData->u.type1.IOBase, 0);
  886. bridgeIoMax = (USHORT)PciBridgeIO2Limit(pciData->u.type1.IOLimit, 0);
  887. //
  888. // Keep track of address space allocation.
  889. //
  890. if (bridgeIoMin > ((newMaxIo / 2) + (newMinIo / 2))) {
  891. newMaxIo = MIN(newMaxIo, bridgeIoMin);
  892. }
  893. if (bridgeIoMax < ((newMaxIo / 2) + (newMinIo / 2))) {
  894. newMinIo = MAX(newMinIo, bridgeIoMax) + 1;
  895. }
  896. if (bridgeMemMin > ((newMaxMem / 2) + (newMinMem / 2))) {
  897. newMaxMem = MIN(newMaxMem, bridgeMemMin);
  898. }
  899. if (bridgeMemMax < ((newMaxMem / 2) + (newMinMem / 2))) {
  900. newMinMem = MAX(newMinMem, bridgeMemMax) + 1;
  901. }
  902. //
  903. // Keep track of bus numbers.
  904. //
  905. if (pciData->u.type1.PrimaryBus > ((newMaxBus / 2) + (newMinBus / 2))) {
  906. newMaxBus = MIN(newMaxBus, pciData->u.type1.PrimaryBus);
  907. }
  908. if (pciData->u.type1.SubordinateBus < ((newMaxBus / 2) + (newMinBus / 2))) {
  909. newMinBus = MAX(newMinBus, pciData->u.type1.SubordinateBus) + 1;
  910. }
  911. }
  912. break;
  913. default:
  914. break;
  915. }
  916. }
  917. if (!PCI_MULTIFUNCTION_DEVICE(pciData) &&
  918. (func == 0)) {
  919. break;
  920. }
  921. }
  922. }
  923. }
  924. *MinMem = newMinMem;
  925. *MaxMem = newMaxMem;
  926. *MinIo = newMinIo;
  927. *MaxIo = newMaxIo;
  928. *MinBus = newMinBus;
  929. *MaxBus = newMaxBus;
  930. }
  931. NTSTATUS
  932. HalpSetupUnconfiguredDebuggingDevice(
  933. IN ULONG Bus,
  934. IN ULONG Slot,
  935. IN ULONG IoMin,
  936. IN ULONG IoMax,
  937. IN ULONG MemMin,
  938. IN ULONG MemMax,
  939. IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
  940. )
  941. {
  942. UCHAR buffer[PCI_COMMON_HDR_LENGTH];
  943. PPCI_COMMON_CONFIG pciData;
  944. ULONG barLength, bytesRead;
  945. ULONG barContents = 0;
  946. PHYSICAL_ADDRESS physicalAddress;
  947. PCI_SLOT_NUMBER pciSlot;
  948. UCHAR barNo;
  949. pciSlot.u.AsULONG = Slot;
  950. pciData = (PPCI_COMMON_CONFIG)buffer;
  951. bytesRead = (UCHAR)HalpPhase0GetPciDataByOffset(Bus,
  952. pciSlot.u.AsULONG,
  953. pciData,
  954. 0,
  955. PCI_COMMON_HDR_LENGTH);
  956. ASSERT(bytesRead != 0);
  957. PciDevice->Bus = Bus;
  958. PciDevice->Slot = pciSlot.u.AsULONG;
  959. PciDevice->VendorID = pciData->VendorID;
  960. PciDevice->DeviceID = pciData->DeviceID;
  961. PciDevice->BaseClass = pciData->BaseClass;
  962. PciDevice->SubClass = pciData->SubClass;
  963. //DbgPrint("Configuring device between %x - %x\n",
  964. // MemMin, MemMax);
  965. //
  966. // Cycle through the BARs, turning them on if necessary,
  967. // and mapping them.
  968. //
  969. for (barNo = 0; barNo < PCI_TYPE0_ADDRESSES; barNo++) {
  970. barContents = 0xffffffff;
  971. PciDevice->BaseAddress[barNo].Valid = FALSE;
  972. HalpPhase0SetPciDataByOffset(Bus,
  973. pciSlot.u.AsULONG,
  974. &barContents,
  975. 0x10 + (4 * barNo),
  976. 4);
  977. HalpPhase0GetPciDataByOffset(Bus,
  978. pciSlot.u.AsULONG,
  979. &barContents,
  980. 0x10 + (4 * barNo),
  981. 4);
  982. if (pciData->u.type0.BaseAddresses[barNo] &
  983. PCI_ADDRESS_IO_SPACE) {
  984. //
  985. // This is an I/O BAR.
  986. //
  987. barLength = (((USHORT)barContents & PCI_ADDRESS_IO_ADDRESS_MASK) - 1) ^
  988. 0xffff;
  989. if (!(pciData->u.type0.BaseAddresses[barNo] &
  990. PCI_ADDRESS_IO_ADDRESS_MASK)) {
  991. //
  992. // And it's empty.
  993. //
  994. //
  995. // Try to fit this I/O window half-way between the min and the max.
  996. //
  997. if ((ULONG)(IoMax - IoMin) >= (barLength * 3)) {
  998. //
  999. // There is plenty of room, make a safe guess. Try
  1000. // to put it half-way between the upper and lower
  1001. // bounds, rounding up to the next natural alignment.
  1002. //
  1003. pciData->u.type0.BaseAddresses[barNo] =
  1004. (((IoMax / 2) + (IoMin / 2)) + barLength) & (barLength -1);
  1005. } else if (barLength >= (IoMax -
  1006. ((IoMin & (barLength -1)) ?
  1007. ((IoMin + barLength) & (barLength -1)) :
  1008. IoMin))) {
  1009. //
  1010. // Space is tight, make a not-so-safe guess. Try
  1011. // to put it at the bottom of the range, rounded
  1012. // up the the next natural alignment.
  1013. //
  1014. pciData->u.type0.BaseAddresses[barNo] =
  1015. ((IoMin & (barLength -1)) ?
  1016. ((IoMin + barLength) & (barLength -1)) :
  1017. IoMin);
  1018. }
  1019. IoMin = (USHORT)pciData->u.type0.BaseAddresses[barNo];
  1020. }
  1021. pciData->Command |= PCI_ENABLE_IO_SPACE;
  1022. PciDevice->BaseAddress[barNo].Type = CmResourceTypePort;
  1023. PciDevice->BaseAddress[barNo].Valid = TRUE;
  1024. PciDevice->BaseAddress[barNo].TranslatedAddress =
  1025. (PUCHAR)(ULONG_PTR)(pciData->u.type0.BaseAddresses[barNo] &
  1026. PCI_ADDRESS_IO_ADDRESS_MASK);
  1027. PciDevice->BaseAddress[barNo].Length = barLength;
  1028. } else {
  1029. //
  1030. // This is a memory BAR.
  1031. //
  1032. barLength = ((barContents & PCI_ADDRESS_MEMORY_ADDRESS_MASK) - 1) ^
  1033. 0xffffffff;
  1034. if (!(pciData->u.type0.BaseAddresses[barNo] &
  1035. PCI_ADDRESS_MEMORY_ADDRESS_MASK)) {
  1036. //
  1037. // And it's empty.
  1038. //
  1039. if (barLength == 0) continue;
  1040. //
  1041. // Try to fit this memory window half-way between the min and the max.
  1042. //
  1043. if ((ULONG)(MemMax - MemMin) >= (barLength * 3)) {
  1044. //
  1045. // There is plenty of room, make a safe guess. Try
  1046. // to put it half-way between the upper and lower
  1047. // bounds, rounding up to the next natural alignment.
  1048. //
  1049. pciData->u.type0.BaseAddresses[barNo] =
  1050. (ULONG)(((MemMax / 2) + (MemMin / 2))
  1051. + barLength) & ~(barLength -1);
  1052. } else if (barLength >= (ULONG)(MemMax -
  1053. ((MemMin & ~(barLength -1)) ?
  1054. ((MemMin + barLength) & ~(barLength -1)) :
  1055. MemMin))) {
  1056. //
  1057. // Space is tight, make a not-so-safe guess. Try
  1058. // to put it at the bottom of the range, rounded
  1059. // up the the next natural alignment.
  1060. //
  1061. pciData->u.type0.BaseAddresses[barNo] =
  1062. (ULONG)((MemMin & ~(barLength -1)) ?
  1063. ((MemMin + barLength) & ~(barLength -1)) :
  1064. MemMin);
  1065. }
  1066. MemMin = pciData->u.type0.BaseAddresses[barNo] &
  1067. PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  1068. }
  1069. pciData->Command |= PCI_ENABLE_MEMORY_SPACE;
  1070. physicalAddress.HighPart = 0;
  1071. physicalAddress.LowPart = pciData->u.type0.BaseAddresses[barNo]
  1072. & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
  1073. PciDevice->BaseAddress[barNo].Type = CmResourceTypeMemory;
  1074. PciDevice->BaseAddress[barNo].Valid = TRUE;
  1075. PciDevice->BaseAddress[barNo].TranslatedAddress =
  1076. HalpMapPhysicalMemory64(physicalAddress,
  1077. ADDRESS_AND_SIZE_TO_SPAN_PAGES(physicalAddress.LowPart, barLength));
  1078. PciDevice->BaseAddress[barNo].Length = barLength;
  1079. }
  1080. }
  1081. pciData->Command |= PCI_ENABLE_BUS_MASTER;
  1082. //
  1083. // Write back any changes we made.
  1084. //
  1085. HalpPhase0SetPciDataByOffset(Bus,
  1086. pciSlot.u.AsULONG,
  1087. pciData,
  1088. 0,
  1089. 0x40);
  1090. return STATUS_SUCCESS;
  1091. }
  1092. NTSTATUS
  1093. HalpSearchForPciDebuggingDevice(
  1094. IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice,
  1095. IN ULONG StartBusNumber,
  1096. IN ULONG EndBusNumber,
  1097. IN ULONG MinMem,
  1098. IN ULONG MaxMem,
  1099. IN USHORT MinIo,
  1100. IN USHORT MaxIo,
  1101. IN BOOLEAN ConfigureBridges
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. This routine is a helper function for
  1106. HalpSetupPciDeviceForDebugging.
  1107. Arguments:
  1108. PciDevice - Structure indicating the device
  1109. Return Value:
  1110. STATUS_SUCCESS if the device is configured and usable.
  1111. STATUS_NO_MORE_MATCHES if no device matched the criteria.
  1112. STATUS_UNSUCCESSFUL if the routine fails for other reasons.
  1113. --*/
  1114. #define TARGET_DEVICE_NOT_FOUND 0x10000
  1115. {
  1116. NTSTATUS status;
  1117. UCHAR buffer[PCI_COMMON_HDR_LENGTH];
  1118. PPCI_COMMON_CONFIG pciData;
  1119. UCHAR bus, dev, func, bytesRead;
  1120. PCI_SLOT_NUMBER pciSlot, targetSlot;
  1121. ULONG newMinMem, newMaxMem;
  1122. ULONG newMinIo, newMaxIo;
  1123. ULONG newMinBus, newMaxBus;
  1124. UCHAR barNo;
  1125. BOOLEAN unconfigureBridge;
  1126. pciData = (PPCI_COMMON_CONFIG)buffer;
  1127. pciSlot.u.AsULONG = 0;
  1128. newMinMem = MinMem;
  1129. newMaxMem = MaxMem;
  1130. newMinIo = MinIo;
  1131. newMaxIo = MaxIo;
  1132. newMinBus = StartBusNumber;
  1133. newMaxBus = EndBusNumber;
  1134. bus = (UCHAR)StartBusNumber;
  1135. //DbgPrint("HalpSearchForPciDebuggingDevice:\n"
  1136. // "\tMem: %x-%x\n"
  1137. // "\tI/O: %x-%x\n"
  1138. // "\tBus: %x-%x\n"
  1139. // "\t%s Configuring Bridges\n",
  1140. // MinMem, MaxMem,
  1141. // MinIo, MaxIo,
  1142. // StartBusNumber, EndBusNumber,
  1143. // ConfigureBridges ? "" : "Not");
  1144. //
  1145. // This bit stays set to 1 until we find the device.
  1146. //
  1147. targetSlot.u.bits.Reserved = TARGET_DEVICE_NOT_FOUND;
  1148. while (TRUE) {
  1149. UCHAR nextBus;
  1150. nextBus = bus + 1;
  1151. HalpFindFreeResourceLimits(bus,
  1152. &newMinIo,
  1153. &newMaxIo,
  1154. &newMinMem,
  1155. &newMaxMem,
  1156. &newMinBus,
  1157. &newMaxBus
  1158. );
  1159. for (dev = 0; dev < PCI_MAX_DEVICES; dev++) {
  1160. for (func = 0; func < PCI_MAX_FUNCTION; func++) {
  1161. pciSlot.u.bits.DeviceNumber = dev;
  1162. pciSlot.u.bits.FunctionNumber = func;
  1163. bytesRead = (UCHAR)HalpPhase0GetPciDataByOffset(bus,
  1164. pciSlot.u.AsULONG,
  1165. pciData,
  1166. 0,
  1167. PCI_COMMON_HDR_LENGTH);
  1168. if (bytesRead == 0) continue;
  1169. if (pciData->VendorID != PCI_INVALID_VENDORID) {
  1170. //DbgPrint("%04x:%04x - %x/%x/%x - \tSlot: %x\n",
  1171. // pciData->VendorID,
  1172. // pciData->DeviceID,
  1173. // pciData->BaseClass,
  1174. // pciData->SubClass,
  1175. // pciData->ProgIf,
  1176. // pciSlot.u.AsULONG);
  1177. switch (PCI_CONFIGURATION_TYPE(pciData)) {
  1178. case PCI_DEVICE_TYPE:
  1179. //
  1180. // Match first on Bus/Dev/Func
  1181. //
  1182. if ((PciDevice->Bus == bus) &&
  1183. (PciDevice->Slot == pciSlot.u.AsULONG)) {
  1184. //DbgPrint("\n\nMatched on Bus/Slot\n\n");
  1185. return HalpSetupUnconfiguredDebuggingDevice(
  1186. bus,
  1187. pciSlot.u.AsULONG,
  1188. newMinIo,
  1189. newMaxIo,
  1190. newMinMem,
  1191. newMaxMem,
  1192. PciDevice
  1193. );
  1194. }
  1195. if ((PciDevice->Bus == MAXULONG) &&
  1196. (PciDevice->Slot == MAXULONG)) {
  1197. //
  1198. // Bus and Slot weren't specified. Match
  1199. // on VID/DID.
  1200. //
  1201. if ((pciData->VendorID == PciDevice->VendorID) &&
  1202. (pciData->DeviceID == PciDevice->DeviceID)) {
  1203. //DbgPrint("\n\nMatched on Vend/Dev\n\n");
  1204. return HalpSetupUnconfiguredDebuggingDevice(
  1205. bus,
  1206. pciSlot.u.AsULONG,
  1207. newMinIo,
  1208. newMaxIo,
  1209. newMinMem,
  1210. newMaxMem,
  1211. PciDevice
  1212. );
  1213. }
  1214. if ((PciDevice->VendorID == MAXUSHORT) &&
  1215. (PciDevice->DeviceID == MAXUSHORT)) {
  1216. //
  1217. // VID/DID weren't specified. Match
  1218. // on class codes.
  1219. //
  1220. if ((pciData->BaseClass == PciDevice->BaseClass) &&
  1221. (pciData->SubClass == PciDevice->SubClass)) {
  1222. //DbgPrint("\n\nMatched on Base/Sub\n\n");
  1223. //
  1224. // Further match on Programming Interface,
  1225. // if specified.
  1226. //
  1227. if ((PciDevice->ProgIf != MAXUCHAR) &&
  1228. (PciDevice->ProgIf != pciData->ProgIf)) {
  1229. break;
  1230. }
  1231. //DbgPrint("\n\nMatched on programming interface\n\n");
  1232. return HalpSetupUnconfiguredDebuggingDevice(
  1233. bus,
  1234. pciSlot.u.AsULONG,
  1235. newMinIo,
  1236. newMaxIo,
  1237. newMinMem,
  1238. newMaxMem,
  1239. PciDevice
  1240. );
  1241. }
  1242. }
  1243. }
  1244. break;
  1245. case PCI_CARDBUS_BRIDGE_TYPE:
  1246. {
  1247. ULONG bridgeMemMin = 0, bridgeMemMax = 0;
  1248. USHORT bridgeIoMin, bridgeIoMax;
  1249. ULONG LegacyBaseAddress;
  1250. unconfigureBridge = FALSE;
  1251. //DbgPrint("Found a CardBus bridge\n");
  1252. HalpPhase0GetPciDataByOffset(bus,
  1253. pciSlot.u.AsULONG,
  1254. &LegacyBaseAddress,
  1255. CARDBUS_LEGACY_MODE_BASE_ADDR,
  1256. 4);
  1257. if (!(((LegacyBaseAddress & ~1) == 0) &&
  1258. (pciData->u.type2.SecondaryBus != 0) &&
  1259. (pciData->u.type2.SubordinateBus !=0) &&
  1260. (pciData->u.type2.Range[0].Base != 0) &&
  1261. (pciData->u.type2.SocketRegistersBaseAddress != 0) &&
  1262. (pciData->Command & PCI_ENABLE_MEMORY_SPACE) &&
  1263. (pciData->Command & PCI_ENABLE_IO_SPACE))) {
  1264. //
  1265. // The bridge is unconfigured.
  1266. //
  1267. if (ConfigureBridges){
  1268. //
  1269. // We should configure it now.
  1270. //
  1271. status = HalpConfigureCardBusBridge(
  1272. PciDevice,
  1273. bus,
  1274. pciSlot.u.AsULONG,
  1275. newMinIo,
  1276. newMaxIo,
  1277. newMinMem,
  1278. newMaxMem,
  1279. MAX((UCHAR)newMinBus, (bus + 1)),
  1280. newMaxBus,
  1281. pciData
  1282. );
  1283. if (!NT_SUCCESS(status)) {
  1284. break;
  1285. }
  1286. unconfigureBridge = TRUE;
  1287. } else {
  1288. //
  1289. // We aren't configuring bridges
  1290. // on this pass.
  1291. //
  1292. break;
  1293. }
  1294. }
  1295. bridgeMemMin = pciData->u.type2.Range[0].Base;
  1296. bridgeMemMax = pciData->u.type2.Range[0].Limit | 0xfff;
  1297. bridgeIoMin = (USHORT)pciData->u.type2.Range[2].Base;
  1298. bridgeIoMax = (USHORT)pciData->u.type2.Range[2].Limit | 0x3;
  1299. //DbgPrint("Configured: I/O %x-%x Mem %x-%x\n",
  1300. // bridgeIoMin, bridgeIoMax,
  1301. // bridgeMemMin, bridgeMemMax);
  1302. //
  1303. // Recurse.
  1304. //
  1305. status = HalpSearchForPciDebuggingDevice(
  1306. PciDevice,
  1307. (ULONG)pciData->u.type2.SecondaryBus,
  1308. (ULONG)pciData->u.type2.SubordinateBus,
  1309. bridgeMemMin,
  1310. bridgeMemMax,
  1311. bridgeIoMin,
  1312. bridgeIoMax,
  1313. ConfigureBridges);
  1314. if (NT_SUCCESS(status)) {
  1315. return status;
  1316. }
  1317. if (!unconfigureBridge) {
  1318. //
  1319. // Bump up the bus number so that we don't
  1320. // scan down the busses we just recursed into.
  1321. //
  1322. nextBus = pciData->u.type2.SubordinateBus + 1;
  1323. } else {
  1324. HalpUnconfigureCardBusBridge(bus,
  1325. pciSlot.u.AsULONG);
  1326. }
  1327. }
  1328. break;
  1329. case PCI_BRIDGE_TYPE:
  1330. {
  1331. ULONG bridgeMemMin = 0, bridgeMemMax = 0;
  1332. USHORT bridgeIoMin, bridgeIoMax;
  1333. unconfigureBridge = FALSE;
  1334. //DbgPrint("Found a PCI to PCI bridge\n");
  1335. if (!((pciData->u.type1.SecondaryBus != 0) &&
  1336. (pciData->u.type1.SubordinateBus !=0) &&
  1337. (pciData->Command & PCI_ENABLE_MEMORY_SPACE) &&
  1338. (pciData->Command & PCI_ENABLE_IO_SPACE))) {
  1339. //
  1340. // The bridge is unconfigured.
  1341. //
  1342. if (ConfigureBridges){
  1343. //
  1344. // We should configure it now.
  1345. //
  1346. status = HalpConfigurePciBridge(
  1347. PciDevice,
  1348. bus,
  1349. pciSlot.u.AsULONG,
  1350. newMinIo,
  1351. newMaxIo,
  1352. newMinMem,
  1353. newMaxMem,
  1354. MAX((UCHAR)newMinBus, (bus + 1)),
  1355. newMaxBus,
  1356. pciData
  1357. );
  1358. if (!NT_SUCCESS(status)) {
  1359. break;
  1360. }
  1361. unconfigureBridge = TRUE;
  1362. } else {
  1363. //
  1364. // We aren't configuring bridges
  1365. // on this pass.
  1366. //
  1367. break;
  1368. }
  1369. }
  1370. bridgeMemMin = PciBridgeMemory2Base(pciData->u.type1.MemoryBase);
  1371. bridgeMemMax = PciBridgeMemory2Limit(pciData->u.type1.MemoryLimit);
  1372. bridgeIoMin = (USHORT)PciBridgeIO2Base(pciData->u.type1.IOBase, 0);
  1373. bridgeIoMax = (USHORT)PciBridgeIO2Limit(pciData->u.type1.IOLimit, 0);
  1374. //DbgPrint("Configured: I/O %x-%x Mem %x-%x\n",
  1375. // bridgeIoMin, bridgeIoMax,
  1376. // bridgeMemMin, bridgeMemMax);
  1377. //
  1378. // Recurse.
  1379. //
  1380. status = HalpSearchForPciDebuggingDevice(
  1381. PciDevice,
  1382. (ULONG)pciData->u.type1.SecondaryBus,
  1383. (ULONG)pciData->u.type1.SubordinateBus,
  1384. bridgeMemMin,
  1385. bridgeMemMax,
  1386. bridgeIoMin,
  1387. bridgeIoMax,
  1388. ConfigureBridges);
  1389. if (NT_SUCCESS(status)) {
  1390. return status;
  1391. }
  1392. if (!unconfigureBridge) {
  1393. //
  1394. // Bump up the bus number so that we don't
  1395. // scan down the busses we just recursed into.
  1396. //
  1397. nextBus = pciData->u.type1.SubordinateBus + 1;
  1398. } else {
  1399. HalpUnconfigurePciBridge(bus,
  1400. pciSlot.u.AsULONG);
  1401. }
  1402. }
  1403. break;
  1404. default:
  1405. break;
  1406. }
  1407. }
  1408. if (!PCI_MULTIFUNCTION_DEVICE(pciData) &&
  1409. (func == 0)) {
  1410. break;
  1411. }
  1412. }
  1413. }
  1414. if (nextBus >= EndBusNumber) {
  1415. break;
  1416. }
  1417. bus = nextBus;
  1418. }
  1419. return STATUS_NOT_FOUND;
  1420. }
  1421. NTSTATUS
  1422. HalpReleasePciDeviceForDebugging(
  1423. IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. This routine de-allocates any resources acquired in
  1428. HalpSetupPciDeviceForDebugging.
  1429. Arguments:
  1430. PciDevice - Structure indicating the device
  1431. Return Value:
  1432. --*/
  1433. {
  1434. ULONG i;
  1435. for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) {
  1436. if (PciDevice->BaseAddress[i].Valid &&
  1437. PciDevice->BaseAddress[i].Type == CmResourceTypeMemory) {
  1438. PciDevice->BaseAddress[i].Valid = FALSE;
  1439. HalpUnmapVirtualAddress(PciDevice->BaseAddress[i].TranslatedAddress,
  1440. ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  1441. PciDevice->BaseAddress[i].TranslatedAddress,
  1442. PciDevice->BaseAddress[i].Length));
  1443. }
  1444. }
  1445. return STATUS_SUCCESS;
  1446. }
  1447. VOID
  1448. HalpRegisterKdSupportFunctions(
  1449. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1450. )
  1451. /*++
  1452. Routine Description:
  1453. This routine fills in the HalPrivateDispatchTable
  1454. with the functions needed for debugging through
  1455. PCI devices.
  1456. Arguments:
  1457. LoaderBlock - The Loader Block
  1458. Return Value:
  1459. --*/
  1460. {
  1461. KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
  1462. KdReleasePciDeviceForDebugging = HalpReleasePciDeviceForDebugging;
  1463. #ifdef ACPI_HAL
  1464. KdGetAcpiTablePhase0 = HalpGetAcpiTablePhase0;
  1465. #endif
  1466. KdCheckPowerButton = HalpCheckPowerButton;
  1467. KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
  1468. KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
  1469. }
  1470. VOID
  1471. HalpRegisterPciDebuggingDeviceInfo(
  1472. VOID
  1473. )
  1474. {
  1475. OBJECT_ATTRIBUTES ObjectAttributes;
  1476. UNICODE_STRING UnicodeString;
  1477. HANDLE BaseHandle = NULL;
  1478. HANDLE Handle = NULL;
  1479. ULONG disposition;
  1480. ULONG bus;
  1481. UCHAR i;
  1482. PCI_SLOT_NUMBER slot;
  1483. NTSTATUS status;
  1484. BOOLEAN debuggerFound = FALSE;
  1485. PAGED_CODE();
  1486. for (i = 0;
  1487. i < MAX_DEBUGGING_DEVICES_SUPPORTED;
  1488. i++) {
  1489. if (HalpPciDebuggingDevice[i].u.bits.Reserved1 == TRUE) {
  1490. //
  1491. // Must be using a PCI device for a debugger.
  1492. //
  1493. debuggerFound = TRUE;
  1494. }
  1495. }
  1496. if (!debuggerFound) {
  1497. return;
  1498. }
  1499. //
  1500. // Open PCI service key.
  1501. //
  1502. RtlInitUnicodeString (&UnicodeString,
  1503. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\PCI");
  1504. InitializeObjectAttributes(&ObjectAttributes,
  1505. &UnicodeString,
  1506. OBJ_CASE_INSENSITIVE,
  1507. NULL,
  1508. (PSECURITY_DESCRIPTOR) NULL);
  1509. status = ZwOpenKey (&BaseHandle,
  1510. KEY_READ,
  1511. &ObjectAttributes);
  1512. if (!NT_SUCCESS(status)) {
  1513. return;
  1514. }
  1515. // Get the right key
  1516. RtlInitUnicodeString (&UnicodeString,
  1517. L"Debug");
  1518. InitializeObjectAttributes(&ObjectAttributes,
  1519. &UnicodeString,
  1520. OBJ_CASE_INSENSITIVE,
  1521. BaseHandle,
  1522. (PSECURITY_DESCRIPTOR) NULL);
  1523. status = ZwCreateKey (&Handle,
  1524. KEY_READ,
  1525. &ObjectAttributes,
  1526. 0,
  1527. (PUNICODE_STRING) NULL,
  1528. REG_OPTION_VOLATILE,
  1529. &disposition);
  1530. ZwClose(BaseHandle);
  1531. BaseHandle = Handle;
  1532. ASSERT(disposition == REG_CREATED_NEW_KEY);
  1533. if (!NT_SUCCESS(status)) {
  1534. return;
  1535. }
  1536. for (i = 0;
  1537. i < MAX_DEBUGGING_DEVICES_SUPPORTED;
  1538. i++) {
  1539. if (HalpPciDebuggingDevice[i].u.bits.Reserved1 == TRUE) {
  1540. //
  1541. // This entry is populated. Create a key for it.
  1542. //
  1543. RtlInitUnicodeString (&UnicodeString,
  1544. L"0");
  1545. (*(PCHAR)&(UnicodeString.Buffer[0])) += i;
  1546. InitializeObjectAttributes(&ObjectAttributes,
  1547. &UnicodeString,
  1548. OBJ_CASE_INSENSITIVE,
  1549. BaseHandle,
  1550. (PSECURITY_DESCRIPTOR) NULL);
  1551. status = ZwCreateKey (&Handle,
  1552. KEY_READ,
  1553. &ObjectAttributes,
  1554. 0,
  1555. (PUNICODE_STRING) NULL,
  1556. REG_OPTION_VOLATILE,
  1557. &disposition);
  1558. ASSERT(disposition == REG_CREATED_NEW_KEY);
  1559. //
  1560. // Fill in the values below this key.
  1561. //
  1562. bus = HalpPciDebuggingDevice[i].u.bits.BusNumber;
  1563. RtlInitUnicodeString (&UnicodeString,
  1564. L"Bus");
  1565. status = ZwSetValueKey (Handle,
  1566. &UnicodeString,
  1567. 0,
  1568. REG_DWORD,
  1569. &bus,
  1570. sizeof(ULONG));
  1571. //ASSERT(NT_SUCCESS(status));
  1572. slot.u.AsULONG = 0;
  1573. slot.u.bits.FunctionNumber = HalpPciDebuggingDevice[i].u.bits.FunctionNumber;
  1574. slot.u.bits.DeviceNumber = HalpPciDebuggingDevice[i].u.bits.DeviceNumber;
  1575. RtlInitUnicodeString (&UnicodeString,
  1576. L"Slot");
  1577. status = ZwSetValueKey (Handle,
  1578. &UnicodeString,
  1579. 0,
  1580. REG_DWORD,
  1581. &slot.u.AsULONG,
  1582. sizeof(ULONG));
  1583. //ASSERT(NT_SUCCESS(status));
  1584. ZwClose(Handle);
  1585. }
  1586. }
  1587. ZwClose(BaseHandle);
  1588. return;
  1589. }
  1590. NTSTATUS
  1591. HalpConfigurePciBridge(
  1592. IN PDEBUG_DEVICE_DESCRIPTOR PciDevice,
  1593. IN ULONG Bus,
  1594. IN ULONG Slot,
  1595. IN ULONG IoMin,
  1596. IN ULONG IoMax,
  1597. IN ULONG MemMin,
  1598. IN ULONG MemMax,
  1599. IN ULONG BusMin,
  1600. IN ULONG BusMax,
  1601. IN OUT PPCI_COMMON_CONFIG PciData
  1602. )
  1603. {
  1604. USHORT memUnits = 0;
  1605. ULONG memSize;
  1606. PciData->u.type1.PrimaryBus = (UCHAR)Bus;
  1607. PciData->u.type1.SecondaryBus = (UCHAR)BusMin;
  1608. PciData->u.type1.SubordinateBus = (UCHAR)(MIN(BusMax, (BusMin + 2)));
  1609. PciData->Command &= ~PCI_ENABLE_BUS_MASTER;
  1610. //DbgPrint("HalpConfigurePciBridge: P: %x S: %x S: %x\n"
  1611. // "\tI/O %x-%x Mem %x-%x Bus %x-%x\n",
  1612. // PciData->u.type1.PrimaryBus,
  1613. // PciData->u.type1.SecondaryBus,
  1614. // PciData->u.type1.SubordinateBus,
  1615. // IoMin, IoMax,
  1616. // MemMin, MemMax,
  1617. // BusMin, BusMax);
  1618. //
  1619. // Only enable I/O on the bridge if we are looking for
  1620. // something besides a 1394 controller.
  1621. //
  1622. if (!((PciDevice->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
  1623. (PciDevice->SubClass == PCI_SUBCLASS_SB_IEEE1394))) {
  1624. if (((IoMax & 0xf000) - (IoMin & 0xf000)) >= 0X1000) {
  1625. //
  1626. // There is enough I/O space here to enable
  1627. // an I/O window.
  1628. //
  1629. PciData->u.type1.IOBase =
  1630. (UCHAR)((IoMax & 0xf000) >> 12) - 1;
  1631. PciData->u.type1.IOLimit = PciData->u.type1.IOBase;
  1632. PciData->Command |= PCI_ENABLE_IO_SPACE;
  1633. PciData->Command |= PCI_ENABLE_BUS_MASTER;
  1634. }
  1635. }
  1636. //
  1637. // Enable a memory window if possible.
  1638. //
  1639. memSize = ((MemMax + 1) & 0xfff00000) - (MemMin & 0xfff00000);
  1640. if (memSize >= 0x100000) {
  1641. memUnits = 1;
  1642. }
  1643. if (memSize >= 0x400000) {
  1644. memUnits = 4;
  1645. }
  1646. if (memUnits > 0) {
  1647. //
  1648. // There is enough space.
  1649. //
  1650. PciData->u.type1.MemoryBase =
  1651. (USHORT)((MemMax & 0xfff00000) >> 16) - (memUnits << 4);
  1652. PciData->u.type1.MemoryLimit = PciData->u.type1.MemoryBase + ((memUnits - 1) << 4);
  1653. PciData->Command |= PCI_ENABLE_MEMORY_SPACE;
  1654. PciData->Command |= PCI_ENABLE_BUS_MASTER;
  1655. }
  1656. if (PciData->Command & PCI_ENABLE_BUS_MASTER) {
  1657. HalpPhase0SetPciDataByOffset(Bus,
  1658. Slot,
  1659. PciData,
  1660. 0,
  1661. 0x24);
  1662. return STATUS_SUCCESS;
  1663. } else {
  1664. return STATUS_UNSUCCESSFUL;
  1665. }
  1666. }
  1667. VOID
  1668. HalpUnconfigurePciBridge(
  1669. IN ULONG Bus,
  1670. IN ULONG Slot
  1671. )
  1672. {
  1673. UCHAR buffer[0x20] = {0};
  1674. //
  1675. // Zero the command register.
  1676. //
  1677. HalpPhase0SetPciDataByOffset(Bus,
  1678. Slot,
  1679. buffer,
  1680. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1681. 2);
  1682. //
  1683. // Zero the address space and bus number registers.
  1684. //
  1685. HalpPhase0SetPciDataByOffset(Bus,
  1686. Slot,
  1687. buffer,
  1688. FIELD_OFFSET (PCI_COMMON_CONFIG, u),
  1689. 0x20);
  1690. }
  1691. NTSTATUS
  1692. HalpConfigureCardBusBridge(
  1693. IN PDEBUG_DEVICE_DESCRIPTOR PciDevice,
  1694. IN ULONG Bus,
  1695. IN ULONG Slot,
  1696. IN ULONG IoMin,
  1697. IN ULONG IoMax,
  1698. IN ULONG MemMin,
  1699. IN ULONG MemMax,
  1700. IN ULONG BusMin,
  1701. IN ULONG BusMax,
  1702. IN OUT PPCI_COMMON_CONFIG PciData
  1703. )
  1704. {
  1705. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1706. ULONG ulTemp;
  1707. ULONG SocketRegBase;
  1708. USHORT BridgeControl = 0;
  1709. PCARDBUS_SOCKET_REGS SocketRegs;
  1710. PHYSICAL_ADDRESS physicalAddress;
  1711. static BOOLEAN FirstCall = TRUE;
  1712. UCHAR bytesRead;
  1713. USHORT command, origCmd;
  1714. //
  1715. // First check to see there is a CardBus device in the slot
  1716. // power it on.
  1717. //
  1718. //
  1719. // Turn on socket registers in a suitable location
  1720. //
  1721. bytesRead = (UCHAR) HalpPhase0GetPciDataByOffset(Bus,
  1722. Slot,
  1723. &SocketRegBase,
  1724. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type2.SocketRegistersBaseAddress),
  1725. 4);
  1726. if (bytesRead != 4) {
  1727. return STATUS_UNSUCCESSFUL;
  1728. }
  1729. if (!SocketRegBase) {
  1730. SocketRegBase = ((MemMin + 0xfff) & 0xfffff000);
  1731. if ((SocketRegBase + 0x1000) >= MemMax) {
  1732. return STATUS_UNSUCCESSFUL;
  1733. }
  1734. //
  1735. // Adjust MemMin to allow the socket registers to remain visible
  1736. //
  1737. MemMin = SocketRegBase + 0x1000;
  1738. HalpPhase0SetPciDataByOffset(Bus,
  1739. Slot,
  1740. &SocketRegBase,
  1741. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type2.SocketRegistersBaseAddress),
  1742. 4);
  1743. }
  1744. physicalAddress.HighPart = 0;
  1745. physicalAddress.LowPart = SocketRegBase;
  1746. SocketRegs = HalpMapPhysicalMemory64(physicalAddress, 1);
  1747. if (!SocketRegs) {
  1748. return STATUS_UNSUCCESSFUL;
  1749. }
  1750. PciData->u.type2.SocketRegistersBaseAddress = SocketRegBase;
  1751. //
  1752. // Turn off legacy mode base address
  1753. //
  1754. ulTemp = 0;
  1755. HalpPhase0SetPciDataByOffset(Bus,
  1756. Slot,
  1757. &ulTemp,
  1758. CARDBUS_LEGACY_MODE_BASE_ADDR,
  1759. 4);
  1760. //
  1761. // Make sure memory space is enabled
  1762. //
  1763. bytesRead = (UCHAR) HalpPhase0GetPciDataByOffset(Bus,
  1764. Slot,
  1765. &origCmd,
  1766. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1767. 2);
  1768. command = origCmd | PCI_ENABLE_MEMORY_SPACE;
  1769. if (command != origCmd) {
  1770. HalpPhase0SetPciDataByOffset(Bus,
  1771. Slot,
  1772. &command,
  1773. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1774. 2);
  1775. }
  1776. //
  1777. // make sure it looks like cardbus socket registers
  1778. //
  1779. if ((SocketRegs->Mask & 0xfffffff0) == 0) {
  1780. //
  1781. // make sure events are disabled
  1782. //
  1783. SocketRegs->Mask = 0;
  1784. HalpKdStallExecution(600);
  1785. //
  1786. // See if a CardBus card is in the slot
  1787. //
  1788. if ((SocketRegs->PresentState & SKTSTATE_CARDTYPE_MASK) == SKTSTATE_CBCARD) {
  1789. //
  1790. // power up the card
  1791. //
  1792. SocketRegs->Control = SKTPOWER_VCC_033V | SKTPOWER_VPP_033V;
  1793. HalpKdStallExecution(600);
  1794. status = STATUS_SUCCESS;
  1795. }
  1796. }
  1797. //
  1798. // if we don't have a useable cardbus device, clean up and exit
  1799. //
  1800. if (!NT_SUCCESS(status)) {
  1801. if (command != origCmd) {
  1802. HalpPhase0SetPciDataByOffset(Bus,
  1803. Slot,
  1804. &origCmd,
  1805. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1806. 2);
  1807. }
  1808. //
  1809. // turn socket registers back off
  1810. //
  1811. SocketRegBase = 0;
  1812. HalpPhase0SetPciDataByOffset(Bus,
  1813. Slot,
  1814. &SocketRegBase,
  1815. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type2.SocketRegistersBaseAddress),
  1816. 4);
  1817. return status;
  1818. }
  1819. //
  1820. // Make sure CBRST is off
  1821. //
  1822. HalpPhase0GetPciDataByOffset(Bus,
  1823. Slot,
  1824. &BridgeControl,
  1825. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type2.BridgeControl),
  1826. 2);
  1827. if (BridgeControl & CARDBUS_BRIDGE_CONTROL_RESET) {
  1828. BridgeControl &= ~CARDBUS_BRIDGE_CONTROL_RESET;
  1829. HalpPhase0SetPciDataByOffset(Bus,
  1830. Slot,
  1831. &BridgeControl,
  1832. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type2.BridgeControl),
  1833. 2);
  1834. }
  1835. PciData->u.type2.PrimaryBus = (UCHAR)Bus;
  1836. PciData->u.type2.SecondaryBus = (UCHAR)BusMin;
  1837. PciData->u.type2.SubordinateBus = (UCHAR)(MIN(BusMax, (BusMin + 2)));
  1838. PciData->Command &= ~PCI_ENABLE_BUS_MASTER;
  1839. //DbgPrint("HalpConfigureCardBusBridge: P: %x S: %x S: %x\n"
  1840. // "\tI/O %x-%x Mem %x-%x Bus %x-%x\n",
  1841. // PciData->u.type2.PrimaryBus,
  1842. // PciData->u.type2.SecondaryBus,
  1843. // PciData->u.type2.SubordinateBus,
  1844. // IoMin, IoMax,
  1845. // MemMin, MemMax,
  1846. // BusMin, BusMax);
  1847. //
  1848. // Only enable I/O on the bridge if we are looking for
  1849. // something besides a 1394 controller.
  1850. //
  1851. if (!((PciDevice->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
  1852. (PciDevice->SubClass == PCI_SUBCLASS_SB_IEEE1394))) {
  1853. PciData->u.type2.Range[2].Base = IoMin;
  1854. PciData->u.type2.Range[2].Limit = IoMax & 0xffc;
  1855. PciData->Command |= PCI_ENABLE_IO_SPACE;
  1856. PciData->Command |= PCI_ENABLE_BUS_MASTER;
  1857. }
  1858. //
  1859. // Enable a memory window if possible.
  1860. //
  1861. if (MemMax > MemMin) {
  1862. PciData->u.type2.Range[0].Base = MemMin;
  1863. PciData->u.type2.Range[0].Limit = MemMax & 0xfffff000;
  1864. PciData->Command |= PCI_ENABLE_MEMORY_SPACE;
  1865. PciData->Command |= PCI_ENABLE_BUS_MASTER;
  1866. }
  1867. if (PciData->Command & PCI_ENABLE_BUS_MASTER) {
  1868. HalpPhase0SetPciDataByOffset(Bus,
  1869. Slot,
  1870. PciData,
  1871. 0,
  1872. 0x3c);
  1873. return STATUS_SUCCESS;
  1874. } else {
  1875. return STATUS_UNSUCCESSFUL;
  1876. }
  1877. }
  1878. VOID
  1879. HalpUnconfigureCardBusBridge(
  1880. IN ULONG Bus,
  1881. IN ULONG Slot
  1882. )
  1883. {
  1884. UCHAR buffer[0x2c] = {0};
  1885. ULONG SocketRegBase = 0xffffffff;
  1886. PCARDBUS_SOCKET_REGS SocketRegs;
  1887. PHYSICAL_ADDRESS physicalAddress;
  1888. HalpPhase0GetPciDataByOffset(Bus,
  1889. Slot,
  1890. &SocketRegBase,
  1891. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type2.SocketRegistersBaseAddress),
  1892. 4);
  1893. if (SocketRegBase) {
  1894. physicalAddress.HighPart = 0;
  1895. physicalAddress.LowPart = SocketRegBase;
  1896. SocketRegs = HalpMapPhysicalMemory64(physicalAddress, 1);
  1897. //
  1898. // Turn power back off
  1899. //
  1900. if (SocketRegs) {
  1901. SocketRegs->Control = 0;
  1902. }
  1903. }
  1904. //
  1905. // Zero the command register.
  1906. //
  1907. HalpPhase0SetPciDataByOffset(Bus,
  1908. Slot,
  1909. buffer,
  1910. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1911. 2);
  1912. //
  1913. // Zero the address space and bus number registers.
  1914. //
  1915. HalpPhase0SetPciDataByOffset(Bus,
  1916. Slot,
  1917. buffer,
  1918. FIELD_OFFSET (PCI_COMMON_CONFIG, u),
  1919. 0x2c);
  1920. }
  1921. ULONG
  1922. HalpKdStallExecution(
  1923. ULONG LoopCount
  1924. )
  1925. {
  1926. ULONG i,j,b,k,l;
  1927. b = 1;
  1928. for (k=0;k<LoopCount;k++) {
  1929. for (i=1;i<100000;i++) {
  1930. PAUSE_PROCESSOR
  1931. b=b* (i>>k);
  1932. }
  1933. };
  1934. return b;
  1935. }