Browse Source

new: xhci get descriptor

fslongjin 2 years ago
parent
commit
416a802b9c
7 changed files with 967 additions and 107 deletions
  1. 6 2
      Makefile
  2. 2 0
      kernel/driver/pci/msi.c
  3. 118 7
      kernel/driver/usb/usb.h
  4. 678 81
      kernel/driver/usb/xhci/xhci.c
  5. 142 7
      kernel/driver/usb/xhci/xhci.h
  6. 4 5
      kernel/main.c
  7. 17 5
      run.sh

+ 6 - 2
Makefile

@@ -1,18 +1,22 @@
 SUBDIRS = kernel user
 
-
+# ifndef $(EMULATOR)
+ifeq ($(EMULATOR), )
+export EMULATOR=__NO_EMULATION__
+endif
 
 
 export ARCH=__x86_64__
 export ROOT_PATH=$(shell pwd)
 
 export DEBUG=DEBUG
-export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64  -fno-stack-protector -D $(ARCH) -O1
+export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64  -fno-stack-protector -D $(ARCH) -D $(EMULATOR) -O1
 
 ifeq ($(DEBUG), DEBUG)
 GLOBAL_CFLAGS += -g 
 endif
 
+
 .PHONY: all
 all: kernel user
 	

+ 2 - 0
kernel/driver/pci/msi.c

@@ -164,6 +164,7 @@ int pci_enable_msi(struct msi_desc_t *msi_desc)
 
     if (msi_desc->pci.msi_attribute.is_msix) // MSI-X
     {
+        kdebug("is msix");
         // 读取msix的信息
         struct pci_msix_cap_t cap = __msi_read_msix_cap_list(msi_desc, cap_ptr);
         // 映射msix table
@@ -181,6 +182,7 @@ int pci_enable_msi(struct msi_desc_t *msi_desc)
     }
     else
     {
+        kdebug("is msi");
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
         message_control = (tmp >> 16) & 0xffff;
 

+ 118 - 7
kernel/driver/usb/usb.h

@@ -1,4 +1,5 @@
 #pragma once
+#include <common/sys/types.h>
 
 // usb设备在pci总线上的class
 #define USB_CLASS 0xC
@@ -9,17 +10,127 @@
 #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)
+#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
+#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 设备描述符
+ *
+ */
+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
+};
+
+/**
+ * @brief usb设备请求包
+ *
+ */
+struct usb_request_packet_t
+{
+    uint8_t request_type;
+    uint8_t request;
+    uint16_t value;
+
+    uint16_t index;
+    uint16_t length;
+};
+// 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_SET_INTERFACE (__USB_REQ_TYPE_H2D | __USB_REQ_TYPE_STANDARD | __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,
+    // 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_HID = 0x21,
+    USB_DT_HID_REPORT,
+    USB_DT_HID_PHYSICAL,
+
+    USB_DT_INTERFACE_FUNCTION = 0x24,
+    USB_DT_ENDPOINT_FUNCTION,
+
+    HUB = 0x29
+};
+
+// 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驱动程序
- * 
+ *
  */
 void usb_init();

File diff suppressed because it is too large
+ 678 - 81
kernel/driver/usb/xhci/xhci.c


+ 142 - 7
kernel/driver/usb/xhci/xhci.h

@@ -8,7 +8,7 @@
 
 // ========== irq BEGIN ===========
 
-#define XHCI_IRQ_DONE (1<<31)   // 当command trb 的status的第31位被驱动程序置位时,表明该trb已经执行完成(这是由于xhci规定,第31位可以由驱动程序自行决定用途)
+#define XHCI_IRQ_DONE (1 << 31) // 当command trb 的status的第31位被驱动程序置位时,表明该trb已经执行完成(这是由于xhci规定,第31位可以由驱动程序自行决定用途)
 /**
  * @brief 每个xhci控制器的中断向量号
  *
@@ -188,6 +188,10 @@ struct xhci_ops_config_reg_t
 #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结构
  *
@@ -220,7 +224,7 @@ struct xhci_TRB_normal_t
     uint16_t Reserved;     // 保留且置为0
 } __attribute__((packed));
 
-struct xhci_TRB_setup_state_t
+struct xhci_TRB_setup_stage_t
 {
     uint8_t bmRequestType;
     uint8_t bRequest;
@@ -229,14 +233,14 @@ struct xhci_TRB_setup_state_t
     uint16_t wIndex;
     uint16_t wLength;
 
-    unsigned transfer_legth : 17;
-    unsigned resv1 : 5; // Reserved and zero'd
+    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;
-    unsigned idt : 1;
+    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
@@ -354,8 +358,132 @@ struct xhci_intr_moderation_t
 
 #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
@@ -376,6 +504,12 @@ struct xhci_port_info_t
     uint8_t reserved;
 } __attribute__((packed));
 
+struct xhci_ep_ring_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
+};
 struct xhci_host_controller_t
 {
     struct pci_device_structure_general_device_t *pci_dev_hdr; // 指向pci header结构体的指针
@@ -385,7 +519,7 @@ struct xhci_host_controller_t
     uint32_t rts_offset;                                       // Runtime Register Space offset
     uint32_t db_offset;                                        // Doorbell offset
     uint32_t ext_caps_off;                                     // 扩展能力寄存器偏移量
-    uint8_t context_size;                                      // 上下文大小
+    uint8_t context_size;                                      // 设备上下文大小
     uint16_t port_num;                                         // 总的端口数量
     uint8_t port_num_u2;                                       // usb 2.0端口数量
     uint8_t port_num_u3;                                       // usb 3端口数量
@@ -399,6 +533,7 @@ struct xhci_host_controller_t
     uint8_t cmd_trb_cycle;                                     // 当前command ring cycle
     uint8_t current_event_ring_cycle;                          // 当前event ring cycle
     struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS];    // 指向端口信息数组的指针(由于端口offset是从1开始的,因此该数组第0项为空)
+    struct xhci_ep_ring_info_t control_ep_info;                // 控制端点的信息
 };
 
 // Common TRB types

+ 4 - 5
kernel/main.c

@@ -88,22 +88,21 @@ void system_initialize()
 
     cpu_core_info[0].stack_start = _stack_start;
     cpu_core_info[0].tss_vaddr = (uint64_t)&initial_tss[0];
-    kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr);
-    kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start);
+    // kdebug("cpu_core_info[0].tss_vaddr=%#018lx", cpu_core_info[0].tss_vaddr);
+    // kdebug("cpu_core_info[0].stack_start%#018lx", cpu_core_info[0].stack_start);
 
     // 初始化中断描述符表
     sys_vector_init();
 
     //  初始化内存管理单元
     mm_init();
-    
+
     // 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
     // 原因是,系统启动初期,framebuffer被映射到48M地址处,
     // mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃
     // 对显示模块进行低级初始化,不启用double buffer
     scm_reinit();
 
-
     // =========== 重新设置initial_tss[0]的ist
     uchar *ptr = (uchar *)kzalloc(STACK_SIZE, 0) + STACK_SIZE;
     ((struct process_control_block *)(ptr - STACK_SIZE))->cpu_id = 0;
@@ -158,7 +157,7 @@ void system_initialize()
     io_mfence();
     // current_pcb->preempt_count = 0;
     // kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
-   
+
     process_init();
     // 启用double buffer
     scm_enable_double_buffer();

+ 17 - 5
run.sh

@@ -7,6 +7,16 @@ fi
 GENERATE_ISO=0
 IN_DOCKER=0
 
+IA32_USE_QEMU=1
+bochsrc="./bochsrc"
+ARCH="x86_64"
+
+if [ ${IA32_USE_QEMU} == "1" ];then
+    export EMULATOR=__QEMU_EMULATION__
+else
+    export EMULATOR=__NO_EMULATION__
+fi
+
 # 第一个参数如果是--notbuild 那就不构建,直接运行
 if [ ! "$1" == "--nobuild" ]; then
     echo "开始构建..."
@@ -28,9 +38,6 @@ if [ ! "$1" == "--nobuild" ]; then
     fi
 fi
 
-IA32_USE_QEMU=1
-bochsrc="./bochsrc"
-ARCH="x86_64"
 
 # 内核映像
 root_folder="$(pwd)"
@@ -128,8 +135,13 @@ flag_can_run=1
 
 allflags=$(qemu-system-x86_64 -cpu help | awk '/flags/ {y=1; getline}; y {print}' | tr ' ' '\n' | grep -Ev "^$" | sed -r 's|^|+|' | tr '\n' ',' | sed -r "s|,$||")
 
+# 请根据自己的需要,在-d 后方加入所需的trace事件
+
+# 标准的trace events
+qemu_trace_std=cpu_reset,guest_errors,trace:check_exception,exec,cpu
 # 调试usb的trace
-qemu_trace_usb=trace:usb_xhci_reset,trace:usb_xhci_run,trace:usb_xhci_stop,trace:usb_xhci_irq_msi,trace:usb_xhci_irq_msix,trace:usb_xhci_port_reset
+qemu_trace_usb=trace:usb_xhci_reset,trace:usb_xhci_run,trace:usb_xhci_stop,trace:usb_xhci_irq_msi,trace:usb_xhci_irq_msix,trace:usb_xhci_port_reset,trace:msix_write_config,trace:usb_xhci_irq_msix,trace:usb_xhci_irq_msix_use,trace:usb_xhci_irq_msix_unuse,trace:usb_xhci_irq_msi,trace:usb_xhci_*
+
 
 qemu_accel=kvm
 if [ "${OS}" == "Darwin" ]; then
@@ -142,7 +154,7 @@ if [ $flag_can_run -eq 1 ]; then
     else
         qemu-system-x86_64 -d bin/disk.img -m 512M -smp 2,cores=2,threads=1,sockets=1 \
         -boot order=d   \
-        -monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm,${qemu_trace_usb} \
+        -monitor stdio -d ${qemu_trace_std} \
         -s -S -cpu IvyBridge,apic,x2apic,+fpu,check,${allflags} -rtc clock=host,base=localtime -serial file:serial_opt.txt \
         -drive id=disk,file=bin/disk.img,if=none \
         -device ahci,id=ahci \

Some files were not shown because too many files changed in this diff