|
@@ -69,49 +69,44 @@ hardware_intr_controller xhci_hc_intr_controller =
|
|
|
这种情况下,我们必须从32bit的寄存器的0地址处开始读取32bit,然后通过移位的方式得到其中的字节。
|
|
|
*/
|
|
|
|
|
|
-#define xhci_read_cap_reg32(id, offset) (*(uint32_t *)(xhci_hc[id].vbase + (offset)))
|
|
|
+#define xhci_read_cap_reg32(id, offset) (__read4b(xhci_hc[id].vbase + (offset)))
|
|
|
#define xhci_get_ptr_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_write_cap_reg32(id, offset, value) (__write4b(xhci_hc[id].vbase + (offset), (value)))
|
|
|
|
|
|
-#define xhci_read_cap_reg64(id, offset) (*(uint64_t *)(xhci_hc[id].vbase + (offset)))
|
|
|
+#define xhci_read_cap_reg64(id, offset) (__read8b(xhci_hc[id].vbase + (offset)))
|
|
|
#define xhci_get_ptr_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_write_cap_reg64(id, offset, value) (__write8b(xhci_hc[id].vbase + (offset), (value)))
|
|
|
|
|
|
#define xhci_read_op_reg8(id, offset) (*(uint8_t *)(xhci_hc[id].vbase_op + (offset)))
|
|
|
#define xhci_get_ptr_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_read_op_reg32(id, offset) (__read4b(xhci_hc[id].vbase_op + (offset)))
|
|
|
#define xhci_get_ptr_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_write_op_reg32(id, offset, value) (__write4b(xhci_hc[id].vbase_op + (offset), (value)))
|
|
|
|
|
|
-#define xhci_read_op_reg64(id, offset) (*(uint64_t *)(xhci_hc[id].vbase_op + (offset)))
|
|
|
+#define xhci_read_op_reg64(id, offset) (__read8b(xhci_hc[id].vbase_op + (offset)))
|
|
|
#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_write_mem32(vaddr, value) (*(uint32_t *)(vaddr) = (value))
|
|
|
-#define xhci_write_mem64(vaddr, value) (*(uint64_t *)(vaddr) = (value))
|
|
|
-#define xhci_read_mem32(vaddr) (*(uint32_t *)(vaddr))
|
|
|
-#define xhci_read_mem64(vaddr) (*(uint64_t *)(vaddr))
|
|
|
+#define xhci_write_op_reg64(id, offset, value) (__write8b(xhci_hc[id].vbase_op + (offset), (value)))
|
|
|
|
|
|
/**
|
|
|
* @brief 计算中断寄存器组虚拟地址
|
|
|
* @param id 主机控制器id
|
|
|
* @param num xhci中断寄存器组号
|
|
|
*/
|
|
|
-#define xhci_calc_intr_vaddr(id, num) (xhci_hc[id].vbase + xhci_hc[id].rts_offset + XHCI_RT_IR0 + num * XHCI_IR_SIZE)
|
|
|
+#define xhci_calc_intr_vaddr(id, num) (xhci_hc[id].vbase + xhci_hc[id].rts_offset + XHCI_RT_IR0 + (num)*XHCI_IR_SIZE)
|
|
|
/**
|
|
|
* @brief 读取/写入中断寄存器
|
|
|
* @param id 主机控制器id
|
|
|
* @param num xhci中断寄存器组号
|
|
|
* @param intr_offset 寄存器在当前寄存器组中的偏移量
|
|
|
*/
|
|
|
-#define xhci_read_intr_reg32(id, num, intr_offset) (*(uint32_t *)(xhci_calc_intr_vaddr(id, num) + intr_offset))
|
|
|
-#define xhci_write_intr_reg32(id, num, intr_offset, value) (*(uint32_t *)(xhci_calc_intr_vaddr(id, num) + intr_offset) = value)
|
|
|
-#define xhci_read_intr_reg64(id, num, intr_offset) (*(uint64_t *)(xhci_calc_intr_vaddr(id, num) + intr_offset))
|
|
|
-#define xhci_write_intr_reg64(id, num, intr_offset, value) (*(uint64_t *)(xhci_calc_intr_vaddr(id, num) + intr_offset) = value)
|
|
|
+#define xhci_read_intr_reg32(id, num, intr_offset) (__read4b(xhci_calc_intr_vaddr(id, num) + (intr_offset)))
|
|
|
+#define xhci_write_intr_reg32(id, num, intr_offset, value) (__write4b(xhci_calc_intr_vaddr(id, num) + (intr_offset), (value)))
|
|
|
+#define xhci_read_intr_reg64(id, num, intr_offset) (__read8b(xhci_calc_intr_vaddr(id, num) + (intr_offset)))
|
|
|
+#define xhci_write_intr_reg64(id, num, intr_offset, value) (__write8b(xhci_calc_intr_vaddr(id, num) + (intr_offset), (value)))
|
|
|
|
|
|
-#define xhci_is_aligned64(addr) ((addr & 0x3f) == 0) // 是否64bytes对齐
|
|
|
+#define xhci_is_aligned64(addr) (((addr)&0x3f) == 0) // 是否64bytes对齐
|
|
|
|
|
|
/**
|
|
|
* @brief 判断端口信息
|
|
@@ -172,9 +167,9 @@ static int xhci_hc_find_available_id()
|
|
|
*/
|
|
|
static __always_inline void xhci_get_trb(struct xhci_TRB_t *trb, const uint64_t address)
|
|
|
{
|
|
|
- trb->param = xhci_read_mem64(address);
|
|
|
- trb->status = xhci_read_mem32(address + 8);
|
|
|
- trb->command = xhci_read_mem32(address + 12);
|
|
|
+ trb->param = __read8b(address);
|
|
|
+ trb->status = __read4b(address + 8);
|
|
|
+ trb->command = __read4b(address + 12);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -185,9 +180,9 @@ static __always_inline void xhci_get_trb(struct xhci_TRB_t *trb, const uint64_t
|
|
|
*/
|
|
|
static __always_inline void xhci_set_trb(struct xhci_TRB_t *trb, const uint64_t address)
|
|
|
{
|
|
|
- xhci_write_mem64(address, trb->param);
|
|
|
- xhci_write_mem32(address + 8, trb->status);
|
|
|
- xhci_write_mem32(address + 12, trb->command);
|
|
|
+ __write8b(address, trb->param);
|
|
|
+ __write4b(address + 8, trb->status);
|
|
|
+ __write4b(address + 12, trb->command);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -781,7 +776,7 @@ void xhci_hc_irq_handler(uint64_t irq_num, uint64_t cid, struct pt_regs *regs)
|
|
|
{
|
|
|
case TRB_TYPE_TRANS_EVENT: // 当前 event trb是 transfer event TRB
|
|
|
// If SPD was encountered in this TD, comp_code will be SPD, else it should be SUCCESS (specs 4.10.1.1)
|
|
|
- xhci_write_mem32(phys_2_virt(event_trb.param), (event_trb.status | XHCI_IRQ_DONE)); // return code + bytes *not* transferred
|
|
|
+ __write4b((uint64_t)phys_2_virt(event_trb.param), (event_trb.status | XHCI_IRQ_DONE)); // return code + bytes *not* transferred
|
|
|
break;
|
|
|
|
|
|
default:
|
|
@@ -841,6 +836,7 @@ static int xhci_reset_port(const int id, const int port)
|
|
|
io_mfence();
|
|
|
// 确保端口的status被清0
|
|
|
xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | XHCI_PORTUSB_CHANGE_BITS);
|
|
|
+ // kdebug("to reset timeout;");
|
|
|
io_mfence();
|
|
|
// 重置当前端口
|
|
|
if (XHCI_PORT_IS_USB3(id, port))
|
|
@@ -849,13 +845,14 @@ static int xhci_reset_port(const int id, const int port)
|
|
|
xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | (1 << 4));
|
|
|
|
|
|
retval = -ETIMEDOUT;
|
|
|
-
|
|
|
+ // kdebug("to wait reset timeout;");
|
|
|
// 等待portsc的port reset change位被置位,说明reset完成
|
|
|
int timeout = 200;
|
|
|
while (timeout)
|
|
|
{
|
|
|
io_mfence();
|
|
|
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
|
|
|
+ // kdebug("val=%#010lx", val);
|
|
|
io_mfence();
|
|
|
if (XHCI_PORT_IS_USB3(id, port) && (val & (1 << 31)) == 0)
|
|
|
break;
|
|
@@ -872,13 +869,15 @@ static int xhci_reset_port(const int id, const int port)
|
|
|
if (timeout > 0)
|
|
|
{
|
|
|
// 等待恢复
|
|
|
- usleep(USB_TIME_RST_REC * 1000);
|
|
|
+ usleep(USB_TIME_RST_REC * 100);
|
|
|
+ // kdebug("to check if reset ok");
|
|
|
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
|
|
|
io_mfence();
|
|
|
|
|
|
// 如果reset之后,enable bit仍然是1,那么说明reset成功
|
|
|
if (val & (1 << 1))
|
|
|
{
|
|
|
+ // kdebug("reset ok");
|
|
|
retval = 0;
|
|
|
io_mfence();
|
|
|
// 清除status change bit
|
|
@@ -888,7 +887,7 @@ static int xhci_reset_port(const int id, const int port)
|
|
|
else
|
|
|
retval = -1;
|
|
|
}
|
|
|
-
|
|
|
+ // kdebug("reset ok!");
|
|
|
// 如果usb2端口成功reset,则处理该端口的active状态
|
|
|
if (retval == 0 && XHCI_PORT_IS_USB2(id, port))
|
|
|
{
|
|
@@ -928,7 +927,7 @@ static uint64_t xhci_initialize_slot(const int id, const int slot_id, const int
|
|
|
uint64_t device_context_vaddr = (uint64_t)kzalloc(xhci_hc[id].context_size * 2, 0);
|
|
|
// kdebug("slot id=%d, device_context_vaddr=%#018lx, port=%d", slot_id, device_context_vaddr, port);
|
|
|
// 写到数组中
|
|
|
- xhci_write_mem64(xhci_hc[id].dcbaap_vaddr + (slot_id * sizeof(uint64_t)), virt_2_phys(device_context_vaddr));
|
|
|
+ __write8b(xhci_hc[id].dcbaap_vaddr + (slot_id * sizeof(uint64_t)), virt_2_phys(device_context_vaddr));
|
|
|
|
|
|
slot_ctx.entries = 1;
|
|
|
slot_ctx.speed = speed;
|
|
@@ -1009,7 +1008,7 @@ static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int s
|
|
|
uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 32, 0);
|
|
|
|
|
|
// 置位input control context和slot context的add bit
|
|
|
- xhci_write_mem32(input_ctx_buffer + 4, 0x3);
|
|
|
+ __write4b(input_ctx_buffer + 4, 0x3);
|
|
|
|
|
|
// 拷贝slot上下文和control ep上下文到输入上下文中
|
|
|
__write_slot(input_ctx_buffer + xhci_hc[id].context_size, (struct xhci_slot_context_t *)slot_vaddr);
|
|
@@ -1198,9 +1197,9 @@ static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr)
|
|
|
int timer = 500;
|
|
|
while (timer)
|
|
|
{
|
|
|
- if (xhci_read_mem32(status_vaddr) & XHCI_IRQ_DONE)
|
|
|
+ if (__read4b(status_vaddr) & XHCI_IRQ_DONE)
|
|
|
{
|
|
|
- uint32_t status = xhci_read_mem32(status_vaddr);
|
|
|
+ uint32_t status = __read4b(status_vaddr);
|
|
|
// 判断完成码
|
|
|
switch (xhci_get_comp_code(status))
|
|
|
{
|
|
@@ -1349,15 +1348,17 @@ static int xhci_get_descriptor(const int id, const int port_id)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ kdebug("to init slot");
|
|
|
// 初始化接口的上下文
|
|
|
uint64_t slot_vaddr = xhci_initialize_slot(id, slot_id, port_id, speed, max_packet);
|
|
|
|
|
|
+ kdebug("to set address");
|
|
|
// 发送 address_device命令
|
|
|
retval = xhci_set_address(id, slot_vaddr, slot_id, true);
|
|
|
if (retval != 0)
|
|
|
return retval;
|
|
|
|
|
|
+ kdebug("to ctrl in");
|
|
|
// 发送用于 “get_descriptor” 的数据包。
|
|
|
count = xhci_control_in(id, &dev_desc, 8, slot_id, max_packet);
|
|
|
if (unlikely(count == 0))
|
|
@@ -1370,13 +1371,16 @@ static int xhci_get_descriptor(const int id, const int port_id)
|
|
|
*/
|
|
|
|
|
|
// 重置当前端口
|
|
|
+ kdebug("to reset");
|
|
|
xhci_reset_port(id, port_id);
|
|
|
|
|
|
// 再次发送 set_address命令
|
|
|
+ kdebug("to set addr again");
|
|
|
retval = xhci_set_address(id, slot_vaddr, slot_id, false);
|
|
|
if (retval != 0)
|
|
|
return retval;
|
|
|
|
|
|
+ kdebug("to ctrl in again");
|
|
|
count = xhci_control_in(id, &dev_desc, 18, slot_id, max_packet);
|
|
|
if (unlikely(count == 0))
|
|
|
return -EAGAIN;
|
|
@@ -1441,10 +1445,12 @@ static int xhci_hc_start_ports(int id)
|
|
|
{
|
|
|
if (XHCI_PORT_IS_USB2(id, i) && XHCI_PORT_IS_ACTIVE(id, i))
|
|
|
{
|
|
|
+ // kdebug("initializing usb2: %d", i);
|
|
|
// reset该端口
|
|
|
if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功,就获取它的描述符
|
|
|
// 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的
|
|
|
{
|
|
|
+ // kdebug("reset ok");
|
|
|
if (xhci_get_descriptor(id, i) == 0)
|
|
|
++cnt;
|
|
|
else
|
|
@@ -1537,9 +1543,9 @@ static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring)
|
|
|
uint64_t origin_trb_vaddr = xhci_hc[id].cmd_trb_vaddr;
|
|
|
|
|
|
// 必须先写入参数和状态数据,最后写入command
|
|
|
- xhci_write_mem64(xhci_hc[id].cmd_trb_vaddr, trb->param); // 参数
|
|
|
- xhci_write_mem32(xhci_hc[id].cmd_trb_vaddr + 8, trb->status); // 状态
|
|
|
- xhci_write_mem32(xhci_hc[id].cmd_trb_vaddr + 12, trb->command | xhci_hc[id].cmd_trb_cycle); // 命令
|
|
|
+ __write8b(xhci_hc[id].cmd_trb_vaddr, trb->param); // 参数
|
|
|
+ __write4b(xhci_hc[id].cmd_trb_vaddr + 8, trb->status); // 状态
|
|
|
+ __write4b(xhci_hc[id].cmd_trb_vaddr + 12, trb->command | xhci_hc[id].cmd_trb_cycle); // 命令
|
|
|
|
|
|
xhci_hc[id].cmd_trb_vaddr += sizeof(struct xhci_TRB_t); // 跳转到下一个trb
|
|
|
|
|
@@ -1564,7 +1570,7 @@ static int xhci_send_command(int id, struct xhci_TRB_t *trb, const bool do_ring)
|
|
|
|
|
|
// Now wait for the interrupt to happen
|
|
|
// We use bit 31 of the command dword since it is reserved
|
|
|
- while (timer && ((xhci_read_mem32(origin_trb_vaddr + 8) & XHCI_IRQ_DONE) == 0))
|
|
|
+ while (timer && ((__read4b(origin_trb_vaddr + 8) & XHCI_IRQ_DONE) == 0))
|
|
|
{
|
|
|
usleep(1000);
|
|
|
--timer;
|