refactor pci stage 3

This commit is contained in:
Runji Wang 2020-06-11 01:39:10 +08:00
parent 1cad730bde
commit 8c70da4ab4
7 changed files with 52 additions and 92 deletions

View File

@ -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"]

View File

@ -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;

View File

@ -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>) {

View File

@ -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;
}
}
}
}

View File

@ -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()
}

View File

@ -10,6 +10,7 @@
#![feature(ptr_offset_from)]
#![feature(range_is_empty)]
#![feature(new_uninit)]
#![feature(const_in_array_repeat_expressions)]
extern crate alloc;

View File

@ -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
}