1use crate::config::{BridgeControlRegister, SecondaryStatusRegister, Type01Config};
5use crate::device::Device;
6use crate::util::format_bytes;
7use std::fmt;
8use zerocopy::Ref;
9
10pub struct Bridge<'a> {
13 device: &'a Device<'a>,
14 cfg: Ref<&'a [u8], Type01Config>,
15}
16
17impl<'a> Bridge<'a> {
18 pub fn new(device: &'a Device<'_>) -> Self {
19 let cfg = Type01Config::new(&device.device.config);
20 Bridge { device, cfg }
21 }
22
23 pub fn decode_bridge_io(&self) -> Option<(u32, u32)> {
24 let mut io_base: u32 = (self.cfg.io_base >> 4).into();
26 let mut io_limit: u32 = (self.cfg.io_limit >> 4).into();
27 let is_32bit: bool = self.cfg.io_base & 0xF == 1;
28 if (io_base == 0 && io_limit == 0) || io_base > io_limit {
30 return None;
31 }
32
33 io_base <<= 12;
36 io_limit <<= 12;
38 io_limit |= 0xFFF;
39 if is_32bit {
40 Some((
41 (io_base) | self.cfg.io_base_upper_16 as u32,
42 (io_limit) | self.cfg.io_limit_upper_16 as u32,
43 ))
44 } else {
45 Some((io_base, io_limit))
46 }
47 }
48
49 pub fn decode_bridge_mem(&self) -> Option<(u32, u32)> {
50 let mut mem_base: u32 = (self.cfg.memory_base >> 4).into();
52 let mut mem_limit: u32 = (self.cfg.memory_limit >> 4).into();
53 if (mem_base == 0 && mem_limit == 0) || mem_base > mem_limit {
55 return None;
56 }
57
58 mem_base <<= 20;
61 mem_limit <<= 20;
63 mem_limit |= 0xFFFFF;
64 Some((mem_base, mem_limit))
65 }
66
67 pub fn decode_bridge_pf(&self) -> Option<(u64, u64)> {
68 let mut pf_base: u64 = (self.cfg.pf_memory_base >> 4).into();
70 let mut pf_limit: u64 = (self.cfg.pf_memory_limit >> 4).into();
71 let is_64bit: bool = self.cfg.pf_memory_base & 0xF == 1;
72 if (pf_base == 0 && pf_limit == 0) || pf_base > pf_limit {
74 return None;
75 }
76
77 pf_base <<= 20;
80 pf_limit <<= 20;
82 pf_limit |= 0xFFFFF;
83 if is_64bit {
84 Some((
85 (pf_base) | (self.cfg.pf_base_upper_32 as u64) << 32,
86 (pf_limit) | (self.cfg.pf_limit_upper_32 as u64) << 32,
87 ))
88 } else {
89 Some((pf_base, pf_limit))
90 }
91 }
92}
93
94impl<'a> fmt::Display for Bridge<'a> {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 self.device.print_common_header(f)?;
98 if self.device.args.verbose {
99 writeln!(
100 f,
101 "\tBus: primary = 0x{:02x}, secondary = 0x{:02x}, subordinate = 0x{:02x}, sec-latency = {}",
102 self.cfg.primary_bus_number,
103 self.cfg.secondary_bus_number,
104 self.cfg.subordinate_bus_number,
105 self.cfg.secondary_latency_timer)?;
106
107 write!(f, "\tI/O behind bridge: ")?;
108 if let Some((base, limit)) = self.decode_bridge_io() {
109 writeln!(
110 f,
111 "[0x{:8x}, 0x{:8x}] [size={}]",
112 base,
113 limit,
114 format_bytes((limit - base + 1) as u64)
115 )?;
116 } else {
117 writeln!(f, "[disabled]")?;
118 }
119 write!(f, "\tMemory behind bridge: ")?;
120 if let Some((base, limit)) = self.decode_bridge_mem() {
121 writeln!(
122 f,
123 "[0x{:8x}, 0x{:8x}] [size={}]",
124 base,
125 limit,
126 format_bytes((limit - base + 1) as u64)
127 )?;
128 } else {
129 writeln!(f, "[disabled]")?;
130 }
131 write!(f, "\tPrefetchable memory behind bridge: ")?;
132 if let Some((base, limit)) = self.decode_bridge_pf() {
133 writeln!(
134 f,
135 "[0x{:16x}, 0x{:16x}] [size={}]",
136 base,
137 limit,
138 format_bytes((limit - base + 1) as u64)
139 )?;
140 } else {
141 writeln!(f, "[disabled]")?;
142 }
143 writeln!(
144 f,
145 "\tSecondary Status: {}",
146 SecondaryStatusRegister(self.cfg.secondary_status)
147 )?;
148 writeln!(f, "\tBridge Control: {}", BridgeControlRegister(self.cfg.bridge_control))?;
149 }
150 self.device.print_common_footer(f)
151 }
152}