[Zion][Denali] Move to MSI for AHCI devices.
This will allow us to properly do interrupts for XHCI devices in the future. Also move PCI device header parsing to a shared library. Get rid of the old irq register format which supplied an irq number and instead pass the appropriate irq number back out to the caller.
This commit is contained in:
parent
c645405ca8
commit
f26fd73116
|
@ -34,6 +34,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bitfield-struct",
|
||||
"mammoth",
|
||||
"pci",
|
||||
"yellowstone-yunq",
|
||||
"yunq",
|
||||
"yunqc",
|
||||
|
@ -83,6 +84,14 @@ dependencies = [
|
|||
"linked_list_allocator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pci"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitfield-struct",
|
||||
"mammoth",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.20"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
members = [
|
||||
"lib/client/denali_client", "lib/fs/ext2",
|
||||
"lib/mammoth",
|
||||
"lib/mammoth", "lib/pci",
|
||||
"lib/voyageurs",
|
||||
"lib/yellowstone",
|
||||
"lib/yunq",
|
||||
|
|
|
@ -258,6 +258,7 @@ pub const kZionPortSend: u64 = 81;
|
|||
pub const kZionPortRecv: u64 = 82;
|
||||
pub const kZionPortPoll: u64 = 83;
|
||||
pub const kZionIrqRegister: u64 = 88;
|
||||
pub const kZionMsiIrqRegister: u64 = 89;
|
||||
pub const kZionEndpointCreate: u64 = 96;
|
||||
pub const kZionEndpointSend: u64 = 97;
|
||||
pub const kZionEndpointRecv: u64 = 98;
|
||||
|
@ -478,6 +479,12 @@ pub struct ZIrqRegisterReq {
|
|||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ZMsiIrqRegisterReq {
|
||||
pub irq_num: *mut u64,
|
||||
pub port_cap: *mut z_cap_t,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ZEndpointCreateReq {
|
||||
pub endpoint_cap: *mut z_cap_t,
|
||||
}
|
||||
|
|
|
@ -120,6 +120,12 @@ impl<T> AsRef<T> for MemoryRegion {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<T> for MemoryRegion {
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
unsafe { (self.virt_addr as *mut T).as_mut().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MemoryRegion {
|
||||
fn drop(&mut self) {
|
||||
// FIXME: We shouldn't have to do this manual adjustment.
|
||||
|
|
|
@ -310,16 +310,17 @@ pub fn port_poll(
|
|||
Ok((num_bytes, num_caps))
|
||||
}
|
||||
|
||||
pub fn register_irq(irq_num: u64) -> Result<Capability, ZError> {
|
||||
pub fn register_msi_irq() -> Result<(Capability, u64), ZError> {
|
||||
let mut irq_num: u64 = 0;
|
||||
let mut port_cap: z_cap_t = 0;
|
||||
syscall(
|
||||
zion::kZionIrqRegister,
|
||||
&zion::ZIrqRegisterReq {
|
||||
irq_num,
|
||||
zion::kZionMsiIrqRegister,
|
||||
&zion::ZMsiIrqRegisterReq {
|
||||
irq_num: &mut irq_num as *mut u64,
|
||||
port_cap: &mut port_cap,
|
||||
},
|
||||
)?;
|
||||
Ok(Capability::take(port_cap))
|
||||
Ok((Capability::take(port_cap), irq_num))
|
||||
}
|
||||
|
||||
pub fn endpoint_create() -> Result<Capability, ZError> {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "pci"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
bitfield-struct = "0.8.0"
|
||||
mammoth = {path = "../mammoth/"}
|
|
@ -0,0 +1,89 @@
|
|||
use alloc::vec::Vec;
|
||||
use mammoth::{cap::Capability, mem::MemoryRegion, syscall, zion::ZError};
|
||||
|
||||
use crate::header::{
|
||||
PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, PciMsiControl,
|
||||
get_header_type,
|
||||
};
|
||||
|
||||
pub struct PciDevice {
|
||||
memory_region: MemoryRegion,
|
||||
}
|
||||
|
||||
impl PciDevice {
|
||||
pub fn from(mut memory_region: MemoryRegion) -> Result<Self, ZError> {
|
||||
match get_header_type(&memory_region)? {
|
||||
PciHeaderType::Device => {}
|
||||
t => {
|
||||
mammoth::debug!("Invalid header type: {:?}", t);
|
||||
return Err(ZError::INVALID_ARGUMENT);
|
||||
}
|
||||
}
|
||||
Ok(Self { memory_region })
|
||||
}
|
||||
|
||||
pub fn from_cap(capability: Capability) -> Result<Self, ZError> {
|
||||
Self::from(MemoryRegion::from_cap(capability)?)
|
||||
}
|
||||
|
||||
pub fn header(&self) -> &PciDeviceHeader {
|
||||
self.memory_region.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_capability_list(&self) -> Result<Vec<&PciCapabilityPointer>, ZError> {
|
||||
let status = self.header().status;
|
||||
if !status.capability_list() {
|
||||
return Err(ZError::NOT_FOUND);
|
||||
}
|
||||
|
||||
let mut cap_offset = self.header().capability_ptr;
|
||||
|
||||
let mut cap_vec = Vec::new();
|
||||
while cap_offset != 0 {
|
||||
let cap_ptr: &PciCapabilityPointer = unsafe {
|
||||
self.memory_region
|
||||
.raw_ptr_at_offset::<PciCapabilityPointer>(cap_offset as u64)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
cap_vec.push(cap_ptr);
|
||||
cap_offset = cap_ptr.next_cap_offset;
|
||||
}
|
||||
|
||||
Ok(cap_vec)
|
||||
}
|
||||
|
||||
pub fn register_msi(&mut self) -> Result<Capability, ZError> {
|
||||
let caps = self.get_capability_list()?;
|
||||
const MSI_CAP_ID: u8 = 0x05;
|
||||
let msi_cap: &PciCapabilityPointer = caps
|
||||
.iter()
|
||||
.find(|cp| cp.cap_id == MSI_CAP_ID)
|
||||
.ok_or(ZError::NOT_FOUND)?;
|
||||
|
||||
let msi_cap = unsafe {
|
||||
((msi_cap as *const PciCapabilityPointer) as *mut PciMsiCapability)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
mammoth::debug!("MSI Cap: {:#x?}", msi_cap);
|
||||
|
||||
let control = msi_cap.msi_control;
|
||||
assert!(control.capable_address_64());
|
||||
assert!(control.multi_message_capable() == 0);
|
||||
|
||||
// FIXME: These probably need to be volatile writes.
|
||||
let header: &mut PciDeviceHeader = self.memory_region.as_mut();
|
||||
header.command = header.command.with_interrupt_disable(true);
|
||||
msi_cap.msi_control = control.with_msi_enable(true);
|
||||
msi_cap.msi_addr_lower = 0xFEE00000;
|
||||
msi_cap.msi_addr_upper_or_data = 0x0;
|
||||
|
||||
let (cap, irq_num) = syscall::register_msi_irq()?;
|
||||
|
||||
msi_cap.msi_data_if_64 = irq_num as u32;
|
||||
|
||||
Ok(cap)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
use bitfield_struct::bitfield;
|
||||
use mammoth::{mem::MemoryRegion, zion::ZError};
|
||||
|
||||
#[bitfield(u16)]
|
||||
pub struct PciCommand {
|
||||
io_space_enable: bool,
|
||||
memory_space_enable: bool,
|
||||
bus_master_enable: bool,
|
||||
|
||||
#[bits(access=RO)]
|
||||
special_cycles_enable: bool,
|
||||
|
||||
#[bits(access=RO)]
|
||||
memory_write_and_invalidate_enable: bool,
|
||||
|
||||
#[bits(access=RO)]
|
||||
vga_pallette_snoop_enable: bool,
|
||||
|
||||
parity_error_response_enable: bool,
|
||||
|
||||
#[bits(access=RO)]
|
||||
wait_cycle_enable: bool,
|
||||
|
||||
serr_enable: bool,
|
||||
|
||||
fast_back_to_back_enable: bool,
|
||||
|
||||
/// Parity is reversed here, set to true to disable.
|
||||
/// Does not affect MSI.
|
||||
pub interrupt_disable: bool,
|
||||
|
||||
#[bits(5)]
|
||||
__: u8,
|
||||
}
|
||||
|
||||
#[bitfield(u16)]
|
||||
pub struct PciStatus {
|
||||
#[bits(3)]
|
||||
__: u8,
|
||||
|
||||
#[bits(access=RO)]
|
||||
pub interrupt_status: bool,
|
||||
#[bits(access=RO)]
|
||||
pub capability_list: bool,
|
||||
#[bits(access=RO)]
|
||||
pub capable_of_66mhz: bool,
|
||||
|
||||
___: bool,
|
||||
|
||||
#[bits(access=RO)]
|
||||
pub fast_back_to_back_capabale: bool,
|
||||
|
||||
/// Write 1 to clear
|
||||
pub master_data_parity_error: bool,
|
||||
|
||||
#[bits(2, access=RO)]
|
||||
pub devsel_timing: u8,
|
||||
|
||||
/// Write 1 to clear
|
||||
pub signaled_target_abort: bool,
|
||||
/// Write 1 to clear
|
||||
pub received_target_abort: bool,
|
||||
/// Write 1 to clear
|
||||
pub received_master_abort: bool,
|
||||
/// Write 1 to clear
|
||||
pub signaled_system_erro: bool,
|
||||
/// Write 1 to clear
|
||||
pub detected_parity_error: bool,
|
||||
}
|
||||
|
||||
/// Header definitions from https://wiki.osdev.org/PCI
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug)]
|
||||
pub struct HeaderShared {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: PciCommand,
|
||||
pub status: PciStatus,
|
||||
pub revision_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub latency_timer: u8,
|
||||
pub header_type: u8,
|
||||
bist: u8,
|
||||
}
|
||||
|
||||
const _: () = assert!(size_of::<HeaderShared>() == 16);
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug)]
|
||||
pub struct PciDeviceHeader {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: PciCommand,
|
||||
pub status: PciStatus,
|
||||
pub revision_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub latency_timer: u8,
|
||||
pub header_type: u8,
|
||||
bist: u8,
|
||||
pub bars: [u32; 6],
|
||||
pub cardbus_cis_ptr: u32,
|
||||
pub subsystem_vendor_id: u16,
|
||||
pub subsystem_id: u16,
|
||||
pub expansion_rom_address: u32,
|
||||
pub capability_ptr: u8,
|
||||
__: [u8; 7],
|
||||
pub interrupt_line: u8,
|
||||
pub interrupt_pin: u8,
|
||||
pub min_grant: u8,
|
||||
pub max_latency: u8,
|
||||
}
|
||||
|
||||
const _: () = assert!(size_of::<PciDeviceHeader>() == 0x40);
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug)]
|
||||
pub struct PciCapabilityPointer {
|
||||
pub cap_id: u8,
|
||||
pub next_cap_offset: u8,
|
||||
}
|
||||
|
||||
#[bitfield(u16)]
|
||||
pub struct PciMsiControl {
|
||||
pub msi_enable: bool,
|
||||
#[bits(3, access=RO)]
|
||||
pub multi_message_capable: u8,
|
||||
#[bits(3)]
|
||||
pub multi_message_enable: u8,
|
||||
|
||||
#[bits(access=RO)]
|
||||
pub capable_address_64: bool,
|
||||
|
||||
#[bits(access=RO)]
|
||||
pub per_vector_masking: bool,
|
||||
|
||||
#[bits(7)]
|
||||
__: u8,
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug)]
|
||||
pub struct PciMsiCapability {
|
||||
pub cap_id: u8,
|
||||
pub next_cap_offset: u8,
|
||||
pub msi_control: PciMsiControl,
|
||||
pub msi_addr_lower: u32,
|
||||
pub msi_addr_upper_or_data: u32,
|
||||
pub msi_data_if_64: u32,
|
||||
pub mask: u32,
|
||||
pub pending: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PciHeaderType {
|
||||
Device,
|
||||
PciBridge,
|
||||
CardBusBridge,
|
||||
}
|
||||
|
||||
pub fn get_header_type(memory_region: &MemoryRegion) -> Result<PciHeaderType, ZError> {
|
||||
let shared: &HeaderShared = memory_region.as_ref();
|
||||
// The only reference I can find to the high bit here is at
|
||||
// https://www.khoury.northeastern.edu/~pjd/cs7680/homework/pci-enumeration.html
|
||||
// > Header Type: bit 7 (0x80) indicates whether it is a multi-function device,
|
||||
match shared.header_type & (!0x80) {
|
||||
0x0 => Ok(PciHeaderType::Device),
|
||||
0x1 => Ok(PciHeaderType::PciBridge),
|
||||
0x2 => Ok(PciHeaderType::CardBusBridge),
|
||||
_ => {
|
||||
mammoth::debug!("Unknown pci header type: {:#x}", shared.header_type);
|
||||
Err(ZError::INVALID_ARGUMENT)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod device;
|
||||
mod header;
|
||||
|
||||
pub use device::PciDevice;
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
|||
[dependencies]
|
||||
bitfield-struct = "0.8.0"
|
||||
mammoth = { path = "../../lib/mammoth" }
|
||||
pci = { path = "../../lib/pci" }
|
||||
yunq = { path = "../../lib/yunq" }
|
||||
yellowstone-yunq = { path = "../../lib/yellowstone" }
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use mammoth::{
|
|||
thread,
|
||||
zion::ZError,
|
||||
};
|
||||
use pci::PciDevice;
|
||||
|
||||
use crate::ahci::{
|
||||
port::{AhciDeviceDetection, AhciInterfacePowerManagement},
|
||||
|
@ -14,36 +15,8 @@ use crate::ahci::{
|
|||
|
||||
use super::{hba::AhciHba, port::AhciPortHba, port_controller::PortController};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C, packed)]
|
||||
pub struct PciDeviceHeader {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command_reg: u16,
|
||||
pub status_reg: u16,
|
||||
pub revision: u8,
|
||||
pub prog_interface: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub latency_timer: u8,
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
pub bars: [u32; 5],
|
||||
pub abar: u32,
|
||||
__: u32,
|
||||
pub subsystem_id: u32,
|
||||
pub expansion_rom: u32,
|
||||
pub cap_ptr: u8,
|
||||
___: [u8; 7],
|
||||
pub interrupt_line: u8,
|
||||
pub interrupt_pin: u8,
|
||||
pub min_grant: u8,
|
||||
pub max_latency: u8,
|
||||
}
|
||||
|
||||
pub struct AhciController {
|
||||
pci_header: &'static mut PciDeviceHeader,
|
||||
pci_device: Mutex<PciDevice>,
|
||||
hba: Mutex<&'static mut AhciHba>,
|
||||
ports: [Option<PortController>; 32],
|
||||
hba_vaddr: u64,
|
||||
|
@ -51,13 +24,13 @@ pub struct AhciController {
|
|||
|
||||
impl AhciController {
|
||||
pub fn new(pci_memory: Capability) -> Self {
|
||||
let pci_vaddr = mem::map_cap_and_leak(pci_memory);
|
||||
let pci_header = unsafe { (pci_vaddr as *mut PciDeviceHeader).as_mut().unwrap() };
|
||||
let pci_device = PciDevice::from_cap(pci_memory).unwrap();
|
||||
|
||||
let hba_vaddr = mem::map_direct_physical_and_leak(pci_header.abar as u64, 0x1100);
|
||||
let hba_vaddr =
|
||||
mem::map_direct_physical_and_leak(pci_device.header().bars[5] as u64, 0x1100);
|
||||
let hba = unsafe { (hba_vaddr as *mut AhciHba).as_mut().unwrap() };
|
||||
let mut controller = Self {
|
||||
pci_header,
|
||||
pci_device: Mutex::new(pci_device),
|
||||
hba: Mutex::new(hba),
|
||||
ports: [const { None }; 32],
|
||||
hba_vaddr,
|
||||
|
@ -100,17 +73,8 @@ impl AhciController {
|
|||
}
|
||||
}
|
||||
|
||||
fn irq_num(&self) -> u64 {
|
||||
match self.pci_header.interrupt_pin {
|
||||
1 => mammoth::zion::kZIrqPci1,
|
||||
2 => mammoth::zion::kZIrqPci2,
|
||||
3 => mammoth::zion::kZIrqPci3,
|
||||
4 => mammoth::zion::kZIrqPci4,
|
||||
_ => panic!(
|
||||
"Unrecognized pci interrupt pin {}",
|
||||
self.pci_header.interrupt_pin
|
||||
),
|
||||
}
|
||||
fn register_irq(&self) -> Result<Capability, ZError> {
|
||||
self.pci_device.lock().register_msi()
|
||||
}
|
||||
|
||||
fn handle_irq(&self) {
|
||||
|
@ -184,9 +148,8 @@ impl AhciController {
|
|||
|
||||
pub fn spawn_irq_thread(controller: Arc<AhciController>) -> thread::JoinHandle {
|
||||
let irq_thread = move || {
|
||||
let irq_num = controller.irq_num();
|
||||
let irq_port =
|
||||
mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap());
|
||||
let irq_port_cap = controller.register_irq().unwrap();
|
||||
let irq_port = mammoth::port::PortServer::from_cap(irq_port_cap);
|
||||
controller.hba.lock().global_host_control.update(|ghc| {
|
||||
ghc.set_interrupt_enable(true);
|
||||
});
|
||||
|
|
|
@ -48,7 +48,7 @@ SYS5(PortRecv, z_cap_t, port_cap, uint64_t*, num_bytes, void*, data, uint64_t*,
|
|||
SYS5(PortPoll, z_cap_t, port_cap, uint64_t*, num_bytes, void*, data, uint64_t*,
|
||||
num_caps, z_cap_t*, caps);
|
||||
|
||||
SYS2(IrqRegister, uint64_t, irq_num, z_cap_t*, port_cap);
|
||||
SYS2(MsiIrqRegister, uint64_t*, irq_num, z_cap_t*, port_cap);
|
||||
|
||||
SYS1(EndpointCreate, z_cap_t*, endpoint_cap);
|
||||
SYS6(EndpointSend, z_cap_t, endpoint_cap, uint64_t, num_bytes, const void*,
|
||||
|
|
|
@ -43,7 +43,7 @@ const uint64_t kZionPortSend = 0x51;
|
|||
const uint64_t kZionPortRecv = 0x52;
|
||||
const uint64_t kZionPortPoll = 0x53;
|
||||
|
||||
const uint64_t kZionIrqRegister = 0x58;
|
||||
const uint64_t kZionMsiIrqRegister = 0x59;
|
||||
|
||||
const uint64_t kZionEndpointCreate = 0x60;
|
||||
const uint64_t kZionEndpointSend = 0x61;
|
||||
|
|
|
@ -136,23 +136,6 @@ Apic::Apic(const ApicConfiguration& config)
|
|||
// FIXME: Get this offset from ACPI.
|
||||
SetIoDoubleReg(0x14, 0x20 | APIC_MASK);
|
||||
|
||||
// Map Keyboard
|
||||
SetIoDoubleReg(0x12, 0x22);
|
||||
|
||||
// For now set these based on the presets in the following spec.
|
||||
// http://web.archive.org/web/20161130153145/http://download.intel.com/design/chipsets/datashts/29056601.pdf
|
||||
// FIXME: However in the future we should likely use the MADT for legacy
|
||||
// interrupts and AML for PCI etc.
|
||||
// PCI Line 1-4
|
||||
// FIXME: These should be level triggered according to spec I believe
|
||||
// but because we handle the interrupt outside of the kernel it is tricky
|
||||
// to wait to send the end of interrupt message.
|
||||
// Because of this leave them as edge triggered and send EOI immediately.
|
||||
SetIoDoubleReg(0x30, 0x30);
|
||||
SetIoDoubleReg(0x32, 0x31);
|
||||
SetIoDoubleReg(0x34, 0x32);
|
||||
SetIoDoubleReg(0x36, 0x33);
|
||||
|
||||
DumpInfo();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,18 +9,24 @@ DriverManager& DriverManager::Get() { return *gDriverManager; }
|
|||
DriverManager::DriverManager() { gDriverManager = this; }
|
||||
|
||||
void DriverManager::WriteMessage(uint64_t irq_num, IpcMessage&& message) {
|
||||
if (!driver_map_.Contains(irq_num)) {
|
||||
if (irq_num < IRQ_OFFSET) {
|
||||
dbgln("WARN IRQ {x} below min offset {x}", irq_num, IRQ_OFFSET);
|
||||
}
|
||||
uint64_t offset = irq_num - IRQ_OFFSET;
|
||||
if (offset >= driver_list_.size()) {
|
||||
dbgln("WARN IRQ for {x} with no registered driver", irq_num);
|
||||
return;
|
||||
}
|
||||
|
||||
driver_map_.at(irq_num)->Send(glcr::Move(message));
|
||||
driver_list_[offset]->Send(glcr::Move(message));
|
||||
}
|
||||
|
||||
glcr::ErrorCode DriverManager::RegisterListener(uint64_t irq_num,
|
||||
glcr::ErrorOr<uint8_t> DriverManager::RegisterListener(
|
||||
glcr::RefPtr<Port> port) {
|
||||
if (driver_map_.Contains(irq_num)) {
|
||||
return glcr::ALREADY_EXISTS;
|
||||
if (driver_list_.size() + IRQ_OFFSET >= 0xFF) {
|
||||
return glcr::EXHAUSTED;
|
||||
}
|
||||
return driver_map_.Insert(irq_num, port);
|
||||
uint8_t offset = (driver_list_.size() + IRQ_OFFSET);
|
||||
driver_list_.PushBack(port);
|
||||
return offset;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,10 @@ class DriverManager {
|
|||
|
||||
void WriteMessage(uint64_t irq_num, IpcMessage&& message);
|
||||
|
||||
[[nodiscard]] glcr::ErrorCode RegisterListener(uint64_t irq_num,
|
||||
[[nodiscard]] glcr::ErrorOr<uint8_t> RegisterListener(
|
||||
glcr::RefPtr<Port> port);
|
||||
|
||||
private:
|
||||
glcr::HashMap<uint64_t, glcr::RefPtr<Port>> driver_map_;
|
||||
const uint64_t IRQ_OFFSET = 0x60;
|
||||
glcr::Vector<glcr::RefPtr<Port>> driver_list_;
|
||||
};
|
||||
|
|
|
@ -109,7 +109,7 @@ extern "C" void interrupt_protection_fault(InterruptFrame* frame) {
|
|||
} else {
|
||||
dbgln("GDT");
|
||||
}
|
||||
dbgln("Index: {}", err >> 3);
|
||||
dbgln("Index: {} ({x})", err >> 3, err >> 3);
|
||||
dbgln("RIP: {x}", frame->rip);
|
||||
dbgln("RAX: {x}, RBX: {x}, RCX: {x}, RDX: {x}", frame->rax, frame->rbx,
|
||||
frame->rcx, frame->rdx);
|
||||
|
@ -197,40 +197,27 @@ extern "C" void interrupt_apic_timer(InterruptFrame*) {
|
|||
gScheduler->Preempt();
|
||||
}
|
||||
|
||||
extern "C" void isr_keyboard();
|
||||
extern "C" void interrupt_keyboard(InterruptFrame*) {
|
||||
glcr::Array<uint8_t> data(1);
|
||||
data[0] = inb(0x60);
|
||||
IpcMessage msg{.data = glcr::Move(data)};
|
||||
DriverManager::Get().WriteMessage(kZIrqKbd, glcr::Move(msg));
|
||||
|
||||
extern "C" void isr_60();
|
||||
extern "C" void interrupt_60(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(0x60, {});
|
||||
gApic->SignalEOI();
|
||||
}
|
||||
|
||||
extern "C" void isr_pci1();
|
||||
extern "C" void interrupt_pci1(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(kZIrqPci1, {});
|
||||
extern "C" void isr_61();
|
||||
extern "C" void interrupt_61(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(0x61, {});
|
||||
gApic->SignalEOI();
|
||||
}
|
||||
|
||||
extern "C" void isr_pci2();
|
||||
extern "C" void interrupt_pci2(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(kZIrqPci2, {});
|
||||
dbgln("Interrupt PCI line 2");
|
||||
extern "C" void isr_62();
|
||||
extern "C" void interrupt_62(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(0x62, {});
|
||||
gApic->SignalEOI();
|
||||
}
|
||||
|
||||
extern "C" void isr_pci3();
|
||||
extern "C" void interrupt_pci3(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(kZIrqPci3, {});
|
||||
dbgln("Interrupt PCI line 3");
|
||||
gApic->SignalEOI();
|
||||
}
|
||||
|
||||
extern "C" void isr_pci4();
|
||||
extern "C" void interrupt_pci4(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(kZIrqPci4, {});
|
||||
dbgln("Interrupt PCI line 4");
|
||||
extern "C" void isr_63();
|
||||
extern "C" void interrupt_63(InterruptFrame*) {
|
||||
DriverManager::Get().WriteMessage(0x63, {});
|
||||
gApic->SignalEOI();
|
||||
}
|
||||
|
||||
|
@ -243,12 +230,11 @@ void InitIdt() {
|
|||
|
||||
gIdt[0x20] = CreateDescriptor(isr_timer);
|
||||
gIdt[0x21] = CreateDescriptor(isr_apic_timer);
|
||||
gIdt[0x22] = CreateDescriptor(isr_keyboard);
|
||||
|
||||
gIdt[0x30] = CreateDescriptor(isr_pci1);
|
||||
gIdt[0x31] = CreateDescriptor(isr_pci2);
|
||||
gIdt[0x32] = CreateDescriptor(isr_pci3);
|
||||
gIdt[0x33] = CreateDescriptor(isr_pci4);
|
||||
gIdt[0x60] = CreateDescriptor(isr_60);
|
||||
gIdt[0x61] = CreateDescriptor(isr_61);
|
||||
gIdt[0x62] = CreateDescriptor(isr_62);
|
||||
gIdt[0x63] = CreateDescriptor(isr_63);
|
||||
|
||||
InterruptDescriptorTablePointer idtp{
|
||||
.size = sizeof(gIdt),
|
||||
|
|
|
@ -63,10 +63,8 @@ isr_handler fpe_fault
|
|||
|
||||
isr_handler timer
|
||||
isr_handler apic_timer
|
||||
isr_handler keyboard
|
||||
|
||||
isr_handler pci1
|
||||
isr_handler pci2
|
||||
isr_handler pci3
|
||||
isr_handler pci4
|
||||
|
||||
isr_handler 60
|
||||
isr_handler 61
|
||||
isr_handler 62
|
||||
isr_handler 63
|
||||
|
|
|
@ -156,13 +156,14 @@ glcr::ErrorCode PortPoll(ZPortPollReq* req) {
|
|||
return TranslateIpcMessageToResponse(msg, req);
|
||||
}
|
||||
|
||||
glcr::ErrorCode IrqRegister(ZIrqRegisterReq* req) {
|
||||
glcr::ErrorCode MsiIrqRegister(ZMsiIrqRegisterReq* req) {
|
||||
auto& proc = gScheduler->CurrentProcess();
|
||||
|
||||
glcr::RefPtr<Port> port = glcr::MakeRefCounted<Port>();
|
||||
|
||||
*req->port_cap = proc.AddNewCapability(port);
|
||||
return DriverManager::Get().RegisterListener(req->irq_num, port);
|
||||
ASSIGN_OR_RETURN(*req->irq_num, DriverManager::Get().RegisterListener(port));
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorCode EndpointCreate(ZEndpointCreateReq* req) {
|
||||
|
|
|
@ -12,7 +12,7 @@ glcr::ErrorCode PortCreate(ZPortCreateReq* req);
|
|||
glcr::ErrorCode PortSend(ZPortSendReq* req);
|
||||
glcr::ErrorCode PortRecv(ZPortRecvReq* req);
|
||||
glcr::ErrorCode PortPoll(ZPortPollReq* req);
|
||||
glcr::ErrorCode IrqRegister(ZIrqRegisterReq* req);
|
||||
glcr::ErrorCode MsiIrqRegister(ZMsiIrqRegisterReq* req);
|
||||
|
||||
glcr::ErrorCode EndpointCreate(ZEndpointCreateReq* req);
|
||||
glcr::ErrorCode EndpointSend(ZEndpointSendReq* req);
|
||||
|
|
|
@ -77,7 +77,7 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) {
|
|||
CASE(PortSend);
|
||||
CASE(PortRecv);
|
||||
CASE(PortPoll);
|
||||
CASE(IrqRegister);
|
||||
CASE(MsiIrqRegister);
|
||||
CASE(EndpointCreate);
|
||||
CASE(EndpointSend);
|
||||
CASE(EndpointRecv);
|
||||
|
|
Loading…
Reference in New Issue