|
|
@ -16,7 +16,8 @@ const PCI_INTERRUPT_PIN: u16 = 0x3d;
|
|
|
|
const PCI_MSI_CTRL_CAP: u16 = 0x00;
|
|
|
|
const PCI_MSI_CTRL_CAP: u16 = 0x00;
|
|
|
|
const PCI_MSI_ADDR: u16 = 0x04;
|
|
|
|
const PCI_MSI_ADDR: u16 = 0x04;
|
|
|
|
const PCI_MSI_UPPER_ADDR: u16 = 0x08;
|
|
|
|
const PCI_MSI_UPPER_ADDR: u16 = 0x08;
|
|
|
|
const PCI_MSI_DATA: u16 = 0x0C;
|
|
|
|
const PCI_MSI_DATA_32: u16 = 0x08;
|
|
|
|
|
|
|
|
const PCI_MSI_DATA_64: u16 = 0x0C;
|
|
|
|
|
|
|
|
|
|
|
|
const PCI_CAP_ID_MSI: u8 = 0x05;
|
|
|
|
const PCI_CAP_ID_MSI: u8 = 0x05;
|
|
|
|
|
|
|
|
|
|
|
@ -94,6 +95,7 @@ unsafe fn enable(loc: Location) -> Option<u32> {
|
|
|
|
while cap_ptr > 0 {
|
|
|
|
while cap_ptr > 0 {
|
|
|
|
let cap_id = am.read8(ops, loc, cap_ptr);
|
|
|
|
let cap_id = am.read8(ops, loc, cap_ptr);
|
|
|
|
if cap_id == PCI_CAP_ID_MSI {
|
|
|
|
if cap_id == PCI_CAP_ID_MSI {
|
|
|
|
|
|
|
|
let orig_ctrl = am.read32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP);
|
|
|
|
// The manual Volume 3 Chapter 10.11 Message Signalled Interrupts
|
|
|
|
// The manual Volume 3 Chapter 10.11 Message Signalled Interrupts
|
|
|
|
// 0 is (usually) the apic id of the bsp.
|
|
|
|
// 0 is (usually) the apic id of the bsp.
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_ADDR, 0xfee00000 | (0 << 12));
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_ADDR, 0xfee00000 | (0 << 12));
|
|
|
@ -101,10 +103,15 @@ unsafe fn enable(loc: Location) -> Option<u32> {
|
|
|
|
let irq = MSI_IRQ;
|
|
|
|
let irq = MSI_IRQ;
|
|
|
|
assigned_irq = Some(irq);
|
|
|
|
assigned_irq = Some(irq);
|
|
|
|
// we offset all our irq numbers by 32
|
|
|
|
// we offset all our irq numbers by 32
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_DATA, irq + 32);
|
|
|
|
if (orig_ctrl >> 16) & (1 << 7) != 0 {
|
|
|
|
|
|
|
|
// 64bit
|
|
|
|
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_DATA_64, irq + 32);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 32bit
|
|
|
|
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_DATA_32, irq + 32);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// enable MSI interrupt, assuming 64bit for now
|
|
|
|
// enable MSI interrupt, assuming 64bit for now
|
|
|
|
let orig_ctrl = am.read32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP);
|
|
|
|
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
|
|
|
|
am.write32(ops, loc, cap_ptr + PCI_MSI_CTRL_CAP, orig_ctrl | 0x10000);
|
|
|
|
debug!(
|
|
|
|
debug!(
|
|
|
|
"MSI control {:#b}, enabling MSI interrupt {}",
|
|
|
|
"MSI control {:#b}, enabling MSI interrupt {}",
|
|
|
@ -112,7 +119,6 @@ unsafe fn enable(loc: Location) -> Option<u32> {
|
|
|
|
irq
|
|
|
|
irq
|
|
|
|
);
|
|
|
|
);
|
|
|
|
msi_found = true;
|
|
|
|
msi_found = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
debug!("PCI device has cap id {} at {:#X}", cap_id, cap_ptr);
|
|
|
|
debug!("PCI device has cap id {} at {:#X}", cap_id, cap_ptr);
|
|
|
|
cap_ptr = am.read8(ops, loc, cap_ptr + 1) as u16;
|
|
|
|
cap_ptr = am.read8(ops, loc, cap_ptr + 1) as u16;
|
|
|
@ -125,6 +131,8 @@ unsafe fn enable(loc: Location) -> Option<u32> {
|
|
|
|
debug!("MSI not found, using PCI interrupt");
|
|
|
|
debug!("MSI not found, using PCI interrupt");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info!("pci device enable done");
|
|
|
|
|
|
|
|
|
|
|
|
assigned_irq
|
|
|
|
assigned_irq
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -162,6 +170,7 @@ pub fn init_driver(dev: &PCIDevice) {
|
|
|
|
// 200 Series PCH SATA controller [AHCI mode]
|
|
|
|
// 200 Series PCH SATA controller [AHCI mode]
|
|
|
|
// C610/X99 series chipset 6-Port SATA Controller [AHCI mode]
|
|
|
|
// C610/X99 series chipset 6-Port SATA Controller [AHCI mode]
|
|
|
|
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[5] {
|
|
|
|
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[5] {
|
|
|
|
|
|
|
|
info!("Found AHCI dev {:?} BAR5 {:x?}", dev, addr);
|
|
|
|
let irq = unsafe { enable(dev.loc) };
|
|
|
|
let irq = unsafe { enable(dev.loc) };
|
|
|
|
assert!(len as usize <= PAGE_SIZE);
|
|
|
|
assert!(len as usize <= PAGE_SIZE);
|
|
|
|
let vaddr = phys_to_virt(addr as usize);
|
|
|
|
let vaddr = phys_to_virt(addr as usize);
|
|
|
|