Sync computers
This commit is contained in:
11
src/main.rs
11
src/main.rs
@@ -6,7 +6,11 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
// #![warn(clippy::pedantic)]
|
// #![warn(clippy::pedantic)]
|
||||||
#![allow(static_mut_refs)]
|
#![allow(static_mut_refs)]
|
||||||
#![feature(riscv_ext_intrinsics, str_from_raw_parts, arbitrary_self_types_pointers)]
|
#![feature(
|
||||||
|
riscv_ext_intrinsics,
|
||||||
|
str_from_raw_parts,
|
||||||
|
arbitrary_self_types_pointers
|
||||||
|
)]
|
||||||
|
|
||||||
use core::sync::atomic::AtomicBool;
|
use core::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
@@ -16,7 +20,7 @@ use log::info;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
io::init_log,
|
io::init_log,
|
||||||
pci::{PciDeviceIterator, scan_pci_for_virtio_keyboard, scan_pci_for_virtio_keyboard2},
|
pci::{PciDeviceIterator, scan_pci_for_virtio_keyboard},
|
||||||
riscv::enable_supervisor_interrupt,
|
riscv::enable_supervisor_interrupt,
|
||||||
scheduler::{SCHEDULER, idle},
|
scheduler::{SCHEDULER, idle},
|
||||||
user::{proc2, test},
|
user::{proc2, test},
|
||||||
@@ -29,7 +33,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
mod volatile;
|
|
||||||
mod boot;
|
mod boot;
|
||||||
mod critical_section;
|
mod critical_section;
|
||||||
mod draw;
|
mod draw;
|
||||||
@@ -51,6 +54,7 @@ mod vga;
|
|||||||
mod virtio;
|
mod virtio;
|
||||||
mod virtual_console;
|
mod virtual_console;
|
||||||
mod virtual_fs;
|
mod virtual_fs;
|
||||||
|
mod volatile;
|
||||||
|
|
||||||
pub const HEAP_SIZE: usize = 1024 * 1024 * 32; // 32Mo RAM
|
pub const HEAP_SIZE: usize = 1024 * 1024 * 32; // 32Mo RAM
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
@@ -96,7 +100,6 @@ pub extern "C" fn supervisor_mode_entry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
scan_pci_for_virtio_keyboard2();
|
|
||||||
let pci_info = scan_pci_for_virtio_keyboard().unwrap();
|
let pci_info = scan_pci_for_virtio_keyboard().unwrap();
|
||||||
KBD_DRIVER = Some(VirtioPciDriver::new(
|
KBD_DRIVER = Some(VirtioPciDriver::new(
|
||||||
pci_info.common_cfg,
|
pci_info.common_cfg,
|
||||||
|
|||||||
396
src/pci.rs
396
src/pci.rs
@@ -1,6 +1,13 @@
|
|||||||
use core::ops::{Deref, DerefMut};
|
use core::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
ptr::{addr_of, addr_of_mut},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{println, volatile::Volatile};
|
use crate::{
|
||||||
|
println,
|
||||||
|
virtio::{VirtioCapability, VirtioCapabilityType, VirtioNotificationCapability},
|
||||||
|
volatile::Volatile,
|
||||||
|
};
|
||||||
|
|
||||||
// Configuration pour RISC-V Virt
|
// Configuration pour RISC-V Virt
|
||||||
const PCI_ECAM_BASE: usize = 0x3000_0000;
|
const PCI_ECAM_BASE: usize = 0x3000_0000;
|
||||||
@@ -48,46 +55,55 @@ pub struct PciDevice {
|
|||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct PciHeader {
|
pub struct PciHeader {
|
||||||
pub vendor_id: Volatile<u16>,
|
pub vendor_id: u16,
|
||||||
pub device_id: Volatile<u16>,
|
pub device_id: u16,
|
||||||
pub command: Volatile<u16>,
|
pub command: u16,
|
||||||
pub status: Volatile<u16>,
|
pub status: u16,
|
||||||
pub revision_id: Volatile<u8>,
|
pub revision_id: u8,
|
||||||
pub programming_interface_bytes: Volatile<u8>,
|
pub programming_interface_bytes: u8,
|
||||||
pub subclass: Volatile<u8>,
|
pub subclass: u8,
|
||||||
pub class_code: Volatile<u8>,
|
pub class_code: u8,
|
||||||
pub cache_line_size: Volatile<u8>,
|
pub cache_line_size: u8,
|
||||||
pub latency_timer: Volatile<u8>,
|
pub latency_timer: u8,
|
||||||
pub header_type: Volatile<u8>,
|
pub header_type: u8,
|
||||||
pub bist: Volatile<u8>,
|
pub bist: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum PciBar {
|
pub enum PciBar {
|
||||||
B32(PciBar32),
|
Mem32(MemoryBar32),
|
||||||
B64(PciBar64),
|
IO32(IOBar32),
|
||||||
|
Mem64(MemoryBar64),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct PciBar32(*mut u32);
|
pub struct MemoryBar32(*mut u32);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct PciBar64(*mut u64);
|
pub struct IOBar32(*mut u32);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct MemoryBar64(*mut u64);
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct PciGeneralHeader {
|
pub struct PciGeneralHeader {
|
||||||
pub common_header: Volatile<PciHeader>,
|
pub common_header: PciHeader,
|
||||||
pub bars: [Volatile<u32>; 6],
|
pub bars: [u32; 6],
|
||||||
pub cardbus_cis_pointer: Volatile<u32>,
|
pub cardbus_cis_pointer: u32,
|
||||||
pub subsystem_vendor_id: Volatile<u16>,
|
pub subsystem_vendor_id: u16,
|
||||||
pub subsystem_id: Volatile<u16>,
|
pub subsystem_id: u16,
|
||||||
pub expansion_rom_base_address: Volatile<u32>,
|
pub expansion_rom_base_address: u32,
|
||||||
pub capabilities_pointer: Volatile<u8>,
|
pub capabilities_pointer: u8,
|
||||||
pub _reserved1: [Volatile<u8>; 7],
|
pub _reserved1: [u8; 7],
|
||||||
pub interrupt_line: Volatile<u8>,
|
pub interrupt_line: u8,
|
||||||
pub interrupt_pin: Volatile<u8>,
|
pub interrupt_pin: u8,
|
||||||
pub min_grant: Volatile<u8>,
|
pub min_grant: u8,
|
||||||
pub max_lantency: Volatile<u8>,
|
pub max_lantency: u8,
|
||||||
|
}
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct PciCapability {
|
||||||
|
pub capability_id: u8,
|
||||||
|
pub next_ptr: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PciGeneralDevice {
|
pub struct PciGeneralDevice {
|
||||||
@@ -124,17 +140,17 @@ impl PciDevice {
|
|||||||
(self.get_vendor_id(), self.get_device_id())
|
(self.get_vendor_id(), self.get_device_id())
|
||||||
}
|
}
|
||||||
pub fn get_device_id(&self) -> u16 {
|
pub fn get_device_id(&self) -> u16 {
|
||||||
unsafe { (&raw const (*self.inner).device_id).read() }
|
unsafe { (*self.inner).device_id }
|
||||||
}
|
}
|
||||||
pub fn get_vendor_id(&self) -> u16 {
|
pub fn get_vendor_id(&self) -> u16 {
|
||||||
unsafe { (*self.inner).vendor_id }
|
unsafe { (*self.inner).vendor_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_command(&self) -> u16 {
|
pub fn get_command(&self) -> u16 {
|
||||||
unsafe { (*self.inner).command }
|
unsafe { core::ptr::read_volatile(&raw const (*self.inner).command) }
|
||||||
}
|
}
|
||||||
pub fn set_command(&mut self, command: u16) {
|
pub fn set_command(&mut self, command: u16) {
|
||||||
unsafe { (*self.inner).command = command }
|
unsafe { core::ptr::write_volatile(&raw mut (*self.inner).command, command) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@@ -146,14 +162,35 @@ impl PciDevice {
|
|||||||
|
|
||||||
impl PciGeneralDevice {
|
impl PciGeneralDevice {
|
||||||
pub fn get_interrupt_pin(&self) -> u8 {
|
pub fn get_interrupt_pin(&self) -> u8 {
|
||||||
unsafe { (*self.inner).interrupt_pin }
|
unsafe { (&raw const (*self.inner).interrupt_pin).read_volatile() }
|
||||||
}
|
}
|
||||||
pub fn set_interrupt_irq(&mut self, irq: u8) {
|
pub fn set_interrupt_irq(&mut self, irq: u8) {
|
||||||
unsafe { (*self.inner).interrupt_line = irq }
|
unsafe { (&raw mut (*self.inner).interrupt_line).write_volatile(irq) }
|
||||||
|
}
|
||||||
|
pub fn get_capabilities_pointer(&self) -> *mut PciCapability {
|
||||||
|
unsafe {
|
||||||
|
(self.inner as usize
|
||||||
|
+ (&raw mut (*self.inner).capabilities_pointer).read_volatile() as usize)
|
||||||
|
as *mut PciCapability
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn capabilities(&self) -> PciCapabilitiesIterator {
|
||||||
|
PciCapabilitiesIterator {
|
||||||
|
base: self.inner as *mut u8,
|
||||||
|
current: self.get_capabilities_pointer(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_bars(&mut self) -> PciBarIterator {
|
||||||
|
PciBarIterator {
|
||||||
|
current: 0,
|
||||||
|
base_addr: unsafe { addr_of_mut!((*self.inner).bars) as *mut u32 },
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn get_bar(&mut self, i: u8) -> PciBar {
|
pub fn get_bar(&mut self, i: u8) -> PciBar {
|
||||||
unsafe { PciBar((&raw mut (*self.inner).bars as *mut u32).add(i as usize)) }
|
unsafe {
|
||||||
|
PciBar::new((&raw mut (*self.inner).bars as *mut u32).add(i as usize) as *mut u32)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,35 +200,99 @@ pub struct PciBarIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for PciBarIterator {
|
impl Iterator for PciBarIterator {
|
||||||
type Item = PciBar;
|
type Item = (u8, PciBar);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.current >= 6 {
|
if self.current >= 6 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let res = if unsafe { *(self.base_addr.add(self.current as usize)) & 0b100 != 0 } {
|
let addr = self.base_addr.wrapping_add(self.current as usize);
|
||||||
self.current += 1;
|
let res = (self.current, unsafe { PciBar::new(addr) });
|
||||||
PciBar64
|
|
||||||
} else {
|
|
||||||
};
|
|
||||||
self.current += 1;
|
self.current += 1;
|
||||||
res
|
if matches!(res.1, PciBar::Mem64(_)) {
|
||||||
|
self.current += 1;
|
||||||
|
}
|
||||||
|
Some(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MemoryBar32 {
|
||||||
|
pub fn is_prefetchable(self) -> bool {
|
||||||
|
unsafe { self.0.read_volatile() & 0b1000 != 0 }
|
||||||
|
}
|
||||||
|
pub fn base_addr(self) -> *const u8 {
|
||||||
|
unsafe { (self.0.read_volatile() & !0b1111) as *const u8 }
|
||||||
|
}
|
||||||
|
pub fn allocate_if_needed(self, addr: *const u8) {
|
||||||
|
if self.base_addr().is_null() {
|
||||||
|
self.allocate(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn allocate(self, addr: *const u8) {
|
||||||
|
debug_assert!(addr as usize <= 0xFFFF_FFFF);
|
||||||
|
unsafe { self.0.write_volatile((*self.0 & 0b11) | addr as u32) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryBar64 {
|
||||||
|
pub fn is_prefetchable(self) -> bool {
|
||||||
|
unsafe { self.0.read_volatile() & 0b1000 != 0 }
|
||||||
|
}
|
||||||
|
pub fn base_addr(self) -> *const u8 {
|
||||||
|
unsafe { (self.0.read_volatile() & !0b1111) as *const u8 }
|
||||||
|
}
|
||||||
|
pub fn allocate(self, addr: *const u8) {
|
||||||
|
unsafe { self.0.write_volatile((*self.0 & 0b1111) | addr as u64) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IOBar32 {
|
||||||
|
pub fn base_addr(self) -> *const u8 {
|
||||||
|
unsafe { (self.0.read_volatile() & !0b11) as *const u8 }
|
||||||
|
}
|
||||||
|
pub fn allocate(self, addr: *const u8) {
|
||||||
|
debug_assert!(addr as usize <= 0xFFFF_FFFF);
|
||||||
|
unsafe { self.0.write_volatile((*self.0 & 0b11) | addr as u32) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PciBar {
|
impl PciBar {
|
||||||
pub fn as_ptr(self) -> *const u8 {
|
pub unsafe fn new(addr: *mut u32) -> Self {
|
||||||
self.0 as *const u8
|
if unsafe { *addr & 0b1 != 0 } {
|
||||||
|
PciBar::IO32(IOBar32(addr))
|
||||||
|
} else if unsafe { *addr & 0b100 != 0 } {
|
||||||
|
PciBar::Mem64(MemoryBar64(addr as *mut u64))
|
||||||
|
} else {
|
||||||
|
PciBar::Mem32(MemoryBar32(addr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn as_mut_ptr(self) -> *mut u8 {
|
pub fn is_memory_space(self) -> bool {
|
||||||
self.0 as *mut u8
|
matches!(self, PciBar::Mem32(_) | PciBar::Mem64(_))
|
||||||
}
|
}
|
||||||
pub fn is_64bits(self) -> bool {
|
pub fn is_io_space(self) -> bool {
|
||||||
unsafe { *self.0 & 0b100 != 0 }
|
matches!(self, PciBar::IO32(_))
|
||||||
}
|
}
|
||||||
pub fn is_prefetchable(self) -> bool {
|
pub fn is_prefetchable(self) -> bool {
|
||||||
unsafe { *self.0 & 0b1000 != 0 }
|
match self {
|
||||||
|
PciBar::Mem32(pci_bar32) => pci_bar32.is_prefetchable(),
|
||||||
|
PciBar::Mem64(pci_bar64) => pci_bar64.is_prefetchable(),
|
||||||
|
PciBar::IO32(_) => panic!("IO Space Bars are not prefetchable"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn base_address(self) -> *const u8 {
|
||||||
|
match self {
|
||||||
|
PciBar::Mem32(pci_bar32) => pci_bar32.base_addr(),
|
||||||
|
PciBar::Mem64(pci_bar64) => pci_bar64.base_addr(),
|
||||||
|
PciBar::IO32(iobar32) => iobar32.base_addr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn allocate(self, addr: *const u8) {
|
||||||
|
match self {
|
||||||
|
PciBar::Mem32(pci_bar32) => pci_bar32.allocate(addr),
|
||||||
|
PciBar::Mem64(pci_bar64) => pci_bar64.allocate(addr),
|
||||||
|
PciBar::IO32(iobar32) => iobar32.allocate(addr),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +327,34 @@ impl Iterator for PciDeviceIterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn scan_pci_for_virtio_keyboard2() -> Option<VirtioPciCaps> {
|
pub struct PciCapabilitiesIterator {
|
||||||
|
base: *mut u8,
|
||||||
|
current: *mut PciCapability,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PciCapabilitiesIterator {
|
||||||
|
type Item = *mut PciCapability;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.current.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let res = self.current;
|
||||||
|
self.current = unsafe {
|
||||||
|
let offset =
|
||||||
|
(&raw const (*(self.current as *const PciCapability)).next_ptr).read_volatile();
|
||||||
|
if offset != 0 {
|
||||||
|
self.base.add(offset as usize) as *mut PciCapability
|
||||||
|
} else {
|
||||||
|
core::ptr::null_mut()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scan_pci_for_virtio_keyboard() -> Option<VirtioPciCaps> {
|
||||||
let device = PciDeviceIterator::new()
|
let device = PciDeviceIterator::new()
|
||||||
.find(|device| device.vendor_and_device_id() == (0x1af4, 0x1052))
|
.find(|device| device.vendor_and_device_id() == (0x1af4, 0x1052))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -235,139 +363,67 @@ pub fn scan_pci_for_virtio_keyboard2() -> Option<VirtioPciCaps> {
|
|||||||
device.to_general_device()
|
device.to_general_device()
|
||||||
};
|
};
|
||||||
let interrupt_pin = device.get_interrupt_pin();
|
let interrupt_pin = device.get_interrupt_pin();
|
||||||
|
// Interrupt swizzling
|
||||||
let irq = 32 + (device.device + interrupt_pin - 1) % 4;
|
let irq = 32 + (device.device + interrupt_pin - 1) % 4;
|
||||||
device.set_interrupt_irq(irq);
|
device.set_interrupt_irq(irq);
|
||||||
|
|
||||||
let command = device.get_command() | 0b110;
|
let command = device.get_command() | 0b110;
|
||||||
device.set_command(command);
|
device.set_command(command);
|
||||||
|
|
||||||
for i in 0..6 {
|
for (i, bar) in device.get_bars() {
|
||||||
let bar = device.get_bar(i);
|
println!("bar {} {:x?}", i, bar);
|
||||||
println!("bar {} {:x?} 64: {}", i, bar, bar.is_64bits())
|
if bar.is_memory_space() && bar.base_address().is_null() {
|
||||||
|
println!("alloc");
|
||||||
|
bar.allocate(
|
||||||
|
(0x5100_0000 + (device.device as u32 * 0x100_000) + (i as u32 * 0x4000))
|
||||||
|
as *const u8,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
let mut common_cfg = 0;
|
||||||
}
|
let mut notify_cfg = 0;
|
||||||
|
let mut isr_cfg = 0;
|
||||||
|
let mut notify_multiplier = 1;
|
||||||
|
|
||||||
pub fn scan_pci_for_virtio_keyboard() -> Option<VirtioPciCaps> {
|
for capability_addr in device.capabilities() {
|
||||||
// Sur RISC-V Virt, on scanne généralement le bus 0
|
if unsafe { (*capability_addr).capability_id == 0x9 } {
|
||||||
for dev in 0..32 {
|
let capability = unsafe { *(capability_addr as *mut VirtioCapability) };
|
||||||
let vdev: u32 = pci_read(0, dev, 0, 0x00);
|
|
||||||
let vendor = (vdev & 0xffff) as u16;
|
|
||||||
let device = (vdev >> 16) as u16;
|
|
||||||
|
|
||||||
// On cherche le Vendor ID VirtIO (0x1AF4)
|
if capability.bar <= 5 {
|
||||||
// et le Device ID Keyboard (0x1012 ou 0x1052 pour Modern)
|
let bar_addr = device.get_bar(capability.bar).base_address();
|
||||||
if vendor == 0x1af4 && (device >= 0x1000 && device <= 0x107f) {
|
let addr = bar_addr.wrapping_add(capability.offset as usize);
|
||||||
// Dans ta boucle de scan, après avoir trouvé le device
|
match capability.capability_type {
|
||||||
// let interrupt_pin = (pci_read::<u32>(0, dev, 0, 0x3C) >> 8) & 0xFF; // Offset 0x3D
|
VirtioCapabilityType::Common => {
|
||||||
// let irq = 32 + (dev as u32 + interrupt_pin - 1) % 4;
|
common_cfg = addr as usize;
|
||||||
|
println!("[VirtIO] CommonCfg trouvé à 0x{:x?}", addr);
|
||||||
// // let old_val = pci_read::<u32>(0, 2, 0, 0x3C);
|
|
||||||
|
|
||||||
// // On garde les 24 bits du haut (Interrupt Pin, etc.) et on change les 8 bits du bas
|
|
||||||
// // let new_val = (old_val & 0xFFFFFF00) | irq;
|
|
||||||
|
|
||||||
// // pci_write(0, 2, 0, 0x3C, new_val);
|
|
||||||
|
|
||||||
// println!(
|
|
||||||
// "VirtIO Keyboard sur Slot {}, PIN {}, mappé sur IRQ PLIC {}",
|
|
||||||
// dev, interrupt_pin, irq
|
|
||||||
// ); // ACTIVER l'accès mémoire et le bus mastering (PCI Command)
|
|
||||||
// let cmd = pci_read::<u32>(0, dev, 0, 0x04);
|
|
||||||
// pci_write(0, dev, 0, 0x04, cmd | 0x6);
|
|
||||||
|
|
||||||
let mut common_cfg = 0;
|
|
||||||
let mut notify_cfg = 0;
|
|
||||||
let mut isr_cfg = 0;
|
|
||||||
|
|
||||||
// On initialise le multiplicateur à 1 par défaut
|
|
||||||
let mut notify_multiplier: u32 = 1;
|
|
||||||
|
|
||||||
// 1. Activer le Bus Master et le Memory Space globalement pour ce périphérique avant de commencer
|
|
||||||
// let old_cmd = pci_read::<u32>(0, dev, 0, 0x04);
|
|
||||||
// pci_write(0, dev, 0, 0x04, old_cmd | 0x06);
|
|
||||||
|
|
||||||
// 2. Boucle d'assignation des BARs (AVANT de lire les capabilities)
|
|
||||||
let mut bar_idx = 0;
|
|
||||||
while bar_idx < 6 {
|
|
||||||
let bar_reg = 0x10 + (bar_idx * 4);
|
|
||||||
let bar_val = pci_read::<u32>(0, dev, 0, bar_reg);
|
|
||||||
|
|
||||||
// Si le BAR veut de la mémoire (bit 0 == 0) et n'est pas mappé
|
|
||||||
if bar_val & 0x1 == 0 && (bar_val & 0xFFFF_FFF0) == 0 {
|
|
||||||
let new_addr =
|
|
||||||
0x5100_0000 + (dev as u32 * 0x100_000) + (bar_idx as u32 * 0x4000);
|
|
||||||
println!("ALLOCATE BAR {} at {:x}", bar_idx, new_addr);
|
|
||||||
pci_write(0, dev, 0, bar_reg, new_addr | (bar_val & 0xF));
|
|
||||||
|
|
||||||
// Gérer les BAR 64-bits (ils consomment deux slots)
|
|
||||||
if (bar_val >> 1) & 0x3 == 2 {
|
|
||||||
println!("bar {} is 64 bits", bar_idx);
|
|
||||||
pci_write(0, dev, 0, bar_reg + 4, 0);
|
|
||||||
|
|
||||||
bar_idx += 1
|
|
||||||
}
|
}
|
||||||
pci_write(0, dev, 0, bar_reg, new_addr);
|
VirtioCapabilityType::Notify => {
|
||||||
let confirm = pci_read::<u32>(0, dev, 0, bar_reg);
|
notify_cfg = addr as usize;
|
||||||
println!("BAR confirmé : {:x}", confirm);
|
notify_multiplier = unsafe {
|
||||||
}
|
(*(capability_addr as *mut VirtioNotificationCapability))
|
||||||
bar_idx += 1
|
.notify_offset_multiplier
|
||||||
}
|
};
|
||||||
let mut cap_ptr = (pci_read::<u32>(0, dev, 0, 0x34) & 0xFF) as u16;
|
println!("[VirtIO] NotifyCfg trouvé à 0x{:x?}", addr);
|
||||||
|
|
||||||
while cap_ptr != 0 {
|
|
||||||
let header: u32 = pci_read(0, dev, 0, cap_ptr);
|
|
||||||
let cap_id = (header & 0xFF) as u8;
|
|
||||||
let next_ptr = ((header >> 8) & 0xFF) as u16;
|
|
||||||
let v_type = ((header >> 24) & 0xFF) as u8;
|
|
||||||
|
|
||||||
if cap_id == 0x09 {
|
|
||||||
// VirtIO Vendor Capability
|
|
||||||
let bar_idx = (pci_read::<u32>(0, dev, 0, cap_ptr + 4) & 0xFF) as u8;
|
|
||||||
let offset = pci_read::<u32>(0, dev, 0, cap_ptr + 8) as usize;
|
|
||||||
|
|
||||||
// VirtIO : bar_idx doit être entre 0 et 5. 0xFF signifie "ignoré".
|
|
||||||
if bar_idx <= 5 {
|
|
||||||
let bar_reg_offset = 0x10 + (bar_idx as u16 * 4);
|
|
||||||
let mut bar_val = pci_read::<u32>(0, dev, 0, bar_reg_offset);
|
|
||||||
|
|
||||||
let bar_addr = (bar_val & 0xFFFF_FFF0) as usize;
|
|
||||||
let final_addr = bar_addr + offset;
|
|
||||||
|
|
||||||
match v_type {
|
|
||||||
1 => {
|
|
||||||
common_cfg = final_addr;
|
|
||||||
println!("[VirtIO] CommonCfg trouvé à 0x{:x}", final_addr);
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
notify_cfg = final_addr;
|
|
||||||
// TRÈS IMPORTANT : Lire le multiplicateur (offset 16 de la capability)
|
|
||||||
notify_multiplier = pci_read(0, dev, 0, cap_ptr + 16);
|
|
||||||
println!(
|
|
||||||
"[VirtIO] NotifyCfg trouvé à 0x{:x} (mult: {})",
|
|
||||||
final_addr, notify_multiplier
|
|
||||||
);
|
|
||||||
}
|
|
||||||
3 => {
|
|
||||||
isr_cfg = final_addr;
|
|
||||||
println!("[VirtIO] IsrCfg trouvé à 0x{:x}", final_addr);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
VirtioCapabilityType::Isr => {
|
||||||
|
isr_cfg = addr as usize;
|
||||||
|
println!("[VirtIO] IsrCfg trouvé à 0x{:x?}", addr);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
cap_ptr = next_ptr;
|
|
||||||
}
|
|
||||||
if common_cfg != 0 && notify_cfg != 0 && isr_cfg != 0 {
|
|
||||||
return Some(VirtioPciCaps {
|
|
||||||
common_cfg,
|
|
||||||
notify_cfg,
|
|
||||||
isr_cfg,
|
|
||||||
notify_multiplier,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
|
||||||
|
if common_cfg != 0 && notify_cfg != 0 && isr_cfg != 0 {
|
||||||
|
Some(VirtioPciCaps {
|
||||||
|
common_cfg,
|
||||||
|
notify_cfg,
|
||||||
|
isr_cfg,
|
||||||
|
notify_multiplier,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,3 +65,42 @@ pub struct VirtioInputEvent {
|
|||||||
pub code: u16,
|
pub code: u16,
|
||||||
pub value: u32,
|
pub value: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct VirtioCapability {
|
||||||
|
pub capability_id: u8,
|
||||||
|
pub next_ptr: u8,
|
||||||
|
pub capability_len: u8,
|
||||||
|
pub capability_type: VirtioCapabilityType,
|
||||||
|
pub bar: u8,
|
||||||
|
pub id: u8,
|
||||||
|
pub padding: [u8; 2],
|
||||||
|
pub offset: u32,
|
||||||
|
pub length: u32,
|
||||||
|
}
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct VirtioNotificationCapability {
|
||||||
|
pub capabilities: VirtioCapability,
|
||||||
|
pub notify_offset_multiplier: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum VirtioCapabilityType {
|
||||||
|
/// Common configuration
|
||||||
|
Common = 1,
|
||||||
|
/// Notifications
|
||||||
|
Notify = 2,
|
||||||
|
/// ISR Status
|
||||||
|
Isr = 3,
|
||||||
|
/// Device specific configuration
|
||||||
|
Device = 4,
|
||||||
|
/// PCI configuration access
|
||||||
|
Pci = 5,
|
||||||
|
/// Shared memory region
|
||||||
|
SharedMemory = 8,
|
||||||
|
/// Vendor-specific data
|
||||||
|
Vendor = 9,
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
pub struct Volatile<T>(T);
|
pub struct Volatile<T>(T);
|
||||||
|
|
||||||
impl<T> Volatile<T> {
|
impl<T> Volatile<T> {
|
||||||
pub unsafe fn read(self: *const Self) -> T {
|
pub unsafe fn read_volatile(self: *const Self) -> T {
|
||||||
unsafe { core::ptr::read_volatile(self as *const T) }
|
unsafe { core::ptr::read_volatile(self as *const T) }
|
||||||
}
|
}
|
||||||
pub unsafe fn write(self: *mut Self, value: T) {
|
pub unsafe fn write_volatile(self: *mut Self, value: T) {
|
||||||
unsafe { core::ptr::write_volatile(self as *mut T, value) }
|
unsafe { core::ptr::write_volatile(self as *mut T, value) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user