mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
PCI设备中断重构,删去USB相关代码 (#285)
* 修复ecam无法获取MCFG table的问题 * 完善pcie * 完善irq的错误检测机制
This commit is contained in:
parent
2311e2f300
commit
cc36cf4a18
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@ -14,7 +14,8 @@
|
||||
"compilerPath": "~/opt/dragonos-gcc/gcc-x86_64-unknown-none/bin/x86_64-elf-gcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
|
3
kernel/rust-toolchain.toml
Normal file
3
kernel/rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-01-21"
|
||||
components = ["rust-src"]
|
@ -5,6 +5,7 @@ pub mod cpu;
|
||||
pub mod fpu;
|
||||
pub mod interrupt;
|
||||
pub mod mm;
|
||||
pub mod msi;
|
||||
pub mod pci;
|
||||
pub mod rand;
|
||||
pub mod sched;
|
||||
|
23
kernel/src/arch/x86_64/msi.rs
Normal file
23
kernel/src/arch/x86_64/msi.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::driver::pci::pci_irq::TriggerMode;
|
||||
/// @brief 获得MSI Message Address
|
||||
/// @param processor 目标CPU ID号
|
||||
/// @return MSI Message Address
|
||||
pub fn ia64_pci_get_arch_msi_message_address(processor: u16) -> u32 {
|
||||
0xfee00000 as u32 | ((processor as u32) << 12)
|
||||
}
|
||||
/// @brief 获得MSI Message Data
|
||||
/// @param vector 分配的中断向量号
|
||||
/// @param processor 目标CPU ID号
|
||||
/// @param trigger 申请中断的触发模式,MSI默认为边沿触发
|
||||
/// @return MSI Message Address
|
||||
pub fn ia64_pci_get_arch_msi_message_data(
|
||||
vector: u16,
|
||||
processor: u16,
|
||||
trigger: TriggerMode,
|
||||
) -> u32 {
|
||||
match trigger {
|
||||
TriggerMode::EdgeTrigger => vector as u32,
|
||||
TriggerMode::AssertHigh => vector as u32 | 1 << 15 | 1 << 14,
|
||||
TriggerMode::AssertLow => vector as u32 | 1 << 15,
|
||||
}
|
||||
}
|
@ -50,6 +50,10 @@ impl TraitPciArch for X86_64PciArch {
|
||||
unsafe {
|
||||
acpi_iter_SDT(Some(acpi_get_MCFG), data_point as *mut usize as *mut c_void);
|
||||
};
|
||||
// 防止无PCIE的机器找不到MCFG Table导致的错误
|
||||
if data == 0 {
|
||||
return Err(PciError::McfgTableNotFound);
|
||||
}
|
||||
//kdebug!("{}",data);
|
||||
//loop{}
|
||||
let head = NonNull::new(data as *mut acpi_system_description_table_header_t).unwrap();
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers hid
|
||||
kernel_driver_subdirs:=video interrupt pci acpi disk keyboard mouse multiboot2 timers hid
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
@ -1,11 +1,14 @@
|
||||
|
||||
all: pci.o msi.o
|
||||
all: pci.o pci_irq.o msi.o
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
|
||||
pci.o: pci.c
|
||||
$(CC) $(CFLAGS) -c pci.c -o pci.o
|
||||
|
||||
|
||||
pci_irq.o: pci_irq.c
|
||||
$(CC) $(CFLAGS) -c pci_irq.c -o pci_irq.o
|
||||
|
||||
msi.o: msi.c
|
||||
$(CC) $(CFLAGS) -c msi.c -o msi.o
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
pub mod pci;
|
||||
pub mod pci_irq;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
// 目前仅支持单主桥单Segment
|
||||
|
||||
use super::pci_irq::{IrqType, PciIrqError};
|
||||
use crate::arch::{PciArch, TraitPciArch};
|
||||
use crate::include::bindings::bindings::{
|
||||
initial_mm, mm_map, mm_struct, PAGE_2M_SIZE, VM_DONTCOPY, VM_IO,
|
||||
@ -11,12 +12,10 @@ use crate::{kdebug, kerror, kinfo, kwarn};
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{boxed::Box, collections::LinkedList};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use core::{
|
||||
convert::TryFrom,
|
||||
fmt::{self, Debug, Display, Formatter},
|
||||
};
|
||||
|
||||
// PCI_DEVICE_LINKEDLIST 添加了读写锁的全局链表,里面存储了检索到的PCI设备结构体
|
||||
// PCI_ROOT_0 Segment为0的全局PciRoot
|
||||
lazy_static! {
|
||||
@ -146,6 +145,8 @@ const BAR0_OFFSET: u8 = 0x10;
|
||||
const STATUS_COMMAND_OFFSET: u8 = 0x04;
|
||||
/// ID for vendor-specific PCI capabilities.(Virtio Capabilities)
|
||||
pub const PCI_CAP_ID_VNDR: u8 = 0x09;
|
||||
pub const PCI_CAP_ID_MSI: u8 = 0x05;
|
||||
pub const PCI_CAP_ID_MSIX: u8 = 0x11;
|
||||
pub const PORT_PCI_CONFIG_ADDRESS: u16 = 0xcf8;
|
||||
pub const PORT_PCI_CONFIG_DATA: u16 = 0xcfc;
|
||||
// pci设备分组的id
|
||||
@ -239,9 +240,11 @@ pub enum PciError {
|
||||
CreateMmioError,
|
||||
InvalidBusDeviceFunction,
|
||||
SegmentNotFound,
|
||||
McfgTableNotFound,
|
||||
GetWrongHeader,
|
||||
UnrecognisedHeaderType,
|
||||
PciDeviceStructureTransformError,
|
||||
PciIrqError(PciIrqError),
|
||||
}
|
||||
///实现PciError的Display trait,使其可以直接输出
|
||||
impl Display for PciError {
|
||||
@ -251,11 +254,13 @@ impl Display for PciError {
|
||||
Self::CreateMmioError => write!(f, "Error occurred while creating mmio."),
|
||||
Self::InvalidBusDeviceFunction => write!(f, "Found invalid BusDeviceFunction."),
|
||||
Self::SegmentNotFound => write!(f, "Target segment not found"),
|
||||
Self::McfgTableNotFound => write!(f, "ACPI MCFG Table not found"),
|
||||
Self::GetWrongHeader => write!(f, "GetWrongHeader with vendor id 0xffff"),
|
||||
Self::UnrecognisedHeaderType => write!(f, "Found device with unrecognised header type"),
|
||||
Self::PciDeviceStructureTransformError => {
|
||||
write!(f, "Found None When transform Pci device structure")
|
||||
}
|
||||
Self::PciIrqError(err) => write!(f, "Error occurred while setting irq :{:?}.", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,14 +271,17 @@ pub trait PciDeviceStructure: Send + Sync {
|
||||
/// @return HeaderType 设备类型
|
||||
fn header_type(&self) -> HeaderType;
|
||||
/// @brief 当其为standard设备时返回&Pci_Device_Structure_General_Device,其余情况返回None
|
||||
#[inline(always)]
|
||||
fn as_standard_device(&self) -> Option<&PciDeviceStructureGeneralDevice> {
|
||||
None
|
||||
}
|
||||
/// @brief 当其为pci to pci bridge设备时返回&Pci_Device_Structure_Pci_to_Pci_Bridge,其余情况返回None
|
||||
#[inline(always)]
|
||||
fn as_pci_to_pci_bridge_device(&self) -> Option<&PciDeviceStructurePciToPciBridge> {
|
||||
None
|
||||
}
|
||||
/// @brief 当其为pci to cardbus bridge设备时返回&Pci_Device_Structure_Pci_to_Cardbus_Bridge,其余情况返回None
|
||||
#[inline(always)]
|
||||
fn as_pci_to_carbus_bridge_device(&self) -> Option<&PciDeviceStructurePciToCardbusBridge> {
|
||||
None
|
||||
}
|
||||
@ -281,14 +289,17 @@ pub trait PciDeviceStructure: Send + Sync {
|
||||
/// @return 返回其不可变引用
|
||||
fn common_header(&self) -> &PciDeviceStructureHeader;
|
||||
/// @brief 当其为standard设备时返回&mut Pci_Device_Structure_General_Device,其余情况返回None
|
||||
#[inline(always)]
|
||||
fn as_standard_device_mut(&mut self) -> Option<&mut PciDeviceStructureGeneralDevice> {
|
||||
None
|
||||
}
|
||||
/// @brief 当其为pci to pci bridge设备时返回&mut Pci_Device_Structure_Pci_to_Pci_Bridge,其余情况返回None
|
||||
#[inline(always)]
|
||||
fn as_pci_to_pci_bridge_device_mut(&mut self) -> Option<&mut PciDeviceStructurePciToPciBridge> {
|
||||
None
|
||||
}
|
||||
/// @brief 当其为pci to cardbus bridge设备时返回&mut Pci_Device_Structure_Pci_to_Cardbus_Bridge,其余情况返回None
|
||||
#[inline(always)]
|
||||
fn as_pci_to_carbus_bridge_device_mut(
|
||||
&mut self,
|
||||
) -> Option<&mut PciDeviceStructurePciToCardbusBridge> {
|
||||
@ -319,28 +330,50 @@ pub trait PciDeviceStructure: Send + Sync {
|
||||
/// @brief 获取Pci设备共有的common_header
|
||||
/// @return 返回其可变引用
|
||||
fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader;
|
||||
|
||||
/// @brief 读取standard设备的bar寄存器,映射后将结果加入结构体的standard_device_bar变量
|
||||
/// @return 只有standard设备才返回成功或者错误,其余返回None
|
||||
fn bar_init(&mut self) -> Option<Result<u8, PciError>> {
|
||||
#[inline(always)]
|
||||
fn bar_ioremap(&mut self) -> Option<Result<u8, PciError>> {
|
||||
None
|
||||
}
|
||||
/// todo
|
||||
fn msix_init(&mut self) -> Option<Result<u8, PciError>> {
|
||||
/// @brief 获取PCI设备的bar寄存器的引用
|
||||
/// @return
|
||||
#[inline(always)]
|
||||
fn bar(&mut self) -> Option<&PciStandardDeviceBar> {
|
||||
None
|
||||
}
|
||||
/// @brief 通过设置该pci设备的command
|
||||
fn enable_master(&mut self) {
|
||||
self.set_command(Command::IO_SPACE | Command::MEMORY_SPACE | Command::BUS_MASTER);
|
||||
}
|
||||
/// @brief 寻找设备的msix空间的offset
|
||||
fn msix_capability_offset(&self) -> Option<u8> {
|
||||
for capability in self.capabilities()? {
|
||||
if capability.id == PCI_CAP_ID_MSIX {
|
||||
return Some(capability.offset);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
/// @brief 寻找设备的msi空间的offset
|
||||
fn msi_capability_offset(&self) -> Option<u8> {
|
||||
for capability in self.capabilities()? {
|
||||
if capability.id == PCI_CAP_ID_MSI {
|
||||
return Some(capability.offset);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
/// @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>>;
|
||||
}
|
||||
|
||||
/// Pci_Device_Structure_Header PCI设备结构体共有的头部
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PciDeviceStructureHeader {
|
||||
// 包含msix table地址的bar的mmio基地址 todo:以下四个作为一个结构体统一管理
|
||||
pub msix_mmio_vaddr: u64,
|
||||
pub msix_mmio_size: u64, // msix映射长度
|
||||
pub msix_offset: u32, // msix表的offset
|
||||
pub msix_table_size: u16, // msix表的表项数量
|
||||
// ==== busdevicefunction变量表示该结构体所处的位置
|
||||
pub bus_device_function: BusDeviceFunction,
|
||||
pub vendor_id: u16, // 供应商ID 0xffff是一个无效值,在读取访问不存在的设备的配置空间寄存器时返回
|
||||
@ -365,6 +398,10 @@ pub struct PciDeviceStructureHeader {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PciDeviceStructureGeneralDevice {
|
||||
pub common_header: PciDeviceStructureHeader,
|
||||
// 中断结构体,包括legacy,msi,msix三种情况
|
||||
pub irq_type: IrqType,
|
||||
// 使用的中断号的vec集合
|
||||
pub irq_vector: Vec<u16>,
|
||||
pub standard_device_bar: PciStandardDeviceBar,
|
||||
pub cardbus_cis_pointer: u32, // 指向卡信息结构,供在 CardBus 和 PCI 之间共享芯片的设备使用。
|
||||
pub subsystem_vendor_id: u16,
|
||||
@ -380,19 +417,23 @@ pub struct PciDeviceStructureGeneralDevice {
|
||||
pub max_latency: u8, // 一个只读寄存器,指定设备需要多长时间访问一次 PCI 总线(以 1/4 微秒为单位)。
|
||||
}
|
||||
impl PciDeviceStructure for PciDeviceStructureGeneralDevice {
|
||||
#[inline(always)]
|
||||
fn header_type(&self) -> HeaderType {
|
||||
HeaderType::Standard
|
||||
}
|
||||
#[inline(always)]
|
||||
fn as_standard_device(&self) -> Option<&PciDeviceStructureGeneralDevice> {
|
||||
Some(self)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn as_standard_device_mut(&mut self) -> Option<&mut PciDeviceStructureGeneralDevice> {
|
||||
Some(self)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn common_header(&self) -> &PciDeviceStructureHeader {
|
||||
&self.common_header
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader {
|
||||
&mut self.common_header
|
||||
}
|
||||
@ -402,7 +443,7 @@ impl PciDeviceStructure for PciDeviceStructureGeneralDevice {
|
||||
next_capability_offset: Some(self.capabilities_pointer),
|
||||
})
|
||||
}
|
||||
fn bar_init(&mut self) -> Option<Result<u8, PciError>> {
|
||||
fn bar_ioremap(&mut self) -> Option<Result<u8, PciError>> {
|
||||
let common_header = &self.common_header;
|
||||
match pci_bar_init(common_header.bus_device_function) {
|
||||
Ok(bar) => {
|
||||
@ -412,11 +453,27 @@ impl PciDeviceStructure for PciDeviceStructureGeneralDevice {
|
||||
Err(e) => Some(Err(e)),
|
||||
}
|
||||
}
|
||||
fn bar(&mut self) -> Option<&PciStandardDeviceBar> {
|
||||
Some(&self.standard_device_bar)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn irq_type_mut(&mut self) -> Option<&mut IrqType> {
|
||||
Some(&mut self.irq_type)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
|
||||
Some(&mut self.irq_vector)
|
||||
}
|
||||
}
|
||||
|
||||
/// Pci_Device_Structure_Pci_to_Pci_Bridge pci-to-pci桥设备结构体
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PciDeviceStructurePciToPciBridge {
|
||||
pub common_header: PciDeviceStructureHeader,
|
||||
// 中断结构体,包括legacy,msi,msix三种情况
|
||||
pub irq_type: IrqType,
|
||||
// 使用的中断号的vec集合
|
||||
pub irq_vector: Vec<u16>,
|
||||
pub bar0: u32,
|
||||
pub bar1: u32,
|
||||
pub primary_bus_number: u8,
|
||||
@ -443,22 +500,34 @@ pub struct PciDeviceStructurePciToPciBridge {
|
||||
pub bridge_control: u16,
|
||||
}
|
||||
impl PciDeviceStructure for PciDeviceStructurePciToPciBridge {
|
||||
#[inline(always)]
|
||||
fn header_type(&self) -> HeaderType {
|
||||
HeaderType::PciPciBridge
|
||||
}
|
||||
#[inline(always)]
|
||||
fn as_pci_to_pci_bridge_device(&self) -> Option<&PciDeviceStructurePciToPciBridge> {
|
||||
Some(self)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn as_pci_to_pci_bridge_device_mut(&mut self) -> Option<&mut PciDeviceStructurePciToPciBridge> {
|
||||
Some(self)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn common_header(&self) -> &PciDeviceStructureHeader {
|
||||
&self.common_header
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader {
|
||||
&mut self.common_header
|
||||
}
|
||||
#[inline(always)]
|
||||
fn irq_type_mut(&mut self) -> Option<&mut IrqType> {
|
||||
Some(&mut self.irq_type)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
|
||||
Some(&mut self.irq_vector)
|
||||
}
|
||||
}
|
||||
/// Pci_Device_Structure_Pci_to_Cardbus_Bridge Pci_to_Cardbus桥设备结构体
|
||||
#[derive(Clone, Debug)]
|
||||
@ -488,24 +557,36 @@ pub struct PciDeviceStructurePciToCardbusBridge {
|
||||
pub pc_card_legacy_mode_base_address_16_bit: u32,
|
||||
}
|
||||
impl PciDeviceStructure for PciDeviceStructurePciToCardbusBridge {
|
||||
#[inline(always)]
|
||||
fn header_type(&self) -> HeaderType {
|
||||
HeaderType::PciCardbusBridge
|
||||
}
|
||||
#[inline(always)]
|
||||
fn as_pci_to_carbus_bridge_device(&self) -> Option<&PciDeviceStructurePciToCardbusBridge> {
|
||||
Some(&self)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn as_pci_to_carbus_bridge_device_mut(
|
||||
&mut self,
|
||||
) -> Option<&mut PciDeviceStructurePciToCardbusBridge> {
|
||||
Some(self)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn common_header(&self) -> &PciDeviceStructureHeader {
|
||||
&self.common_header
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader {
|
||||
&mut self.common_header
|
||||
}
|
||||
#[inline(always)]
|
||||
fn irq_type_mut(&mut self) -> Option<&mut IrqType> {
|
||||
None
|
||||
}
|
||||
#[inline(always)]
|
||||
fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// 代表一个PCI segement greoup.
|
||||
@ -672,10 +753,6 @@ fn pci_read_header(
|
||||
return Err(PciError::GetWrongHeader);
|
||||
}
|
||||
let header = PciDeviceStructureHeader {
|
||||
msix_mmio_vaddr: 0,
|
||||
msix_mmio_size: 0,
|
||||
msix_offset: 0,
|
||||
msix_table_size: 0,
|
||||
bus_device_function,
|
||||
vendor_id,
|
||||
device_id,
|
||||
@ -755,6 +832,8 @@ fn pci_read_general_device_header(
|
||||
let max_latency = (result >> 24) as u8;
|
||||
PciDeviceStructureGeneralDevice {
|
||||
common_header,
|
||||
irq_type: IrqType::Unused,
|
||||
irq_vector: Vec::new(),
|
||||
standard_device_bar,
|
||||
cardbus_cis_pointer,
|
||||
subsystem_vendor_id,
|
||||
@ -823,6 +902,8 @@ fn pci_read_pci_to_pci_bridge_header(
|
||||
let bridge_control = (result >> 16) as u16;
|
||||
PciDeviceStructurePciToPciBridge {
|
||||
common_header,
|
||||
irq_type: IrqType::Unused,
|
||||
irq_vector: Vec::new(),
|
||||
bar0,
|
||||
bar1,
|
||||
primary_bus_number,
|
||||
@ -854,7 +935,7 @@ fn pci_read_pci_to_pci_bridge_header(
|
||||
/// 本函数只应被 pci_read_header()调用
|
||||
/// @param common_header 共有头部
|
||||
/// @param bus_device_function PCI设备的唯一标识
|
||||
/// @return ) -> Pci_Device_Structure_Pci_to_Cardbus_Bridge pci-to-cardbus 桥设备头部
|
||||
/// @return Pci_Device_Structure_Pci_to_Cardbus_Bridge pci-to-cardbus 桥设备头部
|
||||
fn pci_read_pci_to_cardbus_bridge_header(
|
||||
common_header: PciDeviceStructureHeader,
|
||||
busdevicefunction: &BusDeviceFunction,
|
||||
@ -1221,6 +1302,8 @@ impl Display for BarInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
//todo 增加对桥的bar的支持
|
||||
pub trait PciDeviceBar {}
|
||||
///一个普通PCI设备(非桥)有6个BAR寄存器,PciStandardDeviceBar存储其全部信息
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct PciStandardDeviceBar {
|
||||
|
88
kernel/src/driver/pci/pci_irq.c
Normal file
88
kernel/src/driver/pci/pci_irq.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include "pci_irq.h"
|
||||
#include "exception/irq.h"
|
||||
#include <common/errno.h>
|
||||
#include <common/kprint.h>
|
||||
// 现在pci设备的中断由自己进行控制,这些不执行内容的函数是为了适配旧的中断处理机制
|
||||
void pci_irq_enable(ul irq_num)
|
||||
{
|
||||
|
||||
}
|
||||
void pci_irq_disable(ul irq_num)
|
||||
{
|
||||
|
||||
}
|
||||
void pci_irq_install(ul irq_num)
|
||||
{
|
||||
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
hardware_intr_controller* pci_interrupt_controller = kmalloc(sizeof(hardware_intr_controller),0);
|
||||
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;
|
||||
if(pci_irq_ack)
|
||||
pci_interrupt_controller->ack = pci_irq_ack;
|
||||
int namelen = sizeof(strlen(irq_name) + 1);
|
||||
p->irq_name = (char *)kmalloc(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;
|
||||
}
|
5
kernel/src/driver/pci/pci_irq.h
Normal file
5
kernel/src/driver/pci/pci_irq.h
Normal file
@ -0,0 +1,5 @@
|
||||
#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);
|
1005
kernel/src/driver/pci/pci_irq.rs
Normal file
1005
kernel/src/driver/pci/pci_irq.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,9 +0,0 @@
|
||||
CFLAGS += -I .
|
||||
|
||||
all: usb.o xhci.o
|
||||
|
||||
usb.o: usb.c
|
||||
$(CC) $(CFLAGS) -c usb.c -o usb.o
|
||||
|
||||
xhci.o: xhci/xhci.c
|
||||
$(CC) $(CFLAGS) -c xhci/xhci.c -o xhci/xhci.o
|
@ -1,64 +0,0 @@
|
||||
#include "usb.h"
|
||||
#include "xhci/xhci.h"
|
||||
#include <common/kprint.h>
|
||||
#include <common/errno.h>
|
||||
#include <driver/pci/pci.h>
|
||||
#include <debug/bug.h>
|
||||
#include <common/spinlock.h>
|
||||
|
||||
extern spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁
|
||||
|
||||
#define MAX_USB_NUM 8 // pci总线上的usb设备的最大数量
|
||||
|
||||
// 在pci总线上寻找到的usb设备控制器的header
|
||||
static struct pci_device_structure_header_t *usb_pdevs[MAX_USB_NUM];
|
||||
static int usb_pdevs_count = 0;
|
||||
|
||||
/**
|
||||
* @brief 初始化usb驱动程序
|
||||
*
|
||||
*/
|
||||
int usb_init(void* unused)
|
||||
{
|
||||
kinfo("Initializing usb driver...");
|
||||
spin_init(&xhci_controller_init_lock);
|
||||
|
||||
// 获取所有usb-pci设备的列表
|
||||
pci_get_device_structure(USB_CLASS, USB_SUBCLASS, usb_pdevs, &usb_pdevs_count);
|
||||
|
||||
if (WARN_ON(usb_pdevs_count == 0))
|
||||
{
|
||||
kwarn("There is no usb hardware in this computer!");
|
||||
return 0;
|
||||
}
|
||||
kdebug("usb_pdevs_count=%d", usb_pdevs_count);
|
||||
// 初始化每个usb控制器
|
||||
for (volatile int i = 0; i < usb_pdevs_count; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
switch (usb_pdevs[i]->ProgIF)
|
||||
{
|
||||
case USB_TYPE_UHCI:
|
||||
case USB_TYPE_OHCI:
|
||||
case USB_TYPE_EHCI:
|
||||
case USB_TYPE_UNSPEC:
|
||||
case USB_TYPE_DEVICE:
|
||||
kwarn("Unsupported usb host type: %#02x", usb_pdevs[i]->ProgIF);
|
||||
break;
|
||||
|
||||
case USB_TYPE_XHCI:
|
||||
// 初始化对应的xhci控制器
|
||||
io_mfence();
|
||||
xhci_init((struct pci_device_structure_general_device_t *)usb_pdevs[i]);
|
||||
io_mfence();
|
||||
break;
|
||||
|
||||
default:
|
||||
kerror("Error value of usb_pdevs[%d]->ProgIF: %#02x", i, usb_pdevs[i]->ProgIF);
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kinfo("Successfully initialized all usb host controllers!");
|
||||
return 0;
|
||||
}
|
@ -1,308 +0,0 @@
|
||||
#pragma once
|
||||
#include <common/sys/types.h>
|
||||
|
||||
// usb设备在pci总线上的class
|
||||
#define USB_CLASS 0xC
|
||||
#define USB_SUBCLASS 0x3
|
||||
|
||||
// 不同的usb设备在pci总线上的prog IF
|
||||
#define USB_TYPE_UHCI 0x0
|
||||
#define USB_TYPE_OHCI 0x10
|
||||
#define USB_TYPE_EHCI 0x20
|
||||
#define USB_TYPE_XHCI 0x30
|
||||
#define USB_TYPE_UNSPEC 0x80 // Unspecified
|
||||
#define USB_TYPE_DEVICE 0xfe // USB Device(Not controller)
|
||||
|
||||
// Reset wait times(milliseconds) ,USB 2.0 specs, page 153, section 7.1.7.5, paragraph 3
|
||||
#define USB_TIME_RST_RH 50 // reset on a root hub
|
||||
#define USB_TIME_RST_MIN 10 // minimum delay for a reset
|
||||
#define USB_TIME_RST_NOMORE 3 // No more than this between resets for root hubs
|
||||
#define USB_TIME_RST_REC 10 // reset recovery
|
||||
|
||||
/**
|
||||
* @brief usb描述符的头部
|
||||
*
|
||||
* String Descriptor:
|
||||
* String Language Descriptor:
|
||||
* 先获取头部,然后根据长度申请空间,再获取整个string desc
|
||||
*/
|
||||
struct usb_desc_header
|
||||
{
|
||||
uint8_t len; // 整个描述符的大小(字节)
|
||||
uint8_t type;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @brief usb 设备描述符
|
||||
*
|
||||
*/
|
||||
struct usb_device_desc
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t type;
|
||||
uint16_t usb_version;
|
||||
uint8_t _class;
|
||||
uint8_t subclass;
|
||||
uint8_t protocol;
|
||||
uint8_t max_packet_size;
|
||||
|
||||
uint16_t vendor_id;
|
||||
uint16_t product_id;
|
||||
uint16_t device_rel;
|
||||
uint8_t manufacturer_index;
|
||||
uint8_t procuct_index;
|
||||
|
||||
uint8_t serial_index;
|
||||
uint8_t config; // number of configurations
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @brief usb设备配置信息描述符
|
||||
*
|
||||
*/
|
||||
struct usb_config_desc
|
||||
{
|
||||
uint8_t len; // 当前描述符的大小(字节)
|
||||
uint8_t type; // USB_DT_CONFIG
|
||||
uint16_t total_len; /*
|
||||
Total length of data returned for this
|
||||
configuration. Includes the combined length
|
||||
of all descriptors (configuration, interface,
|
||||
endpoint, and class- or vendor-specific)
|
||||
returned for this configuration
|
||||
*/
|
||||
uint8_t num_interfaces; // 当前conf对应的接口数量
|
||||
uint8_t value; /*
|
||||
Value to use as an argument to the
|
||||
SetConfiguration() request to select this
|
||||
configuration
|
||||
*/
|
||||
uint8_t index; // Index of string descriptor describing this configuration
|
||||
uint8_t bmAttr; /*
|
||||
Configuration characteristics:
|
||||
D7: Reserved (要设置为1)
|
||||
D6: Self-powered
|
||||
D5: Remote Wakeup
|
||||
D4...0: Reserved (设置为0)
|
||||
*/
|
||||
uint8_t max_power; /*
|
||||
当这个设备满载时,为在这个conf上提供对应的功能,需要消耗的电流值。
|
||||
当设备是在High-speed时,这里的单位是2mA (也就是说,值为50,代表最大消耗100mA的电流)
|
||||
当设备运行在Gen X speed时,这里的单位是8mA
|
||||
*/
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @brief usb接口描述符
|
||||
*
|
||||
*/
|
||||
struct usb_interface_desc
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t type; // USB_DT_INTERFACE
|
||||
uint8_t interface_number; // 当前接口序号(从0开始的)
|
||||
uint8_t alternate_setting; // used to select alt. setting
|
||||
uint8_t num_endpoints; // 当前interface的端点数量
|
||||
uint8_t interface_class; // Class code
|
||||
uint8_t interface_sub_class; // Sub class code
|
||||
uint8_t interface_protocol; // 协议 These codes are qualified by the value of thebInterfaceClass and the
|
||||
// bInterfaceSubClass fields.
|
||||
uint8_t index; // index of String Descriptor describing this interface
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @brief usb端点描述符
|
||||
*
|
||||
* 详见usb3.2 Specification Table 9-26
|
||||
*/
|
||||
struct usb_endpoint_desc
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t type; // descriptor type
|
||||
uint8_t endpoint_addr; /* Bit 3...0: The endpoint number
|
||||
Bit 6...4: Reserved, reset to zero
|
||||
Bit 7: Direction, ignored for
|
||||
control endpoints
|
||||
0 = OUT endpoint
|
||||
1 = IN endpoint
|
||||
*/
|
||||
uint8_t attributes;
|
||||
uint16_t max_packet;
|
||||
uint8_t interval;
|
||||
};
|
||||
|
||||
// 从endpoint描述符中获取max burst size大小
|
||||
#define usb_get_max_burst_from_ep(__ep_desc) (((__ep_desc)->max_packet & 0x1800) >> 11)
|
||||
|
||||
/**
|
||||
* @brief usb设备请求包
|
||||
*
|
||||
*/
|
||||
struct usb_request_packet_t
|
||||
{
|
||||
uint8_t request_type;
|
||||
uint8_t request;
|
||||
uint16_t value;
|
||||
|
||||
uint16_t index;
|
||||
uint16_t length;
|
||||
} __attribute__((packed));
|
||||
// usb设备请求包的request_type字段的值
|
||||
#define __USB_REQ_TYPE_H2D 0x00
|
||||
#define __USB_REQ_TYPE_D2H 0x80
|
||||
|
||||
#define __USB_REQ_TYPE_STANDARD 0x00
|
||||
#define __USB_REQ_TYPE_CLASS 0x20
|
||||
#define __USB_REQ_TYPE_VENDOR 0x40
|
||||
#define __USB_REQ_TYPE_RSVD 0x60
|
||||
|
||||
#define __USB_REQ_TYPE_DEVICE 0x00
|
||||
#define __USB_REQ_TYPE_INTERFACE 0x01
|
||||
#define __USB_REQ_TYPE_ENDPOINT 0x02
|
||||
#define __USB_REQ_TYPE_OTHER 0x03
|
||||
|
||||
#define USB_REQ_TYPE_GET_REQUEST (__USB_REQ_TYPE_D2H | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_DEVICE)
|
||||
#define USB_REQ_TYPE_SET_REQUEST (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_DEVICE)
|
||||
#define USB_REQ_TYPE_GET_INTERFACE_REQUEST (__USB_REQ_TYPE_D2H | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_INTERFACE)
|
||||
#define USB_REQ_TYPE_SET_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __USB_REQ_TYPE_INTERFACE)
|
||||
#define USB_REQ_TYPE_SET_CLASS_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_CLASS | __USB_REQ_TYPE_INTERFACE)
|
||||
|
||||
// device requests
|
||||
enum
|
||||
{
|
||||
USB_REQ_GET_STATUS = 0,
|
||||
USB_REQ_CLEAR_FEATURE,
|
||||
USB_REQ_SET_FEATURE = 3,
|
||||
USB_REQ_SET_ADDRESS = 5,
|
||||
USB_REQ_GET_DESCRIPTOR = 6,
|
||||
USB_REQ_SET_DESCRIPTOR,
|
||||
USB_REQ_GET_CONFIGURATION,
|
||||
USB_REQ_SET_CONFIGURATION,
|
||||
// interface requests
|
||||
USB_REQ_GET_INTERFACE,
|
||||
USB_REQ_SET_INTERFACE,
|
||||
// standard endpoint requests
|
||||
USB_REQ_SYNCH_FRAME,
|
||||
USB_REQ_SET_ENCRYPTION,
|
||||
USB_REQ_GET_ENCRYPTION,
|
||||
USB_REQ_SET_HANDSHAKE,
|
||||
USB_REQ_GET_HANDSHAKE,
|
||||
USB_REQ_SET_CONNECTION,
|
||||
USB_REQ_SET_SECURITY_DATA,
|
||||
USB_REQ_GET_SECURITY_DATA,
|
||||
USB_REQ_SET_WUSB_DATA,
|
||||
USB_REQ_LOOPBACK_DATA_WRITE,
|
||||
USB_REQ_LOOPBACK_DATA_READ,
|
||||
USB_REQ_SET_INTERFACE_DS,
|
||||
USB_REQ_GET_FW_STATUS = 26,
|
||||
USB_REQ_SET_FW_STATUS,
|
||||
USB_REQ_SET_SEL = 48,
|
||||
USB_REQ_SET_ISOCH_DELAY,
|
||||
// Device specific
|
||||
USB_REQ_GET_MAX_LUNS = 0xFE,
|
||||
USB_REQ_BULK_ONLY_RESET
|
||||
};
|
||||
|
||||
// Descriptor types
|
||||
enum
|
||||
{
|
||||
USB_DT_DEVICE = 1,
|
||||
USB_DT_CONFIG,
|
||||
USB_DT_STRING,
|
||||
USB_DT_INTERFACE,
|
||||
USB_DT_ENDPOINT,
|
||||
USB_DT_DEVICE_QUALIFIER,
|
||||
USB_DT_OTHER_SPEED_CONFIG,
|
||||
USB_DT_INTERFACE_POWER,
|
||||
USB_DT_OTG,
|
||||
USB_DT_DEBUG,
|
||||
USB_DT_INTERFACE_ASSOSIATION,
|
||||
USB_DT_BOS = 15,
|
||||
USB_DT_DEVICE_CAPABILITY,
|
||||
|
||||
USB_DT_HID = 0x21,
|
||||
USB_DT_HID_REPORT,
|
||||
USB_DT_HID_PHYSICAL,
|
||||
|
||||
USB_DT_INTERFACE_FUNCTION = 0x24,
|
||||
USB_DT_ENDPOINT_FUNCTION,
|
||||
|
||||
// HUB = 0x29
|
||||
|
||||
USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION = 48,
|
||||
USB_DT_SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION,
|
||||
};
|
||||
|
||||
// transfer types (Endpoint types) (USB 2.0 page 270)
|
||||
enum
|
||||
{
|
||||
USB_EP_CONTROL = 0,
|
||||
USB_EP_ISOCHRONOUS,
|
||||
USB_EP_BULK,
|
||||
USB_EP_INTERRUPT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 该宏定义用于声明usb请求包,并初始化其中的各个字段
|
||||
*
|
||||
*/
|
||||
#define DECLARE_USB_PACKET(pak_name, _trans_req_type, _trans_request, _trans_value, _trans_index, _transfer_length) \
|
||||
struct usb_request_packet_t pak_name = {0}; \
|
||||
pak_name.request_type = (_trans_req_type); \
|
||||
pak_name.request = (_trans_request); \
|
||||
pak_name.value = (_trans_value); \
|
||||
pak_name.index = (_trans_index); \
|
||||
pak_name.length = (_transfer_length);
|
||||
|
||||
/*
|
||||
usb class codes
|
||||
refs: https://www.usb.org/defined-class-codes
|
||||
*/
|
||||
enum
|
||||
{
|
||||
USB_CLASS_IF = 0x00,
|
||||
USB_CLASS_AUDIO,
|
||||
USB_CLASS_CDC,
|
||||
USB_CLASS_HID,
|
||||
USB_CLASS_PHYSICAL = 0x05,
|
||||
USB_CLASS_IMAGE,
|
||||
USB_CLASS_PRINTER,
|
||||
USB_CLASS_MASS_STORAGE,
|
||||
USB_CLASS_HUB,
|
||||
USB_CLASS_CDC_DATA,
|
||||
USB_CLASS_SMART_CARD,
|
||||
USB_CLASS_CONTENT_SEC = 0x0d,
|
||||
USB_CLASS_VIDEO,
|
||||
USB_CLASS_PERSONAL_HEALTHCARE = 0x0f,
|
||||
USB_CLASS_AV,
|
||||
USB_CLASS_BILLBOARD,
|
||||
USB_CLASS_TYPEC_BRIDGE,
|
||||
USB_CLASS_I3C = 0x3c,
|
||||
USB_CLASS_DIAGNOSTIC = 0xdc,
|
||||
USB_CLASS_WIRELESS_CTRL = 0xe0,
|
||||
USB_CLASS_MISC = 0xef,
|
||||
USB_CLASS_APP_SPEC = 0xfe,
|
||||
USB_CLASS_VENDOR_SPEC = 0XFF,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief usb hid descriptor的结构体
|
||||
*
|
||||
*/
|
||||
struct usb_hid_desc
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t type; // USB_DT_HID
|
||||
uint16_t bcdHID; // 标识HIDClass规范版本的数字表达式。
|
||||
|
||||
uint8_t country_code;
|
||||
uint8_t descriptors_num; // the number of class descriptors
|
||||
uint8_t desc_type; // Constant name identifying type of class descriptor
|
||||
uint16_t report_desc_len; // Report descriptor的大小
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 初始化usb驱动程序
|
||||
*
|
||||
*/
|
||||
int usb_init();
|
@ -1,87 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
注意!!!
|
||||
|
||||
尽管采用MMI/O的方式访问寄存器,但是对于指定大小的寄存器,
|
||||
在发起读请求的时候,只能从寄存器的起始地址位置开始读取。
|
||||
|
||||
例子:不能在一个32bit的寄存器中的偏移量8的位置开始读取1个字节
|
||||
这种情况下,我们必须从32bit的寄存器的0地址处开始读取32bit,然后通过移位的方式得到其中的字节。
|
||||
*/
|
||||
|
||||
#define xhci_read_cap_reg32(id, offset) (__read4b(xhci_hc[id].vbase + (offset)))
|
||||
#define xhci_get_ptr_cap_reg32(id, offset) ((uint32_t *)(xhci_hc[id].vbase + (offset)))
|
||||
#define xhci_write_cap_reg32(id, offset, value) (__write4b(xhci_hc[id].vbase + (offset), (value)))
|
||||
|
||||
#define xhci_read_cap_reg64(id, offset) (__read8b(xhci_hc[id].vbase + (offset)))
|
||||
#define xhci_get_ptr_reg64(id, offset) ((uint64_t *)(xhci_hc[id].vbase + (offset)))
|
||||
#define xhci_write_cap_reg64(id, offset, value) (__write8b(xhci_hc[id].vbase + (offset), (value)))
|
||||
|
||||
#define xhci_read_op_reg8(id, offset) (*(uint8_t *)(xhci_hc[id].vbase_op + (offset)))
|
||||
#define xhci_get_ptr_op_reg8(id, offset) ((uint8_t *)(xhci_hc[id].vbase_op + (offset)))
|
||||
#define xhci_write_op_reg8(id, offset, value) (*(uint8_t *)(xhci_hc[id].vbase_op + (offset)) = (uint8_t)(value))
|
||||
|
||||
#define xhci_read_op_reg32(id, offset) (__read4b(xhci_hc[id].vbase_op + (offset)))
|
||||
#define xhci_get_ptr_op_reg32(id, offset) ((uint32_t *)(xhci_hc[id].vbase_op + (offset)))
|
||||
#define xhci_write_op_reg32(id, offset, value) (__write4b(xhci_hc[id].vbase_op + (offset), (value)))
|
||||
|
||||
#define xhci_read_op_reg64(id, offset) (__read8b(xhci_hc[id].vbase_op + (offset)))
|
||||
#define xhci_get_ptr_op_reg64(id, offset) ((uint64_t *)(xhci_hc[id].vbase_op + (offset)))
|
||||
#define xhci_write_op_reg64(id, offset, value) (__write8b(xhci_hc[id].vbase_op + (offset), (value)))
|
||||
|
||||
/**
|
||||
* @brief 计算中断寄存器组虚拟地址
|
||||
* @param id 主机控制器id
|
||||
* @param num xhci中断寄存器组号
|
||||
*/
|
||||
#define xhci_calc_intr_vaddr(id, num) (xhci_hc[id].vbase + xhci_hc[id].rts_offset + XHCI_RT_IR0 + (num)*XHCI_IR_SIZE)
|
||||
/**
|
||||
* @brief 读取/写入中断寄存器
|
||||
* @param id 主机控制器id
|
||||
* @param num xhci中断寄存器组号
|
||||
* @param intr_offset 寄存器在当前寄存器组中的偏移量
|
||||
*/
|
||||
#define xhci_read_intr_reg32(id, num, intr_offset) (__read4b(xhci_calc_intr_vaddr(id, num) + (intr_offset)))
|
||||
#define xhci_write_intr_reg32(id, num, intr_offset, value) (__write4b(xhci_calc_intr_vaddr(id, num) + (intr_offset), (value)))
|
||||
#define xhci_read_intr_reg64(id, num, intr_offset) (__read8b(xhci_calc_intr_vaddr(id, num) + (intr_offset)))
|
||||
#define xhci_write_intr_reg64(id, num, intr_offset, value) (__write8b(xhci_calc_intr_vaddr(id, num) + (intr_offset), (value)))
|
||||
|
||||
#define xhci_is_aligned64(addr) (((addr)&0x3f) == 0) // 是否64bytes对齐
|
||||
|
||||
/**
|
||||
* @brief 判断端口信息
|
||||
* @param cid 主机控制器id
|
||||
* @param pid 端口id
|
||||
*/
|
||||
#define XHCI_PORT_IS_USB2(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_INFO) == XHCI_PROTOCOL_USB2)
|
||||
#define XHCI_PORT_IS_USB3(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_INFO) == XHCI_PROTOCOL_USB3)
|
||||
|
||||
#define XHCI_PORT_IS_USB2_HSO(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_HSO) == XHCI_PROTOCOL_HSO)
|
||||
#define XHCI_PORT_HAS_PAIR(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_HAS_PAIR) == XHCI_PROTOCOL_HAS_PAIR)
|
||||
#define XHCI_PORT_IS_ACTIVE(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_ACTIVE) == XHCI_PROTOCOL_ACTIVE)
|
||||
|
||||
#define XHCI_PORT_REGISTER_OFFSET(__port_id) (XHCI_OPS_PRS + 16 * (__port_id))
|
||||
|
||||
// 获取端口速度 full=1, low=2, high=3, super=4
|
||||
#define xhci_get_port_speed(__id, __port_id) ((xhci_read_op_reg32((__id), XHCI_PORT_REGISTER_OFFSET(__port_id) + XHCI_PORT_PORTSC) >> 10) & 0xf)
|
||||
|
||||
/**
|
||||
* @brief 设置link TRB的命令(dword3)
|
||||
*
|
||||
*/
|
||||
#define xhci_TRB_set_link_cmd(trb_vaddr) \
|
||||
do \
|
||||
{ \
|
||||
struct xhci_TRB_normal_t *ptr = (struct xhci_TRB_normal_t *)(trb_vaddr); \
|
||||
ptr->TRB_type = TRB_TYPE_LINK; \
|
||||
ptr->ioc = 0; \
|
||||
ptr->chain = 0; \
|
||||
ptr->ent = 0; \
|
||||
ptr->cycle = 1; \
|
||||
} while (0)
|
||||
|
||||
// 设置endpoint结构体的dequeue_cycle_state bit
|
||||
#define xhci_ep_set_dequeue_cycle_state(ep_ctx_ptr, state) ((ep_ctx_ptr)->tr_dequeue_ptr |= ((state)&1))
|
||||
// 获取endpoint结构体的dequeue_cycle_state bit
|
||||
#define xhci_ep_get_dequeue_cycle_state(ep_ctx_ptr) (((ep_ctx_ptr)->tr_dequeue_ptr) & 1)
|
File diff suppressed because it is too large
Load Diff
@ -1,649 +0,0 @@
|
||||
#pragma once
|
||||
#include <driver/usb/usb.h>
|
||||
#include <driver/pci/pci.h>
|
||||
#include <driver/pci/msi.h>
|
||||
// #pragma GCC optimize("O0")
|
||||
#define XHCI_MAX_HOST_CONTROLLERS 4 // 本驱动程序最大支持4个xhci root hub controller
|
||||
#define XHCI_MAX_ROOT_HUB_PORTS 128 // 本驱动程序最大支持127个root hub 端口(第0个保留)
|
||||
|
||||
// ========== irq BEGIN ===========
|
||||
|
||||
#define XHCI_IRQ_DONE (1U << 31) // 当command trb 的status的第31位被驱动程序置位时,表明该trb已经执行完成(这是由于xhci规定,第31位可以由驱动程序自行决定用途)
|
||||
/**
|
||||
* @brief 每个xhci控制器的中断向量号
|
||||
*
|
||||
*/
|
||||
const uint8_t xhci_controller_irq_num[XHCI_MAX_HOST_CONTROLLERS] = {157, 158, 159, 160};
|
||||
|
||||
/**
|
||||
* @brief 通过irq号寻找对应的主机控制器id
|
||||
*
|
||||
*/
|
||||
#define xhci_find_hcid_by_irq_num(irq_num) ({ \
|
||||
int retval = -1; \
|
||||
for (int i = 0; i < XHCI_MAX_HOST_CONTROLLERS; ++i) \
|
||||
if (xhci_controller_irq_num[i] == irq_num) \
|
||||
retval = i; \
|
||||
retval; \
|
||||
})
|
||||
|
||||
struct xhci_hc_irq_install_info_t
|
||||
{
|
||||
int processor; // 中断目标处理器
|
||||
int8_t edge_trigger; // 是否边缘触发
|
||||
int8_t assert; // 是否高电平触发
|
||||
};
|
||||
// ========== irq END ===========
|
||||
|
||||
// ======== Capability Register Set BEGIN ============
|
||||
|
||||
// xhci Capability Registers offset
|
||||
#define XHCI_CAPS_CAPLENGTH 0x00 // Cap 寄存器组的长度
|
||||
#define XHCI_CAPS_RESERVED 0x01
|
||||
#define XHCI_CAPS_HCIVERSION 0x02 // 接口版本号
|
||||
#define XHCI_CAPS_HCSPARAMS1 0x04
|
||||
#define XHCI_CAPS_HCSPARAMS2 0x08
|
||||
#define XHCI_CAPS_HCSPARAMS3 0x0c
|
||||
#define XHCI_CAPS_HCCPARAMS1 0x10 // capability params 1
|
||||
#define XHCI_CAPS_DBOFF 0x14 // Doorbell offset
|
||||
#define XHCI_CAPS_RTSOFF 0x18 // Runtime register space offset
|
||||
#define XHCI_CAPS_HCCPARAMS2 0x1c // capability params 2
|
||||
|
||||
struct xhci_caps_HCSPARAMS1_reg_t
|
||||
{
|
||||
unsigned max_slots : 8; // 最大插槽数
|
||||
unsigned max_intrs : 11; // 最大中断数
|
||||
unsigned reserved : 5;
|
||||
unsigned max_ports : 8; // 最大端口数
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_caps_HCSPARAMS2_reg_t
|
||||
{
|
||||
unsigned ist : 4; // 同步调度阈值
|
||||
unsigned ERST_Max : 4; // Event Ring Segment Table: Max segs
|
||||
unsigned Reserved : 13;
|
||||
unsigned max_scratchpad_buf_HI5 : 5; // 草稿行buffer地址(高5bit)
|
||||
unsigned spr : 1; // scratchpad restore
|
||||
unsigned max_scratchpad_buf_LO5 : 5; // 草稿行buffer地址(低5bit)
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_caps_HCSPARAMS3_reg_t
|
||||
{
|
||||
uint8_t u1_device_exit_latency; // 0~10ms
|
||||
uint8_t Reserved;
|
||||
uint16_t u2_device_exit_latency; // 0~2047ms
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_caps_HCCPARAMS1_reg_t
|
||||
{
|
||||
unsigned int ac64 : 1; // 64-bit addressing capability
|
||||
unsigned int bnc : 1; // bw negotiation capability
|
||||
unsigned int csz : 1; // context size
|
||||
unsigned int ppc : 1; // 端口电源控制
|
||||
unsigned int pind : 1; // port indicators
|
||||
unsigned int lhrc : 1; // Light HC reset capability
|
||||
unsigned int ltc : 1; // latency tolerance messaging capability
|
||||
unsigned int nss : 1; // no secondary SID support
|
||||
|
||||
unsigned int pae : 1; // parse all event data
|
||||
unsigned int spc : 1; // Stopped - Short packet capability
|
||||
unsigned int sec : 1; // Stopped EDTLA capability
|
||||
unsigned int cfc : 1; // Continuous Frame ID capability
|
||||
unsigned int MaxPSASize : 4; // Max Primary Stream Array Size
|
||||
|
||||
uint16_t xECP; // xhci extended capabilities pointer
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_caps_HCCPARAMS2_reg_t
|
||||
{
|
||||
unsigned u3c : 1; // U3 Entry Capability
|
||||
unsigned cmc : 1; // ConfigEP command Max exit latency too large
|
||||
unsigned fsc : 1; // Force Save Context Capability
|
||||
unsigned ctc : 1; // Compliance Transition Capability
|
||||
unsigned lec : 1; // large ESIT payload capability
|
||||
unsigned cic : 1; // configuration information capability
|
||||
unsigned Reserved : 26;
|
||||
} __attribute__((packed));
|
||||
// ======== Capability Register Set END ============
|
||||
|
||||
// ======== Operational Register Set BEGIN =========
|
||||
|
||||
// xhci operational registers offset
|
||||
#define XHCI_OPS_USBCMD 0x00 // USB Command
|
||||
#define XHCI_OPS_USBSTS 0x04 // USB status
|
||||
#define XHCI_OPS_PAGESIZE 0x08 // Page size
|
||||
#define XHCI_OPS_DNCTRL 0x14 // Device notification control
|
||||
#define XHCI_OPS_CRCR 0x18 // Command ring control
|
||||
#define XHCI_OPS_DCBAAP 0x30 // Device context base address array pointer
|
||||
#define XHCI_OPS_CONFIG 0x38 // configuire
|
||||
#define XHCI_OPS_PRS 0x400 // Port register sets
|
||||
|
||||
struct xhci_ops_usbcmd_reg_t
|
||||
{
|
||||
unsigned rs : 1; // Run/Stop
|
||||
unsigned hcrst : 1; // host controller reset
|
||||
unsigned inte : 1; // Interrupt enable
|
||||
unsigned hsee : 1; // Host system error enable
|
||||
unsigned rsvd_psvd1 : 3; // Reserved and preserved
|
||||
unsigned lhcrst : 1; // light host controller reset
|
||||
unsigned css : 1; // controller save state
|
||||
unsigned crs : 1; // controller restore state
|
||||
unsigned ewe : 1; // enable wrap event
|
||||
unsigned ue3s : 1; // enable U3 MFINDEX Stop
|
||||
unsigned spe : 1; // stopped short packet enable
|
||||
unsigned cme : 1; // CEM Enable
|
||||
unsigned rsvd_psvd2 : 18; // Reserved and preserved
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_ops_usbsts_reg_t
|
||||
{
|
||||
unsigned HCHalted : 1;
|
||||
unsigned rsvd_psvd1 : 1; // Reserved and preserved
|
||||
unsigned hse : 1; // Host system error
|
||||
unsigned eint : 1; // event interrupt
|
||||
unsigned pcd : 1; // Port change detected
|
||||
unsigned rsvd_zerod : 3; // Reserved and Zero'd
|
||||
unsigned sss : 1; // Save State Status
|
||||
unsigned rss : 1; // restore state status
|
||||
unsigned sre : 1; // save/restore error
|
||||
unsigned cnr : 1; // controller not ready
|
||||
unsigned hce : 1; // host controller error
|
||||
unsigned rsvd_psvd2 : 19; // Reserved and Preserved
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_ops_pagesize_reg_t
|
||||
{
|
||||
uint16_t page_size; // The actual pagesize is ((this field)<<12)
|
||||
uint16_t reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_ops_dnctrl_reg_t
|
||||
{
|
||||
uint16_t value;
|
||||
uint16_t reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_ops_config_reg_t
|
||||
{
|
||||
uint8_t MaxSlotsEn; // Max slots enabled
|
||||
unsigned u3e : 1; // U3 Entry Enable
|
||||
unsigned cie : 1; // Configuration information enable
|
||||
unsigned rsvd_psvd : 22; // Reserved and Preserved
|
||||
} __attribute__((packed));
|
||||
|
||||
// ======== Operational Register Set END =========
|
||||
// ========= TRB begin ===========
|
||||
|
||||
// TRB的Transfer Type可用值定义
|
||||
#define XHCI_TRB_TRT_NO_DATA 0
|
||||
#define XHCI_TRB_TRT_RESERVED 1
|
||||
#define XHCI_TRB_TRT_OUT_DATA 2
|
||||
#define XHCI_TRB_TRT_IN_DATA 3
|
||||
|
||||
#define XHCI_CMND_RING_TRBS 128 // TRB num of command ring, not more than 4096
|
||||
|
||||
#define XHCI_TRBS_PER_RING 256
|
||||
|
||||
#define XHCI_TRB_CYCLE_OFF 0
|
||||
#define XHCI_TRB_CYCLE_ON 1
|
||||
|
||||
// 获取、设置trb中的status部分的complete code
|
||||
#define xhci_get_comp_code(status) (((status) >> 24) & 0x7f)
|
||||
#define xhci_set_comp_code(code) ((code & 0x7f) << 24)
|
||||
|
||||
/**
|
||||
* @brief xhci通用TRB结构
|
||||
*
|
||||
*/
|
||||
struct xhci_TRB_t
|
||||
{
|
||||
uint64_t param; // 参数
|
||||
uint32_t status;
|
||||
uint32_t command;
|
||||
} __attribute__((packed));
|
||||
struct xhci_TRB_normal_t
|
||||
{
|
||||
uint64_t buf_paddr; // 数据缓冲区物理地址
|
||||
|
||||
unsigned transfer_length : 17; // 传输数据长度
|
||||
unsigned TD_size : 5; // 传输描述符中剩余的数据包的数量
|
||||
unsigned intr_target : 10; // 中断目标 [0:MaxIntrs-1]
|
||||
|
||||
unsigned cycle : 1; // used to mark the enqueue pointer of transfer ring
|
||||
unsigned ent : 1; // evaluate next TRB before updating the endpoint's state
|
||||
unsigned isp : 1; // Interrupt on short packet bit
|
||||
unsigned ns : 1; // No snoop
|
||||
unsigned chain : 1; // The chain bit is used to tell the controller that this
|
||||
// TRB is associated with the next TRB in the TD
|
||||
unsigned ioc : 1; // 完成时发起中断
|
||||
unsigned idt : 1; // Immediate Data
|
||||
unsigned resv : 2; // Reserved and zero'd
|
||||
unsigned bei : 1; // Block event interrupt
|
||||
unsigned TRB_type : 6; // TRB类型
|
||||
uint16_t Reserved; // 保留且置为0
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_TRB_setup_stage_t
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
|
||||
unsigned transfer_legth : 17; // TRB transfer length
|
||||
unsigned resv1 : 5; // Reserved and zero'd
|
||||
unsigned intr_target : 10;
|
||||
|
||||
unsigned cycle : 1;
|
||||
unsigned resv2 : 4; // Reserved and zero'd
|
||||
unsigned ioc : 1; // interrupt on complete
|
||||
unsigned idt : 1; // immediate data (should always set for setup TRB)
|
||||
unsigned resv3 : 3; // Reserved and zero'd
|
||||
unsigned TRB_type : 6;
|
||||
unsigned trt : 2; // Transfer type
|
||||
unsigned resv4 : 14; // Reserved and zero'd
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_TRB_data_stage_t
|
||||
{
|
||||
uint64_t buf_paddr; // 数据缓冲区物理地址
|
||||
|
||||
unsigned transfer_length : 17; // 传输数据长度
|
||||
unsigned TD_size : 5; // 传输描述符中剩余的数据包的数量
|
||||
unsigned intr_target : 10; // 中断目标 [0:MaxIntrs-1]
|
||||
|
||||
unsigned cycle : 1; // used to mark the enqueue pointer of transfer ring
|
||||
unsigned ent : 1; // evaluate next TRB before updating the endpoint's state
|
||||
unsigned isp : 1; // Interrupt on short packet bit
|
||||
unsigned ns : 1; // No snoop
|
||||
unsigned chain : 1; // The chain bit is used to tell the controller that this
|
||||
// TRB is associated with the next TRB in the TD
|
||||
unsigned ioc : 1; // 完成时发起中断
|
||||
unsigned idt : 1; // Immediate Data
|
||||
unsigned resv : 3; // Reserved and zero'd
|
||||
unsigned TRB_type : 6; // TRB类型
|
||||
unsigned dir : 1; // 0 -> out packet
|
||||
// 1 -> in packet
|
||||
unsigned Reserved : 15; // 保留且置为0
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_TRB_status_stage_t
|
||||
{
|
||||
uint64_t resv1; // Reserved and zero'd
|
||||
|
||||
unsigned resv2 : 22; // Reserved and zero'd
|
||||
unsigned intr_target : 10; // 中断目标 [0:MaxIntrs-1]
|
||||
|
||||
unsigned cycle : 1; // used to mark the enqueue pointer of transfer ring
|
||||
unsigned ent : 1; // evaluate next TRB before updating the endpoint's state
|
||||
unsigned resv3 : 2; // Reserved and zero'd
|
||||
unsigned chain : 1; // The chain bit is used to tell the controller that this
|
||||
// TRB is associated with the next TRB in the TD
|
||||
unsigned ioc : 1; // 完成时发起中断
|
||||
unsigned resv4 : 4; // Reserved and zero'd
|
||||
unsigned TRB_type : 6; // TRB类型
|
||||
unsigned dir : 1; // 0 -> out packet
|
||||
// 1 -> in packet
|
||||
unsigned Reserved : 15; // 保留且置为0
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_TRB_cmd_complete_t
|
||||
{
|
||||
uint64_t cmd_trb_pointer_paddr; // 指向生成当前Event TRB的TRB的物理地址(16bytes对齐)
|
||||
|
||||
unsigned resv1 : 24; // Reserved and zero'd
|
||||
uint8_t code; // Completion code
|
||||
|
||||
unsigned cycle : 1; // cycle bit
|
||||
unsigned resv2 : 9; // Reserved and zero'd
|
||||
unsigned TRB_type : 6; // TRB类型
|
||||
uint8_t VF_ID;
|
||||
uint8_t slot_id; // the id of the slot associated with the
|
||||
// command that generated the event
|
||||
} __attribute__((packed));
|
||||
// ========= TRB end ===========
|
||||
|
||||
// ======== Runtime Register Set Begin =========
|
||||
|
||||
#define XHCI_RT_IR0 0x20 // 中断寄存器组0距离runtime Register set起始位置的偏移量
|
||||
#define XHCI_IR_SIZE 32 // 中断寄存器组大小
|
||||
|
||||
// 中断寄存器组内的偏移量
|
||||
#define XHCI_IR_MAN 0x00 // Interrupter Management Register
|
||||
#define XHCI_IR_MOD 0x04 // Interrupter Moderation
|
||||
#define XHCI_IR_TABLE_SIZE 0x08 // Event Ring Segment Table size (count of segments)
|
||||
#define XHCI_IR_TABLE_ADDR 0x10 // Event Ring Segment Table Base Address
|
||||
#define XHCI_IR_DEQUEUE 0x18 // Event Ring Dequeue Pointer
|
||||
|
||||
// MAN寄存器内的bit的含义
|
||||
#define XHCI_IR_IMR_PENDING (1 << 0) // Interrupt pending bit in Management Register
|
||||
#define XHCI_IR_IMR_ENABLE (1 << 1) // Interrupt enable bit in Management Register
|
||||
|
||||
struct xhci_intr_moderation_t
|
||||
{
|
||||
uint16_t interval; // 产生一个中断的时间,是interval*250ns (wait before next interrupt)
|
||||
uint16_t counter;
|
||||
} __attribute__((packed));
|
||||
// ======== Runtime Register Set END =========
|
||||
|
||||
// ======= xhci Extended Capabilities List BEGIN========
|
||||
|
||||
// ID 部分的含义定义
|
||||
#define XHCI_XECP_ID_RESERVED 0
|
||||
#define XHCI_XECP_ID_LEGACY 1 // USB Legacy Support
|
||||
#define XHCI_XECP_ID_PROTOCOL 2 // Supported protocol
|
||||
#define XHCI_XECP_ID_POWER 3 // Extended power management
|
||||
#define XHCI_XECP_ID_IOVIRT 4 // I/0 virtualization
|
||||
#define XHCI_XECP_ID_MSG 5 // Message interrupt
|
||||
#define XHCI_XECP_ID_LOCAL_MEM 6 // local memory
|
||||
#define XHCI_XECP_ID_DEBUG 10 // USB Debug capability
|
||||
#define XHCI_XECP_ID_EXTMSG 17 // Extended message interrupt
|
||||
|
||||
#define XHCI_XECP_LEGACY_TIMEOUT 10 // 设置legacy状态的等待时间
|
||||
#define XHCI_XECP_LEGACY_BIOS_OWNED (1 << 16) // 当bios控制着该hc时,该位被置位
|
||||
#define XHCI_XECP_LEGACY_OS_OWNED (1 << 24) // 当系统控制着该hc时,该位被置位
|
||||
#define XHCI_XECP_LEGACY_OWNING_MASK (XHCI_XECP_LEGACY_BIOS_OWNED | XHCI_XECP_LEGACY_OS_OWNED)
|
||||
|
||||
// ======= xhci Extended Capabilities List END ========
|
||||
|
||||
// ======= Port status and control registers BEGIN ====
|
||||
#define XHCI_PORT_PORTSC 0x00 // Port status and control
|
||||
#define XHCI_PORT_PORTPMSC 0x04 // Port power management status and control
|
||||
#define XHCI_PORT_PORTLI 0x08 // Port Link info
|
||||
#define XHCI_PORT_PORTHLMPC 0x0c // Port hardware LPM control (version 1.10 only
|
||||
|
||||
#define XHCI_PORTUSB_CHANGE_BITS ((1 << 17) | (1 << 18) | (1 << 20) | (1 << 21) | (1 << 22))
|
||||
|
||||
// 存储于portsc中的端口速度的可用值
|
||||
#define XHCI_PORT_SPEED_FULL 1
|
||||
#define XHCI_PORT_SPEED_LOW 2
|
||||
#define XHCI_PORT_SPEED_HI 3
|
||||
#define XHCI_PORT_SPEED_SUPER 4
|
||||
|
||||
// ======= Port status and control registers END ====
|
||||
|
||||
// ======= Device Slot Context BEGIN ====
|
||||
|
||||
/**
|
||||
* @brief 设备上下文结构体
|
||||
*
|
||||
*/
|
||||
struct xhci_slot_context_t
|
||||
{
|
||||
unsigned route_string : 20;
|
||||
unsigned speed : 4;
|
||||
unsigned Rsvd0 : 1; // Reserved and zero'd
|
||||
unsigned mtt : 1; // multi-TT
|
||||
unsigned hub : 1;
|
||||
unsigned entries : 5; // count of context entries
|
||||
|
||||
uint16_t max_exit_latency;
|
||||
uint8_t rh_port_num; // root hub port number
|
||||
uint8_t num_ports; // number of ports
|
||||
|
||||
uint8_t tt_hub_slot_id;
|
||||
uint8_t tt_port_num;
|
||||
unsigned ttt : 2; // TT Think Time
|
||||
unsigned Rsvd2 : 4;
|
||||
unsigned int_target : 10; // Interrupter target
|
||||
|
||||
uint8_t device_address;
|
||||
unsigned Rsvd1 : 19;
|
||||
unsigned slot_state : 5;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define XHCI_SLOT_STATE_DISABLED_OR_ENABLED 0
|
||||
#define XHCI_SLOT_STATE_DEFAULT 1
|
||||
#define XHCI_SLOT_STATE_ADDRESSED 2
|
||||
#define XHCI_SLOT_STATE_CONFIGURED 3
|
||||
|
||||
// ======= Device Slot Context END ====
|
||||
|
||||
// ======= Device Endpoint Context BEGIN ====
|
||||
|
||||
#define XHCI_EP_STATE_DISABLED 0
|
||||
#define XHCI_EP_STATE_RUNNING 1
|
||||
#define XHCI_EP_STATE_HALTED 2
|
||||
#define XHCI_EP_STATE_STOPPED 3
|
||||
#define XHCI_EP_STATE_ERROR 4
|
||||
|
||||
// End Point Doorbell numbers
|
||||
#define XHCI_SLOT_CNTX 0
|
||||
#define XHCI_EP_CONTROL 1
|
||||
#define XHCI_EP1_OUT 2
|
||||
#define XHCI_EP1_IN 3
|
||||
#define XHCI_EP2_OUT 4
|
||||
#define XHCI_EP2_IN 5
|
||||
#define XHCI_EP3_OUT 6
|
||||
#define XHCI_EP3_IN 7
|
||||
#define XHCI_EP4_OUT 8
|
||||
#define XHCI_EP4_IN 9
|
||||
#define XHCI_EP5_OUT 10
|
||||
#define XHCI_EP5_IN 11
|
||||
#define XHCI_EP6_OUT 12
|
||||
#define XHCI_EP6_IN 13
|
||||
#define XHCI_EP7_OUT 14
|
||||
#define XHCI_EP7_IN 15
|
||||
#define XHCI_EP8_OUT 16
|
||||
#define XHCI_EP8_IN 17
|
||||
#define XHCI_EP9_OUT 18
|
||||
#define XHCI_EP9_IN 19
|
||||
#define XHCI_EP10_OUT 20
|
||||
#define XHCI_EP10_IN 21
|
||||
#define XHCI_EP11_OUT 22
|
||||
#define XHCI_EP11_IN 23
|
||||
#define XHCI_EP12_OUT 24
|
||||
#define XHCI_EP12_IN 25
|
||||
#define XHCI_EP13_OUT 26
|
||||
#define XHCI_EP13_IN 27
|
||||
#define XHCI_EP14_OUT 28
|
||||
#define XHCI_EP14_IN 29
|
||||
#define XHCI_EP15_OUT 30
|
||||
#define XHCI_EP15_IN 31
|
||||
|
||||
// xhci 传输方向(用于setup stage TRB)
|
||||
#define XHCI_DIR_NO_DATA 0
|
||||
#define XHCI_DIR_OUT 2
|
||||
#define XHCI_DIR_IN 3
|
||||
|
||||
// xhci传输方向(单个bit的表示)
|
||||
#define XHCI_DIR_OUT_BIT 0
|
||||
#define XHCI_DIR_IN_BIT 1
|
||||
|
||||
/**
|
||||
* @brief xhci 端点上下文结构体
|
||||
*
|
||||
*/
|
||||
struct xhci_ep_context_t
|
||||
{
|
||||
unsigned ep_state : 3;
|
||||
unsigned Rsvd0 : 5; // Reserved and zero'd
|
||||
unsigned mult : 2; // the maximum supported number of bursts within an interval
|
||||
unsigned max_primary_streams : 5;
|
||||
unsigned linear_stream_array : 1;
|
||||
uint8_t interval;
|
||||
uint8_t max_esti_payload_hi; // Max Endpoint Service Time Interval Payload (High 8bit)
|
||||
|
||||
unsigned Rsvd1 : 1;
|
||||
unsigned err_cnt : 2; // error count. 当错误发生时,该位会自减。当减为0时,控制器会把这个端点挂起
|
||||
unsigned ep_type : 3; // endpoint type
|
||||
unsigned Rsvd2 : 1;
|
||||
unsigned hid : 1; // Host Initiate Disable
|
||||
uint8_t max_burst_size;
|
||||
uint16_t max_packet_size;
|
||||
|
||||
uint64_t tr_dequeue_ptr; // 第0bit为dequeue cycle state, 第1~3bit应保留。
|
||||
|
||||
uint16_t average_trb_len; // 平均TRB长度。该部分不应为0
|
||||
uint16_t max_esti_payload_lo; // Max Endpoint Service Time Interval Payload (Low 16bit)
|
||||
} __attribute__((packed));
|
||||
|
||||
// ======= Device Endpoint Context END ====
|
||||
|
||||
// 端口信息标志位
|
||||
#define XHCI_PROTOCOL_USB2 0
|
||||
#define XHCI_PROTOCOL_USB3 1
|
||||
#define XHCI_PROTOCOL_INFO (1 << 0) // 1->usb3, 0->usb2
|
||||
#define XHCI_PROTOCOL_HSO (1 << 1) // 1-> usb2 high speed only
|
||||
#define XHCI_PROTOCOL_HAS_PAIR (1 << 2) // 当前位被置位,意味着当前端口具有一个与之配对的端口
|
||||
#define XHCI_PROTOCOL_ACTIVE (1 << 3) // 当前端口是这个配对中,被激活的端口
|
||||
|
||||
struct xhci_ep_info_t
|
||||
{
|
||||
uint64_t ep_ring_vbase; // transfer ring的基地址
|
||||
uint64_t current_ep_ring_vaddr; // transfer ring下一个要写入的地址
|
||||
uint8_t current_ep_ring_cycle; // 当前ep的cycle bit
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief xhci端口信息
|
||||
*
|
||||
*/
|
||||
struct xhci_port_info_t
|
||||
{
|
||||
uint8_t flags; // port flags
|
||||
uint8_t paired_port_num; // 与当前端口所配对的另一个端口(相同物理接口的不同速度的port)
|
||||
uint8_t offset; // offset of this port within this protocal
|
||||
uint8_t reserved;
|
||||
uint8_t slot_id; // address device获得的slot id
|
||||
struct usb_device_desc *dev_desc; // 指向设备描述符结构体的指针
|
||||
struct xhci_ep_info_t ep_info[32]; // 各个端点的信息
|
||||
} __attribute__((packed));
|
||||
|
||||
struct xhci_host_controller_t
|
||||
{
|
||||
struct pci_device_structure_general_device_t *pci_dev_hdr; // 指向pci header结构体的指针
|
||||
int controller_id; // 操作系统给controller的编号
|
||||
uint64_t vbase; // 虚拟地址base(bar0映射到的虚拟地址)
|
||||
uint64_t vbase_op; // Operational registers 起始虚拟地址
|
||||
uint32_t rts_offset; // Runtime Register Space offset
|
||||
uint32_t db_offset; // Doorbell offset
|
||||
|
||||
uint32_t ext_caps_off; // 扩展能力寄存器偏移量
|
||||
uint16_t port_num; // 总的端口数量
|
||||
uint8_t context_size; // 设备上下文大小
|
||||
uint8_t port_num_u2; // usb 2.0端口数量
|
||||
|
||||
uint8_t port_num_u3; // usb 3端口数量
|
||||
uint8_t current_event_ring_cycle; // 当前event ring cycle
|
||||
uint8_t cmd_trb_cycle; // 当前command ring cycle
|
||||
uint32_t page_size; // page size
|
||||
|
||||
uint64_t dcbaap_vaddr; // Device Context Base Address Array Pointer的虚拟地址
|
||||
uint64_t cmd_ring_vaddr; // command ring的虚拟地址
|
||||
uint64_t cmd_trb_vaddr; // 下一个要写入的trb的虚拟地址
|
||||
uint64_t event_ring_vaddr; // event ring的虚拟地址
|
||||
uint64_t event_ring_table_vaddr; // event ring table的虚拟地址
|
||||
uint64_t current_event_ring_vaddr; // 下一个要读取的event TRB的虚拟地址
|
||||
uint64_t scratchpad_buf_array_vaddr; // 草稿行缓冲区数组的虚拟地址
|
||||
struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针(由于端口offset是从1开始的,因此该数组第0项为空)
|
||||
};
|
||||
|
||||
// Common TRB types
|
||||
enum
|
||||
{
|
||||
TRB_TYPE_NORMAL = 1,
|
||||
TRB_TYPE_SETUP_STAGE,
|
||||
TRB_TYPE_DATA_STAGE,
|
||||
TRB_TYPE_STATUS_STAGE,
|
||||
TRB_TYPE_ISOCH,
|
||||
TRB_TYPE_LINK,
|
||||
TRB_TYPE_EVENT_DATA,
|
||||
TRB_TYPE_NO_OP,
|
||||
TRB_TYPE_ENABLE_SLOT,
|
||||
TRB_TYPE_DISABLE_SLOT = 10,
|
||||
|
||||
TRB_TYPE_ADDRESS_DEVICE = 11,
|
||||
TRB_TYPE_CONFIG_EP,
|
||||
TRB_TYPE_EVALUATE_CONTEXT,
|
||||
TRB_TYPE_RESET_EP,
|
||||
TRB_TYPE_STOP_EP = 15,
|
||||
TRB_TYPE_SET_TR_DEQUEUE,
|
||||
TRB_TYPE_RESET_DEVICE,
|
||||
TRB_TYPE_FORCE_EVENT,
|
||||
TRB_TYPE_DEG_BANDWIDTH,
|
||||
TRB_TYPE_SET_LAT_TOLERANCE = 20,
|
||||
|
||||
TRB_TYPE_GET_PORT_BAND = 21,
|
||||
TRB_TYPE_FORCE_HEADER,
|
||||
TRB_TYPE_NO_OP_CMD, // 24 - 31 = reserved
|
||||
|
||||
TRB_TYPE_TRANS_EVENT = 32,
|
||||
TRB_TYPE_COMMAND_COMPLETION,
|
||||
TRB_TYPE_PORT_STATUS_CHANGE,
|
||||
TRB_TYPE_BANDWIDTH_REQUEST,
|
||||
TRB_TYPE_DOORBELL_EVENT,
|
||||
TRB_TYPE_HOST_CONTROLLER_EVENT = 37,
|
||||
TRB_TYPE_DEVICE_NOTIFICATION,
|
||||
TRB_TYPE_MFINDEX_WRAP,
|
||||
// 40 - 47 = reserved
|
||||
// 48 - 63 = Vendor Defined
|
||||
};
|
||||
|
||||
// event ring trb的完成码
|
||||
enum
|
||||
{
|
||||
TRB_COMP_TRB_SUCCESS = 1,
|
||||
TRB_COMP_DATA_BUFFER_ERROR,
|
||||
TRB_COMP_BABBLE_DETECTION,
|
||||
TRB_COMP_TRANSACTION_ERROR,
|
||||
TRB_COMP_TRB_ERROR,
|
||||
TRB_COMP_STALL_ERROR,
|
||||
TRB_COMP_RESOURCE_ERROR = 7,
|
||||
TRB_COMP_BANDWIDTH_ERROR,
|
||||
TRB_COMP_NO_SLOTS_ERROR,
|
||||
TRB_COMP_INVALID_STREAM_TYPE,
|
||||
TRB_COMP_SLOT_NOT_ENABLED,
|
||||
TRB_COMP_EP_NOT_ENABLED,
|
||||
TRB_COMP_SHORT_PACKET = 13,
|
||||
TRB_COMP_RING_UNDERRUN,
|
||||
TRB_COMP_RUNG_OVERRUN,
|
||||
TRB_COMP_VF_EVENT_RING_FULL,
|
||||
TRB_COMP_PARAMETER_ERROR,
|
||||
TRB_COMP_BANDWITDH_OVERRUN,
|
||||
TRB_COMP_CONTEXT_STATE_ERROR = 19,
|
||||
TRB_COMP_NO_PING_RESPONSE,
|
||||
TRB_COMP_EVENT_RING_FULL,
|
||||
TRB_COMP_INCOMPATIBLE_DEVICE,
|
||||
TRB_COMP_MISSED_SERVICE,
|
||||
TRB_COMP_COMMAND_RING_STOPPED = 24,
|
||||
TRB_COMP_COMMAND_ABORTED,
|
||||
TRB_COMP_STOPPED,
|
||||
TRB_COMP_STOPPER_LENGTH_ERROR,
|
||||
TRB_COMP_RESERVED,
|
||||
TRB_COMP_ISOCH_BUFFER_OVERRUN,
|
||||
TRB_COMP_EVERN_LOST = 32,
|
||||
TRB_COMP_UNDEFINED,
|
||||
TRB_COMP_INVALID_STREAM_ID,
|
||||
TRB_COMP_SECONDARY_BANDWIDTH,
|
||||
TRB_COMP_SPLIT_TRANSACTION
|
||||
/* 37 - 191 reserved */
|
||||
/* 192 - 223 vender defined errors */
|
||||
/* 224 - 225 vendor defined info */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief xhci endpoint类型
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
XHCI_EP_TYPE_INVALID = 0,
|
||||
XHCI_EP_TYPE_ISO_OUT,
|
||||
XHCI_EP_TYPE_BULK_OUT,
|
||||
XHCI_EP_TYPE_INTR_OUT,
|
||||
XHCI_EP_TYPE_CONTROL,
|
||||
XHCI_EP_TYPE_ISO_IN,
|
||||
XHCI_EP_TYPE_BULK_IN,
|
||||
XHCI_EP_TYPE_INTR_IN,
|
||||
};
|
||||
/**
|
||||
* @brief 初始化xhci控制器
|
||||
*
|
||||
* @param header 指定控制器的pci device头部
|
||||
*/
|
||||
void xhci_init(struct pci_device_structure_general_device_t *header);
|
@ -109,7 +109,7 @@ impl PciTransport {
|
||||
let mut notify_off_multiplier = 0;
|
||||
let mut isr_cfg = None;
|
||||
let mut device_cfg = None;
|
||||
device.bar_init().unwrap()?;
|
||||
device.bar_ioremap().unwrap()?;
|
||||
device.enable_master();
|
||||
//device_capability为迭代器,遍历其相当于遍历所有的cap空间
|
||||
for capability in device.capabilities().unwrap() {
|
||||
@ -487,7 +487,7 @@ fn get_bar_region<T>(
|
||||
Ok(vaddr.cast())
|
||||
}
|
||||
|
||||
/// @brief 获取虚拟地址并将其转化为对应类型的
|
||||
/// @brief 获取虚拟地址并将其转化为对应类型的切片的指针
|
||||
/// @param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息切片的指针
|
||||
/// @return Result<NonNull<[T]>, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error
|
||||
fn get_bar_region_slice<T>(
|
||||
|
@ -48,3 +48,5 @@
|
||||
#include <smp/smp.h>
|
||||
#include <time/clocksource.h>
|
||||
#include <time/sleep.h>
|
||||
#include <driver/pci/pci_irq.h>
|
||||
#include <common/errno.h>
|
@ -169,5 +169,6 @@ macro_rules! volwrite {
|
||||
VolatileWritable::vwrite(core::ptr::addr_of_mut!((*$nonnull.as_ptr()).$field), $value)
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use volread;
|
||||
pub(crate) use volwrite;
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "driver/pci/pci.h"
|
||||
#include <driver/timers/HPET/HPET.h>
|
||||
#include <driver/uart/uart.h>
|
||||
#include <driver/usb/usb.h>
|
||||
#include <driver/video/video.h>
|
||||
#include <time/timer.h>
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <debug/bug.h>
|
||||
#include <debug/traceback/traceback.h>
|
||||
#include <driver/disk/ahci/ahci.h>
|
||||
#include <driver/usb/usb.h>
|
||||
#include <driver/video/video.h>
|
||||
#include <driver/virtio/virtio.h>
|
||||
#include <exception/gate.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user