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:
+24
-3
@@ -1,12 +1,12 @@
|
||||
#include "src/kernel/xhci.h"
|
||||
#include "src/kernel/log.h"
|
||||
#include "src/kernel/memory.h"
|
||||
#include "src/kernel/panic.h"
|
||||
#include "src/kernel/pci.h"
|
||||
#include "src/kernel/stream.h"
|
||||
#include "src/lib/layout.h"
|
||||
#include "src/lib/memory.h"
|
||||
#include "src/lib/util.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define XHCI_PCI_CLASS 0x0C
|
||||
#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_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_SCRATCHPAD_BUFFERS(c) (BITS_R((c)->hcsparams2, 31, 27) << 5 | BITS_R((c)->hcsparams2, 4, 0))
|
||||
|
||||
typedef volatile struct __attribute__((packed)) {
|
||||
uint32_t usbcmd;
|
||||
@@ -96,6 +97,8 @@ static xhci_db_regs *db_regs;
|
||||
|
||||
#define MAX_SLOTS 32
|
||||
|
||||
static void *scratchpads[32];
|
||||
|
||||
static void *dcbaa[MAX_SLOTS + 1] __attribute__((aligned(PAGE_SIZE)));
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
@@ -408,6 +411,13 @@ void xhci_init() {
|
||||
RING_WRAP(cmd);
|
||||
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...");
|
||||
XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS);
|
||||
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);
|
||||
|
||||
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);
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
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)
|
||||
;
|
||||
LOG_VAL_TRACE(&port_regs[port].portsc, "%x");
|
||||
LOG_VAL_TRACE(port_regs[port].portsc, "%x");
|
||||
|
||||
LOG_LN_STEP("Enabling a slot...");
|
||||
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...");
|
||||
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);
|
||||
uint16_t size = max < cmd->status ? max : (uint16_t)cmd->status;
|
||||
memory_copy(PHYS_TO_VIRT(cmd->parameter), size, to);
|
||||
|
||||
LOG_VAL_TRACE(size, "%d");
|
||||
LOG_VAL_TRACE(*(uint64_t *)to, "%lx");
|
||||
|
||||
transferred = size;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user