aboutsummaryrefslogtreecommitdiff
path: root/kapi/gdb/devices/resource.py
blob: dd5fd3204af2ad75da8ae229193e8ef8e7056ef7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import gdb


# Map from the resource_type enum integer value to a readable name.
# kapi::devices::resource_type is a plain enum struct with no backing store
# other than int, so we match by integer.
_RESOURCE_TYPES = {
    0: "mmio",
    1: "port",
    2: "irq",
    3: "dma",
}


class KapiDevicesResourcePrinter(gdb.ValuePrinter):

    def __init__(self, val):
        self.__val = val
        self.__type_int = int(val["type"])
        self.__type_name = _RESOURCE_TYPES.get(self.__type_int, f"<unknown:{self.__type_int}>")

    def _active_member(self):
        union = self.__val["m_value"]
        t = self.__type_int
        if t == 0:
            return union["range"]
        if t == 1:
            return union["port"]
        if t == 2:
            return union["irq"]
        if t == 3:
            return union["channel"]
        return union

    def to_string(self):
        try:
            t = self.__type_int
            union = self.__val["m_value"]
            if t == 0:  # mmio
                start = int(union["range"]["start"]["m_value"])
                size = int(union["range"]["size"]["value"])
                return f"mmio [{start:#x}, +{size:#x})"
            if t == 1:  # port
                start = int(union["port"]["start"])
                count = int(union["port"]["count"])
                return f"port {start:#x}+{count}"
            if t == 2:  # irq
                number = int(union["irq"]["number"])
                return f"irq {number}"
            if t == 3:  # dma
                number = int(union["channel"]["number"])
                return f"dma channel {number}"
        except (gdb.error, AttributeError):
            pass
        return f"resource ({self.__type_name})"

    def children(self):
        yield ("type", self.__val["type"])
        yield (self.__type_name, self._active_member())

    def display_hint(self):
        return None