Windows NT 4.0 source code leak
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.

3585 lines
100 KiB

4 years ago
  1. // #pragma comment(exestr, "@(#) pcibus.c 1.1 95/09/28 15:45:56 nec")
  2. /*++
  3. Copyright (c) 1989 Microsoft Corporation
  4. Module Name:
  5. ixpcidat.c
  6. Abstract:
  7. Get/Set bus data routines for the PCI bus
  8. Author:
  9. Ken Reneris (kenr) 14-June-1994
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. Modification History:
  14. H001 Fri Jun 30 02:54:08 1995 kbnes!kisimoto
  15. - Merge build 1057 ixpcibus.c
  16. H002 Tue Jul 4 20:43:12 1995 kbnes!kisimoto
  17. - disable preferred setting for back-to-back
  18. support. If enable, IoAssign... allocates
  19. current enabled address space.
  20. H003 Wed Jul 5 14:27:46 1995 kbnes!kisimoto
  21. - initialize with FALSE
  22. H004 Tue Sep 5 20:06:16 1995 kbnes!kisimoto
  23. - PCI Fast Back-to-back transfer support
  24. --*/
  25. #include "halp.h"
  26. #include "pci.h"
  27. #include "pcip.h"
  28. #if defined(_R94A_) // H001
  29. #include "r94adef.h"
  30. #include "string.h"
  31. #endif // _R94A_
  32. extern WCHAR rgzMultiFunctionAdapter[];
  33. extern WCHAR rgzConfigurationData[];
  34. extern WCHAR rgzIdentifier[];
  35. extern WCHAR rgzPCIIdentifier[];
  36. typedef ULONG (*FncConfigIO) (
  37. IN PPCIPBUSDATA BusData,
  38. IN PVOID State,
  39. IN PUCHAR Buffer,
  40. IN ULONG Offset
  41. );
  42. typedef VOID (*FncSync) (
  43. IN PBUS_HANDLER BusHandler,
  44. IN PCI_SLOT_NUMBER Slot,
  45. IN PKIRQL Irql,
  46. IN PVOID State
  47. );
  48. typedef VOID (*FncReleaseSync) (
  49. IN PBUS_HANDLER BusHandler,
  50. IN KIRQL Irql
  51. );
  52. typedef struct _PCI_CONFIG_HANDLER {
  53. FncSync Synchronize;
  54. FncReleaseSync ReleaseSynchronzation;
  55. FncConfigIO ConfigRead[3];
  56. FncConfigIO ConfigWrite[3];
  57. } PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
  58. //
  59. // Prototypes
  60. //
  61. ULONG
  62. HalpGetPCIData (
  63. IN PBUS_HANDLER BusHandler,
  64. IN PBUS_HANDLER RootHandler,
  65. IN PCI_SLOT_NUMBER SlotNumber,
  66. IN PVOID Buffer,
  67. IN ULONG Offset,
  68. IN ULONG Length
  69. );
  70. ULONG
  71. HalpSetPCIData (
  72. IN PBUS_HANDLER BusHandler,
  73. IN PBUS_HANDLER RootHandler,
  74. IN PCI_SLOT_NUMBER SlotNumber,
  75. IN PVOID Buffer,
  76. IN ULONG Offset,
  77. IN ULONG Length
  78. );
  79. NTSTATUS
  80. HalpAssignPCISlotResources (
  81. IN PBUS_HANDLER BusHandler,
  82. IN PBUS_HANDLER RootHandler,
  83. IN PUNICODE_STRING RegistryPath,
  84. IN PUNICODE_STRING DriverClassName OPTIONAL,
  85. IN PDRIVER_OBJECT DriverObject,
  86. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  87. IN ULONG SlotNumber,
  88. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  89. );
  90. #if 0
  91. VOID
  92. HalpInitializePciBus (
  93. VOID
  94. );
  95. #endif
  96. BOOLEAN
  97. HalpIsValidPCIDevice (
  98. IN PBUS_HANDLER BusHandler,
  99. IN PCI_SLOT_NUMBER Slot
  100. );
  101. BOOLEAN
  102. HalpValidPCISlot (
  103. IN PBUS_HANDLER BusHandler,
  104. IN PCI_SLOT_NUMBER Slot
  105. );
  106. //-------------------------------------------------
  107. VOID HalpPCISynchronizeType1 (
  108. IN PBUS_HANDLER BusHandler,
  109. IN PCI_SLOT_NUMBER Slot,
  110. IN PKIRQL Irql,
  111. IN PVOID State
  112. );
  113. VOID HalpPCIReleaseSynchronzationType1 (
  114. IN PBUS_HANDLER BusHandler,
  115. IN KIRQL Irql
  116. );
  117. ULONG HalpPCIReadUlongType1 (
  118. IN PPCIPBUSDATA BusData,
  119. IN PVOID State,
  120. IN PUCHAR Buffer,
  121. IN ULONG Offset
  122. );
  123. ULONG HalpPCIReadUcharType1 (
  124. IN PPCIPBUSDATA BusData,
  125. IN PVOID State,
  126. IN PUCHAR Buffer,
  127. IN ULONG Offset
  128. );
  129. ULONG HalpPCIReadUshortType1 (
  130. IN PPCIPBUSDATA BusData,
  131. IN PVOID State,
  132. IN PUCHAR Buffer,
  133. IN ULONG Offset
  134. );
  135. ULONG HalpPCIWriteUlongType1 (
  136. IN PPCIPBUSDATA BusData,
  137. IN PVOID State,
  138. IN PUCHAR Buffer,
  139. IN ULONG Offset
  140. );
  141. ULONG HalpPCIWriteUcharType1 (
  142. IN PPCIPBUSDATA BusData,
  143. IN PVOID State,
  144. IN PUCHAR Buffer,
  145. IN ULONG Offset
  146. );
  147. ULONG HalpPCIWriteUshortType1 (
  148. IN PPCIPBUSDATA BusData,
  149. IN PVOID State,
  150. IN PUCHAR Buffer,
  151. IN ULONG Offset
  152. );
  153. VOID HalpPCISynchronizeType2 (
  154. IN PBUS_HANDLER BusHandler,
  155. IN PCI_SLOT_NUMBER Slot,
  156. IN PKIRQL Irql,
  157. IN PVOID State
  158. );
  159. VOID HalpPCIReleaseSynchronzationType2 (
  160. IN PBUS_HANDLER BusHandler,
  161. IN KIRQL Irql
  162. );
  163. ULONG HalpPCIReadUlongType2 (
  164. IN PPCIPBUSDATA BusData,
  165. IN PVOID State,
  166. IN PUCHAR Buffer,
  167. IN ULONG Offset
  168. );
  169. ULONG HalpPCIReadUcharType2 (
  170. IN PPCIPBUSDATA BusData,
  171. IN PVOID State,
  172. IN PUCHAR Buffer,
  173. IN ULONG Offset
  174. );
  175. ULONG HalpPCIReadUshortType2 (
  176. IN PPCIPBUSDATA BusData,
  177. IN PVOID State,
  178. IN PUCHAR Buffer,
  179. IN ULONG Offset
  180. );
  181. ULONG HalpPCIWriteUlongType2 (
  182. IN PPCIPBUSDATA BusData,
  183. IN PVOID State,
  184. IN PUCHAR Buffer,
  185. IN ULONG Offset
  186. );
  187. ULONG HalpPCIWriteUcharType2 (
  188. IN PPCIPBUSDATA BusData,
  189. IN PVOID State,
  190. IN PUCHAR Buffer,
  191. IN ULONG Offset
  192. );
  193. ULONG HalpPCIWriteUshortType2 (
  194. IN PPCIPBUSDATA BusData,
  195. IN PVOID State,
  196. IN PUCHAR Buffer,
  197. IN ULONG Offset
  198. );
  199. //
  200. // Globals
  201. //
  202. // KSPIN_LOCK HalpPCIConfigLock; // H001
  203. PCI_CONFIG_HANDLER PCIConfigHandler;
  204. PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
  205. HalpPCISynchronizeType1,
  206. HalpPCIReleaseSynchronzationType1,
  207. {
  208. HalpPCIReadUlongType1, // 0
  209. HalpPCIReadUcharType1, // 1
  210. HalpPCIReadUshortType1 // 2
  211. },
  212. {
  213. HalpPCIWriteUlongType1, // 0
  214. HalpPCIWriteUcharType1, // 1
  215. HalpPCIWriteUshortType1 // 2
  216. }
  217. };
  218. PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
  219. HalpPCISynchronizeType2,
  220. HalpPCIReleaseSynchronzationType2,
  221. {
  222. HalpPCIReadUlongType2, // 0
  223. HalpPCIReadUcharType2, // 1
  224. HalpPCIReadUshortType2 // 2
  225. },
  226. {
  227. HalpPCIWriteUlongType2, // 0
  228. HalpPCIWriteUcharType2, // 1
  229. HalpPCIWriteUshortType2 // 2
  230. }
  231. };
  232. UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
  233. BOOLEAN HalpDoingCrashDump = FALSE; // H003
  234. ULONG HalpFoundUncapablePCIDevice = 0; // H004
  235. ULONG HalpPCINumberOfMappedGA = 0;
  236. ULONG HalpPCIBackToBackReg0Start = 0;
  237. ULONG HalpPCIBackToBackReg1Start = 0;
  238. ULONG HalpPCIBackToBackReg0Open = 1;
  239. ULONG HalpPCIBackToBackReg1Open = 1;
  240. ULONG HalpNumberOfPCIGA = 0;
  241. ULONG HalpPCIMemoryLimit = 0xffffffff;
  242. #define INIT_VALUE_OF_BACK_TO_BACK_ADDR 0x00000000
  243. #define INIT_VALUE_OF_BACK_TO_BACK_MASK 0xffffffff
  244. VOID
  245. HalpPCIConfig (
  246. IN PBUS_HANDLER BusHandler,
  247. IN PCI_SLOT_NUMBER Slot,
  248. IN PUCHAR Buffer,
  249. IN ULONG Offset,
  250. IN ULONG Length,
  251. IN FncConfigIO *ConfigIO
  252. );
  253. #if defined(_R94A_) // H001
  254. ULONG
  255. HalpGetPCIInterruptVector(
  256. IN PBUS_HANDLER BusHandler,
  257. IN PBUS_HANDLER RootHandler,
  258. IN ULONG BusInterruptLevel,
  259. IN ULONG BusInterruptVector,
  260. OUT PKIRQL Irql,
  261. OUT PKAFFINITY Affinity
  262. );
  263. ULONG
  264. HalpGetNumberOfPCIGA(
  265. IN ULONG NumberBuses
  266. );
  267. VOID
  268. HalpSetBackToBackSpace(
  269. IN PPCI_COMMON_CONFIG PciConfigRequired,
  270. IN PPCI_COMMON_CONFIG PciConfigMapped,
  271. IN PBUS_HANDLER BusHandler
  272. );
  273. VOID
  274. HalpSetBackToBackRegister(
  275. IN ULONG BaseAddress,
  276. IN ULONG Length,
  277. IN ULONG Register
  278. );
  279. #endif // _R94A_
  280. #if DBG
  281. #define DBGMSG(a) DbgPrint(a)
  282. ULONG R94aDoTestPci = 0;
  283. ULONG R94aDoTestPciNec = 0;
  284. ULONG R94aDoOtherTest = 0;
  285. VOID
  286. HalpTestPciNec (
  287. ULONG
  288. );
  289. VOID
  290. HalpTestPciPrintResult(
  291. IN PULONG Buffer,
  292. IN ULONG Length
  293. );
  294. VOID
  295. HalpOtherTestNec (
  296. ULONG
  297. );
  298. VOID
  299. HalpTestPci (
  300. ULONG
  301. );
  302. #else
  303. #define DBGMSG(a)
  304. #endif
  305. #ifdef ALLOC_PRAGMA
  306. #pragma alloc_text(INIT,HalpInitializePciBus)
  307. #pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
  308. #pragma alloc_text(INIT,HalpIsValidPCIDevice)
  309. #pragma alloc_text(PAGE,HalpAssignPCISlotResources)
  310. #endif
  311. VOID
  312. HalpInitializePciBus (
  313. VOID
  314. )
  315. {
  316. PPCI_REGISTRY_INFO PCIRegInfo;
  317. UNICODE_STRING unicodeString, ConfigName, IdentName;
  318. OBJECT_ATTRIBUTES objectAttributes;
  319. HANDLE hMFunc, hBus;
  320. NTSTATUS status;
  321. UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
  322. PWSTR p;
  323. WCHAR wstr[8];
  324. ULONG i, d, junk, HwType, BusNo, f;
  325. PBUS_HANDLER BusHandler;
  326. PCI_SLOT_NUMBER SlotNumber;
  327. PPCI_COMMON_CONFIG PciData;
  328. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
  329. PKEY_VALUE_FULL_INFORMATION ValueInfo;
  330. PCM_FULL_RESOURCE_DESCRIPTOR Desc;
  331. PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
  332. PCI_REGISTRY_INFO tPCIRegInfo; // H001
  333. #if 0 // H001
  334. //
  335. // Search the hardware description looking for any reported
  336. // PCI bus. The first ARC entry for a PCI bus will contain
  337. // the PCI_REGISTRY_INFO.
  338. RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
  339. InitializeObjectAttributes (
  340. &objectAttributes,
  341. &unicodeString,
  342. OBJ_CASE_INSENSITIVE,
  343. NULL, // handle
  344. NULL);
  345. status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
  346. if (!NT_SUCCESS(status)) {
  347. return ;
  348. }
  349. unicodeString.Buffer = wstr;
  350. unicodeString.MaximumLength = sizeof (wstr);
  351. RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
  352. RtlInitUnicodeString (&IdentName, rgzIdentifier);
  353. ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
  354. for (i=0; TRUE; i++) {
  355. RtlIntegerToUnicodeString (i, 10, &unicodeString);
  356. InitializeObjectAttributes (
  357. &objectAttributes,
  358. &unicodeString,
  359. OBJ_CASE_INSENSITIVE,
  360. hMFunc,
  361. NULL);
  362. status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
  363. if (!NT_SUCCESS(status)) {
  364. //
  365. // Out of Multifunction adapter entries...
  366. //
  367. ZwClose (hMFunc);
  368. return ;
  369. }
  370. //
  371. // Check the Indentifier to see if this is a PCI entry
  372. //
  373. status = ZwQueryValueKey (
  374. hBus,
  375. &IdentName,
  376. KeyValueFullInformation,
  377. ValueInfo,
  378. sizeof (buffer),
  379. &junk
  380. );
  381. if (!NT_SUCCESS (status)) {
  382. ZwClose (hBus);
  383. continue;
  384. }
  385. p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
  386. if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
  387. ZwClose (hBus);
  388. continue;
  389. }
  390. //
  391. // The first PCI entry has the PCI_REGISTRY_INFO structure
  392. // attached to it.
  393. //
  394. status = ZwQueryValueKey (
  395. hBus,
  396. &ConfigName,
  397. KeyValueFullInformation,
  398. ValueInfo,
  399. sizeof (buffer),
  400. &junk
  401. );
  402. ZwClose (hBus);
  403. if (!NT_SUCCESS(status)) {
  404. continue ;
  405. }
  406. Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
  407. ValueInfo + ValueInfo->DataOffset);
  408. PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
  409. Desc->PartialResourceList.PartialDescriptors);
  410. if (PDesc->Type == CmResourceTypeDeviceSpecific) {
  411. // got it..
  412. PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
  413. break;
  414. }
  415. }
  416. //
  417. // Initialize spinlock for synchronizing access to PCI space
  418. //
  419. // KeInitializeSpinLock (&HalpPCIConfigLock); // H001
  420. PciData = (PPCI_COMMON_CONFIG) iBuffer;
  421. #endif // 0
  422. #if defined(_R94A_) // H001
  423. PCIRegInfo = &tPCIRegInfo;
  424. PCIRegInfo->NoBuses = 1;
  425. PCIRegInfo->HardwareMechanism=0x1; // HURRICANE PCI Config Type
  426. #if DBG
  427. DbgPrint("PCI System Get Data:\n");
  428. DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision );
  429. DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision );
  430. DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses );
  431. DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism );
  432. #endif // DBG
  433. #endif // _R94A_
  434. //
  435. // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
  436. //
  437. HwType = PCIRegInfo->HardwareMechanism & 0xf;
  438. //
  439. // Some AMI bioses claim machines are Type2 configuration when they
  440. // are really type1. If this is a Type2 with at least one bus,
  441. // try to verify it's not really a type1 bus
  442. //
  443. if (PCIRegInfo->NoBuses && HwType == 2) {
  444. //
  445. // Check each slot for a valid device. Which every style configuration
  446. // space shows a valid device first will be used
  447. //
  448. SlotNumber.u.bits.Reserved = 0;
  449. SlotNumber.u.bits.FunctionNumber = 0;
  450. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  451. SlotNumber.u.bits.DeviceNumber = d;
  452. //
  453. // First try what the BIOS claims - type 2. Allocate type2
  454. // test handle for PCI bus 0.
  455. //
  456. HwType = 2;
  457. BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
  458. if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
  459. break;
  460. }
  461. //
  462. // Valid device not found on Type2 access for this slot.
  463. // Reallocate the bus handler are Type1 and take a look.
  464. //
  465. HwType = 1;
  466. BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
  467. if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
  468. break;
  469. }
  470. HwType = 2;
  471. }
  472. //
  473. // Reset handler for PCI bus 0 to whatever style config space
  474. // was finally decided.
  475. //
  476. HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
  477. }
  478. //
  479. // For each PCI bus present, allocate a handler structure and
  480. // fill in the dispatch functions
  481. //
  482. #if 0 // H001
  483. do {
  484. #endif
  485. for (i=0; i < PCIRegInfo->NoBuses; i++) {
  486. //
  487. // If handler not already built, do it now
  488. //
  489. if (!HalpHandlerForBus (PCIBus, i)) {
  490. HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
  491. }
  492. }
  493. //
  494. // Bus handlers for all PCI buses have been allocated, go collect
  495. // pci bridge information.
  496. //
  497. #if 0 // H001
  498. } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
  499. //
  500. // Fixup SUPPORTED_RANGES
  501. //
  502. HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
  503. //
  504. // Look for PCI controllers which have known work-arounds, and make
  505. // sure they are applied.
  506. //
  507. SlotNumber.u.bits.Reserved = 0;
  508. for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
  509. BusHandler = HalpHandlerForBus (PCIBus, BusNo);
  510. for (d = 0; d < PCI_MAX_DEVICES; d++) {
  511. SlotNumber.u.bits.DeviceNumber = d;
  512. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  513. SlotNumber.u.bits.FunctionNumber = f;
  514. //
  515. // Read PCI configuration information
  516. //
  517. HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
  518. //
  519. // Check for chips with known work-arounds to apply
  520. //
  521. if (PciData->VendorID == 0x8086 &&
  522. PciData->DeviceID == 0x04A3 &&
  523. PciData->RevisionID < 0x11) {
  524. //
  525. // 82430 PCMC controller
  526. //
  527. HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
  528. buffer[0] &= ~0x08; // turn off bit 3 register 0x53
  529. if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
  530. buffer[1] &= ~0x01; // bit 0 register 0x54
  531. }
  532. HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
  533. }
  534. if (PciData->VendorID == 0x8086 &&
  535. PciData->DeviceID == 0x0484 &&
  536. PciData->RevisionID <= 3) {
  537. //
  538. // 82378 ISA bridge & SIO
  539. //
  540. HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
  541. buffer[0] &= ~0x1; // turn off bit 0 register 0x41
  542. HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
  543. }
  544. } // next function
  545. } // next device
  546. } // next bus
  547. #endif
  548. //
  549. // H005
  550. // Compute the number of PCI-GA device and
  551. // initialize Fast Back-to-back register.
  552. //
  553. HalpNumberOfPCIGA = HalpGetNumberOfPCIGA(PCIRegInfo->NoBuses);
  554. #if DBG
  555. HalpTestPci (0);
  556. #if defined(_R94A_)
  557. DbgPrint("HalpInitializePciBus: Call HalpTestPci(%x)\n",R94aDoTestPci);
  558. HalpTestPci (R94aDoTestPci);
  559. DbgPrint("HalpInitializePciBus: Call HalpTestPciNec(%x)\n",R94aDoTestPciNec);
  560. HalpTestPciNec (R94aDoTestPciNec);
  561. DbgPrint("HalpInitializePciBus: Call HalpOtherTest(%x)\n",R94aDoOtherTest);
  562. HalpOtherTestNec (R94aDoOtherTest);
  563. #endif
  564. #endif
  565. }
  566. PBUS_HANDLER
  567. HalpAllocateAndInitPciBusHandler (
  568. IN ULONG HwType,
  569. IN ULONG BusNo,
  570. IN BOOLEAN TestAllocation
  571. )
  572. {
  573. PBUS_HANDLER Bus;
  574. PPCIPBUSDATA BusData;
  575. Bus = HalpAllocateBusHandler (
  576. PCIBus, // Interface type
  577. PCIConfiguration, // Has this configuration space
  578. BusNo, // bus #
  579. Internal, // child of this bus
  580. 0, // and number
  581. sizeof (PCIPBUSDATA) // sizeof bus specific buffer
  582. );
  583. //
  584. // Fill in PCI handlers
  585. //
  586. Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
  587. Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
  588. #if defined(_R94A_)
  589. Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIInterruptVector;
  590. #else
  591. Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
  592. #endif
  593. Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
  594. Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
  595. Bus->BusAddresses->Dma.Limit = 0;
  596. BusData = (PPCIPBUSDATA) Bus->BusData;
  597. //
  598. // Fill in common PCI data
  599. //
  600. BusData->CommonData.Tag = PCI_DATA_TAG;
  601. BusData->CommonData.Version = PCI_DATA_VERSION;
  602. BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
  603. BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
  604. BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
  605. BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
  606. //
  607. // Set defaults
  608. //
  609. BusData->MaxDevice = PCI_MAX_DEVICES;
  610. BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
  611. RtlInitializeBitMap (&BusData->DeviceConfigured,
  612. BusData->ConfiguredBits, 256);
  613. switch (HwType) {
  614. case 1:
  615. //
  616. // Initialize access port information for Type1 handlers
  617. //
  618. RtlCopyMemory (&PCIConfigHandler,
  619. &PCIConfigHandlerType1,
  620. sizeof (PCIConfigHandler));
  621. #if defined(_R94A_) // H001
  622. BusData->Config.Type1.Address = (PULONG)R94A_PCI_TYPE1_ADDR_PORT;
  623. BusData->Config.Type1.Data = R94A_PCI_TYPE1_DATA_PORT;
  624. #else
  625. BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
  626. BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
  627. #endif // _R94A_
  628. break;
  629. case 2:
  630. //
  631. // Initialize access port information for Type2 handlers
  632. //
  633. RtlCopyMemory (&PCIConfigHandler,
  634. &PCIConfigHandlerType2,
  635. sizeof (PCIConfigHandler));
  636. BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
  637. BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
  638. BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
  639. //
  640. // Early PCI machines didn't decode the last bit of
  641. // the device id. Shrink type 2 support max device.
  642. //
  643. BusData->MaxDevice = 0x10;
  644. break;
  645. default:
  646. // unsupport type
  647. DBGMSG ("HAL: Unkown PCI type\n");
  648. }
  649. if (!TestAllocation) {
  650. #ifdef SUBCLASSPCI
  651. HalpSubclassPCISupport (Bus, HwType);
  652. #endif
  653. }
  654. return Bus;
  655. }
  656. BOOLEAN
  657. HalpIsValidPCIDevice (
  658. IN PBUS_HANDLER BusHandler,
  659. IN PCI_SLOT_NUMBER Slot
  660. )
  661. /*++
  662. Routine Description:
  663. Reads the device configuration data for the given slot and
  664. returns TRUE if the configuration data appears to be valid for
  665. a PCI device; otherwise returns FALSE.
  666. Arguments:
  667. BusHandler - Bus to check
  668. Slot - Slot to check
  669. --*/
  670. {
  671. PPCI_COMMON_CONFIG PciData;
  672. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
  673. ULONG i, j;
  674. PciData = (PPCI_COMMON_CONFIG) iBuffer;
  675. //
  676. // Read device common header
  677. //
  678. HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
  679. //
  680. // Valid device header?
  681. //
  682. if (PciData->VendorID == PCI_INVALID_VENDORID ||
  683. PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
  684. return FALSE;
  685. }
  686. //
  687. // Check fields for reasonable values
  688. //
  689. if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
  690. (PciData->u.type0.InterruptLine & 0x70)) {
  691. return FALSE;
  692. }
  693. for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
  694. j = PciData->u.type0.BaseAddresses[i];
  695. if (j & PCI_ADDRESS_IO_SPACE) {
  696. if ((j > 0x2 && j < 0xffff) || j > 0xffffff) { // H001
  697. // IO port < 64KB | IO port > 16MB
  698. return FALSE;
  699. }
  700. } else {
  701. if (j > 0xf && j < 0x3ffffff) { // H001
  702. // Mem address < 64MB
  703. return FALSE;
  704. }
  705. }
  706. if (Is64BitBaseAddress(j)) {
  707. i += 1;
  708. }
  709. }
  710. //
  711. // Guess it's a valid device..
  712. //
  713. return TRUE;
  714. }
  715. ULONG
  716. HalpGetPCIData (
  717. IN PBUS_HANDLER BusHandler,
  718. IN PBUS_HANDLER RootHandler,
  719. IN PCI_SLOT_NUMBER Slot,
  720. IN PUCHAR Buffer,
  721. IN ULONG Offset,
  722. IN ULONG Length
  723. )
  724. /*++
  725. Routine Description:
  726. The function returns the Pci bus data for a device.
  727. Arguments:
  728. BusNumber - Indicates which bus.
  729. VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
  730. Buffer - Supplies the space to store the data.
  731. Length - Supplies a count in bytes of the maximum amount to return.
  732. Return Value:
  733. Returns the amount of data stored into the buffer.
  734. If this PCI slot has never been set, then the configuration information
  735. returned is zeroed.
  736. --*/
  737. {
  738. PPCI_COMMON_CONFIG PciData;
  739. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
  740. PPCIPBUSDATA BusData;
  741. ULONG Len;
  742. ULONG i, bit;
  743. if (Length > sizeof (PCI_COMMON_CONFIG)) {
  744. Length = sizeof (PCI_COMMON_CONFIG);
  745. }
  746. Len = 0;
  747. PciData = (PPCI_COMMON_CONFIG) iBuffer;
  748. if (Offset >= PCI_COMMON_HDR_LENGTH) {
  749. //
  750. // The user did not request any data from the common
  751. // header. Verify the PCI device exists, then continue
  752. // in the device specific area.
  753. //
  754. HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
  755. if (PciData->VendorID == PCI_INVALID_VENDORID) {
  756. return 0;
  757. }
  758. } else {
  759. //
  760. // Caller requested at least some data within the
  761. // common header. Read the whole header, effect the
  762. // fields we need to and then copy the user's requested
  763. // bytes from the header
  764. //
  765. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  766. //
  767. // Read this PCI devices slot data
  768. //
  769. Len = PCI_COMMON_HDR_LENGTH;
  770. HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
  771. #if 0
  772. DbgPrint ("--------------->>> Now Print the Slot Information\n");
  773. DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
  774. BusHandler->BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, PciData->VendorID, PciData->DeviceID,
  775. PciData->RevisionID);
  776. if (PciData->u.type0.InterruptPin) {
  777. DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin);
  778. }
  779. if (PciData->u.type0.InterruptLine) {
  780. DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine);
  781. }
  782. if (PciData->u.type0.ROMBaseAddress) {
  783. DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress);
  784. }
  785. DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
  786. PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
  787. { ULONG k, j;
  788. k = 0;
  789. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  790. if (PciData->u.type0.BaseAddresses[j]) {
  791. DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
  792. k = 1;
  793. }
  794. }
  795. DbgPrint("\n");
  796. }
  797. #endif // DBG
  798. if (PciData->VendorID == PCI_INVALID_VENDORID ||
  799. PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
  800. PciData->VendorID = PCI_INVALID_VENDORID;
  801. Len = 2; // only return invalid id
  802. } else {
  803. BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
  804. }
  805. //
  806. // Has this PCI device been configured?
  807. //
  808. #if DBG
  809. //
  810. // On DBG build, if this PCI device has not yet been configured,
  811. // then don't report any current configuration the device may have.
  812. //
  813. bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
  814. if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
  815. for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
  816. PciData->u.type0.BaseAddresses[i] = 0;
  817. }
  818. PciData->u.type0.ROMBaseAddress = 0;
  819. PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
  820. }
  821. #endif
  822. //
  823. // Copy whatever data overlaps into the callers buffer
  824. //
  825. if (Len < Offset) {
  826. // no data at caller's buffer
  827. return 0;
  828. }
  829. Len -= Offset;
  830. if (Len > Length) {
  831. Len = Length;
  832. }
  833. RtlMoveMemory(Buffer, iBuffer + Offset, Len);
  834. Offset += Len;
  835. Buffer += Len;
  836. Length -= Len;
  837. }
  838. if (Length) {
  839. if (Offset >= PCI_COMMON_HDR_LENGTH) {
  840. //
  841. // The remaining Buffer comes from the Device Specific
  842. // area - put on the kitten gloves and read from it.
  843. //
  844. // Specific read/writes to the PCI device specific area
  845. // are guarenteed:
  846. //
  847. // Not to read/write any byte outside the area specified
  848. // by the caller. (this may cause WORD or BYTE references
  849. // to the area in order to read the non-dword aligned
  850. // ends of the request)
  851. //
  852. // To use a WORD access if the requested length is exactly
  853. // a WORD long.
  854. //
  855. // To use a BYTE access if the requested length is exactly
  856. // a BYTE long.
  857. //
  858. HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
  859. Len += Length;
  860. }
  861. }
  862. return Len;
  863. }
  864. ULONG
  865. HalpSetPCIData (
  866. IN PBUS_HANDLER BusHandler,
  867. IN PBUS_HANDLER RootHandler,
  868. IN PCI_SLOT_NUMBER Slot,
  869. IN PUCHAR Buffer,
  870. IN ULONG Offset,
  871. IN ULONG Length
  872. )
  873. /*++
  874. Routine Description:
  875. The function returns the Pci bus data for a device.
  876. Arguments:
  877. VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
  878. Buffer - Supplies the space to store the data.
  879. Length - Supplies a count in bytes of the maximum amount to return.
  880. Return Value:
  881. Returns the amount of data stored into the buffer.
  882. --*/
  883. {
  884. PPCI_COMMON_CONFIG PciData, PciData2;
  885. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
  886. UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
  887. PPCIPBUSDATA BusData;
  888. ULONG Len, cnt;
  889. if (Length > sizeof (PCI_COMMON_CONFIG)) {
  890. Length = sizeof (PCI_COMMON_CONFIG);
  891. }
  892. Len = 0;
  893. PciData = (PPCI_COMMON_CONFIG) iBuffer;
  894. PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
  895. if (Offset >= PCI_COMMON_HDR_LENGTH) {
  896. //
  897. // The user did not request any data from the common
  898. // header. Verify the PCI device exists, then continue in
  899. // the device specific area.
  900. //
  901. HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
  902. if (PciData->VendorID == PCI_INVALID_VENDORID) {
  903. return 0;
  904. }
  905. } else {
  906. //
  907. // Caller requested to set at least some data within the
  908. // common header.
  909. //
  910. Len = PCI_COMMON_HDR_LENGTH;
  911. HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
  912. if (PciData->VendorID == PCI_INVALID_VENDORID ||
  913. PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
  914. // no device, or header type unkown
  915. return 0;
  916. }
  917. //
  918. // Set this device as configured
  919. //
  920. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  921. #if DBG
  922. cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
  923. RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
  924. #endif
  925. //
  926. // Copy COMMON_HDR values to buffer2, then overlay callers changes.
  927. //
  928. RtlMoveMemory (iBuffer2, iBuffer, Len);
  929. BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
  930. Len -= Offset;
  931. if (Len > Length) {
  932. Len = Length;
  933. }
  934. RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
  935. // in case interrupt line or pin was editted
  936. BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
  937. #if DBG
  938. //
  939. // Verify R/O fields haven't changed
  940. //
  941. if (PciData2->VendorID != PciData->VendorID ||
  942. PciData2->DeviceID != PciData->DeviceID ||
  943. PciData2->RevisionID != PciData->RevisionID ||
  944. PciData2->ProgIf != PciData->ProgIf ||
  945. PciData2->SubClass != PciData->SubClass ||
  946. PciData2->BaseClass != PciData->BaseClass ||
  947. PciData2->HeaderType != PciData->HeaderType ||
  948. PciData2->BaseClass != PciData->BaseClass ||
  949. PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
  950. PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
  951. DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
  952. DbgBreakPoint ();
  953. }
  954. #endif
  955. //
  956. // Set new PCI configuration
  957. //
  958. #if DBG // H001
  959. DbgPrint("SetPciData: PciData2->u.type0.InterruptLine:%x\n",PciData2->u.type0.InterruptLine);
  960. #endif
  961. HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
  962. Offset += Len;
  963. Buffer += Len;
  964. Length -= Len;
  965. }
  966. if (Length) {
  967. if (Offset >= PCI_COMMON_HDR_LENGTH) {
  968. //
  969. // The remaining Buffer comes from the Device Specific
  970. // area - put on the kitten gloves and write it
  971. //
  972. // Specific read/writes to the PCI device specific area
  973. // are guarenteed:
  974. //
  975. // Not to read/write any byte outside the area specified
  976. // by the caller. (this may cause WORD or BYTE references
  977. // to the area in order to read the non-dword aligned
  978. // ends of the request)
  979. //
  980. // To use a WORD access if the requested length is exactly
  981. // a WORD long.
  982. //
  983. // To use a BYTE access if the requested length is exactly
  984. // a BYTE long.
  985. //
  986. HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
  987. Len += Length;
  988. }
  989. }
  990. return Len;
  991. }
  992. VOID
  993. HalpReadPCIConfig (
  994. IN PBUS_HANDLER BusHandler,
  995. IN PCI_SLOT_NUMBER Slot,
  996. IN PVOID Buffer,
  997. IN ULONG Offset,
  998. IN ULONG Length
  999. )
  1000. {
  1001. USHORT IdValue; // H001
  1002. ULONG OrigData; // H001
  1003. if (!HalpValidPCISlot (BusHandler, Slot)) {
  1004. //
  1005. // Invalid SlotID return no data
  1006. //
  1007. RtlFillMemory (Buffer, Length, (UCHAR) -1);
  1008. return ;
  1009. }
  1010. #if defined(_R94A_) // H001
  1011. //
  1012. // resolve PCI master abort during we are looking for PCI device
  1013. // check to see if spcified slot is valid.
  1014. //
  1015. //
  1016. // Disable PCI-MasterAbort interrupt during configration read.
  1017. //
  1018. OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
  1019. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
  1020. HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
  1021. PCIConfigHandler.ConfigRead);
  1022. if (IdValue == 0xffff){
  1023. //
  1024. // This PCI slot has no card
  1025. // wait until ReceivedMasterAbort bit is set
  1026. //
  1027. while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
  1028. ;
  1029. //
  1030. // clear the ReceivedMasterAbort bit
  1031. //
  1032. WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
  1033. //
  1034. // Clear memory address error registers.
  1035. //
  1036. {
  1037. LARGE_INTEGER registerLarge;
  1038. READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
  1039. }
  1040. //
  1041. // Restore the PCIInterruptEnable register, and return no data
  1042. //
  1043. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
  1044. RtlFillMemory (Buffer, Length, (UCHAR) -1);
  1045. return ;
  1046. }
  1047. //
  1048. // Restore the PCIInterruptEnable register.
  1049. //
  1050. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
  1051. #endif // _R94A_
  1052. HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
  1053. PCIConfigHandler.ConfigRead);
  1054. }
  1055. VOID
  1056. HalpWritePCIConfig (
  1057. IN PBUS_HANDLER BusHandler,
  1058. IN PCI_SLOT_NUMBER Slot,
  1059. IN PVOID Buffer,
  1060. IN ULONG Offset,
  1061. IN ULONG Length
  1062. )
  1063. {
  1064. USHORT IdValue; // H001
  1065. ULONG OrigData; // H001
  1066. if (!HalpValidPCISlot (BusHandler, Slot)) {
  1067. //
  1068. // Invalid SlotID do nothing
  1069. //
  1070. return ;
  1071. }
  1072. #if defined(_R94A_) // H001
  1073. //
  1074. // resolve PCI master abort during we are looking for PCI device
  1075. // check to see if spcified slot is valid.
  1076. //
  1077. //
  1078. // Disable PCI-MasterAbort interrupt during configration read.
  1079. //
  1080. OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
  1081. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
  1082. HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
  1083. PCIConfigHandler.ConfigRead);
  1084. if (IdValue == 0xffff){
  1085. //
  1086. // This PCI slot has no card
  1087. // wait until ReceivedMasterAbort bit is set
  1088. //
  1089. while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
  1090. ;
  1091. //
  1092. // clear the ReceivedMasterAbort bit
  1093. //
  1094. WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
  1095. //
  1096. // Clear memory address error registers.
  1097. //
  1098. {
  1099. LARGE_INTEGER registerLarge;
  1100. READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &registerLarge);
  1101. }
  1102. //
  1103. // Restore the PCIInterruptEnable register, and return no data
  1104. //
  1105. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
  1106. RtlFillMemory (Buffer, Length, (UCHAR) -1);
  1107. return ;
  1108. }
  1109. //
  1110. // Restore the PCIInterruptEnable register.
  1111. //
  1112. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
  1113. #endif // _R94A_
  1114. HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
  1115. PCIConfigHandler.ConfigWrite);
  1116. }
  1117. BOOLEAN
  1118. HalpValidPCISlot (
  1119. IN PBUS_HANDLER BusHandler,
  1120. IN PCI_SLOT_NUMBER Slot
  1121. )
  1122. {
  1123. PCI_SLOT_NUMBER Slot2;
  1124. PPCIPBUSDATA BusData;
  1125. UCHAR HeaderType;
  1126. ULONG i;
  1127. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1128. if (Slot.u.bits.Reserved != 0) {
  1129. return FALSE;
  1130. }
  1131. #if defined(_R94A_) // H001
  1132. if (Slot.u.bits.DeviceNumber < 3 ||
  1133. Slot.u.bits.DeviceNumber > 20) {
  1134. return FALSE;
  1135. }
  1136. #else
  1137. if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
  1138. return FALSE;
  1139. }
  1140. #endif // _R94A_
  1141. if (Slot.u.bits.FunctionNumber == 0) {
  1142. return TRUE;
  1143. }
  1144. //
  1145. // Non zero function numbers are only supported if the
  1146. // device has the PCI_MULTIFUNCTION bit set in it's header
  1147. //
  1148. i = Slot.u.bits.DeviceNumber;
  1149. //
  1150. // Read DeviceNumber, Function zero, to determine if the
  1151. // PCI supports multifunction devices
  1152. //
  1153. Slot2 = Slot;
  1154. Slot2.u.bits.FunctionNumber = 0;
  1155. HalpReadPCIConfig (
  1156. BusHandler,
  1157. Slot2,
  1158. &HeaderType,
  1159. FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
  1160. sizeof (UCHAR)
  1161. );
  1162. if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
  1163. // this device doesn't exists or doesn't support MULTIFUNCTION types
  1164. return FALSE;
  1165. }
  1166. return TRUE;
  1167. }
  1168. VOID
  1169. HalpPCIConfig (
  1170. IN PBUS_HANDLER BusHandler,
  1171. IN PCI_SLOT_NUMBER Slot,
  1172. IN PUCHAR Buffer,
  1173. IN ULONG Offset,
  1174. IN ULONG Length,
  1175. IN FncConfigIO *ConfigIO
  1176. )
  1177. {
  1178. KIRQL OldIrql;
  1179. ULONG i;
  1180. UCHAR State[20];
  1181. PPCIPBUSDATA BusData;
  1182. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1183. if (Slot.u.bits.DeviceNumber < 3) { // H001
  1184. #if DBG
  1185. DbgPrint("HalpPCIConfig: Ignore Slot %x\n",Slot.u.bits.DeviceNumber);
  1186. #endif
  1187. return;
  1188. }
  1189. PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
  1190. while (Length) {
  1191. i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
  1192. i = ConfigIO[i] (BusData, State, Buffer, Offset);
  1193. Offset += i;
  1194. Buffer += i;
  1195. Length -= i;
  1196. }
  1197. PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
  1198. }
  1199. VOID HalpPCISynchronizeType1 (
  1200. IN PBUS_HANDLER BusHandler,
  1201. IN PCI_SLOT_NUMBER Slot,
  1202. IN PKIRQL Irql,
  1203. IN PPCI_TYPE1_CFG_BITS PciCfg1
  1204. )
  1205. {
  1206. //
  1207. // Initialize PciCfg1
  1208. //
  1209. PciCfg1->u.AsULONG = 0;
  1210. PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
  1211. PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
  1212. PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
  1213. PciCfg1->u.bits.Enable = TRUE;
  1214. //
  1215. // Synchronize with PCI type1 config space
  1216. //
  1217. if (!HalpDoingCrashDump) {
  1218. KeRaiseIrql (PROFILE_LEVEL, Irql); // H001
  1219. KiAcquireSpinLock (&HalpPCIConfigLock);
  1220. } else {
  1221. *Irql = HIGH_LEVEL;
  1222. }
  1223. }
  1224. VOID HalpPCIReleaseSynchronzationType1 (
  1225. IN PBUS_HANDLER BusHandler,
  1226. IN KIRQL Irql
  1227. )
  1228. {
  1229. PCI_TYPE1_CFG_BITS PciCfg1;
  1230. PPCIPBUSDATA BusData;
  1231. //
  1232. // Disable PCI configuration space
  1233. //
  1234. PciCfg1.u.AsULONG = 0;
  1235. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1236. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
  1237. //
  1238. // Release spinlock
  1239. //
  1240. if (!HalpDoingCrashDump) {
  1241. KiReleaseSpinLock (&HalpPCIConfigLock);
  1242. KeLowerIrql (Irql); // H001
  1243. }
  1244. }
  1245. ULONG
  1246. HalpPCIReadUcharType1 (
  1247. IN PPCIPBUSDATA BusData,
  1248. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  1249. IN PUCHAR Buffer,
  1250. IN ULONG Offset
  1251. )
  1252. {
  1253. ULONG i;
  1254. i = Offset % sizeof(ULONG);
  1255. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  1256. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
  1257. *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
  1258. return sizeof (UCHAR);
  1259. }
  1260. ULONG
  1261. HalpPCIReadUshortType1 (
  1262. IN PPCIPBUSDATA BusData,
  1263. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  1264. IN PUCHAR Buffer,
  1265. IN ULONG Offset
  1266. )
  1267. {
  1268. ULONG i;
  1269. i = Offset % sizeof(ULONG);
  1270. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  1271. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
  1272. *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
  1273. return sizeof (USHORT);
  1274. }
  1275. ULONG
  1276. HalpPCIReadUlongType1 (
  1277. IN PPCIPBUSDATA BusData,
  1278. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  1279. IN PUCHAR Buffer,
  1280. IN ULONG Offset
  1281. )
  1282. {
  1283. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  1284. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
  1285. *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
  1286. return sizeof (ULONG);
  1287. }
  1288. ULONG
  1289. HalpPCIWriteUcharType1 (
  1290. IN PPCIPBUSDATA BusData,
  1291. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  1292. IN PUCHAR Buffer,
  1293. IN ULONG Offset
  1294. )
  1295. {
  1296. ULONG i;
  1297. i = Offset % sizeof(ULONG);
  1298. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  1299. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
  1300. WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer);
  1301. return sizeof (UCHAR);
  1302. }
  1303. ULONG
  1304. HalpPCIWriteUshortType1 (
  1305. IN PPCIPBUSDATA BusData,
  1306. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  1307. IN PUCHAR Buffer,
  1308. IN ULONG Offset
  1309. )
  1310. {
  1311. ULONG i;
  1312. i = Offset % sizeof(ULONG);
  1313. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  1314. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
  1315. WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
  1316. return sizeof (USHORT);
  1317. }
  1318. ULONG
  1319. HalpPCIWriteUlongType1 (
  1320. IN PPCIPBUSDATA BusData,
  1321. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  1322. IN PUCHAR Buffer,
  1323. IN ULONG Offset
  1324. )
  1325. {
  1326. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  1327. WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
  1328. WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
  1329. return sizeof (ULONG);
  1330. }
  1331. VOID HalpPCISynchronizeType2 (
  1332. IN PBUS_HANDLER BusHandler,
  1333. IN PCI_SLOT_NUMBER Slot,
  1334. IN PKIRQL Irql,
  1335. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
  1336. )
  1337. {
  1338. PCI_TYPE2_CSE_BITS PciCfg2Cse;
  1339. PPCIPBUSDATA BusData;
  1340. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1341. //
  1342. // Initialize Cfg2Addr
  1343. //
  1344. PciCfg2Addr->u.AsUSHORT = 0;
  1345. PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
  1346. PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
  1347. //
  1348. // Synchronize with type2 config space - type2 config space
  1349. // remaps 4K of IO space, so we can not allow other I/Os to occur
  1350. // while using type2 config space.
  1351. //
  1352. HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
  1353. PciCfg2Cse.u.AsUCHAR = 0;
  1354. PciCfg2Cse.u.bits.Enable = TRUE;
  1355. PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
  1356. PciCfg2Cse.u.bits.Key = 0xff;
  1357. //
  1358. // Select bus & enable type 2 configuration space
  1359. //
  1360. WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
  1361. WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
  1362. }
  1363. VOID HalpPCIReleaseSynchronzationType2 (
  1364. IN PBUS_HANDLER BusHandler,
  1365. IN KIRQL Irql
  1366. )
  1367. {
  1368. PCI_TYPE2_CSE_BITS PciCfg2Cse;
  1369. PPCIPBUSDATA BusData;
  1370. //
  1371. // disable PCI configuration space
  1372. //
  1373. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1374. PciCfg2Cse.u.AsUCHAR = 0;
  1375. WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
  1376. WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
  1377. //
  1378. // Restore interrupts, release spinlock
  1379. //
  1380. HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
  1381. }
  1382. ULONG
  1383. HalpPCIReadUcharType2 (
  1384. IN PPCIPBUSDATA BusData,
  1385. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
  1386. IN PUCHAR Buffer,
  1387. IN ULONG Offset
  1388. )
  1389. {
  1390. PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
  1391. *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
  1392. return sizeof (UCHAR);
  1393. }
  1394. ULONG
  1395. HalpPCIReadUshortType2 (
  1396. IN PPCIPBUSDATA BusData,
  1397. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
  1398. IN PUCHAR Buffer,
  1399. IN ULONG Offset
  1400. )
  1401. {
  1402. PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
  1403. *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
  1404. return sizeof (USHORT);
  1405. }
  1406. ULONG
  1407. HalpPCIReadUlongType2 (
  1408. IN PPCIPBUSDATA BusData,
  1409. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
  1410. IN PUCHAR Buffer,
  1411. IN ULONG Offset
  1412. )
  1413. {
  1414. PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
  1415. *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
  1416. return sizeof(ULONG);
  1417. }
  1418. ULONG
  1419. HalpPCIWriteUcharType2 (
  1420. IN PPCIPBUSDATA BusData,
  1421. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
  1422. IN PUCHAR Buffer,
  1423. IN ULONG Offset
  1424. )
  1425. {
  1426. PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
  1427. WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
  1428. return sizeof (UCHAR);
  1429. }
  1430. ULONG
  1431. HalpPCIWriteUshortType2 (
  1432. IN PPCIPBUSDATA BusData,
  1433. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
  1434. IN PUCHAR Buffer,
  1435. IN ULONG Offset
  1436. )
  1437. {
  1438. PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
  1439. WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
  1440. return sizeof (USHORT);
  1441. }
  1442. ULONG
  1443. HalpPCIWriteUlongType2 (
  1444. IN PPCIPBUSDATA BusData,
  1445. IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
  1446. IN PUCHAR Buffer,
  1447. IN ULONG Offset
  1448. )
  1449. {
  1450. PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
  1451. WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
  1452. return sizeof(ULONG);
  1453. }
  1454. NTSTATUS
  1455. HalpAssignPCISlotResources (
  1456. IN PBUS_HANDLER BusHandler,
  1457. IN PBUS_HANDLER RootHandler,
  1458. IN PUNICODE_STRING RegistryPath,
  1459. IN PUNICODE_STRING DriverClassName OPTIONAL,
  1460. IN PDRIVER_OBJECT DriverObject,
  1461. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  1462. IN ULONG Slot,
  1463. IN OUT PCM_RESOURCE_LIST *pAllocatedResources
  1464. )
  1465. /*++
  1466. Routine Description:
  1467. Reads the targeted device to determine it's required resources.
  1468. Calls IoAssignResources to allocate them.
  1469. Sets the targeted device with it's assigned resoruces
  1470. and returns the assignments to the caller.
  1471. Arguments:
  1472. Return Value:
  1473. STATUS_SUCCESS or error
  1474. --*/
  1475. {
  1476. NTSTATUS status;
  1477. PUCHAR WorkingPool;
  1478. PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
  1479. PCI_COMMON_CONFIG PciData3; // H005
  1480. PCI_SLOT_NUMBER PciSlot;
  1481. PPCIPBUSDATA BusData;
  1482. PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
  1483. PIO_RESOURCE_DESCRIPTOR Descriptor;
  1484. PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
  1485. ULONG BusNumber;
  1486. ULONG i, j, m, length, memtype;
  1487. ULONG NoBaseAddress, RomIndex, Option;
  1488. PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
  1489. PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
  1490. BOOLEAN Match, EnableRomBase;
  1491. *pAllocatedResources = NULL;
  1492. PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
  1493. BusNumber = BusHandler->BusNumber;
  1494. BusData = (PPCIPBUSDATA) BusHandler->BusData;
  1495. //
  1496. // Allocate some pool for working space
  1497. //
  1498. i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
  1499. sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
  1500. PCI_COMMON_HDR_LENGTH * 3;
  1501. WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
  1502. if (!WorkingPool) {
  1503. return STATUS_INSUFFICIENT_RESOURCES;
  1504. }
  1505. //
  1506. // Zero initialize pool, and get pointers into memory
  1507. //
  1508. RtlZeroMemory (WorkingPool, i);
  1509. CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
  1510. PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
  1511. PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
  1512. PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
  1513. //
  1514. // Read the PCI device's configuration
  1515. //
  1516. HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
  1517. if (PciData->VendorID == PCI_INVALID_VENDORID) {
  1518. ExFreePool (WorkingPool);
  1519. return STATUS_NO_SUCH_DEVICE;
  1520. }
  1521. //
  1522. // Make a copy of the device's current settings
  1523. //
  1524. RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
  1525. //
  1526. // Initialize base addresses base on configuration data type
  1527. //
  1528. switch (PCI_CONFIG_TYPE(PciData)) {
  1529. case 0 :
  1530. NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
  1531. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  1532. BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
  1533. OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
  1534. }
  1535. BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
  1536. OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
  1537. RomIndex = j;
  1538. break;
  1539. case 1:
  1540. NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
  1541. for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
  1542. BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
  1543. OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
  1544. }
  1545. BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
  1546. OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
  1547. RomIndex = j;
  1548. break;
  1549. default:
  1550. ExFreePool (WorkingPool);
  1551. return STATUS_NO_SUCH_DEVICE;
  1552. }
  1553. //
  1554. // If the BIOS doesn't have the device's ROM enabled, then we won't
  1555. // enable it either. Remove it from the list.
  1556. //
  1557. EnableRomBase = TRUE;
  1558. #if 0 // H001
  1559. if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
  1560. ASSERT (RomIndex+1 == NoBaseAddress);
  1561. EnableRomBase = FALSE;
  1562. NoBaseAddress -= 1;
  1563. }
  1564. #endif
  1565. //
  1566. // Set resources to all bits on to see what type of resources
  1567. // are required.
  1568. //
  1569. for (j=0; j < NoBaseAddress; j++) {
  1570. *BaseAddress[j] = 0xFFFFFFFF;
  1571. }
  1572. PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
  1573. *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
  1574. HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
  1575. HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
  1576. //
  1577. // H004
  1578. // Make a copy of the device's current settings
  1579. //
  1580. RtlMoveMemory ((PPCI_COMMON_CONFIG)&PciData3, PciData, PCI_COMMON_HDR_LENGTH);
  1581. // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
  1582. BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
  1583. //
  1584. // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
  1585. //
  1586. CompleteList->InterfaceType = PCIBus;
  1587. CompleteList->BusNumber = BusNumber;
  1588. CompleteList->SlotNumber = Slot;
  1589. CompleteList->AlternativeLists = 1;
  1590. CompleteList->List[0].Version = 1;
  1591. CompleteList->List[0].Revision = 1;
  1592. Descriptor = CompleteList->List[0].Descriptors;
  1593. //
  1594. // If PCI device has an interrupt resource, add it
  1595. //
  1596. if (PciData->u.type0.InterruptPin) {
  1597. CompleteList->List[0].Count++;
  1598. Descriptor->Option = 0;
  1599. Descriptor->Type = CmResourceTypeInterrupt;
  1600. Descriptor->ShareDisposition = CmResourceShareShared;
  1601. Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  1602. // Fill in any vector here - we'll pick it back up in
  1603. // HalAdjustResourceList and adjust it to it's allowed settings
  1604. Descriptor->u.Interrupt.MinimumVector = 0;
  1605. Descriptor->u.Interrupt.MaximumVector = 0xff;
  1606. Descriptor++;
  1607. }
  1608. //
  1609. // Add a memory/port resoruce for each PCI resource
  1610. //
  1611. // Clear ROM reserved bits
  1612. *BaseAddress[RomIndex] &= ~0x7FF;
  1613. for (j=0; j < NoBaseAddress; j++) {
  1614. if (*BaseAddress[j]) {
  1615. i = *BaseAddress[j];
  1616. // scan for first set bit, that's the length & alignment
  1617. length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
  1618. while (!(i & length) && length) {
  1619. length <<= 1;
  1620. }
  1621. // scan for last set bit, that's the maxaddress + 1
  1622. for (m = length; i & m; m <<= 1) ;
  1623. m--;
  1624. // check for hosed PCI configuration requirements
  1625. if (length & ~m) {
  1626. #if DBG
  1627. DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
  1628. BusNumber,
  1629. PciSlot.u.bits.DeviceNumber,
  1630. PciSlot.u.bits.FunctionNumber
  1631. );
  1632. DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
  1633. #endif
  1634. // the device is in error - punt. don't allow this
  1635. // resource any option - it either gets set to whatever
  1636. // bits it was able to return, or it doesn't get set.
  1637. if (i & PCI_ADDRESS_IO_SPACE) {
  1638. m = i & ~0x3;
  1639. Descriptor->u.Port.MinimumAddress.LowPart = m;
  1640. } else {
  1641. m = i & ~0xf;
  1642. Descriptor->u.Memory.MinimumAddress.LowPart = m;
  1643. }
  1644. m += length; // max address is min address + length
  1645. }
  1646. //
  1647. // Add requested resource
  1648. //
  1649. Descriptor->Option = 0;
  1650. if (i & PCI_ADDRESS_IO_SPACE) {
  1651. memtype = 0;
  1652. #if 0 // H002
  1653. if (!Is64BitBaseAddress(i) &&
  1654. PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
  1655. //
  1656. // The IO range is/was already enabled at some location, add that
  1657. // as it's preferred setting.
  1658. //
  1659. Descriptor->Type = CmResourceTypePort;
  1660. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1661. Descriptor->Flags = CM_RESOURCE_PORT_IO;
  1662. Descriptor->Option = IO_RESOURCE_PREFERRED;
  1663. Descriptor->u.Port.Length = length;
  1664. Descriptor->u.Port.Alignment = length;
  1665. Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
  1666. Descriptor->u.Port.MaximumAddress.LowPart =
  1667. Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
  1668. CompleteList->List[0].Count++;
  1669. Descriptor++;
  1670. Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
  1671. }
  1672. #endif
  1673. //
  1674. // Add this IO range
  1675. //
  1676. Descriptor->Type = CmResourceTypePort;
  1677. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1678. Descriptor->Flags = CM_RESOURCE_PORT_IO;
  1679. Descriptor->u.Port.Length = length;
  1680. Descriptor->u.Port.Alignment = length;
  1681. Descriptor->u.Port.MaximumAddress.LowPart = m;
  1682. #if DBG // H001
  1683. DbgPrint("HalpAssign: Port %x len %x align %x\n", length, length, m);
  1684. #endif // DBG
  1685. } else {
  1686. memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
  1687. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  1688. if (j == RomIndex) {
  1689. // this is a ROM address
  1690. Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
  1691. }
  1692. if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
  1693. Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
  1694. }
  1695. #if 0 // H002
  1696. if (!Is64BitBaseAddress(i) &&
  1697. (j == RomIndex ||
  1698. PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
  1699. //
  1700. // The memory range is/was already enabled at some location, add that
  1701. // as it's preferred setting.
  1702. //
  1703. Descriptor->Type = CmResourceTypeMemory;
  1704. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1705. Descriptor->Option = IO_RESOURCE_PREFERRED;
  1706. Descriptor->u.Port.Length = length;
  1707. Descriptor->u.Port.Alignment = length;
  1708. Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
  1709. Descriptor->u.Port.MaximumAddress.LowPart =
  1710. Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
  1711. CompleteList->List[0].Count++;
  1712. Descriptor++;
  1713. Descriptor->Flags = Descriptor[-1].Flags;
  1714. Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
  1715. }
  1716. #endif
  1717. //
  1718. // Add this memory range
  1719. //
  1720. Descriptor->Type = CmResourceTypeMemory;
  1721. Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
  1722. Descriptor->u.Memory.Length = length;
  1723. Descriptor->u.Memory.Alignment = length;
  1724. Descriptor->u.Memory.MaximumAddress.LowPart = m;
  1725. if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
  1726. // limit to 20 bit address
  1727. Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
  1728. }
  1729. #if DBG // H001
  1730. DbgPrint("HalpAssign: Memory %x len %x align %x\n", length, length, m);
  1731. #endif // DBG
  1732. }
  1733. CompleteList->List[0].Count++;
  1734. Descriptor++;
  1735. if (Is64BitBaseAddress(i)) {
  1736. // skip upper half of 64 bit address since this processor
  1737. // only supports 32 bits of address space
  1738. j++;
  1739. }
  1740. }
  1741. }
  1742. CompleteList->ListSize = (ULONG)
  1743. ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
  1744. //
  1745. // Restore the device settings as we found them, enable memory
  1746. // and io decode after setting base addresses. This is done in
  1747. // case HalAdjustResourceList wants to read the current settings
  1748. // in the device.
  1749. //
  1750. HalpWritePCIConfig (
  1751. BusHandler,
  1752. PciSlot,
  1753. &PciOrigData->Status,
  1754. FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
  1755. PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
  1756. );
  1757. HalpWritePCIConfig (
  1758. BusHandler,
  1759. PciSlot,
  1760. PciOrigData,
  1761. 0,
  1762. FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
  1763. );
  1764. //
  1765. // Have the IO system allocate resource assignments
  1766. //
  1767. #if DBG // H001
  1768. DbgPrint("Call IoAssignResources\n");
  1769. #endif // DBG
  1770. status = IoAssignResources (
  1771. RegistryPath,
  1772. DriverClassName,
  1773. DriverObject,
  1774. DeviceObject,
  1775. CompleteList,
  1776. pAllocatedResources
  1777. );
  1778. if (!NT_SUCCESS(status)) {
  1779. goto CleanUp;
  1780. }
  1781. //
  1782. // Slurp the assigments back into the PciData structure and
  1783. // perform them
  1784. //
  1785. CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
  1786. //
  1787. // If PCI device has an interrupt resource then that was
  1788. // passed in as the first requested resource
  1789. //
  1790. if (PciData->u.type0.InterruptPin) {
  1791. PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
  1792. BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
  1793. CmDescriptor++;
  1794. }
  1795. //
  1796. // Pull out resources in the order they were passed to IoAssignResources
  1797. //
  1798. for (j=0; j < NoBaseAddress; j++) {
  1799. i = *BaseAddress[j];
  1800. if (i) {
  1801. if (i & PCI_ADDRESS_IO_SPACE) {
  1802. *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
  1803. #if DBG // H001
  1804. DbgPrint("HalpAssign assigned: Port %x\n", *BaseAddress[j]);
  1805. #endif // DBG
  1806. } else {
  1807. *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
  1808. #if DBG // H001
  1809. DbgPrint("HalpAssign assigned: Memory %x\n", *BaseAddress[j]);
  1810. #endif // DBG
  1811. }
  1812. CmDescriptor++;
  1813. }
  1814. if (Is64BitBaseAddress(i)) {
  1815. // skip upper 32 bits
  1816. j++;
  1817. }
  1818. }
  1819. //
  1820. // Turn off decodes, then set new addresses
  1821. //
  1822. #if DBG // H001
  1823. DbgPrint("Set Assigned Resources\n");
  1824. #endif // DBG
  1825. HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
  1826. //
  1827. // Read configuration back and verify address settings took
  1828. //
  1829. #if DBG // H001
  1830. DbgPrint("Read Common header to see write results\n");
  1831. #endif // DBG
  1832. HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
  1833. Match = TRUE;
  1834. if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
  1835. PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
  1836. PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
  1837. Match = FALSE;
  1838. }
  1839. for (j=0; j < NoBaseAddress; j++) {
  1840. if (*BaseAddress[j]) {
  1841. if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
  1842. i = (ULONG) ~0x3;
  1843. } else {
  1844. i = (ULONG) ~0xF;
  1845. }
  1846. if ((*BaseAddress[j] & i) !=
  1847. *((PULONG) ((PUCHAR) BaseAddress[j] -
  1848. (PUCHAR) PciData +
  1849. (PUCHAR) PciData2)) & i) {
  1850. Match = FALSE;
  1851. }
  1852. if (Is64BitBaseAddress(*BaseAddress[j])) {
  1853. // skip upper 32 bits
  1854. j++;
  1855. }
  1856. }
  1857. }
  1858. if (!Match) {
  1859. #if DBG
  1860. DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
  1861. BusNumber,
  1862. PciSlot.u.bits.DeviceNumber,
  1863. PciSlot.u.bits.FunctionNumber
  1864. );
  1865. #endif
  1866. status = STATUS_DEVICE_PROTOCOL_ERROR;
  1867. goto CleanUp;
  1868. }
  1869. //
  1870. // H004
  1871. // set memory space as back-to-back available
  1872. //
  1873. HalpSetBackToBackSpace(&PciData3, PciData2, BusHandler);
  1874. //
  1875. // Settings took - turn on the appropiate decodes
  1876. //
  1877. if (EnableRomBase && *BaseAddress[RomIndex]) {
  1878. // a rom address was allocated and should be enabled
  1879. *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
  1880. HalpWritePCIConfig (
  1881. BusHandler,
  1882. PciSlot,
  1883. BaseAddress[RomIndex],
  1884. (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
  1885. sizeof (ULONG)
  1886. );
  1887. }
  1888. //
  1889. // Enable IO, Memory, and BUS_MASTER decodes
  1890. // (use HalSetBusData since valid settings now set)
  1891. //
  1892. PciData->Command |= PCI_ENABLE_IO_SPACE |
  1893. PCI_ENABLE_MEMORY_SPACE |
  1894. PCI_ENABLE_BUS_MASTER;
  1895. HalSetBusDataByOffset (
  1896. PCIConfiguration,
  1897. BusHandler->BusNumber,
  1898. PciSlot.u.AsULONG,
  1899. &PciData->Command,
  1900. FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
  1901. sizeof (PciData->Command)
  1902. );
  1903. CleanUp:
  1904. if (!NT_SUCCESS(status)) {
  1905. //
  1906. // Failure, if there are any allocated resources free them
  1907. //
  1908. if (*pAllocatedResources) {
  1909. IoAssignResources (
  1910. RegistryPath,
  1911. DriverClassName,
  1912. DriverObject,
  1913. DeviceObject,
  1914. NULL,
  1915. NULL
  1916. );
  1917. ExFreePool (*pAllocatedResources);
  1918. *pAllocatedResources = NULL;
  1919. }
  1920. //
  1921. // Restore the device settings as we found them, enable memory
  1922. // and io decode after setting base addresses
  1923. //
  1924. HalpWritePCIConfig (
  1925. BusHandler,
  1926. PciSlot,
  1927. &PciOrigData->Status,
  1928. FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
  1929. PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
  1930. );
  1931. HalpWritePCIConfig (
  1932. BusHandler,
  1933. PciSlot,
  1934. PciOrigData,
  1935. 0,
  1936. FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
  1937. );
  1938. }
  1939. ExFreePool (WorkingPool);
  1940. return status;
  1941. }
  1942. #if DBG
  1943. VOID
  1944. HalpTestPci (ULONG flag2)
  1945. {
  1946. PCI_SLOT_NUMBER SlotNumber;
  1947. PCI_COMMON_CONFIG PciData, OrigData;
  1948. ULONG i, f, j, k, bus;
  1949. BOOLEAN flag;
  1950. if (!flag2) {
  1951. return ;
  1952. }
  1953. DbgBreakPoint ();
  1954. SlotNumber.u.bits.Reserved = 0;
  1955. //
  1956. // Read every possible PCI Device/Function and display it's
  1957. // default info.
  1958. //
  1959. // (note this destories it's current settings)
  1960. //
  1961. flag = TRUE;
  1962. for (bus = 0; flag; bus++) {
  1963. for (i = 0; i < PCI_MAX_DEVICES; i++) {
  1964. SlotNumber.u.bits.DeviceNumber = i;
  1965. for (f = 0; f < PCI_MAX_FUNCTION; f++) {
  1966. SlotNumber.u.bits.FunctionNumber = f;
  1967. //
  1968. // Note: This is reading the DeviceSpecific area of
  1969. // the device's configuration - normally this should
  1970. // only be done on device for which the caller understands.
  1971. // I'm doing it here only for debugging.
  1972. //
  1973. j = HalGetBusData (
  1974. PCIConfiguration,
  1975. bus,
  1976. SlotNumber.u.AsULONG,
  1977. &PciData,
  1978. sizeof (PciData)
  1979. );
  1980. if (j == 0) {
  1981. // out of buses
  1982. flag = FALSE;
  1983. break;
  1984. }
  1985. if (j < PCI_COMMON_HDR_LENGTH) {
  1986. continue;
  1987. }
  1988. HalSetBusData (
  1989. PCIConfiguration,
  1990. bus,
  1991. SlotNumber.u.AsULONG,
  1992. &PciData,
  1993. 1
  1994. );
  1995. HalGetBusData (
  1996. PCIConfiguration,
  1997. bus,
  1998. SlotNumber.u.AsULONG,
  1999. &PciData,
  2000. sizeof (PciData)
  2001. );
  2002. #if 0
  2003. memcpy (&OrigData, &PciData, sizeof PciData);
  2004. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  2005. PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
  2006. }
  2007. PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
  2008. HalSetBusData (
  2009. PCIConfiguration,
  2010. bus,
  2011. SlotNumber.u.AsULONG,
  2012. &PciData,
  2013. sizeof (PciData)
  2014. );
  2015. HalGetBusData (
  2016. PCIConfiguration,
  2017. bus,
  2018. SlotNumber.u.AsULONG,
  2019. &PciData,
  2020. sizeof (PciData)
  2021. );
  2022. #endif
  2023. DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
  2024. bus, i, f, PciData.VendorID, PciData.DeviceID,
  2025. PciData.RevisionID);
  2026. if (PciData.u.type0.InterruptPin) {
  2027. DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
  2028. }
  2029. if (PciData.u.type0.InterruptLine) {
  2030. DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
  2031. }
  2032. if (PciData.u.type0.ROMBaseAddress) {
  2033. DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
  2034. }
  2035. DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
  2036. PciData.Command, PciData.Status, PciData.ProgIf,
  2037. PciData.SubClass, PciData.BaseClass);
  2038. k = 0;
  2039. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  2040. if (PciData.u.type0.BaseAddresses[j]) {
  2041. DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
  2042. k = 1;
  2043. }
  2044. }
  2045. #if 0
  2046. if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
  2047. PciData.u.type0.ROMBaseAddress = 0xC00001;
  2048. HalSetBusData (
  2049. PCIConfiguration,
  2050. bus,
  2051. SlotNumber.u.AsULONG,
  2052. &PciData,
  2053. sizeof (PciData)
  2054. );
  2055. HalGetBusData (
  2056. PCIConfiguration,
  2057. bus,
  2058. SlotNumber.u.AsULONG,
  2059. &PciData,
  2060. sizeof (PciData)
  2061. );
  2062. DbgPrint ("\n Bogus rom address, edit yields:%08lx",
  2063. PciData.u.type0.ROMBaseAddress);
  2064. }
  2065. #endif
  2066. if (k) {
  2067. DbgPrint ("\n");
  2068. }
  2069. if (PciData.VendorID == 0x8086) {
  2070. // dump complete buffer
  2071. DbgPrint ("Command %x, Status %x, BIST %x\n",
  2072. PciData.Command, PciData.Status,
  2073. PciData.BIST
  2074. );
  2075. DbgPrint ("CacheLineSz %x, LatencyTimer %x",
  2076. PciData.CacheLineSize, PciData.LatencyTimer
  2077. );
  2078. for (j=0; j < 192; j++) {
  2079. if ((j & 0xf) == 0) {
  2080. DbgPrint ("\n%02x: ", j + 0x40);
  2081. }
  2082. DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
  2083. }
  2084. DbgPrint ("\n");
  2085. }
  2086. #if 0
  2087. //
  2088. // now print original data
  2089. //
  2090. if (OrigData.u.type0.ROMBaseAddress) {
  2091. DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
  2092. }
  2093. DbgPrint ("\n");
  2094. k = 0;
  2095. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  2096. if (OrigData.u.type0.BaseAddresses[j]) {
  2097. DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
  2098. k = 1;
  2099. }
  2100. }
  2101. //
  2102. // Restore original settings
  2103. //
  2104. HalSetBusData (
  2105. PCIConfiguration,
  2106. bus,
  2107. SlotNumber.u.AsULONG,
  2108. &OrigData,
  2109. sizeof (PciData)
  2110. );
  2111. #endif
  2112. //
  2113. // Next
  2114. //
  2115. if (k) {
  2116. DbgPrint ("\n\n");
  2117. }
  2118. }
  2119. }
  2120. }
  2121. DbgBreakPoint ();
  2122. }
  2123. #if defined (_R94A_) // H001
  2124. VOID
  2125. HalpTestPciNec (ULONG flag2)
  2126. {
  2127. PCI_SLOT_NUMBER SlotNumber;
  2128. PCI_COMMON_CONFIG PciData, OrigData;
  2129. ULONG i, f, j, k, bus;
  2130. BOOLEAN flag;
  2131. if (!flag2) {
  2132. return ;
  2133. }
  2134. DbgBreakPoint ();
  2135. SlotNumber.u.bits.Reserved = 0;
  2136. //
  2137. // Read every possible PCI Device/Function and display it's
  2138. // default info.
  2139. //
  2140. // (note this destories it's current settings)
  2141. //
  2142. flag = TRUE;
  2143. for (bus = 0; flag && bus < 1; bus++) { /* R94A_ Support Only 1 */
  2144. for (i = 0; i < PCI_MAX_DEVICES; i++) { /* R94A_ Support Only 2 slots(include bridge) */
  2145. SlotNumber.u.bits.DeviceNumber = i;
  2146. for (f = 0; f < 8; f++) {
  2147. SlotNumber.u.bits.FunctionNumber = f;
  2148. DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
  2149. j = HalGetBusData (
  2150. PCIConfiguration,
  2151. bus,
  2152. SlotNumber.u.AsULONG,
  2153. &PciData,
  2154. sizeof (PciData)
  2155. );
  2156. HalpTestPciPrintResult((PULONG)&PciData, j);
  2157. if (j == 0) {
  2158. // out of buses
  2159. flag = FALSE;
  2160. break;
  2161. }
  2162. if (j < PCI_COMMON_HDR_LENGTH) {
  2163. continue;
  2164. }
  2165. DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f);
  2166. HalSetBusData (
  2167. PCIConfiguration,
  2168. bus,
  2169. SlotNumber.u.AsULONG,
  2170. &PciData,
  2171. 1
  2172. );
  2173. HalpTestPciPrintResult((PULONG)&PciData, 1);
  2174. DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
  2175. HalGetBusData (
  2176. PCIConfiguration,
  2177. bus,
  2178. SlotNumber.u.AsULONG,
  2179. &PciData,
  2180. sizeof (PciData)
  2181. );
  2182. HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
  2183. memcpy (&OrigData, &PciData, sizeof PciData);
  2184. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  2185. PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
  2186. }
  2187. PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
  2188. PciData.u.type0.InterruptLine = 5; // For trial
  2189. DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f);
  2190. HalSetBusData (
  2191. PCIConfiguration,
  2192. bus,
  2193. SlotNumber.u.AsULONG,
  2194. &PciData,
  2195. PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
  2196. );
  2197. HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
  2198. DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
  2199. HalGetBusData (
  2200. PCIConfiguration,
  2201. bus,
  2202. SlotNumber.u.AsULONG,
  2203. &PciData,
  2204. sizeof (PciData)
  2205. );
  2206. HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
  2207. DbgPrint ("--------------->>> Now Print the Slot Information\n");
  2208. DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
  2209. bus, i, f, PciData.VendorID, PciData.DeviceID,
  2210. PciData.RevisionID);
  2211. if (PciData.u.type0.InterruptPin) {
  2212. DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
  2213. }
  2214. if (PciData.u.type0.InterruptLine) {
  2215. DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
  2216. }
  2217. if (PciData.u.type0.ROMBaseAddress) {
  2218. DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
  2219. }
  2220. DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
  2221. PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
  2222. k = 0;
  2223. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  2224. if (PciData.u.type0.BaseAddresses[j]) {
  2225. DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
  2226. k = 1;
  2227. }
  2228. }
  2229. if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
  2230. PciData.u.type0.ROMBaseAddress = 0xC00001;
  2231. HalSetBusData (
  2232. PCIConfiguration,
  2233. bus,
  2234. SlotNumber.u.AsULONG,
  2235. &PciData,
  2236. sizeof (PciData)
  2237. );
  2238. HalGetBusData (
  2239. PCIConfiguration,
  2240. bus,
  2241. SlotNumber.u.AsULONG,
  2242. &PciData,
  2243. sizeof (PciData)
  2244. );
  2245. DbgPrint ("\n Bogus rom address, edit yields:%08lx",
  2246. PciData.u.type0.ROMBaseAddress);
  2247. }
  2248. if (k) {
  2249. DbgPrint ("\n");
  2250. }
  2251. if (PciData.VendorID == 0x8086) {
  2252. // dump complete buffer
  2253. DbgPrint ("We got the bridge\n");
  2254. DbgPrint ("Command %x, Status %x, BIST %x\n",
  2255. PciData.Command, PciData.Status,
  2256. PciData.BIST
  2257. );
  2258. DbgPrint ("CacheLineSz %x, LatencyTimer %x",
  2259. PciData.CacheLineSize, PciData.LatencyTimer
  2260. );
  2261. for (j=0; j < 192; j++) {
  2262. if ((j & 0xf) == 0) {
  2263. DbgPrint ("\n%02x: ", j + 0x40);
  2264. }
  2265. DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
  2266. }
  2267. DbgPrint ("\n");
  2268. }
  2269. //
  2270. // now print original data
  2271. //
  2272. DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
  2273. if (OrigData.u.type0.ROMBaseAddress) {
  2274. DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
  2275. }
  2276. DbgPrint ("\n");
  2277. k = 0;
  2278. for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
  2279. if (OrigData.u.type0.BaseAddresses[j]) {
  2280. DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
  2281. k = 1;
  2282. }
  2283. }
  2284. //
  2285. // Restore original settings
  2286. //
  2287. DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
  2288. HalSetBusData (
  2289. PCIConfiguration,
  2290. bus,
  2291. SlotNumber.u.AsULONG,
  2292. &OrigData,
  2293. sizeof (PciData)
  2294. );
  2295. HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
  2296. //
  2297. // Next
  2298. //
  2299. if (k) {
  2300. DbgPrint ("\n\n");
  2301. }
  2302. }
  2303. }
  2304. }
  2305. DbgBreakPoint ();
  2306. }
  2307. VOID
  2308. HalpTestPciPrintResult(
  2309. IN PULONG Buffer,
  2310. IN ULONG Length
  2311. )
  2312. {
  2313. ULONG i, Lines, pchar;
  2314. DbgPrint("----- I/O Data. (%d)byts.\n", Length);
  2315. for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
  2316. DbgPrint("%08x: ", Lines * 16);
  2317. for (i = 0; i < 4; pchar += 4, i++) {
  2318. if (pchar >= Length)
  2319. break;
  2320. DbgPrint("%08x ", *Buffer++);
  2321. }
  2322. DbgPrint("\n");
  2323. }
  2324. }
  2325. VOID
  2326. HalpOtherTestNec (
  2327. IN ULONG doOtherTest
  2328. )
  2329. {
  2330. if (!doOtherTest)
  2331. return;
  2332. DbgPrint("\n\n===== Additional Testing...\n");
  2333. {
  2334. CM_EISA_SLOT_INFORMATION EisaSlotInfo;
  2335. PCM_EISA_SLOT_INFORMATION EisaBuffer;
  2336. PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo;
  2337. ULONG slot, funcs, Length;
  2338. #define MAX_EISA_SLOT 4
  2339. DbgPrint("----- Read Eisa Configration:\n");
  2340. for (slot = 0; slot < MAX_EISA_SLOT; slot++) {
  2341. Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo));
  2342. if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) {
  2343. //
  2344. // The data is messed up since this should never occur
  2345. //
  2346. break;
  2347. }
  2348. Length = sizeof(CM_EISA_SLOT_INFORMATION) +
  2349. (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions);
  2350. EisaBuffer = ExAllocatePool(NonPagedPool, Length);
  2351. HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length);
  2352. // Print all Eisa Data
  2353. EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION)
  2354. ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION));
  2355. DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot);
  2356. DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n",
  2357. EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags,
  2358. EisaBuffer->MajorRevision, EisaBuffer->MinorRevision);
  2359. DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n",
  2360. EisaBuffer->Checksum,
  2361. EisaBuffer->NumberFunctions,
  2362. EisaBuffer->FunctionInformation,
  2363. EisaBuffer->CompressedId);
  2364. for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) {
  2365. DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n",
  2366. EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1,
  2367. EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision,
  2368. EisaFunctionInfo->MajorRevision);
  2369. // EisaFunctionInfo->Selections[26];
  2370. // EisaFunctionInfo->FunctionFlags;
  2371. // EisaFunctionInfo->TypeString[80];
  2372. // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9];
  2373. // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7];
  2374. // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4];
  2375. // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20];
  2376. // UCHAR EisaFunctionInfo->InitializationData[60];
  2377. EisaFunctionInfo++;
  2378. }
  2379. }
  2380. }
  2381. DbgBreakPoint ();
  2382. {
  2383. #define MEMORY_SPACE 0
  2384. #define IO_SPACE 1
  2385. PHYSICAL_ADDRESS cardAddress;
  2386. ULONG addressSpace = IO_SPACE;
  2387. PHYSICAL_ADDRESS PhysAddr;
  2388. PhysAddr.LowPart = 0;
  2389. PhysAddr.HighPart = 0;
  2390. DbgPrint("----- Translate Internal Bus Address(I/O): ");
  2391. HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2392. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2393. DbgPrint("Translate Eisa Bus Address(I/O): ");
  2394. addressSpace = IO_SPACE;
  2395. HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2396. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2397. DbgPrint("Translate Isa Bus Address(I/O): ");
  2398. addressSpace = IO_SPACE;
  2399. HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2400. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2401. DbgPrint("Translate PCI Bus Address(I/O): ");
  2402. addressSpace = IO_SPACE;
  2403. HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2404. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2405. DbgPrint("Translate Internal Bus Address(MEMORY): ");
  2406. addressSpace = MEMORY_SPACE;
  2407. HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2408. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2409. DbgPrint("Translate Eisa Bus Address(MEMORY): ");
  2410. addressSpace = MEMORY_SPACE;
  2411. HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2412. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2413. DbgPrint("Translate Isa Bus Address(MEMORY): ");
  2414. addressSpace = MEMORY_SPACE;
  2415. HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2416. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2417. DbgPrint("Translate PCI Bus Address(MEMORY): ");
  2418. addressSpace = MEMORY_SPACE;
  2419. HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
  2420. DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
  2421. }
  2422. DbgBreakPoint ();
  2423. {
  2424. KAFFINITY affinity;
  2425. KIRQL Irql;
  2426. ULONG Vec;
  2427. DbgPrint("----- GetInterruptVector internal\n");
  2428. Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity);
  2429. DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
  2430. DbgPrint("GetInterruptVector Eisa\n");
  2431. Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity);
  2432. DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
  2433. DbgPrint("GetInterruptVector Isa\n");
  2434. Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity);
  2435. DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
  2436. DbgPrint("GetInterruptVector PCI\n");
  2437. Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity);
  2438. DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
  2439. }
  2440. DbgBreakPoint ();
  2441. }
  2442. #endif // _R94A_
  2443. #endif // DBG
  2444. VOID
  2445. HalpSetBackToBackSpace(
  2446. IN PPCI_COMMON_CONFIG PciConfigRequired,
  2447. IN PPCI_COMMON_CONFIG PciConfigMapped,
  2448. IN PBUS_HANDLER BusHandler
  2449. )
  2450. /*++
  2451. Routine Description:
  2452. This function sets memory space of PCI device to Fast Back-to-back register.
  2453. Arguments:
  2454. PciConfigRequired - Supplies the description of the memory space which
  2455. device required.
  2456. PciConfigMapped - Supplies the description of the memory space which
  2457. should be mapped to back-to-back space.
  2458. BusHandler - Supplies the pointer to Bushandler.
  2459. Return Value:
  2460. None.
  2461. --*/
  2462. {
  2463. ULONG NoBaseAddress;
  2464. ULONG BaseAddress, LowerAddress;
  2465. ULONG CurrentAddress;
  2466. ULONG FoundMemoryAddress;
  2467. ULONG i, j, Length;
  2468. #if DBG
  2469. DbgPrint(" check PCI-device!\n");
  2470. DbgPrint(" - VendorID ................ %04x\n", PciConfigMapped->VendorID);
  2471. DbgPrint(" - DeviceID ................ %04x\n", PciConfigMapped->DeviceID);
  2472. DbgPrint(" - back-to-back capable? ... %s\n", (PciConfigMapped->Status & 0x80) ? "o" : "x");
  2473. if (PciConfigMapped->BaseClass == 0x03
  2474. || (PciConfigMapped->BaseClass == 0x00 && PciConfigMapped->SubClass == 0x01)){
  2475. DbgPrint(" - Is this GA device? ...... o\n");
  2476. } else {
  2477. DbgPrint(" - Is this GA device? ...... x\n");
  2478. }
  2479. #endif
  2480. KiAcquireSpinLock(&HalpPCIBackToBackLock);
  2481. //
  2482. // calulate memory region of this device.
  2483. //
  2484. switch (PCI_CONFIG_TYPE(PciConfigMapped)) {
  2485. case 0 :
  2486. NoBaseAddress = PCI_TYPE0_ADDRESSES;
  2487. break;
  2488. case 1:
  2489. NoBaseAddress = PCI_TYPE1_ADDRESSES;
  2490. break;
  2491. default:
  2492. // never come here.
  2493. // (already except by HalpAssignPCISlotResources)
  2494. return;
  2495. }
  2496. Length = 0;
  2497. BaseAddress = 0xffffffff;
  2498. LowerAddress = 0xffffffff;
  2499. FoundMemoryAddress = 0;
  2500. //
  2501. // get base and limit address
  2502. //
  2503. for (i = 0; i < NoBaseAddress; i++) {
  2504. CurrentAddress = PciConfigMapped->u.type0.BaseAddresses[i];
  2505. if (!(CurrentAddress & PCI_ADDRESS_IO_SPACE)
  2506. && ((CurrentAddress & PCI_ADDRESS_MEMORY_TYPE_MASK) != 0x2)) {
  2507. //
  2508. // this is memory space and not need to map below 1M
  2509. //
  2510. CurrentAddress = CurrentAddress & 0xfffffff0;
  2511. if (CurrentAddress) {
  2512. FoundMemoryAddress = 1;
  2513. if (LowerAddress > CurrentAddress)
  2514. LowerAddress = CurrentAddress;
  2515. // scan for first set bit, that's the length & alignment
  2516. j = 1 << 4;
  2517. while (!(PciConfigRequired->u.type0.BaseAddresses[i] & j) && j)
  2518. j <<= 1;
  2519. #if DBG
  2520. DbgPrint(" - [%d]MemoryAddress ........ 0x%08x\n", i, CurrentAddress);
  2521. DbgPrint(" - [%d]Length ............... 0x%08x\n", i, j);
  2522. #endif
  2523. if (Length < j){
  2524. BaseAddress = CurrentAddress;
  2525. Length = j;
  2526. }
  2527. }
  2528. }
  2529. }
  2530. #if DBG
  2531. DbgPrint(" - LowerAddress ............ 0x%08x\n", LowerAddress);
  2532. DbgPrint(" - BaseAddress ............. 0x%08x\n", BaseAddress);
  2533. DbgPrint(" - Length .................. 0x%08x\n", Length);
  2534. #endif
  2535. //
  2536. // If this device has memory space, then change memory limit
  2537. // value used be allocation for PCI memory space to
  2538. // 'LowerAddress - 1' of this device, otherwise release spinlock
  2539. // and return.
  2540. //
  2541. if (FoundMemoryAddress) {
  2542. HalpPCIMemoryLimit = LowerAddress - 1;
  2543. } else {
  2544. goto NotSetBackToBack;
  2545. }
  2546. //
  2547. // We do not support the PCI devices which connected under
  2548. // PCI-PCI bridge.
  2549. //
  2550. if (BusHandler->BusNumber == 0) {
  2551. if (PciConfigMapped->Status & 0x80) {
  2552. //
  2553. // This device is back-to-back capable.
  2554. // We can map the memory space of this device as
  2555. // back-to-back available.
  2556. // Set flag to indicate setting started.
  2557. //
  2558. if (!HalpPCIBackToBackReg0Start) {
  2559. HalpPCIBackToBackReg0Start = 1;
  2560. } else if (HalpPCIBackToBackReg0Start && !HalpPCIBackToBackReg0Open) {
  2561. HalpPCIBackToBackReg1Start = 1;
  2562. }
  2563. //
  2564. // BUGBUG: Some pci drivers assign its memory space by itself.
  2565. // This means that we can not control the memory address of
  2566. // such device by MemoryLimit value. So, we can not enable the
  2567. // following codes now.
  2568. // N.B. following code does not finished.
  2569. //
  2570. // if (!HalpFoundUncapablePCIDevice) {
  2571. //
  2572. // //
  2573. // // Uncapable device not mapped yet, so we can expand
  2574. // // back-to-back space.
  2575. // // We expand back-to-back space until uncapable device
  2576. // // is found.
  2577. // //
  2578. //
  2579. // if (back-to-back reg0 == initialize value){
  2580. // HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
  2581. // } else {
  2582. // back-to-back reg0 =+ add this memory range;
  2583. // MemoryLimit = the BaseAddress of this device;
  2584. // }
  2585. //
  2586. // if (PciConfigMapped->BaseClass == 0x03
  2587. // || (PciConfigMapped->BaseClass == 0x00
  2588. // && PciConfigMapped->SubClass == 0x01)) {
  2589. // HalpPCINumberOfMappedGA++;
  2590. // }
  2591. //
  2592. // } else {
  2593. if (HalpNumberOfPCIGA > 1) {
  2594. //
  2595. // There are some PCI-GA cards.
  2596. // If this is PCI-GA, then set to back-to-back,
  2597. // else we do not map.
  2598. //
  2599. if (PciConfigMapped->BaseClass == 0x03
  2600. || (PciConfigMapped->BaseClass == 0x00
  2601. && PciConfigMapped->SubClass == 0x01)) {
  2602. switch (HalpPCINumberOfMappedGA) {
  2603. case 0:
  2604. //
  2605. // We need set PCI-GA to both back-to-back space.
  2606. // The control reach here, it indicates PCI-GA
  2607. // not mapped to back-to-back space yet.
  2608. //
  2609. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
  2610. HalpPCIBackToBackReg0Open = 0;
  2611. break;
  2612. case 1:
  2613. //
  2614. // Control is transfered to this routine when one PCI-GA
  2615. // is already mapped. This means that reg0 had already used.
  2616. // We use reg1.
  2617. //
  2618. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
  2619. HalpPCIBackToBackReg1Open = 0;
  2620. }
  2621. HalpPCINumberOfMappedGA++;
  2622. }
  2623. } else {
  2624. //
  2625. // There is only one-card as PCI-GA.
  2626. // We need set PCI-GA to back-to-back.
  2627. // If this is GA and reg0 is opened, then use reg0.
  2628. // If this is GA and reg0 is closeed, then use reg1.
  2629. //
  2630. if (PciConfigMapped->BaseClass == 0x03
  2631. || (PciConfigMapped->BaseClass == 0x00
  2632. && PciConfigMapped->SubClass == 0x01)) {
  2633. if (HalpPCIBackToBackReg0Open) {
  2634. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
  2635. HalpPCIBackToBackReg0Open = 0;
  2636. } else {
  2637. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
  2638. HalpPCIBackToBackReg1Open = 0;
  2639. }
  2640. HalpPCINumberOfMappedGA++;
  2641. } else {
  2642. //
  2643. // We can set only if reg0 or reg1 is not used.
  2644. //
  2645. if (HalpPCIBackToBackReg0Open) {
  2646. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
  2647. HalpPCIBackToBackReg0Open = 0;
  2648. } else if (HalpPCIBackToBackReg1Open){
  2649. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
  2650. HalpPCIBackToBackReg1Open = 0;
  2651. }
  2652. }
  2653. }
  2654. // }
  2655. } else {
  2656. //
  2657. // This is back-to-back uncapable.
  2658. //
  2659. HalpFoundUncapablePCIDevice = 1;
  2660. //
  2661. // if device is back-to-back uncapable��map only GA.
  2662. //
  2663. if (PciConfigMapped->BaseClass == 0x03
  2664. || (PciConfigMapped->BaseClass == 0x00
  2665. && PciConfigMapped->SubClass == 0x01)) {
  2666. //
  2667. // In case of two or more cards are connected, the
  2668. // process is depend on the number of PCI-GA which
  2669. // already mapped.
  2670. // But we do not need to map 3rd PCI-GA or more.
  2671. //
  2672. if (HalpNumberOfPCIGA > 1) {
  2673. switch (HalpPCINumberOfMappedGA) {
  2674. case 0:
  2675. //
  2676. // Re-nitialize all values to void already settings,
  2677. // and use reg0
  2678. //
  2679. HalpPCIBackToBackReg0Start = 1;
  2680. HalpPCIBackToBackReg1Start = 0;
  2681. HalpPCIBackToBackReg0Open = 1;
  2682. HalpPCIBackToBackReg1Open = 1;
  2683. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
  2684. break;
  2685. case 1:
  2686. //
  2687. // Control is transfered to this routine when one PCI-GA
  2688. // is already mapped. This means that reg0 had already used.
  2689. // We use reg1.
  2690. //
  2691. // N.B. We do not know reg0 is opened or closed, so close
  2692. // reg0 here.
  2693. // (ex) 1st mapped ... capable = 1, not GA
  2694. // 2nd mapped ... capable = 0, GA
  2695. //
  2696. HalpPCIBackToBackReg0Open = 0;
  2697. HalpPCIBackToBackReg1Start = 1;
  2698. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
  2699. }
  2700. } else {
  2701. //
  2702. // There is only one-card as PCI-GA.
  2703. // If back-to-back reg0 not being useed, use reg0,
  2704. // else close the space of reg0 and use reg1.
  2705. // (Also when reg0 is closed, use reg1)
  2706. //
  2707. if (!HalpPCIBackToBackReg0Start) {
  2708. HalpPCIBackToBackReg0Start = 1;
  2709. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
  2710. } else {
  2711. HalpPCIBackToBackReg0Open = 0;
  2712. HalpPCIBackToBackReg1Start = 1;
  2713. HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
  2714. }
  2715. }
  2716. }
  2717. //
  2718. // if being to set to back-to-back register, we have to close.
  2719. //
  2720. if (HalpPCIBackToBackReg0Start && HalpPCIBackToBackReg0Open) {
  2721. HalpPCIBackToBackReg0Open = 0;
  2722. } else if (HalpPCIBackToBackReg1Start && HalpPCIBackToBackReg1Open) {
  2723. HalpPCIBackToBackReg1Open = 0;
  2724. }
  2725. }
  2726. }
  2727. NotSetBackToBack:
  2728. KiReleaseSpinLock(&HalpPCIBackToBackLock);
  2729. }
  2730. VOID
  2731. HalpSetBackToBackRegister(
  2732. IN ULONG BaseAddress,
  2733. IN ULONG Length,
  2734. IN ULONG Register
  2735. )
  2736. /*++
  2737. Routine Description:
  2738. This function sets memory space of PCI device to Fast Back-to-back register.
  2739. Arguments:
  2740. BaseAddress - Supplies the address which to be mapped with back-to-back.
  2741. Length - Supplies the length which to be mapped with back-to-back.
  2742. Register - Supplies the back-to-back register number.
  2743. Return Value:
  2744. None.
  2745. --*/
  2746. {
  2747. ULONG Mask;
  2748. //
  2749. // make mask value
  2750. //
  2751. Mask = ~(Length - 1);
  2752. //
  2753. // set to back-to-back register
  2754. //
  2755. #if DBG
  2756. DbgPrint(" set back-to-back register.\n");
  2757. DbgPrint(" - Register ................ %d\n", Register);
  2758. DbgPrint(" - Address ................. 0x%08x\n", BaseAddress);
  2759. DbgPrint(" - Mask .................... 0x%08x\n", Mask);
  2760. #endif
  2761. WRITE_REGISTER_ULONG(
  2762. &DMA_CONTROL->PCIFastBackToBack[Register].Address,
  2763. BaseAddress
  2764. );
  2765. WRITE_REGISTER_ULONG(
  2766. &DMA_CONTROL->PCIFastBackToBack[Register].Mask,
  2767. Mask
  2768. );
  2769. }
  2770. ULONG
  2771. HalpGetNumberOfPCIGA(
  2772. IN ULONG NumberBuses
  2773. )
  2774. /*++
  2775. Routine Description:
  2776. This function determines the number of PCI-GAs.
  2777. And initialize Fast Back-to-back register.
  2778. Arguments:
  2779. NumberBuses - Supplies the number of the PCI-buses.
  2780. Return Value:
  2781. number of PCI-GA.
  2782. --*/
  2783. {
  2784. UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
  2785. ULONG Bus;
  2786. ULONG Slot;
  2787. ULONG Function;
  2788. PBUS_HANDLER BusHandler;
  2789. PCI_SLOT_NUMBER SlotNumber;
  2790. PPCI_COMMON_CONFIG PciData;
  2791. ULONG Count;
  2792. ULONG Register;
  2793. USHORT commandValue;
  2794. Count = 0;
  2795. PciData = (PPCI_COMMON_CONFIG)&iBuffer;
  2796. //
  2797. // BUGBUG: Fast Back-to-back transaction can be used
  2798. // only bus number zero on this version.
  2799. // PCI devices connected on bus number 1 or more will
  2800. // be available with back-to-back on future.
  2801. //
  2802. NumberBuses = 1;
  2803. //
  2804. // Look for PCI controllers which have known work-arounds, and make
  2805. // sure they are applied.
  2806. //
  2807. SlotNumber.u.bits.Reserved = 0;
  2808. for (Bus = 0; Bus < NumberBuses; Bus++) {
  2809. BusHandler = HalpHandlerForBus (PCIBus, Bus);
  2810. for (Slot = 0; Slot < PCI_MAX_DEVICES; Slot++) {
  2811. SlotNumber.u.bits.DeviceNumber = Slot;
  2812. for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
  2813. SlotNumber.u.bits.FunctionNumber = Function;
  2814. //
  2815. // Read PCI configuration information
  2816. //
  2817. HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
  2818. //
  2819. // Check for chips with known work-arounds to apply
  2820. //
  2821. if (PciData->BaseClass == 0x03
  2822. || (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01)){
  2823. //
  2824. // This is Graphics Adapter. Inclement count.
  2825. //
  2826. Count++;
  2827. }
  2828. } // next PCI function
  2829. } // next PCI slot
  2830. } // next PCI bus
  2831. #if DBG
  2832. DbgPrint(" number of PCI-GA.\n");
  2833. DbgPrint(" - number of PCI-GA ........ %d\n", Count);
  2834. #endif
  2835. //
  2836. // Initialize Fast Back-to-back register.
  2837. //
  2838. for (Register = 0; Register < 2; Register++) {
  2839. WRITE_REGISTER_ULONG(
  2840. &DMA_CONTROL->PCIFastBackToBack[Register].Address,
  2841. INIT_VALUE_OF_BACK_TO_BACK_ADDR
  2842. );
  2843. WRITE_REGISTER_ULONG(
  2844. &DMA_CONTROL->PCIFastBackToBack[Register].Mask,
  2845. INIT_VALUE_OF_BACK_TO_BACK_MASK
  2846. );
  2847. }
  2848. commandValue = READ_REGISTER_USHORT(&DMA_CONTROL->PCICommand);
  2849. WRITE_REGISTER_USHORT(&DMA_CONTROL->PCICommand, (commandValue & ~0x0200));
  2850. return Count;
  2851. }