mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 00:16:17 +04:00
Implement irq allocation and use irq number to identify irq source
This commit is contained in:
parent
c423f10483
commit
0d2bc0a7d4
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user