1use core::ops::Deref;
12
13use crate::device::Device;
14
15#[derive(Copy, Clone, Debug)]
24pub struct BaseCap<'a> {
25 dev: &'a Device,
26 ptr: u16,
27}
28
29impl BaseCap<'_> {
30 pub fn id(&self) -> u8 {
32 self.dev.read8(self.ptr)
33 }
34
35 pub fn next(&self) -> u8 {
37 self.dev.read8(self.ptr + 1)
38 }
39
40 #[inline]
42 pub fn read8(&self, offset: u16) -> u8 {
43 self.dev.read8(self.ptr + offset)
44 }
45
46 #[inline]
48 pub fn write8(&self, offset: u16, val: u8) {
49 self.dev.write8(self.ptr + offset, val)
50 }
51
52 #[inline]
54 pub fn read16(&self, offset: u16) -> u16 {
55 self.dev.read16(self.ptr + offset)
56 }
57
58 #[inline]
60 pub fn write16(&self, offset: u16, val: u16) {
61 self.dev.write16(self.ptr + offset, val)
62 }
63
64 #[inline]
66 pub fn read32(&self, offset: u16) -> u32 {
67 self.dev.read32(self.ptr + offset)
68 }
69
70 #[inline]
72 pub fn write32(&self, offset: u16, val: u32) {
73 self.dev.write32(self.ptr + offset, val)
74 }
75}
76
77pub struct MsiCap<'a>(BaseCap<'a>);
79
80impl MsiCap<'_> {
81 pub const ID: u8 = 0x05;
83
84 pub fn control(&self) -> u16 {
86 self.0.dev.read16(self.0.ptr + 2)
87 }
88
89 pub fn enabled(&self) -> bool {
91 self.control() & 0x0001 != 0
92 }
93
94 pub fn disable(&self) {
96 let mut ctrl = self.control();
97 ctrl &= !0x0001;
98 self.0.dev.write16(self.0.ptr + 2, ctrl);
99 }
100}
101
102pub struct VendorCap<'a>(BaseCap<'a>);
107
108impl VendorCap<'_> {
109 pub const ID: u8 = 0x09;
111
112 pub fn length(&self) -> u8 {
114 self.0.dev.read8(self.0.ptr + 2)
115 }
116}
117
118impl<'a> Deref for VendorCap<'a> {
119 type Target = BaseCap<'a>;
120 fn deref(&self) -> &Self::Target {
121 &self.0
122 }
123}
124
125pub struct MsixCap<'a>(BaseCap<'a>);
127
128impl MsixCap<'_> {
129 pub const ID: u8 = 0x11;
131
132 pub fn control(&self) -> u16 {
134 self.0.dev.read16(self.0.ptr + 2)
135 }
136
137 pub fn enabled(&self) -> bool {
139 self.control() & 0x8000 != 0
140 }
141
142 pub fn disable(&self) {
144 let mut ctrl = self.control();
145 ctrl &= !0x8000;
146 self.0.dev.write16(self.0.ptr + 2, ctrl);
147 }
148}
149
150pub enum Cap<'a> {
152 Msi(MsiCap<'a>),
153 Msix(MsixCap<'a>),
154 Vendor(VendorCap<'a>),
155 Other(BaseCap<'a>),
156}
157
158impl<'a> From<BaseCap<'a>> for Cap<'a> {
159 fn from(base: BaseCap<'a>) -> Self {
160 match base.id() {
161 MsiCap::ID => Cap::Msi(MsiCap(base)),
162 MsixCap::ID => Cap::Msix(MsixCap(base)),
163 VendorCap::ID => Cap::Vendor(VendorCap(base)),
164 _ => Cap::Other(base),
165 }
166 }
167}
168
169pub struct CapIter<'a> {
171 dev: &'a Device,
172 cur: u16,
173 visited: u8,
174}
175
176impl<'a> CapIter<'a> {
177 pub(crate) fn new(dev: &'a Device) -> Self {
179 let cur = dev.cap_ptr().unwrap_or(0) as u16;
180 Self {
181 dev,
182 cur,
183 visited: 0,
184 }
185 }
186}
187
188impl<'a> Iterator for CapIter<'a> {
189 type Item = Cap<'a>;
190
191 fn next(&mut self) -> Option<Self::Item> {
192 if self.cur == 0 {
194 return None;
195 }
196
197 if self.cur >= 256 {
199 return None;
200 }
201 if self.visited > 64 {
202 return None;
203 }
204
205 let base = BaseCap {
206 dev: self.dev,
207 ptr: self.cur,
208 };
209
210 self.cur = base.next() as u16;
211 self.visited += 1;
212
213 Some(base.into())
214 }
215}