4
1
mirror of https://github.com/DragonOS-Community/DragonOS.git synced 2025-06-21 13:16:35 +00:00

完成中断管理模块重构 (#554)

- 支持中断共享
- 把现有驱动程序移植到新的irq模块
- 使用`ProcessorId`标识处理器id
- 尚未实现threaded_irq

性能上,edge irq flow handler里面,对于锁的使用,可能有点问题。为了获取/修改common data还有其他几个结构体的状态,进行了多次加锁和放锁,导致性能降低。这是接下来需要优化的点。
This commit is contained in:
LoGin
2024-03-03 16:31:08 +08:00
committed by GitHub
parent 44d051e586
commit e28411791f
108 changed files with 4504 additions and 2203 deletions

@ -1,7 +1,7 @@
CFLAGS += -I .
kernel_driver_subdirs:=pci acpi disk keyboard mouse multiboot2 timers hid
kernel_driver_subdirs:=acpi disk multiboot2 timers hid
ECHO:
@echo "$@"

@ -50,7 +50,7 @@ pub fn driver_manager() -> &'static DriverManager {
/// 否则在运行时会报错
pub trait Driver: Sync + Send + Debug + KObject {
fn coredump(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
Err(SystemError::ENOSYS)
}
/// @brief: 获取驱动标识符

@ -9,6 +9,7 @@ use crate::{
acpi::glue::acpi_device_notify,
base::map::{LockedDevsMap, LockedKObjMap},
},
exception::irqdata::IrqHandlerData,
filesystem::{
sysfs::{
file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
@ -875,7 +876,7 @@ impl DeviceMatcher<&str> for DeviceMatchName {
}
/// Cookie to identify the device
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Hash)]
pub struct DeviceId {
data: Option<&'static str>,
allocated: Option<String>,
@ -883,7 +884,7 @@ pub struct DeviceId {
impl DeviceId {
#[allow(dead_code)]
pub fn new(data: Option<&'static str>, allocated: Option<String>) -> Option<Self> {
pub fn new(data: Option<&'static str>, allocated: Option<String>) -> Option<Arc<Self>> {
if data.is_none() && allocated.is_none() {
return None;
}
@ -893,7 +894,7 @@ impl DeviceId {
return None;
}
return Some(Self { data, allocated });
return Some(Arc::new(Self { data, allocated }));
}
pub fn id(&self) -> Option<&str> {
@ -904,6 +905,7 @@ impl DeviceId {
}
}
#[allow(dead_code)]
pub fn set_allocated(&mut self, allocated: String) {
self.allocated = Some(allocated);
self.data = None;
@ -915,3 +917,7 @@ impl PartialEq for DeviceId {
return self.id() == other.id();
}
}
impl Eq for DeviceId {}
impl IrqHandlerData for DeviceId {}

@ -1 +1,46 @@
use bitfield_struct::bitfield;
pub mod ps2_device;
/// PS2键盘控制器的状态寄存器
#[bitfield(u8)]
pub struct Ps2StatusRegister {
/// 输出缓冲区满标志
///
/// (必须在尝试从 IO 端口 0x60 读取数据之前设置)
pub outbuf_full: bool,
/// 输入缓冲区满标志
///
/// (在尝试向 IO 端口 0x60 或 IO 端口 0x64 写入数据之前必须清除)
pub inbuf_full: bool,
/// 系统标志
///
/// 如果系统通过自检 (POST),则意味着在复位时被清除并由固件设置(通过 PS/2 控制器配置字节)
pub system_flag: bool,
/// 命令/数据标志
///
/// 0 = 写入输入缓冲区的数据是 PS/2 设备的数据1 = 写入输入缓冲区的数据是 PS/2 控制器命令的数据)
pub command_data: bool,
/// 未知标志1
///
/// 可能是“键盘锁”(现代系统中更可能未使用)
pub unknown1: bool,
/// 未知标志2
///
/// 可能是“接收超时”或“第二个 PS/2 端口输出缓冲区已满”
pub unknown2: bool,
/// 超时错误标志
///
/// 超时错误0 = 无错误1 = 超时错误)
pub timeout_error: bool,
/// 奇偶校验错误标志
///
/// 0 = 无错误1 = 奇偶校验错误)
pub parity_error: bool,
}

@ -3,6 +3,7 @@ use core::hint::spin_loop;
use alloc::{
string::ToString,
sync::{Arc, Weak},
vec::Vec,
};
use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer};
use system_error::SystemError;
@ -637,7 +638,7 @@ impl IndexNode for Ps2MouseDevice {
self
}
fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
fn list(&self) -> Result<Vec<alloc::string::String>, SystemError> {
todo!()
}

@ -10,7 +10,7 @@ use crate::{
arch::{io::PortIOArch, CurrentPortIOArch},
driver::{
base::{
device::{bus::Bus, driver::Driver, Device, IdTable},
device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable},
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
},
@ -19,6 +19,12 @@ use crate::{
serio_driver::{serio_driver_manager, SerioDriver},
},
},
exception::{
irqdata::IrqHandlerData,
irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
manage::irq_manager,
IrqNumber,
},
filesystem::kernfs::KernFSInode,
init::initcall::INITCALL_DEVICE,
libs::{
@ -29,18 +35,30 @@ use crate::{
use super::ps_mouse_device::{ps2_mouse_device, Ps2MouseDevice};
extern "C" {
fn c_ps2_mouse_init();
}
const PS2_MOUSE_IRQ_NUM: IrqNumber = IrqNumber::new(0x2c);
#[no_mangle]
unsafe extern "C" fn ps2_mouse_driver_interrupt() {
if let Some(psmouse_device) = ps2_mouse_device() {
ps2_mouse_driver()
.interrupt(&(psmouse_device as Arc<dyn SerioDevice>), 0, 0)
.ok();
} else {
unsafe { CurrentPortIOArch::in8(0x60) };
unsafe extern "C" fn ps2_mouse_driver_interrupt() {}
#[derive(Debug)]
struct Ps2MouseIrqHandler;
impl IrqHandler for Ps2MouseIrqHandler {
fn handle(
&self,
_irq: IrqNumber,
_static_data: Option<&dyn IrqHandlerData>,
_dev_id: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
if let Some(psmouse_device) = ps2_mouse_device() {
return Ok(ps2_mouse_driver()
.interrupt(&(psmouse_device as Arc<dyn SerioDevice>), 0, 0)
.map(|_| IrqReturn::Handled)
.unwrap_or_else(|_| IrqReturn::NotHandled));
} else {
unsafe { CurrentPortIOArch::in8(0x60) };
return Ok(IrqReturn::NotHandled);
}
}
}
@ -226,7 +244,13 @@ impl SerioDriver for Ps2MouseDriver {
device.set_driver(Some(self.inner.lock_irqsave().self_ref.clone()));
device.init()?;
unsafe { c_ps2_mouse_init() };
irq_manager().request_irq(
PS2_MOUSE_IRQ_NUM,
"psmouse".to_string(),
&Ps2MouseIrqHandler,
IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_TRIGGER_RISING,
Some(DeviceId::new(Some(Self::NAME), None).unwrap()),
)?;
return Ok(());
}

@ -1,10 +0,0 @@
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
CFLAGS += -I .
.PHONY: all
all: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

@ -1,24 +1 @@
use crate::init::initcall::INITCALL_LATE;
use core::ffi::c_void;
use system_error::SystemError;
use unified_init::macros::unified_init;
pub mod ps2_keyboard;
// pub mod ps2_keyboard_inode;
extern "C" {
fn ps2_keyboard_init() -> c_void;
}
/// 初始化ps2键盘
///
/// todo: 将ps2键盘适配到设备驱动模型后把初始化时机改为INITCALL_DEVICE
///
/// 当前是LATE的原因是键盘驱动的TypeOneFSM需要在tty设备初始化之后才能工作。
#[unified_init(INITCALL_LATE)]
fn rs_ps2_keyboard_init() -> Result<(), SystemError> {
unsafe {
ps2_keyboard_init();
}
return Ok(());
}

@ -1,209 +0,0 @@
#include "ps2_keyboard.h"
#include <arch/x86_64/driver/apic/apic.h>
#include <mm/mm.h>
#include <mm/slab.h>
#include <common/printk.h>
#include <filesystem/vfs/VFS.h>
#include <common/spinlock.h>
#include <common/kfifo.h>
// 键盘输入缓冲区
static struct kfifo_t kb_buf;
extern void ps2_keyboard_register(struct vfs_file_operations_t *);
extern void ps2_keyboard_parse_keycode(uint8_t input);
// 缓冲区读写锁
static spinlock_t ps2_kb_buf_rw_lock;
/**
* @brief 重置ps2键盘输入缓冲区
*
* @param kbp 缓冲区对象指针
*/
static void ps2_keyboard_reset_buffer(struct kfifo_t *kbp)
{
kfifo_reset(kbp);
}
struct apic_IO_APIC_RTE_entry entry;
hardware_intr_controller ps2_keyboard_intr_controller =
{
.enable = apic_ioapic_enable,
.disable = apic_ioapic_disable,
.install = apic_ioapic_install,
.uninstall = apic_ioapic_uninstall,
.ack = apic_ioapic_edge_ack,
};
/**
* @brief 打开键盘文件
*
* @param inode 所在的inode
* @param filp 文件指针
* @return long
*/
long ps2_keyboard_open(void *inode, void *filp)
{
ps2_keyboard_reset_buffer(&kb_buf);
return 0;
}
/**
* @brief 关闭键盘文件
*
* @param inode 所在的inode
* @param filp 文件指针
* @return long
*/
long ps2_keyboard_close(void *inode, void *filp)
{
ps2_keyboard_reset_buffer(&kb_buf);
return 0;
}
/**
* @brief 键盘io控制接口
*
* @param inode 所在的inode
* @param filp 键盘文件指针
* @param cmd 命令
* @param arg 参数
* @return long
*/
long ps2_keyboard_ioctl(void *inode, void *filp, uint64_t cmd, uint64_t arg)
{
switch (cmd)
{
case KEYBOARD_CMD_RESET_BUFFER:
ps2_keyboard_reset_buffer(&kb_buf);
break;
default:
break;
}
return 0;
}
/**
* @brief 读取键盘文件的操作接口
*
* @param filp 文件指针
* @param buf 输出缓冲区
* @param count 要读取的字节数
* @param position 读取的位置
* @return long 读取的字节数
*/
long ps2_keyboard_read(void *filp, char *buf, int64_t count, long *position)
{
// 缓冲区为空则等待
while (kfifo_empty(&kb_buf))
;
count = (count > kb_buf.size) ? kb_buf.size : count;
return kfifo_out(&kb_buf, buf, count);
}
/**
* @brief 键盘文件写入接口(无作用,空)
*
* @param filp
* @param buf
* @param count
* @param position
* @return long
*/
long ps2_keyboard_write(void *filp, char *buf, int64_t count, long *position)
{
return 0;
}
/**
* @brief ps2键盘驱动的虚拟文件接口
*
*/
struct vfs_file_operations_t ps2_keyboard_fops =
{
.open = ps2_keyboard_open,
.close = ps2_keyboard_close,
.ioctl = ps2_keyboard_ioctl,
.read = ps2_keyboard_read,
.write = ps2_keyboard_write,
};
/**
* @brief 键盘中断处理函数(中断上半部)
* 将数据存入缓冲区
* @param irq_num 中断向量号
* @param param 参数
* @param regs 寄存器信息
*/
void ps2_keyboard_handler(ul irq_num, ul buf_vaddr, struct pt_regs *regs)
{
unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA);
ps2_keyboard_parse_keycode((uint8_t)x);
}
/**
* @brief 初始化键盘驱动程序的函数
*
*/
void ps2_keyboard_init()
{
// ======= 初始化键盘循环队列缓冲区 ===========
// 初始化键盘循环队列缓冲区
kfifo_alloc(&kb_buf, ps2_keyboard_buffer_size, 0);
// ======== 初始化中断RTE entry ==========
entry.vector = PS2_KEYBOARD_INTR_VECTOR; // 设置中断向量号
entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合
entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断
entry.deliver_status = IDLE;
entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发
entry.polarity = POLARITY_HIGH; // 高电平触发
entry.remote_IRR = IRR_RESET;
entry.mask = MASKED;
entry.reserved = 0;
entry.destination.physical.reserved1 = 0;
entry.destination.physical.reserved2 = 0;
entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器
// ======== 初始化键盘控制器,写入配置值 =========
wait_ps2_keyboard_write();
io_out8(PORT_PS2_KEYBOARD_CONTROL, PS2_KEYBOARD_COMMAND_WRITE);
wait_ps2_keyboard_write();
io_out8(PORT_PS2_KEYBOARD_DATA, PS2_KEYBOARD_PARAM_INIT);
wait_ps2_keyboard_write();
// 执行一百万次nop等待键盘控制器把命令执行完毕
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < 1000; ++j)
nop();
// 初始化键盘缓冲区的读写锁
spin_init(&ps2_kb_buf_rw_lock);
// 注册中断处理程序
irq_register(PS2_KEYBOARD_INTR_VECTOR, &entry, &ps2_keyboard_handler, (ul)&kb_buf, &ps2_keyboard_intr_controller, "ps/2 keyboard");
// 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。
io_in8(PORT_PS2_KEYBOARD_DATA);
// 将设备挂载到devfs
ps2_keyboard_register(&ps2_keyboard_fops);
kinfo("ps/2 keyboard registered.");
}
/**
* @brief 键盘驱动卸载函数
*
*/
void ps2_keyboard_exit()
{
irq_unregister(PS2_KEYBOARD_INTR_VECTOR);
kfifo_free_alloc(&kb_buf);
}

@ -1,40 +0,0 @@
#pragma once
#include <common/glib.h>
#define PS2_KEYBOARD_INTR_VECTOR 0x21 // 键盘的中断向量号
// 定义键盘循环队列缓冲区大小为100bytes
#define ps2_keyboard_buffer_size 8
#define KEYBOARD_CMD_RESET_BUFFER 1
#define PORT_PS2_KEYBOARD_DATA 0x60
#define PORT_PS2_KEYBOARD_STATUS 0x64
#define PORT_PS2_KEYBOARD_CONTROL 0x64
#define PS2_KEYBOARD_COMMAND_WRITE 0x60 // 向键盘发送配置命令
#define PS2_KEYBOARD_COMMAND_READ 0x20 // 读取键盘的配置值
#define PS2_KEYBOARD_PARAM_INIT 0x47 // 初始化键盘控制器的配置值
// ========= 检测键盘控制器输入/输出缓冲区是否已满
#define PS2_KEYBOARD_FLAG_OUTBUF_FULL 0x01 // 键盘的输出缓冲区已满标志位
#define PS2_KEYBOARD_FLAG_INBUF_FULL 0x02 // 键盘的输入缓冲区已满标志位
// 等待向键盘控制器写入信息完成
// todo: bugfix:在不包含ps2键盘控制器的机器上这里会卡死
#define wait_ps2_keyboard_write() \
while (io_in8(PORT_PS2_KEYBOARD_STATUS) & PS2_KEYBOARD_FLAG_INBUF_FULL)
// #define wait_ps2_keyboard_write() (1)
// 等待从键盘控制器读取信息完成
#define wait_ps2_keyboard_read() \
while (io_in8(PORT_PS2_KEYBOARD_STATUS) & PS2_KEYBOARD_FLAG_OUTBUF_FULL)
// #define wait_ps2_keyboard_read() (1)
extern struct vfs_file_operations_t ps2_keyboard_fops;
/**
* @brief 键盘驱动卸载函数
*
*/
void ps2_keyboard_exit();

@ -1,9 +1,24 @@
use core::{ffi::c_void, sync::atomic::AtomicI32};
use core::hint::spin_loop;
use alloc::sync::{Arc, Weak};
use alloc::{
string::ToString,
sync::{Arc, Weak},
};
use unified_init::macros::unified_init;
use crate::{
driver::base::device::device_number::{DeviceNumber, Major},
arch::{io::PortIOArch, CurrentPortIOArch},
driver::{
base::device::device_number::{DeviceNumber, Major},
input::ps2_dev::Ps2StatusRegister,
},
exception::{
irqdata::IrqHandlerData,
irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
manage::irq_manager,
IrqNumber,
},
filesystem::{
devfs::{devfs_register, DevFS, DeviceINode},
vfs::{
@ -11,13 +26,30 @@ use crate::{
FileSystem, FileType, IndexNode, Metadata,
},
},
include::bindings::bindings::vfs_file_operations_t,
init::initcall::INITCALL_DEVICE,
libs::{keyboard_parser::TypeOneFSM, rwlock::RwLock, spinlock::SpinLock},
time::TimeSpec,
};
use system_error::SystemError;
/// PS2键盘的中断向量号
const PS2_KEYBOARD_INTR_VECTOR: IrqNumber = IrqNumber::new(0x21);
const PORT_PS2_KEYBOARD_DATA: u8 = 0x60;
const PORT_PS2_KEYBOARD_STATUS: u8 = 0x64;
const PORT_PS2_KEYBOARD_CONTROL: u8 = 0x64;
/// 向键盘发送配置命令
const PS2_KEYBOARD_COMMAND_WRITE: u8 = 0x60;
/// 读取键盘的配置值
#[allow(dead_code)]
const PS2_KEYBOARD_COMMAND_READ: u8 = 0x20;
/// 初始化键盘控制器的配置值
const PS2_KEYBOARD_PARAM_INIT: u8 = 0x47;
#[derive(Debug)]
pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>, AtomicI32); // self.1 用来记录有多少个文件打开了这个inode
pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>);
lazy_static! {
static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = SpinLock::new(TypeOneFSM::new());
@ -33,17 +65,14 @@ pub struct PS2KeyBoardInode {
fs: Weak<DevFS>,
/// INode 元数据
metadata: Metadata,
/// 键盘操作函数
f_ops: vfs_file_operations_t,
}
impl LockedPS2KeyBoardInode {
pub fn new(f_ops: &vfs_file_operations_t) -> Arc<Self> {
pub fn new() -> Arc<Self> {
let inode = PS2KeyBoardInode {
// uuid: Uuid::new_v5(),
self_ref: Weak::default(),
fs: Weak::default(),
f_ops: f_ops.clone(), // 从引用复制一遍获取所有权
metadata: Metadata {
dev_id: 1,
inode_id: generate_inode_id(),
@ -62,10 +91,7 @@ impl LockedPS2KeyBoardInode {
},
};
let result = Arc::new(LockedPS2KeyBoardInode(
RwLock::new(inode),
AtomicI32::new(0),
));
let result = Arc::new(LockedPS2KeyBoardInode(RwLock::new(inode)));
result.0.write().self_ref = Arc::downgrade(&result);
return result;
@ -78,9 +104,8 @@ impl DeviceINode for LockedPS2KeyBoardInode {
}
}
#[no_mangle] // 不重命名
pub extern "C" fn ps2_keyboard_register(f_ops: &vfs_file_operations_t) {
devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new(f_ops))
fn ps2_keyboard_register() {
devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new())
.expect("Failed to register ps/2 keyboard");
}
@ -88,21 +113,11 @@ impl IndexNode for LockedPS2KeyBoardInode {
fn read_at(
&self,
_offset: usize,
len: usize,
buf: &mut [u8],
_len: usize,
_buf: &mut [u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
let guard = self.0.read();
let func = guard.f_ops.read.unwrap();
let r = unsafe {
func(
0 as *mut c_void,
&mut buf[0..len] as *mut [u8] as *mut i8,
len as i64,
0 as *mut i64,
)
};
return Ok(r as usize);
return Err(SystemError::ENOSYS);
}
fn write_at(
@ -112,28 +127,14 @@ impl IndexNode for LockedPS2KeyBoardInode {
_buf: &[u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
return Err(SystemError::ENOSYS);
}
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
let prev_ref_count = self.1.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
if prev_ref_count == 0 {
// 第一次打开,需要初始化
let guard = self.0.write();
let func = guard.f_ops.open.unwrap();
let _ = unsafe { func(0 as *mut c_void, 0 as *mut c_void) };
}
return Ok(());
}
fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
let prev_ref_count = self.1.fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
if prev_ref_count == 1 {
// 最后一次关闭,需要释放
let guard = self.0.write();
let func = guard.f_ops.close.unwrap();
let _ = unsafe { func(0 as *mut c_void, 0 as *mut c_void) };
}
return Ok(());
}
@ -166,9 +167,85 @@ impl IndexNode for LockedPS2KeyBoardInode {
}
}
#[allow(dead_code)]
#[no_mangle]
/// for test
pub extern "C" fn ps2_keyboard_parse_keycode(input: u8) {
PS2_KEYBOARD_FSM.lock().parse(input);
#[derive(Debug)]
struct Ps2KeyboardIrqHandler;
impl IrqHandler for Ps2KeyboardIrqHandler {
fn handle(
&self,
_irq: IrqNumber,
_static_data: Option<&dyn IrqHandlerData>,
_dev_id: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
// 先检查状态寄存器,看看是否有数据
let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
let status = Ps2StatusRegister::from(status);
if !status.outbuf_full() {
return Ok(IrqReturn::NotHandled);
}
let input = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
// wait_ps2_keyboard_read();
PS2_KEYBOARD_FSM.lock().parse(input);
return Ok(IrqReturn::Handled);
}
}
impl Ps2KeyboardIrqHandler {
const INTR_HANDLE_FLAGS: IrqHandleFlags =
IrqHandleFlags::from_bits_truncate(IrqHandleFlags::IRQF_TRIGGER_RISING.bits());
}
/// 等待 PS/2 键盘的输入缓冲区为空
fn wait_ps2_keyboard_write() {
let mut status: Ps2StatusRegister;
loop {
status = Ps2StatusRegister::from(unsafe {
CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into())
});
if !status.inbuf_full() {
break;
}
spin_loop();
}
}
#[unified_init(INITCALL_DEVICE)]
fn ps2_keyboard_init() -> Result<(), SystemError> {
// ======== 初始化键盘控制器,写入配置值 =========
wait_ps2_keyboard_write();
unsafe {
CurrentPortIOArch::out8(PORT_PS2_KEYBOARD_CONTROL.into(), PS2_KEYBOARD_COMMAND_WRITE);
wait_ps2_keyboard_write();
CurrentPortIOArch::out8(PORT_PS2_KEYBOARD_DATA.into(), PS2_KEYBOARD_PARAM_INIT);
wait_ps2_keyboard_write();
}
// 执行一百万次nop等待键盘控制器把命令执行完毕
for _ in 0..1000000 {
spin_loop();
}
irq_manager()
.request_irq(
PS2_KEYBOARD_INTR_VECTOR,
"ps2keyboard".to_string(),
&Ps2KeyboardIrqHandler,
Ps2KeyboardIrqHandler::INTR_HANDLE_FLAGS,
None,
)
.expect("Failed to request irq for ps2 keyboard");
// 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。
let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
let status = Ps2StatusRegister::from(status);
if status.outbuf_full() {
unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
}
// 将设备挂载到devfs
ps2_keyboard_register();
Ok(())
}

@ -1,10 +0,0 @@
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
CFLAGS += -I .
.PHONY: all
all: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

@ -1,58 +0,0 @@
#include "ps2_mouse.h"
#include <arch/x86_64/driver/apic/apic.h>
#include <mm/mm.h>
#include <mm/slab.h>
#include <common/printk.h>
#include <common/kprint.h>
extern void ps2_mouse_driver_interrupt();
/**
* @brief 鼠标中断处理函数(中断上半部)
* 将数据存入缓冲区
* @param irq_num 中断向量号
* @param param 参数
* @param regs 寄存器信息
*/
void ps2_mouse_handler(ul irq_num, ul param, struct pt_regs *regs)
{
ps2_mouse_driver_interrupt();
}
struct apic_IO_APIC_RTE_entry ps2_mouse_entry;
hardware_intr_controller ps2_mouse_intr_controller =
{
.enable = apic_ioapic_enable,
.disable = apic_ioapic_disable,
.install = apic_ioapic_install,
.uninstall = apic_ioapic_uninstall,
.ack = apic_ioapic_edge_ack,
};
/**
* @brief 初始化鼠标驱动程序
*
*/
void c_ps2_mouse_init()
{
// ======== 初始化中断RTE entry ==========
ps2_mouse_entry.vector = PS2_MOUSE_INTR_VECTOR; // 设置中断向量号
ps2_mouse_entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合
ps2_mouse_entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断
ps2_mouse_entry.deliver_status = IDLE;
ps2_mouse_entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发
ps2_mouse_entry.polarity = POLARITY_HIGH; // 高电平触发
ps2_mouse_entry.remote_IRR = IRR_RESET;
ps2_mouse_entry.mask = MASKED;
ps2_mouse_entry.reserved = 0;
ps2_mouse_entry.destination.physical.reserved1 = 0;
ps2_mouse_entry.destination.physical.reserved2 = 0;
ps2_mouse_entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器
// 注册中断处理程序
irq_register(PS2_MOUSE_INTR_VECTOR, &ps2_mouse_entry, &ps2_mouse_handler, 0, &ps2_mouse_intr_controller, "ps/2 mouse");
}

@ -1,38 +0,0 @@
#pragma once
#include <common/glib.h>
#define PS2_MOUSE_INTR_VECTOR 0x2c // 鼠标的中断向量号
#define KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE 0xd4 // 键盘控制器向鼠标设备发送数据的命令
#define PS2_MOUSE_GET_ID 0xf2 // 获取鼠标的ID
#define PS2_MOUSE_SET_SAMPLING_RATE 0xf3 // 设置鼠标的采样率
#define PS2_MOUSE_ENABLE 0xf4 // 允许鼠标设备发送数据包
#define PS2_MOUSE_DISABLE 0xf5 // 禁止鼠标设备发送数据包
#define PS2_MOUSE_SET_DEFAULT_SAMPLING_RATE 0xf6 // 设置使用默认采样率100hz分辨率4px/mm
#define PS2_MOUSE_RESEND_LAST_PACKET 0xfe // 重新发送上一条数据包
#define PS2_MOUSE_RESET 0xff // 重启鼠标
#define KEYBOARD_COMMAND_ENABLE_PS2_MOUSE_PORT 0xa8 // 通过键盘控制器开启鼠标端口的命令
#define ps2_mouse_buffer_size 360
#define PORT_KEYBOARD_DATA 0x60
#define PORT_KEYBOARD_STATUS 0x64
#define PORT_KEYBOARD_CONTROL 0x64
#define KEYBOARD_COMMAND_WRITE 0x60 // 向键盘发送配置命令
#define KEYBOARD_COMMAND_READ 0x20 // 读取键盘的配置值
#define KEYBOARD_PARAM_INIT 0x47 // 初始化键盘控制器的配置值
// ========= 检测键盘控制器输入/输出缓冲区是否已满
#define KEYBOARD_FLAG_OUTBUF_FULL 0x01 // 键盘的输出缓冲区已满标志位
#define KEYBOARD_FLAG_INBUF_FULL 0x02 // 键盘的输入缓冲区已满标志位
/**
* @brief 初始化鼠标驱动程序
*
*/
void c_ps2_mouse_init();

@ -1,6 +1,8 @@
// 参考手册: PCIe* GbE Controllers Open Source Software Developers Manual
// Refernce: PCIe* GbE Controllers Open Source Software Developers Manual
use alloc::string::ToString;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::intrinsics::unlikely;
use core::mem::size_of;
@ -9,15 +11,18 @@ use core::slice::{from_raw_parts, from_raw_parts_mut};
use core::sync::atomic::{compiler_fence, Ordering};
use super::e1000e_driver::e1000e_driver_init;
use crate::driver::base::device::DeviceId;
use crate::driver::net::dma::{dma_alloc, dma_dealloc};
use crate::driver::net::irq_handle::DefaultNetIrqHandler;
use crate::driver::pci::pci::{
get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError,
PCI_DEVICE_LINKEDLIST,
};
use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ};
use crate::include::bindings::bindings::pt_regs;
use crate::exception::IrqNumber;
use crate::libs::volatile::{ReadOnly, Volatile, WriteOnly};
use crate::net::net_core::poll_ifaces_try_lock_onetime;
use crate::{kdebug, kinfo};
const PAGE_SIZE: usize = 4096;
@ -55,7 +60,7 @@ const E1000E_REG_SIZE: u8 = 4;
const E1000E_DMA_PAGES: usize = 1;
// 中断相关
const E1000E_RECV_VECTOR: u16 = 57;
const E1000E_RECV_VECTOR: IrqNumber = IrqNumber::new(57);
// napi队列中暂时存储的buffer个数
const E1000E_RECV_NAPI: usize = 1024;
@ -157,12 +162,6 @@ impl E1000EBuffer {
}
}
// 中断处理函数, 调用协议栈的poll函数未来可能会用napi来替换这里
// Interrupt handler
unsafe extern "C" fn e1000e_irq_handler(_irq_num: u64, _irq_paramer: u64, _regs: *mut pt_regs) {
poll_ifaces_try_lock_onetime().ok();
}
#[allow(dead_code)]
pub struct E1000EDevice {
// 设备寄存器
@ -201,7 +200,10 @@ impl E1000EDevice {
// 从PCI标准设备进行驱动初始化
// init the device for PCI standard device struct
#[allow(unused_assignments)]
pub fn new(device: &mut PciDeviceStructureGeneralDevice) -> Result<Self, E1000EPciError> {
pub fn new(
device: &mut PciDeviceStructureGeneralDevice,
device_id: Arc<DeviceId>,
) -> Result<Self, E1000EPciError> {
// 从BAR0获取我们需要的寄存器
// Build registers sturcts from BAR0
device.bar_ioremap().unwrap()?;
@ -230,10 +232,9 @@ impl E1000EDevice {
let msg = PciIrqMsg {
irq_common_message: IrqCommonMsg::init_from(
0,
"E1000E_RECV_IRQ",
0,
e1000e_irq_handler,
None,
"E1000E_RECV_IRQ".to_string(),
&DefaultNetIrqHandler,
device_id,
),
irq_specific_message: IrqSpecificMsg::msi_default(),
};
@ -619,7 +620,12 @@ pub fn e1000e_probe() -> Result<u64, E1000EPciError> {
"Detected e1000e PCI device with device id {:#x}",
header.device_id
);
let e1000e = E1000EDevice::new(standard_device)?;
// todo: 根据pci的path来生成device id
let e1000e = E1000EDevice::new(
standard_device,
DeviceId::new(None, Some(format!("e1000e_{}", header.device_id))).unwrap(),
)?;
e1000e_driver_init(e1000e);
}
}

@ -0,0 +1,27 @@
use alloc::sync::Arc;
use system_error::SystemError;
use crate::{
exception::{
irqdata::IrqHandlerData,
irqdesc::{IrqHandler, IrqReturn},
IrqNumber,
},
net::net_core::poll_ifaces_try_lock_onetime,
};
/// 默认的网卡中断处理函数
#[derive(Debug)]
pub struct DefaultNetIrqHandler;
impl IrqHandler for DefaultNetIrqHandler {
fn handle(
&self,
_irq: IrqNumber,
_static_data: Option<&dyn IrqHandlerData>,
_dynamic_data: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
poll_ifaces_try_lock_onetime().ok();
Ok(IrqReturn::Handled)
}
}

@ -10,6 +10,7 @@ use system_error::SystemError;
mod dma;
pub mod e1000e;
pub mod irq_handle;
pub mod virtio_net;
pub trait NetDriver: Driver {

@ -15,14 +15,15 @@ use super::NetDriver;
use crate::{
driver::{
base::{
device::{bus::Bus, driver::Driver, Device, IdTable},
device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable},
kobject::{KObjType, KObject, KObjectState},
},
virtio::virtio_impl::HalImpl,
virtio::{irq::virtio_irq_manager, virtio_impl::HalImpl, VirtIODevice},
},
exception::{irqdesc::IrqReturn, IrqNumber},
kerror, kinfo,
libs::spinlock::SpinLock,
net::{generate_iface_id, NET_DRIVERS},
net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DRIVERS},
time::Instant,
};
use system_error::SystemError;
@ -40,7 +41,8 @@ impl<T: Transport> Clone for VirtioNICDriver<T> {
}
}
/// @brief 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
/// 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
///
/// 由于smoltcp的设计导致需要在poll的时候获取网卡驱动的可变引用
/// 同时需要在token的consume里面获取可变引用。为了避免双重加锁所以需要这个包裹器。
struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>);
@ -76,6 +78,7 @@ pub struct VirtioInterface<T: Transport> {
iface_id: usize,
iface: SpinLock<smoltcp::iface::Interface>,
name: String,
dev_id: Arc<DeviceId>,
}
impl<T: Transport> Debug for VirtioInterface<T> {
@ -90,7 +93,7 @@ impl<T: Transport> Debug for VirtioInterface<T> {
}
impl<T: Transport> VirtioInterface<T> {
pub fn new(mut driver: VirtioNICDriver<T>) -> Arc<Self> {
pub fn new(mut driver: VirtioNICDriver<T>, dev_id: Arc<DeviceId>) -> Arc<Self> {
let iface_id = generate_iface_id();
let mut iface_config = smoltcp::iface::Config::new();
@ -109,12 +112,31 @@ impl<T: Transport> VirtioInterface<T> {
iface_id,
iface: SpinLock::new(iface),
name: format!("eth{}", iface_id),
dev_id,
});
return result;
}
}
impl<T: Transport + 'static> VirtIODevice for VirtioInterface<T> {
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
poll_ifaces_try_lock_onetime().ok();
return Ok(IrqReturn::Handled);
}
fn dev_id(&self) -> &Arc<DeviceId> {
return &self.dev_id;
}
}
impl<T: Transport> Drop for VirtioInterface<T> {
fn drop(&mut self) {
// 从全局的网卡接口信息表中删除这个网卡的接口信息
NET_DRIVERS.write_irqsave().remove(&self.iface_id);
}
}
impl<T: 'static + Transport> VirtioNICDriver<T> {
pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self {
let mut iface_config = smoltcp::iface::Config::new();
@ -223,7 +245,7 @@ impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
}
/// @brief virtio-net 驱动的初始化与测试
pub fn virtio_net<T: Transport + 'static>(transport: T) {
pub fn virtio_net<T: Transport + 'static>(transport: T, dev_id: Arc<DeviceId>) {
let driver_net: VirtIONet<HalImpl, T, 2> =
match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) {
Ok(net) => net,
@ -234,12 +256,16 @@ pub fn virtio_net<T: Transport + 'static>(transport: T) {
};
let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address());
let driver: VirtioNICDriver<T> = VirtioNICDriver::new(driver_net);
let iface = VirtioInterface::new(driver);
let iface = VirtioInterface::new(driver, dev_id);
let name = iface.name.clone();
// 将网卡的接口信息注册到全局的网卡接口信息表中
NET_DRIVERS
.write_irqsave()
.insert(iface.nic_id(), iface.clone());
virtio_irq_manager()
.register_device(iface.clone())
.expect("Register virtio net failed");
kinfo!(
"Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]",
name,

@ -1,11 +0,0 @@
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
CFLAGS += -I .
.PHONY: all
all: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

@ -3,6 +3,7 @@
use super::pci_irq::{IrqType, PciIrqError};
use crate::arch::{PciArch, TraitPciArch};
use crate::exception::IrqNumber;
use crate::include::bindings::bindings::PAGE_2M_SIZE;
use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
@ -371,7 +372,7 @@ pub trait PciDeviceStructure: Send + Sync {
/// @brief 返回结构体中的irq_type的可变引用
fn irq_type_mut(&mut self) -> Option<&mut IrqType>;
/// @brief 返回结构体中的irq_vector的可变引用
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>>;
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>>;
}
/// Pci_Device_Structure_Header PCI设备结构体共有的头部
@ -404,7 +405,7 @@ pub struct PciDeviceStructureGeneralDevice {
// 中断结构体包括legacy,msi,msix三种情况
pub irq_type: IrqType,
// 使用的中断号的vec集合
pub irq_vector: Vec<u16>,
pub irq_vector: Vec<IrqNumber>,
pub standard_device_bar: PciStandardDeviceBar,
pub cardbus_cis_pointer: u32, // 指向卡信息结构,供在 CardBus 和 PCI 之间共享芯片的设备使用。
pub subsystem_vendor_id: u16,
@ -464,7 +465,7 @@ impl PciDeviceStructure for PciDeviceStructureGeneralDevice {
Some(&mut self.irq_type)
}
#[inline(always)]
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>> {
Some(&mut self.irq_vector)
}
}
@ -476,7 +477,7 @@ pub struct PciDeviceStructurePciToPciBridge {
// 中断结构体包括legacy,msi,msix三种情况
pub irq_type: IrqType,
// 使用的中断号的vec集合
pub irq_vector: Vec<u16>,
pub irq_vector: Vec<IrqNumber>,
pub bar0: u32,
pub bar1: u32,
pub primary_bus_number: u8,
@ -528,7 +529,7 @@ impl PciDeviceStructure for PciDeviceStructurePciToPciBridge {
Some(&mut self.irq_type)
}
#[inline(always)]
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>> {
Some(&mut self.irq_vector)
}
}
@ -587,7 +588,7 @@ impl PciDeviceStructure for PciDeviceStructurePciToCardbusBridge {
None
}
#[inline(always)]
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>> {
None
}
}

@ -1,95 +0,0 @@
#include "pci_irq.h"
#include "exception/irq.h"
#include <common/errno.h>
#include <common/kprint.h>
#include "common/string.h"
#include "mm/slab.h"
// 现在pci设备的中断由自己进行控制这些不执行内容的函数是为了适配旧的中断处理机制
void pci_irq_enable(ul irq_num)
{
}
void pci_irq_disable(ul irq_num)
{
}
ul pci_irq_install(ul num , void* data)
{
}
void pci_irq_uninstall(ul irq_num)
{
}
/// @brief 与本操作系统的中断机制进行交互把中断处理函数等注册到中断结构体中被rust调用
/// @param irq_num 要进行注册的中断号
/// @param pci_irq_handler 对应的中断处理函数
/// @param parameter 中断处理函数传入参数
/// @param irq_name 中断名字
/// @param pci_irq_ack 对于中断的回复为NULL时会使用默认回应
uint16_t c_irq_install(ul irq_num, void (*pci_irq_handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul parameter, const char *irq_name, void (*pci_irq_ack)(ul irq_num))
{
// 由于为I/O APIC分配的中断向量号是从32开始的因此要减去32才是对应的interrupt_desc的元素
irq_desc_t *p = NULL;
hardware_intr_controller *pci_interrupt_controller = NULL;
if (irq_num >= 32 && irq_num < 0x80)
p = &interrupt_desc[irq_num - 32];
else if (irq_num >= 150 && irq_num < 200)
p = &local_apic_interrupt_desc[irq_num - 150];
else
{
// kerror("irq install for pci irq: invalid irq num: %ld.", irq_num);
return EINVAL;
}
if (p->irq_name != NULL)
{
return EAGAIN;
}
pci_interrupt_controller = kzalloc(sizeof(hardware_intr_controller), 0);
if (pci_interrupt_controller)
{
pci_interrupt_controller->enable = pci_irq_enable;
pci_interrupt_controller->disable = pci_irq_disable;
pci_interrupt_controller->install = pci_irq_install;
pci_interrupt_controller->uninstall = pci_irq_uninstall;
pci_interrupt_controller->ack = pci_irq_ack;
p->controller = pci_interrupt_controller;
}
else
{
return EAGAIN;
}
size_t namelen = strlen(irq_name) + 1;
p->irq_name = (char *)kzalloc(namelen, 0);
memset(p->irq_name, 0, namelen);
strncpy(p->irq_name, irq_name, namelen);
p->parameter = parameter;
p->flags = 0;
p->handler = pci_irq_handler;
return 0;
};
/// @brief 与本操作系统的中断机制进行交互,把中断处理函数等从中断结构体中移除,需要释放空间的进行空间的释放
/// @param irq_num 要进行注销的中断号
void c_irq_uninstall(ul irq_num)
{
// 由于为I/O APIC分配的中断向量号是从32开始的因此要减去32才是对应的interrupt_desc的元素
irq_desc_t *p = NULL;
if (irq_num >= 32 && irq_num < 0x80)
p = &interrupt_desc[irq_num - 32];
else if (irq_num >= 150 && irq_num < 200)
p = &local_apic_interrupt_desc[irq_num - 150];
else
{
kerror("irq install for pci irq: invalid irq num: %ld.", irq_num);
}
if (p->irq_name != NULL)
{
kfree(p->irq_name);
p->irq_name = NULL;
}
if (p->controller != NULL)
{
kfree(p->controller);
p->controller = NULL;
}
p->parameter = 0;
p->handler = NULL;
}

@ -1,5 +0,0 @@
#pragma once
#include <common/glib.h>
#include <process/ptrace.h>
uint16_t c_irq_install(ul irq_num,void (*pci_irq_handler)(ul irq_num, ul parameter, struct pt_regs *regs),ul parameter,const char *irq_name,void (*pci_irq_ack)(ul irq_num));
void c_irq_uninstall(ul irq_num);

@ -3,16 +3,19 @@
use core::mem::size_of;
use core::ptr::NonNull;
use alloc::ffi::CString;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use system_error::SystemError;
use super::pci::{PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
use crate::arch::msi::{arch_msi_message_address, arch_msi_message_data};
use crate::arch::{PciArch, TraitPciArch};
use crate::include::bindings::bindings::{
c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
};
use crate::driver::base::device::DeviceId;
use crate::exception::irqdesc::{IrqHandleFlags, IrqHandler};
use crate::exception::manage::irq_manager;
use crate::exception::IrqNumber;
use crate::libs::volatile::{volread, volwrite, Volatile};
/// MSIX表的一项
@ -37,8 +40,8 @@ pub enum PciIrqError {
PciDeviceNotSupportIrq,
IrqTypeUnmatch,
InvalidIrqIndex(u16),
InvalidIrqNum(u16),
IrqNumOccupied(u16),
InvalidIrqNum(IrqNumber),
IrqNumOccupied(IrqNumber),
DeviceIrqOverflow,
MxiIrqNumWrong,
PciBarNotInited,
@ -78,29 +81,35 @@ pub struct PciIrqMsg {
// PCI设备install中断时需要传递的共同参数
#[derive(Clone, Debug)]
pub struct IrqCommonMsg {
irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index
irq_name: CString, //中断名字
irq_parameter: u16, //中断额外参数,可传入中断处理函数
irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), // 中断处理函数
irq_ack: Option<unsafe extern "C" fn(irq_num: ul)>, // 中断的ack可为None,若为None则中断处理中会正常通知中断结束不为None则调用传入的函数进行回复
irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index
irq_name: String, //中断名字
irq_hander: &'static dyn IrqHandler, // 中断处理函数
/// 全局设备标志符
dev_id: Arc<DeviceId>,
}
impl IrqCommonMsg {
pub fn init_from(
irq_index: u16,
irq_name: &str,
irq_parameter: u16,
irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs),
irq_ack: Option<unsafe extern "C" fn(irq_num: ul)>,
irq_name: String,
irq_hander: &'static dyn IrqHandler,
dev_id: Arc<DeviceId>,
) -> Self {
IrqCommonMsg {
irq_index,
irq_name: CString::new(irq_name).expect("CString::new failed"),
irq_parameter,
irq_name,
irq_hander,
irq_ack,
dev_id,
}
}
pub fn set_handler(&mut self, irq_hander: &'static dyn IrqHandler) {
self.irq_hander = irq_hander;
}
pub fn dev_id(&self) -> &Arc<DeviceId> {
&self.dev_id
}
}
// PCI设备install中断时需要传递的特有参数Msi代表MSI与MSIX
@ -347,28 +356,43 @@ pub trait PciInterrupt: PciDeviceStructure {
}
let irq_num =
self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize];
let irq_num = IrqNumber::new(irq_num.into());
let common_msg = &msg.irq_common_message;
let result = unsafe {
c_irq_install(
irq_num as u64,
Some(common_msg.irq_hander),
common_msg.irq_parameter as u64,
common_msg.irq_name.as_ptr(),
common_msg.irq_ack,
)
};
match result as u32 {
EINVAL => {
let result = irq_manager().request_irq(
irq_num,
common_msg.irq_name.clone(),
common_msg.irq_hander,
IrqHandleFlags::empty(),
Some(common_msg.dev_id.clone()),
);
match result {
Ok(_) => {}
Err(SystemError::EINVAL) => {
return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num)));
}
EAGAIN => {
Err(SystemError::EAGAIN_OR_EWOULDBLOCK) => {
return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied(
irq_num,
)));
}
Err(_) => {
kerror!(
"Failed to request pci irq {} for device {}",
irq_num.data(),
&common_msg.irq_name
);
return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied(
irq_num,
)));
}
_ => {}
}
//MSI中断只需配置一次PCI寄存器
// MSI中断只需配置一次PCI寄存器
if common_msg.irq_index == 0 {
let msg_address = arch_msi_message_address(0);
let trigger = match msg.irq_specific_message {
@ -377,8 +401,8 @@ pub trait PciInterrupt: PciDeviceStructure {
}
IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode,
};
let msg_data = arch_msi_message_data(irq_num, 0, trigger);
//写入Message Data和Message Address
let msg_data = arch_msi_message_data(irq_num.data() as u16, 0, trigger);
// 写入Message Data和Message Address
if address_64 {
PciArch::write_config(
&self.common_header().bus_device_function,
@ -496,26 +520,39 @@ pub trait PciInterrupt: PciDeviceStructure {
}
let irq_num =
self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize];
let common_msg = &msg.irq_common_message;
let result = unsafe {
c_irq_install(
irq_num as u64,
Some(common_msg.irq_hander),
common_msg.irq_parameter as u64,
common_msg.irq_name.as_ptr(),
common_msg.irq_ack,
)
};
match result as u32 {
EINVAL => {
let result = irq_manager().request_irq(
irq_num,
common_msg.irq_name.clone(),
common_msg.irq_hander,
IrqHandleFlags::empty(),
Some(common_msg.dev_id.clone()),
);
match result {
Ok(_) => {}
Err(SystemError::EINVAL) => {
return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num)));
}
EAGAIN => {
Err(SystemError::EAGAIN_OR_EWOULDBLOCK) => {
return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied(
irq_num,
)));
}
Err(_) => {
kerror!(
"Failed to request pci irq {} for device {}",
irq_num.data(),
&common_msg.irq_name
);
return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied(
irq_num,
)));
}
_ => {}
}
let msg_address = arch_msi_message_address(0);
@ -525,7 +562,7 @@ pub trait PciInterrupt: PciDeviceStructure {
}
IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode,
};
let msg_data = arch_msi_message_data(irq_num, 0, trigger);
let msg_data = arch_msi_message_data(irq_num.data() as u16, 0, trigger);
//写入Message Data和Message Address
let pcistandardbar = self
.bar()
@ -589,9 +626,8 @@ pub trait PciInterrupt: PciDeviceStructure {
..
} => {
for vector in self.irq_vector_mut().unwrap() {
unsafe {
c_irq_uninstall(vector.clone() as u64);
}
let irq = IrqNumber::new((*vector).into());
irq_manager().free_irq(irq, None);
}
PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0);
PciArch::write_config(
@ -636,9 +672,8 @@ pub trait PciInterrupt: PciDeviceStructure {
..
} => {
for vector in self.irq_vector_mut().unwrap() {
unsafe {
c_irq_uninstall(vector.clone() as u64);
}
let irq = IrqNumber::new((*vector).into());
irq_manager().free_irq(irq, None);
}
PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0);
let pcistandardbar = self

@ -0,0 +1,85 @@
use alloc::sync::Arc;
use hashbrown::HashMap;
use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{driver::base::device::DeviceId, init::initcall::INITCALL_CORE, libs::rwlock::RwLock};
use super::VirtIODevice;
static mut VIRTIO_IRQ_MANAGER: Option<VirtIOIrqManager> = None;
#[inline(always)]
pub fn virtio_irq_manager() -> &'static VirtIOIrqManager {
unsafe { VIRTIO_IRQ_MANAGER.as_ref().unwrap() }
}
pub struct VirtIOIrqManager {
map: RwLock<HashMap<Arc<DeviceId>, Arc<dyn VirtIODevice>>>,
}
impl VirtIOIrqManager {
fn new() -> Self {
VirtIOIrqManager {
map: RwLock::new(HashMap::new()),
}
}
/// 注册一个新的设备到virtio中断请求IRQ映射中。
///
/// # 参数
///
/// - `device` - 实现了 `VirtIODevice` trait 的设备对象,被封装在 `Arc` 智能指针中。
///
/// # 返回值
///
/// - 如果设备成功注册,返回 `Ok(())`。
/// - 如果设备ID已经存在于映射中返回 `Err(SystemError::EEXIST)`。
pub fn register_device(&self, device: Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
let mut map = self.map.write_irqsave();
if map.contains_key(device.dev_id()) {
return Err(SystemError::EEXIST);
}
map.insert(device.dev_id().clone(), device);
return Ok(());
}
/// 取消注册设备
///
/// 这个函数会从内部映射中移除指定的设备。设备是通过设备ID来识别的。
///
/// # 参数
///
/// - `device` - 需要被取消注册的设备,它是一个实现了 `VirtIODevice` trait 的智能指针。
#[allow(dead_code)]
pub fn unregister_device(&self, dev_id: &Arc<DeviceId>) {
let mut map = self.map.write_irqsave();
map.remove(dev_id);
}
/// 查找并返回指定设备ID的设备。
///
/// # 参数
/// - `dev_id` - 我们要查找的设备的设备ID。
///
/// # 返回
/// - 如果找到了设备,返回一个包含设备的`Option<Arc<dyn VirtIODevice>>`。
/// - 如果没有找到设备,返回`None`。
pub fn lookup_device(&self, dev_id: &Arc<DeviceId>) -> Option<Arc<dyn VirtIODevice>> {
let map = self.map.read_irqsave();
map.get(dev_id).map(|x| x.clone())
}
}
#[unified_init(INITCALL_CORE)]
fn init_virtio_irq_manager() -> Result<(), SystemError> {
let manager = VirtIOIrqManager::new();
unsafe {
VIRTIO_IRQ_MANAGER = Some(manager);
}
return Ok(());
}

@ -1,3 +1,19 @@
use core::any::Any;
use alloc::sync::Arc;
use system_error::SystemError;
use crate::exception::{irqdesc::IrqReturn, IrqNumber};
use super::base::device::DeviceId;
pub(super) mod irq;
pub mod transport_pci;
pub mod virtio;
pub mod virtio_impl;
pub trait VirtIODevice: Send + Sync + Any {
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError>;
fn dev_id(&self) -> &Arc<DeviceId>;
}

@ -1,22 +1,31 @@
//! PCI transport for VirtIO.
use crate::arch::{PciArch, TraitPciArch};
use crate::driver::base::device::DeviceId;
use crate::driver::pci::pci::{
BusDeviceFunction, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError,
PciStandardDeviceBar, PCI_CAP_ID_VNDR,
};
use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ};
use crate::include::bindings::bindings::pt_regs;
use crate::driver::virtio::irq::virtio_irq_manager;
use crate::exception::irqdata::IrqHandlerData;
use crate::exception::irqdesc::{IrqHandler, IrqReturn};
use crate::exception::IrqNumber;
use crate::libs::volatile::{
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
};
use crate::mm::VirtAddr;
use crate::net::net_core::poll_ifaces_try_lock_onetime;
use alloc::string::ToString;
use alloc::sync::Arc;
use core::{
fmt::{self, Display, Formatter},
mem::{align_of, size_of},
ptr::{self, addr_of_mut, NonNull},
};
use system_error::SystemError;
use virtio_drivers::{
transport::{DeviceStatus, DeviceType, Transport},
Error, Hal, PhysAddr,
@ -57,7 +66,7 @@ const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3;
const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4;
/// Virtio设备接收中断的设备号
const VIRTIO_RECV_VECTOR: u16 = 56;
const VIRTIO_RECV_VECTOR: IrqNumber = IrqNumber::new(56);
/// Virtio设备接收中断的设备号的表项号
const VIRTIO_RECV_VECTOR_INDEX: u16 = 0;
// 接收的queue号
@ -82,6 +91,7 @@ fn device_type(pci_device_id: u16) -> DeviceType {
/// PCI transport for VirtIO.
///
/// Ref: 4.1 Virtio Over PCI Bus
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct PciTransport {
device_type: DeviceType,
@ -96,21 +106,24 @@ pub struct PciTransport {
isr_status: NonNull<Volatile<u8>>,
/// The VirtIO device-specific configuration within some BAR.
config_space: Option<NonNull<[u32]>>,
}
unsafe extern "C" fn virtio_irq_hander(_irq_num: u64, _irq_paramer: u64, _regs: *mut pt_regs) {
// kdebug!("12345");
poll_ifaces_try_lock_onetime().ok();
irq: IrqNumber,
dev_id: Arc<DeviceId>,
}
impl PciTransport {
/// Construct a new PCI VirtIO device driver for the given device function on the given PCI
/// root controller.
///
/// ## 参数
///
/// - `device` - The PCI device structure for the VirtIO device.
/// - `irq_handler` - An optional handler for the device's interrupt. If `None`, a default
/// handler `DefaultVirtioIrqHandler` will be used.
pub fn new<H: Hal>(
device: &mut PciDeviceStructureGeneralDevice,
dev_id: Arc<DeviceId>,
) -> Result<Self, VirtioPciError> {
let irq = VIRTIO_RECV_VECTOR;
let header = &device.common_header;
let bus_device_function = header.bus_device_function;
if header.vendor_id != VIRTIO_VENDOR_ID {
@ -128,7 +141,7 @@ impl PciTransport {
let standard_device = device.as_standard_device_mut().unwrap();
// 目前缺少对PCI设备中断号的统一管理所以这里需要指定一个中断号。不能与其他中断重复
let irq_vector = standard_device.irq_vector_mut().unwrap();
irq_vector.push(VIRTIO_RECV_VECTOR);
irq_vector.push(irq);
standard_device
.irq_init(IRQ::PCI_IRQ_MSIX)
.expect("IRQ init failed");
@ -136,10 +149,9 @@ impl PciTransport {
let msg = PciIrqMsg {
irq_common_message: IrqCommonMsg::init_from(
0,
"Virtio_Recv_IRQ",
0,
virtio_irq_hander,
None,
"Virtio_IRQ".to_string(),
&DefaultVirtioIrqHandler,
dev_id.clone(),
),
irq_specific_message: IrqSpecificMsg::msi_default(),
};
@ -222,6 +234,8 @@ impl PciTransport {
notify_off_multiplier,
isr_status,
config_space,
irq,
dev_id,
})
}
}
@ -374,7 +388,9 @@ impl Transport for PciTransport {
impl Drop for PciTransport {
fn drop(&mut self) {
// Reset the device when the transport is dropped.
self.set_status(DeviceStatus::empty())
self.set_status(DeviceStatus::empty());
// todo: 调用pci的中断释放函数并且在virtio_irq_manager里面删除对应的设备的中断
}
}
@ -544,3 +560,36 @@ fn get_bar_region_slice<T>(
fn nonnull_slice_from_raw_parts<T>(data: NonNull<T>, len: usize) -> NonNull<[T]> {
NonNull::new(ptr::slice_from_raw_parts_mut(data.as_ptr(), len)).unwrap()
}
/// `DefaultVirtioIrqHandler` 是一个默认的virtio设备中断处理程序。
///
/// 当虚拟设备产生中断时,该处理程序会被调用。
///
/// 它首先检查设备ID是否存在然后尝试查找与设备ID关联的设备。
/// 如果找到设备,它会调用设备的 `handle_irq` 方法来处理中断。
/// 如果没有找到设备,它会记录一条警告并返回 `IrqReturn::NotHandled`,表示中断未被处理。
#[derive(Debug)]
struct DefaultVirtioIrqHandler;
impl IrqHandler for DefaultVirtioIrqHandler {
fn handle(
&self,
irq: IrqNumber,
_static_data: Option<&dyn IrqHandlerData>,
dev_id: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
let dev_id = dev_id.ok_or(SystemError::EINVAL)?;
let dev_id = dev_id
.arc_any()
.downcast::<DeviceId>()
.map_err(|_| SystemError::EINVAL)?;
if let Some(dev) = virtio_irq_manager().lookup_device(&dev_id) {
return dev.handle_irq(irq);
} else {
// 未绑定具体设备,因此无法处理中断
return Ok(IrqReturn::NotHandled);
}
}
}

@ -1,5 +1,6 @@
use super::transport_pci::PciTransport;
use super::virtio_impl::HalImpl;
use crate::driver::base::device::DeviceId;
use crate::driver::net::virtio_net::virtio_net;
use crate::driver::pci::pci::{
get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice,
@ -7,6 +8,7 @@ use crate::driver::pci::pci::{
};
use crate::libs::rwlock::RwLockWriteGuard;
use crate::{kdebug, kerror, kwarn};
use alloc::sync::Arc;
use alloc::{boxed::Box, collections::LinkedList};
use virtio_drivers::transport::{DeviceType, Transport};
const NETWORK_CLASS: u8 = 0x2;
@ -23,14 +25,16 @@ pub fn virtio_probe() {
let mut list = PCI_DEVICE_LINKEDLIST.write();
if let Ok(virtio_list) = virtio_device_search(&mut list) {
for virtio_device in virtio_list {
match PciTransport::new::<HalImpl>(virtio_device) {
let dev_id = virtio_device.common_header.device_id;
let dev_id = DeviceId::new(None, Some(format!("virtio_{}", dev_id))).unwrap();
match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
Ok(mut transport) => {
kdebug!(
"Detected virtio PCI device with device type {:?}, features {:#018x}",
transport.device_type(),
transport.read_device_features(),
);
virtio_device_init(transport);
virtio_device_init(transport, dev_id);
}
Err(err) => {
kerror!("Pci transport create failed because of error: {}", err);
@ -43,7 +47,7 @@ pub fn virtio_probe() {
}
///@brief 为virtio设备寻找对应的驱动进行初始化
fn virtio_device_init(transport: impl Transport + 'static) {
fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc<DeviceId>) {
match transport.device_type() {
DeviceType::Block => {
kwarn!("Not support virtio_block device for now");
@ -54,7 +58,7 @@ fn virtio_device_init(transport: impl Transport + 'static) {
DeviceType::Input => {
kwarn!("Not support virtio_input device for now");
}
DeviceType::Network => virtio_net(transport),
DeviceType::Network => virtio_net(transport, dev_id),
t => {
kwarn!("Unrecognized virtio device: {:?}", t);
}