更改xhci驱动程序对寄存器的读写范围。

This commit is contained in:
fslongjin 2022-09-01 21:47:34 +08:00
parent 33a1e2baad
commit 7d983bd5cb

View File

@ -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;