1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 08:26:17 +04:00

Implement irq allocation and use irq number to identify irq source

This commit is contained in:
Jiajie Chen 2019-03-18 19:58:35 +08:00
parent c423f10483
commit 0d2bc0a7d4
9 changed files with 41 additions and 18 deletions

View File

@ -139,7 +139,7 @@ fn try_process_serial() -> bool {
fn try_process_drivers() -> bool { fn try_process_drivers() -> bool {
for driver in DRIVERS.read().iter() { for driver in DRIVERS.read().iter() {
if driver.try_handle_interrupt() == true { if driver.try_handle_interrupt(None) == true {
return true return true
} }
} }

View File

@ -93,7 +93,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
IDE => ide(), IDE => ide(),
_ => { _ => {
for driver in DRIVERS.read().iter() { for driver in DRIVERS.read().iter() {
if driver.try_handle_interrupt() == true { if driver.try_handle_interrupt(Some(irq.into())) == true {
debug!("driver processed interrupt"); debug!("driver processed interrupt");
return; return;
} }

View File

@ -90,7 +90,7 @@ bitflags! {
} }
impl Driver for VirtIOBlkDriver { impl Driver for VirtIOBlkDriver {
fn try_handle_interrupt(&self) -> bool { fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let mut driver = self.0.lock(); let mut driver = self.0.lock();
// ensure header page is mapped // ensure header page is mapped

View File

@ -161,18 +161,21 @@ impl PciTag {
// returns a tuple of (vid, did, next) // returns a tuple of (vid, did, next)
pub fn probe(&self) -> Option<(u32, u32, bool)> { pub fn probe(&self) -> Option<(u32, u32, bool)> {
unsafe { unsafe {
// To lookup vendor and device, please see https://pci-ids.ucw.cz/read/PC/
let v = self.read(PCI_VENDOR, 2); let v = self.read(PCI_VENDOR, 2);
if v == 0xffff { if v == 0xffff {
return None; return None;
} }
let d = self.read(PCI_DEVICE, 2); let d = self.read(PCI_DEVICE, 2);
let mf = self.read(PCI_HEADER, 1); let mf = self.read(PCI_HEADER, 1);
// To lookup class and subclass, please see https://pci-ids.ucw.cz/read/PD/
let cl = self.read(PCI_CLASS, 1); let cl = self.read(PCI_CLASS, 1);
let scl = self.read(PCI_SUBCLASS, 1); let scl = self.read(PCI_SUBCLASS, 1);
let line = self.read(PCI_INTERRUPT_LINE, 1); let line = self.read(PCI_INTERRUPT_LINE, 1);
let pin = self.read(PCI_INTERRUPT_PIN, 1); let pin = self.read(PCI_INTERRUPT_PIN, 1);
info!( info!(
"{}: {}: {}: {:#X} {:#X} ({} {}) at {}:{}", "{:02x}:{:02x}.{}: {:#x} {:#x} ({} {}) irq {}:{}",
self.bus(), self.bus(),
self.dev(), self.dev(),
self.func(), self.func(),
@ -188,7 +191,13 @@ impl PciTag {
} }
} }
pub unsafe fn enable(&self) {
/// Enable the pci tag and its interrupt
/// Return assigned MSI interrupt number when applicable
pub unsafe fn enable(&self) -> Option<u32> {
// 23 and lower are used
static mut MSI_IRQ: u32 = 23;
let orig = self.read(PCI_COMMAND, 2); let orig = self.read(PCI_COMMAND, 2);
// IO Space | MEM Space | Bus Mastering | Special Cycles | PCI Interrupt Disable // IO Space | MEM Space | Bus Mastering | Special Cycles | PCI Interrupt Disable
self.write(PCI_COMMAND, orig | 0x40f); self.write(PCI_COMMAND, orig | 0x40f);
@ -196,14 +205,17 @@ impl PciTag {
// find MSI cap // find MSI cap
let mut msi_found = false; let mut msi_found = false;
let mut cap_ptr = self.read(PCI_CAP_PTR, 1); let mut cap_ptr = self.read(PCI_CAP_PTR, 1);
let mut assigned_irq = None;
while cap_ptr > 0 { while cap_ptr > 0 {
let cap_id = self.read(cap_ptr, 1); let cap_id = self.read(cap_ptr, 1);
if cap_id == PCI_CAP_ID_MSI { if cap_id == PCI_CAP_ID_MSI {
self.write(cap_ptr + PCI_MSI_ADDR, 0xfee00000); self.write(cap_ptr + PCI_MSI_ADDR, 0xfee00000);
// irq 23 means no 23, should be allocated from a pool MSI_IRQ += 1;
// 23 + 32 = 55 let irq = MSI_IRQ;
assigned_irq = Some(irq);
// irq number + 32 = MSI data
// 0 is (usually) the apic id of the bsp. // 0 is (usually) the apic id of the bsp.
self.write(cap_ptr + PCI_MSI_DATA, 55 | 0 << 12); self.write(cap_ptr + PCI_MSI_DATA, (irq + 32) | 0 << 12);
// enable MSI interrupt // enable MSI interrupt
let orig_ctrl = self.read(cap_ptr + PCI_MSI_CTRL_CAP, 4); let orig_ctrl = self.read(cap_ptr + PCI_MSI_CTRL_CAP, 4);
@ -224,6 +236,8 @@ impl PciTag {
let pin = self.read(PCI_INTERRUPT_PIN, 1); let pin = self.read(PCI_INTERRUPT_PIN, 1);
debug!("MSI not found, using PCI interrupt line {} pin {}", line, pin); debug!("MSI not found, using PCI interrupt line {} pin {}", line, pin);
} }
assigned_irq
} }
} }
@ -249,10 +263,10 @@ pub fn init_driver(name: String, vid: u32, did: u32, tag: PciTag) {
} else if did == 0x10fb { } else if did == 0x10fb {
// 82599ES 10-Gigabit SFI/SFP+ Network Connection // 82599ES 10-Gigabit SFI/SFP+ Network Connection
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } { if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
unsafe { let irq = unsafe {
tag.enable(); tag.enable()
} };
ixgbe::ixgbe_init(name, addr, len); ixgbe::ixgbe_init(name, irq, addr, len);
} }
} }
} }

View File

@ -189,7 +189,7 @@ const VIRTIO_GPU_RESOURCE_ID: u32 = 0xbabe;
pub struct VirtIOGpuDriver(Mutex<VirtIOGpu>); pub struct VirtIOGpuDriver(Mutex<VirtIOGpu>);
impl Driver for VirtIOGpuDriver { impl Driver for VirtIOGpuDriver {
fn try_handle_interrupt(&self) -> bool { fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
// for simplicity // for simplicity
if cpu::id() > 0 { if cpu::id() > 0 {
return false return false

View File

@ -27,7 +27,9 @@ pub enum DeviceType {
pub trait Driver : Send + Sync { pub trait Driver : Send + Sync {
// if interrupt belongs to this driver, handle it and return true // if interrupt belongs to this driver, handle it and return true
// return false otherwise // return false otherwise
fn try_handle_interrupt(&self) -> bool; // irq number is provided when available
// driver should skip handling when irq number is mismatched
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool;
// return the correspondent device type, see DeviceType // return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType; fn device_type(&self) -> DeviceType;

View File

@ -76,7 +76,7 @@ pub struct E1000Interface {
} }
impl Driver for E1000Interface { impl Driver for E1000Interface {
fn try_handle_interrupt(&self) -> bool { fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let irq = { let irq = {
let driver = self.driver.0.lock(); let driver = self.driver.0.lock();

View File

@ -141,10 +141,16 @@ pub struct IXGBEInterface {
driver: IXGBEDriver, driver: IXGBEDriver,
sockets: Mutex<SocketSet<'static, 'static, 'static>>, sockets: Mutex<SocketSet<'static, 'static, 'static>>,
name: String, name: String,
irq: Option<u32>,
} }
impl Driver for IXGBEInterface { impl Driver for IXGBEInterface {
fn try_handle_interrupt(&self) -> bool { fn try_handle_interrupt(&self, irq: Option<u32>) -> bool {
if irq.is_some() && self.irq.is_some() && irq != self.irq {
// not ours, skip it
return false;
}
let (handled, rx) = { let (handled, rx) = {
let driver = self.driver.0.lock(); let driver = self.driver.0.lock();
@ -436,7 +442,7 @@ bitflags! {
} }
} }
pub fn ixgbe_init(name: String, header: usize, size: usize) { pub fn ixgbe_init(name: String, irq: Option<u32>, header: usize, size: usize) {
assert_eq!(size_of::<IXGBESendDesc>(), 16); assert_eq!(size_of::<IXGBESendDesc>(), 16);
assert_eq!(size_of::<IXGBERecvDesc>(), 16); assert_eq!(size_of::<IXGBERecvDesc>(), 16);
@ -786,6 +792,7 @@ pub fn ixgbe_init(name: String, header: usize, size: usize) {
sockets: Mutex::new(SocketSet::new(vec![])), sockets: Mutex::new(SocketSet::new(vec![])),
driver: net_driver.clone(), driver: net_driver.clone(),
name, name,
irq,
}; };
let driver = Arc::new(ixgbe_iface); let driver = Arc::new(ixgbe_iface);

View File

@ -42,7 +42,7 @@ const VIRTIO_QUEUE_RECEIVE: usize = 0;
const VIRTIO_QUEUE_TRANSMIT: usize = 1; const VIRTIO_QUEUE_TRANSMIT: usize = 1;
impl Driver for VirtIONetDriver { impl Driver for VirtIONetDriver {
fn try_handle_interrupt(&self) -> bool { fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let driver = self.0.lock(); let driver = self.0.lock();
// ensure header page is mapped // ensure header page is mapped