1 #pragma once
2 
3 /*
4     注意!!!
5 
6     尽管采用MMI/O的方式访问寄存器,但是对于指定大小的寄存器,
7     在发起读请求的时候,只能从寄存器的起始地址位置开始读取。
8 
9     例子:不能在一个32bit的寄存器中的偏移量8的位置开始读取1个字节
10             这种情况下,我们必须从32bit的寄存器的0地址处开始读取32bit,然后通过移位的方式得到其中的字节。
11 */
12 
13 #define xhci_read_cap_reg32(id, offset) (__read4b(xhci_hc[id].vbase + (offset)))
14 #define xhci_get_ptr_cap_reg32(id, offset) ((uint32_t *)(xhci_hc[id].vbase + (offset)))
15 #define xhci_write_cap_reg32(id, offset, value) (__write4b(xhci_hc[id].vbase + (offset), (value)))
16 
17 #define xhci_read_cap_reg64(id, offset) (__read8b(xhci_hc[id].vbase + (offset)))
18 #define xhci_get_ptr_reg64(id, offset) ((uint64_t *)(xhci_hc[id].vbase + (offset)))
19 #define xhci_write_cap_reg64(id, offset, value) (__write8b(xhci_hc[id].vbase + (offset), (value)))
20 
21 #define xhci_read_op_reg8(id, offset) (*(uint8_t *)(xhci_hc[id].vbase_op + (offset)))
22 #define xhci_get_ptr_op_reg8(id, offset) ((uint8_t *)(xhci_hc[id].vbase_op + (offset)))
23 #define xhci_write_op_reg8(id, offset, value) (*(uint8_t *)(xhci_hc[id].vbase_op + (offset)) = (uint8_t)(value))
24 
25 #define xhci_read_op_reg32(id, offset) (__read4b(xhci_hc[id].vbase_op + (offset)))
26 #define xhci_get_ptr_op_reg32(id, offset) ((uint32_t *)(xhci_hc[id].vbase_op + (offset)))
27 #define xhci_write_op_reg32(id, offset, value) (__write4b(xhci_hc[id].vbase_op + (offset), (value)))
28 
29 #define xhci_read_op_reg64(id, offset) (__read8b(xhci_hc[id].vbase_op + (offset)))
30 #define xhci_get_ptr_op_reg64(id, offset) ((uint64_t *)(xhci_hc[id].vbase_op + (offset)))
31 #define xhci_write_op_reg64(id, offset, value) (__write8b(xhci_hc[id].vbase_op + (offset), (value)))
32 
33 /**
34  * @brief 计算中断寄存器组虚拟地址
35  * @param id 主机控制器id
36  * @param num xhci中断寄存器组号
37  */
38 #define xhci_calc_intr_vaddr(id, num) (xhci_hc[id].vbase + xhci_hc[id].rts_offset + XHCI_RT_IR0 + (num)*XHCI_IR_SIZE)
39 /**
40  * @brief 读取/写入中断寄存器
41  * @param id 主机控制器id
42  * @param num xhci中断寄存器组号
43  * @param intr_offset 寄存器在当前寄存器组中的偏移量
44  */
45 #define xhci_read_intr_reg32(id, num, intr_offset) (__read4b(xhci_calc_intr_vaddr(id, num) + (intr_offset)))
46 #define xhci_write_intr_reg32(id, num, intr_offset, value) (__write4b(xhci_calc_intr_vaddr(id, num) + (intr_offset), (value)))
47 #define xhci_read_intr_reg64(id, num, intr_offset) (__read8b(xhci_calc_intr_vaddr(id, num) + (intr_offset)))
48 #define xhci_write_intr_reg64(id, num, intr_offset, value) (__write8b(xhci_calc_intr_vaddr(id, num) + (intr_offset), (value)))
49 
50 #define xhci_is_aligned64(addr) (((addr)&0x3f) == 0) // 是否64bytes对齐
51 
52 /**
53  * @brief 判断端口信息
54  * @param cid 主机控制器id
55  * @param pid 端口id
56  */
57 #define XHCI_PORT_IS_USB2(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_INFO) == XHCI_PROTOCOL_USB2)
58 #define XHCI_PORT_IS_USB3(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_INFO) == XHCI_PROTOCOL_USB3)
59 
60 #define XHCI_PORT_IS_USB2_HSO(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_HSO) == XHCI_PROTOCOL_HSO)
61 #define XHCI_PORT_HAS_PAIR(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_HAS_PAIR) == XHCI_PROTOCOL_HAS_PAIR)
62 #define XHCI_PORT_IS_ACTIVE(cid, pid) ((xhci_hc[cid].ports[pid].flags & XHCI_PROTOCOL_ACTIVE) == XHCI_PROTOCOL_ACTIVE)
63 
64 #define XHCI_PORT_REGISTER_OFFSET(__port_id) (XHCI_OPS_PRS + 16 * (__port_id))
65 
66 // 获取端口速度 full=1, low=2, high=3, super=4
67 #define xhci_get_port_speed(__id, __port_id) ((xhci_read_op_reg32((__id), XHCI_PORT_REGISTER_OFFSET(__port_id) + XHCI_PORT_PORTSC) >> 10) & 0xf)
68 
69 /**
70  * @brief 设置link TRB的命令(dword3)
71  *
72  */
73 #define xhci_TRB_set_link_cmd(trb_vaddr)                                         \
74     do                                                                           \
75     {                                                                            \
76         struct xhci_TRB_normal_t *ptr = (struct xhci_TRB_normal_t *)(trb_vaddr); \
77         ptr->TRB_type = TRB_TYPE_LINK;                                           \
78         ptr->ioc = 0;                                                            \
79         ptr->chain = 0;                                                          \
80         ptr->ent = 0;                                                            \
81         ptr->cycle = 1;                                                          \
82     } while (0)
83 
84 // 设置endpoint结构体的dequeue_cycle_state bit
85 #define xhci_ep_set_dequeue_cycle_state(ep_ctx_ptr, state) ((ep_ctx_ptr)->tr_dequeue_ptr |= ((state)&1))
86 // 获取endpoint结构体的dequeue_cycle_state bit
87 #define xhci_ep_get_dequeue_cycle_state(ep_ctx_ptr) (((ep_ctx_ptr)->tr_dequeue_ptr) & 1)