Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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