mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-15 17:16:47 +00:00
更改xhci驱动程序对寄存器的读写范围。
This commit is contained in:
parent
33a1e2baad
commit
7d983bd5cb
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user