Finalize xHCI and USB modules

Scratchpad buffers allocation added to xHCI. Missing initialization steps
for keyboards - set configuration and set idle - added to USB. (Even
though they are specific to HID protocol, they go through USB command
endpoint, and with current module contents it's cleaner to have them
in USB module.)
This commit is contained in:
2026-08-25 21:20:53 +03:00
parent a3240d9316
commit 7d274da197
3 changed files with 43 additions and 11 deletions
+1
View File
@@ -170,6 +170,7 @@ static uint64_t stream_read(__attribute__((unused)) stream_t *self, uint64_t max
} }
buffer_length -= size; buffer_length -= size;
buffer_offset = (buffer_offset + size) % BUFFER_SIZE; buffer_offset = (buffer_offset + size) % BUFFER_SIZE;
return size; return size;
} }
+18 -8
View File
@@ -35,6 +35,8 @@ typedef struct __attribute__((packed)) {
#define USB_SETUP_RECIPIENT_OTHER 3 #define USB_SETUP_RECIPIENT_OTHER 3
#define USB_SETUP_GET_DESCRIPTOR 0x06 #define USB_SETUP_GET_DESCRIPTOR 0x06
#define USB_SETUP_SET_CONFIGURATION 0x09
#define USB_SETUP_SET_IDLE 0x0A
#define USB_SETUP_SET_PROTOCOL 0x0B #define USB_SETUP_SET_PROTOCOL 0x0B
#define USB_SETUP_DESCRIPTOR_TYPE_R(s) BITS_R((s)->w_value, 15, 8) #define USB_SETUP_DESCRIPTOR_TYPE_R(s) BITS_R((s)->w_value, 15, 8)
@@ -52,11 +54,6 @@ typedef struct __attribute__((packed)) {
#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02 #define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02
#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04 #define USB_DESCRIPTOR_TYPE_INTERFACE 0x04
#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05 #define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05
#define USB_DESCRIPTOR_TYPE_HID 0x21
#define USB_INTERFACE_HID_KEYBOARD_CLASS 0x3
#define USB_INTERFACE_HID_KEYBOARD_SUBCLASS 0x1
#define USB_INTERFACE_HID_KEYBOARD_PROTOCOL 0x1
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
usb_descriptor_base_t base; usb_descriptor_base_t base;
@@ -176,7 +173,6 @@ void usb_enumerate(stream_t *out) {
} }
xhci_slot_t slot = xhci_attach(port); xhci_slot_t slot = xhci_attach(port);
if (slot == (xhci_slot_t)-1) { if (slot == (xhci_slot_t)-1) {
continue; continue;
} }
@@ -206,7 +202,6 @@ xhci_port_t usb_find_by_interface(uint8_t class, uint8_t subclass, uint8_t proto
} }
xhci_slot_t slot = xhci_attach(port); xhci_slot_t slot = xhci_attach(port);
if (slot == (xhci_slot_t)-1) { if (slot == (xhci_slot_t)-1) {
continue; continue;
} }
@@ -239,6 +234,14 @@ xhci_endpoint_t usb_open_endpoint(xhci_slot_t slot, uint8_t type, uint16_t max_p
scan_device(slot, &device, &configuration, &interface, &endpoint); scan_device(slot, &device, &configuration, &interface, &endpoint);
usb_setup_t setup; usb_setup_t setup;
memory_set(0, sizeof(setup), &setup);
USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D);
USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_STANDARD);
USB_SETUP_RECIPIENT_W(&setup, USB_SETUP_RECIPIENT_DEVICE);
setup.b_request = USB_SETUP_SET_CONFIGURATION;
setup.w_value = configuration.configuration_value;
xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0);
memory_set(0, sizeof(setup), &setup); memory_set(0, sizeof(setup), &setup);
USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D); USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D);
USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS); USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS);
@@ -246,9 +249,16 @@ xhci_endpoint_t usb_open_endpoint(xhci_slot_t slot, uint8_t type, uint16_t max_p
setup.b_request = USB_SETUP_SET_PROTOCOL; setup.b_request = USB_SETUP_SET_PROTOCOL;
xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0); xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0);
memory_set(0, sizeof(setup), &setup);
USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D);
USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS);
USB_SETUP_RECIPIENT_W(&setup, USB_SETUP_RECIPIENT_INTERFACE);
setup.b_request = USB_SETUP_SET_IDLE;
xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0);
ASSERT(endpoint.max_packet_size == max_packet_size, "usb_open_endpoint: Unexpected max packet size."); ASSERT(endpoint.max_packet_size == max_packet_size, "usb_open_endpoint: Unexpected max packet size.");
return xhci_open_endpoint(slot, endpoint.endpoint_address, type, endpoint.max_packet_size, endpoint.interval); return xhci_open_endpoint(slot, endpoint.endpoint_address, type, endpoint.max_packet_size, 7);
} }
uint16_t usb_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t max, void *to) { uint16_t usb_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t max, void *to) {
+24 -3
View File
@@ -1,12 +1,12 @@
#include "src/kernel/xhci.h" #include "src/kernel/xhci.h"
#include "src/kernel/log.h" #include "src/kernel/log.h"
#include "src/kernel/memory.h"
#include "src/kernel/panic.h" #include "src/kernel/panic.h"
#include "src/kernel/pci.h" #include "src/kernel/pci.h"
#include "src/kernel/stream.h" #include "src/kernel/stream.h"
#include "src/lib/layout.h" #include "src/lib/layout.h"
#include "src/lib/memory.h" #include "src/lib/memory.h"
#include "src/lib/util.h" #include "src/lib/util.h"
#include <stdint.h>
#define XHCI_PCI_CLASS 0x0C #define XHCI_PCI_CLASS 0x0C
#define XHCI_PCI_SUBCLASS 0x03 #define XHCI_PCI_SUBCLASS 0x03
@@ -29,6 +29,7 @@ typedef volatile struct __attribute__((packed)) {
#define XHCI_CAP_REGS_MAX_INTRS(c) BITS_R((c)->hcsparams1, 18, 8) #define XHCI_CAP_REGS_MAX_INTRS(c) BITS_R((c)->hcsparams1, 18, 8)
#define XHCI_CAP_REGS_MAX_PORTS(c) BITS_R((c)->hcsparams1, 31, 24) #define XHCI_CAP_REGS_MAX_PORTS(c) BITS_R((c)->hcsparams1, 31, 24)
#define XHCI_CAP_REGS_MAX_ERSTS(c) BITS_R((c)->hcsparams2, 7, 4) #define XHCI_CAP_REGS_MAX_ERSTS(c) BITS_R((c)->hcsparams2, 7, 4)
#define XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(c) (BITS_R((c)->hcsparams2, 31, 27) << 5 | BITS_R((c)->hcsparams2, 4, 0))
typedef volatile struct __attribute__((packed)) { typedef volatile struct __attribute__((packed)) {
uint32_t usbcmd; uint32_t usbcmd;
@@ -96,6 +97,8 @@ static xhci_db_regs *db_regs;
#define MAX_SLOTS 32 #define MAX_SLOTS 32
static void *scratchpads[32];
static void *dcbaa[MAX_SLOTS + 1] __attribute__((aligned(PAGE_SIZE))); static void *dcbaa[MAX_SLOTS + 1] __attribute__((aligned(PAGE_SIZE)));
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
@@ -408,6 +411,13 @@ void xhci_init() {
RING_WRAP(cmd); RING_WRAP(cmd);
XHCI_TRB_CYCLE_W(&cmd_r[RING_LENGTH], cmd_r_cycle); XHCI_TRB_CYCLE_W(&cmd_r[RING_LENGTH], cmd_r_cycle);
LOG_LN_INFO("Setting up scratchpad buffers...");
ASSERT(XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(cap_regs) <= sizeof(scratchpads), "Too many scratchpad buffers expected.");
for (uint32_t i = 0; i < XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(cap_regs); i++) {
scratchpads[i] = memory_page_allocate();
}
dcbaa[0] = VIRT_TO_PHYS(scratchpads);
LOG_LN_INFO("Configuring controller..."); LOG_LN_INFO("Configuring controller...");
XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS); XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS);
op_regs->dcbaap = (uint64_t)VIRT_TO_PHYS(dcbaa); op_regs->dcbaap = (uint64_t)VIRT_TO_PHYS(dcbaa);
@@ -475,13 +485,17 @@ xhci_slot_t xhci_attach(xhci_port_t port) {
RING_WRAP(tsf); RING_WRAP(tsf);
LOG_LN_STEP("Resetting device..."); LOG_LN_STEP("Resetting device...");
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | 0x00FE0000;
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | (1 << 4); port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | (1 << 4);
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
while (XHCI_PORT_REGS_PR_R(&port_regs[port])) while (XHCI_PORT_REGS_PR_R(&port_regs[port]))
; ;
LOG_VAL_TRACE(&port_regs[port].portsc, "%x"); LOG_VAL_TRACE(port_regs[port].portsc, "%x");
while (!XHCI_PORT_REGS_PED(&port_regs[port]) && XHCI_PORT_REGS_PLL(&port_regs[port]) != 0) while (!XHCI_PORT_REGS_PED(&port_regs[port]) && XHCI_PORT_REGS_PLL(&port_regs[port]) != 0)
; ;
LOG_VAL_TRACE(&port_regs[port].portsc, "%x"); LOG_VAL_TRACE(port_regs[port].portsc, "%x");
LOG_LN_STEP("Enabling a slot..."); LOG_LN_STEP("Enabling a slot...");
xhci_trb_t cmd_es; xhci_trb_t cmd_es;
@@ -612,10 +626,17 @@ uint16_t xhci_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t
LOG_LN_STEP("Received transfer event, returning..."); LOG_LN_STEP("Received transfer event, returning...");
ep_processed_events++; ep_processed_events++;
LOG_VAL_TRACE(cmp->parameter, "%lx");
LOG_VAL_TRACE(cmp->status, "%x");
LOG_VAL_TRACE(cmp->control, "%x");
xhci_trb_t *cmd = PHYS_TO_VIRT(cmp->parameter); xhci_trb_t *cmd = PHYS_TO_VIRT(cmp->parameter);
uint16_t size = max < cmd->status ? max : (uint16_t)cmd->status; uint16_t size = max < cmd->status ? max : (uint16_t)cmd->status;
memory_copy(PHYS_TO_VIRT(cmd->parameter), size, to); memory_copy(PHYS_TO_VIRT(cmd->parameter), size, to);
LOG_VAL_TRACE(size, "%d");
LOG_VAL_TRACE(*(uint64_t *)to, "%lx");
transferred = size; transferred = size;
} }