Browse Source

new: create ring

fslongjin 2 years ago
parent
commit
d18a69ac2f
2 changed files with 247 additions and 14 deletions
  1. 115 9
      kernel/driver/usb/xhci/xhci.c
  2. 132 5
      kernel/driver/usb/xhci/xhci.h

+ 115 - 9
kernel/driver/usb/xhci/xhci.c

@@ -3,6 +3,7 @@
 #include <debug/bug.h>
 #include <process/spinlock.h>
 #include <mm/mm.h>
+#include <mm/slab.h>
 #include <debug/traceback/traceback.h>
 #include <common/time.h>
 
@@ -46,6 +47,8 @@ static struct xhci_host_controller_t xhci_hc[XHCI_MAX_HOST_CONTROLLERS] = {0};
 #define xhci_get_ptr_op_reg64(id, offset) ((uint64_t *)(xhci_hc[id].vbase_op + offset))
 #define xhci_write_op_reg64(id, offset, value) (*(uint64_t *)(xhci_hc[id].vbase_op + offset) = (uint64_t)value)
 
+#define xhci_is_aligned64(addr) ((addr & 0x3f) == 0) // 是否64bytes对齐
+
 /**
  * @brief 判断端口信息
  * @param cid 主机控制器id
@@ -58,6 +61,21 @@ static struct xhci_host_controller_t xhci_hc[XHCI_MAX_HOST_CONTROLLERS] = {0};
 #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)
 
+/**
+ * @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)
+
 #define FAIL_ON(value, to)        \
     do                            \
     {                             \
@@ -65,6 +83,47 @@ static struct xhci_host_controller_t xhci_hc[XHCI_MAX_HOST_CONTROLLERS] = {0};
             goto to;              \
     } while (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
+};
+
 /**
  * @brief 在controller数组之中寻找可用插槽
  *
@@ -239,15 +298,9 @@ static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int
  */
 static int xhci_hc_pair_ports(int id)
 {
-    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(id, XHCI_CAPS_HCCPARAMS1), sizeof(struct xhci_caps_HCCPARAMS1_reg_t));
-    memcpy(&hcc2, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCCPARAMS2), sizeof(struct xhci_caps_HCCPARAMS1_reg_t));
     memcpy(&hcs1, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCCPARAMS1_reg_t));
-    memcpy(&hcs2, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS2), sizeof(struct xhci_caps_HCCPARAMS1_reg_t));
 
     // 从hcs1获取端口数量
     xhci_hc[id].port_num = hcs1.max_ports;
@@ -350,6 +403,24 @@ static int xhci_hc_pair_ports(int id)
     return 0;
 }
 
+/**
+ * @brief 创建ring,并将最后一个trb指向头一个trb
+ *
+ * @param trbs 要创建的trb数量
+ * @return uint64_t
+ */
+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);
+    memset(vaddr, 0, total_size);
+
+    // 设置最后一个trb为link trb
+    xhci_TRB_set_link_cmd(vaddr + total_size - sizeof(sizeof(struct xhci_TRB_t)));
+
+    return vaddr;
+}
+
 /**
  * @brief 初始化xhci控制器
  *
@@ -386,16 +457,26 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
 
     // 读取xhci控制寄存器
     uint16_t iversion = *(uint16_t *)(xhci_hc[cid].vbase + XHCI_CAPS_HCIVERSION);
-    uint32_t hcc1 = xhci_read_cap_reg32(cid, XHCI_CAPS_HCCPARAMS1);
 
+    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_HCCPARAMS1_reg_t));
+    memcpy(&hcs1, xhci_get_ptr_cap_reg32(cid, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCCPARAMS1_reg_t));
+    memcpy(&hcs2, xhci_get_ptr_cap_reg32(cid, XHCI_CAPS_HCSPARAMS2), sizeof(struct xhci_caps_HCCPARAMS1_reg_t));
+
+    // kdebug("hcc1.xECP=%#010lx", hcc1.xECP);
     // 计算operational registers的地址
     xhci_hc[cid].vbase_op = xhci_hc[cid].vbase + xhci_read_cap_reg8(cid, XHCI_CAPS_CAPLENGTH);
 
     xhci_hc[cid].db_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_DBOFF) & (~0x3);    // bits [1:0] reserved
     xhci_hc[cid].rts_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_RTSOFF) & (~0x1f); // bits [4:0] reserved.
 
-    xhci_hc[cid].ext_caps_off = ((hcc1 & 0xffff0000) >> 16) * 4;
-    xhci_hc[cid].context_size = (hcc1 & (1 << 2)) ? 64 : 32;
+    xhci_hc[cid].ext_caps_off = (hcc1.xECP) * 4;
+    xhci_hc[cid].context_size = (hcc1.csz) ? 64 : 32;
 
     if (iversion < 0x95)
     {
@@ -414,18 +495,43 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
 
     // 重置xhci控制器
     FAIL_ON(xhci_hc_reset(cid), failed);
+    // 关闭legacy支持
     FAIL_ON(xhci_hc_stop_legacy(cid), failed);
+    // 端口配对
     FAIL_ON(xhci_hc_pair_ports(cid), failed);
 
+    // 获取页面大小
+    xhci_hc[cid].page_size = (xhci_read_op_reg32(cid, XHCI_OPS_PAGESIZE) & 0xffff) << 12;
+    kdebug("pg size=%d", xhci_hc[cid].page_size);
+
+    // 获取设备上下文空间
+    xhci_hc[cid].dcbaap_vaddr = (uint64_t)kmalloc(2048, 0); // 分配2KB的设备上下文地址数组空间
+    memset(xhci_hc[cid].dcbaap_vaddr, 0, 2048);
+
+    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_cap_reg64(cid, XHCI_OPS_DCBAAP, virt_2_phys(xhci_hc[cid].dcbaap_vaddr));
+    xhci_hc[cid].cmd_ring_vaddr = xhci_create_ring(XHCI_CMND_RING_TRBS);
     ++xhci_ctrl_count;
     spin_unlock(&xhci_controller_init_lock);
     return;
+
+failed_free_dyn:; // 释放动态申请的内存
+    if (xhci_hc[cid].dcbaap_vaddr)
+        kfree(xhci_hc[cid].dcbaap_vaddr);
+
 failed:;
     // 取消地址映射
     mm_unmap(xhci_hc[cid].vbase, 65536);
 
     // 清空数组
     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);

+ 132 - 5
kernel/driver/usb/xhci/xhci.h

@@ -2,7 +2,7 @@
 #include <driver/usb/usb.h>
 #include <driver/pci/pci.h>
 
-#define XHCI_MAX_HOST_CONTROLLERS 4     // 本驱动程序最大支持4个xhci root hub controller
+#define XHCI_MAX_HOST_CONTROLLERS 4 // 本驱动程序最大支持4个xhci root hub controller
 #define XHCI_MAX_ROOT_HUB_PORTS 128 // 本驱动程序最大支持127个root hub 端口(第0个保留)
 
 // xhci Capability Registers offset
@@ -157,10 +157,134 @@ struct xhci_ops_config_reg_t
 // 端口信息标志位
 #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) // 当前端口是这个配对中,被激活的端口
+#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)   // 当前端口是这个配对中,被激活的端口
+
+// 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
+
+/**
+ * @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_state_t
+{
+    uint8_t bmRequestType;
+    uint8_t bRequest;
+    uint16_t wValue;
+
+    uint16_t wIndex;
+    uint16_t wLength;
+
+    unsigned transfer_legth : 17;
+    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 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));
 
 /**
  * @brief xhci端口信息
@@ -187,6 +311,9 @@ struct xhci_host_controller_t
     uint16_t port_num;                                         // 总的端口数量
     uint8_t port_num_u2;                                       // usb 2.0端口数量
     uint8_t port_num_u3;                                       // usb 3端口数量
+    uint8_t page_size;                                         // page size
+    uint64_t dcbaap_vaddr;                                     // Device Context Base Address Array Pointer的虚拟地址
+    uint64_t cmd_ring_vaddr;                                   // command ring的虚拟地址
     struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS];    // 指向端口信息数组的指针(由于端口offset是从1开始的,因此该数组第0项为空)
 };