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.

590 lines
17 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ixpcisup.c
  5. Abstract:
  6. Support functions for doing PCI the bus-handler
  7. way.
  8. Author:
  9. Ken Reneris (kenr) 14-June-1994
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. Moved code into this file so that it would be
  14. easier to build a non-bus-handler HAL. This
  15. file will only be compiled into HALs that
  16. use bus handlers. -- Jake Oshins 2-Dec-1997
  17. --*/
  18. #include "halp.h"
  19. #include "pci.h"
  20. #include "pcip.h"
  21. #include "chiphacks.h"
  22. BOOLEAN
  23. HalpIsIdeDevice(
  24. IN PPCI_COMMON_CONFIG PciData
  25. );
  26. VOID
  27. HalpGetNMICrashFlag (
  28. VOID
  29. );
  30. extern BOOLEAN HalpDisableHibernate;
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text(INIT,HalpInitializePciBus)
  33. #pragma alloc_text(INIT,HalpIsIdeDevice)
  34. #pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
  35. #endif
  36. VOID
  37. HalpInitializePciBus (
  38. VOID
  39. )
  40. {
  41. PPCI_REGISTRY_INFO_INTERNAL PCIRegInfo;
  42. ULONG i, d, HwType, BusNo, f;
  43. PBUS_HANDLER BusHandler;
  44. PCI_SLOT_NUMBER SlotNumber;
  45. PPCI_COMMON_CONFIG PciData;
  46. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH + sizeof(TYPE2EXTRAS)];
  47. ULONG OPBNumber;
  48. BOOLEAN OPBA2B0Found, COPBInbPostingEnabled;
  49. UCHAR buffer [4];
  50. BOOLEAN fullDecodeChipset = FALSE;
  51. NTSTATUS Status;
  52. ULONG flags;
  53. PCIRegInfo = HalpQueryPciRegistryInfo();
  54. if (!PCIRegInfo) {
  55. return;
  56. }
  57. //
  58. // Initialize spinlock for synchronizing access to PCI space
  59. //
  60. KeInitializeSpinLock (&HalpPCIConfigLock);
  61. PciData = (PPCI_COMMON_CONFIG) iBuffer;
  62. //
  63. // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
  64. //
  65. HwType = PCIRegInfo->HardwareMechanism & 0xf;
  66. //
  67. // Some AMI bioses claim machines are Type2 configuration when they
  68. // are really type1. If this is a Type2 with at least one bus,
  69. // try to verify it's not really a type1 bus
  70. //
  71. if (PCIRegInfo->NoBuses && HwType == 2) {
  72. //
  73. // Check each slot for a valid device. Which every style configuration
  74. // space shows a valid device first will be used
  75. //
  76. SlotNumber.u.bits.Reserved = 0;
  77. SlotNumber.u.bits.FunctionNumber = 0;
  78. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  79. SlotNumber.u.bits.DeviceNumber = d;
  80. //
  81. // First try what the BIOS claims - type 2. Allocate type2
  82. // test handle for PCI bus 0.
  83. //
  84. HwType = 2;
  85. BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
  86. if (!BusHandler) {
  87. break;
  88. }
  89. if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
  90. break;
  91. }
  92. //
  93. // Valid device not found on Type2 access for this slot.
  94. // Reallocate the bus handler are Type1 and take a look.
  95. //
  96. HwType = 1;
  97. BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
  98. if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
  99. break;
  100. }
  101. HwType = 2;
  102. }
  103. //
  104. // Reset handler for PCI bus 0 to whatever style config space
  105. // was finally decided.
  106. //
  107. HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
  108. }
  109. //
  110. // For each PCI bus present, allocate a handler structure and
  111. // fill in the dispatch functions
  112. //
  113. do {
  114. for (i=0; i < PCIRegInfo->NoBuses; i++) {
  115. //
  116. // If handler not already built, do it now
  117. //
  118. if (!HalpHandlerForBus (PCIBus, i)) {
  119. HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
  120. }
  121. }
  122. //
  123. // Bus handlers for all PCI buses have been allocated, go collect
  124. // pci bridge information.
  125. //
  126. } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
  127. //
  128. // Fixup SUPPORTED_RANGES
  129. //
  130. HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
  131. //
  132. // Look for PCI controllers which have known work-arounds, and make
  133. // sure they are applied.
  134. //
  135. // In addition, fill in the bitmask HalpPciIrqMask with all the
  136. // interrupts that PCI devices might use.
  137. //
  138. OPBNumber = 0;
  139. OPBA2B0Found = FALSE;
  140. COPBInbPostingEnabled = FALSE;
  141. SlotNumber.u.bits.Reserved = 0;
  142. for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
  143. BusHandler = HalpHandlerForBus (PCIBus, BusNo);
  144. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  145. SlotNumber.u.bits.DeviceNumber = d;
  146. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  147. SlotNumber.u.bits.FunctionNumber = f;
  148. //
  149. // Read PCI configuration information
  150. //
  151. HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
  152. if (*((PULONG)(PciData)) == 0xffffffff) {
  153. continue;
  154. }
  155. if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) {
  156. HalpReadPCIConfig(
  157. BusHandler,
  158. SlotNumber,
  159. PciData+1,
  160. FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceSpecific),
  161. sizeof(TYPE2EXTRAS)
  162. );
  163. }
  164. #ifndef SUBCLASSPCI
  165. //
  166. // Look at interrupt line register and fill in HalpPciIrqMask,
  167. // but not for an IDE controller, as IDE controllers really
  168. // trigger interrupts like ISA devices.
  169. //
  170. if (PCI_CONFIGURATION_TYPE(PciData) != 1) {
  171. if ((PciData->u.type0.InterruptPin != 0) &&
  172. (PciData->u.type0.InterruptLine != 0) &&
  173. (PciData->u.type0.InterruptLine < PIC_VECTORS) &&
  174. !HalpIsIdeDevice(PciData)) {
  175. HalpPciIrqMask |= 1 << PciData->u.type0.InterruptLine;
  176. }
  177. }
  178. #endif
  179. //
  180. // Check for chips with known work-arounds to apply
  181. //
  182. if (PciData->VendorID == 0x8086 &&
  183. PciData->DeviceID == 0x04A3 &&
  184. PciData->RevisionID < 0x11) {
  185. //
  186. // 82430 PCMC controller
  187. //
  188. HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
  189. buffer[0] &= ~0x08; // turn off bit 3 register 0x53
  190. if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
  191. buffer[1] &= ~0x01; // bit 0 register 0x54
  192. }
  193. HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
  194. }
  195. if (PciData->VendorID == 0x8086 &&
  196. PciData->DeviceID == 0x0484 &&
  197. PciData->RevisionID <= 3) {
  198. //
  199. // 82378 ISA bridge & SIO
  200. //
  201. HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
  202. buffer[0] &= ~0x1; // turn off bit 0 register 0x41
  203. HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
  204. }
  205. //
  206. // Look for Orion PCI Bridge
  207. //
  208. if (PciData->VendorID == 0x8086 &&
  209. PciData->DeviceID == 0x84c4 ) {
  210. //
  211. // 82450 Orion PCI Bridge Workaround
  212. // Need a workaround if following conditions are true:
  213. // i) 2 OPBs present
  214. // ii)There is an A2/B0 step OPB present.
  215. // iii) Inbound posting on the compatibility OPB is
  216. // enabled.
  217. // NOTE: Inbound Posting on the non-compatibility OPB
  218. // MUST BE disabled by BIOS
  219. //
  220. OPBNumber += 1;
  221. if (PciData->RevisionID <= 4) {
  222. OPBA2B0Found = TRUE;
  223. }
  224. if (SlotNumber.u.bits.DeviceNumber == (0xc8>>3)) {
  225. // Found compatibility OPB. Determine if the compatibility
  226. // OPB has inbound posting enabled by testing bit 0 of reg 54
  227. HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x54, 2);
  228. COPBInbPostingEnabled = (buffer[0] & 0x1) ? TRUE : FALSE;
  229. } else {
  230. // The compatibility OPB ALWAYS has a device
  231. // number 0xc8. Save the ncOPB slot number
  232. // and BusHandler
  233. HalpOrionOPB.Slot = SlotNumber;
  234. HalpOrionOPB.Handler = BusHandler;
  235. }
  236. }
  237. //
  238. // Check the list for host bridges who's existance will mark a
  239. // chipset as 16bit decode. We use this to cover for BIOS
  240. // writers who list "fixed" PnPBIOS resources without noticing
  241. // that such a descriptor implies their device is 10bit decode.
  242. //
  243. if ((!fullDecodeChipset) &&
  244. HalpIsRecognizedCard(PCIRegInfo, PciData,
  245. PCIFT_FULLDECODE_HOSTBRIDGE)) {
  246. fullDecodeChipset = TRUE;
  247. }
  248. //
  249. // Look for ICH, or any other Intel or VIA UHCI USB controller.
  250. //
  251. if ((PciData->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
  252. (PciData->SubClass == PCI_SUBCLASS_SB_USB) &&
  253. (PciData->ProgIf == 0x00)) {
  254. if (PciData->VendorID == 0x8086) {
  255. HalpStopUhciInterrupt(BusNo,
  256. SlotNumber,
  257. TRUE);
  258. } else if (PciData->VendorID == 0x1106) {
  259. HalpStopUhciInterrupt(BusNo,
  260. SlotNumber,
  261. FALSE);
  262. }
  263. }
  264. //
  265. // Look for an OHCI-compliant USB controller.
  266. //
  267. if ((PciData->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
  268. (PciData->SubClass == PCI_SUBCLASS_SB_USB) &&
  269. (PciData->ProgIf == 0x10)) {
  270. HalpStopOhciInterrupt(BusNo,
  271. SlotNumber);
  272. }
  273. Status = HalpGetChipHacks(PciData->VendorID,
  274. PciData->DeviceID,
  275. PciData->RevisionID,
  276. &flags);
  277. if (NT_SUCCESS(Status)) {
  278. if (flags & DISABLE_HIBERNATE_HACK_FLAG) {
  279. HalpDisableHibernate = TRUE;
  280. }
  281. if (flags & WHACK_ICH_USB_SMI_HACK_FLAG) {
  282. HalpWhackICHUsbSmi(BusNo, SlotNumber);
  283. }
  284. }
  285. } // next function
  286. } // next device
  287. } // next bus
  288. //
  289. // Is Orion B0 workaround needed?
  290. //
  291. if (OPBNumber >= 2 && OPBA2B0Found && COPBInbPostingEnabled) {
  292. //
  293. // Replace synchronization functions with Orion specific functions
  294. //
  295. ASSERT (PCIConfigHandler.Synchronize == HalpPCISynchronizeType1);
  296. MmLockPagableCodeSection (&HalpPCISynchronizeOrionB0);
  297. PCIConfigHandler.Synchronize = HalpPCISynchronizeOrionB0;
  298. PCIConfigHandler.ReleaseSynchronzation = HalpPCIReleaseSynchronzationOrionB0;
  299. }
  300. //
  301. // Check if we should crashdump on NMI.
  302. //
  303. HalpGetNMICrashFlag();
  304. #if DBG
  305. HalpTestPci (0);
  306. #endif
  307. //
  308. // Mark the chipset appropriately.
  309. //
  310. HalpMarkChipsetDecode(fullDecodeChipset);
  311. ExFreePool(PCIRegInfo);
  312. }
  313. PBUS_HANDLER
  314. HalpAllocateAndInitPciBusHandler (
  315. IN ULONG HwType,
  316. IN ULONG BusNo,
  317. IN BOOLEAN TestAllocation
  318. )
  319. {
  320. PBUS_HANDLER Bus;
  321. PPCIPBUSDATA BusData;
  322. Bus = HalpAllocateBusHandler (
  323. PCIBus, // Interface type
  324. PCIConfiguration, // Has this configuration space
  325. BusNo, // bus #
  326. Internal, // child of this bus
  327. 0, // and number
  328. sizeof (PCIPBUSDATA) // sizeof bus specific buffer
  329. );
  330. if (!Bus) {
  331. return NULL;
  332. }
  333. //
  334. // Fill in PCI handlers
  335. //
  336. Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
  337. Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
  338. Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
  339. Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
  340. Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
  341. Bus->BusAddresses->Dma.Limit = 0;
  342. BusData = (PPCIPBUSDATA) Bus->BusData;
  343. //
  344. // Fill in common PCI data
  345. //
  346. BusData->CommonData.Tag = PCI_DATA_TAG;
  347. BusData->CommonData.Version = PCI_DATA_VERSION;
  348. BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
  349. BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
  350. BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
  351. BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
  352. //
  353. // Set defaults
  354. //
  355. BusData->MaxDevice = PCI_MAX_DEVICES;
  356. BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
  357. RtlInitializeBitMap (&BusData->DeviceConfigured,
  358. BusData->ConfiguredBits, 256);
  359. switch (HwType) {
  360. case 1:
  361. //
  362. // Initialize access port information for Type1 handlers
  363. //
  364. RtlCopyMemory (&PCIConfigHandler,
  365. &PCIConfigHandlerType1,
  366. sizeof (PCIConfigHandler));
  367. BusData->Config.Type1.Address = (PULONG)PCI_TYPE1_ADDR_PORT;
  368. BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
  369. break;
  370. case 2:
  371. //
  372. // Initialize access port information for Type2 handlers
  373. //
  374. RtlCopyMemory (&PCIConfigHandler,
  375. &PCIConfigHandlerType2,
  376. sizeof (PCIConfigHandler));
  377. BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
  378. BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
  379. BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
  380. //
  381. // Early PCI machines didn't decode the last bit of
  382. // the device id. Shrink type 2 support max device.
  383. //
  384. BusData->MaxDevice = 0x10;
  385. break;
  386. default:
  387. // unsupport type
  388. DBGMSG ("HAL: Unkown PCI type\n");
  389. }
  390. if (!TestAllocation) {
  391. #ifdef SUBCLASSPCI
  392. HalpSubclassPCISupport (Bus, HwType);
  393. #endif
  394. }
  395. return Bus;
  396. }
  397. BOOLEAN
  398. HalpIsIdeDevice(
  399. IN PPCI_COMMON_CONFIG PciData
  400. )
  401. {
  402. if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
  403. (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR)) {
  404. return TRUE;
  405. }
  406. //
  407. // Now look for old, hard to recognize controllers.
  408. //
  409. if (PciData->VendorID == 0x1c1c) { // Old Symphony controller
  410. return TRUE;
  411. }
  412. if ((PciData->VendorID == 0x10B9) &&
  413. ((PciData->DeviceID == 0x5215) ||
  414. (PciData->DeviceID == 0x5219))) { // ALI controllers
  415. return TRUE;
  416. }
  417. if ((PciData->VendorID == 0x1097) &&
  418. (PciData->DeviceID == 0x0038)) { // Appian controller
  419. return TRUE;
  420. }
  421. if ((PciData->VendorID == 0x0E11) &&
  422. (PciData->DeviceID == 0xAE33)) { // Compaq controller
  423. return TRUE;
  424. }
  425. if ((PciData->VendorID == 0x1042) &&
  426. (PciData->DeviceID == 0x1000)) { // PCTECH controller
  427. return TRUE;
  428. }
  429. if ((PciData->VendorID == 0x1039) &&
  430. ((PciData->DeviceID == 0x0601) ||
  431. (PciData->DeviceID == 0x5513))) { // SIS controllers
  432. return TRUE;
  433. }
  434. if ((PciData->VendorID == 0x10AD) &&
  435. ((PciData->DeviceID == 0x0001) ||
  436. (PciData->DeviceID == 0x0150))) { // Newer Symphony controllers
  437. return TRUE;
  438. }
  439. if ((PciData->VendorID == 0x1060) &&
  440. (PciData->DeviceID == 0x0101)) { // United Microelectronics controller
  441. return TRUE;
  442. }
  443. return FALSE;
  444. }