From cc36cf4a186be834e6c2ab857b9b9501ddb8b1eb Mon Sep 17 00:00:00 2001 From: YJwu2023 Date: Sat, 8 Jul 2023 17:22:42 +0800 Subject: [PATCH] =?UTF-8?q?PCI=E8=AE=BE=E5=A4=87=E4=B8=AD=E6=96=AD?= =?UTF-8?q?=E9=87=8D=E6=9E=84=EF=BC=8C=E5=88=A0=E5=8E=BBUSB=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E4=BB=A3=E7=A0=81=20(#285)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复ecam无法获取MCFG table的问题 * 完善pcie * 完善irq的错误检测机制 --- .vscode/c_cpp_properties.json | 3 +- kernel/rust-toolchain.toml | 3 + kernel/src/arch/x86_64/mod.rs | 1 + kernel/src/arch/x86_64/msi.rs | 23 + kernel/src/arch/x86_64/pci/pci.rs | 4 + kernel/src/driver/Makefile | 2 +- kernel/src/driver/pci/Makefile | 9 +- kernel/src/driver/pci/mod.rs | 1 + kernel/src/driver/pci/pci.rs | 121 +- kernel/src/driver/pci/pci_irq.c | 88 + kernel/src/driver/pci/pci_irq.h | 5 + kernel/src/driver/pci/pci_irq.rs | 1005 +++++++++ kernel/src/driver/usb/Makefile | 9 - kernel/src/driver/usb/usb.c | 64 - kernel/src/driver/usb/usb.h | 308 --- kernel/src/driver/usb/xhci/internal.h | 87 - kernel/src/driver/usb/xhci/xhci.c | 2271 --------------------- kernel/src/driver/usb/xhci/xhci.h | 649 ------ kernel/src/driver/virtio/transport_pci.rs | 4 +- kernel/src/include/bindings/wrapper.h | 2 + kernel/src/libs/volatile.rs | 1 + kernel/src/main.c | 1 - kernel/src/process/process.c | 1 - 23 files changed, 1246 insertions(+), 3416 deletions(-) create mode 100644 kernel/rust-toolchain.toml create mode 100644 kernel/src/arch/x86_64/msi.rs create mode 100644 kernel/src/driver/pci/pci_irq.c create mode 100644 kernel/src/driver/pci/pci_irq.h create mode 100644 kernel/src/driver/pci/pci_irq.rs delete mode 100644 kernel/src/driver/usb/Makefile delete mode 100644 kernel/src/driver/usb/usb.c delete mode 100644 kernel/src/driver/usb/usb.h delete mode 100644 kernel/src/driver/usb/xhci/internal.h delete mode 100644 kernel/src/driver/usb/xhci/xhci.c delete mode 100644 kernel/src/driver/usb/xhci/xhci.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 31db8592..a8a6ec84 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -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 diff --git a/kernel/rust-toolchain.toml b/kernel/rust-toolchain.toml new file mode 100644 index 00000000..3d808158 --- /dev/null +++ b/kernel/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2023-01-21" +components = ["rust-src"] \ No newline at end of file diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 6975444e..5b325ac9 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -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; diff --git a/kernel/src/arch/x86_64/msi.rs b/kernel/src/arch/x86_64/msi.rs new file mode 100644 index 00000000..394206f1 --- /dev/null +++ b/kernel/src/arch/x86_64/msi.rs @@ -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, + } +} diff --git a/kernel/src/arch/x86_64/pci/pci.rs b/kernel/src/arch/x86_64/pci/pci.rs index a6c42477..2f4d4d4c 100644 --- a/kernel/src/arch/x86_64/pci/pci.rs +++ b/kernel/src/arch/x86_64/pci/pci.rs @@ -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(); diff --git a/kernel/src/driver/Makefile b/kernel/src/driver/Makefile index df9f5458..36a847a7 100644 --- a/kernel/src/driver/Makefile +++ b/kernel/src/driver/Makefile @@ -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 "$@" diff --git a/kernel/src/driver/pci/Makefile b/kernel/src/driver/pci/Makefile index 55f6c1b9..91c13318 100644 --- a/kernel/src/driver/pci/Makefile +++ b/kernel/src/driver/pci/Makefile @@ -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 + diff --git a/kernel/src/driver/pci/mod.rs b/kernel/src/driver/pci/mod.rs index 7652d2c4..457dff62 100644 --- a/kernel/src/driver/pci/mod.rs +++ b/kernel/src/driver/pci/mod.rs @@ -1 +1,2 @@ pub mod pci; +pub mod pci_irq; diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 695989d0..5c089fe2 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -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> { + #[inline(always)] + fn bar_ioremap(&mut self) -> Option> { None } - /// todo - fn msix_init(&mut self) -> Option> { + /// @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 { + 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 { + 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>; } /// 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, 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> { + fn bar_ioremap(&mut self) -> Option> { 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> { + 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, 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> { + 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> { + 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 { diff --git a/kernel/src/driver/pci/pci_irq.c b/kernel/src/driver/pci/pci_irq.c new file mode 100644 index 00000000..ae3dffd6 --- /dev/null +++ b/kernel/src/driver/pci/pci_irq.c @@ -0,0 +1,88 @@ +#include "pci_irq.h" +#include "exception/irq.h" +#include +#include +// 现在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; +} \ No newline at end of file diff --git a/kernel/src/driver/pci/pci_irq.h b/kernel/src/driver/pci/pci_irq.h new file mode 100644 index 00000000..4de4bd95 --- /dev/null +++ b/kernel/src/driver/pci/pci_irq.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include +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); \ No newline at end of file diff --git a/kernel/src/driver/pci/pci_irq.rs b/kernel/src/driver/pci/pci_irq.rs new file mode 100644 index 00000000..24e95afe --- /dev/null +++ b/kernel/src/driver/pci/pci_irq.rs @@ -0,0 +1,1005 @@ +#![allow(dead_code)] + +use core::mem::size_of; +use core::ptr::NonNull; + +use alloc::ffi::CString; +use alloc::vec::Vec; + +use super::pci::{HeaderType, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError}; +use crate::arch::msi::{ia64_pci_get_arch_msi_message_address, ia64_pci_get_arch_msi_message_data}; +use crate::arch::{PciArch, TraitPciArch}; +use crate::include::bindings::bindings::{ + c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL, +}; +use crate::libs::volatile::{ + volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, +}; +use crate::{kdebug, kerror, kinfo, kwarn}; +/// MSIX表的一项 +#[repr(C)] +struct MsixEntry { + vector_control: Volatile, + msg_data: Volatile, + msg_upper_addr: Volatile, + msg_addr: Volatile, +} +/// Pending表的一项 +#[repr(C)] +struct PendingEntry { + entry: Volatile, +} +/// PCI设备中断错误 +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum PciIrqError { + IrqTypeNotSupported, + PciDeviceNotSupportIrq, + IrqTypeUnmatch, + InvalidIrqIndex(u16), + InvalidIrqNum(u16), + IrqNumOccupied(u16), + DeviceIrqOverflow, + MxiIrqNumWrong, + PciBarNotInited, + BarGetVaddrFailed, + MaskNotSupported, + IrqNotInited, +} +/// PCI设备的中断类型 +#[derive(Copy, Clone, Debug)] +pub enum IrqType { + Msi { + address_64: bool, + maskable: bool, + irq_max_num: u16, + cap_offset: u8, + }, + Msix { + msix_table_bar: u8, + msix_table_offset: u32, + pending_table_bar: u8, + pending_table_offset: u32, + irq_max_num: u16, + cap_offset: u8, + }, + Legacy, + Unused, +} +// PCI设备install中断时需要传递的参数 +#[derive(Clone, Debug)] +pub struct IrqMsg { + irq_common_message: IrqCommonMsg, + irq_specific_message: IrqSpecificMsg, +} +// PCI设备install中断时需要传递的共同参数 +#[derive(Clone, Debug)] +pub struct IrqCommonMsg { + irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index + irq_name: CString, //中断名字 + irq_parameter: u16, //中断额外参数,可传入中断处理函数 + irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), // 中断处理函数 + irq_ack: Option, // 中断的ack,可为None,若为None则中断处理中会正常通知中断结束,不为None则调用传入的函数进行回复 +} +// PCI设备install中断时需要传递的特有参数,Msi代表MSI与MSIX +#[derive(Clone, Debug)] +pub enum IrqSpecificMsg { + Legacy, + Msi { + processor: u16, + trigger_mode: TriggerMode, + }, +} +impl IrqSpecificMsg { + fn msi_default() -> Self { + IrqSpecificMsg::Msi { + processor: 0, + trigger_mode: TriggerMode::EdgeTrigger, + } + } +} +// 申请中断的触发模式,MSI默认为边沿触发 +#[derive(Copy, Clone, Debug)] +pub enum TriggerMode { + EdgeTrigger, + AssertHigh, + AssertLow, +} +bitflags! { + /// 设备中断类型,使用bitflag使得中断类型的选择更多元化 + pub struct IRQ: u8{ + const PCI_IRQ_LEGACY = 1 << 0; + const PCI_IRQ_MSI = 1 << 1; + const PCI_IRQ_MSIX = 1 << 2; + const PCI_IRQ_ALL_TYPES=IRQ::PCI_IRQ_LEGACY.bits|IRQ::PCI_IRQ_MSI.bits|IRQ::PCI_IRQ_MSIX.bits; + } +} +/// PciDeviceStructure的子trait,使用继承以直接使用PciDeviceStructure里的接口 +pub trait PciInterrupt: PciDeviceStructure { + /// @brief PCI设备调用该函数选择中断类型 + /// @param self PCI设备的可变引用 + /// @param flag 选择的中断类型(支持多个选择),如PCI_IRQ_ALL_TYPES表示所有中断类型均可,让系统按顺序进行选择 + /// @return Option 失败返回None,成功则返回对应中断类型 + fn irq_init(&mut self, flag: IRQ) -> Option { + // MSIX中断优先 + if flag.contains(IRQ::PCI_IRQ_MSIX) { + if let Some(cap_offset) = self.msix_capability_offset() { + let data = + PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4); + let irq_max_num = ((data >> 16) & 0x07ff) as u16; + let data = + PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4); + let msix_table_bar = (data & 0x01) as u8; + let msix_table_offset = data & 0xfffe; + let data = + PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 8); + let pending_table_bar = (data & 0x01) as u8; + let pending_table_offset = data & 0xfffe; + *self.irq_type_mut()? = IrqType::Msix { + msix_table_bar, + msix_table_offset, + pending_table_bar, + pending_table_offset, + irq_max_num, + cap_offset, + }; + return Some(IrqType::Msix { + msix_table_bar, + msix_table_offset, + pending_table_bar, + pending_table_offset, + irq_max_num, + cap_offset, + }); + } + } + // 其次MSI + if flag.contains(IRQ::PCI_IRQ_MSI) { + if let Some(cap_offset) = self.msi_capability_offset() { + let data = + PciArch::read_config(&self.common_header().bus_device_function, cap_offset); + let message_control = (data >> 16) as u16; + let maskable = (message_control & 0x0100) != 0; + let address_64 = (message_control & 0x0080) != 0; + let irq_max_num = (1 << (((message_control & 0x000e) >> 1) + 1)) as u16; + *self.irq_type_mut()? = IrqType::Msi { + address_64, + maskable, + irq_max_num, + cap_offset, + }; + return Some(IrqType::Msi { + address_64, + maskable, + irq_max_num, + cap_offset, + }); + } + } + // 最后选择legacy# + if flag.contains(IRQ::PCI_IRQ_LEGACY) { + *self.irq_type_mut()? = IrqType::Legacy; + return Some(IrqType::Legacy); + } + None + } + + /// @brief 启动/关闭设备中断 + /// @param self PCI设备的可变引用 + /// @param enable 开启/关闭 + fn irq_enable(&mut self, enable: bool) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { .. } => { + return self.msix_enable(enable); + } + IrqType::Msi { .. } => { + return self.msi_enable(enable); + } + IrqType::Legacy => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported)); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 启动/关闭设备MSIX中断 + /// @param self PCI设备的可变引用 + /// @param enable 开启/关闭 + fn msix_enable(&mut self, enable: bool) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { cap_offset, .. } => { + let mut message = + PciArch::read_config(&self.common_header().bus_device_function, cap_offset); + if enable { + message |= 1 << 31; + } else { + message &= !(1 << 31); + } + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + message, + ); + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 启动/关闭设备MSI中断 + /// @param self PCI设备的可变引用 + /// @param enable 开启/关闭 + fn msi_enable(&mut self, enable: bool) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msi { cap_offset, .. } => { + let mut message = + PciArch::read_config(&self.common_header().bus_device_function, cap_offset); + if enable { + message |= 1 << 16; + } else { + message &= !(1 << 16); + } + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + message, + ); + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 获取指定数量的中断号 todo 需要中断重构支持 + fn irq_alloc(num: u16) -> Option> { + None + } + /// @brief 进行PCI设备中断的安装 + /// @param self PCI设备的可变引用 + /// @param msg PCI设备install中断时需要传递的共同参数 + /// @return 一切正常返回Ok(0),有错误返回对应错误原因 + fn irq_install(&mut self, msg: IrqMsg) -> Result { + if let Some(irq_vector) = self.irq_vector_mut() { + if msg.irq_common_message.irq_index as usize > irq_vector.len() { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + msg.irq_common_message.irq_index, + ))); + } + } + self.irq_enable(false)?; //中断设置更改前先关闭对应PCI设备的中断 + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { .. } => { + return self.msix_install(msg); + } + IrqType::Msi { .. } => { + return self.msi_install(msg); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 进行PCI设备中断的安装(MSI) + /// @param self PCI设备的可变引用 + /// @param msg PCI设备install中断时需要传递的共同参数 + /// @return 一切正常返回Ok(0),有错误返回对应错误原因 + fn msi_install(&mut self, msg: IrqMsg) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msi { + address_64, + irq_max_num, + cap_offset, + .. + } => { + // 注意:MSI中断分配的中断号必须连续且大小为2的倍数 + if self.irq_vector_mut().unwrap().len() > irq_max_num as usize { + return Err(PciError::PciIrqError(PciIrqError::DeviceIrqOverflow)); + } + let irq_num = + self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize]; + let common_msg = &msg.irq_common_message; + let result = unsafe { + c_irq_install( + irq_num as u64, + Some(common_msg.irq_hander), + common_msg.irq_parameter as u64, + common_msg.irq_name.as_ptr(), + common_msg.irq_ack, + ) + }; + match result as u32 { + EINVAL => { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num))); + } + EAGAIN => { + return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied( + irq_num, + ))); + } + _ => {} + } + //MSI中断只需配置一次PCI寄存器 + if common_msg.irq_index == 0 { + let msg_address = ia64_pci_get_arch_msi_message_address(0); + let trigger = match msg.irq_specific_message { + IrqSpecificMsg::Legacy => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode, + }; + let msg_data = ia64_pci_get_arch_msi_message_data(irq_num, 0, trigger); + //写入Message Data和Message Address + if address_64 { + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 4, + msg_address, + ); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 8, + 0, + ); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 12, + msg_data, + ); + } else { + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 4, + msg_address, + ); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 8, + msg_data, + ); + } + let data = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset, + ); + let message_control = (data >> 16) as u16; + match self.irq_vector_mut().unwrap().len() { + 1 => { + let temp = message_control & (!0x0070); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + (temp as u32) << 16, + ); + } + 2 => { + let temp = message_control & (!0x0070); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + ((temp | (0x0001 << 4)) as u32) << 16, + ); + } + 4 => { + let temp = message_control & (!0x0070); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + ((temp | (0x0002 << 4)) as u32) << 16, + ); + } + 8 => { + let temp = message_control & (!0x0070); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + ((temp | (0x0003 << 4)) as u32) << 16, + ); + } + 16 => { + let temp = message_control & (!0x0070); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + ((temp | (0x0004 << 4)) as u32) << 16, + ); + } + 32 => { + let temp = message_control & (!0x0070); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + ((temp | (0x0005 << 4)) as u32) << 16, + ); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::MxiIrqNumWrong)); + } + } + } + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 进行PCI设备中断的安装(MSIX) + /// @param self PCI设备的可变引用 + /// @param msg PCI设备install中断时需要传递的共同参数 + /// @return 一切正常返回Ok(0),有错误返回对应错误原因 + fn msix_install(&mut self, msg: IrqMsg) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { + irq_max_num, + msix_table_bar, + msix_table_offset, + .. + } => { + if self.irq_vector_mut().unwrap().len() > irq_max_num as usize { + return Err(PciError::PciIrqError(PciIrqError::DeviceIrqOverflow)); + } + let irq_num = + self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize]; + let common_msg = &msg.irq_common_message; + let result = unsafe { + c_irq_install( + irq_num as u64, + Some(common_msg.irq_hander), + common_msg.irq_parameter as u64, + common_msg.irq_name.as_ptr(), + common_msg.irq_ack, + ) + }; + match result as u32 { + EINVAL => { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num))); + } + EAGAIN => { + return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied( + irq_num, + ))); + } + _ => {} + } + + let msg_address = ia64_pci_get_arch_msi_message_address(0); + let trigger = match msg.irq_specific_message { + IrqSpecificMsg::Legacy => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode, + }; + let msg_data = ia64_pci_get_arch_msi_message_data(irq_num, 0, trigger); + //写入Message Data和Message Address + let pcistandardbar = self + .bar() + .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))?; + let msix_bar = pcistandardbar.get_bar(msix_table_bar)?; + let vaddr = msix_bar + .virtual_address() + .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))? + as usize + + msix_table_offset as usize + + msg.irq_common_message.irq_index as usize * size_of::(); + let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); + unsafe { + volwrite!(msix_entry, vector_control, 0); + volwrite!(msix_entry, msg_data, msg_data); + volwrite!(msix_entry, msg_upper_addr, 0); + volwrite!(msix_entry, msg_addr, msg_address); + } + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 进行PCI设备中断的卸载 + /// @param self PCI设备的可变引用 + fn irq_uninstall(&mut self) -> Result { + self.irq_enable(false)?; //中断设置更改前先关闭对应PCI设备的中断 + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { .. } => { + return self.msix_uninstall(); + } + IrqType::Msi { .. } => { + return self.msi_uninstall(); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 进行PCI设备中断的卸载(MSI) + /// @param self PCI设备的可变引用 + fn msi_uninstall(&mut self) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msi { + address_64, + cap_offset, + .. + } => { + for vector in self.irq_vector_mut().unwrap() { + unsafe { + c_irq_uninstall(vector.clone() as u64); + } + } + PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 4, + 0, + ); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 8, + 0, + ); + if address_64 { + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset + 12, + 0, + ); + } + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 进行PCI设备中断的卸载(MSIX) + /// @param self PCI设备的可变引用 + fn msix_uninstall(&mut self) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { + irq_max_num, + cap_offset, + msix_table_bar, + msix_table_offset, + .. + } => { + for vector in self.irq_vector_mut().unwrap() { + unsafe { + c_irq_uninstall(vector.clone() as u64); + } + } + PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0); + let pcistandardbar = self + .bar() + .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) + .unwrap(); + let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap(); + for index in 0..irq_max_num { + let vaddr = msix_bar + .virtual_address() + .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed)) + .unwrap() as usize + + msix_table_offset as usize + + index as usize * size_of::(); + let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); + unsafe { + volwrite!(msix_entry, vector_control, 0); + volwrite!(msix_entry, msg_data, 0); + volwrite!(msix_entry, msg_upper_addr, 0); + volwrite!(msix_entry, msg_addr, 0); + } + } + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 屏蔽相应位置的中断 + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + fn irq_mask(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { .. } => { + return self.msix_mask(irq_index); + } + IrqType::Msi { .. } => { + return self.msi_mask(irq_index); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 屏蔽相应位置的中断(MSI) + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + fn msi_mask(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msi { + maskable, + address_64, + cap_offset, + irq_max_num, + } => { + if irq_index >= irq_max_num { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + irq_index, + ))); + } + if maskable { + match address_64 { + true => { + let mut mask = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset + 16, + ); + mask |= 1 << irq_index; + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + mask, + ); + } + false => { + let mut mask = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset + 12, + ); + mask |= 1 << irq_index; + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + mask, + ); + } + } + return Ok(0); + } + return Err(PciError::PciIrqError(PciIrqError::MaskNotSupported)); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 屏蔽相应位置的中断(MSIX) + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + fn msix_mask(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { + irq_max_num, + msix_table_bar, + msix_table_offset, + .. + } => { + if irq_index >= irq_max_num { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + irq_index, + ))); + } + let pcistandardbar = self + .bar() + .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) + .unwrap(); + let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap(); + let vaddr = msix_bar.virtual_address().unwrap() as usize + + msix_table_offset as usize + + irq_index as usize * size_of::(); + let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); + unsafe { + volwrite!(msix_entry, vector_control, 1); + } + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 解除屏蔽相应位置的中断 + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + fn irq_unmask(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { .. } => { + return self.msix_unmask(irq_index); + } + IrqType::Msi { .. } => { + return self.msi_unmask(irq_index); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 解除屏蔽相应位置的中断(MSI) + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + fn msi_unmask(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msi { + maskable, + address_64, + cap_offset, + irq_max_num, + } => { + if irq_index >= irq_max_num { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + irq_index, + ))); + } + if maskable { + match address_64 { + true => { + let mut mask = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset + 16, + ); + mask &= !(1 << irq_index); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + mask, + ); + } + false => { + let mut mask = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset + 12, + ); + mask &= !(1 << irq_index); + PciArch::write_config( + &self.common_header().bus_device_function, + cap_offset, + mask, + ); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::MaskNotSupported)); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 解除屏蔽相应位置的中断(MSIX) + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + fn msix_unmask(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { + irq_max_num, + msix_table_bar, + msix_table_offset, + .. + } => { + if irq_index >= irq_max_num { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + irq_index, + ))); + } + let pcistandardbar = self + .bar() + .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) + .unwrap(); + let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap(); + let vaddr = msix_bar.virtual_address().unwrap() as usize + + msix_table_offset as usize + + irq_index as usize * size_of::(); + let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap(); + unsafe { + volwrite!(msix_entry, vector_control, 0); + } + return Ok(0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 检查被挂起的中断是否在挂起的时候产生了 + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + /// @return 是否在挂起过程中产生中断(异常情况也返回false) + fn irq_check_pending(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { .. } => { + return self.msix_check_pending(irq_index); + } + IrqType::Msi { .. } => { + return self.msi_check_pending(irq_index); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 检查被挂起的中断是否在挂起的时候产生了(MSI) + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + /// @return 是否在挂起过程中产生中断(异常情况也返回false) + fn msi_check_pending(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msi { + maskable, + address_64, + cap_offset, + irq_max_num, + } => { + if irq_index >= irq_max_num { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + irq_index, + ))); + } + if maskable { + match address_64 { + true => { + let mut pend = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset + 20, + ); + pend &= 1 << irq_index; + return Ok(pend != 0); + } + false => { + let mut pend = PciArch::read_config( + &self.common_header().bus_device_function, + cap_offset + 16, + ); + pend &= 1 << irq_index; + return Ok(pend != 0); + } + } + } + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } + /// @brief 检查被挂起的中断是否在挂起的时候产生了(MSIX) + /// @param self PCI设备的可变引用 + /// @param irq_index 中断的位置(在vec中的index和安装的index相同) + /// @return 是否在挂起过程中产生中断(异常情况也返回false) + fn msix_check_pending(&mut self, irq_index: u16) -> Result { + if let Some(irq_type) = self.irq_type_mut() { + match *irq_type { + IrqType::Msix { + irq_max_num, + pending_table_bar, + pending_table_offset, + .. + } => { + if irq_index >= irq_max_num { + return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex( + irq_index, + ))); + } + let pcistandardbar = self + .bar() + .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited)) + .unwrap(); + let pending_bar = pcistandardbar.get_bar(pending_table_bar).unwrap(); + let vaddr = pending_bar.virtual_address().unwrap() as usize + + pending_table_offset as usize + + (irq_index as usize / 64) * size_of::(); + let pending_entry = NonNull::new(vaddr as *mut PendingEntry).unwrap(); + let pending_entry = unsafe { volread!(pending_entry, entry) }; + return Ok(pending_entry & (1 << (irq_index as u64 % 64)) != 0); + } + IrqType::Unused => { + return Err(PciError::PciIrqError(PciIrqError::IrqNotInited)); + } + _ => { + return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch)); + } + } + } + return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq)); + } +} +/// PCI标准设备的msi/msix中断相关函数块 +impl PciInterrupt for PciDeviceStructureGeneralDevice {} diff --git a/kernel/src/driver/usb/Makefile b/kernel/src/driver/usb/Makefile deleted file mode 100644 index 27beeef0..00000000 --- a/kernel/src/driver/usb/Makefile +++ /dev/null @@ -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 \ No newline at end of file diff --git a/kernel/src/driver/usb/usb.c b/kernel/src/driver/usb/usb.c deleted file mode 100644 index fb8673ae..00000000 --- a/kernel/src/driver/usb/usb.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "usb.h" -#include "xhci/xhci.h" -#include -#include -#include -#include -#include - -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; -} \ No newline at end of file diff --git a/kernel/src/driver/usb/usb.h b/kernel/src/driver/usb/usb.h deleted file mode 100644 index c2298342..00000000 --- a/kernel/src/driver/usb/usb.h +++ /dev/null @@ -1,308 +0,0 @@ -#pragma once -#include - -// 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(); \ No newline at end of file diff --git a/kernel/src/driver/usb/xhci/internal.h b/kernel/src/driver/usb/xhci/internal.h deleted file mode 100644 index c7ef1598..00000000 --- a/kernel/src/driver/usb/xhci/internal.h +++ /dev/null @@ -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) \ No newline at end of file diff --git a/kernel/src/driver/usb/xhci/xhci.c b/kernel/src/driver/usb/xhci/xhci.c deleted file mode 100644 index 1b24be42..00000000 --- a/kernel/src/driver/usb/xhci/xhci.c +++ /dev/null @@ -1,2271 +0,0 @@ -#include "xhci.h" -#include "internal.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// 由于xhci寄存器读取需要对齐,因此禁用GCC优化选项 -#pragma GCC optimize("O0") - -spinlock_t xhci_controller_init_lock = {0}; // xhci控制器初始化锁(在usb_init中被初始化) - -static int xhci_ctrl_count = 0; // xhci控制器计数 - -static struct xhci_host_controller_t xhci_hc[XHCI_MAX_HOST_CONTROLLERS] = {0}; - -void xhci_hc_irq_enable(uint64_t irq_num); -void xhci_hc_irq_disable(uint64_t irq_num); -uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg); -void xhci_hc_irq_uninstall(uint64_t irq_num); - -static int xhci_hc_find_available_id(); -static int xhci_hc_stop(int id); -static int xhci_hc_reset(int id); -static int xhci_hc_stop_legacy(int id); -static int xhci_hc_start_sched(int id); -static int xhci_hc_stop_sched(int id); -static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int version, uint32_t *offset, - uint32_t *count, uint16_t *protocol_flag); -static int xhci_hc_pair_ports(int id); -static uint64_t xhci_create_ring(int trbs); -static uint64_t xhci_create_event_ring(int trbs, uint64_t *ret_ring_addr); -void xhci_hc_irq_handler(uint64_t irq_num, uint64_t cid, struct pt_regs *regs); -static int xhci_hc_init_intr(int id); -static int xhci_hc_start_ports(int id); - -static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring); -static uint64_t xhci_initialize_slot(const int id, const int port, const int speed, const int max_packet); -static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const int port_id, const int ep_num, - const int max_packet, const int max_burst, const int type, const int direction, - const int speed, const int ep_interval); -static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int slot_id, const bool block); -static int xhci_control_in(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, - const int max_packet); -static int xhci_control_out(const int id, struct usb_request_packet_t *packet, void *target, const int slot_id, - const int max_packet); -static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_packet_t *packet, - const uint8_t direction); -static int xhci_data_stage(struct xhci_ep_info_t *ep, uint64_t buf_vaddr, uint8_t trb_type, const uint32_t size, - uint8_t direction, const int max_packet, const uint64_t status_vaddr); -static int xhci_status_stage(struct xhci_ep_info_t *ep, uint8_t direction, uint64_t status_buf_vaddr); -static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr); -static inline int xhci_get_desc(const int id, const int port_id, void *target, const uint16_t desc_type, - const uint8_t desc_index, const uint16_t lang_id, const uint16_t length); -static int xhci_get_config_desc(const int id, const int port_id, struct usb_config_desc *conf_desc); -static inline int xhci_get_config_desc_full(const int id, const int port_id, const struct usb_config_desc *conf_desc, - void *target); -static int xhci_get_interface_desc(const void *in_buf, const uint8_t if_num, struct usb_interface_desc **if_desc); -static inline int xhci_get_endpoint_desc(const struct usb_interface_desc *if_desc, const uint8_t ep_num, - struct usb_endpoint_desc **ep_desc); -static int xhci_get_descriptor(const int id, const int port_id, struct usb_device_desc *dev_desc); -static int xhci_configure_port(const int id, const int port_id); -static int xhci_configure_endpoint(const int id, const int port_id, const uint8_t ep_num, const uint8_t ep_type, - struct usb_endpoint_desc *ep_desc); -static int xhci_get_hid_report(int id, int port_id, int interface_number, void *ret_hid_report, - uint32_t hid_report_len); -static int xhci_get_hid_descriptor(int id, int port_id, const void *full_conf, int interface_number, - struct usb_hid_desc **ret_hid_desc); - -hardware_intr_controller xhci_hc_intr_controller = { - .enable = xhci_hc_irq_enable, - .disable = xhci_hc_irq_disable, - .install = xhci_hc_irq_install, - .uninstall = xhci_hc_irq_uninstall, - .ack = apic_local_apic_edge_ack, -}; - -/** - * @brief 在controller数组之中寻找可用插槽 - * - * 注意:该函数只能被获得init锁的进程所调用 - * @return int 可用id(无空位时返回-1) - */ -static int xhci_hc_find_available_id() -{ - if (unlikely(xhci_ctrl_count >= XHCI_MAX_HOST_CONTROLLERS)) - return -1; - - for (int i = 0; i < XHCI_MAX_HOST_CONTROLLERS; ++i) - { - if (xhci_hc[i].pci_dev_hdr == NULL) - return i; - } - return -1; -} - -/** - * @brief 从指定地址读取trb - * - * @param trb 要存储到的trb的地址 - * @param address 待读取trb的地址 - */ -static __always_inline void xhci_get_trb(struct xhci_TRB_t *trb, const uint64_t address) -{ - trb->param = __read8b(address); - trb->status = __read4b(address + 8); - trb->command = __read4b(address + 12); -} - -/** - * @brief 将给定的trb写入指定的地址 - * - * @param trb 源trb - * @param address 拷贝的目标地址 - */ -static __always_inline void xhci_set_trb(struct xhci_TRB_t *trb, const uint64_t address) -{ - __write8b(address, trb->param); - __write4b(address + 8, trb->status); - __write4b(address + 12, trb->command); -} - -/** - * @brief 将ep结构体写入到设备上下文中的对应块内 - * - * @param id 主机控制器id - * @param slot_vaddr 设备上下文虚拟地址 - * @param ep_num ep结构体要写入到哪个块中(在设备上下文中的块号) - * @param ep 源数据 - */ -static __always_inline void __write_ep(int id, uint64_t slot_vaddr, int ep_num, struct xhci_ep_context_t *ep) -{ - memcpy((void *)(slot_vaddr + ep_num * xhci_hc[id].context_size), ep, sizeof(struct xhci_ep_context_t)); -} - -/** - * @brief 从设备上下文中的对应块内读取数据到ep结构体 - * - * @param id 主机控制器id - * @param slot_vaddr 设备上下文虚拟地址 - * @param ep_num 要从哪个块中读取(在设备上下文中的块号) - * @param ep 目标地址 - */ -static __always_inline void __read_from_ep(int id, uint64_t slot_vaddr, int ep_num, struct xhci_ep_context_t *ep) -{ - memcpy(ep, (void *)(slot_vaddr + ep_num * xhci_hc[id].context_size), sizeof(struct xhci_ep_context_t)); -} - -/** - * @brief 将slot上下文数组结构体写入插槽的上下文空间 - * - * @param vaddr 目标地址 - * @param slot_ctx slot上下文数组 - */ -static __always_inline void __write_slot(const uint64_t vaddr, struct xhci_slot_context_t *slot_ctx) -{ - memcpy((void *)vaddr, slot_ctx, sizeof(struct xhci_slot_context_t)); -} - -/** - * @brief 从指定地址读取slot context - * - * @param slot_ctx 目标地址 - * @param slot_vaddr 源地址 - * @return __always_inline - */ -static __always_inline void __read_from_slot(struct xhci_slot_context_t *slot_ctx, uint64_t slot_vaddr) -{ - memcpy(slot_ctx, (void *)slot_vaddr, sizeof(struct xhci_slot_context_t)); -} - -/** - * @brief 写入doorbell寄存器 - * - * @param id 主机控制器id - * @param slot_id usb控制器插槽id(0用作命令门铃,其他的用于具体的设备的门铃) - * @param value endpoint - */ -static __always_inline void __xhci_write_doorbell(const int id, const uint16_t slot_id, const uint32_t value) -{ - // 确保写入门铃寄存器之前,所有的写操作均已完成 - io_mfence(); - xhci_write_cap_reg32(id, xhci_hc[id].db_offset + slot_id * sizeof(uint32_t), value); - io_mfence(); -} - -/** - * @brief 将trb写入指定的ring中,并更新下一个要写入的地址的值 - * - * @param ep_info 端点信息结构体 - * @param trb 待写入的trb - */ -static __always_inline void __xhci_write_trb(struct xhci_ep_info_t *ep_info, struct xhci_TRB_t *trb) -{ - memcpy((void *)ep_info->current_ep_ring_vaddr, trb, sizeof(struct xhci_TRB_t)); - - ep_info->current_ep_ring_vaddr += sizeof(struct xhci_TRB_t); - - struct xhci_TRB_normal_t *ptr = (struct xhci_TRB_normal_t *)(ep_info->current_ep_ring_vaddr); - - // ring到头了,转换cycle,然后回到第一个trb - if (unlikely(ptr->TRB_type == TRB_TYPE_LINK)) - { - ptr->cycle = ep_info->current_ep_ring_cycle; - ep_info->current_ep_ring_vaddr = ep_info->ep_ring_vbase; - ep_info->current_ep_ring_cycle ^= 1; - } -} - -/** - * @brief 获取设备上下文缓冲区的虚拟地址 - * - * @param id 主机控制器id - * @param port_id 端口id - * @return 设备上下文缓冲区的虚拟地址 - */ -static __always_inline uint64_t xhci_get_device_context_vaddr(const int id, const int port_id) -{ - return (uint64_t)phys_2_virt( - __read8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port_id].slot_id * sizeof(uint64_t)))); -} - -/** - * @brief 停止xhci主机控制器 - * - * @param id 主机控制器id - * @return int - */ -static int xhci_hc_stop(int id) -{ - - // 判断是否已经停止 - if (unlikely((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 1)) - return 0; - io_mfence(); - xhci_write_op_reg32(id, XHCI_OPS_USBCMD, 0x00000000); - io_mfence(); - char timeout = 17; - while ((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 0) - { - io_mfence(); - rs_usleep(1000); - if (--timeout == 0) - return -ETIMEDOUT; - } - - return 0; -} - -/** - * @brief reset xHCI主机控制器 - * - * @param id 主机控制器id - * @return int - */ -static int xhci_hc_reset(int id) -{ - int retval = 0; - io_mfence(); - // 判断HCHalted是否置位 - if ((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 0) - { - io_mfence(); - kdebug("stopping usb hc..."); - // 未置位,需要先尝试停止usb主机控制器 - retval = xhci_hc_stop(id); - if (unlikely(retval)) - return retval; - } - int timeout = 500; // wait 500ms - // reset - uint32_t cmd = xhci_read_op_reg32(id, XHCI_OPS_USBCMD); - io_mfence(); - - cmd |= (1 << 1); - xhci_write_op_reg32(id, XHCI_OPS_USBCMD, cmd); - io_mfence(); - io_mfence(); - while (xhci_read_op_reg32(id, XHCI_OPS_USBCMD) & (1 << 1)) - { - io_mfence(); - rs_usleep(1000); - if (--timeout == 0) - return -ETIMEDOUT; - } - - return retval; -} - -/** - * @brief 停止指定xhci控制器的legacy support - * - * @param id 控制器id - * @return int - */ -static int xhci_hc_stop_legacy(int id) -{ - uint64_t current_offset = xhci_hc[id].ext_caps_off; - - do - { - // 判断当前entry是否为legacy support entry - if ((xhci_read_cap_reg32(id, current_offset) & 0xff) == XHCI_XECP_ID_LEGACY) - { - io_mfence(); - // 接管控制权 - xhci_write_cap_reg32(id, current_offset, - xhci_read_cap_reg32(id, current_offset) | XHCI_XECP_LEGACY_OS_OWNED); - io_mfence(); - // 等待响应完成 - int timeout = XHCI_XECP_LEGACY_TIMEOUT; - while ((xhci_read_cap_reg32(id, current_offset) & XHCI_XECP_LEGACY_OWNING_MASK) != - XHCI_XECP_LEGACY_OS_OWNED) - { - io_mfence(); - rs_usleep(1000); - if (--timeout == 0) - { - kerror("The BIOS doesn't stop legacy support."); - return -ETIMEDOUT; - } - } - // 处理完成 - return 0; - } - io_mfence(); - // 读取下一个entry的偏移增加量 - int next_off = ((xhci_read_cap_reg32(id, current_offset) & 0xff00) >> 8) << 2; - io_mfence(); - // 将指针跳转到下一个entry - current_offset = next_off ? (current_offset + next_off) : 0; - } while (current_offset); - - // 当前controller不存在legacy支持,也问题不大,不影响 - return 0; -} - -/** - * @brief 启用指定xhci控制器的调度 - * - * @param id 控制器id - * @return int - */ -static int xhci_hc_start_sched(int id) -{ - io_mfence(); - xhci_write_op_reg32(id, XHCI_OPS_USBCMD, (1 << 0) | (1 << 2) | (1 << 3)); - io_mfence(); - rs_usleep(100 * 1000); -} - -/** - * @brief 停止指定xhci控制器的调度 - * - * @param id 控制器id - * @return int - */ -static int xhci_hc_stop_sched(int id) -{ - io_mfence(); - xhci_write_op_reg32(id, XHCI_OPS_USBCMD, 0x00); - io_mfence(); -} - -/** - * @brief 在Ex capability list中寻找符合指定的协议号的寄存器offset、count、flag信息 - * - * @param id 主机控制器id - * @param list_off 列表项位置距离控制器虚拟基地址的偏移量 - * @param version 要寻找的端口版本号(2或3) - * @param offset 返回的 Compatible Port Offset - * @param count 返回的 Compatible Port Count - * @param protocol_flag 返回的与协议相关的flag - * @return uint32_t 下一个列表项的偏移量 - */ -static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int version, uint32_t *offset, - uint32_t *count, uint16_t *protocol_flag) -{ - if (count) - *count = 0; - - do - { - uint32_t dw0 = xhci_read_cap_reg32(id, list_off); - io_mfence(); - uint32_t next_list_off = (dw0 >> 8) & 0xff; - next_list_off = next_list_off ? (list_off + (next_list_off << 2)) : 0; - - if ((dw0 & 0xff) == XHCI_XECP_ID_PROTOCOL && ((dw0 & 0xff000000) >> 24) == version) - { - uint32_t dw2 = xhci_read_cap_reg32(id, list_off + 8); - io_mfence(); - if (offset != NULL) - *offset = (uint32_t)(dw2 & 0xff) - 1; // 使其转换为zero based - if (count != NULL) - *count = (uint32_t)((dw2 & 0xff00) >> 8); - if (protocol_flag != NULL && version == 2) - *protocol_flag = (uint16_t)((dw2 >> 16) & 0x0fff); - - return next_list_off; - } - - list_off = next_list_off; - } while (list_off); - - return 0; -} -/** - * @brief 配对xhci主机控制器的usb2、usb3端口 - * - * @param id 主机控制器id - * @return int 返回码 - */ -static int xhci_hc_pair_ports(int id) -{ - - struct xhci_caps_HCSPARAMS1_reg_t hcs1; - io_mfence(); - memcpy(&hcs1, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCSPARAMS1_reg_t)); - io_mfence(); - // 从hcs1获取端口数量 - xhci_hc[id].port_num = hcs1.max_ports; - - // 找到所有的端口并标记其端口信息 - - xhci_hc[id].port_num_u2 = 0; - xhci_hc[id].port_num_u3 = 0; - - uint32_t next_off = xhci_hc[id].ext_caps_off; - uint32_t offset, cnt; - uint16_t protocol_flags = 0; - - // 寻找所有的usb2端口 - while (next_off) - { - io_mfence(); - next_off = xhci_hc_get_protocol_offset(id, next_off, 2, &offset, &cnt, &protocol_flags); - io_mfence(); - - if (cnt) - { - for (int i = 0; i < cnt; ++i) - { - io_mfence(); - xhci_hc[id].ports[offset + i].offset = xhci_hc[id].port_num_u2++; - xhci_hc[id].ports[offset + i].flags = XHCI_PROTOCOL_USB2; - io_mfence(); - // usb2 high speed only - if (protocol_flags & 2) - xhci_hc[id].ports[offset + i].flags |= XHCI_PROTOCOL_HSO; - } - } - } - - // 寻找所有的usb3端口 - next_off = xhci_hc[id].ext_caps_off; - while (next_off) - { - io_mfence(); - next_off = xhci_hc_get_protocol_offset(id, next_off, 3, &offset, &cnt, &protocol_flags); - io_mfence(); - - if (cnt) - { - for (int i = 0; i < cnt; ++i) - { - io_mfence(); - xhci_hc[id].ports[offset + i].offset = xhci_hc[id].port_num_u3++; - xhci_hc[id].ports[offset + i].flags = XHCI_PROTOCOL_USB3; - } - } - } - - // 将对应的USB2端口和USB3端口进行配对 - for (int i = 0; i < xhci_hc[id].port_num; ++i) - { - for (int j = 0; j < xhci_hc[id].port_num; ++j) - { - if (unlikely(i == j)) - continue; - io_mfence(); - if ((xhci_hc[id].ports[i].offset == xhci_hc[id].ports[j].offset) && - ((xhci_hc[id].ports[i].flags & XHCI_PROTOCOL_INFO) != - (xhci_hc[id].ports[j].flags & XHCI_PROTOCOL_INFO))) - { - xhci_hc[id].ports[i].paired_port_num = j; - xhci_hc[id].ports[i].flags |= XHCI_PROTOCOL_HAS_PAIR; - io_mfence(); - xhci_hc[id].ports[j].paired_port_num = i; - xhci_hc[id].ports[j].flags |= XHCI_PROTOCOL_HAS_PAIR; - } - } - } - - // 标记所有的usb3、单独的usb2端口为激活状态 - for (int i = 0; i < xhci_hc[id].port_num; ++i) - { - io_mfence(); - if (XHCI_PORT_IS_USB3(id, i) || (XHCI_PORT_IS_USB2(id, i) && (!XHCI_PORT_HAS_PAIR(id, i)))) - xhci_hc[id].ports[i].flags |= XHCI_PROTOCOL_ACTIVE; - } - kinfo("Found %d ports on root hub, usb2 ports:%d, usb3 ports:%d", xhci_hc[id].port_num, xhci_hc[id].port_num_u2, - xhci_hc[id].port_num_u3); - - /* - // 打印配对结果 - for (int i = 1; i <= xhci_hc[id].port_num; ++i) - { - if (XHCI_PORT_IS_USB3(id, i)) - { - kdebug("USB3 port %d, offset=%d, pair with usb2 port %d, current port is %s", i, - xhci_hc[id].ports[i].offset, xhci_hc[id].ports[i].paired_port_num, XHCI_PORT_IS_ACTIVE(id, i) ? "active" : - "inactive"); - } - else if (XHCI_PORT_IS_USB2(id, i) && (!XHCI_PORT_HAS_PAIR(id, i))) // 单独的2.0接口 - { - kdebug("Stand alone USB2 port %d, offset=%d, current port is %s", i, xhci_hc[id].ports[i].offset, - XHCI_PORT_IS_ACTIVE(id, i) ? "active" : "inactive"); - } - else if (XHCI_PORT_IS_USB2(id, i)) - { - kdebug("USB2 port %d, offset=%d, current port is %s, has pair=%s", i, xhci_hc[id].ports[i].offset, - XHCI_PORT_IS_ACTIVE(id, i) ? "active" : "inactive", XHCI_PORT_HAS_PAIR(id, i) ? "true" : "false"); - } - } - */ - - return 0; -} - -/** - * @brief 创建ring,并将最后一个trb指向头一个trb - * - * @param trbs 要创建的trb数量 - * @return uint64_t trb数组的起始虚拟地址 - */ -static uint64_t xhci_create_ring(int trbs) -{ - int total_size = trbs * sizeof(struct xhci_TRB_t); - const uint64_t vaddr = (uint64_t)kmalloc(total_size, 0); - io_mfence(); - memset((void *)vaddr, 0, total_size); - io_mfence(); - // 设置最后一个trb为link trb - xhci_TRB_set_link_cmd(vaddr + total_size - sizeof(struct xhci_TRB_t)); - io_mfence(); - return vaddr; -} - -/** - * @brief 创建新的event ring table和对应的ring segment - * - * @param trbs 包含的trb的数量 - * @param ret_ring_addr 返回的第一个event ring segment的基地址(虚拟) - * @return uint64_t trb table的虚拟地址 - */ -static uint64_t xhci_create_event_ring(int trbs, uint64_t *ret_ring_addr) -{ - const uint64_t table_vaddr = (const uint64_t)kmalloc(64, 0); // table支持8个segment - io_mfence(); - if (unlikely(table_vaddr == NULL)) - return -ENOMEM; - memset((void *)table_vaddr, 0, 64); - - // 暂时只创建1个segment - const uint64_t seg_vaddr = (const uint64_t)kmalloc(trbs * sizeof(struct xhci_TRB_t), 0); - io_mfence(); - if (unlikely(seg_vaddr == NULL)) - return -ENOMEM; - - memset((void *)seg_vaddr, 0, trbs * sizeof(struct xhci_TRB_t)); - io_mfence(); - // 将segment地址和大小写入table - *(uint64_t *)(table_vaddr) = virt_2_phys(seg_vaddr); - *(uint64_t *)(table_vaddr + 8) = trbs; - - *ret_ring_addr = seg_vaddr; - return table_vaddr; -} - -void xhci_hc_irq_enable(uint64_t irq_num) -{ - int cid = xhci_find_hcid_by_irq_num(irq_num); - io_mfence(); - if (WARN_ON(cid == -1)) - return; - - io_mfence(); - pci_start_msi(xhci_hc[cid].pci_dev_hdr); - - io_mfence(); - xhci_hc_start_sched(cid); - io_mfence(); - xhci_hc_start_ports(cid); -} - -void xhci_hc_irq_disable(uint64_t irq_num) -{ - int cid = xhci_find_hcid_by_irq_num(irq_num); - io_mfence(); - if (WARN_ON(cid == -1)) - return; - - xhci_hc_stop_sched(cid); - io_mfence(); - pci_disable_msi(xhci_hc[cid].pci_dev_hdr); - io_mfence(); -} - -/** - * @brief xhci中断的安装函数 - * - * @param irq_num 要安装的中断向量号 - * @param arg 参数 - * @return uint64_t 错误码 - */ -uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg) -{ - int cid = xhci_find_hcid_by_irq_num(irq_num); - io_mfence(); - if (WARN_ON(cid == -1)) - return -EINVAL; - - struct xhci_hc_irq_install_info_t *info = (struct xhci_hc_irq_install_info_t *)arg; - struct msi_desc_t msi_desc; - memset(&msi_desc, 0, sizeof(struct msi_desc_t)); - io_mfence(); - msi_desc.irq_num = irq_num; - msi_desc.msi_index = 0; - msi_desc.pci_dev = (struct pci_device_structure_header_t *)xhci_hc[cid].pci_dev_hdr; - msi_desc.assert = info->assert; - msi_desc.edge_trigger = info->edge_trigger; - msi_desc.processor = info->processor; - msi_desc.pci.msi_attribute.is_64 = 1; - msi_desc.pci.msi_attribute.is_msix = 1; - io_mfence(); - // 因pci_enable_msi不再单独映射MSIX表,所以需要对pci设备的bar进行映射 - - int retval = pci_enable_msi(&msi_desc); - - return 0; -} - -void xhci_hc_irq_uninstall(uint64_t irq_num) -{ - // todo - int cid = xhci_find_hcid_by_irq_num(irq_num); - io_mfence(); - if (WARN_ON(cid == -1)) - return; - xhci_hc_stop(cid); - io_mfence(); -} -/** - * @brief xhci主机控制器的中断处理函数 - * - * @param irq_num 中断向量号 - * @param cid 控制器号 - * @param regs 寄存器值 - */ -void xhci_hc_irq_handler(uint64_t irq_num, uint64_t cid, struct pt_regs *regs) -{ - // kdebug("USB irq received."); - /* - 写入usb status寄存器,以表明当前收到了中断,清除usb status寄存器中的EINT位 - 需要先清除这个位,再清除interrupter中的pending bit) - */ - xhci_write_op_reg32(cid, XHCI_OPS_USBSTS, xhci_read_op_reg32(cid, XHCI_OPS_USBSTS)); - - // 读取第0个usb interrupter的intr management寄存器 - const uint32_t iman0 = xhci_read_intr_reg32(cid, 0, XHCI_IR_MAN); - uint64_t dequeue_reg = xhci_read_intr_reg64(cid, 0, XHCI_IR_DEQUEUE); - - if (((iman0 & 3) == 3) || (dequeue_reg & 8)) // 中断被启用,且pending不为0 - { - // kdebug("to handle"); - // 写入1以清除该interrupter的pending bit - xhci_write_intr_reg32(cid, 0, XHCI_IR_MAN, iman0 | 3); - io_mfence(); - struct xhci_TRB_t event_trb, origin_trb; // event ring trb以及其对应的command trb - uint64_t origin_vaddr; - // 暂存当前trb的起始地址 - uint64_t last_event_ring_vaddr = xhci_hc[cid].current_event_ring_vaddr; - xhci_get_trb(&event_trb, xhci_hc[cid].current_event_ring_vaddr); - - { - struct xhci_TRB_cmd_complete_t *event_trb_ptr = (struct xhci_TRB_cmd_complete_t *)&event_trb; - // kdebug("TRB_type=%d, comp_code=%d", event_trb_ptr->TRB_type, event_trb_ptr->code); - } - while ((event_trb.command & 1) == xhci_hc[cid].current_event_ring_cycle) // 循环处理处于当前周期的所有event ring - { - - struct xhci_TRB_cmd_complete_t *event_trb_ptr = (struct xhci_TRB_cmd_complete_t *)&event_trb; - // kdebug("TRB_type=%d, comp_code=%d", event_trb_ptr->TRB_type, event_trb_ptr->code); - if ((event_trb.command & (1 << 2)) == 0) // 当前event trb不是由于short packet产生的 - { - // kdebug("event_trb_ptr->code=%d", event_trb_ptr->code); - // kdebug("event_trb_ptr->TRB_type=%d", event_trb_ptr->TRB_type); - switch (event_trb_ptr->code) // 判断它的完成码 - { - case TRB_COMP_TRB_SUCCESS: // trb执行成功,则将结果返回到对应的command ring的trb里面 - - switch (event_trb_ptr->TRB_type) // 根据event trb类型的不同,采取不同的措施 - { - case TRB_TYPE_COMMAND_COMPLETION: // 命令已经完成 - origin_vaddr = (uint64_t)phys_2_virt(event_trb.param); - // 获取对应的command trb - xhci_get_trb(&origin_trb, origin_vaddr); - - switch (((struct xhci_TRB_normal_t *)&origin_trb)->TRB_type) - { - case TRB_TYPE_ENABLE_SLOT: // 源命令为enable slot - // 将slot id返回到命令TRB的command字段中 - origin_trb.command &= 0x00ffffff; - origin_trb.command |= (event_trb.command & 0xff000000); - origin_trb.status = event_trb.status; - break; - default: - origin_trb.status = event_trb.status; - break; - } - - // 标记该命令已经执行完成 - origin_trb.status |= XHCI_IRQ_DONE; - // 将command trb写入到表中 - xhci_set_trb(&origin_trb, origin_vaddr); - // kdebug("set origin:%#018lx", origin_vaddr); - break; - } - break; - - default: - break; - } - } - else // 当前TRB是由short packet产生的 - { - switch (event_trb_ptr->TRB_type) - { - case TRB_TYPE_TRANS_EVENT: // 当前 event trb是 transfer event TRB - // If SPD was encountered in this TD, comp_code will be SPD, else it should be SUCCESS - // (specs 4.10.1.1) - __write4b((uint64_t)phys_2_virt(event_trb.param), - (event_trb.status | XHCI_IRQ_DONE)); // return code + bytes *not* transferred - break; - - default: - break; - } - } - - // 获取下一个event ring TRB - last_event_ring_vaddr = xhci_hc[cid].current_event_ring_vaddr; - xhci_hc[cid].current_event_ring_vaddr += sizeof(struct xhci_TRB_t); - xhci_get_trb(&event_trb, xhci_hc[cid].current_event_ring_vaddr); - if (((struct xhci_TRB_normal_t *)&event_trb)->TRB_type == TRB_TYPE_LINK) - { - xhci_hc[cid].current_event_ring_vaddr = xhci_hc[cid].event_ring_vaddr; - xhci_get_trb(&event_trb, xhci_hc[cid].current_event_ring_vaddr); - } - } - - // 当前event ring cycle的TRB处理结束 - // 更新dequeue指针, 并清除event handler busy标志位 - xhci_write_intr_reg64(cid, 0, XHCI_IR_DEQUEUE, virt_2_phys(last_event_ring_vaddr) | (1 << 3)); - io_mfence(); - } -} -/** - * @brief 重置端口 - * - * @param id 控制器id - * @param port 端口id - * @return int - */ -static int xhci_reset_port(const int id, const int port) -{ - int retval = 0; - // 相对于op寄存器基地址的偏移量 - uint64_t port_status_offset = XHCI_OPS_PRS + port * 16; - - io_mfence(); - // 检查端口电源状态 - if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0) - { - kdebug("port is power off, starting..."); - io_mfence(); - xhci_write_cap_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9)); - io_mfence(); - rs_usleep(2000); - // 检测端口是否被启用, 若未启用,则报错 - if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0) - { - kdebug("cannot power on %d", port); - return -EAGAIN; - } - } - // kdebug("port:%d, power check ok", port); - io_mfence(); - // 确保端口的status被清0 - xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | XHCI_PORTUSB_CHANGE_BITS); - // kdebug("to reset timeout;"); - io_mfence(); - // 重置当前端口 - if (XHCI_PORT_IS_USB3(id, port)) - xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | (1U << 31)); - else - xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | (1 << 4)); - - retval = -ETIMEDOUT; - // kdebug("to wait reset timeout;"); - // 等待portsc的port reset change位被置位,说明reset完成 - int timeout = 100; - while (timeout) - { - io_mfence(); - uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC); - io_mfence(); - if (val & (1 << 21)) - break; - // QEMU对usb的模拟有bug,因此需要检测这里 -#ifdef __QEMU_EMULATION__ - - if (XHCI_PORT_IS_USB3(id, port) && (val & (1U << 31)) == 0) - break; - else if (XHCI_PORT_IS_USB2(id, port) && (val & (1 << 4)) == 0) - break; -#endif - --timeout; - rs_usleep(500); - } - // kdebug("timeout= %d", timeout); - - if (timeout > 0) - { - // 等待恢复 - rs_usleep(USB_TIME_RST_REC * 100); - uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC); - io_mfence(); - - // kdebug("to check if reset ok, val=%#010lx", val); - - // 如果reset之后,enable bit仍然是1,那么说明reset成功 - if (val & (1 << 1)) - { - // kdebug("reset ok"); - retval = 0; - io_mfence(); - // 清除status change bit - xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | XHCI_PORTUSB_CHANGE_BITS); - io_mfence(); - } - else - retval = -1; - } - // kdebug("reset ok!"); - // 如果usb2端口成功reset,则处理该端口的active状态 - if (retval == 0 && XHCI_PORT_IS_USB2(id, port)) - { - xhci_hc[id].ports[port].flags |= XHCI_PROTOCOL_ACTIVE; - if (XHCI_PORT_HAS_PAIR(id, port)) // 如果有对应的usb3端口,则将usb3端口设置为未激活 - xhci_hc[id].ports[xhci_hc[id].ports[port].paired_port_num].flags &= ~(XHCI_PROTOCOL_ACTIVE); - } - - // 如果usb3端口reset失败,则启用与之配对的usb2端口 - if (retval != 0 && XHCI_PORT_IS_USB3(id, port)) - { - xhci_hc[id].ports[port].flags &= ~XHCI_PROTOCOL_ACTIVE; - xhci_hc[id].ports[xhci_hc[id].ports[port].paired_port_num].flags |= XHCI_PROTOCOL_ACTIVE; - } - - return retval; -} - -/** - * @brief 初始化设备slot的上下文,并将其写入dcbaap中的上下文index数组 - * - at this time, we don't know if the device is a hub or not, so we don't - * set the slot->hub, ->mtt, ->ttt, ->etc, items. - * - * @param id 控制器id - * @param port 端口号 - * @param speed 端口速度 - * @param max_packet 最大数据包大小 - * @return uint64_t 初始化好的设备上下文空间的虚拟地址 - */ -static uint64_t xhci_initialize_slot(const int id, const int port, const int speed, const int max_packet) -{ - // 为所有的endpoint分配上下文空间 - // todo: 按需分配上下文空间 - uint64_t device_context_vaddr = (uint64_t)kzalloc(xhci_hc[id].context_size * 32, 0); - // kdebug("slot id=%d, device_context_vaddr=%#018lx, port=%d", slot_id, device_context_vaddr, port); - // 写到数组中 - __write8b(xhci_hc[id].dcbaap_vaddr + (xhci_hc[id].ports[port].slot_id * sizeof(uint64_t)), - virt_2_phys(device_context_vaddr)); - struct xhci_slot_context_t slot_ctx = {0}; - slot_ctx.entries = 1; - slot_ctx.speed = speed; - slot_ctx.route_string = 0; - slot_ctx.rh_port_num = port + 1; // 由于xhci控制器是1-base的,因此把驱动程序中存储的端口号加1,才是真实的端口号 - slot_ctx.max_exit_latency = 0; // 稍后会计算这个值 - slot_ctx.int_target = 0; // 当前全部使用第0个interrupter - slot_ctx.slot_state = XHCI_SLOT_STATE_DISABLED_OR_ENABLED; - slot_ctx.device_address = 0; - - // 将slot信息写入上下文空间 - __write_slot(device_context_vaddr, &slot_ctx); - - // 初始化控制端点 - xhci_initialize_ep(id, device_context_vaddr, port, XHCI_EP_CONTROL, max_packet, 0, USB_EP_CONTROL, 0, speed, 0); - - return device_context_vaddr; -} - -/** - * @brief 初始化endpoint - * - * @param id 控制器id - * @param slot_vaddr slot上下文的虚拟地址 - * @param port_id 插槽id - * @param ep_num 端点上下文在slot上下文区域内的编号 - * @param max_packet 最大数据包大小 - * @param type 端点类型 - * @param direction 传输方向 - * @param speed 传输速度 - * @param ep_interval 端点的连续请求间隔 - */ -static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const int port_id, const int ep_num, - const int max_packet, const int max_burst, const int type, const int direction, - const int speed, const int ep_interval) -{ - // 由于目前只实现获取设备的描述符,因此暂时只支持control ep - if (type != USB_EP_CONTROL && type != USB_EP_INTERRUPT) - return; - struct xhci_ep_context_t ep_ctx = {0}; - memset(&ep_ctx, 0, sizeof(struct xhci_ep_context_t)); - - xhci_hc[id].ports[port_id].ep_info[ep_num].ep_ring_vbase = xhci_create_ring(XHCI_TRBS_PER_RING); - // 申请ep的 transfer ring - ep_ctx.tr_dequeue_ptr = virt_2_phys(xhci_hc[id].ports[port_id].ep_info[ep_num].ep_ring_vbase); - xhci_ep_set_dequeue_cycle_state(&ep_ctx, XHCI_TRB_CYCLE_ON); - - xhci_hc[id].ports[port_id].ep_info[ep_num].current_ep_ring_vaddr = - xhci_hc[id].ports[port_id].ep_info[ep_num].ep_ring_vbase; - xhci_hc[id].ports[port_id].ep_info[ep_num].current_ep_ring_cycle = xhci_ep_get_dequeue_cycle_state(&ep_ctx); - // kdebug("ep_ctx.tr_dequeue_ptr = %#018lx", ep_ctx.tr_dequeue_ptr); - // kdebug("xhci_hc[id].control_ep_info.current_ep_ring_cycle = %d", - // xhci_hc[id].control_ep_info.current_ep_ring_cycle); - kdebug("max_packet=%d, max_burst=%d", max_packet, max_burst); - switch (type) - { - case USB_EP_CONTROL: // Control ep - // 设置初始值 - ep_ctx.max_packet_size = max_packet; - ep_ctx.linear_stream_array = 0; - ep_ctx.max_primary_streams = 0; - ep_ctx.mult = 0; - ep_ctx.ep_state = XHCI_EP_STATE_DISABLED; - ep_ctx.hid = 0; - ep_ctx.ep_type = XHCI_EP_TYPE_CONTROL; - ep_ctx.average_trb_len = 8; // 所有的control ep的该值均为8 - ep_ctx.err_cnt = 3; - ep_ctx.max_burst_size = max_burst; - ep_ctx.interval = ep_interval; - - break; - case USB_EP_INTERRUPT: - ep_ctx.max_packet_size = max_packet & 0x7ff; - ep_ctx.max_burst_size = max_burst; - ep_ctx.ep_state = XHCI_EP_STATE_DISABLED; - ep_ctx.mult = 0; - ep_ctx.err_cnt = 3; - ep_ctx.max_esti_payload_hi = ((max_packet * (max_burst + 1)) >> 8) & 0xff; - ep_ctx.max_esti_payload_lo = ((max_packet * (max_burst + 1))) & 0xff; - ep_ctx.interval = ep_interval; - ep_ctx.average_trb_len = 8; // todo: It's not sure how much to fill in this value - // ep_ctx.ep_type = XHCI_EP_TYPE_INTR_IN; - ep_ctx.ep_type = ((ep_num % 2) ? XHCI_EP_TYPE_INTR_IN : XHCI_EP_TYPE_INTR_OUT); - - break; - default: - break; - } - - // 将ep的信息写入到slot上下文中对应的ep的块中 - __write_ep(id, slot_vaddr, ep_num, &ep_ctx); -} - -/** - * @brief 向usb控制器发送 address_device命令 - * - * @param id 主机控制器id - * @param slot_vaddr 插槽上下文的虚拟基地址 - * @param slot_id 插槽id - * @param block 是否阻断 set address 信息向usb设备的传输 - * @return int 错误码 - */ -static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int slot_id, const bool block) -{ - int retval = 0; - struct xhci_slot_context_t slot; - struct xhci_ep_context_t ep; - // 创建输入上下文缓冲区 - uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 33, 0); - - // 置位input control context和slot context的add bit - __write4b(input_ctx_buffer + 4, 0x3); - - // 拷贝slot上下文和control ep上下文到输入上下文中 - - // __write_ep(id, input_ctx_buffer, 2, &ep_ctx); - __read_from_slot(&slot, slot_vaddr); - __read_from_ep(id, slot_vaddr, 1, &ep); - ep.err_cnt = 3; - kdebug("slot.slot_state=%d, speed=%d, root hub port num=%d", slot.slot_state, slot.speed, slot.rh_port_num); - kdebug("ep.type=%d, max_packet=%d, dequeue_ptr=%#018lx", ep.ep_type, ep.max_packet_size, ep.tr_dequeue_ptr); - - __write_slot(input_ctx_buffer + xhci_hc[id].context_size, &slot); - __write_ep(id, input_ctx_buffer, 2, &ep); - - struct xhci_TRB_normal_t trb = {0}; - trb.buf_paddr = virt_2_phys(input_ctx_buffer); - trb.bei = (block ? 1 : 0); - trb.TRB_type = TRB_TYPE_ADDRESS_DEVICE; - trb.intr_target = 0; - trb.cycle = xhci_hc[id].cmd_trb_cycle; - trb.Reserved |= ((slot_id << 8) & 0xffff); - - retval = xhci_send_command(id, (struct xhci_TRB_t *)&trb, true); - if (unlikely(retval != 0)) - { - kerror("slotid:%d, address device failed", slot_id); - goto failed; - } - - struct xhci_TRB_cmd_complete_t *trb_done = (struct xhci_TRB_cmd_complete_t *)&trb; - if (trb_done->code == TRB_COMP_TRB_SUCCESS) // 成功执行 - { - // 如果要从控制器获取刚刚设置的设备地址的话,可以在这里读取slot context - ksuccess("slot %d successfully addressed.", slot_id); - - retval = 0; - } - else - retval = -EAGAIN; -done:; -failed:; - kfree((void *)input_ctx_buffer); - return retval; -} - -/** - * @brief 在指定的端点的ring中,写入一个setup stage TRB - * - * @param ep 端点信息结构体 - * @param packet usb请求包 - * @param direction 传输的方向 - * @return int 产生的TRB数量 - */ -static int xhci_setup_stage(struct xhci_ep_info_t *ep, const struct usb_request_packet_t *packet, - const uint8_t direction) -{ - // kdebug("ep->current_ep_ring_cycle=%d", ep->current_ep_ring_cycle); - struct xhci_TRB_setup_stage_t trb = {0}; - trb.bmRequestType = packet->request_type; - trb.bRequest = packet->request; - trb.wValue = packet->value; - trb.wIndex = packet->index; - trb.wLength = packet->length; - trb.transfer_legth = 8; - trb.intr_target = 0; // 使用第0个interrupter - trb.cycle = ep->current_ep_ring_cycle; - trb.ioc = 0; - trb.idt = 1; - trb.TRB_type = TRB_TYPE_SETUP_STAGE; - trb.trt = direction; - - // 将setup stage trb拷贝到ep的transfer ring中 - __xhci_write_trb(ep, (struct xhci_TRB_t *)&trb); - return 1; -} - -/** - * @brief 向指定的端点中写入data stage trb - * - * @param ep 端点信息结构体 - * @param buf_vaddr 数据缓冲区虚拟地址 - * @param trb_type trb类型 - * @param size 要传输的数据大小 - * @param direction 传输方向 - * @param max_packet 最大请求包大小 - * @param status_vaddr event data TRB的缓冲区(4字节,且地址按照16字节对齐) - * @return int 产生的TRB数量 - */ -static int xhci_data_stage(struct xhci_ep_info_t *ep, uint64_t buf_vaddr, uint8_t trb_type, const uint32_t size, - uint8_t direction, const int max_packet, const uint64_t status_vaddr) -{ - if (size == 0) - return 0; - int64_t remain_bytes = size; - uint32_t remain_packets = (size + max_packet - 1) / max_packet; - struct xhci_TRB_data_stage_t trb = {0}; - int count_packets = 0; - // 分多个trb来执行 - while (remain_bytes > 0) - { - --remain_packets; - - trb.buf_paddr = virt_2_phys(buf_vaddr); - trb.intr_target = 0; - trb.TD_size = remain_packets; - trb.transfer_length = (remain_bytes < max_packet ? size : max_packet); - trb.dir = direction; - trb.TRB_type = trb_type; - trb.chain = 1; - trb.ent = (remain_packets == 0); - trb.cycle = ep->current_ep_ring_cycle; - trb.ioc = 0; - - // 将data stage trb拷贝到ep的transfer ring中 - __xhci_write_trb(ep, (struct xhci_TRB_t *)&trb); - - buf_vaddr += max_packet; - remain_bytes -= max_packet; - ++count_packets; - - // 对于data stage trb而言,除了第一个trb以外,剩下的trb都是NORMAL的,并且dir是无用的 - trb_type = TRB_TYPE_NORMAL; - direction = 0; - } - - // 写入data event trb, 待完成后,完成信息将会存到status_vaddr指向的地址中 - memset(&trb, 0, sizeof(struct xhci_TRB_data_stage_t *)); - trb.buf_paddr = virt_2_phys(status_vaddr); - trb.intr_target = 0; - trb.cycle = ep->current_ep_ring_cycle; - trb.ioc = 1; - trb.TRB_type = TRB_TYPE_EVENT_DATA; - __xhci_write_trb(ep, (struct xhci_TRB_t *)&trb); - - return count_packets + 1; -} - -/** - * @brief 填写xhci status stage TRB到control ep的transfer ring - * - * @param ep 端点信息结构体 - * @param direction 方向:(h2d:0, d2h:1) - * @param status_buf_vaddr - * @return int 创建的TRB数量 - */ -static int xhci_status_stage(struct xhci_ep_info_t *ep, uint8_t direction, uint64_t status_buf_vaddr) -{ - // kdebug("write status stage trb"); - - { - struct xhci_TRB_status_stage_t trb = {0}; - - // 写入status stage trb - trb.intr_target = 0; - trb.cycle = ep->current_ep_ring_cycle; - trb.ent = 0; - trb.ioc = 1; - trb.TRB_type = TRB_TYPE_STATUS_STAGE; - trb.dir = direction; - __xhci_write_trb(ep, (struct xhci_TRB_t *)&trb); - } - - { - // 写入event data TRB - struct xhci_TRB_data_stage_t trb = {0}; - trb.buf_paddr = virt_2_phys(status_buf_vaddr); - trb.intr_target = 0; - trb.TRB_type = TRB_TYPE_EVENT_DATA; - trb.ioc = 1; - - trb.cycle = ep->current_ep_ring_cycle; - - __xhci_write_trb(ep, (struct xhci_TRB_t *)&trb); - } - - return 2; -} - -/** - * @brief 等待状态数据被拷贝到status缓冲区中 - * - * @param id 主机控制器id - * @param status_vaddr status 缓冲区 - * @return int 错误码 - */ -static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr) -{ - int timer = 500; - while (timer) - { - if (__read4b(status_vaddr) & XHCI_IRQ_DONE) - { - uint32_t status = __read4b(status_vaddr); - // 判断完成码 - switch (xhci_get_comp_code(status)) - { - case TRB_COMP_TRB_SUCCESS: - case TRB_COMP_SHORT_PACKET: - return 0; - break; - case TRB_COMP_STALL_ERROR: - case TRB_COMP_DATA_BUFFER_ERROR: - case TRB_COMP_BABBLE_DETECTION: - return -EINVAL; - default: - kerror("xhci wait interrupt: status=%#010x, complete_code=%d", status, xhci_get_comp_code(status)); - return -EIO; - } - } - --timer; - rs_usleep(1000); - } - - kerror(" USB xHCI Interrupt wait timed out."); - return -ETIMEDOUT; -} - -/** - * @brief 从指定插槽的control endpoint读取信息 - * - * @param id 主机控制器id - * @param packet usb数据包 - * @param target 读取到的信息存放到的位置 - * @param port_id 端口id - * @param max_packet 最大数据包大小 - * @return int 读取到的数据的大小 - */ -static int xhci_control_in(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, - const int max_packet) -{ - - uint64_t status_buf_vaddr = - (uint64_t)kzalloc(16, 0); // 本来是要申请4bytes的buffer的,但是因为xhci控制器需要16bytes对齐,因此申请16bytes - uint64_t data_buf_vaddr = 0; - int retval = 0; - - // 往control ep写入一个setup stage trb - xhci_setup_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], packet, XHCI_DIR_IN); - if (packet->length) - { - data_buf_vaddr = (uint64_t)kzalloc(packet->length, 0); - xhci_data_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], data_buf_vaddr, TRB_TYPE_DATA_STAGE, - packet->length, XHCI_DIR_IN_BIT, max_packet, status_buf_vaddr); - } - -/* - QEMU doesn't quite handle SETUP/DATA/STATUS transactions correctly. - It will wait for the STATUS TRB before it completes the transfer. - Technically, you need to check for a good transfer before you send the - STATUS TRB. However, since QEMU doesn't update the status until after - the STATUS TRB, waiting here will not complete a successful transfer. - Bochs and real hardware handles this correctly, however QEMU does not. - If you are using QEMU, do not ring the doorbell here. Ring the doorbell - *after* you place the STATUS TRB on the ring. - (See bug report: https://bugs.launchpad.net/qemu/+bug/1859378 ) -*/ -#ifndef __QEMU_EMULATION__ - // 如果不是qemu虚拟机,则可以直接发起传输 - // kdebug(" not qemu"); - __xhci_write_doorbell(id, xhci_hc[id].ports[port_id].slot_id, XHCI_EP_CONTROL); - retval = xhci_wait_for_interrupt(id, status_buf_vaddr); - if (unlikely(retval != 0)) - goto failed; -#endif - memset((void *)status_buf_vaddr, 0, 16); - xhci_status_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], XHCI_DIR_OUT_BIT, status_buf_vaddr); - - __xhci_write_doorbell(id, xhci_hc[id].ports[port_id].slot_id, XHCI_EP_CONTROL); - - retval = xhci_wait_for_interrupt(id, status_buf_vaddr); - - if (unlikely(retval != 0)) - goto failed; - - // 将读取到的数据拷贝到目标区域 - if (packet->length) - memcpy(target, (void *)data_buf_vaddr, packet->length); - retval = packet->length; - goto done; - -failed:; - kdebug("wait 4 interrupt failed"); - retval = 0; -done:; - // 释放内存 - kfree((void *)status_buf_vaddr); - if (packet->length) - kfree((void *)data_buf_vaddr); - return retval; -} - -/** - * @brief 向指定插槽的control ep输出信息 - * - * @param id 主机控制器id - * @param packet usb数据包 - * @param target 返回的数据存放的位置 - * @param port_id 端口id - * @param max_packet 最大数据包大小 - * @return int 读取到的数据的大小 - */ -static int xhci_control_out(const int id, struct usb_request_packet_t *packet, void *target, const int port_id, - const int max_packet) -{ - uint64_t status_buf_vaddr = (uint64_t)kzalloc(16, 0); - uint64_t data_buf_vaddr = 0; - int retval = 0; - - // 往control ep写入一个setup stage trb - xhci_setup_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], packet, XHCI_DIR_OUT); - - if (packet->length) - { - data_buf_vaddr = (uint64_t)kzalloc(packet->length, 0); - xhci_data_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], data_buf_vaddr, TRB_TYPE_DATA_STAGE, - packet->length, XHCI_DIR_OUT_BIT, max_packet, status_buf_vaddr); - } - -#ifndef __QEMU_EMULATION__ - // 如果不是qemu虚拟机,则可以直接发起传输 - __xhci_write_doorbell(id, xhci_hc[id].ports[port_id].slot_id, XHCI_EP_CONTROL); - retval = xhci_wait_for_interrupt(id, status_buf_vaddr); - if (unlikely(retval != 0)) - goto failed; -#endif - - memset((void *)status_buf_vaddr, 0, 16); - xhci_status_stage(&xhci_hc[id].ports[port_id].ep_info[XHCI_EP_CONTROL], XHCI_DIR_IN_BIT, status_buf_vaddr); - - __xhci_write_doorbell(id, xhci_hc[id].ports[port_id].slot_id, XHCI_EP_CONTROL); -#ifndef __QEMU_EMULATION__ - // qemu对于这个操作的处理有问题,status_buf并不会被修改。而真机不存在该问题 - retval = xhci_wait_for_interrupt(id, status_buf_vaddr); -#endif - - if (unlikely(retval != 0)) - goto failed; - - // 将读取到的数据拷贝到目标区域 - if (packet->length) - memcpy(target, (void *)data_buf_vaddr, packet->length); - retval = packet->length; - goto done; -failed:; - kdebug("wait 4 interrupt failed"); - retval = 0; -done:; - // 释放内存 - kfree((void *)status_buf_vaddr); - if (packet->length) - kfree((void *)data_buf_vaddr); - return retval; -} - -/** - * @brief 获取描述符 - * - * @param id 控制器号 - * @param port_id 端口号 - * @param target 获取到的数据要拷贝到的地址 - * @param desc_type 描述符类型 - * @param desc_index 描述符的索引号 - * @param lang_id 语言id(默认为0) - * @param length 要传输的数据长度 - * @return int 错误码 - */ -static inline int xhci_get_desc(const int id, const int port_id, void *target, const uint16_t desc_type, - const uint8_t desc_index, const uint16_t lang_id, const uint16_t length) -{ - struct usb_device_desc *dev_desc = xhci_hc[id].ports[port_id].dev_desc; - int count; - - BUG_ON(dev_desc == NULL); - // 设备端口没有对应的描述符 - if (unlikely(dev_desc == NULL)) - return -EINVAL; - - uint8_t req_type = USB_REQ_TYPE_GET_REQUEST; - if (desc_type == USB_DT_HID_REPORT) - req_type = USB_REQ_TYPE_GET_INTERFACE_REQUEST; - - DECLARE_USB_PACKET(ctrl_in_packet, req_type, USB_REQ_GET_DESCRIPTOR, (desc_type << 8) | desc_index, lang_id, - length); - count = xhci_control_in(id, &ctrl_in_packet, target, port_id, dev_desc->max_packet_size); - if (unlikely(count == 0)) - return -EAGAIN; - return 0; -} - -static inline int xhci_set_configuration(const int id, const int port_id, const uint8_t conf_value) -{ - struct usb_device_desc *dev_desc = xhci_hc[id].ports[port_id].dev_desc; - int count; - - BUG_ON(dev_desc == NULL); - // 设备端口没有对应的描述符 - if (unlikely(dev_desc == NULL)) - return -EINVAL; - DECLARE_USB_PACKET(ctrl_out_packet, USB_REQ_TYPE_SET_REQUEST, USB_REQ_SET_CONFIGURATION, conf_value & 0xff, 0, 0); - // kdebug("set conf: to control out"); - count = xhci_control_out(id, &ctrl_out_packet, NULL, port_id, dev_desc->max_packet_size); - // kdebug("set conf: count=%d", count); - return 0; -} - -/** - * @brief 获取usb 设备的config_desc - * - * @param id 主机控制器id - * @param port_id 端口id - * @param conf_desc 要获取的conf_desc - * @return int 错误码 - */ -static int xhci_get_config_desc(const int id, const int port_id, struct usb_config_desc *conf_desc) -{ - if (unlikely(conf_desc == NULL)) - return -EINVAL; - - kdebug("to get conf for port %d", port_id); - int retval = xhci_get_desc(id, port_id, conf_desc, USB_DT_CONFIG, 0, 0, 9); - if (unlikely(retval != 0)) - return retval; - kdebug("port %d got conf ok. type=%d, len=%d, total_len=%d, num_interfaces=%d, max_power=%dmA", port_id, - conf_desc->type, conf_desc->len, conf_desc->total_len, conf_desc->num_interfaces, - (xhci_get_port_speed(id, port_id) == XHCI_PORT_SPEED_SUPER) ? (conf_desc->max_power * 8) - : (conf_desc->max_power * 2)); - return 0; -} - -/** - * @brief 获取完整的config desc(包含conf、interface、endpoint) - * - * @param id 控制器id - * @param port_id 端口id - * @param conf_desc 之前已经获取好的config_desc - * @param target 最终结果要拷贝到的地址 - * @return int 错误码 - */ -static inline int xhci_get_config_desc_full(const int id, const int port_id, const struct usb_config_desc *conf_desc, - void *target) -{ - if (unlikely(conf_desc == NULL || target == NULL)) - return -EINVAL; - - return xhci_get_desc(id, port_id, target, USB_DT_CONFIG, 0, 0, conf_desc->total_len); -} - -/** - * @brief 从完整的conf_desc数据中获取指定的interface_desc的指针 - * - * @param in_buf 存储了完整的conf_desc的缓冲区 - * @param if_num 接口号 - * @param if_desc 返回的指向接口结构体的指针 - * @return int 错误码 - */ -static int xhci_get_interface_desc(const void *in_buf, const uint8_t if_num, struct usb_interface_desc **if_desc) -{ - if (unlikely(if_desc == NULL || in_buf == NULL)) - return -EINVAL; - // 判断接口index是否合理 - if (if_num >= ((struct usb_config_desc *)in_buf)->num_interfaces) - return -EINVAL; - uint32_t total_len = ((struct usb_config_desc *)in_buf)->total_len; - uint32_t pos = 0; - while (pos < total_len) - { - struct usb_interface_desc *ptr = (struct usb_interface_desc *)(in_buf + pos); - if (ptr->type != USB_DT_INTERFACE) - { - pos += ptr->len; - continue; - } - - if (ptr->interface_number == if_num) // 找到目标interface desc - { - kdebug("get interface desc ok. interface_number=%d, num_endpoints=%d, class=%d, subclass=%d", - ptr->interface_number, ptr->num_endpoints, ptr->interface_class, ptr->interface_sub_class); - *if_desc = ptr; - return 0; - } - pos += ptr->len; - } - - return -EINVAL; -} - -/** - * @brief 获取端点描述符 - * - * @param if_desc 接口描述符 - * @param ep_num 端点号 - * @param ep_desc 返回的指向端点描述符的指针 - * @return int 错误码 - */ -static inline int xhci_get_endpoint_desc(const struct usb_interface_desc *if_desc, const uint8_t ep_num, - struct usb_endpoint_desc **ep_desc) -{ - if (unlikely(if_desc == NULL || ep_desc == NULL)) - return -EINVAL; - BUG_ON(ep_num >= if_desc->num_endpoints); - - *ep_desc = (struct usb_endpoint_desc *)((uint64_t)(if_desc + 1) + ep_num * sizeof(struct usb_endpoint_desc)); - kdebug("get endpoint desc: ep_addr=%d, max_packet=%d, attr=%#06x, interval=%d", (*ep_desc)->endpoint_addr, - (*ep_desc)->max_packet, (*ep_desc)->attributes, (*ep_desc)->interval); - return 0; -} - -/** - * @brief 初始化设备端口,并获取端口的描述信息 - * - * @param id 主机控制器id - * @param port_id 端口id - * @param dev_desc 设备描述符 - * @return int 错误码 - */ -static int xhci_get_descriptor(const int id, const int port_id, struct usb_device_desc *dev_desc) -{ - int retval = 0; - int count = 0; - if (unlikely(dev_desc == NULL)) - return -EINVAL; - // 读取端口速度。 full=1, low=2, high=3, super=4 - uint32_t speed = xhci_get_port_speed(id, port_id); - - /* - * Some devices will only send the first 8 bytes of the device descriptor - * while in the default state. We must request the first 8 bytes, then reset - * the port, set address, then request all 18 bytes. - */ - struct xhci_TRB_normal_t trb = {0}; - trb.TRB_type = TRB_TYPE_ENABLE_SLOT; - // kdebug("to enable slot"); - if (xhci_send_command(id, (struct xhci_TRB_t *)&trb, true) != 0) - { - kerror("portid:%d: send enable slot failed", port_id); - return -ETIMEDOUT; - } - // kdebug("send enable slot ok"); - - uint32_t slot_id = ((struct xhci_TRB_cmd_complete_t *)&trb)->slot_id; - int16_t max_packet; - if (slot_id != 0) // slot id不为0时,是合法的slot id - { - // 为不同速度的设备确定最大的数据包大小 - switch (speed) - { - case XHCI_PORT_SPEED_LOW: - max_packet = 8; - break; - case XHCI_PORT_SPEED_FULL: - case XHCI_PORT_SPEED_HI: - max_packet = 64; - break; - case XHCI_PORT_SPEED_SUPER: - max_packet = 512; - break; - } - } - else - return -EAGAIN; // slot id 不合法 - - xhci_hc[id].ports[port_id].slot_id = slot_id; - // kdebug("speed=%d", speed); - // 初始化接口的上下文 - uint64_t slot_vaddr = xhci_initialize_slot(id, port_id, speed, max_packet); - - retval = xhci_set_address(id, slot_vaddr, slot_id, true); - // kdebug("set addr again"); - // 再次发送 set_address命令 - // kdebug("to set addr again"); - retval = xhci_set_address(id, slot_vaddr, slot_id, false); - if (retval != 0) - return retval; - - memset(dev_desc, 0, sizeof(struct usb_device_desc)); - DECLARE_USB_PACKET(ctrl_in_packet, USB_REQ_TYPE_GET_REQUEST, USB_REQ_GET_DESCRIPTOR, (USB_DT_DEVICE << 8), 0, 18); - count = xhci_control_in(id, &ctrl_in_packet, dev_desc, port_id, max_packet); - if (unlikely(count == 0)) - return -EAGAIN; - /* - TODO: if the dev_desc->max_packet was different than what we have as max_packet, - you would need to change it here and in the slot context by doing a - evaluate_slot_context call. - */ - - xhci_hc[id].ports[port_id].dev_desc = dev_desc; - - // print the descriptor - printk(" Found USB Device:\n" - " port: %i\n" - " len: %i\n" - " type: %i\n" - " version: %01X.%02X\n" - " class: %i\n" - " subclass: %i\n" - " protocol: %i\n" - " max packet size: %i\n" - " vendor id: 0x%04X\n" - " product id: 0x%04X\n" - " release ver: %i%i.%i%i\n" - " manufacture index: %i (index to a string)\n" - " product index: %i\n" - " serial index: %i\n" - " number of configs: %i\n", - port_id, dev_desc->len, dev_desc->type, dev_desc->usb_version >> 8, dev_desc->usb_version & 0xFF, - dev_desc->_class, dev_desc->subclass, dev_desc->protocol, dev_desc->max_packet_size, dev_desc->vendor_id, - dev_desc->product_id, (dev_desc->device_rel & 0xF000) >> 12, (dev_desc->device_rel & 0x0F00) >> 8, - (dev_desc->device_rel & 0x00F0) >> 4, (dev_desc->device_rel & 0x000F) >> 0, dev_desc->manufacturer_index, - dev_desc->procuct_index, dev_desc->serial_index, dev_desc->config); - return 0; -} - -/** - * @brief 启用xhci控制器的端口 - * - * @param id 控制器id - * @return int - */ -static int xhci_hc_start_ports(int id) -{ - int cnt = 0; - // 注意,这两个循环应该不能合并到一起,因为可能存在usb2端口offset在前,usb3端口在后的情况,那样的话就会出错 - - // 循环启动所有的usb3端口 - for (int i = 0; i < xhci_hc[id].port_num; ++i) - { - if (XHCI_PORT_IS_USB3(id, i) && XHCI_PORT_IS_ACTIVE(id, i)) - { - io_mfence(); - // kdebug("to reset port %d, rflags=%#018lx", id, get_rflags()); - int rst_ret = xhci_reset_port(id, i); - // kdebug("reset done!, val=%d", rst_ret); - // reset该端口 - if (likely(rst_ret == 0)) // 如果端口reset成功,就获取它的描述符 - // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 - { - // kdebug("reset port %d ok", id); - struct usb_device_desc dev_desc = {0}; - if (xhci_get_descriptor(id, i, &dev_desc) == 0) - { - xhci_configure_port(id, i); - ++cnt; - } - kdebug("usb3 port %d get desc ok", i); - } - } - } - kdebug("Active usb3 ports:%d", cnt); - - // 循环启动所有的usb2端口 - for (int i = 0; i < xhci_hc[id].port_num; ++i) - { - if (XHCI_PORT_IS_USB2(id, i) && XHCI_PORT_IS_ACTIVE(id, i)) - { - // kdebug("initializing usb2: %d", i); - // reset该端口 - // kdebug("to reset port %d, rflags=%#018lx", i, get_rflags()); - if (likely(xhci_reset_port(id, i) == - 0)) // 如果端口reset成功,就获取它的描述符 - // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 - { - // kdebug("reset port %d ok", id); - - struct usb_device_desc dev_desc = {0}; - if (xhci_get_descriptor(id, i, &dev_desc) == 0) - { - xhci_configure_port(id, i); - ++cnt; - } - kdebug("USB2 port %d get desc ok", i); - } - } - } - kinfo("xHCI controller %d: Started %d ports.", id, cnt); - return 0; -} - -/** - * @brief 发送HID设备的IDLE数据包 - * - * @param id 主机控制器号 - * @param port_id 端口号 - * @param if_desc 接口结构体 - * @return int - */ -static int xhci_hid_set_idle(const int id, const int port_id, struct usb_interface_desc *if_desc) -{ - struct usb_device_desc *dev_desc = xhci_hc[id].ports[port_id].dev_desc; - if (unlikely(dev_desc) == NULL) - { - BUG_ON(1); - return -EINVAL; - } - - DECLARE_USB_PACKET(ctrl_out_packet, USB_REQ_TYPE_SET_CLASS_INTERFACE, 0x0a, 0, 0, 0); - xhci_control_out(id, &ctrl_out_packet, NULL, port_id, dev_desc->max_packet_size); - kdebug("xhci set idle done!"); - return 0; -} - -/** - * @brief 配置端点上下文,并发送configure endpoint命令 - * - * @param id 主机控制器id - * @param port_id 端口号 - * @param ep_num 端点号 - * @param ep_type 端点类型 - * @param ep_desc 端点描述符 - * @return int 错误码 - */ -static int xhci_configure_endpoint(const int id, const int port_id, const uint8_t ep_num, const uint8_t ep_type, - struct usb_endpoint_desc *ep_desc) -{ - - int retval = 0; - uint64_t slot_context_vaddr = xhci_get_device_context_vaddr(id, port_id); - - xhci_initialize_ep(id, slot_context_vaddr, port_id, ep_num, xhci_hc[id].ports[port_id].dev_desc->max_packet_size, - usb_get_max_burst_from_ep(ep_desc), ep_type, (ep_num % 2) ? XHCI_DIR_IN_BIT : XHCI_DIR_OUT_BIT, - xhci_get_port_speed(id, port_id), ep_desc->interval); - - struct xhci_slot_context_t slot; - struct xhci_ep_context_t ep = {0}; - // 创建输入上下文缓冲区 - uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 33, 0); - // 置位对应的add bit - __write4b(input_ctx_buffer + 4, (1 << ep_num) | 1); - __write4b(input_ctx_buffer + 0x1c, 1); - - // 拷贝slot上下文 - __read_from_slot(&slot, slot_context_vaddr); - // 设置该端口的最大端点号。注意,必须设置这里,否则会出错 - slot.entries = (ep_num > slot.entries) ? ep_num : slot.entries; - - __write_slot(input_ctx_buffer + xhci_hc[id].context_size, &slot); - - // __write_ep(id, input_ctx_buffer, 2, &ep); - // kdebug("ep_num=%d", ep_num); - // 拷贝将要被配置的端点的信息 - __read_from_ep(id, slot_context_vaddr, ep_num, &ep); - // kdebug("ep.tr_dequeue_ptr=%#018lx", ep.tr_dequeue_ptr); - ep.err_cnt = 3; - // 加一是因为input_context头部比slot_context多了一个input_control_ctx - __write_ep(id, input_ctx_buffer, ep_num + 1, &ep); - - struct xhci_TRB_normal_t trb = {0}; - trb.buf_paddr = virt_2_phys(input_ctx_buffer); - trb.TRB_type = TRB_TYPE_CONFIG_EP; - trb.cycle = xhci_hc[id].cmd_trb_cycle; - trb.Reserved |= (((uint16_t)xhci_hc[id].ports[port_id].slot_id) << 8) & 0xffff; - - // kdebug("addr=%#018lx", ((struct xhci_TRB_t *)&trb)->param); - // kdebug("status=%#018lx", ((struct xhci_TRB_t *)&trb)->status); - // kdebug("command=%#018lx", ((struct xhci_TRB_t *)&trb)->command); - retval = xhci_send_command(id, (struct xhci_TRB_t *)&trb, true); - - if (unlikely(retval != 0)) - { - kerror("port_id:%d, configure endpoint %d failed", port_id, ep_num); - goto failed; - } - - struct xhci_TRB_cmd_complete_t *trb_done = (struct xhci_TRB_cmd_complete_t *)&trb; - if (trb_done->code == TRB_COMP_TRB_SUCCESS) // 成功执行 - { - // 如果要从控制器获取刚刚设置的设备地址的话,可以在这里读取slot context - ksuccess("port_id:%d, ep:%d successfully configured.", port_id, ep_num); - retval = 0; - } - else - retval = -EAGAIN; -done:; -failed:; - kfree((void *)input_ctx_buffer); - return retval; -} - -/** - * @brief 配置连接在指定端口上的设备 - * - * @param id 主机控制器id - * @param port_id 端口id - * @param full_conf 完整的config - * @return int 错误码 - */ -static int xhci_configure_port(const int id, const int port_id) -{ - void *full_conf = NULL; - struct usb_interface_desc *if_desc = NULL; - struct usb_endpoint_desc *ep_desc = NULL; - int retval = 0; - - // hint: 暂时只考虑对键盘的初始化 - // 获取完整的config - { - struct usb_config_desc conf_desc = {0}; - retval = xhci_get_config_desc(id, port_id, &conf_desc); - if (unlikely(retval != 0)) - return retval; - - full_conf = kzalloc(conf_desc.total_len, 0); - if (unlikely(full_conf == NULL)) - return -ENOMEM; - - retval = xhci_get_config_desc_full(id, port_id, &conf_desc, full_conf); - if (unlikely(retval != 0)) - goto failed; - } - - retval = xhci_get_interface_desc(full_conf, 0, &if_desc); - if (unlikely(retval != 0)) - goto failed; - - if (if_desc->interface_class == USB_CLASS_HID) - { - // 由于暂时只支持键盘,因此把键盘的驱动也写在这里 - // todo: 分离usb键盘驱动 - - retval = xhci_get_endpoint_desc(if_desc, 0, &ep_desc); - if (unlikely(retval != 0)) - goto failed; - // kdebug("to set conf, val=%#010lx", ((struct usb_config_desc *)full_conf)->value); - retval = xhci_set_configuration(id, port_id, ((struct usb_config_desc *)full_conf)->value); - if (unlikely(retval != 0)) - goto failed; - // kdebug("set conf ok"); - - // configure endpoint - retval = xhci_configure_endpoint(id, port_id, ep_desc->endpoint_addr, USB_EP_INTERRUPT, ep_desc); - if (unlikely(retval != 0)) - goto failed; - - retval = xhci_hid_set_idle(id, port_id, if_desc); - if (unlikely(retval != 0)) - goto failed; - - struct usb_hid_desc *hid_desc = NULL; - uint32_t hid_desc_len = 0; - // 获取hid desc - retval = xhci_get_hid_descriptor(id, port_id, full_conf, if_desc->interface_number, &hid_desc); - if (unlikely(retval != 0)) - goto failed; - - // 获取hid report - void *hid_report_data = kzalloc(hid_desc->report_desc_len, 0); - if (unlikely(hid_report_data == NULL)) - goto failed; - retval = - xhci_get_hid_report(id, port_id, if_desc->interface_number, hid_report_data, hid_desc->report_desc_len); - if (unlikely(retval != 0)) - { - kfree(hid_report_data); - goto failed; - } - - kdebug("to parse hid report"); - // todo:这里的parse有问题,详见hid_parse函数的注释 - // hid_parse_report(hid_report_data, hid_desc->report_desc_len); - kdebug("parse hid report done"); - - // kdebug("to find object from hid path"); - // struct hid_data_t data = {0}; - // data.type = HID_ITEM_INPUT; - // data.path.node[0].u_page = HID_USAGE_PAGE_GEN_DESKTOP; - // data.path.node[0].usage = 0xff; - // data.path.node[2].usage = USAGE_POINTER_Y; // to get the Y Coordinate, comment X above and uncomment this - // line data.path.node[2].usage = USAGE_POINTER_WHEEL; // to get the Wheel Coordinate, comment X above and - // uncomment this line - // data.path.size = 1; - // hid_parse_find_object(hid_report_data, hid_desc->report_desc_len, &data); - kfree(hid_report_data); - } - goto out; -failed:; - kerror("failed at xhci_configure_port, retval=%d", retval); -out:; - kfree(full_conf); - return retval; -} -/** - * @brief 初始化xhci主机控制器的中断控制 - * - * @param id 主机控制器id - * @return int 返回码 - */ -static int xhci_hc_init_intr(int id) -{ - uint64_t retval = 0; - - struct xhci_caps_HCSPARAMS1_reg_t hcs1; - struct xhci_caps_HCSPARAMS2_reg_t hcs2; - io_mfence(); - memcpy(&hcs1, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCSPARAMS1_reg_t)); - io_mfence(); - memcpy(&hcs2, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS2), sizeof(struct xhci_caps_HCSPARAMS2_reg_t)); - io_mfence(); - - uint32_t max_segs = (1 << (uint32_t)(hcs2.ERST_Max)); - uint32_t max_interrupters = hcs1.max_intrs; - - // 创建 event ring - retval = xhci_create_event_ring(4096, &xhci_hc[id].event_ring_vaddr); - io_mfence(); - if (unlikely((int64_t)(retval) == -ENOMEM)) - return -ENOMEM; - xhci_hc[id].event_ring_table_vaddr = retval; - xhci_hc[id].current_event_ring_vaddr = - xhci_hc[id].event_ring_vaddr; // 设置驱动程序要读取的下一个event ring trb的地址 - retval = 0; - - xhci_hc[id].current_event_ring_cycle = 1; - - // 写入第0个中断寄存器组 - io_mfence(); - xhci_write_intr_reg32(id, 0, XHCI_IR_MAN, 0x3); // 使能中断并清除pending位(这个pending位是写入1就清0的) - io_mfence(); - xhci_write_intr_reg32(id, 0, XHCI_IR_MOD, 0); // 关闭中断管制 - io_mfence(); - xhci_write_intr_reg32(id, 0, XHCI_IR_TABLE_SIZE, 1); // 当前只有1个segment - io_mfence(); - xhci_write_intr_reg64(id, 0, XHCI_IR_DEQUEUE, - virt_2_phys(xhci_hc[id].current_event_ring_vaddr) | - (1 << 3)); // 写入dequeue寄存器,并清除busy位(写1就会清除) - io_mfence(); - xhci_write_intr_reg64(id, 0, XHCI_IR_TABLE_ADDR, virt_2_phys(xhci_hc[id].event_ring_table_vaddr)); // 写入table地址 - io_mfence(); - - // 清除状态位 - xhci_write_op_reg32(id, XHCI_OPS_USBSTS, (1 << 10) | (1 << 4) | (1 << 3) | (1 << 2)); - io_mfence(); - // 开启usb中断 - // 注册中断处理程序 - struct xhci_hc_irq_install_info_t install_info; - install_info.assert = 1; - install_info.edge_trigger = 1; - install_info.processor = 0; // 投递到bsp - - char *buf = (char *)kmalloc(16, 0); - memset(buf, 0, 16); - sprintk(buf, "xHCI HC%d", id); - io_mfence(); - irq_register(xhci_controller_irq_num[id], &install_info, &xhci_hc_irq_handler, id, &xhci_hc_intr_controller, buf); - io_mfence(); - kfree(buf); - - kdebug("xhci host controller %d: interrupt registered. irq num=%d", id, xhci_controller_irq_num[id]); - - return 0; -} - -/** - * @brief 往xhci控制器发送trb, 并将返回的数据存入原始的trb中 - * - * @param id xhci控制器号 - * @param trb 传输请求块 - * @param do_ring 是否通知doorbell register - * @return int 错误码 - */ -static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring) -{ - uint64_t origin_trb_vaddr = xhci_hc[id].cmd_trb_vaddr; - - // 必须先写入参数和状态数据,最后写入command - __write8b(xhci_hc[id].cmd_trb_vaddr, trb->param); // 参数 - __write4b(xhci_hc[id].cmd_trb_vaddr + 8, trb->status); // 状态 - __write4b(xhci_hc[id].cmd_trb_vaddr + 12, trb->command | xhci_hc[id].cmd_trb_cycle); // 命令 - - xhci_hc[id].cmd_trb_vaddr += sizeof(struct xhci_TRB_t); // 跳转到下一个trb - - { - // 如果下一个trb是link trb,则将下一个要操作的地址是设置为第一个trb - struct xhci_TRB_normal_t *ptr = (struct xhci_TRB_normal_t *)xhci_hc[id].cmd_trb_vaddr; - if (ptr->TRB_type == TRB_TYPE_LINK) - { - ptr->cycle = xhci_hc[id].cmd_trb_cycle; - xhci_hc[id].cmd_trb_vaddr = xhci_hc[id].cmd_ring_vaddr; - xhci_hc[id].cmd_trb_cycle ^= 1; - } - } - - if (do_ring) // 按响命令门铃 - { - __xhci_write_doorbell(id, 0, 0); - - // 等待中断产生 - int timer = 400; - const uint32_t iman0 = xhci_read_intr_reg32(id, 0, XHCI_IR_MAN); - - // Now wait for the interrupt to happen - // We use bit 31 of the command dword since it is reserved - while (timer && ((__read4b(origin_trb_vaddr + 8) & XHCI_IRQ_DONE) == 0)) - { - rs_usleep(1000); - --timer; - } - uint32_t x = xhci_read_cap_reg32(id, xhci_hc[id].rts_offset + 0x20); - if (timer == 0) - return -ETIMEDOUT; - else - { - xhci_get_trb(trb, origin_trb_vaddr); - trb->status &= (~XHCI_IRQ_DONE); - } - } - return 0; -} - -/** - * @brief 获取接口的hid descriptor - * - * @param id 主机控制器号 - * @param port_id 端口号 - * @param full_conf 完整的cofig缓冲区 - * @param interface_number 接口号 - * @param ret_hid_desc 返回的指向hid描述符的指针 - * @return int 错误码 - */ -static int xhci_get_hid_descriptor(int id, int port_id, const void *full_conf, int interface_number, - struct usb_hid_desc **ret_hid_desc) -{ - if (unlikely(ret_hid_desc == NULL || full_conf == NULL)) - return -EINVAL; - kdebug("to get hid_descriptor."); - // 判断接口index是否合理 - if (interface_number >= ((struct usb_config_desc *)full_conf)->num_interfaces) - return -EINVAL; - uint32_t total_len = ((struct usb_config_desc *)full_conf)->total_len; - uint32_t pos = 0; - while (pos < total_len) - { - struct usb_hid_desc *ptr = (struct usb_hid_desc *)(full_conf + pos); - if (ptr->type != USB_DT_HID) - { - pos += ptr->len; - continue; - } - // 找到目标hid描述符 - *ret_hid_desc = ptr; - kdebug("Found hid descriptor for port:%d, if:%d, report_desc_len=%d", port_id, interface_number, - ptr->report_desc_len); - return 0; - } - - return -EINVAL; -} - -/** - * @brief 发送get_hid_descriptor请求,将hid - * - * @param id 主机控制器号 - * @param port_id 端口号 - * @param interface_number 接口号 - * @param ret_hid_report hid report要拷贝到的地址 - * @param hid_report_len hid report的长度 - * @return int 错误码 - */ -static int xhci_get_hid_report(int id, int port_id, int interface_number, void *ret_hid_report, uint32_t hid_report_len) -{ - int retval = xhci_get_desc(id, port_id, ret_hid_report, USB_DT_HID_REPORT, 0, interface_number, hid_report_len); - if (unlikely(retval != 0)) - kerror("xhci_get_hid_report failed: host_controller:%d, port:%d, interface %d", id, port_id, interface_number); - return retval; -} -/** - * @brief 初始化xhci控制器 - * - * @param header 指定控制器的pci device头部 - */ -void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) -{ - - if (xhci_ctrl_count >= XHCI_MAX_HOST_CONTROLLERS) - { - kerror("Initialize xhci controller failed: exceed the limit of max controllers."); - return; - } - - spin_lock(&xhci_controller_init_lock); - kinfo("Initializing xhci host controller: bus=%#02x, device=%#02x, func=%#02x, VendorID=%#04x, irq_line=%d, " - "irq_pin=%d", - dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, dev_hdr->header.Vendor_ID, - dev_hdr->Interrupt_Line, dev_hdr->Interrupt_PIN); - io_mfence(); - int cid = xhci_hc_find_available_id(); - if (cid < 0) - { - kerror("Initialize xhci controller failed: exceed the limit of max controllers."); - goto failed_exceed_max; - } - - memset(&xhci_hc[cid], 0, sizeof(struct xhci_host_controller_t)); - xhci_hc[cid].controller_id = cid; - xhci_hc[cid].pci_dev_hdr = dev_hdr; - io_mfence(); - { - uint32_t tmp = pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0x4); - tmp |= 0x6; - // mem I/O access enable and bus master enable - pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0x4, tmp); - } - io_mfence(); - // 为当前控制器映射寄存器地址空间 - xhci_hc[cid].vbase = - SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + XHCI_MAPPING_OFFSET + 65536 * xhci_hc[cid].controller_id; - // kdebug("dev_hdr->BAR0 & (~0xf)=%#018lx", dev_hdr->BAR0 & (~0xf)); - mm_map_phys_addr(xhci_hc[cid].vbase, dev_hdr->BAR0 & (~0xf), 65536, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, true); - io_mfence(); - - // 计算operational registers的地址 - xhci_hc[cid].vbase_op = xhci_hc[cid].vbase + (xhci_read_cap_reg32(cid, XHCI_CAPS_CAPLENGTH) & 0xff); - io_mfence(); - // 重置xhci控制器 - FAIL_ON_TO(xhci_hc_reset(cid), failed); - io_mfence(); - - // 读取xhci控制寄存器 - uint16_t iversion = *(uint16_t *)(xhci_hc[cid].vbase + XHCI_CAPS_HCIVERSION); - - struct xhci_caps_HCCPARAMS1_reg_t hcc1; - struct xhci_caps_HCCPARAMS2_reg_t hcc2; - - struct xhci_caps_HCSPARAMS1_reg_t hcs1; - struct xhci_caps_HCSPARAMS2_reg_t hcs2; - memcpy(&hcc1, xhci_get_ptr_cap_reg32(cid, XHCI_CAPS_HCCPARAMS1), sizeof(struct xhci_caps_HCCPARAMS1_reg_t)); - memcpy(&hcc2, xhci_get_ptr_cap_reg32(cid, XHCI_CAPS_HCCPARAMS2), sizeof(struct xhci_caps_HCCPARAMS2_reg_t)); - memcpy(&hcs1, xhci_get_ptr_cap_reg32(cid, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCSPARAMS1_reg_t)); - memcpy(&hcs2, xhci_get_ptr_cap_reg32(cid, XHCI_CAPS_HCSPARAMS2), sizeof(struct xhci_caps_HCSPARAMS2_reg_t)); - - xhci_hc[cid].db_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_DBOFF) & (~0x3); // bits [1:0] reserved - io_mfence(); - xhci_hc[cid].rts_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_RTSOFF) & (~0x1f); // bits [4:0] reserved. - io_mfence(); - - xhci_hc[cid].ext_caps_off = 1UL * (hcc1.xECP) * 4; - xhci_hc[cid].context_size = (hcc1.csz) ? 64 : 32; - - if (iversion < 0x95) - kwarn("Unsupported/Unknowned xHCI controller version: %#06x. This may cause unexpected behavior.", iversion); - - { - - // Write to the FLADJ register incase the BIOS didn't - uint32_t tmp = pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0x60); - tmp |= (0x20 << 8); - pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0x60, tmp); - } - // if it is a Panther Point device, make sure sockets are xHCI controlled. - if (((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0) & 0xffff) == 0x8086) && - (((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0) >> 16) & 0xffff) == - 0x1E31) && - ((pci_read_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 8) & 0xff) == 4)) - { - kdebug("Is a Panther Point device"); - pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0xd8, 0xffffffff); - pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0xd0, 0xffffffff); - } - io_mfence(); - // 关闭legacy支持 - FAIL_ON_TO(xhci_hc_stop_legacy(cid), failed); - io_mfence(); - - // 端口配对 - FAIL_ON_TO(xhci_hc_pair_ports(cid), failed); - io_mfence(); - - // ========== 设置USB host controller ========= - // 获取页面大小 - xhci_hc[cid].page_size = (xhci_read_op_reg32(cid, XHCI_OPS_PAGESIZE) & 0xffff) << 12; - io_mfence(); - // 获取设备上下文空间 - xhci_hc[cid].dcbaap_vaddr = (uint64_t)kzalloc(2048, 0); // 分配2KB的设备上下文地址数组空间 - - io_mfence(); - // kdebug("dcbaap_vaddr=%#018lx", xhci_hc[cid].dcbaap_vaddr); - if (unlikely(!xhci_is_aligned64(xhci_hc[cid].dcbaap_vaddr))) // 地址不是按照64byte对齐 - { - kerror("dcbaap isn't 64 byte aligned."); - goto failed_free_dyn; - } - // 写入dcbaap - xhci_write_op_reg64(cid, XHCI_OPS_DCBAAP, virt_2_phys(xhci_hc[cid].dcbaap_vaddr)); - io_mfence(); - - // 创建scratchpad buffer array - uint32_t max_scratchpad_buf = (((uint32_t)hcs2.max_scratchpad_buf_HI5) << 5) | hcs2.max_scratchpad_buf_LO5; - kdebug("max scratchpad buffer=%d", max_scratchpad_buf); - if (max_scratchpad_buf > 0) - { - xhci_hc[cid].scratchpad_buf_array_vaddr = (uint64_t)kzalloc(sizeof(uint64_t) * max_scratchpad_buf, 0); - __write8b(xhci_hc[cid].dcbaap_vaddr, virt_2_phys(xhci_hc[cid].scratchpad_buf_array_vaddr)); - - // 创建scratchpad buffers - for (int i = 0; i < max_scratchpad_buf; ++i) - { - uint64_t buf_vaddr = (uint64_t)kzalloc(xhci_hc[cid].page_size, 0); - __write8b(xhci_hc[cid].scratchpad_buf_array_vaddr, virt_2_phys(buf_vaddr)); - } - } - - // 创建command ring - xhci_hc[cid].cmd_ring_vaddr = xhci_create_ring(XHCI_CMND_RING_TRBS); - xhci_hc[cid].cmd_trb_vaddr = xhci_hc[cid].cmd_ring_vaddr; - - if (unlikely(!xhci_is_aligned64(xhci_hc[cid].cmd_ring_vaddr))) // 地址不是按照64byte对齐 - { - kerror("cmd ring isn't 64 byte aligned."); - goto failed_free_dyn; - } - - // 设置初始cycle bit为1 - xhci_hc[cid].cmd_trb_cycle = XHCI_TRB_CYCLE_ON; - io_mfence(); - // 写入command ring控制寄存器 - xhci_write_op_reg64(cid, XHCI_OPS_CRCR, virt_2_phys(xhci_hc[cid].cmd_ring_vaddr) | xhci_hc[cid].cmd_trb_cycle); - // 写入配置寄存器 - uint32_t max_slots = hcs1.max_slots; - // kdebug("max slots = %d", max_slots); - io_mfence(); - xhci_write_op_reg32(cid, XHCI_OPS_CONFIG, max_slots); - io_mfence(); - // 写入设备通知控制寄存器 - xhci_write_op_reg32(cid, XHCI_OPS_DNCTRL, (1 << 1)); // 目前只有N1被支持 - io_mfence(); - - FAIL_ON_TO(xhci_hc_init_intr(cid), failed_free_dyn); - io_mfence(); - - ++xhci_ctrl_count; - io_mfence(); - spin_unlock(&xhci_controller_init_lock); - io_mfence(); - - return; - -failed_free_dyn:; // 释放动态申请的内存 - if (xhci_hc[cid].dcbaap_vaddr) - kfree((void *)xhci_hc[cid].dcbaap_vaddr); - - if (xhci_hc[cid].cmd_ring_vaddr) - kfree((void *)xhci_hc[cid].cmd_ring_vaddr); - - if (xhci_hc[cid].event_ring_table_vaddr) - kfree((void *)xhci_hc[cid].event_ring_table_vaddr); - - if (xhci_hc[cid].event_ring_vaddr) - kfree((void *)xhci_hc[cid].event_ring_vaddr); - -failed:; - io_mfence(); - // 取消地址映射 - mm_unmap_addr(xhci_hc[cid].vbase, 65536); - io_mfence(); - // 清空数组 - memset((void *)&xhci_hc[cid], 0, sizeof(struct xhci_host_controller_t)); - -failed_exceed_max:; - kerror("Failed to initialize controller: bus=%d, dev=%d, func=%d", dev_hdr->header.bus, dev_hdr->header.device, - dev_hdr->header.func); - spin_unlock(&xhci_controller_init_lock); -} \ No newline at end of file diff --git a/kernel/src/driver/usb/xhci/xhci.h b/kernel/src/driver/usb/xhci/xhci.h deleted file mode 100644 index a2d7a153..00000000 --- a/kernel/src/driver/usb/xhci/xhci.h +++ /dev/null @@ -1,649 +0,0 @@ -#pragma once -#include -#include -#include -// #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); \ No newline at end of file diff --git a/kernel/src/driver/virtio/transport_pci.rs b/kernel/src/driver/virtio/transport_pci.rs index de4f8331..fe44cbf4 100644 --- a/kernel/src/driver/virtio/transport_pci.rs +++ b/kernel/src/driver/virtio/transport_pci.rs @@ -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( Ok(vaddr.cast()) } -/// @brief 获取虚拟地址并将其转化为对应类型的 +/// @brief 获取虚拟地址并将其转化为对应类型的切片的指针 /// @param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息切片的指针 /// @return Result, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error fn get_bar_region_slice( diff --git a/kernel/src/include/bindings/wrapper.h b/kernel/src/include/bindings/wrapper.h index 8b64c995..b7a0d376 100644 --- a/kernel/src/include/bindings/wrapper.h +++ b/kernel/src/include/bindings/wrapper.h @@ -48,3 +48,5 @@ #include #include