Sync computers
This commit is contained in:
@@ -8,6 +8,7 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "2"
|
||||
embedded-alloc = "0.7"
|
||||
kernel-macros = { path = "crates/kernel-macros" }
|
||||
log = "0.4"
|
||||
@@ -15,6 +16,5 @@ critical-section = { version = "1", features = ["restore-state-bool"] }
|
||||
bffs = { path = "crates/bffs", features = ["alloc"] }
|
||||
io = { path = "crates/io", features = ["alloc"] }
|
||||
shared = { path = "crates/shared", features = ["kernel"] }
|
||||
# ELF parsing helper
|
||||
goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] }
|
||||
hashbrown = "0.16"
|
||||
|
||||
0
crates/shared/src/endian.rs
Normal file
0
crates/shared/src/endian.rs
Normal file
@@ -2,3 +2,4 @@
|
||||
|
||||
pub mod fs;
|
||||
pub mod syscall;
|
||||
pub mod endian;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#![no_main]
|
||||
// #![warn(clippy::pedantic)]
|
||||
#![allow(static_mut_refs)]
|
||||
#![feature(riscv_ext_intrinsics, str_from_raw_parts)]
|
||||
#![feature(riscv_ext_intrinsics, str_from_raw_parts, arbitrary_self_types_pointers)]
|
||||
|
||||
use core::sync::atomic::AtomicBool;
|
||||
|
||||
@@ -16,7 +16,7 @@ use log::info;
|
||||
|
||||
use crate::{
|
||||
io::init_log,
|
||||
pci::{PciDeviceIterator, scan_pci_for_virtio_keyboard},
|
||||
pci::{PciDeviceIterator, scan_pci_for_virtio_keyboard, scan_pci_for_virtio_keyboard2},
|
||||
riscv::enable_supervisor_interrupt,
|
||||
scheduler::{SCHEDULER, idle},
|
||||
user::{proc2, test},
|
||||
@@ -29,6 +29,7 @@ use crate::{
|
||||
};
|
||||
|
||||
extern crate alloc;
|
||||
mod volatile;
|
||||
mod boot;
|
||||
mod critical_section;
|
||||
mod draw;
|
||||
@@ -95,6 +96,7 @@ pub extern "C" fn supervisor_mode_entry() {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
scan_pci_for_virtio_keyboard2();
|
||||
let pci_info = scan_pci_for_virtio_keyboard().unwrap();
|
||||
KBD_DRIVER = Some(VirtioPciDriver::new(
|
||||
pci_info.common_cfg,
|
||||
|
||||
195
src/pci.rs
195
src/pci.rs
@@ -1,4 +1,6 @@
|
||||
use crate::println;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::{println, volatile::Volatile};
|
||||
|
||||
// Configuration pour RISC-V Virt
|
||||
const PCI_ECAM_BASE: usize = 0x3000_0000;
|
||||
@@ -41,42 +43,155 @@ pub struct VirtioPciCaps {
|
||||
pub struct PciDevice {
|
||||
pub bus: u8,
|
||||
pub device: u8,
|
||||
pub inner: *mut PciHeader,
|
||||
}
|
||||
|
||||
pub struct PciGeneralDevice(PciDevice);
|
||||
#[repr(C, packed)]
|
||||
pub struct PciHeader {
|
||||
pub vendor_id: Volatile<u16>,
|
||||
pub device_id: Volatile<u16>,
|
||||
pub command: Volatile<u16>,
|
||||
pub status: Volatile<u16>,
|
||||
pub revision_id: Volatile<u8>,
|
||||
pub programming_interface_bytes: Volatile<u8>,
|
||||
pub subclass: Volatile<u8>,
|
||||
pub class_code: Volatile<u8>,
|
||||
pub cache_line_size: Volatile<u8>,
|
||||
pub latency_timer: Volatile<u8>,
|
||||
pub header_type: Volatile<u8>,
|
||||
pub bist: Volatile<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PciBar {
|
||||
B32(PciBar32),
|
||||
B64(PciBar64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PciBar32(*mut u32);
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PciBar64(*mut u64);
|
||||
|
||||
#[repr(C, packed)]
|
||||
pub struct PciGeneralHeader {
|
||||
pub common_header: Volatile<PciHeader>,
|
||||
pub bars: [Volatile<u32>; 6],
|
||||
pub cardbus_cis_pointer: Volatile<u32>,
|
||||
pub subsystem_vendor_id: Volatile<u16>,
|
||||
pub subsystem_id: Volatile<u16>,
|
||||
pub expansion_rom_base_address: Volatile<u32>,
|
||||
pub capabilities_pointer: Volatile<u8>,
|
||||
pub _reserved1: [Volatile<u8>; 7],
|
||||
pub interrupt_line: Volatile<u8>,
|
||||
pub interrupt_pin: Volatile<u8>,
|
||||
pub min_grant: Volatile<u8>,
|
||||
pub max_lantency: Volatile<u8>,
|
||||
}
|
||||
|
||||
pub struct PciGeneralDevice {
|
||||
pub bus: u8,
|
||||
pub device: u8,
|
||||
pub inner: *mut PciGeneralHeader,
|
||||
}
|
||||
|
||||
impl Deref for PciGeneralDevice {
|
||||
type Target = PciDevice;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*(self as *const Self as *const Self::Target) }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PciGeneralDevice {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PciDevice {
|
||||
pub fn new(bus: u8, device: u8) -> Self {
|
||||
Self { bus, device }
|
||||
let addr = PCI_ECAM_BASE | ((bus as usize) << 20) | ((device as usize) << 15);
|
||||
Self {
|
||||
bus,
|
||||
device,
|
||||
inner: addr as *mut PciHeader,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vendor_and_device_id(&self) -> (u16, u16) {
|
||||
let id = self.read::<u32>(0);
|
||||
((id & 0xFFFF) as u16, (id >> 16) as u16)
|
||||
(self.get_vendor_id(), self.get_device_id())
|
||||
}
|
||||
pub fn device_id(&self) -> u16 {
|
||||
self.vendor_and_device_id().1
|
||||
pub fn get_device_id(&self) -> u16 {
|
||||
unsafe { (&raw const (*self.inner).device_id).read() }
|
||||
}
|
||||
pub fn vendor_id(&self) -> u16 {
|
||||
self.vendor_and_device_id().0
|
||||
pub fn get_vendor_id(&self) -> u16 {
|
||||
unsafe { (*self.inner).vendor_id }
|
||||
}
|
||||
|
||||
pub fn interrupt_pin(&self) -> u8 {
|
||||
self.read(0x3D)
|
||||
pub fn get_command(&self) -> u16 {
|
||||
unsafe { (*self.inner).command }
|
||||
}
|
||||
|
||||
fn read<T>(&self, offset: u16) -> T {
|
||||
pci_read(self.bus, self.device, 0, offset)
|
||||
}
|
||||
|
||||
fn write_u32(&self, offset: u16, value: u32) {
|
||||
pci_write(self.bus, self.device, 0, offset, value)
|
||||
pub fn set_command(&mut self, command: u16) {
|
||||
unsafe { (*self.inner).command = command }
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// `self` must be a valid general PCI device.
|
||||
pub unsafe fn to_general_device(self) -> PciGeneralDevice {
|
||||
PciGeneralDevice(self)
|
||||
unsafe { core::mem::transmute::<PciDevice, PciGeneralDevice>(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PciGeneralDevice {
|
||||
pub fn get_interrupt_pin(&self) -> u8 {
|
||||
unsafe { (*self.inner).interrupt_pin }
|
||||
}
|
||||
pub fn set_interrupt_irq(&mut self, irq: u8) {
|
||||
unsafe { (*self.inner).interrupt_line = irq }
|
||||
}
|
||||
|
||||
pub fn get_bar(&mut self, i: u8) -> PciBar {
|
||||
unsafe { PciBar((&raw mut (*self.inner).bars as *mut u32).add(i as usize)) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PciBarIterator {
|
||||
pub current: u8,
|
||||
pub base_addr: *mut u32,
|
||||
}
|
||||
|
||||
impl Iterator for PciBarIterator {
|
||||
type Item = PciBar;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.current >= 6 {
|
||||
None
|
||||
} else {
|
||||
let res = if unsafe { *(self.base_addr.add(self.current as usize)) & 0b100 != 0 } {
|
||||
self.current += 1;
|
||||
PciBar64
|
||||
} else {
|
||||
};
|
||||
self.current += 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PciBar {
|
||||
pub fn as_ptr(self) -> *const u8 {
|
||||
self.0 as *const u8
|
||||
}
|
||||
pub fn as_mut_ptr(self) -> *mut u8 {
|
||||
self.0 as *mut u8
|
||||
}
|
||||
pub fn is_64bits(self) -> bool {
|
||||
unsafe { *self.0 & 0b100 != 0 }
|
||||
}
|
||||
pub fn is_prefetchable(self) -> bool {
|
||||
unsafe { *self.0 & 0b1000 != 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,10 +230,22 @@ pub fn scan_pci_for_virtio_keyboard2() -> Option<VirtioPciCaps> {
|
||||
let device = PciDeviceIterator::new()
|
||||
.find(|device| device.vendor_and_device_id() == (0x1af4, 0x1052))
|
||||
.unwrap();
|
||||
let device = unsafe {
|
||||
let mut device = unsafe {
|
||||
// VirtIO keyboard is a general PCI device
|
||||
device.to_general_device()
|
||||
};
|
||||
let interrupt_pin = device.get_interrupt_pin();
|
||||
let irq = 32 + (device.device + interrupt_pin - 1) % 4;
|
||||
device.set_interrupt_irq(irq);
|
||||
|
||||
let command = device.get_command() | 0b110;
|
||||
device.set_command(command);
|
||||
|
||||
for i in 0..6 {
|
||||
let bar = device.get_bar(i);
|
||||
println!("bar {} {:x?} 64: {}", i, bar, bar.is_64bits())
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@@ -133,22 +260,22 @@ pub fn scan_pci_for_virtio_keyboard() -> Option<VirtioPciCaps> {
|
||||
// et le Device ID Keyboard (0x1012 ou 0x1052 pour Modern)
|
||||
if vendor == 0x1af4 && (device >= 0x1000 && device <= 0x107f) {
|
||||
// Dans ta boucle de scan, après avoir trouvé le device
|
||||
let interrupt_pin = (pci_read::<u32>(0, dev, 0, 0x3C) >> 8) & 0xFF; // Offset 0x3D
|
||||
let irq = 32 + (dev as u32 + interrupt_pin - 1) % 4;
|
||||
// let interrupt_pin = (pci_read::<u32>(0, dev, 0, 0x3C) >> 8) & 0xFF; // Offset 0x3D
|
||||
// let irq = 32 + (dev as u32 + interrupt_pin - 1) % 4;
|
||||
|
||||
let old_val = pci_read::<u32>(0, 2, 0, 0x3C);
|
||||
// // 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;
|
||||
// // 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);
|
||||
// // 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);
|
||||
// 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;
|
||||
@@ -158,8 +285,8 @@ pub fn scan_pci_for_virtio_keyboard() -> Option<VirtioPciCaps> {
|
||||
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);
|
||||
// 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;
|
||||
|
||||
12
src/volatile.rs
Normal file
12
src/volatile.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Volatile<T>(T);
|
||||
|
||||
impl<T> Volatile<T> {
|
||||
pub unsafe fn read(self: *const Self) -> T {
|
||||
unsafe { core::ptr::read_volatile(self as *const T) }
|
||||
}
|
||||
pub unsafe fn write(self: *mut Self, value: T) {
|
||||
unsafe { core::ptr::write_volatile(self as *mut T, value) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user