mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 15:26:47 +00:00
🆕 xhci:匹配usb2、usb3端口
This commit is contained in:
parent
10537cd1bc
commit
8e5f769a0e
@ -35,7 +35,7 @@
|
||||
printk("[ DEBUG ] (%s:%d)\t", __FILE__, __LINE__); \
|
||||
printk(__VA_ARGS__); \
|
||||
printk("\n"); \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
#define kwarn(...) \
|
||||
do \
|
||||
|
@ -46,6 +46,18 @@ 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)
|
||||
|
||||
/**
|
||||
* @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 FAIL_ON(value, to) \
|
||||
do \
|
||||
{ \
|
||||
@ -172,6 +184,53 @@ static int xhci_hc_stop_legacy(int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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);
|
||||
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);
|
||||
|
||||
if (offset != NULL)
|
||||
*offset = (uint32_t)(dw2 & 0xff);
|
||||
if (count != NULL)
|
||||
*count = (uint32_t)((dw2 & 0xff00) >> 8);
|
||||
if (protocol_flag != NULL)
|
||||
*protocol_flag = (uint16_t)((dw2 >> 16) & 0xffff);
|
||||
|
||||
return next_list_off;
|
||||
}
|
||||
|
||||
list_off = next_list_off;
|
||||
} while (list_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @brief 配对xhci主机控制器的usb2、usb3端口
|
||||
*
|
||||
@ -192,10 +251,102 @@ static int xhci_hc_pair_ports(int id)
|
||||
|
||||
// 从hcs1获取端口数量
|
||||
xhci_hc[id].port_num = hcs1.max_ports;
|
||||
kinfo("Found %d ports on xhci root hub.", 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;
|
||||
|
||||
// 寻找所有的usb2端口
|
||||
while (next_off)
|
||||
{
|
||||
next_off = xhci_hc_get_protocol_offset(id, next_off, 2, &offset, &cnt, &protocol_flags);
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
xhci_hc[id].ports[offset + i].offset = ++xhci_hc[id].port_num_u2;
|
||||
xhci_hc[id].ports[offset + i].flags = XHCI_PROTOCOL_USB2;
|
||||
|
||||
// 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)
|
||||
{
|
||||
next_off = xhci_hc_get_protocol_offset(id, next_off, 3, &offset, &cnt, &protocol_flags);
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
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 = 1; i <= xhci_hc[id].port_num; ++i)
|
||||
{
|
||||
for (int j = i; j <= xhci_hc[id].port_num; ++j)
|
||||
{
|
||||
if (unlikely(i == j))
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
xhci_hc[id].ports[j].paired_port_num = i;
|
||||
xhci_hc[id].ports[j].flags |= XHCI_PROTOCOL_HAS_PAIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标记所有的usb3端口为激活状态
|
||||
for (int i = 1; i <= xhci_hc[id].port_num; ++i)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -230,7 +381,7 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
|
||||
// 为当前控制器映射寄存器地址空间
|
||||
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));
|
||||
// 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);
|
||||
|
||||
// 读取xhci控制寄存器
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include <driver/usb/usb.h>
|
||||
#include <driver/pci/pci.h>
|
||||
|
||||
#define XHCI_MAX_HOST_CONTROLLERS 8
|
||||
#define XHCI_MAX_ROOT_HUB_PORTS 128
|
||||
#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
|
||||
#define XHCI_CAPS_CAPLENGTH 0x00 // Cap 寄存器组的长度
|
||||
@ -141,7 +141,7 @@ struct xhci_ops_config_reg_t
|
||||
// ID 部分的含义定义
|
||||
#define XHCI_XECP_ID_RESERVED 0
|
||||
#define XHCI_XECP_ID_LEGACY 1 // USB Legacy Support
|
||||
#define XHCI_XECP_ID_PROTOCAL 2 // Supported protocal
|
||||
#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
|
||||
@ -154,6 +154,14 @@ struct xhci_ops_config_reg_t
|
||||
#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)
|
||||
|
||||
// 端口信息标志位
|
||||
#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) // 当前端口是这个配对中,被激活的端口
|
||||
|
||||
/**
|
||||
* @brief xhci端口信息
|
||||
*
|
||||
@ -179,7 +187,7 @@ struct xhci_host_controller_t
|
||||
uint16_t port_num; // 总的端口数量
|
||||
uint8_t port_num_u2; // usb 2.0端口数量
|
||||
uint8_t port_num_u3; // usb 3端口数量
|
||||
struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针
|
||||
struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针(由于端口offset是从1开始的,因此该数组第0项为空)
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user