diff --git a/kernel/driver/usb/usb.c b/kernel/driver/usb/usb.c index f9e8d9a3..42735745 100644 --- a/kernel/driver/usb/usb.c +++ b/kernel/driver/usb/usb.c @@ -17,7 +17,7 @@ static int usb_pdevs_count = 0; * @brief 初始化usb驱动程序 * */ -void usb_init() +int usb_init() { kinfo("Initializing usb driver..."); spin_init(&xhci_controller_init_lock); @@ -30,7 +30,7 @@ void usb_init() kwarn("There is no usb hardware in this computer!"); return; } - kdebug("usb_pdevs_count=%d",usb_pdevs_count); + kdebug("usb_pdevs_count=%d", usb_pdevs_count); // 初始化每个usb控制器 for (volatile int i = 0; i < usb_pdevs_count; ++i) { @@ -59,4 +59,5 @@ void usb_init() } } kinfo("Successfully initialized all usb host controllers!"); + return 0; } \ No newline at end of file diff --git a/kernel/driver/usb/usb.h b/kernel/driver/usb/usb.h index e1068b0a..728d9992 100644 --- a/kernel/driver/usb/usb.h +++ b/kernel/driver/usb/usb.h @@ -133,4 +133,4 @@ enum * @brief 初始化usb驱动程序 * */ -void usb_init(); \ No newline at end of file +int usb_init(); \ No newline at end of file diff --git a/kernel/driver/usb/xhci/xhci.c b/kernel/driver/usb/xhci/xhci.c index 33185c39..bcfe3cc8 100644 --- a/kernel/driver/usb/xhci/xhci.c +++ b/kernel/driver/usb/xhci/xhci.c @@ -47,9 +47,6 @@ static int xhci_data_stage(struct xhci_ep_ring_info_t *ep, uint64_t buf_vaddr, u static int xhci_status_stage(const int id, uint8_t direction, uint64_t status_buf_vaddr); static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr); -static struct xhci_ep_context_t ep_ctx = {0}; -struct xhci_slot_context_t slot_ctx = {0}; - hardware_intr_controller xhci_hc_intr_controller = { .enable = xhci_hc_irq_enable, @@ -732,7 +729,8 @@ void xhci_hc_irq_handler(uint64_t irq_num, uint64_t cid, struct pt_regs *regs) struct xhci_TRB_cmd_complete_t *event_trb_ptr = (struct xhci_TRB_cmd_complete_t *)&event_trb; if ((event_trb.command & (1 << 2)) == 0) // 当前event trb不是由于short packet产生的 { - + // kdebug("event_trb_ptr->code=%d", event_trb_ptr->code); + // kdebug("event_trb_ptr->TRB_type=%d", event_trb_ptr->TRB_type); switch (event_trb_ptr->code) // 判断它的完成码 { case TRB_COMP_TRB_SUCCESS: // trb执行成功,则将结果返回到对应的command ring的trb里面 @@ -813,9 +811,7 @@ static int xhci_reset_port(const int id, const int port) int retval = 0; // 相对于op寄存器基地址的偏移量 uint64_t port_status_offset = XHCI_OPS_PRS + port * 16; - // kdebug("to reset %d, portsc=%#010lx", port, (xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC))); - // kdebug("to reset %d, usbcmd=%#010lx", port, xhci_read_op_reg32(id, XHCI_OPS_USBCMD)); - // kdebug("to reset %d, usbsts=%#010lx", port, xhci_read_op_reg32(id, XHCI_OPS_USBSTS)); + io_mfence(); // 检查端口电源状态 if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0) @@ -847,20 +843,22 @@ static int xhci_reset_port(const int id, const int port) retval = -ETIMEDOUT; // kdebug("to wait reset timeout;"); // 等待portsc的port reset change位被置位,说明reset完成 - int timeout = 200; + int timeout = 100; 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 (val & (1 << 21)) + break; + // QEMU对usb的模拟有bug,因此需要检测这里 +#ifdef __QEMU_EMULATION__ + if (XHCI_PORT_IS_USB3(id, port) && (val & (1 << 31)) == 0) break; else if (XHCI_PORT_IS_USB2(id, port) && (val & (1 << 4)) == 0) break; - else if (val & (1 << 21)) - break; - +#endif --timeout; usleep(500); } @@ -870,10 +868,11 @@ static int xhci_reset_port(const int id, const int port) { // 等待恢复 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(); + // kdebug("to check if reset ok, val=%#010lx", val); + // 如果reset之后,enable bit仍然是1,那么说明reset成功 if (val & (1 << 1)) { @@ -928,7 +927,7 @@ static uint64_t xhci_initialize_slot(const int id, const int slot_id, const int // kdebug("slot id=%d, device_context_vaddr=%#018lx, port=%d", slot_id, device_context_vaddr, port); // 写到数组中 __write8b(xhci_hc[id].dcbaap_vaddr + (slot_id * sizeof(uint64_t)), virt_2_phys(device_context_vaddr)); - + struct xhci_slot_context_t slot_ctx = {0}; slot_ctx.entries = 1; slot_ctx.speed = speed; slot_ctx.route_string = 0; @@ -964,6 +963,7 @@ static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const in // 由于目前只实现获取设备的描述符,因此暂时只支持control ep if (type != USB_EP_CONTROL) return; + struct xhci_ep_context_t ep_ctx = {0}; memset(&ep_ctx, 0, sizeof(struct xhci_ep_context_t)); xhci_hc[id].control_ep_info.ep_ring_vbase = xhci_create_ring(XHCI_TRBS_PER_RING); @@ -1004,6 +1004,8 @@ static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const in static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int slot_id, const bool block) { int retval = 0; + struct xhci_slot_context_t slot; + struct xhci_ep_context_t ep; // 创建输入上下文缓冲区 uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 32, 0); @@ -1011,9 +1013,16 @@ static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int s __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); - __write_ep(id, input_ctx_buffer, 2, (struct xhci_ep_context_t *)(slot_vaddr + XHCI_EP_CONTROL * xhci_hc[id].context_size)); + // __write_ep(id, input_ctx_buffer, 2, &ep_ctx); + __read_from_slot(&slot, slot_vaddr); + __read_from_ep(id, slot_vaddr, 1, &ep); + ep.err_cnt = 3; + kdebug("slot.slot_state=%d, speed=%d, root hub port num=%d", slot.slot_state, slot.speed, slot.rh_port_num); + kdebug("ep.type=%d, max_packet=%d, dequeue_ptr=%#018lx", ep.ep_type, ep.max_packet_size, ep.tr_dequeue_ptr); + + __write_slot(input_ctx_buffer + xhci_hc[id].context_size, &slot); + __write_ep(id, input_ctx_buffer, 2, &ep); struct xhci_TRB_normal_t trb = {0}; trb.buf_paddr = virt_2_phys(input_ctx_buffer); @@ -1027,25 +1036,15 @@ static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int s if (unlikely(retval != 0)) { kerror("slotid:%d, address device failed", slot_id); - goto failed; } struct xhci_TRB_cmd_complete_t *trb_done = (struct xhci_TRB_cmd_complete_t *)&trb; - // kdebug("address slot: comp code=%d", trb_done->code); if (trb_done->code == TRB_COMP_TRB_SUCCESS) // 成功执行 { // 如果要从控制器获取刚刚设置的设备地址的话,可以在这里读取slot context - // ksuccess("slot %d successfully addressed.", slot_id); - struct xhci_slot_context_t slot; - struct xhci_ep_context_t ep; - __read_from_slot(&slot, slot_vaddr); - slot_ctx.slot_state = slot.slot_state; - slot_ctx.device_address = slot.device_address; - __read_from_ep(id, slot_vaddr, 1, &ep); - // kdebug("ep.ep_state=%d, slot_state=%d", ep.ep_state, slot.slot_state); - ep_ctx.ep_state = ep.ep_state; - ep_ctx.max_packet_size = ep.max_packet_size; + ksuccess("slot %d successfully addressed.", slot_id); + retval = 0; } else @@ -1323,12 +1322,13 @@ static int xhci_get_descriptor(const int id, const int port_id) */ struct xhci_TRB_normal_t trb = {0}; trb.TRB_type = TRB_TYPE_ENABLE_SLOT; - kdebug("to enable slot"); + // kdebug("to enable slot"); if (xhci_send_command(id, (struct xhci_TRB_t *)&trb, true) != 0) { kerror("portid:%d: send enable slot failed", port_id); return -ETIMEDOUT; } + // kdebug("send enable slot ok"); uint32_t slot_id = ((struct xhci_TRB_cmd_complete_t *)&trb)->slot_id; int16_t max_packet; @@ -1350,48 +1350,27 @@ static int xhci_get_descriptor(const int id, const int port_id) } } - - kdebug("speed=%d", speed); + // kdebug("speed=%d", speed); // 初始化接口的上下文 uint64_t slot_vaddr = xhci_initialize_slot(id, slot_id, port_id, speed, max_packet); - kdebug("set addr"); - // 发送 address_device命令 - retval = xhci_set_address(id, slot_vaddr, slot_id, true); + // kdebug("set addr again"); + // 再次发送 set_address命令 + // kdebug("to set addr again"); + retval = xhci_set_address(id, slot_vaddr, slot_id, false); if (retval != 0) return retval; - kdebug("crtl in"); - // 发送用于 “get_descriptor” 的数据包。 - count = xhci_control_in(id, &dev_desc, 8, slot_id, max_packet); + // kdebug("ctrl in again"); + + count = xhci_control_in(id, &dev_desc, 18, slot_id, max_packet); if (unlikely(count == 0)) return -EAGAIN; - /* TODO: if the dev_desc.max_packet was different than what we have as max_packet, you would need to change it here and in the slot context by doing a evaluate_slot_context call. */ - - kdebug("reset port"); - // 重置当前端口 - kdebug("to reset"); - xhci_reset_port(id, port_id); - - kdebug("set addr again"); - // 再次发送 set_address命令 - kdebug("to set addr again"); - retval = xhci_set_address(id, slot_vaddr, slot_id, false); - if (retval != 0) - return retval; - - - kdebug("ctrl in again"); - - count = xhci_control_in(id, &dev_desc, 18, slot_id, max_packet); - if (unlikely(count == 0)) - return -EAGAIN; - // print the descriptor printk(" Found USB Device:\n" " port: %i\n" @@ -1430,18 +1409,22 @@ static int xhci_hc_start_ports(int id) // 注意,这两个循环应该不能合并到一起,因为可能存在usb2端口offset在前,usb3端口在后的情况,那样的话就会出错 // 循环启动所有的usb3端口 - // for (int i = 0; i < xhci_hc[id].port_num; ++i) - for (int i = 0; i < 1; ++i) + for (int i = 0; i < xhci_hc[id].port_num; ++i) { if (XHCI_PORT_IS_USB3(id, i) && XHCI_PORT_IS_ACTIVE(id, i)) { io_mfence(); + // kdebug("to reset port %d, rflags=%#018lx", id, get_rflags()); + int rst_ret = xhci_reset_port(id, i); + // kdebug("reset done!, val=%d", rst_ret); // reset该端口 - if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功,就获取它的描述符 - // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 + if (likely(rst_ret == 0)) // 如果端口reset成功,就获取它的描述符 + // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 { + // kdebug("reset port %d ok", id); if (xhci_get_descriptor(id, i) == 0) ++cnt; + kdebug("usb3 port %d get desc ok", i); } } } @@ -1454,17 +1437,15 @@ static int xhci_hc_start_ports(int id) { // kdebug("initializing usb2: %d", i); // reset该端口 - kdebug("to reset port %d, rflags=%#018lx", id, get_rflags()); + // kdebug("to reset port %d, rflags=%#018lx", i, get_rflags()); if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功,就获取它的描述符 // 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的 { - kdebug("reset port %d ok", id); + // kdebug("reset port %d ok", id); if (xhci_get_descriptor(id, i) == 0) ++cnt; - else - break; - kdebug("port %d get desc ok", id); + kdebug("USB2 port %d get desc ok", i); } } } @@ -1711,6 +1692,23 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) // 写入dcbaap xhci_write_op_reg64(cid, XHCI_OPS_DCBAAP, virt_2_phys(xhci_hc[cid].dcbaap_vaddr)); io_mfence(); + + // 创建scratchpad buffer array + uint32_t max_scratchpad_buf = (((uint32_t)hcs2.max_scratchpad_buf_HI5) << 5) | hcs2.max_scratchpad_buf_LO5; + kdebug("max scratchpad buffer=%d", max_scratchpad_buf); + if (max_scratchpad_buf > 0) + { + xhci_hc[cid].scratchpad_buf_array_vaddr = (uint64_t)kzalloc(sizeof(uint64_t) * max_scratchpad_buf, 0); + __write8b(xhci_hc[cid].dcbaap_vaddr, virt_2_phys(xhci_hc[cid].scratchpad_buf_array_vaddr)); + + // 创建scratchpad buffers + for (int i = 0; i < max_scratchpad_buf; ++i) + { + uint64_t buf_vaddr = kzalloc(xhci_hc[cid].page_size, 0); + __write8b(xhci_hc[cid].scratchpad_buf_array_vaddr, virt_2_phys(buf_vaddr)); + } + } + // 创建command ring xhci_hc[cid].cmd_ring_vaddr = xhci_create_ring(XHCI_CMND_RING_TRBS); xhci_hc[cid].cmd_trb_vaddr = xhci_hc[cid].cmd_ring_vaddr; diff --git a/kernel/driver/usb/xhci/xhci.h b/kernel/driver/usb/xhci/xhci.h index 46d1102a..5164a988 100644 --- a/kernel/driver/usb/xhci/xhci.h +++ b/kernel/driver/usb/xhci/xhci.h @@ -518,22 +518,26 @@ struct xhci_host_controller_t uint64_t vbase_op; // Operational registers 起始虚拟地址 uint32_t rts_offset; // Runtime Register Space offset uint32_t db_offset; // Doorbell offset - uint32_t ext_caps_off; // 扩展能力寄存器偏移量 - uint8_t context_size; // 设备上下文大小 - uint16_t port_num; // 总的端口数量 - uint8_t port_num_u2; // usb 2.0端口数量 - uint8_t port_num_u3; // usb 3端口数量 - uint32_t page_size; // page size - uint64_t dcbaap_vaddr; // Device Context Base Address Array Pointer的虚拟地址 - uint64_t cmd_ring_vaddr; // command ring的虚拟地址 - uint64_t cmd_trb_vaddr; // 下一个要写入的trb的虚拟地址 - uint64_t event_ring_vaddr; // event ring的虚拟地址 - uint64_t event_ring_table_vaddr; // event ring table的虚拟地址 - uint64_t current_event_ring_vaddr; // 下一个要读取的event TRB的虚拟地址 - uint8_t cmd_trb_cycle; // 当前command ring cycle - uint8_t current_event_ring_cycle; // 当前event ring cycle - struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针(由于端口offset是从1开始的,因此该数组第0项为空) - struct xhci_ep_ring_info_t control_ep_info; // 控制端点的信息 + + uint32_t ext_caps_off; // 扩展能力寄存器偏移量 + uint16_t port_num; // 总的端口数量 + uint8_t context_size; // 设备上下文大小 + uint8_t port_num_u2; // usb 2.0端口数量 + + uint8_t port_num_u3; // usb 3端口数量 + uint8_t current_event_ring_cycle; // 当前event ring cycle + uint8_t cmd_trb_cycle; // 当前command ring cycle + uint32_t page_size; // page size + + uint64_t dcbaap_vaddr; // Device Context Base Address Array Pointer的虚拟地址 + uint64_t cmd_ring_vaddr; // command ring的虚拟地址 + uint64_t cmd_trb_vaddr; // 下一个要写入的trb的虚拟地址 + uint64_t event_ring_vaddr; // event ring的虚拟地址 + uint64_t event_ring_table_vaddr; // event ring table的虚拟地址 + uint64_t current_event_ring_vaddr; // 下一个要读取的event TRB的虚拟地址 + uint64_t scratchpad_buf_array_vaddr; // 草稿行缓冲区数组的虚拟地址 + struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针(由于端口offset是从1开始的,因此该数组第0项为空) + struct xhci_ep_ring_info_t control_ep_info; // 控制端点的信息 }; // Common TRB types diff --git a/kernel/process/process.c b/kernel/process/process.c index e5845dc2..b26d7ed4 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -463,7 +463,9 @@ ul initial_kernel_thread(ul arg) { // kinfo("initial proc running...\targ:%#018lx", arg); fat32_init(); - usb_init(); + // 使用单独的内核线程来初始化usb驱动程序 + int usb_pid = kernel_thread(usb_init, 0, 0); + kinfo("LZ4 lib Version=%s", LZ4_versionString()); // 对一些组件进行单元测试 @@ -471,21 +473,14 @@ ul initial_kernel_thread(ul arg) ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_mutex, 0), + usb_pid, }; kinfo("Waiting test thread exit..."); // 等待测试进程退出 for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i) waitpid(tpid[i], NULL, NULL); kinfo("All test done."); - // pid_t p = fork(); - // if (p == 0) - // { - // kdebug("in subproc, rflags=%#018lx", get_rflags()); - // while (1) - // usleep(1000); - // } - // kdebug("subprocess pid=%d", p); // 准备切换到用户态 struct pt_regs *regs; diff --git a/kernel/time/sleep.c b/kernel/time/sleep.c index 10f3bedc..646780b7 100644 --- a/kernel/time/sleep.c +++ b/kernel/time/sleep.c @@ -26,18 +26,17 @@ void nanosleep_handler(void *pcb) */ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { - int64_t total_ns = rqtp->tv_nsec; - if (total_ns < 0 || total_ns >= 1000000000) + if (rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000) return -EINVAL; + // 对于小于500us的时间,使用spin/rdtsc来进行定时 - if (total_ns < 500000) + if (rqtp->tv_nsec < 500000) { - kdebug("use rdtsc to nanosleep"); - uint64_t expired_tsc = rdtsc() + (total_ns * Cpu_tsc_freq) / 1000000000; + uint64_t expired_tsc = rdtsc() + (((uint64_t)rqtp->tv_nsec) * Cpu_tsc_freq) / 1000000000; while (rdtsc() < expired_tsc) - pause(); + ; if (rmtp != NULL) { @@ -51,7 +50,7 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) struct timer_func_list_t *sleep_task = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0); memset(sleep_task, 0, sizeof(struct timer_func_list_t)); - timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, total_ns / 1000); + timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, rqtp->tv_nsec / 1000); timer_func_add(sleep_task); diff --git a/run.sh b/run.sh index 8b16b7fb..92ecc581 100755 --- a/run.sh +++ b/run.sh @@ -11,6 +11,13 @@ IA32_USE_QEMU=1 bochsrc="./bochsrc" ARCH="x86_64" +for i in "$@" +do + if [ $i == "--no-qemu" ];then + IA32_USE_QEMU=0 + fi +done + if [ ${IA32_USE_QEMU} == "1" ];then export EMULATOR=__QEMU_EMULATION__ else