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

Add support for PCI legacy interrupts

This commit is contained in:
Jiajie Chen 2019-03-18 16:17:01 +08:00
parent 28ce8ba81c
commit b7f47235f8
3 changed files with 49 additions and 5 deletions

View File

@ -1,4 +1,5 @@
use once::*; use once::*;
use crate::arch::interrupt::{consts, enable_irq};
pub mod vga; pub mod vga;
pub mod serial; pub mod serial;
@ -19,4 +20,14 @@ pub fn init() {
serial::init(); serial::init();
keyboard::init(); keyboard::init();
// Enable PCI Interrupts
enable_irq(consts::PIRQA);
enable_irq(consts::PIRQB);
enable_irq(consts::PIRQC);
enable_irq(consts::PIRQD);
enable_irq(consts::PIRQE);
enable_irq(consts::PIRQF);
enable_irq(consts::PIRQG);
enable_irq(consts::PIRQH);
} }

View File

@ -34,3 +34,14 @@ pub const COM1: u8 = 4;
pub const IDE: u8 = 14; pub const IDE: u8 = 14;
pub const Error: u8 = 19; pub const Error: u8 = 19;
pub const Spurious: u8 = 31; pub const Spurious: u8 = 31;
// PCI Interrupts
// See https://gist.github.com/mcastelino/4acda7c2407f1c51e68f3f994d8ffc98
pub const PIRQA: u8 = 16;
pub const PIRQB: u8 = 17;
pub const PIRQC: u8 = 18;
pub const PIRQD: u8 = 19;
pub const PIRQE: u8 = 20;
pub const PIRQF: u8 = 21;
pub const PIRQG: u8 = 22;
pub const PIRQH: u8 = 23;

View File

@ -168,15 +168,19 @@ impl PciTag {
let mf = self.read(PCI_HEADER, 1); let mf = self.read(PCI_HEADER, 1);
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 pin = self.read(PCI_INTERRUPT_PIN, 1);
info!( info!(
"{}: {}: {}: {:#X} {:#X} ({} {})", "{}: {}: {}: {:#X} {:#X} ({} {}) at {}:{}",
self.bus(), self.bus(),
self.dev(), self.dev(),
self.func(), self.func(),
v, v,
d, d,
cl, cl,
scl scl,
line,
pin
); );
return Some((v, d, mf & 0x80 != 0)); return Some((v, d, mf & 0x80 != 0));
@ -189,6 +193,7 @@ impl PciTag {
self.write(PCI_COMMAND, orig | 0x40f); self.write(PCI_COMMAND, orig | 0x40f);
// find MSI cap // find MSI cap
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);
while cap_ptr > 0 { while cap_ptr > 0 {
let cap_id = self.read(cap_ptr, 1); let cap_id = self.read(cap_ptr, 1);
@ -202,19 +207,36 @@ impl PciTag {
// 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);
self.write(cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000); self.write(cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
info!("MSI control {:#b}, enabling MSI interrupts", orig_ctrl >> 16);
msi_found = true;
break; break;
} }
info!("cap id {} at {:#X}", self.read(cap_ptr, 1), cap_ptr); info!("PCI device has cap id {} at {:#X}", self.read(cap_ptr, 1), cap_ptr);
cap_ptr = self.read(cap_ptr + 1, 1); cap_ptr = self.read(cap_ptr + 1, 1);
} }
if !msi_found {
// Use PCI legacy interrupt instead
// IO Space | MEM Space | Bus Mastering | Special Cycles
self.write(PCI_COMMAND, orig | 0xf);
let line = self.read(PCI_INTERRUPT_LINE, 1);
let pin = self.read(PCI_INTERRUPT_PIN, 1);
info!("MSI not found, using PCI interrupt line {} pin {}", line, pin);
}
} }
} }
pub fn init_driver(vid: u32, did: u32, tag: PciTag) { pub fn init_driver(vid: u32, did: u32, tag: PciTag) {
if vid == 0x8086 { if vid == 0x8086 {
if did == 0x100e || did == 0x10d3 { if did == 0x100e || did == 0x100f || did == 0x10d3 || did == 0x15b8 {
// 0x100e
// 82540EM Gigabit Ethernet Controller // 82540EM Gigabit Ethernet Controller
// 0x100f
// 82545EM Gigabit Ethernet Controller (Copper)
// 0x10d3
// 82574L Gigabit Network Connection // 82574L Gigabit Network Connection
// 0x15b8
// Ethernet Connection (2) I219-V
if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } { if let Some((addr, len)) = unsafe { tag.get_bar_mem(0) } {
unsafe { unsafe {
tag.enable(); tag.enable();
@ -227,7 +249,7 @@ pub fn init_driver(vid: u32, did: u32, tag: PciTag) {
unsafe { unsafe {
tag.enable(); tag.enable();
} }
ixgbe::ixgbe_init(addr, len); //ixgbe::ixgbe_init(addr, len);
} }
} }
} }