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