forked from rcore-os/zCore
commit
de809efca2
|
@ -88,8 +88,7 @@ pub fn irq_handle(irq: u8) {
|
|||
}
|
||||
|
||||
/// Add a handle to IRQ table. Return the specified irq or an allocated irq on success
|
||||
#[export_name = "hal_irq_add_handle"]
|
||||
pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
||||
fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
||||
info!("IRQ add handle {:#x?}", irq);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
// allocate a valid irq number
|
||||
|
@ -115,8 +114,7 @@ pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
|||
}
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_remove_handle"]
|
||||
pub fn irq_remove_handle(irq: u8) -> bool {
|
||||
fn irq_remove_handle(irq: u8) -> bool {
|
||||
info!("IRQ remove handle {:#x?}", irq);
|
||||
let irq = irq as usize;
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
|
@ -129,50 +127,6 @@ pub fn irq_remove_handle(irq: u8) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[export_name = "hal_irq_allocate_block"]
|
||||
pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
|
||||
info!("hal_irq_allocate_block: count={:#x?}", irq_num);
|
||||
let irq_num = u32::next_power_of_two(irq_num) as usize;
|
||||
let mut irq_start = 0x20;
|
||||
let mut irq_cur = irq_start;
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
while irq_cur < TABLE_SIZE && irq_cur < irq_start + irq_num {
|
||||
if table[irq_cur].is_none() {
|
||||
irq_cur += 1;
|
||||
} else {
|
||||
irq_start = (irq_cur - irq_cur % irq_num) + irq_num;
|
||||
irq_cur = irq_start;
|
||||
}
|
||||
}
|
||||
for i in irq_start..irq_start + irq_num {
|
||||
table[i] = Some(Box::new(|| {}));
|
||||
}
|
||||
info!(
|
||||
"hal_irq_allocate_block: start={:#x?} num={:#x?}",
|
||||
irq_start, irq_num
|
||||
);
|
||||
Some((irq_start, irq_num))
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_free_block"]
|
||||
pub fn free_block(irq_start: u32, irq_num: u32) {
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
for i in irq_start..irq_start + irq_num {
|
||||
table[i as usize] = None;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[export_name = "hal_irq_overwrite_handler"]
|
||||
pub fn overwrite_handler(msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) -> bool {
|
||||
info!("IRQ overwrite handle {:#x?}", msi_id);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
let set = table[msi_id as usize].is_none();
|
||||
table[msi_id as usize] = Some(handle);
|
||||
set
|
||||
}
|
||||
|
||||
fn breakpoint(sepc: &mut usize) {
|
||||
bare_println!("Exception::Breakpoint: A breakpoint set @0x{:x} ", sepc);
|
||||
|
||||
|
|
|
@ -121,8 +121,8 @@ pub fn irq_handle(irq: u8) {
|
|||
}
|
||||
}
|
||||
|
||||
#[export_name = "hal_ioapic_set_handle"]
|
||||
pub fn set_handle(global_irq: u32, handle: InterruptHandle) -> Option<u8> {
|
||||
#[export_name = "hal_irq_register_handler"]
|
||||
pub fn register_irq_handler(global_irq: u32, handle: InterruptHandle) -> Option<u32> {
|
||||
info!("set_handle irq={:#x?}", global_irq);
|
||||
// if global_irq == 1 {
|
||||
// irq_add_handle(global_irq as u8 + IRQ0, handle);
|
||||
|
@ -147,12 +147,12 @@ pub fn set_handle(global_irq: u32, handle: InterruptHandle) -> Option<u8> {
|
|||
global_irq, x
|
||||
);
|
||||
ioapic.set_irq_vector(offset, x);
|
||||
x
|
||||
x as u32
|
||||
})
|
||||
}
|
||||
|
||||
#[export_name = "hal_ioapic_reset_handle"]
|
||||
pub fn reset_handle(global_irq: u32) -> bool {
|
||||
#[export_name = "hal_irq_unregister_handler"]
|
||||
pub fn unregister_irq_handler(global_irq: u32) -> bool {
|
||||
info!("reset_handle");
|
||||
let ioapic_info = if let Some(x) = get_ioapic(global_irq) {
|
||||
x
|
||||
|
@ -171,8 +171,7 @@ pub fn reset_handle(global_irq: u32) -> bool {
|
|||
}
|
||||
|
||||
/// Add a handle to IRQ table. Return the specified irq or an allocated irq on success
|
||||
#[export_name = "hal_irq_add_handle"]
|
||||
pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
||||
fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
||||
info!("IRQ add handle {:#x?}", irq);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
// allocate a valid irq number
|
||||
|
@ -196,8 +195,7 @@ pub fn irq_add_handle(irq: u8, handle: InterruptHandle) -> Option<u8> {
|
|||
}
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_remove_handle"]
|
||||
pub fn irq_remove_handle(irq: u8) -> bool {
|
||||
fn irq_remove_handle(irq: u8) -> bool {
|
||||
// TODO: ioapic redirection entries associated with this should be reset.
|
||||
info!("IRQ remove handle {:#x?}", irq);
|
||||
let irq = irq as usize;
|
||||
|
@ -211,8 +209,16 @@ pub fn irq_remove_handle(irq: u8) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_allocate_block"]
|
||||
pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
|
||||
fn irq_overwrite_handler(irq: u8, handle: Box<dyn Fn() + Send + Sync>) -> bool {
|
||||
info!("IRQ overwrite handle {:#x?}", irq);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
let set = table[irq as usize].is_none();
|
||||
table[irq as usize] = Some(handle);
|
||||
set
|
||||
}
|
||||
|
||||
#[export_name = "hal_msi_allocate_block"]
|
||||
pub fn msi_allocate_block(irq_num: u32) -> Option<(usize, usize)> {
|
||||
info!("hal_irq_allocate_block: count={:#x?}", irq_num);
|
||||
let irq_num = u32::next_power_of_two(irq_num) as usize;
|
||||
let mut irq_start = 0x20;
|
||||
|
@ -236,21 +242,22 @@ pub fn allocate_block(irq_num: u32) -> Option<(usize, usize)> {
|
|||
Some((irq_start, irq_num))
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_free_block"]
|
||||
pub fn free_block(irq_start: u32, irq_num: u32) {
|
||||
#[export_name = "hal_msi_free_block"]
|
||||
pub fn msi_free_block(irq_start: u32, irq_num: u32) {
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
for i in irq_start..irq_start + irq_num {
|
||||
table[i as usize] = None;
|
||||
}
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_overwrite_handler"]
|
||||
pub fn overwrite_handler(msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) -> bool {
|
||||
info!("IRQ overwrite handle {:#x?}", msi_id);
|
||||
let mut table = IRQ_TABLE.lock();
|
||||
let set = table[msi_id as usize].is_none();
|
||||
table[msi_id as usize] = Some(handle);
|
||||
set
|
||||
#[export_name = "hal_msi_register_handler"]
|
||||
pub fn msi_register_handler(
|
||||
irq_start: u32,
|
||||
_irq_num: u32,
|
||||
msi_id: u32,
|
||||
handle: Box<dyn Fn() + Send + Sync>,
|
||||
) {
|
||||
irq_overwrite_handler((irq_start + msi_id) as u8, handle);
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_enable"]
|
||||
|
@ -283,26 +290,21 @@ pub fn irq_disable(irq: u32) {
|
|||
}
|
||||
|
||||
#[export_name = "hal_irq_configure"]
|
||||
pub fn irq_configure(
|
||||
global_irq: u32,
|
||||
vector: u8,
|
||||
dest: u8,
|
||||
level_trig: bool,
|
||||
active_high: bool,
|
||||
) -> bool {
|
||||
pub fn irq_configure(vector: u32, trig_mode: bool, polarity: bool) -> bool {
|
||||
info!(
|
||||
"irq_configure: irq={:#x?}, vector={:#x?}, dest={:#x?}, level_trig={:#x?}, active_high={:#x?}",
|
||||
global_irq, vector, dest, level_trig, active_high
|
||||
"irq_configure: vector={:#x?}, trig_mode={:#x?}, polarity={:#x?}",
|
||||
vector, trig_mode, polarity
|
||||
);
|
||||
get_ioapic(global_irq)
|
||||
let dest = super::apic_local_id();
|
||||
get_ioapic(vector)
|
||||
.map(|x| {
|
||||
let mut ioapic = ioapic_controller(&x);
|
||||
ioapic.config(
|
||||
(global_irq - x.global_system_interrupt_base) as u8,
|
||||
vector,
|
||||
(vector - x.global_system_interrupt_base) as u8,
|
||||
0,
|
||||
dest,
|
||||
level_trig,
|
||||
active_high,
|
||||
trig_mode,
|
||||
polarity,
|
||||
false, /* physical */
|
||||
true, /* mask */
|
||||
);
|
||||
|
@ -310,8 +312,7 @@ pub fn irq_configure(
|
|||
.is_some()
|
||||
}
|
||||
|
||||
#[export_name = "hal_irq_maxinstr"]
|
||||
pub fn ioapic_maxinstr(ioapic_addr: u32) -> Option<u8> {
|
||||
fn ioapic_maxinstr(ioapic_addr: u32) -> Option<u8> {
|
||||
let mut table = MAX_INSTR_TABLE.lock();
|
||||
for (addr, v) in table.iter() {
|
||||
if *addr == ioapic_addr as usize {
|
||||
|
@ -329,7 +330,7 @@ lazy_static! {
|
|||
}
|
||||
|
||||
#[export_name = "hal_irq_isvalid"]
|
||||
pub fn irq_is_valid(irq: u32) -> bool {
|
||||
pub fn is_valid_irq(irq: u32) -> bool {
|
||||
trace!("irq_is_valid: irq={:#x?}", irq);
|
||||
get_ioapic(irq).is_some()
|
||||
}
|
||||
|
|
|
@ -315,86 +315,76 @@ pub fn timer_tick() {
|
|||
|
||||
pub struct InterruptManager {}
|
||||
impl InterruptManager {
|
||||
/// Handle IRQ.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_handle"]
|
||||
pub fn handle(_irq: u8) {
|
||||
unimplemented!()
|
||||
}
|
||||
///
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_ioapic_set_handle"]
|
||||
pub fn set_ioapic_handle(_global_irq: u32, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Add an interrupt handle to an irq
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_add_handle"]
|
||||
pub fn add_handle(_global_irq: u8, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
///
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_ioapic_reset_handle"]
|
||||
pub fn reset_ioapic_handle(_global_irq: u32) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Remove the interrupt handle of an irq
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_remove_handle"]
|
||||
pub fn remove_handle(_irq: u8) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Allocate contiguous positions for irq
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_allocate_block"]
|
||||
pub fn allocate_block(_irq_num: u32) -> Option<(usize, usize)> {
|
||||
unimplemented!()
|
||||
}
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_free_block"]
|
||||
pub fn free_block(_irq_start: u32, _irq_num: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_overwrite_handler"]
|
||||
pub fn overwrite_handler(_msi_id: u32, _handle: Box<dyn Fn() + Send + Sync>) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Enable IRQ.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_enable"]
|
||||
pub fn enable(_global_irq: u32) {
|
||||
pub fn enable_irq(_vector: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Disable IRQ.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_disable"]
|
||||
pub fn disable(_global_irq: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Get IO APIC maxinstr
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_maxinstr"]
|
||||
pub fn maxinstr(_irq: u32) -> Option<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_configure"]
|
||||
pub fn configure(
|
||||
_irq: u32,
|
||||
_vector: u8,
|
||||
_dest: u8,
|
||||
_level_trig: bool,
|
||||
_active_high: bool,
|
||||
) -> bool {
|
||||
pub fn disable_irq(_vector: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Is a valid IRQ number.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_isvalid"]
|
||||
pub fn is_valid(_irq: u32) -> bool {
|
||||
pub fn is_valid_irq(_vector: u32) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Configure the specified interrupt vector. If it is invoked, it muust be
|
||||
/// invoked prior to interrupt registration.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_configure"]
|
||||
pub fn configure_irq(_vector: u32, _trig_mode: bool, _polarity: bool) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Add an interrupt handle to an IRQ
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_register_handler"]
|
||||
pub fn register_irq_handler(_vector: u32, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u32> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Remove the interrupt handle to an IRQ
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_unregister_handler"]
|
||||
pub fn unregister_irq_handler(_vector: u32) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Handle IRQ.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_irq_handle"]
|
||||
pub fn handle_irq(_vector: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Method used for platform allocation of blocks of MSI and MSI-X compatible
|
||||
/// IRQ targets.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_msi_allocate_block"]
|
||||
pub fn msi_allocate_block(_irq_num: u32) -> Option<(usize, usize)> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block().
|
||||
/// This does not unregister IRQ handlers.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_msi_free_block"]
|
||||
pub fn msi_free_block(_irq_start: u32, _irq_num: u32) {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Register a handler function for a given msi_id within an msi_block_t. Passing a
|
||||
/// NULL handler will effectively unregister a handler for a given msi_id within the
|
||||
/// block.
|
||||
#[linkage = "weak"]
|
||||
#[export_name = "hal_msi_register_handler"]
|
||||
pub fn msi_register_handler(
|
||||
_irq_start: u32,
|
||||
_irq_num: u32,
|
||||
_msi_id: u32,
|
||||
_handle: Box<dyn Fn() + Send + Sync>,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ async fn new_thread(thread: CurrentThread) {
|
|||
match cx.trap_num {
|
||||
0x100 => handle_syscall(&thread, &mut cx.general).await,
|
||||
0x20..=0x3f => {
|
||||
kernel_hal::InterruptManager::handle(cx.trap_num as u8);
|
||||
kernel_hal::InterruptManager::handle_irq(cx.trap_num as u32);
|
||||
if cx.trap_num == 0x20 {
|
||||
kernel_hal::yield_now().await;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ async fn new_thread(thread: CurrentThread) {
|
|||
match trap_num {
|
||||
//Irq
|
||||
0 | 4 | 5 | 8 | 9 => {
|
||||
kernel_hal::InterruptManager::handle(trap_num as u8);
|
||||
kernel_hal::InterruptManager::handle_irq(trap_num as u32);
|
||||
|
||||
//Timer
|
||||
if trap_num == 4 || trap_num == 5 {
|
||||
|
@ -144,7 +144,7 @@ async fn new_thread(thread: CurrentThread) {
|
|||
kernel_hal::yield_now().await;
|
||||
}
|
||||
|
||||
//kernel_hal::InterruptManager::handle(trap_num as u8);
|
||||
//kernel_hal::InterruptManager::handle_irq(trap_num as u32);
|
||||
}
|
||||
_ => panic!(
|
||||
"not supported pid: {} interrupt {} from user mode. {:#x?}",
|
||||
|
|
|
@ -53,3 +53,7 @@
|
|||
/libc-test/src/functional/popen.exe
|
||||
/libc-test/src/regression/statvfs-static.exe
|
||||
/libc-test/src/regression/sem_close-unmap-static.exe
|
||||
/libc-test/src/regression/execle-env-static.exe
|
||||
/libc-test/src/regression/execle-env.exe
|
||||
/libc-test/src/functional/pthread_tsd-static.exe
|
||||
/libc-test/src/functional/tls_init-static.exe
|
||||
|
|
|
@ -217,7 +217,7 @@ async fn new_thread(thread: CurrentThread) {
|
|||
match trap_num {
|
||||
0x100 => handle_syscall(&thread).await,
|
||||
0x20..=0x3f => {
|
||||
kernel_hal::InterruptManager::handle(trap_num as u8);
|
||||
kernel_hal::InterruptManager::handle_irq(trap_num as u32);
|
||||
if trap_num == 0x20 {
|
||||
EXCEPTIONS_TIMER.add(1);
|
||||
kernel_hal::yield_now().await;
|
||||
|
|
|
@ -25,6 +25,7 @@ xmas-elf = { version = "0.7", optional = true }
|
|||
region-alloc = { git = "https://github.com/rzswh/region-allocator", rev = "122c7a71" }
|
||||
lazy_static = { version = "1.4", features = ["spin_no_std" ] }
|
||||
acpi = "1.1"
|
||||
cfg-if = "1.0"
|
||||
#rvm = { git = "https://github.com/rcore-os/RVM", rev = "382fc60", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -25,14 +25,14 @@ impl InterruptTrait for EventInterrupt {
|
|||
fn mask(&self) {
|
||||
let inner = self.inner.lock();
|
||||
if inner.register {
|
||||
InterruptManager::disable(self.vector as u32);
|
||||
InterruptManager::disable_irq(self.vector as u32);
|
||||
}
|
||||
}
|
||||
|
||||
fn unmask(&self) {
|
||||
let inner = self.inner.lock();
|
||||
if inner.register {
|
||||
InterruptManager::enable(self.vector as u32);
|
||||
InterruptManager::enable_irq(self.vector as u32);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl InterruptTrait for EventInterrupt {
|
|||
if inner.register {
|
||||
return Err(ZxError::ALREADY_BOUND);
|
||||
}
|
||||
if InterruptManager::set_ioapic_handle(self.vector, handle).is_some() {
|
||||
if InterruptManager::register_irq_handler(self.vector, handle).is_some() {
|
||||
inner.register = true;
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -54,7 +54,7 @@ impl InterruptTrait for EventInterrupt {
|
|||
if !inner.register {
|
||||
return Ok(());
|
||||
}
|
||||
if InterruptManager::reset_ioapic_handle(self.vector) {
|
||||
if InterruptManager::unregister_irq_handler(self.vector) {
|
||||
inner.register = false;
|
||||
Ok(())
|
||||
} else {
|
||||
|
|
|
@ -2,7 +2,7 @@ use {
|
|||
self::event_interrupt::*,
|
||||
self::pci_interrupt::*,
|
||||
self::virtual_interrupt::*,
|
||||
super::IPciNode,
|
||||
crate::dev::pci::IPciNode,
|
||||
crate::object::*,
|
||||
crate::signal::*,
|
||||
alloc::{boxed::Box, sync::Arc},
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
use {super::super::pci::PCIE_IRQRET_MASK, super::super::IPciNode, super::*, spin::Mutex};
|
||||
use alloc::{boxed::Box, sync::Arc};
|
||||
use spin::Mutex;
|
||||
|
||||
use super::InterruptTrait;
|
||||
use crate::dev::pci::{constants::PCIE_IRQRET_MASK, IPciNode};
|
||||
use crate::{ZxError, ZxResult};
|
||||
|
||||
pub struct PciInterrupt {
|
||||
device: Arc<dyn IPciNode>,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
//! Objects for Device Drivers.
|
||||
use super::*;
|
||||
|
||||
mod bti;
|
||||
mod interrupt;
|
||||
mod iommu;
|
||||
mod pci;
|
||||
pub mod pci;
|
||||
mod pmt;
|
||||
mod resource;
|
||||
|
||||
pub use self::{bti::*, interrupt::*, iommu::*, pci::*, pmt::*, resource::*};
|
||||
pub use self::{bti::*, interrupt::*, iommu::*, pmt::*, resource::*};
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
use super::super::*;
|
||||
use super::config::*;
|
||||
use super::*;
|
||||
use super::nodes::{
|
||||
IPciNode, PciNodeType, PciRoot, PcieBarInfo, PcieIrqMode, PcieIrqModeCaps,
|
||||
SharedLegacyIrqHandler,
|
||||
};
|
||||
use super::{
|
||||
config::PciConfig, constants::*, pci_init_args::PciIrqSwizzleLut, pio::pci_bdf_raw_addr,
|
||||
MappedEcamRegion, PciAddrSpace, PciEcamRegion,
|
||||
};
|
||||
use crate::dev::Interrupt;
|
||||
use crate::object::*;
|
||||
use crate::vm::{kernel_allocate_physical, CachePolicy, MMUFlags, PhysAddr, VirtAddr};
|
||||
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
|
||||
use crate::ZxResult;
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use alloc::{collections::BTreeMap, vec::Vec};
|
||||
use core::cmp::min;
|
||||
use core::marker::{Send, Sync};
|
||||
use lazy_static::*;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::super::{ZxError, ZxResult};
|
||||
use super::config::PciConfig;
|
||||
use super::nodes::PcieDeviceType;
|
||||
use super::{config::PciConfig, nodes::PcieDeviceType};
|
||||
use crate::{ZxError, ZxResult};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::convert::TryFrom;
|
||||
use kernel_hal::InterruptManager;
|
||||
|
@ -47,7 +47,7 @@ impl PciMsiBlock {
|
|||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
let (start, size) =
|
||||
InterruptManager::allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
|
||||
InterruptManager::msi_allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
|
||||
Ok(PciMsiBlock {
|
||||
target_addr: (0xFEE0_0000 | 0x08) & !0x4,
|
||||
target_data: start as u32,
|
||||
|
@ -57,12 +57,12 @@ impl PciMsiBlock {
|
|||
})
|
||||
}
|
||||
pub fn free(&self) {
|
||||
InterruptManager::free_block(self.base_irq, self.num_irq)
|
||||
InterruptManager::msi_free_block(self.base_irq, self.num_irq)
|
||||
}
|
||||
pub fn register_handler(&self, msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) {
|
||||
assert!(self.allocated);
|
||||
assert!(msi_id < self.num_irq);
|
||||
InterruptManager::overwrite_handler(self.base_irq + msi_id, handle);
|
||||
InterruptManager::msi_register_handler(self.base_irq, self.num_irq, msi_id, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::*;
|
||||
use numeric_enum_macro::*;
|
||||
use super::pio::{pio_config_read_addr, pio_config_write_addr};
|
||||
use super::PciAddrSpace;
|
||||
use numeric_enum_macro::numeric_enum;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PciConfig {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(missing_docs)]
|
||||
|
||||
mod bus;
|
||||
mod caps;
|
||||
mod config;
|
||||
|
@ -5,17 +7,11 @@ mod nodes;
|
|||
pub mod pci_init_args;
|
||||
mod pio;
|
||||
|
||||
use super::*;
|
||||
use alloc::sync::*;
|
||||
pub(crate) use nodes::*;
|
||||
use pci_init_args::*;
|
||||
use pio::*;
|
||||
|
||||
pub use self::bus::{
|
||||
MmioPcieAddressProvider, PCIeBusDriver, PcieDeviceInfo, PcieDeviceKObject,
|
||||
PioPcieAddressProvider,
|
||||
};
|
||||
pub use self::nodes::PcieIrqMode;
|
||||
pub use self::nodes::{IPciNode, PcieIrqMode};
|
||||
pub use self::pio::{pio_config_read, pio_config_write};
|
||||
|
||||
/// Type of PCI address space.
|
||||
|
@ -46,10 +42,8 @@ pub struct MappedEcamRegion {
|
|||
vaddr: u64,
|
||||
}
|
||||
|
||||
pub use constants::*;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
mod constants {
|
||||
pub mod constants {
|
||||
pub const PCI_MAX_DEVICES_PER_BUS: usize = 32;
|
||||
pub const PCI_MAX_FUNCTIONS_PER_DEVICE: usize = 8;
|
||||
pub const PCI_MAX_LEGACY_IRQ_PINS: usize = 4;
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
#![allow(dead_code)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use super::{caps::*, config::*, *};
|
||||
use crate::vm::PAGE_SIZE;
|
||||
use alloc::{boxed::Box, sync::*, vec::Vec};
|
||||
use super::caps::{
|
||||
PciCapAdvFeatures, PciCapPcie, PciCapability, PciCapabilityMsi, PciCapabilityStd, PciMsiBlock,
|
||||
};
|
||||
use super::config::{
|
||||
PciConfig, PciReg16, PciReg32, PciReg8, PCIE_BASE_CONFIG_SIZE, PCIE_EXTENDED_CONFIG_SIZE,
|
||||
};
|
||||
use super::constants::*;
|
||||
use super::{bus::PCIeBusDriver, pci_init_args::PciIrqSwizzleLut};
|
||||
use crate::{vm::PAGE_SIZE, ZxError, ZxResult};
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use kernel_hal::InterruptManager;
|
||||
use numeric_enum_macro::*;
|
||||
use numeric_enum_macro::numeric_enum;
|
||||
use region_alloc::RegionAllocator;
|
||||
use spin::*;
|
||||
use spin::{Mutex, MutexGuard};
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
|
@ -182,13 +192,13 @@ impl SharedLegacyIrqHandler {
|
|||
/// Create a new SharedLegacyIrqHandler.
|
||||
pub fn create(irq_id: u32) -> Option<Arc<SharedLegacyIrqHandler>> {
|
||||
info!("SharedLegacyIrqHandler created for {:#x?}", irq_id);
|
||||
InterruptManager::disable(irq_id);
|
||||
InterruptManager::disable_irq(irq_id);
|
||||
let handler = Arc::new(SharedLegacyIrqHandler {
|
||||
irq_id,
|
||||
device_handler: Mutex::new(Vec::new()),
|
||||
});
|
||||
let handler_copy = handler.clone();
|
||||
if InterruptManager::set_ioapic_handle(irq_id, Box::new(move || handler_copy.handle()))
|
||||
if InterruptManager::register_irq_handler(irq_id, Box::new(move || handler_copy.handle()))
|
||||
.is_some()
|
||||
{
|
||||
Some(handler)
|
||||
|
@ -201,7 +211,7 @@ impl SharedLegacyIrqHandler {
|
|||
pub fn handle(&self) {
|
||||
let device_handler = self.device_handler.lock();
|
||||
if device_handler.is_empty() {
|
||||
InterruptManager::disable(self.irq_id);
|
||||
InterruptManager::disable_irq(self.irq_id);
|
||||
return;
|
||||
}
|
||||
for dev in device_handler.iter() {
|
||||
|
@ -250,7 +260,7 @@ impl SharedLegacyIrqHandler {
|
|||
let is_first = device_handler.is_empty();
|
||||
device_handler.push(device);
|
||||
if is_first {
|
||||
InterruptManager::enable(self.irq_id);
|
||||
InterruptManager::enable_irq(self.irq_id);
|
||||
}
|
||||
}
|
||||
pub fn remove_device(&self, device: Arc<PcieDevice>) {
|
||||
|
@ -262,7 +272,7 @@ impl SharedLegacyIrqHandler {
|
|||
let mut device_handler = self.device_handler.lock();
|
||||
device_handler.retain(|h| Arc::ptr_eq(h, &device));
|
||||
if device_handler.is_empty() {
|
||||
InterruptManager::disable(self.irq_id);
|
||||
InterruptManager::disable_irq(self.irq_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -953,7 +963,7 @@ impl PcieDevice {
|
|||
}))
|
||||
}
|
||||
}
|
||||
fn enable_msi_irq_mode(&self, inner: &mut MutexGuard<PcieDeviceInner>, irq: u32) -> ZxResult {
|
||||
fn enter_msi_irq_mode(&self, inner: &mut MutexGuard<PcieDeviceInner>, irq: u32) -> ZxResult {
|
||||
let (_std, msi) = inner.msi().ok_or(ZxError::NOT_SUPPORTED)?;
|
||||
let initially_masked = if msi.has_pvm {
|
||||
self.cfg
|
||||
|
@ -1134,7 +1144,7 @@ impl PcieDevice {
|
|||
inner.irq.legacy.shared_handler.add_device(inner.arc_self());
|
||||
Ok(())
|
||||
}
|
||||
PcieIrqMode::Msi => self.enable_msi_irq_mode(&mut inner, irq_count),
|
||||
PcieIrqMode::Msi => self.enter_msi_irq_mode(&mut inner, irq_count),
|
||||
PcieIrqMode::MsiX => Err(ZxError::NOT_SUPPORTED),
|
||||
_ => Err(ZxError::INVALID_ARGS),
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
//!
|
||||
//! reference: zircon/system/public/zircon/syscalls/pci.h
|
||||
|
||||
use super::constants::*;
|
||||
use crate::{ZxError, ZxResult};
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PciIrqSwizzleLut(
|
||||
|
@ -42,7 +45,6 @@ pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::<PciInitArgsAddrWin
|
|||
* PCI_INIT_ARG_MAX_ECAM_WINDOWS
|
||||
+ core::mem::size_of::<PciInitArgsHeader>();
|
||||
|
||||
use super::*;
|
||||
use kernel_hal::InterruptManager;
|
||||
|
||||
impl PciInitArgsHeader {
|
||||
|
@ -50,41 +52,21 @@ impl PciInitArgsHeader {
|
|||
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) {
|
||||
if !InterruptManager::is_valid_irq(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 */
|
||||
)?;
|
||||
} else if !InterruptManager::configure_irq(
|
||||
global_irq,
|
||||
irq.level_triggered, /* Trigger mode */
|
||||
irq.active_high, /* Polarity */
|
||||
) {
|
||||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid_interrupt(irq: u32) -> bool {
|
||||
InterruptManager::is_valid(irq)
|
||||
}
|
||||
|
||||
fn irq_configure(irq: u32, level_trigger: bool, active_high: bool) -> ZxResult {
|
||||
// In fuchsia source code, 'BSP' stands for bootstrap processor
|
||||
let dest = kernel_hal::apic_local_id();
|
||||
if InterruptManager::configure(
|
||||
irq,
|
||||
0, // vector
|
||||
dest,
|
||||
level_trigger,
|
||||
active_high,
|
||||
) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ZxError::INVALID_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
impl PciIrqSwizzleLut {
|
||||
pub(super) fn swizzle(&self, dev_id: usize, func_id: usize, pin: usize) -> ZxResult<usize> {
|
||||
if dev_id >= PCI_MAX_DEVICES_PER_BUS
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
#![allow(missing_docs)]
|
||||
use super::super::*;
|
||||
use kernel_hal::{inpd, outpd};
|
||||
use spin::Mutex;
|
||||
|
||||
static PIO_LOCK: Mutex<()> = Mutex::new(());
|
||||
const PCI_CONFIG_ADDR: u16 = 0xcf8;
|
||||
const PCI_CONFIG_DATA: u16 = 0xcfc;
|
||||
const PCI_CONFIG_ENABLE: u32 = 1 << 31;
|
||||
use crate::{ZxError, ZxResult};
|
||||
|
||||
/// Returns the BDF address without the bottom two bits masked off.
|
||||
pub fn pci_bdf_raw_addr(bus: u8, dev: u8, func: u8, offset: u8) -> u32 {
|
||||
|
@ -16,21 +10,57 @@ pub fn pci_bdf_raw_addr(bus: u8, dev: u8, func: u8, offset: u8) -> u32 {
|
|||
| (offset as u32 & 0xff) // bits 7-2 reg, with bottom 2 bits as well
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
|
||||
use kernel_hal::{inpd, outpd};
|
||||
use spin::Mutex;
|
||||
|
||||
static PIO_LOCK: Mutex<()> = Mutex::new(());
|
||||
const PCI_CONFIG_ADDR: u16 = 0xcf8;
|
||||
const PCI_CONFIG_DATA: u16 = 0xcfc;
|
||||
const PCI_CONFIG_ENABLE: u32 = 1 << 31;
|
||||
|
||||
pub fn pio_config_read_addr(addr: u32, width: usize) -> ZxResult<u32> {
|
||||
let _lock = PIO_LOCK.lock();
|
||||
let shift = ((addr & 0x3) << 3) as usize;
|
||||
if shift + width > 32 {
|
||||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
|
||||
let tmp_val = u32::from_le(inpd(PCI_CONFIG_DATA));
|
||||
Ok((tmp_val >> shift) & (((1u64 << width) - 1) as u32))
|
||||
}
|
||||
pub fn pio_config_write_addr(addr: u32, val: u32, width: usize) -> ZxResult {
|
||||
let _lock = PIO_LOCK.lock();
|
||||
let shift = ((addr & 0x3) << 3) as usize;
|
||||
if shift + width > 32 {
|
||||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
|
||||
let width_mask = ((1u64 << width) - 1) as u32;
|
||||
let val = val & width_mask;
|
||||
let tmp_val = if width < 32 {
|
||||
(u32::from_le(inpd(PCI_CONFIG_DATA)) & !(width_mask << shift)) | (val << shift)
|
||||
} else {
|
||||
val
|
||||
};
|
||||
outpd(PCI_CONFIG_DATA, u32::to_le(tmp_val));
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
pub fn pio_config_read_addr(_addr: u32, _width: usize) -> ZxResult<u32> {
|
||||
Err(ZxError::NOT_SUPPORTED)
|
||||
}
|
||||
pub fn pio_config_write_addr(_addr: u32, _val: u32, _width: usize) -> ZxResult {
|
||||
Err(ZxError::NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
} // cfg_if!
|
||||
|
||||
pub fn pio_config_read(bus: u8, dev: u8, func: u8, offset: u8, width: usize) -> ZxResult<u32> {
|
||||
pio_config_read_addr(pci_bdf_raw_addr(bus, dev, func, offset), width)
|
||||
}
|
||||
|
||||
pub fn pio_config_read_addr(addr: u32, width: usize) -> ZxResult<u32> {
|
||||
let _lock = PIO_LOCK.lock();
|
||||
let shift = ((addr & 0x3) << 3) as usize;
|
||||
if shift + width > 32 {
|
||||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
|
||||
let tmp_val = u32::from_le(inpd(PCI_CONFIG_DATA));
|
||||
Ok((tmp_val >> shift) & (((1u64 << width) - 1) as u32))
|
||||
}
|
||||
|
||||
pub fn pio_config_write(
|
||||
bus: u8,
|
||||
dev: u8,
|
||||
|
@ -41,21 +71,3 @@ pub fn pio_config_write(
|
|||
) -> ZxResult {
|
||||
pio_config_write_addr(pci_bdf_raw_addr(bus, dev, func, offset), val, width)
|
||||
}
|
||||
|
||||
pub fn pio_config_write_addr(addr: u32, val: u32, width: usize) -> ZxResult {
|
||||
let _lock = PIO_LOCK.lock();
|
||||
let shift = ((addr & 0x3) << 3) as usize;
|
||||
if shift + width > 32 {
|
||||
return Err(ZxError::INVALID_ARGS);
|
||||
}
|
||||
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
|
||||
let width_mask = ((1u64 << width) - 1) as u32;
|
||||
let val = val & width_mask;
|
||||
let tmp_val = if width < 32 {
|
||||
(u32::from_le(inpd(PCI_CONFIG_DATA)) & !(width_mask << shift)) | (val << shift)
|
||||
} else {
|
||||
val
|
||||
};
|
||||
outpd(PCI_CONFIG_DATA, u32::to_le(tmp_val));
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -22,4 +22,4 @@ numeric-enum-macro = "0.2"
|
|||
zircon-object = { path = "../zircon-object" }
|
||||
kernel-hal = { path = "../kernel-hal" }
|
||||
futures = { version = "0.3", default-features = false, features = ["alloc", "async-await"] }
|
||||
|
||||
cfg-if = "1.0"
|
||||
|
|
|
@ -132,6 +132,7 @@ impl Syscall<'_> {
|
|||
}
|
||||
|
||||
///
|
||||
#[allow(unused_variables, unused_mut)]
|
||||
pub fn sys_pc_firmware_tables(
|
||||
&self,
|
||||
resource: HandleValue,
|
||||
|
@ -142,10 +143,16 @@ impl Syscall<'_> {
|
|||
let proc = self.thread.proc();
|
||||
proc.get_object::<Resource>(resource)?
|
||||
.validate(ResourceKind::ROOT)?;
|
||||
let (acpi_rsdp, smbios) = kernel_hal::pc_firmware_tables();
|
||||
acpi_rsdp_ptr.write(acpi_rsdp)?;
|
||||
smbios_ptr.write(smbios)?;
|
||||
Ok(())
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
|
||||
let (acpi_rsdp, smbios) = kernel_hal::pc_firmware_tables();
|
||||
acpi_rsdp_ptr.write(acpi_rsdp)?;
|
||||
smbios_ptr.write(smbios)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ZxError::NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an interrupt object which represents a physical or virtual interrupt.
|
||||
|
|
|
@ -322,7 +322,6 @@ impl Syscall<'_> {
|
|||
Sys::PCI_ADD_SUBTRACT_IO_RANGE => {
|
||||
self.sys_pci_add_subtract_io_range(a0 as _, a1 != 0, a2 as _, a3 as _, a4 != 0)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
Sys::PCI_CFG_PIO_RW => self.sys_pci_cfg_pio_rw(
|
||||
a0 as _,
|
||||
a1 as _,
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
use super::*;
|
||||
use alloc::sync::Arc;
|
||||
use core::convert::TryFrom;
|
||||
use zircon_object::{
|
||||
dev::{pci_init_args::*, *},
|
||||
dev::pci::{
|
||||
constants::*,
|
||||
pci_init_args::{PciInitArgsAddrWindows, PciInitArgsHeader, PCI_INIT_ARG_MAX_SIZE},
|
||||
MmioPcieAddressProvider, PCIeBusDriver, PciAddrSpace, PciEcamRegion, PcieDeviceInfo,
|
||||
PcieDeviceKObject, PcieIrqMode, PioPcieAddressProvider,
|
||||
},
|
||||
dev::{Resource, ResourceKind},
|
||||
vm::{pages, VmObject},
|
||||
};
|
||||
|
||||
|
@ -33,8 +40,7 @@ impl Syscall<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[allow(clippy::too_many_arguments, unused_variables, unused_mut)]
|
||||
pub fn sys_pci_cfg_pio_rw(
|
||||
&self,
|
||||
handle: HandleValue,
|
||||
|
@ -50,17 +56,24 @@ impl Syscall<'_> {
|
|||
"pci.cfg_pio_rw: handle={:#x}, addr={:x}:{:x}:{:x}, offset={:#x}, width={:#x}, write={:#}",
|
||||
handle, bus, dev, func, offset, width, write
|
||||
);
|
||||
let proc = self.thread.proc();
|
||||
proc.get_object::<Resource>(handle)?
|
||||
.validate(ResourceKind::ROOT)?;
|
||||
if write {
|
||||
let value = value_ptr.read()?;
|
||||
pio_config_write(bus, dev, func, offset, value, width)?;
|
||||
} else {
|
||||
let value = pio_config_read(bus, dev, func, offset, width)?;
|
||||
value_ptr.write(value)?;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
|
||||
use zircon_object::dev::pci::{pio_config_read, pio_config_write};
|
||||
let proc = self.thread.proc();
|
||||
proc.get_object::<Resource>(handle)?
|
||||
.validate(ResourceKind::ROOT)?;
|
||||
if write {
|
||||
let value = value_ptr.read()?;
|
||||
pio_config_write(bus, dev, func, offset, value, width)?;
|
||||
} else {
|
||||
let value = pio_config_read(bus, dev, func, offset, width)?;
|
||||
value_ptr.write(value)?;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ZxError::NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: review
|
||||
|
|
Loading…
Reference in New Issue