diff --git a/Kernel/include/USB/XHCI.h b/Kernel/include/USB/XHCI.h index 79126a66..a8ffed50 100755 --- a/Kernel/include/USB/XHCI.h +++ b/Kernel/include/USB/XHCI.h @@ -325,7 +325,6 @@ class XHCIController : private PCIDevice { uint32_t rsvdZ[7]; // Reserved xhci_interrupter_t interrupters[]; } __attribute__((packed)) xhci_runtime_regs_t; - static_assert(offsetof(xhci_runtime_regs_t, interrupters) == 0x20); enum DoorbellTarget { DBTargetHostCommand = 0, @@ -343,7 +342,7 @@ class XHCIController : private PCIDevice { } typedef union { - uint64_t doorbell; + uint32_t doorbell; struct { uint32_t target : 8; // 0 for host command ring uint32_t rsvdZ : 8; @@ -654,22 +653,11 @@ class XHCIController : private PCIDevice { static_assert(XHCI_TRB_SIZE == sizeof(xhci_setup_trb_t)); static_assert(XHCI_TRB_SIZE == sizeof(xhci_normal_trb_t)); - struct Port { + struct XHCIPort { xhci_ext_cap_supported_protocol_t* protocol; xhci_port_regs_t* registers; }; - struct Device { - XHCIController* c; - - int port = -1; - int slot = -1; - - void AllocateSlot(); - - ALWAYS_INLINE Device(XHCIController* c) : c(c) {} - }; - struct CommandCompletionEvent { Semaphore completion = Semaphore(0); union { @@ -678,14 +666,50 @@ class XHCIController : private PCIDevice { }; }; - struct XHCIEventRingSegment { - xhci_event_ring_segment_table_entry_t* entry; // Entry given to the xHC + struct CommandRing { + XHCIController* hcd; - uint64_t segmentPhys; // The physical address of the segment itself - xhci_event_trb_t* segment; // The segment itself + uintptr_t physicalAddr; + xhci_trb_t* ring = nullptr; + unsigned enqueueIndex = 0; + unsigned maxIndex = 0; + bool cycleState = 1; - size_t size; // Segment size in TRB entries - }; + lock_t lock = 0; + CommandCompletionEvent* events = nullptr; + + CommandRing(XHCIController* c); + + void SendCommandRaw(void* cmd); + xhci_command_completion_event_trb_t SendCommand(void* cmd); + } commandRing = CommandRing(this); + + struct EventRingSegment { + uintptr_t physicalAddr; + xhci_event_trb_t* segment = nullptr; + + uint32_t size; + } eventRingSegment; + + struct EventRing { + XHCIController* hcd; + + uintptr_t segmentsPhys; + xhci_event_ring_segment_table_entry_t* segmentTable; + EventRingSegment* segments; + + uint32_t segmentCount = 1; + uint32_t dequeueIndex = 0; + + bool cycleState = 1; // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it + // to ‘1’ and toggling it every time the Event Ring Dequeue Pointer wraps back to + // the beginning of the Event Ring. If the Cycle bit of the Event TRB pointed to by + // the Event Ring Dequeue Pointer equals CCS, then the Event TRB is a valid event. + + EventRing(XHCIController* c); + + bool Dequeue(xhci_event_trb_t* outTRB); + } eventRing = EventRing(this); uintptr_t xhciBaseAddress; uintptr_t xhciVirtualAddress; @@ -698,38 +722,10 @@ class XHCIController : private PCIDevice { xhci_doorbell_register_t* doorbellRegs; xhci_interrupter_t* interrupter; - uintptr_t eventRingSegmentTablePhys = 0; - xhci_event_ring_segment_table_entry_t* eventRingSegmentTable = nullptr; - - unsigned eventRingSegmentTableSize = 0; - unsigned eventRingDequeue = 0; - XHCIEventRingSegment* eventRingSegments = nullptr; - bool eventRingCycleState = true; // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it - // to ‘1’ and toggling it every time the Event Ring Dequeue Pointer wraps back to - // the beginning of the Event Ring. If the Cycle bit of the Event TRB pointed to by - // the Event Ring Dequeue Pointer equals CCS, then the Event TRB is a valid event. uintptr_t devContextBaseAddressArrayPhys = 0; uint64_t* devContextBaseAddressArray = nullptr; - struct CommandRing { - XHCIController* hcd; - - uintptr_t physicalAddr; - xhci_trb_t* ring = nullptr; - unsigned enqueueIndex = 0; - unsigned maxIndex = 0; - bool cycleState = 1; - - lock_t lock; - CommandCompletionEvent* events = nullptr; - - ALWAYS_INLINE CommandRing(XHCIController* c) : hcd(c) {} - - void SendCommandRaw(void* cmd); - xhci_command_completion_event_trb_t SendCommand(void* cmd); - } commandRing = CommandRing(this); - uintptr_t scratchpadBuffersPhys = 0; uint64_t* scratchpadBuffers = nullptr; @@ -740,8 +736,7 @@ class XHCIController : private PCIDevice { uint8_t controllerIRQ = 0xFF; Vector protocols; - Port* ports; - List m_devices; + XHCIPort* ports; bool TakeOwnership(); @@ -756,4 +751,4 @@ class XHCIController : private PCIDevice { Status controllerStatus = ControllerNotInitialized; }; -} // namespace USB +} // namespace USB \ No newline at end of file diff --git a/Kernel/src/USB/XHCI.cpp b/Kernel/src/USB/XHCI.cpp index 4cd91962..392b90c4 100755 --- a/Kernel/src/USB/XHCI.cpp +++ b/Kernel/src/USB/XHCI.cpp @@ -79,7 +79,13 @@ XHCIController::XHCIController(const PCIInfo& dev) : PCIDevice(dev) { } } - assert((opRegs->usbStatus & (USB_STS_CNR | USB_STS_HCH)) == USB_STS_HCH); + controllerIRQ = AllocateVector(PCIVectorAny); + if (controllerIRQ == 0xFF) { + Log::Error("[XHCI] Failed to allocate IRQ!"); + return; + } + + IDT::RegisterInterruptHandler(controllerIRQ, reinterpret_cast(&XHCIIRQHandler), this); devContextBaseAddressArrayPhys = Memory::AllocatePhysicalMemoryBlock(); devContextBaseAddressArray = reinterpret_cast(Memory::GetIOMapping(devContextBaseAddressArrayPhys)); @@ -103,38 +109,24 @@ XHCIController::XHCIController(const PCIInfo& dev) : PCIDevice(dev) { devContextBaseAddressArray[0] = scratchpadBuffersPhys; } - controllerIRQ = AllocateVector(PCIVectorAny); - if (controllerIRQ == 0xFF) { - Log::Error("[XHCI] Failed to allocate IRQ!"); - return; - } - - IDT::RegisterInterruptHandler(controllerIRQ, reinterpret_cast(&XHCIIRQHandler), this); - - commandRing.ring = reinterpret_cast(Memory::KernelAllocate4KPages(1)); - commandRing.physicalAddr = Memory::AllocatePhysicalMemoryBlock(); - Memory::KernelMapVirtualMemory4K(commandRing.physicalAddr, reinterpret_cast(commandRing.ring), 1, - PAGE_PRESENT | PAGE_WRITABLE | PAGE_CACHE_DISABLED); - - commandRing.maxIndex = PAGE_SIZE_4K / XHCI_TRB_SIZE; - memset(commandRing.ring, 0, PAGE_SIZE_4K); - - // Initialize an array of completion events - commandRing.events = new CommandCompletionEvent[commandRing.maxIndex]; - opRegs->cmdRingCtl = 0; // Clear everything opRegs->cmdRingCtl = commandRing.physicalAddr | 1; + //opRegs->deviceNotificationControl = 2; // FUNCTION_WAKE notification, all others should be handled automatically + maxSlots = 40; if (maxSlots > capRegs->MaxSlots()) { maxSlots = capRegs->MaxSlots(); } - - opRegs->SetMaxSlotsEnabled(maxSlots); - ports = new Port[capRegs->MaxPorts()]; - - eventRingSegmentTablePhys = Memory::AllocatePhysicalMemoryBlock(); + ports = new XHCIPort[capRegs->MaxPorts()]; + + InitializeProtocols(); + + interrupter = &runtimeRegs->interrupters[0]; + // interrupter->intModerationInterval = 4000; // (~1ms) + + /*eventRingSegmentTablePhys = Memory::AllocatePhysicalMemoryBlock(); eventRingSegmentTable = reinterpret_cast(Memory::KernelAllocate4KPages(1)); Memory::KernelMapVirtualMemory4K(eventRingSegmentTablePhys, reinterpret_cast(eventRingSegmentTable), 1, PAGE_PRESENT | PAGE_WRITABLE | PAGE_CACHE_DISABLED); @@ -142,10 +134,6 @@ XHCIController::XHCIController(const PCIInfo& dev) : PCIDevice(dev) { eventRingSegmentTableSize = 1; // For now we support one segment // PAGE_SIZE_4K / XHCI_EVENT_RING_SEGMENT_TABLE_ENTRY_SIZE; - - int erstMax = 1 << capRegs->ERSTMax(); - assert(eventRingSegmentTableSize <= erstMax); - eventRingSegments = new XHCIEventRingSegment[eventRingSegmentTableSize]; for (unsigned i = 0; i < eventRingSegmentTableSize; i++) { xhci_event_ring_segment_table_entry_t* entry = &eventRingSegmentTable[i]; @@ -163,37 +151,32 @@ XHCIController::XHCIController(const PCIInfo& dev) : PCIDevice(dev) { entry->ringSegmentSize = PAGE_SIZE_4K / XHCI_TRB_SIZE; // Comes down to 256 TRBs per segment segment->size = PAGE_SIZE_4K / XHCI_TRB_SIZE; } - - eventRingDequeue = 0; - eventRingCycleState = true; - - assert(!(opRegs->usbStatus & (USB_STS_HCE))); + eventRingDequeue = eventRingSegments[0].segment; - interrupter = &runtimeRegs->interrupters[0]; - interrupter->intModerationInterval = 0; // Disable interrupt moderation - // Setting ERDP busy clears it interrupter->eventRingSegmentTableSize = eventRingSegmentTableSize; - interrupter->eventRingDequeuePointer = eventRingSegments[0].segmentPhys | XHCI_INT_ERDP_BUSY; interrupter->eventRingSegmentTableBaseAddress = eventRingSegmentTablePhys; - interrupter->interruptEnable = 1; - interrupter->interruptPending = 1; + interrupter->eventRingDequeuePointer = reinterpret_cast(eventRingSegments[0].segment); + opRegs->SetMaxSlotsEnabled(maxSlots);*/ - assert(!(opRegs->usbStatus & (USB_STS_HCE))); + opRegs->SetMaxSlotsEnabled(maxSlots); Log::Info("[XHCI] Interface version: %x, Page size: %d, Operational registers offset: %x, Runtime registers " - "offset: %x, Doorbell registers offset: %x, Supported ERST entries: %d", - capRegs->hciVersion, opRegs->pageSize, capRegs->capLength, capRegs->rtsOff, capRegs->dbOff, erstMax); + "offset: %x, Doorbell registers offset: %x", + capRegs->hciVersion, opRegs->pageSize, capRegs->capLength, capRegs->rtsOff, capRegs->dbOff); if (debugLevelXHCI >= DebugLevelNormal) { - Log::Info("[XHCI] MaxSlots: %x, Max Scratchpad Buffers: %x", maxSlots, + Log::Info("[XHCI] MaxSlots: %x, Max Scratchpad Buffers: %x", capRegs->MaxSlots(), capRegs->MaxScratchpadBuffers()); } - - InitializeProtocols(); - opRegs->usbStatus = USB_STS_PCD | USB_STS_EINT | USB_STS_HSE; - assert(!(opRegs->usbCommand & USB_CMD_RS)); + interrupter->interruptEnable = 1; + interrupter->interruptPending = 1; + interrupter->eventRingSegmentTableSize = eventRing.segmentCount; + interrupter->eventRingSegmentTableBaseAddress = eventRing.segmentsPhys; + interrupter->eventRingDequeuePointer = reinterpret_cast(eventRing.segments[0].physicalAddr) | XHCI_INT_ERDP_BUSY; + opRegs->usbStatus |= USB_STS_EINT; + opRegs->usbCommand |= USB_CMD_HSEE | USB_CMD_INTE | USB_CMD_RS; { int timer = 20; @@ -206,23 +189,56 @@ XHCIController::XHCIController(const PCIInfo& dev) : PCIDevice(dev) { } } - interrupter->interruptEnable = 1; - interrupter->interruptPending = 1; - opRegs->usbStatus |= USB_STS_EINT; - - assert(!(opRegs->usbStatus & (USB_STS_HCH))); - assert(!(opRegs->usbStatus & (USB_STS_CNR))); - assert(!(opRegs->usbStatus & (USB_STS_HSE))); - assert(!(opRegs->usbStatus & (USB_STS_HCE))); - xhci_noop_command_trb_t testCommand; memset(&testCommand, 0, sizeof(xhci_noop_command_trb_t)); testCommand.trbType = TRBTypes::TRBTypeNoOpCommand; testCommand.cycleBit = 1; + + Log::Info("sending noop"); + commandRing.SendCommandRaw(&testCommand); + doorbellRegs[0].doorbell = 0; + Log::Info("sent noop"); + + commandRing.SendCommandRaw(&testCommand); + commandRing.SendCommandRaw(&testCommand); + doorbellRegs[0].doorbell = 0; commandRing.SendCommandRaw(&testCommand); + doorbellRegs[0].doorbell = 0; + commandRing.SendCommandRaw(&testCommand); + doorbellRegs[0].doorbell = 0; + commandRing.SendCommandRaw(&testCommand); + + commandRing.SendCommandRaw(&testCommand); + doorbellRegs[0].doorbell = 0; + + InitializePorts(); +} + +XHCIController::CommandRing::CommandRing(XHCIController* c) : hcd(c) { + physicalAddr = Memory::AllocatePhysicalMemoryBlock(); + ring = (xhci_trb_t*)Memory::KernelAllocate4KPages(1); - doorbellRegs[0].target = 0; - //InitializePorts(); + Memory::KernelMapVirtualMemory4K(physicalAddr, reinterpret_cast(ring), 1, + PAGE_PRESENT | PAGE_WRITABLE | PAGE_CACHE_DISABLED); + + memset(ring, 0, PAGE_SIZE_4K); + + enqueueIndex = 0; + maxIndex = PAGE_SIZE_4K / XHCI_TRB_SIZE; + maxIndex--; + + auto* trb = (xhci_link_trb_t*)(&ring[maxIndex]); + memset(trb, 0, sizeof(xhci_link_trb_t)); + + trb->trbType = TRBTypeLink; + trb->cycleBit = 1; + trb->interrupterTarget = 0; + trb->interruptOnCompletion = 1; + trb->segmentPtr = physicalAddr; + trb->toggleCycle = 1; + trb->chainBit = 0; + + events = new CommandCompletionEvent[maxIndex]; } void XHCIController::CommandRing::SendCommandRaw(void* data) { @@ -238,23 +254,6 @@ void XHCIController::CommandRing::SendCommandRaw(void* data) { memcpy(&ring[enqueueIndex++], command, sizeof(xhci_trb_t)); if (enqueueIndex >= maxIndex - 1) { - xhci_link_trb_t lnkTrb; - - memset(&lnkTrb, 0, sizeof(xhci_link_trb_t)); - - if (cycleState) - lnkTrb.cycleBit = 1; - else - lnkTrb.cycleBit = 0; - - lnkTrb.interrupterTarget = 0; - lnkTrb.interruptOnCompletion = 1; - lnkTrb.segmentPtr = physicalAddr; - lnkTrb.toggleCycle = 1; - - ring[enqueueIndex] = *reinterpret_cast(&lnkTrb); - enqueueIndex = 0; - cycleState = !cycleState; } } @@ -276,35 +275,57 @@ XHCIController::xhci_command_completion_event_trb_t XHCIController::CommandRing: command->cycleBit = 0; ring[enqueueIndex++] = *command; + } + + hcd->doorbellRegs[0].doorbell = 0; - if (enqueueIndex >= maxIndex - 1) { - xhci_link_trb_t lnkTrb; + bool wasInterrupted = ev->completion.Wait(); + assert(!wasInterrupted); + + return ev->event; +} - memset(&lnkTrb, 0, sizeof(xhci_link_trb_t)); +XHCIController::EventRing::EventRing(XHCIController* c) : hcd(c) { + segmentCount = 1; - if (cycleState) - lnkTrb.cycleBit = 1; - else - lnkTrb.cycleBit = 0; + segmentsPhys = Memory::AllocatePhysicalMemoryBlock(); + segmentTable = (xhci_event_ring_segment_table_entry_t*)Memory::KernelAllocate4KPages(1); + Memory::KernelMapVirtualMemory4K(segmentsPhys, reinterpret_cast(segmentTable), 1, + PAGE_PRESENT | PAGE_WRITABLE | PAGE_CACHE_DISABLED); + memset(segmentTable, 0, PAGE_SIZE_4K); - lnkTrb.interrupterTarget = 0; - lnkTrb.interruptOnCompletion = 0; - lnkTrb.segmentPtr = physicalAddr; - lnkTrb.toggleCycle = 1; + segments = new EventRingSegment[segmentCount]; - ring[enqueueIndex] = *reinterpret_cast(&lnkTrb); - enqueueIndex = 0; + for (uint32_t i = 0; i < segmentCount; i++) { + segments[i].physicalAddr = Memory::AllocatePhysicalMemoryBlock(); + segments[i].segment = (xhci_event_trb_t*)Memory::KernelAllocate4KPages(1); + segments[i].size = PAGE_SIZE_4K / XHCI_TRB_SIZE; - cycleState = !cycleState; - } + Memory::KernelMapVirtualMemory4K(segments[i].physicalAddr, reinterpret_cast(segments[i].segment), 1, + PAGE_PRESENT | PAGE_WRITABLE | PAGE_CACHE_DISABLED); + + memset(segments[i].segment, 0, PAGE_SIZE_4K); + + segmentTable[i].ringSegmentBaseAddress = segments[i].physicalAddr; + segmentTable[i].ringSegmentSize = segments[i].size; } +} - hcd->doorbellRegs[0].target = 0; +bool XHCIController::EventRing::Dequeue(xhci_event_trb_t* trb) { + xhci_event_trb_t* ev = &segments[0].segment[dequeueIndex]; + if (!!ev->cycleBit == !!cycleState) { + *trb = *ev; - bool wasInterrupted = ev->completion.Wait(); - assert(!wasInterrupted); + dequeueIndex++; + if (dequeueIndex >= segments[0].size) { + dequeueIndex = 0; + cycleState = !cycleState; + } - return ev->event; + return true; + } + + return false; } void XHCIController::EnableSlot() { @@ -313,77 +334,39 @@ void XHCIController::EnableSlot() { trb.trbType = TRBTypes::TRBTypeEnableSlotCommand; - commandRing.SendCommandRaw(&trb); - doorbellRegs[0].target = 0; + commandRing.SendCommand(&trb); } void XHCIController::OnInterrupt() { Log::Info("[XHCI] Interrupt!"); - if(!(opRegs->usbStatus & USB_STS_HCH)){ - Log::Debug(debugLevelXHCI, DebugLevelNormal, "[XHCI] OnInterrupt: Controller Halted"); - } - - if(!(opRegs->usbStatus & USB_STS_EINT)) { + interrupter->interruptPending = 1; + + if (!(opRegs->usbStatus | USB_STS_EINT)) { return; } opRegs->usbStatus |= USB_STS_EINT; - if(interrupter->interruptPending){ - interrupter->interruptPending = 1; + xhci_event_trb_t ev; + if(eventRing.Dequeue(&ev)){ + Log::Info("recv event!"); } - if(!(interrupter->eventRingDequeuePointer & XHCI_INT_ERDP_BUSY)){ - return; // No events - } - - XHCIEventRingSegment* segment = &eventRingSegments[0]; - xhci_event_trb_t* event = &segment->segment[eventRingDequeue]; - - if (debugLevelXHCI >= DebugLevelVerbose) { - Log::Info("cycle: %Y event cycle: %Y", event->cycleBit, eventRingCycleState); - for (int i = 0; i < segment->size; i++) { - Log::Info("%d: cycle: %Y event cycle: %Y (TRB type: %x)", i, segment->segment[i].cycleBit, eventRingCycleState, segment->segment[i].trbType); - } - } - - while (!!event->cycleBit == !!eventRingCycleState) { - if (debugLevelXHCI >= DebugLevelVerbose) { - Log::Info("[XHCI] Received event (TRB Type: %x (%x))", event->trbType, - (((uint32_t*)event)[3] >> 10) & 0x3f); + for(int i = 0; i < eventRing.segments[0].size; i++){ + auto& trb = eventRing.segments[0].segment[i]; + if(trb.trbType == 0){ + continue; } - if (event->trbType == TRBTypeCommandCompletionEvent) { - ScopedSpinLock lockRing(commandRing.lock); - xhci_command_completion_event_trb_t* ccEvent = - reinterpret_cast(event); - - unsigned cmdIndex = (ccEvent->commandTRBPointer - commandRing.physicalAddr) / XHCI_TRB_SIZE; - assert(cmdIndex < commandRing.maxIndex); - - auto& ev = commandRing.events[cmdIndex]; - ev.event = *ccEvent; - ev.completion.Signal(); - } - - event++; - eventRingDequeue++; - if (eventRingDequeue && - !(eventRingDequeue % segment->size)) { // Check if we are at either beginning or end of ring segment - eventRingDequeue = 0; - event = segment->segment; - eventRingCycleState = !eventRingCycleState; - break; - } + Log::Info("cycle: %Y event cycle: %Y TRB type: %x", trb.cycleBit, eventRing.cycleState, trb.trbType); } - uintptr_t newPtr = reinterpret_cast(segment->segmentPhys) + eventRingDequeue * XHCI_TRB_SIZE; - - // Disable XHCI_INT_ERDP_BUSY - interrupter->eventRingDequeuePointer = (newPtr & ~64ULL) | XHCI_INT_ERDP_BUSY; + interrupter->eventRingDequeuePointer = + (reinterpret_cast(eventRing.segments[0].physicalAddr) + eventRing.dequeueIndex * XHCI_TRB_SIZE) | + XHCI_INT_ERDP_BUSY; interrupter->interruptPending = 0; - assert(interrupter->interruptEnable); + opRegs->usbStatus &= ~USB_STS_EINT; } bool XHCIController::TakeOwnership() { @@ -415,20 +398,18 @@ bool XHCIController::TakeOwnership() { } void XHCIController::InitializeProtocols() { - auto initializeProto = [&](xhci_ext_cap_supported_protocol_t* ptr) { - xhci_ext_cap_supported_protocol_t cap = *ptr; - + auto initializeProto = [&](xhci_ext_cap_supported_protocol_t* cap) { if (debugLevelXHCI) { - Log::Info("[XHCI] Initializing protocol \"%c%c%c%c\", Version: %hu%hu.%hu%hu, Port Range: %u-%u", - cap.name[0], cap.name[1], cap.name[2], cap.name[3], (cap.majorRevision >> 4), - (cap.majorRevision & 0xF), (cap.minorRevision >> 4), (cap.minorRevision & 0xF), cap.portOffset, - (cap.portOffset + cap.portCount)); + Log::Info("[XHCI] Initializing protocol \"%c%c%c%c\", Version: %u%u.%u%u, Port Range: %u-%u", cap->name[0], + cap->name[1], cap->name[2], cap->name[3], (cap->majorRevision >> 4), (cap->majorRevision & 0xF), + (cap->minorRevision >> 4), (cap->minorRevision & 0xF), cap->portOffset, + (cap->portOffset + cap->portCount)); } - protocols.add_back(ptr); + protocols.add_back(cap); - for (unsigned i = cap.portOffset; i < cap.portOffset + cap.portCount && i < capRegs->MaxPorts(); i++) { - ports[i].protocol = ptr; + for (unsigned i = cap->portOffset; i < cap->portOffset + cap->portCount && i < capRegs->MaxPorts(); i++) { + ports[i].protocol = cap; } }; @@ -436,8 +417,6 @@ void XHCIController::InitializeProtocols() { for (;;) { if (cap->capID == XHCIExtendedCapabilities::XHCIExtCapSupportedProtocol) { initializeProto(cap); - } else { - Log::Debug(debugLevelXHCI, DebugLevelVerbose, "[XHCI] Found cap: %d (%x)", cap->capID, cap->capID); } if (!cap->nextCap) { @@ -485,27 +464,8 @@ void XHCIController::InitializePorts() { if (debugLevelXHCI >= DebugLevelVerbose) { Log::Info("Port %i is enabled!", i); } - - Device* dev = new Device(this); - dev->port = i; - dev->AllocateSlot(); } } } } - -void XHCIController::Device::AllocateSlot() { - assert(port > 0); - assert(slot == -1); - - xhci_enable_slot_command_trb_t cmd = {}; - cmd.trbType = TRBTypeEnableSlotCommand; - cmd.slotType = 0; - - auto result = c->commandRing.SendCommand(&cmd); - - auto* cc = reinterpret_cast(&result); - Log::Info("[XHCI] Allocated slot: %d", (int)cc->slotID); -} - } // namespace USB