Browse Source

Merge branch 'usb'

fslongjin 2 years ago
parent
commit
11bb8fb505

+ 1 - 0
docs/index.rst

@@ -22,6 +22,7 @@
    kernel/process_management/index
    kernel/filesystem/index
    kernel/debug/index
+   kernel/cpu_arch/index
 
 
 .. toctree::

+ 10 - 0
docs/kernel/cpu_arch/index.rst

@@ -0,0 +1,10 @@
+处理器架构
+====================================
+
+   该部分文档提供了和处理器架构相关的一些编程实现细节的描述。
+   
+.. toctree::
+   :maxdepth: 1
+   :caption: 目录
+
+   x86_64/index

+ 8 - 0
docs/kernel/cpu_arch/x86_64/index.rst

@@ -0,0 +1,8 @@
+x86-64相关文档
+====================================
+   
+.. toctree::
+   :maxdepth: 1
+   :caption: 目录
+
+   usb_legacy_support

+ 9 - 0
docs/kernel/cpu_arch/x86_64/usb_legacy_support.md

@@ -0,0 +1,9 @@
+# USB Legacy支持
+
+## 简介
+
+  usb legacy support指的是,由BIOS提供的,对USB鼠标、USB键盘的支持。在支持并启用USB Legacy Support的计算机上,USB鼠标、键盘由BIOS提供模拟,在操作系统看来,就像接入了PS/2鼠标、键盘一样。
+
+## 相关
+
+- 在初始化USB控制器时,需要关闭它的USB Legacy Support

+ 71 - 7
kernel/driver/usb/xhci/xhci.c

@@ -4,6 +4,7 @@
 #include <process/spinlock.h>
 #include <mm/mm.h>
 #include <debug/traceback/traceback.h>
+#include <common/time.h>
 
 spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁(在usb_init中被初始化)
 
@@ -11,6 +12,62 @@ static int xhci_ctrl_count = 0; // xhci控制器计数
 
 static struct xhci_host_controller_t xhci_hc[MAX_XHCI_HOST_CONTROLLERS] = {0};
 
+#define xhci_read_cap_reg8(id, offset) (*(uint8_t *)(xhci_hc[id].vbase + offset))
+#define xhci_write_cap_reg8(id, offset, value) (*(uint8_t *)(xhci_hc[id].vbase + offset) = (uint8_t)value)
+#define xhci_read_cap_reg32(id, offset) (*(uint32_t *)(xhci_hc[id].vbase + offset))
+#define xhci_write_cap_reg32(id, offset, value) (*(uint32_t *)(xhci_hc[id].vbase + offset) = (uint32_t)value)
+#define xhci_read_cap_reg64(id, offset) (*(uint64_t *)(xhci_hc[id].vbase + offset))
+#define xhci_write_cap_reg64(id, offset, value) (*(uint64_t *)(xhci_hc[id].vbase + offset) = (uint64_t)value)
+
+#define xhci_read_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) (*(uint32_t *)(xhci_hc[id].vbase_op + offset))
+#define xhci_write_op_reg32(id, offset, value) (*(uint32_t *)(xhci_hc[id].vbase_op + offset) = (uint32_t)value)
+#define xhci_read_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)
+
+/**
+ * @brief 停止xhci主机控制器
+ *
+ * @param id 主机控制器id
+ * @return int
+ */
+static int xhci_hc_stop(int id)
+{
+    // todo: 停止usb控制器
+}
+
+/**
+ * @brief reset xHCI主机控制器
+ *
+ * @param id 主机控制器id
+ * @return int
+ */
+static int xhci_hc_reset(int id)
+{
+    int retval = 0;
+    // 判断HCHalted是否置位
+    if ((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 0)
+    {
+        // 未置位,需要先尝试停止usb主机控制器
+        retval = xhci_hc_stop(id);
+        if (retval)
+            return retval;
+    }
+    int timeout = 500; // wait 500ms
+    // reset
+    xhci_write_cap_reg32(id, XHCI_OPS_USBCMD, (1 << 1));
+    usleep(1000);
+    while (xhci_read_op_reg32(id, XHCI_OPS_USBCMD) & (1 << 1))
+    {
+        usleep(1000);
+        if (--timeout == 0)
+            return -ETIMEDOUT;
+    }
+    kdebug("reset done!, timeout=%d", timeout);
+    return retval;
+}
+
 /**
  * @brief 初始化xhci控制器
  *
@@ -32,19 +89,26 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
 
     // 读取xhci控制寄存器
     uint16_t iversion = *(uint16_t *)(xhci_hc[xhci_ctrl_count].vbase + XHCI_CAPS_HCIVERSION);
-    uint32_t dboff = *(uint16_t *)(xhci_hc[xhci_ctrl_count].vbase + XHCI_CAPS_DBOFF);
-    
-    // kdebug("dboff=%ld", dboff);
-    // struct xhci_caps_HCSPARAMS1_reg_t hcs1 = *(struct xhci_caps_HCSPARAMS1_reg_t *)(xhci_hc[xhci_ctrl_count].vbase + XHCI_CAPS_HCSPARAMS1);
 
-    // kdebug("hcs1.max_ports=%d, hcs1.max_slots=%d, hcs1.max_intrs=%d", hcs1.max_ports, hcs1.max_slots, hcs1.max_intrs);
-    // kdebug("caps size=%d", *(uint8_t *)xhci_hc[xhci_ctrl_count].vbase);
-    // kdebug("iversion=%#06x", iversion);
+    // 计算operational registers的地址
+    xhci_hc[xhci_ctrl_count].vbase_op = xhci_hc[xhci_ctrl_count].vbase + xhci_read_cap_reg8(xhci_ctrl_count, XHCI_CAPS_CAPLENGTH);
+
     if (iversion < 0x95)
     {
         kwarn("Unsupported/Unknowned xHCI controller version: %#06x. This may cause unexpected behavior.", iversion);
     }
 
+    // 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, 2) & 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);
+    }
+    
+    xhci_hc_reset(xhci_ctrl_count);
     ++xhci_ctrl_count;
     spin_unlock(&xhci_controller_init_lock);
     return;

+ 63 - 1
kernel/driver/usb/xhci/xhci.h

@@ -73,7 +73,68 @@ struct xhci_caps_HCCPARAMS2_reg_t
     unsigned Reserved : 26;
 } __attribute__((packed));
 
+// 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));
 
 /**
  * @brief xhci端口信息
@@ -91,7 +152,8 @@ 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;                                            // 虚拟地址base(bar0映射到的虚拟地址)
+    uint64_t vbase_op;                                         // Operational registers 起始虚拟地址
     struct xhci_port_info_t *ports;                            // 指向端口信息数组的指针
 };