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

1091 lines
32 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. pci.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Ken Reneris (kenr) 18-August-1997
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "pci.h"
  15. #pragma hdrstop
  16. #define DUMP_VERBOSE 0x01
  17. #define DUMP_TO_MAX_BUS 0x02 // from 0 to max
  18. #define DUMP_RAW_BYTES 0x04 // hex dump dump raw bytes
  19. #define DUMP_RAW_DWORDS 0x08 // hex dump dump raw dwords
  20. #define DUMP_ALLOW_INVALID_DEVICE 0x10
  21. #define DUMP_ALLOW_INVALID_FUNCTION 0x20
  22. #define DUMP_CAPABILITIES 0x40
  23. #define DUMP_INTEL 0x80
  24. #define DUMP_CONFIGSPACE 0x100
  25. #define ANY 0xFF
  26. PSZ GetClassDesc(BYTE bBaseClass, BYTE bSubClass, BYTE bProgIF);
  27. UCHAR PCIDeref[4][4] = { {4,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
  28. VOID
  29. DumpCfgSpace (
  30. IN PPCI_COMMON_CONFIG pcs
  31. );
  32. VOID
  33. HexDump (
  34. IN ULONG indent,
  35. IN ULONG va,
  36. IN ULONG len,
  37. IN ULONG width,
  38. IN PUCHAR buf
  39. )
  40. {
  41. UCHAR s[80], t[80];
  42. PUCHAR ps, pt;
  43. ULONG i;
  44. static UCHAR rgHexDigit[] = "0123456789abcdef";
  45. i = 0;
  46. //
  47. // If width = 4, dull dump, similar to debugger's dd command.
  48. //
  49. if (width == 4) {
  50. if (len & 3) {
  51. dprintf("hexdump internal error, dump dword, (len & 3) != 0\n");
  52. // round up.
  53. len += 3;
  54. len &= ~3;
  55. }
  56. while (len) {
  57. if (i == 0) {
  58. dprintf("%*s%08x: ", indent, "", va);
  59. va += 16;
  60. }
  61. dprintf(" %08x", *(ULONG UNALIGNED *)buf);
  62. len -= 4;
  63. buf += 4;
  64. if (i == 3) {
  65. dprintf("\n");
  66. i = 0;
  67. } else {
  68. i++;
  69. }
  70. }
  71. return;
  72. }
  73. if (width != 1) {
  74. dprintf ("hexdump internal error\n");
  75. return ;
  76. }
  77. //
  78. // Width = 1, pretty dump, similar to debugger's db command.
  79. //
  80. while (len) {
  81. ps = s;
  82. pt = t;
  83. ps[0] = 0;
  84. pt[0] = '*';
  85. pt++;
  86. for (i=0; i < 16; i++) {
  87. ps[0] = ' ';
  88. ps[1] = ' ';
  89. ps[2] = ' ';
  90. if (len) {
  91. ps[0] = rgHexDigit[buf[0] >> 4];
  92. ps[1] = rgHexDigit[buf[0] & 0xf];
  93. pt[0] = buf[0] < ' ' || buf[0] > 'z' ? '.' : buf[0];
  94. len -= 1;
  95. buf += 1;
  96. pt += 1;
  97. }
  98. ps += 3;
  99. }
  100. ps[0] = 0;
  101. pt[0] = '*';
  102. pt[1] = 0;
  103. s[23] = '-';
  104. if (s[0]) {
  105. dprintf ("%*s%08lx: %s %s\n", indent, "", va, s, t);
  106. va += 16;
  107. }
  108. }
  109. }
  110. BOOL
  111. ReadPci (
  112. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  113. OUT PUCHAR Buffer,
  114. IN ULONG Offset,
  115. IN ULONG Length
  116. )
  117. {
  118. ULONG InputSize;
  119. ULONG IoSize;
  120. ULONG i;
  121. BUSDATA busData;
  122. PCI_SLOT_NUMBER slot;
  123. BOOL b;
  124. //
  125. // Zap input buffer
  126. //
  127. for (i=0; i < Length; i++) {
  128. Buffer[i] = 0xff;
  129. }
  130. //
  131. // It appears that we are only safe to call the HAL for reading
  132. // configuration space if the HAL has actually been initialized far
  133. // enough to do so. Since we have already hit a case where we hadnt
  134. // initialized everything and it crashed the debugger, we are restoring
  135. // X86 so that it reads configspace the way it always used to do.
  136. //
  137. // For non-X86 (i.e IA64) we are forced to call the HAL because we
  138. // currently have no other option. This means we may still crash on
  139. // those platforms in the case where
  140. // the HAL hasnt been initialized enough to handle it.
  141. //
  142. if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
  143. while (Length) {
  144. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  145. IoSize = sizeof(ULONG);
  146. #ifdef IG_IO_SPACE_RETURN
  147. b =
  148. #else
  149. b = TRUE;
  150. #endif
  151. WriteIoSpace64 ( PCI_TYPE1_ADDR_PORT, PciCfg1->u.AsULONG, &IoSize );
  152. if (!b) {
  153. return FALSE;
  154. }
  155. IoSize = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
  156. i = IoSize;
  157. ReadIoSpace64 (
  158. PCI_TYPE1_DATA_PORT + (Offset % sizeof(ULONG)),
  159. (PULONG) Buffer,
  160. &i
  161. );
  162. Offset += IoSize;
  163. Buffer += IoSize;
  164. Length -= IoSize;
  165. }
  166. }else{
  167. //
  168. // Here we are going to call the debugger api that results in the
  169. // call to HalGetBusDataByOffset for the read.
  170. //
  171. // Note: This will crash the current debug session of attempted too
  172. // early in boot.
  173. //
  174. slot.u.AsULONG = 0;
  175. slot.u.bits.DeviceNumber = PciCfg1->u.bits.DeviceNumber;
  176. slot.u.bits.FunctionNumber = PciCfg1->u.bits.FunctionNumber;
  177. busData.BusDataType = PCIConfiguration;
  178. busData.BusNumber = PciCfg1->u.bits.BusNumber;
  179. busData.SlotNumber = slot.u.AsULONG;
  180. busData.Offset = Offset;
  181. busData.Buffer = Buffer;
  182. busData.Length = Length;
  183. //
  184. // Read it
  185. //
  186. #ifdef IG_IO_SPACE_RETURN
  187. b =
  188. #else
  189. b = TRUE;
  190. #endif
  191. Ioctl(IG_GET_BUS_DATA, &busData, sizeof(busData));
  192. if (!b) {
  193. return FALSE;
  194. }
  195. }
  196. return TRUE;
  197. }
  198. BOOLEAN
  199. WritePci (
  200. IN PPCI_TYPE1_CFG_BITS PciCfg1,
  201. IN PUCHAR Buffer,
  202. IN ULONG Offset,
  203. IN ULONG Length
  204. )
  205. {
  206. ULONG IoSize;
  207. ULONG i;
  208. BUSDATA busData;
  209. PCI_SLOT_NUMBER slot;
  210. if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
  211. //
  212. // For the same reasons as the read, we are only calling the HAL
  213. // on non-x86 targets for now.
  214. //
  215. while (Length) {
  216. PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
  217. IoSize = sizeof(ULONG);
  218. WriteIoSpace64 ((ULONG) PCI_TYPE1_ADDR_PORT, PciCfg1->u.AsULONG, &IoSize );
  219. IoSize = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
  220. i = IoSize;
  221. WriteIoSpace64 (
  222. PCI_TYPE1_DATA_PORT + (Offset % sizeof(ULONG)),
  223. *(PULONG)Buffer,
  224. &i);
  225. Offset += IoSize;
  226. Buffer += IoSize;
  227. Length -= IoSize;
  228. }
  229. }else{
  230. slot.u.AsULONG = 0;
  231. slot.u.bits.DeviceNumber = PciCfg1->u.bits.DeviceNumber;
  232. slot.u.bits.FunctionNumber = PciCfg1->u.bits.FunctionNumber;
  233. busData.BusDataType = PCIConfiguration;
  234. busData.BusNumber = PciCfg1->u.bits.BusNumber;
  235. busData.SlotNumber = slot.u.AsULONG;
  236. busData.Offset = Offset;
  237. busData.Buffer = Buffer;
  238. busData.Length = Length;
  239. //
  240. // Write it
  241. //
  242. if (!(Ioctl(IG_SET_BUS_DATA, &busData, sizeof(busData)))){
  243. return FALSE;
  244. }
  245. }
  246. return TRUE;
  247. }
  248. VOID
  249. DumpPciBar (
  250. IN ULONG barno,
  251. IN ULONG indent,
  252. IN ULONG bar,
  253. IN OUT PULONG state
  254. )
  255. {
  256. ULONG type, i;
  257. CHAR m[20], str[80];
  258. if (bar) {
  259. if (bar & 1) {
  260. sprintf (str, "IO[%d]:%x ", barno, bar);
  261. } else {
  262. type = (bar >> 1) & 0x3;
  263. if (bar & 8) {
  264. strcpy (m, "MPF");
  265. } else {
  266. strcpy (m, "MEM");
  267. }
  268. if (type == 0x01) {
  269. m[1] = '1'; // less then 1M
  270. }
  271. sprintf (str, "%s[%d]:%x ", m, barno, bar);
  272. if (type == 0x10) {
  273. dprintf ("warning - 64bit bar not decoded\n");
  274. *state = 0;
  275. }
  276. if (type == 0x11) {
  277. dprintf ("bar type is reserved\n");
  278. *state = 0;
  279. }
  280. }
  281. if (!*state) {
  282. dprintf ("%*s", indent, "");
  283. }
  284. i = strlen(str);
  285. dprintf("%s%*s", str, 17-i, "");
  286. *state += i;
  287. }
  288. }
  289. VOID
  290. DumpPciType2Bar(
  291. IN BOOLEAN barIsIo,
  292. IN BOOLEAN barIsBase,
  293. IN ULONG barno,
  294. IN ULONG indent,
  295. IN ULONG bar,
  296. IN OUT PULONG state
  297. )
  298. {
  299. ULONG i;
  300. CHAR str[80];
  301. if (bar) {
  302. if (barIsIo) {
  303. sprintf (str, "IO[%d].%s:%x ", barno, (barIsBase?"base":"limit"), bar);
  304. } else {
  305. sprintf (str, "MEM[%d].%s:%x ", barno, (barIsBase?"base":"limit"), bar);
  306. }
  307. if (!*state) {
  308. dprintf("%*s", indent, "");
  309. }
  310. i = strlen(str);
  311. dprintf("%s%*s", str, 17-i, "");
  312. *state += i;
  313. }
  314. }
  315. VOID
  316. DumpPciBarComplete(
  317. IN OUT PULONG state
  318. )
  319. {
  320. if (*state) {
  321. dprintf ("\n");
  322. *state = 0;
  323. }
  324. }
  325. VOID
  326. DumpCapabilities(
  327. IN UCHAR CapPtr,
  328. IN PPCI_TYPE1_CFG_BITS PciCfg1
  329. )
  330. {
  331. union _cap_buffer {
  332. PCI_CAPABILITIES_HEADER header;
  333. PCI_PM_CAPABILITY pm;
  334. PCI_AGP_CAPABILITY agp;
  335. } cap;
  336. PCHAR ts;
  337. ULONG t;
  338. do {
  339. if (CapPtr < PCI_COMMON_HDR_LENGTH) {
  340. dprintf(" Error: Capability pointer 0x%02x points to common header (invalid).\n",
  341. CapPtr
  342. );
  343. break;
  344. }
  345. if (CapPtr & 0x3) {
  346. dprintf(" Error: Capability pointer 0x%02x not DWORD aligned (invalid).\n",
  347. CapPtr
  348. );
  349. break;
  350. }
  351. ReadPci (
  352. PciCfg1,
  353. (PUCHAR)&cap,
  354. CapPtr,
  355. sizeof(cap.header)
  356. );
  357. switch (cap.header.CapabilityID) {
  358. case PCI_CAPABILITY_ID_POWER_MANAGEMENT:
  359. ReadPci (
  360. PciCfg1,
  361. (PUCHAR)&cap,
  362. CapPtr,
  363. sizeof(cap.pm)
  364. );
  365. t = cap.pm.PMC.AsUSHORT;
  366. dprintf(" Cap[%02x] ID %02x \n",
  367. CapPtr,
  368. cap.header.CapabilityID
  369. );
  370. dprintf(" PMC %04x (%s%s%s%s%s%s %s%s%s%s%s%sv%x)\n",
  371. t,
  372. t & 0xf800 ? "PME from D" : "<No PME>",
  373. t & 0x8000 ? "3C" : "",
  374. t & 0x4000 ? "3H" : "",
  375. t & 0x2000 ? "2" : "",
  376. t & 0x1000 ? "1" : "",
  377. t & 0x0800 ? "0" : "",
  378. t & 0x0600 ? "Supports D" : "",
  379. cap.pm.PMC.Capabilities.Support.D2 ? "2" : "",
  380. cap.pm.PMC.Capabilities.Support.D1 ? "1" : "",
  381. t & 0x0600 ? " " : "",
  382. cap.pm.PMC.Capabilities.DeviceSpecificInitialization ?
  383. "DSI " : "",
  384. cap.pm.PMC.Capabilities.PMEClock ? "PME needs Clock, " : "",
  385. cap.pm.PMC.Capabilities.Version
  386. );
  387. t &= 0x01d0;
  388. if (t) {
  389. dprintf(" WARNING PMC non-zero reserved fields %04x\n",
  390. t
  391. );
  392. }
  393. t = cap.pm.PMCSR.AsUSHORT;
  394. dprintf(" PMCSR %04x (PME_Status=%d PME_En=%d State=D%d%s)\n",
  395. t,
  396. cap.pm.PMCSR.ControlStatus.PMEStatus,
  397. cap.pm.PMCSR.ControlStatus.PMEEnable,
  398. cap.pm.PMCSR.ControlStatus.PowerState,
  399. cap.pm.PMCSR.ControlStatus.PowerState == 3 ?
  400. "hot" : ""
  401. );
  402. //
  403. // Here would be a good time to run
  404. // run down the data registers if
  405. // they exist.
  406. //
  407. break;
  408. case PCI_CAPABILITY_ID_AGP:
  409. ReadPci (
  410. PciCfg1,
  411. (PUCHAR)&cap,
  412. CapPtr,
  413. sizeof(cap.agp)
  414. );
  415. switch (cap.agp.AGPStatus.Rate) {
  416. case 1:
  417. ts = "1X";
  418. break;
  419. case 2:
  420. ts = "2X";
  421. break;
  422. case 3:
  423. ts = "1,2X";
  424. break;
  425. default:
  426. ts = "<inv>";
  427. break;
  428. }
  429. t = *(PULONG)&cap.agp.AGPStatus;
  430. dprintf(" Cap[%02x] ID %02x AGP mj/mn=%x/%x\n",
  431. CapPtr,
  432. cap.header.CapabilityID,
  433. cap.agp.Major,
  434. cap.agp.Minor
  435. );
  436. dprintf(" Status %08x (Rq:%02x SBA:%x Rate:%x (%s))\n",
  437. t,
  438. cap.agp.AGPStatus.RequestQueueDepthMaximum,
  439. cap.agp.AGPStatus.SideBandAddressing,
  440. cap.agp.AGPStatus.Rate,
  441. ts
  442. );
  443. switch (cap.agp.AGPCommand.Rate) {
  444. case 1:
  445. ts = "1X";
  446. break;
  447. case 2:
  448. ts = "2X";
  449. break;
  450. case 4:
  451. ts = "4X";
  452. break;
  453. default:
  454. ts = "<not set>";
  455. break;
  456. }
  457. t = *(PULONG)&cap.agp.AGPCommand;
  458. dprintf(" Command %08x (Rq:%02x SBA:%x AGP:%x Rate:%x (%s)\n",
  459. t,
  460. cap.agp.AGPCommand.RequestQueueDepth,
  461. cap.agp.AGPCommand.SBAEnable,
  462. cap.agp.AGPCommand.AGPEnable,
  463. cap.agp.AGPCommand.Rate,
  464. ts
  465. );
  466. break;
  467. default:
  468. break;
  469. }
  470. CapPtr = cap.header.Next;
  471. } while (CapPtr != 0);
  472. }
  473. VOID
  474. pcidump (
  475. IN ULONG Flags,
  476. IN ULONG MinBus,
  477. IN ULONG MaxBus,
  478. IN ULONG MinDevice,
  479. IN ULONG MaxDevice,
  480. IN ULONG MinFunction,
  481. IN ULONG MaxFunction,
  482. IN ULONG MinAddr,
  483. IN ULONG MaxAddr
  484. )
  485. {
  486. ULONG Bus, Device, Function;
  487. PCI_TYPE1_CFG_BITS PciCfg1;
  488. PCI_COMMON_CONFIG PciHdr;
  489. BOOLEAN BusHeader, SkipLine, BarIsIo;
  490. ULONG Type, Len, i;
  491. UCHAR s[40];
  492. PUCHAR Buf;
  493. ULONG state;
  494. ULONG bar, barno;
  495. if (MinBus > 0xFF || MaxBus > 0xFF ||
  496. MinDevice > PCI_MAX_DEVICES || MaxDevice > PCI_MAX_DEVICES ||
  497. MinFunction > PCI_MAX_FUNCTION || MaxFunction > PCI_MAX_FUNCTION ||
  498. MinAddr > 0xFF || MaxAddr > 0x100 || MinAddr > MaxAddr) {
  499. dprintf ("Bad pci dump parameter\n");
  500. //dprintf ("Flags %d MinBus %d MaxBus %d\n", Flags, MinBus, MaxBus);
  501. //dprintf ("MinDev %d MaxDev %d MinFnc %d MinFnc %d\n", MinDevice, MaxDevice, MinFunction, MaxFunction);
  502. return ;
  503. }
  504. //dprintf ("Flags %d MinAddr %d MaxAddr %d\n", Flags, MinAddr, MaxAddr);
  505. for (Bus=MinBus; Bus <= MaxBus; Bus++) {
  506. BusHeader = FALSE;
  507. for (Device=MinDevice; Device <= MaxDevice; Device++) {
  508. if (CheckControlC()) {
  509. return;
  510. }
  511. //
  512. // Read the device ID
  513. //
  514. PciCfg1.u.AsULONG = 0;
  515. PciCfg1.u.bits.BusNumber = Bus;
  516. PciCfg1.u.bits.DeviceNumber = Device;
  517. PciCfg1.u.bits.FunctionNumber = 0;
  518. PciCfg1.u.bits.Enable = TRUE;
  519. ReadPci (&PciCfg1, (PUCHAR) &PciHdr, 0, sizeof(ULONG));
  520. //
  521. // If not a valid ID, skip to next device
  522. if (PciHdr.VendorID == PCI_INVALID_VENDORID) {
  523. if (!(Flags & DUMP_ALLOW_INVALID_DEVICE)) {
  524. dprintf ("%02x\r", Device);
  525. continue;
  526. }
  527. }
  528. for (Function=MinFunction; Function <= MaxFunction; Function++) {
  529. if (CheckControlC()) {
  530. return;
  531. }
  532. PciCfg1.u.bits.FunctionNumber = Function;
  533. //
  534. // Read device ID
  535. //
  536. if (Function) {
  537. ReadPci (&PciCfg1, (PUCHAR) &PciHdr, 0, sizeof(ULONG));
  538. }
  539. if (PciHdr.VendorID == PCI_INVALID_VENDORID) {
  540. if (!(Flags & DUMP_ALLOW_INVALID_DEVICE)) {
  541. continue;
  542. }
  543. }
  544. //
  545. // Dump ID
  546. //
  547. if (!BusHeader) {
  548. dprintf ("PCI Bus %d\n", Bus);
  549. BusHeader = TRUE;
  550. }
  551. dprintf ("%02x:%x %04x:%04x",
  552. Device,
  553. Function,
  554. PciHdr.VendorID,
  555. PciHdr.DeviceID
  556. );
  557. //
  558. // Read the rest of the common header
  559. //
  560. ReadPci (
  561. &PciCfg1,
  562. ((PUCHAR) &PciHdr) + sizeof(ULONG),
  563. 0 + sizeof(ULONG),
  564. PCI_COMMON_HDR_LENGTH
  565. );
  566. Type = PciHdr.HeaderType & ~PCI_MULTIFUNCTION;
  567. if (Type == 0x7f && PciHdr.BaseClass == 0xff && PciHdr.SubClass == 0xff) {
  568. if (!(Flags & DUMP_ALLOW_INVALID_FUNCTION)) {
  569. dprintf (" bogus, skipping rest of device\n");
  570. break;
  571. }
  572. }
  573. //
  574. // Dump it
  575. //
  576. s[0] = PciHdr.Command & PCI_ENABLE_IO_SPACE ? 'i' : '.';
  577. s[1] = PciHdr.Command & PCI_ENABLE_MEMORY_SPACE ? 'm' : '.';
  578. s[2] = PciHdr.Command & PCI_ENABLE_BUS_MASTER ? 'b' : '.';
  579. s[3] = PciHdr.Command & PCI_ENABLE_VGA_COMPATIBLE_PALETTE ? 'v' : '.';
  580. s[4] = PciHdr.Command & PCI_ENABLE_PARITY ? 'p' : '.';
  581. s[5] = PciHdr.Command & PCI_ENABLE_SERR ? 's' : '.';
  582. s[6] = 0;
  583. dprintf (".%02x Cmd[%04x:%s] ", PciHdr.RevisionID, PciHdr.Command, s);
  584. s[0] = PciHdr.Status & PCI_STATUS_CAPABILITIES_LIST ? 'c' : '.';
  585. s[1] = PciHdr.Status & PCI_STATUS_66MHZ_CAPABLE ? '6' : '.';
  586. s[2] = PciHdr.Status & PCI_STATUS_DATA_PARITY_DETECTED ? 'P' : '.';
  587. s[3] = PciHdr.Status & PCI_STATUS_SIGNALED_TARGET_ABORT ? 'A' : '.';
  588. s[4] = PciHdr.Status & PCI_STATUS_SIGNALED_SYSTEM_ERROR ? 'S' : '.';
  589. s[5] = 0;
  590. dprintf ("Sts[%04x:%s] ", PciHdr.Status, s);
  591. switch (Type) {
  592. case PCI_DEVICE_TYPE:
  593. dprintf ("Device");
  594. if (PciHdr.u.type0.SubVendorID || PciHdr.u.type0.SubSystemID) {
  595. dprintf (" SubID:%04x:%04x",
  596. PciHdr.u.type0.SubVendorID,
  597. PciHdr.u.type0.SubSystemID
  598. );
  599. }
  600. break;
  601. case PCI_BRIDGE_TYPE:
  602. dprintf ("PciBridge %d->%d-%d",
  603. PciHdr.u.type1.PrimaryBus,
  604. PciHdr.u.type1.SecondaryBus,
  605. PciHdr.u.type1.SubordinateBus
  606. );
  607. break;
  608. case PCI_CARDBUS_BRIDGE_TYPE:
  609. dprintf ("CardbusBridge %d->%d-%d",
  610. PciHdr.u.type2.PrimaryBus,
  611. PciHdr.u.type2.SecondaryBus,
  612. PciHdr.u.type2.SubordinateBus
  613. );
  614. break;
  615. default:
  616. dprintf ("type %x", Type);
  617. break;
  618. }
  619. //
  620. // Search for a class code match
  621. //
  622. PCHAR Desc = GetClassDesc(PciHdr.BaseClass, PciHdr.SubClass, PciHdr.ProgIf);
  623. if (Desc) {
  624. dprintf (" %s", Desc);
  625. } else {
  626. dprintf (" Class:%x:%x:%x",
  627. PciHdr.BaseClass,
  628. PciHdr.SubClass,
  629. PciHdr.ProgIf
  630. );
  631. }
  632. dprintf ("\n");
  633. SkipLine = FALSE;
  634. if (Flags & DUMP_VERBOSE) {
  635. SkipLine = TRUE;
  636. PciCfg1.u.bits.RegisterNumber = 0;
  637. switch (Type) {
  638. case PCI_DEVICE_TYPE:
  639. dprintf (" cf8:%x IntPin:%x IntLine:%x Rom:%x cis:%x cap:%x\n",
  640. PciCfg1.u.AsULONG,
  641. PciHdr.u.type0.InterruptPin,
  642. PciHdr.u.type0.InterruptLine,
  643. PciHdr.u.type0.ROMBaseAddress,
  644. PciHdr.u.type0.CIS,
  645. PciHdr.u.type0.CapabilitiesPtr
  646. );
  647. state = 0;
  648. for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
  649. bar = PciHdr.u.type0.BaseAddresses[i];
  650. DumpPciBar(i, 6, bar, &state);
  651. }
  652. DumpPciBarComplete(&state);
  653. break;
  654. case PCI_BRIDGE_TYPE:
  655. i = PciHdr.u.type1.BridgeControl;
  656. dprintf (" cf8:%x IntPin:%x IntLine:%x Rom:%x cap:%x 2sts:%x BCtrl:%x%s%s%s\n",
  657. PciCfg1.u.AsULONG,
  658. PciHdr.u.type1.InterruptPin,
  659. PciHdr.u.type1.InterruptLine,
  660. PciHdr.u.type1.ROMBaseAddress,
  661. PciHdr.u.type1.CapabilitiesPtr,
  662. PciHdr.u.type1.SecondaryStatus,
  663. PciHdr.u.type1.BridgeControl,
  664. i & PCI_ENABLE_BRIDGE_VGA ? " VGA" : "",
  665. i & PCI_ENABLE_BRIDGE_ISA ? " ISA" : "",
  666. i & PCI_ASSERT_BRIDGE_RESET ? " RESET" : ""
  667. );
  668. dprintf (" IO:%x-%x Mem:%x-%x PMem:%x-%x\n",
  669. PciBridgeIO2Base (PciHdr.u.type1.IOBase, PciHdr.u.type1.IOBaseUpper16),
  670. PciBridgeIO2Limit(PciHdr.u.type1.IOLimit, PciHdr.u.type1.IOLimitUpper16),
  671. PciBridgeMemory2Base (PciHdr.u.type1.MemoryBase),
  672. PciBridgeMemory2Limit(PciHdr.u.type1.MemoryLimit),
  673. PciBridgeMemory2Base (PciHdr.u.type1.PrefetchBase),
  674. PciBridgeMemory2Limit(PciHdr.u.type1.PrefetchLimit)
  675. );
  676. state = 0;
  677. for (i=0; i < PCI_TYPE1_ADDRESSES; i++) {
  678. bar = PciHdr.u.type1.BaseAddresses[i];
  679. DumpPciBar(i, 6, bar, &state);
  680. }
  681. DumpPciBarComplete(&state);
  682. break;
  683. case PCI_CARDBUS_BRIDGE_TYPE:
  684. i = PciHdr.u.type2.BridgeControl;
  685. dprintf (" cf8:%x IntPin:%x IntLine:%x SocketRegBase:%x cap:%x 2sts:%x BCtrl:%x%s%s%s\n",
  686. PciCfg1.u.AsULONG,
  687. PciHdr.u.type2.InterruptPin,
  688. PciHdr.u.type2.InterruptLine,
  689. PciHdr.u.type2.SocketRegistersBaseAddress,
  690. PciHdr.u.type2.CapabilitiesPtr,
  691. PciHdr.u.type2.SecondaryStatus,
  692. PciHdr.u.type2.BridgeControl,
  693. i & PCI_ENABLE_BRIDGE_VGA ? " VGA" : "",
  694. i & PCI_ENABLE_BRIDGE_ISA ? " ISA" : "",
  695. i & PCI_ASSERT_BRIDGE_RESET ? " RESET" : ""
  696. );
  697. dprintf("\n");
  698. state=0;
  699. for (i = 0; i < (PCI_TYPE2_ADDRESSES - 1); i++) {
  700. bar = PciHdr.u.type2.Range[i].Base;
  701. //
  702. // First 2 BARs (base+limit) are memory
  703. //
  704. BarIsIo = (i > 1);
  705. barno = i;
  706. if (BarIsIo) {
  707. barno -= 2;
  708. }
  709. DumpPciType2Bar(BarIsIo,TRUE, barno, 6, bar, &state);
  710. bar = PciHdr.u.type2.Range[i].Limit;
  711. DumpPciType2Bar(BarIsIo, FALSE, i, 6, bar, &state);
  712. }
  713. DumpPciBarComplete(&state);
  714. break;
  715. }
  716. }
  717. //
  718. // Dump CAPABILITIES if any.
  719. //
  720. if (Flags & DUMP_CAPABILITIES) {
  721. if (PciHdr.Status & PCI_STATUS_CAPABILITIES_LIST) {
  722. UCHAR capPtr = 0;
  723. SkipLine = TRUE;
  724. switch (Type) {
  725. case PCI_DEVICE_TYPE:
  726. capPtr = PciHdr.u.type0.CapabilitiesPtr;
  727. break;
  728. case PCI_BRIDGE_TYPE:
  729. capPtr = PciHdr.u.type1.CapabilitiesPtr;
  730. break;
  731. case PCI_CARDBUS_BRIDGE_TYPE:
  732. capPtr = PciHdr.u.type2.CapabilitiesPtr;
  733. break;
  734. }
  735. if (capPtr != 0) {
  736. DumpCapabilities(capPtr, &PciCfg1);
  737. } else {
  738. //
  739. // Capabilities flag is set in Status but
  740. // pointer is 0??? Something's broken.
  741. //
  742. dprintf(" Warning: Capability bit set in Status but capability pointer is 0.\n");
  743. }
  744. }
  745. }
  746. //
  747. // Dump hex bytes
  748. //
  749. if (Flags & DUMP_RAW_BYTES) {
  750. ULONG w;
  751. //
  752. // Raw dump requested, if no range default to common
  753. // config.
  754. //
  755. if (!MinAddr && !MaxAddr) {
  756. MaxAddr = PCI_COMMON_HDR_LENGTH - 1;
  757. }
  758. //
  759. // Default width to 1. If dumping dwords, set width
  760. // width to 4 and round min and max accordingly.
  761. //
  762. w = 1;
  763. if (Flags & DUMP_RAW_DWORDS) {
  764. w = 4;
  765. MinAddr &= ~3;
  766. MaxAddr &= ~3;
  767. MaxAddr += 3;
  768. }
  769. Buf = ((PUCHAR) &PciHdr) + MinAddr;
  770. Len = MaxAddr - MinAddr + 1;
  771. if (MinAddr <= PCI_COMMON_HDR_LENGTH) {
  772. if (MaxAddr > PCI_COMMON_HDR_LENGTH) {
  773. ReadPci (
  774. &PciCfg1,
  775. PciHdr.DeviceSpecific,
  776. PCI_COMMON_HDR_LENGTH,
  777. MaxAddr - PCI_COMMON_HDR_LENGTH
  778. );
  779. }
  780. } else {
  781. ReadPci (&PciCfg1, Buf, MinAddr, Len);
  782. }
  783. HexDump (w == 4 ? 6 : 1, MinAddr, Len, w, Buf);
  784. SkipLine = TRUE;
  785. } else if ((Flags & DUMP_INTEL) && PciHdr.VendorID == 0x8086) {
  786. Buf = PciHdr.DeviceSpecific;
  787. Len = sizeof (PciHdr) - PCI_COMMON_HDR_LENGTH;
  788. ReadPci (&PciCfg1, Buf, PCI_COMMON_HDR_LENGTH, Len);
  789. HexDump (1, PCI_COMMON_HDR_LENGTH, Len, 1, Buf);
  790. SkipLine = TRUE;
  791. }
  792. if (Flags & DUMP_CONFIGSPACE) {
  793. PCI_COMMON_CONFIG cs;
  794. ReadPci(&PciCfg1, (PUCHAR)&cs, 0, sizeof(cs));
  795. dprintf ("Config Space:\n",
  796. PciCfg1.u.bits.BusNumber,
  797. PciCfg1.u.bits.DeviceNumber,
  798. PciCfg1.u.bits.FunctionNumber);
  799. DumpCfgSpace(&cs);
  800. dprintf ("\n");
  801. }
  802. if (SkipLine) {
  803. dprintf ("\n");
  804. }
  805. //
  806. // If no more functions on this device, skip the rest
  807. // of the functions
  808. //
  809. if (Function == 0 && !(PciHdr.HeaderType & PCI_MULTIFUNCTION)) {
  810. if (!(Flags & DUMP_ALLOW_INVALID_FUNCTION)) {
  811. break;
  812. }
  813. }
  814. }
  815. }
  816. }
  817. }
  818. DECLARE_API( pci )
  819. /*++
  820. Routine Description:
  821. Dumps pci type2 config data
  822. Arguments:
  823. args - Supplies the address in hex.
  824. Return Value:
  825. None
  826. --*/
  827. {
  828. LONG noargs;
  829. ULONG Flags;
  830. ULONG MinBus, MaxBus;
  831. ULONG Device, MinDevice, MaxDevice;
  832. ULONG Function, MinFunction, MaxFunction;
  833. ULONG MinAddr, MaxAddr;
  834. MinBus = 0;
  835. MaxBus = 0;
  836. MinDevice = 0;
  837. MaxDevice = PCI_MAX_DEVICES - 1;
  838. MinFunction = 0;
  839. MaxFunction = PCI_MAX_FUNCTION - 1;
  840. MinAddr = 0;
  841. MaxAddr = 0;
  842. Flags = 0;
  843. if (g_TargetQual == DEBUG_DUMP_SMALL ||
  844. g_TargetQual == DEBUG_DUMP_DEFAULT ||
  845. g_TargetQual == DEBUG_DUMP_FULL) {
  846. dprintf("!pci does not work for dump targets\n");
  847. return E_INVALIDARG;
  848. }
  849. {
  850. INIT_API();
  851. noargs = sscanf(args,"%lX %lX %lX %lX %lX %lX",
  852. &Flags, // 1
  853. &MaxBus, // 2
  854. &Device, // 3
  855. &Function, // 4
  856. &MinAddr, // 5
  857. &MaxAddr // 6
  858. );
  859. MinBus = MaxBus;
  860. if (Flags & DUMP_TO_MAX_BUS) {
  861. MinBus = 0;
  862. }
  863. if (noargs >= 3) {
  864. Flags |= DUMP_ALLOW_INVALID_DEVICE;
  865. MinDevice = Device;
  866. MaxDevice = Device;
  867. }
  868. if (noargs >= 4) {
  869. MinFunction = Function;
  870. MaxFunction = Function;
  871. }
  872. if (MinAddr || MaxAddr) {
  873. Flags |= DUMP_RAW_BYTES;
  874. }
  875. if (Flags & DUMP_RAW_DWORDS) {
  876. Flags |= DUMP_RAW_BYTES;
  877. }
  878. pcidump (
  879. Flags,
  880. MinBus, MaxBus,
  881. MinDevice, MaxDevice,
  882. MinFunction, MaxFunction,
  883. MinAddr, MaxAddr
  884. );
  885. EXIT_API();
  886. }
  887. return S_OK;
  888. }