Leaked source code of windows server 2003
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.

1453 lines
44 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ixpcibrd.c
  5. Abstract:
  6. Get PCI-PCI bridge information
  7. Author:
  8. Ken Reneris (kenr) 14-June-1994
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "halp.h"
  14. #include "pci.h"
  15. #include "pcip.h"
  16. #include "stdio.h"
  17. // debugging only...
  18. // #define INIT_PCI_BRIDGE 1
  19. extern WCHAR rgzMultiFunctionAdapter[];
  20. extern WCHAR rgzConfigurationData[];
  21. extern WCHAR rgzIdentifier[];
  22. extern WCHAR rgzReservedResources[];
  23. #if DBG
  24. #define DBGMSG(a) DbgPrint(a)
  25. #else
  26. #define DBGMSG(a)
  27. #endif
  28. #define IsPciBridge(a) \
  29. ((a)->VendorID != PCI_INVALID_VENDORID && \
  30. PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
  31. (a)->BaseClass == PCI_CLASS_BRIDGE_DEV && \
  32. (a)->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)
  33. #define IsCardbusBridge(a) \
  34. ((a)->VendorID != PCI_INVALID_VENDORID && \
  35. PCI_CONFIG_TYPE(a) == PCI_CARDBUS_BRIDGE_TYPE && \
  36. (a)->BaseClass == PCI_CLASS_BRIDGE_DEV && \
  37. (a)->SubClass == PCI_SUBCLASS_BR_CARDBUS)
  38. typedef struct {
  39. ULONG BusNo;
  40. PBUS_HANDLER BusHandler;
  41. PPCIPBUSDATA BusData;
  42. PCI_SLOT_NUMBER SlotNumber;
  43. PPCI_COMMON_CONFIG PciData;
  44. ULONG IO, Memory, PFMemory;
  45. UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
  46. } CONFIGBRIDGE, *PCONFIGBRIDGE;
  47. //
  48. // Internal prototypes
  49. //
  50. #ifdef INIT_PCI_BRIDGE
  51. VOID
  52. HalpGetPciBridgeNeeds (
  53. IN ULONG HwType,
  54. IN PUCHAR MaxPciBus,
  55. IN PCONFIGBRIDGE Current
  56. );
  57. #endif
  58. VOID
  59. HalpSetPciBridgedVgaCronk (
  60. IN ULONG BusNumber,
  61. IN ULONG Base,
  62. IN ULONG Limit
  63. );
  64. ULONG
  65. HalpGetBridgedPCIInterrupt (
  66. IN PBUS_HANDLER BusHandler,
  67. IN PBUS_HANDLER RootHandler,
  68. IN ULONG BusInterruptLevel,
  69. IN ULONG BusInterruptVector,
  70. OUT PKIRQL Irql,
  71. OUT PKAFFINITY Affinity
  72. );
  73. ULONG
  74. HalpGetBridgedPCIISAInt (
  75. IN PBUS_HANDLER BusHandler,
  76. IN PBUS_HANDLER RootHandler,
  77. IN ULONG BusInterruptLevel,
  78. IN ULONG BusInterruptVector,
  79. OUT PKIRQL Irql,
  80. OUT PKAFFINITY Affinity
  81. );
  82. VOID
  83. HalpPCIBridgedPin2Line (
  84. IN PBUS_HANDLER BusHandler,
  85. IN PBUS_HANDLER RootHandler,
  86. IN PCI_SLOT_NUMBER SlotNumber,
  87. IN PPCI_COMMON_CONFIG PciData
  88. );
  89. VOID
  90. HalpPCIBridgedLine2Pin (
  91. IN PBUS_HANDLER BusHandler,
  92. IN PBUS_HANDLER RootHandler,
  93. IN PCI_SLOT_NUMBER SlotNumber,
  94. IN PPCI_COMMON_CONFIG PciNewData,
  95. IN PPCI_COMMON_CONFIG PciOldData
  96. );
  97. NTSTATUS
  98. HalpGetBridgedPCIIrqTable (
  99. IN PBUS_HANDLER BusHandler,
  100. IN PBUS_HANDLER RootHandler,
  101. IN PCI_SLOT_NUMBER PciSlot,
  102. OUT PUCHAR IrqTable
  103. );
  104. #ifdef ALLOC_PRAGMA
  105. #pragma alloc_text(INIT,HalpGetPciBridgeConfig)
  106. #pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
  107. #pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
  108. #ifdef INIT_PCI_BRIDGE
  109. #pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
  110. //#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
  111. #pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
  112. #endif
  113. #endif
  114. VOID
  115. HalpCardBusPin2Line(
  116. IN PBUS_HANDLER BusHandler,
  117. IN PBUS_HANDLER RootHandler,
  118. IN PCI_SLOT_NUMBER SlotNumber,
  119. IN PPCI_COMMON_CONFIG PciData
  120. )
  121. /*++
  122. Routine Description:
  123. Devices on CardBus busses use the interrupt assigned to the bridge.
  124. That's how it works.
  125. Arguments:
  126. BusHandler Bus Handler for the bus this (cardbus) device. That
  127. is, the bus handler which was created for the bridge
  128. under which this device resides.
  129. RootHandler Pointer to the bus handler for the root.
  130. SlotNumber Slot number for the cardbus device (typically 0).
  131. PciData PCI Config space common header (64 bytes).
  132. Return Value:
  133. None.
  134. --*/
  135. {
  136. PPCIPBUSDATA ChildBusData;
  137. ULONG Length;
  138. UCHAR ParentInterruptLine;
  139. //
  140. // If this device doesn't use interrupts, do nothing.
  141. //
  142. if (!PciData->u.type0.InterruptPin) {
  143. return;
  144. }
  145. ChildBusData = (PPCIPBUSDATA)BusHandler->BusData;
  146. //
  147. // Read the interrupt information from the parent, ie the
  148. // cardbus bridge's config space.
  149. //
  150. // Note: We use HalGetBusData because it will do the Pin2Line
  151. // function in the parent for us.
  152. Length = HalGetBusDataByOffset(
  153. PCIConfiguration,
  154. ChildBusData->ParentBus,
  155. ChildBusData->CommonData.ParentSlot.u.AsULONG,
  156. &ParentInterruptLine,
  157. FIELD_OFFSET(PCI_COMMON_CONFIG, u.type2.InterruptLine),
  158. sizeof(ParentInterruptLine)
  159. );
  160. //
  161. // Return the parent's interrupt line value.
  162. //
  163. PciData->u.type0.InterruptLine = ParentInterruptLine;
  164. }
  165. VOID
  166. HalpPciMakeBusAChild(
  167. IN PBUS_HANDLER Child,
  168. IN PBUS_HANDLER Parent
  169. )
  170. /*++
  171. Routine Description:
  172. Make bus 'Child' a child of bus 'Parent'. This routine is used
  173. when the child bus is disabled or not really present. The child
  174. bus consumes no resources.
  175. Arguments:
  176. Child The bus which is to become a child.
  177. Parent The bus Child is a child of.
  178. Return Value:
  179. None.
  180. --*/
  181. {
  182. HalpSetBusHandlerParent(Child, Parent);
  183. ((PPCIPBUSDATA)(Child->BusData))->ParentBus = (UCHAR)Parent->BusNumber;
  184. //
  185. // Give the bus an empty range list so it isn't
  186. // consumed from the parent.
  187. //
  188. HalpFreeRangeList(Child->BusAddresses);
  189. Child->BusAddresses = HalpAllocateNewRangeList();
  190. }
  191. BOOLEAN
  192. HalpGetPciBridgeConfig (
  193. IN ULONG HwType,
  194. IN PUCHAR MaxPciBus
  195. )
  196. /*++
  197. Routine Description:
  198. Scan the devices on all known pci buses trying to locate any
  199. pci to pci bridges. Record the hierarchy for the buses, and
  200. which buses have what addressing limits.
  201. Arguments:
  202. HwType - Configuration type.
  203. MaxPciBus - # of PCI buses reported by the bios
  204. --*/
  205. {
  206. PBUS_HANDLER ChildBus;
  207. PBUS_HANDLER LastKnownRoot;
  208. PPCIPBUSDATA ChildBusData;
  209. ULONG d, f, i, j, BusNo;
  210. ULONG ChildBusNo, ChildSubNo, ChildPrimaryBusNo;
  211. ULONG FixupBusNo;
  212. UCHAR Rescan, TestLimit1, TestLimit2;
  213. BOOLEAN FoundDisabledBridge;
  214. BOOLEAN FoundSomeFunction;
  215. CONFIGBRIDGE CB;
  216. Rescan = 0;
  217. FoundDisabledBridge = FALSE;
  218. //
  219. // Find each bus on a bridge and initialize it's base and limit information
  220. //
  221. CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
  222. CB.SlotNumber.u.bits.Reserved = 0;
  223. for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
  224. CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
  225. CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
  226. FoundSomeFunction = FALSE;
  227. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  228. CB.SlotNumber.u.bits.DeviceNumber = d;
  229. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  230. CB.SlotNumber.u.bits.FunctionNumber = f;
  231. //
  232. // Read PCI configuration information
  233. //
  234. HalpReadPCIConfig (
  235. CB.BusHandler,
  236. CB.SlotNumber,
  237. CB.PciData,
  238. 0,
  239. PCI_COMMON_HDR_LENGTH
  240. );
  241. if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
  242. // function not populated
  243. continue;
  244. }
  245. FoundSomeFunction = TRUE;
  246. if (IsPciBridge(CB.PciData)) {
  247. //
  248. // PCI-PCI bridge
  249. //
  250. ChildBusNo = (ULONG)CB.PciData->u.type1.SecondaryBus;
  251. ChildSubNo = (ULONG)CB.PciData->u.type1.SubordinateBus;
  252. ChildPrimaryBusNo = (ULONG)CB.PciData->u.type1.PrimaryBus;
  253. } else if (IsCardbusBridge(CB.PciData)) {
  254. //
  255. // PCI-Cardbus bridge
  256. //
  257. ChildBusNo = (ULONG)CB.PciData->u.type2.SecondaryBus;
  258. ChildSubNo = (ULONG)CB.PciData->u.type2.SubordinateBus;
  259. ChildPrimaryBusNo = (ULONG)CB.PciData->u.type2.PrimaryBus;
  260. } else {
  261. //
  262. // Not a known bridge type, next function.
  263. //
  264. continue;
  265. }
  266. //
  267. // Whenever we find a bridge, mark all all bus nodes that
  268. // have not already been processed between this bus and
  269. // the new child as children of this bus.
  270. //
  271. // eg if, on bus 0, we find a bridge to bus 6 thru 8, mark
  272. // busses 1 thru 8 as a child of 0. (unless they have
  273. // already been processed).
  274. //
  275. // This stops non-existant busses in the gap between the
  276. // primary bus and the first child bus from looking like
  277. // additional root busses.
  278. //
  279. for (FixupBusNo = CB.BusHandler->BusNumber + 1;
  280. FixupBusNo <= ChildSubNo;
  281. FixupBusNo++) {
  282. ChildBus = HalpHandlerForBus(PCIBus, FixupBusNo);
  283. if (ChildBus == NULL) {
  284. continue;
  285. }
  286. ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
  287. if (ChildBusData->BridgeConfigRead) {
  288. //
  289. // This child bus's relationships already processed
  290. //
  291. continue;
  292. }
  293. HalpPciMakeBusAChild(ChildBus, CB.BusHandler);
  294. ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
  295. }
  296. if (!(CB.PciData->Command &
  297. (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
  298. // this PCI bridge is not enabled - skip it for now
  299. FoundDisabledBridge = TRUE;
  300. // Even though the bridge is disabled the bus number
  301. // may have been set. If so then update the parent
  302. // child relation ship so that the we do not see this
  303. // as a root bus.
  304. if (ChildBusNo <= CB.BusHandler->BusNumber) {
  305. continue;
  306. }
  307. ChildBus = HalpHandlerForBus (PCIBus, ChildBusNo);
  308. if (ChildBus == NULL) {
  309. //
  310. // Even though the bus is currently disabled,
  311. // the system may configure it so we still
  312. // want a bus handler created for it.
  313. //
  314. if (ChildBusNo > Rescan) {
  315. Rescan = (UCHAR)ChildBusNo;
  316. }
  317. continue;
  318. }
  319. ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
  320. if (ChildBusData->BridgeConfigRead) {
  321. // this child buses relationships already processed
  322. continue;
  323. }
  324. HalpPciMakeBusAChild(ChildBus, CB.BusHandler);
  325. ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
  326. //
  327. // Even though we won't actually configure the
  328. // bridge, mark the configuration as read so we
  329. // don't mistake it for a root bus.
  330. //
  331. ChildBusData->BridgeConfigRead = TRUE;
  332. continue;
  333. }
  334. if (ChildPrimaryBusNo != CB.BusHandler->BusNumber) {
  335. DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
  336. // skip it...
  337. continue;
  338. }
  339. if (ChildBusNo <= CB.BusHandler->BusNumber) {
  340. // secondary bus number doesn't make any sense. HP Omnibook may
  341. // not fill this field in on a virtually disabled pci-pci bridge
  342. FoundDisabledBridge = TRUE;
  343. continue;
  344. }
  345. //
  346. // Found a PCI-PCI bridge. Determine it's parent child
  347. // releationships
  348. //
  349. ChildBus = HalpHandlerForBus (PCIBus, ChildBusNo);
  350. if (!ChildBus) {
  351. DBGMSG ("HAL GetPciData: found configured pci bridge\n");
  352. // up the number of buses
  353. if (ChildBusNo > Rescan) {
  354. Rescan = (UCHAR)ChildBusNo;
  355. }
  356. continue;
  357. }
  358. ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
  359. if (ChildBusData->BridgeConfigRead) {
  360. // this child buses releationships already processed
  361. continue;
  362. }
  363. //
  364. // Remember the limits which are programmed into this bridge
  365. //
  366. ChildBusData->BridgeConfigRead = TRUE;
  367. HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
  368. ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
  369. ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
  370. if (IsCardbusBridge(CB.PciData)) {
  371. //
  372. // Cardbus handled by the PCI driver, don't try to
  373. // interpret here.
  374. //
  375. HalpFreeRangeList(ChildBus->BusAddresses);
  376. ChildBus->BusAddresses = HalpAllocateNewRangeList();
  377. //
  378. // Pin to Line (and vis-versa) for a device plugged
  379. // into the cardbus bus, get the same values as the
  380. // bridge itself. Override the line2pin routine in
  381. // the cardbus bridge handler to use the parent's
  382. // slot value. Note: line2pin doesn't do much.
  383. // In DBG PC/AT builds, it simply undoes the IRQXOR
  384. // used to catch drivers that are accessing the h/w
  385. // directly. The normal routine will do this just
  386. // fine so we don't need to override it as well.
  387. //
  388. ChildBusData->CommonData.Pin2Line = HalpCardBusPin2Line;
  389. continue;
  390. }
  391. ChildBus->BusAddresses->IO.Base =
  392. PciBridgeIO2Base(
  393. CB.PciData->u.type1.IOBase,
  394. CB.PciData->u.type1.IOBaseUpper16
  395. );
  396. ChildBus->BusAddresses->IO.Limit =
  397. PciBridgeIO2Limit(
  398. CB.PciData->u.type1.IOLimit,
  399. CB.PciData->u.type1.IOLimitUpper16
  400. );
  401. ChildBus->BusAddresses->IO.SystemAddressSpace = 1;
  402. //
  403. // Special VGA address remapping occuring on this bridge?
  404. //
  405. if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) {
  406. //
  407. // Yes, then this bridge is positively decoding the
  408. // range 0xA0000 thru 0xBFFFF regardless of the memory
  409. // range settings. Add this range, if it overlaps it
  410. // will get cleaned up later.
  411. //
  412. // Also, IO ranges 3b0 thru 3bb and 3c0 thru 3df.
  413. //
  414. HalpAddRange(
  415. &ChildBus->BusAddresses->Memory,
  416. 0, // address space
  417. 0, // system base
  418. 0xa0000, // range base
  419. 0xbffff // range limit
  420. );
  421. HalpAddRange(
  422. &ChildBus->BusAddresses->IO,
  423. 1, // address space
  424. 0, // system base
  425. 0x3b0, // range base
  426. 0x3bb // range limit
  427. );
  428. HalpAddRange(
  429. &ChildBus->BusAddresses->IO,
  430. 1, // address space
  431. 0, // system base
  432. 0x3c0, // range base
  433. 0x3df // range limit
  434. );
  435. //
  436. // Claim all aliases to these IO addresses.
  437. //
  438. // Bits 15:10 are not decoded so anything in
  439. // the same 10 bits as the above in the range
  440. // 0x400 thru 0xffff is an alias.
  441. //
  442. HalpSetPciBridgedVgaCronk (
  443. ChildBus->BusNumber,
  444. 0x0400,
  445. 0xffff
  446. );
  447. }
  448. //
  449. // If supported I/O ranges on this bus are limitied to
  450. // 256bytes on every 1K aligned boundry within the
  451. // range, then redo supported IO BusAddresses to match
  452. //
  453. if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
  454. ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
  455. // assume Base is 1K aligned
  456. i = (ULONG) ChildBus->BusAddresses->IO.Base;
  457. j = (ULONG) ChildBus->BusAddresses->IO.Limit;
  458. // convert head entry
  459. ChildBus->BusAddresses->IO.Limit = i + 255;
  460. i += 1024;
  461. // add remaining ranges
  462. while (i < j) {
  463. HalpAddRange (
  464. &ChildBus->BusAddresses->IO,
  465. 1, // address space
  466. 0, // system base
  467. i, // bus address
  468. i + 255 // bus limit
  469. );
  470. // next range
  471. i += 1024;
  472. }
  473. }
  474. ChildBus->BusAddresses->Memory.Base =
  475. PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
  476. ChildBus->BusAddresses->Memory.Limit =
  477. PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
  478. // On x86 it's ok to clip Prefetch to 32 bits
  479. if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
  480. ChildBus->BusAddresses->PrefetchMemory.Base =
  481. PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
  482. ChildBus->BusAddresses->PrefetchMemory.Limit =
  483. PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
  484. if (CB.PciData->u.type1.PrefetchLimitUpper32) {
  485. ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
  486. }
  487. }
  488. //
  489. // h/w hack the Win9x people allowed folks to make. Determine
  490. // if the bridge is subtractive decode or not by seeing if
  491. // it's IObase/limit is read-only.
  492. //
  493. TestLimit1 = CB.PciData->u.type1.IOLimit + 1;
  494. if (!TestLimit1) {
  495. TestLimit1 = 0xFE;
  496. }
  497. #if 0
  498. DbgPrint ("PciBridge OrigLimit=%d TestLimit=%d ",
  499. CB.PciData->u.type1.IOLimit,
  500. TestLimit1
  501. );
  502. #endif
  503. HalpWritePCIConfig (
  504. CB.BusHandler,
  505. CB.SlotNumber,
  506. &TestLimit1,
  507. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type1.IOLimit),
  508. 1
  509. );
  510. HalpReadPCIConfig (
  511. CB.BusHandler,
  512. CB.SlotNumber,
  513. &TestLimit2,
  514. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type1.IOLimit),
  515. 1
  516. );
  517. HalpWritePCIConfig (
  518. CB.BusHandler,
  519. CB.SlotNumber,
  520. &CB.PciData->u.type1.IOLimit,
  521. FIELD_OFFSET (PCI_COMMON_CONFIG, u.type1.IOLimit),
  522. 1
  523. );
  524. ChildBusData->Subtractive = TestLimit1 != TestLimit2;
  525. #if 0
  526. DbgPrint ("Result=%d, Subtractive=%d\n",
  527. TestLimit2,
  528. ChildBusData->Subtractive
  529. );
  530. DbgPrint ("Device buffer %x\n", CB.PciData);
  531. #endif
  532. //
  533. // Now if its substractive, assume no range means the entire
  534. // range.
  535. //
  536. if (ChildBusData->Subtractive) {
  537. if (ChildBus->BusAddresses->IO.Base == PciBridgeIO2Base(0,0) &&
  538. ChildBus->BusAddresses->IO.Limit <= PciBridgeIO2Limit(0,0)) {
  539. ChildBus->BusAddresses->IO.Limit = 0x7FFFFFFFFFFFFFFF;
  540. if (ChildBus->BusAddresses->Memory.Base == PciBridgeMemory2Base(0)) {
  541. ChildBus->BusAddresses->Memory.Limit = 0x7FFFFFFFFFFFFFFF;
  542. }
  543. }
  544. }
  545. // should call HalpAssignPCISlotResources to assign
  546. // baseaddresses, etc...
  547. }
  548. }
  549. if (!((PPCIPBUSDATA)(CB.BusHandler->BusData))->BridgeConfigRead) {
  550. //
  551. // We believe this bus to be a root.
  552. //
  553. if ((FoundSomeFunction == FALSE) && (BusNo != 0)) {
  554. //
  555. // Nothing found on this bus. Assume it's not really
  556. // a root. (Always assume 0 is a root). (This bus
  557. // probably doesn't exist at all but ntdetect doesn't
  558. // tell us that).
  559. //
  560. // Pretend this bus is a child of the last known root.
  561. // At least this way it won't get a PDO and be handed
  562. // to the PCI driver.
  563. //
  564. HalpPciMakeBusAChild(CB.BusHandler, LastKnownRoot);
  565. } else {
  566. //
  567. // Found something on it (or it's zero), set as last
  568. // known root.
  569. //
  570. LastKnownRoot = CB.BusHandler;
  571. }
  572. }
  573. }
  574. if (Rescan) {
  575. *MaxPciBus = Rescan+1;
  576. return TRUE;
  577. }
  578. if (!FoundDisabledBridge) {
  579. return FALSE;
  580. }
  581. DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
  582. #ifdef INIT_PCI_BRIDGE
  583. //
  584. // We've calculated all the parent's buses known bases & limits.
  585. // While doing this a pci-pci bus was found that the bios didn't
  586. // configure. This is not expected, and we'll make some guesses
  587. // at a configuration here and enable it.
  588. //
  589. // (this code is primarily for testing the above code since
  590. // currently no system bioses actually configure the child buses)
  591. //
  592. for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
  593. CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
  594. CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
  595. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  596. CB.SlotNumber.u.bits.DeviceNumber = d;
  597. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  598. CB.SlotNumber.u.bits.FunctionNumber = f;
  599. HalpReadPCIConfig (
  600. CB.BusHandler,
  601. CB.SlotNumber,
  602. CB.PciData,
  603. 0,
  604. PCI_COMMON_HDR_LENGTH
  605. );
  606. if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
  607. continue;
  608. }
  609. if (!IsPciBridge (CB.PciData)) {
  610. // not a PCI-PCI bridge
  611. continue;
  612. }
  613. if ((CB.PciData->Command &
  614. (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
  615. // this PCI bridge is enabled
  616. continue;
  617. }
  618. //
  619. // We have a disabled bus - assign it a number, then
  620. // determine all the requirements of all devices
  621. // on the other side of this bridge
  622. //
  623. CB.BusNo = BusNo;
  624. HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
  625. }
  626. }
  627. }
  628. // preform Rescan
  629. return TRUE;
  630. #else
  631. return FALSE;
  632. #endif
  633. }
  634. VOID
  635. HalpFixupPciSupportedRanges (
  636. IN ULONG MaxBuses
  637. )
  638. /*++
  639. Routine Description:
  640. PCI-PCI bridged buses only see addresses which their parent
  641. bueses support. So adjust any PCI SUPPORT_RANGES to be
  642. a complete subset of all of it's parent buses.
  643. For PCI-PCI briges which use postive address decode to forward
  644. addresses, remove any addresses from any PCI bus which are bridged
  645. to a child PCI bus.
  646. --*/
  647. {
  648. ULONG i;
  649. PBUS_HANDLER Bus, ParentBus;
  650. PPCIPBUSDATA BusData;
  651. PSUPPORTED_RANGES HRanges;
  652. //
  653. // Pass 1 - shrink all PCI supported ranges to be a subset of
  654. // all of it's parent buses
  655. //
  656. for (i = 0; i < MaxBuses; i++) {
  657. Bus = HalpHandlerForBus (PCIBus, i);
  658. ParentBus = Bus->ParentHandler;
  659. while (ParentBus) {
  660. HRanges = Bus->BusAddresses;
  661. Bus->BusAddresses = HalpMergeRanges (
  662. ParentBus->BusAddresses,
  663. HRanges
  664. );
  665. HalpFreeRangeList (HRanges);
  666. ParentBus = ParentBus->ParentHandler;
  667. }
  668. }
  669. //
  670. // Pass 2 - remove all positive child PCI bus ranges from parent PCI buses
  671. //
  672. for (i = 0; i < MaxBuses; i++) {
  673. Bus = HalpHandlerForBus (PCIBus, i);
  674. BusData = (PPCIPBUSDATA) Bus->BusData;
  675. //
  676. // If the bridge is not subtractive, remove the ranges from the parents
  677. //
  678. if (!BusData->Subtractive) {
  679. ParentBus = Bus->ParentHandler;
  680. while (ParentBus) {
  681. if (ParentBus->InterfaceType == PCIBus) {
  682. HalpRemoveRanges (
  683. ParentBus->BusAddresses,
  684. Bus->BusAddresses
  685. );
  686. }
  687. ParentBus = ParentBus->ParentHandler;
  688. }
  689. }
  690. }
  691. //
  692. // Cleanup
  693. //
  694. for (i = 0; i < MaxBuses; i++) {
  695. Bus = HalpHandlerForBus (PCIBus, i);
  696. HalpConsolidateRanges (Bus->BusAddresses);
  697. }
  698. }
  699. VOID
  700. HalpSetPciBridgedVgaCronk (
  701. IN ULONG BusNumber,
  702. IN ULONG BaseAddress,
  703. IN ULONG LimitAddress
  704. )
  705. /*++
  706. Routine Description: .
  707. The 'vga compatible addresses' bit is set in the bridge control regiter.
  708. This causes the bridge to pass any I/O address in the range of: 10bit
  709. decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
  710. As far as I can tell this "feature" is an attempt to solve some problem
  711. which the folks solving it did not fully understand, so instead of doing
  712. it right we have this fine mess.
  713. The solution is to take the least of all evils which is to remove any
  714. I/O port ranges which are getting remapped from any IoAssignResource
  715. request. (ie, IoAssignResources will never contimplate giving any
  716. I/O port out in the suspected ranges).
  717. note: memory allocation error here is fatal so don't bother with the
  718. return codes.
  719. Arguments:
  720. Base - Base of IO address range in question
  721. Limit - Limit of IO address range in question
  722. --*/
  723. {
  724. UNICODE_STRING unicodeString;
  725. OBJECT_ATTRIBUTES objectAttributes;
  726. HANDLE handle;
  727. ULONG Length;
  728. PCM_RESOURCE_LIST ResourceList;
  729. PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
  730. ULONG AddressMSBs;
  731. WCHAR ValueName[80];
  732. NTSTATUS status;
  733. //
  734. // Open reserved resource settings
  735. //
  736. RtlInitUnicodeString (&unicodeString, rgzReservedResources);
  737. InitializeObjectAttributes( &objectAttributes,
  738. &unicodeString,
  739. OBJ_CASE_INSENSITIVE,
  740. NULL,
  741. (PSECURITY_DESCRIPTOR) NULL
  742. );
  743. status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
  744. if (!NT_SUCCESS(status)) {
  745. return;
  746. }
  747. //
  748. // Build resource list of reseved ranges
  749. //
  750. Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
  751. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
  752. sizeof (CM_RESOURCE_LIST);
  753. ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool,
  754. Length,
  755. HAL_POOL_TAG);
  756. if (!ResourceList) {
  757. //
  758. // Can't possibly be out of paged pool at this stage of the
  759. // game. This system is very unwell, get out.
  760. //
  761. return;
  762. }
  763. RtlZeroMemory(ResourceList, Length);
  764. ResourceList->Count = 1;
  765. ResourceList->List[0].InterfaceType = PCIBus;
  766. ResourceList->List[0].BusNumber = BusNumber;
  767. Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
  768. while (BaseAddress < LimitAddress) {
  769. AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
  770. //
  771. // Add xx3b0 through xx3bb
  772. //
  773. Descriptor->Type = CmResourceTypePort;
  774. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  775. Descriptor->Flags = CM_RESOURCE_PORT_IO;
  776. Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
  777. Descriptor->u.Port.Length = 0xb;
  778. Descriptor += 1;
  779. ResourceList->List[0].PartialResourceList.Count += 1;
  780. //
  781. // Add xx3c0 through xx3df
  782. //
  783. Descriptor->Type = CmResourceTypePort;
  784. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  785. Descriptor->Flags = CM_RESOURCE_PORT_IO;
  786. Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
  787. Descriptor->u.Port.Length = 0x1f;
  788. Descriptor += 1;
  789. ResourceList->List[0].PartialResourceList.Count += 1;
  790. //
  791. // Next range
  792. //
  793. BaseAddress += 1024;
  794. }
  795. //
  796. // Add the reserved ranges to avoid during IoAssignResource
  797. //
  798. swprintf(ValueName, L"HAL_PCI_%d", BusNumber);
  799. RtlInitUnicodeString(&unicodeString, ValueName);
  800. ZwSetValueKey(handle,
  801. &unicodeString,
  802. 0L,
  803. REG_RESOURCE_LIST,
  804. ResourceList,
  805. (ULONG) Descriptor - (ULONG) ResourceList
  806. );
  807. ExFreePool(ResourceList);
  808. ZwClose(handle);
  809. }
  810. #ifdef INIT_PCI_BRIDGE
  811. VOID
  812. HalpGetPciBridgeNeeds (
  813. IN ULONG HwType,
  814. IN PUCHAR MaxPciBus,
  815. IN PCONFIGBRIDGE Current
  816. )
  817. {
  818. ACCESS_MASK DesiredAccess;
  819. UNICODE_STRING unicodeString;
  820. PUCHAR buffer;
  821. HANDLE handle;
  822. OBJECT_ATTRIBUTES objectAttributes;
  823. PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
  824. PCONFIGURATION_COMPONENT Component;
  825. CONFIGBRIDGE CB;
  826. ULONG mnum, d, f, i;
  827. NTSTATUS status;
  828. buffer = ExAllocatePoolWithTag(PagedPool, 1024, HAL_POOL_TAG);
  829. if (!buffer) {
  830. //
  831. // Give up, we're not going anywhere anyway.
  832. //
  833. return;
  834. }
  835. //
  836. // Init CB structure
  837. //
  838. CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
  839. CB.SlotNumber.u.bits.Reserved = 0;
  840. Current->IO = Current->Memory = Current->PFMemory = 0;
  841. //
  842. // Assign this bridge an ID, and turn on configuration space
  843. //
  844. Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
  845. Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
  846. Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
  847. Current->PciData->u.type1.SecondaryStatus = 0xffff;
  848. Current->PciData->Status = 0xffff;
  849. Current->PciData->Command = 0;
  850. Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
  851. HalpWritePCIConfig (
  852. Current->BusHandler,
  853. Current->SlotNumber,
  854. Current->PciData,
  855. 0,
  856. PCI_COMMON_HDR_LENGTH
  857. );
  858. KeStallExecutionProcessor (100);
  859. Current->PciData->u.type1.BridgeControl = 0;
  860. HalpWritePCIConfig (
  861. Current->BusHandler,
  862. Current->SlotNumber,
  863. Current->PciData,
  864. 0,
  865. PCI_COMMON_HDR_LENGTH
  866. );
  867. KeStallExecutionProcessor (100);
  868. //
  869. // Allocate new handler for bus
  870. //
  871. CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
  872. CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
  873. CB.BusNo = *MaxPciBus;
  874. *MaxPciBus += 1;
  875. //
  876. // Add another PCI bus in the registry
  877. //
  878. mnum = 0;
  879. for (; ;) {
  880. //
  881. // Find next available MultiFunctionAdapter key
  882. //
  883. DesiredAccess = KEY_READ | KEY_WRITE;
  884. swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
  885. RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
  886. InitializeObjectAttributes( &objectAttributes,
  887. &unicodeString,
  888. OBJ_CASE_INSENSITIVE,
  889. NULL,
  890. (PSECURITY_DESCRIPTOR) NULL
  891. );
  892. status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
  893. if (!NT_SUCCESS(status)) {
  894. break;
  895. }
  896. // already exists, next
  897. ZwClose (handle);
  898. mnum += 1;
  899. }
  900. ZwCreateKey (&handle,
  901. DesiredAccess,
  902. &objectAttributes,
  903. 0,
  904. NULL,
  905. REG_OPTION_VOLATILE,
  906. &d
  907. );
  908. //
  909. // Add needed registry values for this MultifucntionAdapter entry
  910. //
  911. RtlInitUnicodeString (&unicodeString, rgzIdentifier);
  912. ZwSetValueKey (handle,
  913. &unicodeString,
  914. 0L,
  915. REG_SZ,
  916. L"PCI",
  917. sizeof (L"PCI")
  918. );
  919. RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
  920. Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
  921. Descriptor->InterfaceType = PCIBus;
  922. Descriptor->BusNumber = CB.BusNo;
  923. Descriptor->PartialResourceList.Version = 0;
  924. Descriptor->PartialResourceList.Revision = 0;
  925. Descriptor->PartialResourceList.Count = 0;
  926. ZwSetValueKey (handle,
  927. &unicodeString,
  928. 0L,
  929. REG_FULL_RESOURCE_DESCRIPTOR,
  930. Descriptor,
  931. sizeof (*Descriptor)
  932. );
  933. RtlInitUnicodeString (&unicodeString, L"Component Information");
  934. Component = (PCONFIGURATION_COMPONENT) buffer;
  935. RtlZeroMemory (Component, sizeof (*Component));
  936. Component->AffinityMask = 0xffffffff;
  937. ZwSetValueKey (handle,
  938. &unicodeString,
  939. 0L,
  940. REG_BINARY,
  941. Component,
  942. FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
  943. );
  944. ZwClose (handle);
  945. //
  946. // Since the BIOS didn't configure this bridge we'll assume that
  947. // the PCI interrupts are bridged. (for BIOS configured buses we
  948. // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
  949. //
  950. CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
  951. CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
  952. //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
  953. if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
  954. //
  955. // The parent bus'es interrupt pin to vector mappings is not
  956. // a static function, and is determined by the boot firmware.
  957. //
  958. //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
  959. // read each device on parent bus
  960. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  961. CB.SlotNumber.u.bits.DeviceNumber = d;
  962. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  963. CB.SlotNumber.u.bits.FunctionNumber = f;
  964. HalpReadPCIConfig (
  965. Current->BusHandler,
  966. CB.SlotNumber,
  967. CB.PciData,
  968. 0,
  969. PCI_COMMON_HDR_LENGTH
  970. );
  971. if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
  972. continue;
  973. }
  974. if (CB.PciData->u.type0.InterruptPin &&
  975. (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
  976. PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
  977. // get bios supplied int mapping
  978. i = CB.PciData->u.type0.InterruptPin + d % 4;
  979. CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
  980. }
  981. }
  982. }
  983. } else {
  984. _asm int 3;
  985. }
  986. //
  987. // Look at each device on the bus and determine it's resource needs
  988. //
  989. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  990. CB.SlotNumber.u.bits.DeviceNumber = d;
  991. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  992. CB.SlotNumber.u.bits.FunctionNumber = f;
  993. HalpReadPCIConfig (
  994. CB.BusHandler,
  995. CB.SlotNumber,
  996. CB.PciData,
  997. 0,
  998. PCI_COMMON_HDR_LENGTH
  999. );
  1000. if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
  1001. continue;
  1002. }
  1003. if (IsPciBridge (CB.PciData)) {
  1004. // oh look - another bridge ...
  1005. HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
  1006. continue;
  1007. }
  1008. if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
  1009. continue;
  1010. }
  1011. // found a device - figure out the resources it needs
  1012. }
  1013. }
  1014. //
  1015. // Found all sub-buses set SubordinateBus accordingly
  1016. //
  1017. Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
  1018. HalpWritePCIConfig (
  1019. Current->BusHandler,
  1020. Current->SlotNumber,
  1021. Current->PciData,
  1022. 0,
  1023. PCI_COMMON_HDR_LENGTH
  1024. );
  1025. //
  1026. // Set the bridges IO, Memory, and Prefetch Memory windows
  1027. //
  1028. // For now just pick some numbers & set everyone the same
  1029. // IO 0x6000 - 0xFFFF
  1030. // MEM 0x40000000 - 0x4FFFFFFF
  1031. // PFMEM 0x50000000 - 0x5FFFFFFF
  1032. Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
  1033. Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
  1034. Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
  1035. Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
  1036. Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
  1037. Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
  1038. Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
  1039. Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
  1040. Current->PciData->u.type1.IOBaseUpper16 = 0;
  1041. Current->PciData->u.type1.IOLimitUpper16 = 0;
  1042. Current->PciData->u.type1.BridgeControl =
  1043. PCI_ENABLE_BRIDGE_ISA;
  1044. HalpWritePCIConfig (
  1045. Current->BusHandler,
  1046. Current->SlotNumber,
  1047. Current->PciData,
  1048. 0,
  1049. PCI_COMMON_HDR_LENGTH
  1050. );
  1051. HalpReadPCIConfig (
  1052. Current->BusHandler,
  1053. Current->SlotNumber,
  1054. Current->PciData,
  1055. 0,
  1056. PCI_COMMON_HDR_LENGTH
  1057. );
  1058. // enable memory & io decodes
  1059. Current->PciData->Command =
  1060. PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
  1061. HalpWritePCIConfig (
  1062. Current->BusHandler,
  1063. Current->SlotNumber,
  1064. &Current->PciData->Command,
  1065. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1066. sizeof (Current->PciData->Command)
  1067. );
  1068. ExFreePool (buffer);
  1069. }
  1070. VOID
  1071. HalpPCIBridgedPin2Line (
  1072. IN PBUS_HANDLER BusHandler,
  1073. IN PBUS_HANDLER RootHandler,
  1074. IN PCI_SLOT_NUMBER SlotNumber,
  1075. IN PPCI_COMMON_CONFIG PciData
  1076. )
  1077. /*++
  1078. This function maps the device's InterruptPin to an InterruptLine
  1079. value.
  1080. test function particular to dec pci-pci bridge card
  1081. --*/
  1082. {
  1083. PPCIPBUSDATA BusData;
  1084. ULONG i;
  1085. if (!PciData->u.type0.InterruptPin) {
  1086. return ;
  1087. }
  1088. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1089. //
  1090. // Convert slot Pin into Bus INTA-D.
  1091. //
  1092. i = (PciData->u.type0.InterruptPin +
  1093. SlotNumber.u.bits.DeviceNumber - 1) % 4;
  1094. PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
  1095. PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
  1096. }
  1097. VOID
  1098. HalpPCIBridgedLine2Pin (
  1099. IN PBUS_HANDLER BusHandler,
  1100. IN PBUS_HANDLER RootHandler,
  1101. IN PCI_SLOT_NUMBER SlotNumber,
  1102. IN PPCI_COMMON_CONFIG PciNewData,
  1103. IN PPCI_COMMON_CONFIG PciOldData
  1104. )
  1105. /*++
  1106. This functions maps the device's InterruptLine to it's
  1107. device specific InterruptPin value.
  1108. test function particular to dec pci-pci bridge card
  1109. --*/
  1110. {
  1111. PPCIPBUSDATA BusData;
  1112. ULONG i;
  1113. if (!PciNewData->u.type0.InterruptPin) {
  1114. return ;
  1115. }
  1116. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1117. i = (PciNewData->u.type0.InterruptPin +
  1118. SlotNumber.u.bits.DeviceNumber - 1) % 4;
  1119. PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
  1120. PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
  1121. }
  1122. #endif