feat: integra renaser (kernel SASOS bare-metal) al monorepo
1// =============================================================================
2// renaser :: kernel/src/drivers/pci.rs — Fase 6.1 :: el acceso al bus PCI
3// -----------------------------------------------------------------------------
4// El cargador `bootloader` entrega el mapa de memoria y el framebuffer, pero
5// NO un censo de perifericos: descubrir el disco es tarea del kernel. Aqui
6// renaser habla con el espacio de configuracion del bus PCI a traves del
7// mecanismo #1 —los puertos 0xCF8 (direccion) y 0xCFC (datos)—.
8//
9// Este modulo provee `CamPuertos`, una implementacion del rasgo
10// `ConfigurationAccess` de `virtio-drivers`: la crate enumera el bus y mapea
11// los BARs del dispositivo apoyandose en estas dos funciones de acceso.
12// =============================================================================
13
14use virtio_drivers::transport::pci::bus::{ConfigurationAccess, DeviceFunction};
15use x86_64::instructions::port::Port;
16
17/// Puerto de DIRECCION del mecanismo de configuracion PCI #1.
18const CONFIG_ADDRESS: u16 = 0xCF8;
19/// Puerto de DATOS del mecanismo de configuracion PCI #1.
20const CONFIG_DATA: u16 = 0xCFC;
21
22/// Compone la palabra de direccion del mecanismo #1: bit 31 de habilitacion,
23/// bus, dispositivo, funcion y offset de registro alineado a dword.
24fn direccion(device_function: DeviceFunction, offset: u8) -> u32 {
25 0x8000_0000
26 | ((device_function.bus as u32) << 16)
27 | ((device_function.device as u32) << 11)
28 | ((device_function.function as u32) << 8)
29 | ((offset as u32) & 0xFC)
30}
31
32/// Lee un registro de 32 bits del espacio de configuracion PCI.
33fn leer(device_function: DeviceFunction, offset: u8) -> u32 {
34 // SEGURIDAD: 0xCF8/0xCFC son los puertos del mecanismo de configuracion
35 // PCI #1, fijos en la arquitectura PC. La direccion lleva su bit de
36 // habilitacion y el offset alineado a dword, como exige el protocolo.
37 unsafe {
38 Port::<u32>::new(CONFIG_ADDRESS).write(direccion(device_function, offset));
39 Port::<u32>::new(CONFIG_DATA).read()
40 }
41}
42
43/// Escribe un registro de 32 bits en el espacio de configuracion PCI.
44fn escribir(device_function: DeviceFunction, offset: u8, dato: u32) {
45 // SEGURIDAD: vease `leer` — mismos puertos, mismo protocolo del 8259/PCI.
46 unsafe {
47 Port::<u32>::new(CONFIG_ADDRESS).write(direccion(device_function, offset));
48 Port::<u32>::new(CONFIG_DATA).write(dato);
49 }
50}
51
52/// Lee el registro «Interrupt Line» (byte bajo del offset 0x3C): la linea de
53/// IRQ del PIC que el firmware UEFI enruto y asigno a este dispositivo. Es el
54/// puente entre el descubrimiento PCI y el manejo de interrupciones (Fase 6.2).
55pub fn linea_irq(device_function: DeviceFunction) -> u8 {
56 (leer(device_function, 0x3C) & 0xFF) as u8
57}
58
59/// Acceso al espacio de configuracion PCI por puertos de E/S — el mecanismo #1.
60/// Es un tipo sin estado: toda la informacion viaja en cada llamada.
61pub struct CamPuertos;
62
63impl ConfigurationAccess for CamPuertos {
64 fn read_word(&self, device_function: DeviceFunction, register_offset: u8) -> u32 {
65 leer(device_function, register_offset)
66 }
67
68 fn write_word(&mut self, device_function: DeviceFunction, register_offset: u8, data: u32) {
69 escribir(device_function, register_offset, data);
70 }
71
72 unsafe fn unsafe_clone(&self) -> Self {
73 // `CamPuertos` no tiene estado: clonarlo es trivial y sin riesgo.
74 CamPuertos
75 }
76}