PCI设备中断重构,删去USB相关代码 (#285)

* 修复ecam无法获取MCFG table的问题

* 完善pcie

* 完善irq的错误检测机制
This commit is contained in:
YJwu2023 2023-07-08 17:22:42 +08:00 committed by GitHub
parent 2311e2f300
commit cc36cf4a18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1246 additions and 3416 deletions

View File

@ -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

View File

@ -0,0 +1,3 @@
[toolchain]
channel = "nightly-2023-01-21"
components = ["rust-src"]

View File

@ -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;

View 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,
}
}

View File

@ -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();

View File

@ -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 "$@"

View File

@ -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

View File

@ -1 +1,2 @@
pub mod pci;
pub mod pci_irq;

View File

@ -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 {

View 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;
}

View 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);

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}

View File

@ -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 50100mA的电流
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();

View File

@ -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

View File

@ -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; // 虚拟地址basebar0映射到的虚拟地址
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);

View File

@ -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>(

View File

@ -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>

View File

@ -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;

View File

@ -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>

View File

@ -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>