forked from rcore-os/zCore
refactor pci stage 3
This commit is contained in:
parent
1cad730bde
commit
8c70da4ab4
|
@ -345,10 +345,6 @@ impl InterruptManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn irq_handle(irq: u8) {
|
||||
InterruptManager::handle(irq)
|
||||
}
|
||||
|
||||
/// Get platform specific information.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_vdso_constants"]
|
||||
|
|
|
@ -203,7 +203,7 @@ fn spawn(thread: Arc<Thread>) {
|
|||
match cx.trap_num {
|
||||
0x100 => exit = handle_syscall(&thread, &mut cx.general).await,
|
||||
0x20..=0x3f => {
|
||||
kernel_hal::irq_handle(cx.trap_num as u8);
|
||||
kernel_hal::InterruptManager::handle(cx.trap_num as u8);
|
||||
if cx.trap_num == 0x20 {
|
||||
EXCEPTIONS_TIMER.add(1);
|
||||
kernel_hal::yield_now().await;
|
||||
|
|
|
@ -39,23 +39,21 @@ pub struct PciMsiBlock {
|
|||
}
|
||||
|
||||
impl PciMsiBlock {
|
||||
pub fn allocate_msi_block(irq_num: u32) -> ZxResult<Self> {
|
||||
pub fn allocate(irq_num: u32) -> ZxResult<Self> {
|
||||
if irq_num == 0 || irq_num > 32 {
|
||||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
if let Some((start, size)) = InterruptManager::allocate_block(irq_num) {
|
||||
Ok(PciMsiBlock {
|
||||
target_addr: (0xFEE0_0000 | 0x08) & !0x4,
|
||||
target_data: start as u32,
|
||||
base_irq: start as u32,
|
||||
num_irq: size as u32,
|
||||
allocated: true,
|
||||
})
|
||||
} else {
|
||||
Err(ZxError::NO_RESOURCES)
|
||||
}
|
||||
let (start, size) =
|
||||
InterruptManager::allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
|
||||
Ok(PciMsiBlock {
|
||||
target_addr: (0xFEE0_0000 | 0x08) & !0x4,
|
||||
target_data: start as u32,
|
||||
base_irq: start as u32,
|
||||
num_irq: size as u32,
|
||||
allocated: true,
|
||||
})
|
||||
}
|
||||
pub fn free_msi_block(&self) {
|
||||
pub fn free(&self) {
|
||||
InterruptManager::free_block(self.base_irq, self.num_irq)
|
||||
}
|
||||
pub fn register_handler(&self, msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) {
|
||||
|
|
|
@ -73,19 +73,6 @@ pub struct MappedEcamRegion {
|
|||
pub vaddr: u64,
|
||||
}
|
||||
|
||||
use numeric_enum_macro::*;
|
||||
numeric_enum! {
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum PcieIrqMode {
|
||||
Disabled = 0,
|
||||
Legacy = 1,
|
||||
Msi = 2,
|
||||
MsiX = 3,
|
||||
Count = 4,
|
||||
}
|
||||
}
|
||||
|
||||
pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::<PciInitArgsAddrWindows>()
|
||||
* PCI_INIT_ARG_MAX_ECAM_WINDOWS
|
||||
+ core::mem::size_of::<PciInitArgsHeader>();
|
||||
|
@ -105,22 +92,24 @@ use super::*;
|
|||
use alloc::sync::*;
|
||||
use kernel_hal::InterruptManager;
|
||||
|
||||
pub fn pci_configure_interrupt(arg_header: &mut PciInitArgsHeader) -> ZxResult {
|
||||
for i in 0..arg_header.num_irqs as usize {
|
||||
let irq = &mut arg_header.irqs[i];
|
||||
let global_irq = irq.global_irq;
|
||||
if !is_valid_interrupt(global_irq) {
|
||||
irq.global_irq = PCI_NO_IRQ_MAPPING;
|
||||
pci_irq_swizzle_lut_remove_irq(&mut arg_header.dev_pin_to_global_irq, global_irq);
|
||||
} else {
|
||||
irq_configure(
|
||||
global_irq,
|
||||
irq.level_triggered, /* Trigger mode */
|
||||
irq.active_high, /* Polarity */
|
||||
)?;
|
||||
impl PciInitArgsHeader {
|
||||
pub fn configure_interrupt(&mut self) -> ZxResult {
|
||||
for i in 0..self.num_irqs as usize {
|
||||
let irq = &mut self.irqs[i];
|
||||
let global_irq = irq.global_irq;
|
||||
if !is_valid_interrupt(global_irq) {
|
||||
irq.global_irq = PCI_NO_IRQ_MAPPING;
|
||||
self.dev_pin_to_global_irq.remove_irq(global_irq);
|
||||
} else {
|
||||
irq_configure(
|
||||
global_irq,
|
||||
irq.level_triggered, /* Trigger mode */
|
||||
irq.active_high, /* Polarity */
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_valid_interrupt(irq: u32) -> bool {
|
||||
|
@ -158,14 +147,14 @@ impl PciIrqSwizzleLut {
|
|||
Ok(irq as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pci_irq_swizzle_lut_remove_irq(lut: &mut PciIrqSwizzleLut, irq: u32) {
|
||||
for dev in lut.0.iter_mut() {
|
||||
for func in dev.iter_mut() {
|
||||
for pin in func.iter_mut() {
|
||||
if *pin == irq {
|
||||
*pin = PCI_NO_IRQ_MAPPING;
|
||||
fn remove_irq(&mut self, irq: u32) {
|
||||
for dev in self.0.iter_mut() {
|
||||
for func in dev.iter_mut() {
|
||||
for pin in func.iter_mut() {
|
||||
if *pin == irq {
|
||||
*pin = PCI_NO_IRQ_MAPPING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use super::{caps::*, config::*, *};
|
||||
use crate::vm::PAGE_SIZE;
|
||||
use alloc::{boxed::Box, sync::*, vec, vec::Vec};
|
||||
use alloc::{boxed::Box, sync::*, vec::Vec};
|
||||
use core::convert::TryFrom;
|
||||
use kernel_hal::InterruptManager;
|
||||
use numeric_enum_macro::*;
|
||||
|
@ -28,13 +28,13 @@ numeric_enum! {
|
|||
}
|
||||
|
||||
pub struct PcieUpstream {
|
||||
pub managed_bus_id: usize,
|
||||
pub inner: Mutex<PcieUpstreamInner>,
|
||||
managed_bus_id: usize,
|
||||
inner: Mutex<PcieUpstreamInner>,
|
||||
}
|
||||
|
||||
pub struct PcieUpstreamInner {
|
||||
pub weak_super: Weak<dyn IPciNode>,
|
||||
pub downstream: Vec<Option<Arc<dyn IPciNode>>>,
|
||||
struct PcieUpstreamInner {
|
||||
weak_super: Weak<dyn IPciNode>,
|
||||
downstream: [Option<Arc<dyn IPciNode>>; PCI_MAX_FUNCTIONS_PER_BUS],
|
||||
}
|
||||
|
||||
impl PcieUpstream {
|
||||
|
@ -43,10 +43,11 @@ impl PcieUpstream {
|
|||
managed_bus_id,
|
||||
inner: Mutex::new(PcieUpstreamInner {
|
||||
weak_super: Weak::<PciRoot>::new(),
|
||||
downstream: vec![None; PCI_MAX_FUNCTIONS_PER_BUS],
|
||||
downstream: [None; PCI_MAX_FUNCTIONS_PER_BUS],
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn scan_downstream(&self, driver: &PCIeBusDriver) {
|
||||
for dev_id in 0..PCI_MAX_DEVICES_PER_BUS {
|
||||
for func_id in 0..PCI_MAX_FUNCTIONS_PER_DEVICE {
|
||||
|
@ -616,7 +617,7 @@ impl PcieDevice {
|
|||
}
|
||||
let upstream = upstream.upgrade();
|
||||
if let Some(up_ptr) = upstream {
|
||||
if let Some(up) = up_ptr.to_root() {
|
||||
if let Some(up) = up_ptr.as_root() {
|
||||
return up.swizzle(dev_id, func_id, pin as usize);
|
||||
}
|
||||
}
|
||||
|
@ -927,7 +928,7 @@ impl PcieDevice {
|
|||
} else {
|
||||
false
|
||||
};
|
||||
match PciMsiBlock::allocate_msi_block(irq) {
|
||||
match PciMsiBlock::allocate(irq) {
|
||||
Ok(block) => *msi.irq_block.lock() = block,
|
||||
Err(ex) => {
|
||||
self.leave_msi_irq_mode(inner);
|
||||
|
@ -962,7 +963,7 @@ impl PcieDevice {
|
|||
for i in 0..block.num_irq {
|
||||
block.register_handler(i, Box::new(|| {}));
|
||||
}
|
||||
block.free_msi_block();
|
||||
block.free();
|
||||
}
|
||||
}
|
||||
self.reset_irq_bookkeeping(inner);
|
||||
|
@ -1159,9 +1160,9 @@ pub trait IPciNode: Send + Sync {
|
|||
fn node_type(&self) -> PciNodeType;
|
||||
fn device(&self) -> Arc<PcieDevice>;
|
||||
fn as_upstream(&self) -> Option<Arc<PcieUpstream>>;
|
||||
fn to_root(&self) -> Option<&PciRoot>;
|
||||
fn to_device(&mut self) -> Option<&mut PciDeviceNode>;
|
||||
fn to_bridge(&mut self) -> Option<&mut PciBridge>;
|
||||
fn as_root(&self) -> Option<&PciRoot> {
|
||||
None
|
||||
}
|
||||
fn allocate_bars(&self) -> ZxResult {
|
||||
unimplemented!("IPciNode.allocate_bars")
|
||||
}
|
||||
|
@ -1237,15 +1238,9 @@ impl IPciNode for PciRoot {
|
|||
fn as_upstream(&self) -> Option<Arc<PcieUpstream>> {
|
||||
Some(self.base_upstream.clone())
|
||||
}
|
||||
fn to_root(&self) -> Option<&PciRoot> {
|
||||
fn as_root(&self) -> Option<&PciRoot> {
|
||||
Some(self)
|
||||
}
|
||||
fn to_device(&mut self) -> Option<&mut PciDeviceNode> {
|
||||
None
|
||||
}
|
||||
fn to_bridge(&mut self) -> Option<&mut PciBridge> {
|
||||
None
|
||||
}
|
||||
fn allocate_bars(&self) -> ZxResult {
|
||||
unimplemented!();
|
||||
}
|
||||
|
@ -1298,15 +1293,6 @@ impl IPciNode for PciDeviceNode {
|
|||
fn as_upstream(&self) -> Option<Arc<PcieUpstream>> {
|
||||
None
|
||||
}
|
||||
fn to_root(&self) -> Option<&PciRoot> {
|
||||
None
|
||||
}
|
||||
fn to_device(&mut self) -> Option<&mut PciDeviceNode> {
|
||||
Some(self)
|
||||
}
|
||||
fn to_bridge(&mut self) -> Option<&mut PciBridge> {
|
||||
None
|
||||
}
|
||||
fn allocate_bars(&self) -> ZxResult {
|
||||
self.base_device.allocate_bars()
|
||||
}
|
||||
|
@ -1421,15 +1407,6 @@ impl IPciNode for PciBridge {
|
|||
fn as_upstream(&self) -> Option<Arc<PcieUpstream>> {
|
||||
Some(self.base_upstream.clone())
|
||||
}
|
||||
fn to_root(&self) -> Option<&PciRoot> {
|
||||
None
|
||||
}
|
||||
fn to_device(&mut self) -> Option<&mut PciDeviceNode> {
|
||||
None
|
||||
}
|
||||
fn to_bridge(&mut self) -> Option<&mut PciBridge> {
|
||||
Some(self)
|
||||
}
|
||||
fn pf_mmio_regions(&self) -> Arc<Mutex<RegionAllocator>> {
|
||||
self.pf_mmio.clone()
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#![feature(ptr_offset_from)]
|
||||
#![feature(range_is_empty)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(const_in_array_repeat_expressions)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
|
|
@ -87,8 +87,7 @@ impl Syscall<'_> {
|
|||
}
|
||||
let mut addr_windows = UserInPtr::<PciInitArgsAddrWindows>::from(init_buf + HEADER_SIZE)
|
||||
.read_array(arg_header.addr_window_count as usize)?;
|
||||
// Configure interrupts
|
||||
pci_configure_interrupt(&mut arg_header)?;
|
||||
arg_header.configure_interrupt()?;
|
||||
if arg_header.addr_window_count != 1 {
|
||||
return Err(ZxError::INVALID_ARGS); // for non DesignWare Controller
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue