1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::str::FromStr;
6 use std::sync::Arc;
7
8 use base::error;
9 use base::warn;
10 use base::Event;
11 use resources::Alloc;
12 use resources::SystemAllocator;
13 use sync::Mutex;
14 use zerocopy::FromBytes;
15
16 use crate::pci::pci_configuration::PciCapConfig;
17 use crate::pci::pci_configuration::PciCapConfigWriteResult;
18 use crate::pci::pci_configuration::PciCapMapping;
19 use crate::pci::pci_configuration::PciCapability;
20 use crate::pci::pcie::pci_bridge::PciBridgeBusRange;
21 use crate::pci::pcie::pcie_device::PcieCap;
22 use crate::pci::pcie::pcie_device::PcieDevice;
23 use crate::pci::pcie::pcie_host::PcieHostPort;
24 use crate::pci::pcie::*;
25 use crate::pci::pm::PciDevicePower;
26 use crate::pci::pm::PciPmCap;
27 use crate::pci::pm::PmConfig;
28 use crate::pci::pm::PmStatusChange;
29 use crate::pci::MsiConfig;
30 use crate::pci::PciAddress;
31 use crate::pci::PciDeviceError;
32
33 // reserve 8MB memory window
34 const PCIE_BR_MEM_SIZE: u64 = 0x80_0000;
35 // reserve 64MB prefetch window
36 const PCIE_BR_PREF_MEM_SIZE: u64 = 0x400_0000;
37
trigger_interrupt(msi: &Option<Arc<Mutex<MsiConfig>>>)38 fn trigger_interrupt(msi: &Option<Arc<Mutex<MsiConfig>>>) {
39 if let Some(msi_config) = msi {
40 let msi_config = msi_config.lock();
41 if msi_config.is_msi_enabled() {
42 msi_config.trigger()
43 }
44 }
45 }
46
47 struct PcieRootCap {
48 secondary_bus_num: u8,
49 subordinate_bus_num: u8,
50
51 control: u16,
52 status: u32,
53 pme_pending_requester_id: Option<u16>,
54
55 msi_config: Option<Arc<Mutex<MsiConfig>>>,
56 }
57
58 impl PcieRootCap {
new(secondary_bus_num: u8, subordinate_bus_num: u8) -> Self59 fn new(secondary_bus_num: u8, subordinate_bus_num: u8) -> Self {
60 PcieRootCap {
61 secondary_bus_num,
62 subordinate_bus_num,
63 control: 0,
64 status: 0,
65 pme_pending_requester_id: None,
66 msi_config: None,
67 }
68 }
69
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)70 fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
71 self.msi_config = Some(msi_config);
72 }
73
trigger_pme_interrupt(&self)74 fn trigger_pme_interrupt(&self) {
75 if (self.control & PCIE_ROOTCTL_PME_ENABLE) != 0
76 && (self.status & PCIE_ROOTSTA_PME_STATUS) != 0
77 {
78 trigger_interrupt(&self.msi_config)
79 }
80 }
81 }
82
83 static PCIE_ROOTS_CAP: Mutex<Vec<Arc<Mutex<PcieRootCap>>>> = Mutex::new(Vec::new());
84
push_pcie_root_cap(root_cap: Arc<Mutex<PcieRootCap>>)85 fn push_pcie_root_cap(root_cap: Arc<Mutex<PcieRootCap>>) {
86 PCIE_ROOTS_CAP.lock().push(root_cap);
87 }
88
get_pcie_root_cap(bus_num: u8) -> Option<Arc<Mutex<PcieRootCap>>>89 fn get_pcie_root_cap(bus_num: u8) -> Option<Arc<Mutex<PcieRootCap>>> {
90 for root_cap in PCIE_ROOTS_CAP.lock().iter() {
91 let root_cap_lock = root_cap.lock();
92 if root_cap_lock.secondary_bus_num <= bus_num
93 && root_cap_lock.subordinate_bus_num >= bus_num
94 {
95 return Some(root_cap.clone());
96 }
97 }
98
99 None
100 }
101
102 pub struct PciePort {
103 device_id: u16,
104 debug_label: String,
105 preferred_address: Option<PciAddress>,
106 pci_address: Option<PciAddress>,
107 bus_range: PciBridgeBusRange,
108 pcie_host: Option<PcieHostPort>,
109 pcie_config: Arc<Mutex<PcieConfig>>,
110 pm_config: Arc<Mutex<PmConfig>>,
111
112 msi_config: Option<Arc<Mutex<MsiConfig>>>,
113
114 // For PcieRootPort, root_cap point to itself
115 // For PcieDownstreamPort or PciDownstreamPort, root_cap point to PcieRootPort its behind.
116 root_cap: Arc<Mutex<PcieRootCap>>,
117 port_type: PcieDevicePortType,
118
119 prepare_hotplug: bool,
120 }
121
122 impl PciePort {
123 /// Constructs a new PCIE port
new( device_id: u16, debug_label: String, primary_bus_num: u8, secondary_bus_num: u8, slot_implemented: bool, port_type: PcieDevicePortType, ) -> Self124 pub fn new(
125 device_id: u16,
126 debug_label: String,
127 primary_bus_num: u8,
128 secondary_bus_num: u8,
129 slot_implemented: bool,
130 port_type: PcieDevicePortType,
131 ) -> Self {
132 let bus_range = PciBridgeBusRange {
133 primary: primary_bus_num,
134 secondary: secondary_bus_num,
135 subordinate: secondary_bus_num,
136 };
137
138 let root_cap = if port_type == PcieDevicePortType::RootPort {
139 let cap = Arc::new(Mutex::new(PcieRootCap::new(
140 secondary_bus_num,
141 secondary_bus_num,
142 )));
143 push_pcie_root_cap(cap.clone());
144 cap
145 } else {
146 get_pcie_root_cap(primary_bus_num).expect("Pcie root port should be created at first")
147 };
148
149 PciePort {
150 device_id,
151 debug_label,
152 preferred_address: None,
153 pci_address: None,
154 bus_range,
155 pcie_host: None,
156 msi_config: None,
157 pcie_config: Arc::new(Mutex::new(PcieConfig::new(
158 root_cap.clone(),
159 slot_implemented,
160 port_type,
161 ))),
162 pm_config: Arc::new(Mutex::new(PmConfig::new(false))),
163
164 root_cap,
165 port_type,
166
167 prepare_hotplug: false,
168 }
169 }
170
new_from_host( pcie_host: PcieHostPort, slot_implemented: bool, port_type: PcieDevicePortType, ) -> std::result::Result<Self, PciDeviceError>171 pub fn new_from_host(
172 pcie_host: PcieHostPort,
173 slot_implemented: bool,
174 port_type: PcieDevicePortType,
175 ) -> std::result::Result<Self, PciDeviceError> {
176 let bus_range = pcie_host.get_bus_range();
177 let host_address = PciAddress::from_str(&pcie_host.host_name())
178 .map_err(|e| PciDeviceError::PciAddressParseFailure(pcie_host.host_name(), e))?;
179 let root_cap = if port_type == PcieDevicePortType::RootPort {
180 let cap = Arc::new(Mutex::new(PcieRootCap::new(
181 bus_range.secondary,
182 bus_range.subordinate,
183 )));
184 push_pcie_root_cap(cap.clone());
185 cap
186 } else {
187 get_pcie_root_cap(bus_range.primary).expect("Pcie root port should be created at first")
188 };
189
190 Ok(PciePort {
191 device_id: pcie_host.read_device_id(),
192 debug_label: pcie_host.host_name(),
193 preferred_address: Some(host_address),
194 pci_address: None,
195 bus_range,
196 pcie_host: Some(pcie_host),
197 msi_config: None,
198 pcie_config: Arc::new(Mutex::new(PcieConfig::new(
199 root_cap.clone(),
200 slot_implemented,
201 port_type,
202 ))),
203 pm_config: Arc::new(Mutex::new(PmConfig::new(false))),
204
205 root_cap,
206 port_type,
207
208 prepare_hotplug: false,
209 })
210 }
211
get_device_id(&self) -> u16212 pub fn get_device_id(&self) -> u16 {
213 self.device_id
214 }
215
get_address(&self) -> Option<PciAddress>216 pub fn get_address(&self) -> Option<PciAddress> {
217 self.pci_address
218 }
219
debug_label(&self) -> String220 pub fn debug_label(&self) -> String {
221 self.debug_label.clone()
222 }
223
preferred_address(&self) -> Option<PciAddress>224 pub fn preferred_address(&self) -> Option<PciAddress> {
225 self.preferred_address
226 }
227
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>228 pub fn allocate_address(
229 &mut self,
230 resources: &mut SystemAllocator,
231 ) -> std::result::Result<PciAddress, PciDeviceError> {
232 if self.pci_address.is_none() {
233 if let Some(address) = self.preferred_address {
234 if resources.reserve_pci(
235 Alloc::PciBar {
236 bus: address.bus,
237 dev: address.dev,
238 func: address.func,
239 bar: 0,
240 },
241 self.debug_label(),
242 ) {
243 self.pci_address = Some(address);
244 } else {
245 self.pci_address = None;
246 }
247 } else {
248 match resources.allocate_pci(self.bus_range.primary, self.debug_label()) {
249 Some(Alloc::PciBar {
250 bus,
251 dev,
252 func,
253 bar: _,
254 }) => self.pci_address = Some(PciAddress { bus, dev, func }),
255 _ => self.pci_address = None,
256 }
257 }
258 }
259 self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
260 }
261
read_config(&self, reg_idx: usize, data: &mut u32)262 pub fn read_config(&self, reg_idx: usize, data: &mut u32) {
263 if let Some(host) = &self.pcie_host {
264 host.read_config(reg_idx, data);
265 }
266 }
267
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])268 pub fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
269 if let Some(host) = self.pcie_host.as_mut() {
270 host.write_config(reg_idx, offset, data);
271 }
272 }
273
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)274 pub fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>) {
275 if let Some(status) = res.downcast_ref::<PmStatusChange>() {
276 if status.from == PciDevicePower::D3
277 && status.to == PciDevicePower::D0
278 && self.prepare_hotplug
279 {
280 if let Some(host) = self.pcie_host.as_mut() {
281 host.hotplug_probe();
282 self.prepare_hotplug = false;
283 }
284 }
285 }
286 }
287
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>288 pub fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)> {
289 vec![
290 (
291 Box::new(PcieCap::new(self.port_type, self.hotplug_implemented(), 0)),
292 Some(Box::new(self.pcie_config.clone())),
293 ),
294 (
295 Box::new(PciPmCap::new()),
296 Some(Box::new(self.pm_config.clone())),
297 ),
298 ]
299 }
300
get_bus_range(&self) -> Option<PciBridgeBusRange>301 pub fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
302 Some(self.bus_range)
303 }
304
get_bridge_window_size(&self) -> (u64, u64)305 pub fn get_bridge_window_size(&self) -> (u64, u64) {
306 if let Some(host) = &self.pcie_host {
307 host.get_bridge_window_size()
308 } else {
309 (PCIE_BR_MEM_SIZE, PCIE_BR_PREF_MEM_SIZE)
310 }
311 }
312
get_slot_control(&self) -> u16313 pub fn get_slot_control(&self) -> u16 {
314 self.pcie_config.lock().get_slot_control()
315 }
316
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)317 pub fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
318 if self.port_type == PcieDevicePortType::RootPort {
319 self.root_cap.lock().clone_interrupt(msi_config.clone());
320 }
321 self.pcie_config.lock().msi_config = Some(msi_config.clone());
322 self.msi_config = Some(msi_config);
323 }
324
hotplug_implemented(&self) -> bool325 pub fn hotplug_implemented(&self) -> bool {
326 self.pcie_config.lock().slot_control.is_some()
327 }
328
inject_pme(&mut self, requester_id: u16)329 pub fn inject_pme(&mut self, requester_id: u16) {
330 let mut r = self.root_cap.lock();
331 if (r.status & PCIE_ROOTSTA_PME_STATUS) != 0 {
332 r.status |= PCIE_ROOTSTA_PME_PENDING;
333 r.pme_pending_requester_id = Some(requester_id);
334 } else {
335 r.status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
336 r.status |= requester_id as u32;
337 r.pme_pending_requester_id = None;
338 r.status |= PCIE_ROOTSTA_PME_STATUS;
339 r.trigger_pme_interrupt();
340 }
341 }
342
343 /// Has command completion pending.
is_hpc_pending(&self) -> bool344 pub fn is_hpc_pending(&self) -> bool {
345 self.pcie_config.lock().hpc_sender.is_some()
346 }
347
348 /// Sets a sender for hot plug or unplug complete.
set_hpc_sender(&mut self, event: Event)349 pub fn set_hpc_sender(&mut self, event: Event) {
350 self.pcie_config
351 .lock()
352 .hpc_sender
353 .replace(HotPlugCompleteSender::new(event));
354 }
355
trigger_hp_or_pme_interrupt(&mut self)356 pub fn trigger_hp_or_pme_interrupt(&mut self) {
357 if self.pm_config.lock().should_trigger_pme() {
358 self.pcie_config.lock().hp_interrupt_pending = true;
359 self.inject_pme(self.pci_address.unwrap().pme_requester_id());
360 } else {
361 self.pcie_config.lock().trigger_hp_interrupt();
362 }
363 }
364
is_host(&self) -> bool365 pub fn is_host(&self) -> bool {
366 self.pcie_host.is_some()
367 }
368
369 /// Checks if the slot is enabled by guest and ready for hotplug events.
is_hotplug_ready(&self) -> bool370 pub fn is_hotplug_ready(&self) -> bool {
371 self.pcie_config.lock().is_hotplug_ready()
372 }
373
374 /// Gets a notification when the port is ready for hotplug. If the port is already ready, then
375 /// the notification event is triggerred immediately.
get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError>376 pub fn get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError> {
377 self.pcie_config.lock().get_ready_notification()
378 }
379
hot_unplug(&mut self)380 pub fn hot_unplug(&mut self) {
381 if let Some(host) = self.pcie_host.as_mut() {
382 host.hot_unplug()
383 }
384 }
385
is_match(&self, host_addr: PciAddress) -> Option<u8>386 pub fn is_match(&self, host_addr: PciAddress) -> Option<u8> {
387 if host_addr.bus == self.bus_range.secondary || self.pcie_host.is_none() {
388 Some(self.bus_range.secondary)
389 } else {
390 None
391 }
392 }
393
removed_downstream_valid(&self) -> bool394 pub fn removed_downstream_valid(&self) -> bool {
395 self.pcie_config.lock().removed_downstream_valid
396 }
397
mask_slot_status(&mut self, mask: u16)398 pub fn mask_slot_status(&mut self, mask: u16) {
399 self.pcie_config.lock().mask_slot_status(mask);
400 }
401
set_slot_status(&mut self, flag: u16)402 pub fn set_slot_status(&mut self, flag: u16) {
403 self.pcie_config.lock().set_slot_status(flag);
404 }
405
should_trigger_pme(&mut self) -> bool406 pub fn should_trigger_pme(&mut self) -> bool {
407 self.pm_config.lock().should_trigger_pme()
408 }
409
prepare_hotplug(&mut self)410 pub fn prepare_hotplug(&mut self) {
411 self.prepare_hotplug = true;
412 }
413 }
414
415 struct HotPlugCompleteSender {
416 sender: Event,
417 armed: bool,
418 }
419
420 impl HotPlugCompleteSender {
new(sender: Event) -> Self421 fn new(sender: Event) -> Self {
422 Self {
423 sender,
424 armed: false,
425 }
426 }
427
arm(&mut self)428 fn arm(&mut self) {
429 self.armed = true;
430 }
431
armed(&self) -> bool432 fn armed(&self) -> bool {
433 self.armed
434 }
435
signal(&self) -> base::Result<()>436 fn signal(&self) -> base::Result<()> {
437 self.sender.signal()
438 }
439 }
440
441 pub struct PcieConfig {
442 msi_config: Option<Arc<Mutex<MsiConfig>>>,
443
444 slot_control: Option<u16>,
445 slot_status: u16,
446
447 // For PcieRootPort, root_cap point to itself
448 // For PcieDownstreamPort or PciDownstreamPort, root_cap point to PcieRootPort its behind.
449 root_cap: Arc<Mutex<PcieRootCap>>,
450 port_type: PcieDevicePortType,
451
452 hpc_sender: Option<HotPlugCompleteSender>,
453 hp_interrupt_pending: bool,
454 removed_downstream_valid: bool,
455
456 enabled: bool,
457 hot_plug_ready_notifications: Vec<Event>,
458 cap_mapping: Option<PciCapMapping>,
459 }
460
461 impl PcieConfig {
new( root_cap: Arc<Mutex<PcieRootCap>>, slot_implemented: bool, port_type: PcieDevicePortType, ) -> Self462 fn new(
463 root_cap: Arc<Mutex<PcieRootCap>>,
464 slot_implemented: bool,
465 port_type: PcieDevicePortType,
466 ) -> Self {
467 PcieConfig {
468 msi_config: None,
469
470 slot_control: if slot_implemented {
471 Some(PCIE_SLTCTL_PIC_OFF | PCIE_SLTCTL_AIC_OFF)
472 } else {
473 None
474 },
475 slot_status: 0,
476
477 root_cap,
478 port_type,
479
480 hpc_sender: None,
481 hp_interrupt_pending: false,
482 removed_downstream_valid: false,
483
484 enabled: false,
485 hot_plug_ready_notifications: Vec::new(),
486 cap_mapping: None,
487 }
488 }
489
read_pcie_cap(&self, offset: usize, data: &mut u32)490 fn read_pcie_cap(&self, offset: usize, data: &mut u32) {
491 if offset == PCIE_SLTCTL_OFFSET {
492 *data = ((self.slot_status as u32) << 16) | (self.get_slot_control() as u32);
493 } else if offset == PCIE_ROOTCTL_OFFSET {
494 *data = match self.port_type {
495 PcieDevicePortType::RootPort => self.root_cap.lock().control as u32,
496 _ => 0,
497 };
498 } else if offset == PCIE_ROOTSTA_OFFSET {
499 *data = match self.port_type {
500 PcieDevicePortType::RootPort => self.root_cap.lock().status,
501 _ => 0,
502 };
503 }
504 }
505
506 // Checks if the slot is enabled by guest and ready for hotplug events.
is_hotplug_ready(&self) -> bool507 fn is_hotplug_ready(&self) -> bool {
508 // The hotplug capability flags are set when the guest enables the device. Checks all flags
509 // required by the hotplug mechanism.
510 let slot_control = self.get_slot_control();
511 (slot_control & (PCIE_SLTCTL_PDCE | PCIE_SLTCTL_ABPE)) != 0
512 && (slot_control & PCIE_SLTCTL_CCIE) != 0
513 && (slot_control & PCIE_SLTCTL_HPIE) != 0
514 }
515
516 /// Gets a notification when the port is ready for hotplug. If the port is already ready, then
517 /// the notification event is triggerred immediately.
get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError>518 fn get_ready_notification(&mut self) -> std::result::Result<Event, PciDeviceError> {
519 let event = Event::new().map_err(|e| PciDeviceError::EventCreationFailed(e.errno()))?;
520 if self.is_hotplug_ready() {
521 event
522 .signal()
523 .map_err(|e| PciDeviceError::EventSignalFailed(e.errno()))?;
524 } else {
525 self.hot_plug_ready_notifications.push(
526 event
527 .try_clone()
528 .map_err(|e| PciDeviceError::EventCloneFailed(e.errno()))?,
529 );
530 }
531 Ok(event)
532 }
533
write_pcie_cap(&mut self, offset: usize, data: &[u8])534 fn write_pcie_cap(&mut self, offset: usize, data: &[u8]) {
535 self.removed_downstream_valid = false;
536 match offset {
537 PCIE_SLTCTL_OFFSET => {
538 let value = match u16::read_from(data) {
539 Some(v) => v,
540 None => {
541 warn!("write SLTCTL isn't word, len: {}", data.len());
542 return;
543 }
544 };
545 if !self.enabled
546 && (value & (PCIE_SLTCTL_PDCE | PCIE_SLTCTL_ABPE)) != 0
547 && (value & PCIE_SLTCTL_CCIE) != 0
548 && (value & PCIE_SLTCTL_HPIE) != 0
549 {
550 // Device is getting enabled by the guest.
551 for notf_event in self.hot_plug_ready_notifications.drain(..) {
552 if let Err(e) = notf_event.signal() {
553 error!("Failed to signal hot plug ready: {}", e);
554 }
555 }
556 self.enabled = true;
557 }
558
559 // if slot is populated, power indicator is off,
560 // it will detach devices
561 let old_control = self.get_slot_control();
562 match self.slot_control.as_mut() {
563 Some(v) => *v = value,
564 None => return,
565 }
566 if (self.slot_status & PCIE_SLTSTA_PDS != 0)
567 && (value & PCIE_SLTCTL_PIC == PCIE_SLTCTL_PIC_OFF)
568 && (old_control & PCIE_SLTCTL_PIC != PCIE_SLTCTL_PIC_OFF)
569 {
570 self.removed_downstream_valid = true;
571 self.slot_status &= !PCIE_SLTSTA_PDS;
572 self.trigger_hp_interrupt();
573 }
574
575 // Guest enable hotplug interrupt and has hotplug interrupt
576 // pending, inject it right row.
577 if (old_control & PCIE_SLTCTL_HPIE == 0)
578 && (value & PCIE_SLTCTL_HPIE == PCIE_SLTCTL_HPIE)
579 && self.hp_interrupt_pending
580 {
581 self.hp_interrupt_pending = false;
582 self.trigger_hp_interrupt();
583 }
584
585 if old_control != value {
586 let old_pic_state = old_control & PCIE_SLTCTL_PIC;
587 let pic_state = value & PCIE_SLTCTL_PIC;
588 if old_pic_state == PCIE_SLTCTL_PIC_BLINK && old_pic_state != pic_state {
589 // The power indicator (PIC) is controled by the guest to indicate the power
590 // state of the slot.
591 // For successful hotplug: OFF => BLINK => (board enabled) => ON
592 // For failed hotplug: OFF => BLINK => (board enable failed) => OFF
593 // For hot unplug: ON => BLINK => (board disabled) => OFF
594 // hot (un)plug is completed at next slot status write after it changed to
595 // ON or OFF state.
596
597 if let Some(sender) = self.hpc_sender.as_mut() {
598 sender.arm();
599 }
600 }
601 self.slot_status |= PCIE_SLTSTA_CC;
602 self.trigger_cc_interrupt();
603 }
604 }
605 PCIE_SLTSTA_OFFSET => {
606 if self.slot_control.is_none() {
607 return;
608 }
609 if let Some(hpc_sender) = self.hpc_sender.as_mut() {
610 if hpc_sender.armed() {
611 if let Err(e) = hpc_sender.signal() {
612 error!("Failed to send hot un/plug complete signal: {}", e);
613 }
614 self.hpc_sender = None;
615 }
616 }
617 let value = match u16::read_from(data) {
618 Some(v) => v,
619 None => {
620 warn!("write SLTSTA isn't word, len: {}", data.len());
621 return;
622 }
623 };
624 if value & PCIE_SLTSTA_ABP != 0 {
625 self.slot_status &= !PCIE_SLTSTA_ABP;
626 }
627 if value & PCIE_SLTSTA_PFD != 0 {
628 self.slot_status &= !PCIE_SLTSTA_PFD;
629 }
630 if value & PCIE_SLTSTA_PDC != 0 {
631 self.slot_status &= !PCIE_SLTSTA_PDC;
632 }
633 if value & PCIE_SLTSTA_CC != 0 {
634 self.slot_status &= !PCIE_SLTSTA_CC;
635 }
636 if value & PCIE_SLTSTA_DLLSC != 0 {
637 self.slot_status &= !PCIE_SLTSTA_DLLSC;
638 }
639 }
640 PCIE_ROOTCTL_OFFSET => match u16::read_from(data) {
641 Some(v) => {
642 if self.port_type == PcieDevicePortType::RootPort {
643 self.root_cap.lock().control = v;
644 } else {
645 warn!("write root control register while device isn't root port");
646 }
647 }
648 None => warn!("write root control isn't word, len: {}", data.len()),
649 },
650 PCIE_ROOTSTA_OFFSET => match u32::read_from(data) {
651 Some(v) => {
652 if self.port_type == PcieDevicePortType::RootPort {
653 if v & PCIE_ROOTSTA_PME_STATUS != 0 {
654 let mut r = self.root_cap.lock();
655 if let Some(requester_id) = r.pme_pending_requester_id {
656 r.status &= !PCIE_ROOTSTA_PME_PENDING;
657 r.status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
658 r.status |= requester_id as u32;
659 r.status |= PCIE_ROOTSTA_PME_STATUS;
660 r.pme_pending_requester_id = None;
661 r.trigger_pme_interrupt();
662 } else {
663 r.status &= !PCIE_ROOTSTA_PME_STATUS;
664 }
665 }
666 } else {
667 warn!("write root status register while device isn't root port");
668 }
669 }
670 None => warn!("write root status isn't dword, len: {}", data.len()),
671 },
672 _ => (),
673 }
674 }
675
get_slot_control(&self) -> u16676 fn get_slot_control(&self) -> u16 {
677 if let Some(slot_control) = self.slot_control {
678 return slot_control;
679 }
680 0
681 }
682
trigger_cc_interrupt(&self)683 fn trigger_cc_interrupt(&self) {
684 if (self.get_slot_control() & PCIE_SLTCTL_CCIE) != 0
685 && (self.slot_status & PCIE_SLTSTA_CC) != 0
686 {
687 trigger_interrupt(&self.msi_config)
688 }
689 }
690
trigger_hp_interrupt(&mut self)691 fn trigger_hp_interrupt(&mut self) {
692 let slot_control = self.get_slot_control();
693 if (slot_control & PCIE_SLTCTL_HPIE) != 0 {
694 self.set_slot_status(PCIE_SLTSTA_PDC);
695 if (self.slot_status & slot_control & (PCIE_SLTCTL_ABPE | PCIE_SLTCTL_PDCE)) != 0 {
696 trigger_interrupt(&self.msi_config)
697 }
698 }
699 }
700
mask_slot_status(&mut self, mask: u16)701 fn mask_slot_status(&mut self, mask: u16) {
702 self.slot_status &= mask;
703 if let Some(mapping) = self.cap_mapping.as_mut() {
704 mapping.set_reg(
705 PCIE_SLTCTL_OFFSET / 4,
706 (self.slot_status as u32) << 16,
707 0xffff0000,
708 );
709 }
710 }
711
set_slot_status(&mut self, flag: u16)712 fn set_slot_status(&mut self, flag: u16) {
713 self.slot_status |= flag;
714 if let Some(mapping) = self.cap_mapping.as_mut() {
715 mapping.set_reg(
716 PCIE_SLTCTL_OFFSET / 4,
717 (self.slot_status as u32) << 16,
718 0xffff0000,
719 );
720 }
721 }
722 }
723
724 const PCIE_CONFIG_READ_MASK: [u32; PCIE_CAP_LEN / 4] = {
725 let mut arr: [u32; PCIE_CAP_LEN / 4] = [0; PCIE_CAP_LEN / 4];
726 arr[PCIE_SLTCTL_OFFSET / 4] = 0xffffffff;
727 arr[PCIE_ROOTCTL_OFFSET / 4] = 0xffffffff;
728 arr[PCIE_ROOTSTA_OFFSET / 4] = 0xffffffff;
729 arr
730 };
731
732 impl PciCapConfig for PcieConfig {
read_mask(&self) -> &'static [u32]733 fn read_mask(&self) -> &'static [u32] {
734 &PCIE_CONFIG_READ_MASK
735 }
736
read_reg(&self, reg_idx: usize) -> u32737 fn read_reg(&self, reg_idx: usize) -> u32 {
738 let mut data = 0;
739 self.read_pcie_cap(reg_idx * 4, &mut data);
740 data
741 }
742
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>743 fn write_reg(
744 &mut self,
745 reg_idx: usize,
746 offset: u64,
747 data: &[u8],
748 ) -> Option<Box<dyn PciCapConfigWriteResult>> {
749 self.write_pcie_cap(reg_idx * 4 + offset as usize, data);
750 None
751 }
752
set_cap_mapping(&mut self, mapping: PciCapMapping)753 fn set_cap_mapping(&mut self, mapping: PciCapMapping) {
754 self.cap_mapping = Some(mapping);
755 }
756 }
757
758 /// Helper trait for implementing PcieDevice where most functions
759 /// are proxied directly to a PciePort instance.
760 pub trait PciePortVariant: Send {
get_pcie_port(&self) -> &PciePort761 fn get_pcie_port(&self) -> &PciePort;
get_pcie_port_mut(&mut self) -> &mut PciePort762 fn get_pcie_port_mut(&mut self) -> &mut PciePort;
763
764 /// Called via PcieDevice.get_removed_devices
get_removed_devices_impl(&self) -> Vec<PciAddress>765 fn get_removed_devices_impl(&self) -> Vec<PciAddress>;
766
767 /// Called via PcieDevice.hotplug_implemented
hotplug_implemented_impl(&self) -> bool768 fn hotplug_implemented_impl(&self) -> bool;
769
770 /// Called via PcieDevice.hotplug
hotplugged_impl(&self) -> bool771 fn hotplugged_impl(&self) -> bool;
772 }
773
774 impl<T: PciePortVariant> PcieDevice for T {
get_device_id(&self) -> u16775 fn get_device_id(&self) -> u16 {
776 self.get_pcie_port().get_device_id()
777 }
778
debug_label(&self) -> String779 fn debug_label(&self) -> String {
780 self.get_pcie_port().debug_label()
781 }
782
preferred_address(&self) -> Option<PciAddress>783 fn preferred_address(&self) -> Option<PciAddress> {
784 self.get_pcie_port().preferred_address()
785 }
786
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>787 fn allocate_address(
788 &mut self,
789 resources: &mut SystemAllocator,
790 ) -> std::result::Result<PciAddress, PciDeviceError> {
791 self.get_pcie_port_mut().allocate_address(resources)
792 }
793
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)794 fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
795 self.get_pcie_port_mut().clone_interrupt(msi_config);
796 }
797
read_config(&self, reg_idx: usize, data: &mut u32)798 fn read_config(&self, reg_idx: usize, data: &mut u32) {
799 self.get_pcie_port().read_config(reg_idx, data);
800 }
801
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])802 fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
803 self.get_pcie_port_mut().write_config(reg_idx, offset, data);
804 }
805
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>806 fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)> {
807 self.get_pcie_port().get_caps()
808 }
809
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)810 fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>) {
811 self.get_pcie_port_mut().handle_cap_write_result(res)
812 }
813
get_bus_range(&self) -> Option<PciBridgeBusRange>814 fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
815 self.get_pcie_port().get_bus_range()
816 }
817
get_removed_devices(&self) -> Vec<PciAddress>818 fn get_removed_devices(&self) -> Vec<PciAddress> {
819 self.get_removed_devices_impl()
820 }
821
hotplug_implemented(&self) -> bool822 fn hotplug_implemented(&self) -> bool {
823 self.hotplug_implemented_impl()
824 }
825
hotplugged(&self) -> bool826 fn hotplugged(&self) -> bool {
827 self.hotplugged_impl()
828 }
829
get_bridge_window_size(&self) -> (u64, u64)830 fn get_bridge_window_size(&self) -> (u64, u64) {
831 self.get_pcie_port().get_bridge_window_size()
832 }
833 }
834