1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2019, Joyent, Inc.
14 */
15
16 /*
17 * PCIe related dcmds
18 */
19
20 #include <mdb/mdb_modapi.h>
21 #include <sys/dditypes.h>
22 #include <sys/ddi_impldefs.h>
23 #include <sys/pcie_impl.h>
24
25 boolean_t
pcie_bus_match(const struct dev_info * devi,uintptr_t * bus_p)26 pcie_bus_match(const struct dev_info *devi, uintptr_t *bus_p)
27 {
28 if (devi->devi_bus.port_up.info.port.type == DEVI_PORT_TYPE_PCI) {
29 *bus_p = (uintptr_t)devi->devi_bus.port_up.priv_p;
30 } else if (devi->devi_bus.port_down.info.port.type ==
31 DEVI_PORT_TYPE_PCI) {
32 *bus_p = (uintptr_t)devi->devi_bus.port_down.priv_p;
33 } else {
34 return (B_FALSE);
35 }
36
37 return (B_TRUE);
38 }
39
40 int
pcie_bus_walk_init(mdb_walk_state_t * wsp)41 pcie_bus_walk_init(mdb_walk_state_t *wsp)
42 {
43 if (wsp->walk_addr != 0) {
44 mdb_warn("pcie_bus walker doesn't support non-global walks\n");
45 return (WALK_ERR);
46 }
47
48 if (mdb_layered_walk("devinfo", wsp) == -1) {
49 mdb_warn("couldn't walk \"devinfo\"");
50 return (WALK_ERR);
51 }
52
53 return (WALK_NEXT);
54 }
55
56 int
pcie_bus_walk_step(mdb_walk_state_t * wsp)57 pcie_bus_walk_step(mdb_walk_state_t *wsp)
58 {
59 const struct dev_info *devi;
60 uintptr_t bus_addr;
61 struct pcie_bus bus;
62
63 if (wsp->walk_layer == NULL) {
64 mdb_warn("missing layered walk info\n");
65 return (WALK_ERR);
66 }
67
68 devi = wsp->walk_layer;
69 if (!pcie_bus_match(devi, &bus_addr)) {
70 return (WALK_NEXT);
71 }
72
73 if (mdb_vread(&bus, sizeof (bus), bus_addr) == -1) {
74 mdb_warn("failed to read pcie_bus_t at %p", bus_addr);
75 return (WALK_NEXT);
76 }
77
78 return (wsp->walk_callback(bus_addr, &bus, wsp->walk_cbdata));
79 }
80