diff --git a/sys/voyageurs/xhci/device_slot.cpp b/sys/voyageurs/xhci/device_slot.cpp index e69d537..413b10b 100644 --- a/sys/voyageurs/xhci/device_slot.cpp +++ b/sys/voyageurs/xhci/device_slot.cpp @@ -4,10 +4,13 @@ #include #include "xhci/trb.h" +#include "xhci/xhci_driver.h" void DeviceSlot::EnableAndInitializeDataStructures( - uint8_t slot_index, uint64_t* output_context, volatile uint32_t* doorbell) { + XhciDriver* driver, uint8_t slot_index, uint64_t* output_context, + volatile uint32_t* doorbell) { enabled_ = true; + xhci_driver_ = driver; slot_index_ = slot_index; doorbell_ = doorbell; @@ -63,3 +66,29 @@ void DeviceSlot::TransferComplete(uint8_t endpoint_index, uint64_t trb_phys) { control_completion_sempahores_.at(trb_phys)->Signal(); check(control_completion_sempahores_.Delete(trb_phys)); } + +mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(uint8_t config_value) { + input_context_->input.add_contexts = (0x1 << 3) | 0x1; + input_context_->input.configuration_value = config_value; + // TODO: Maybe don't hardcode this. + input_context_->input.interface_number = 0; + + input_context_->slot_context.route_speed_entries &= 0xFFFFFF; + + // TODO: Don't hardcode this. + uint8_t max_endpoint = 0x3; + input_context_->slot_context.route_speed_entries |= (max_endpoint << 27); + + // TODO: Dont' hardcode this. + other_endpoint_transfer_trb_ = glcr::MakeUnique(); + input_context_->endpoint_contexts[2].tr_dequeue_ptr = + other_endpoint_transfer_trb_->PhysicalAddress() | 0x1; + + xhci_driver_->IssueCommand(CreateConfigureEndpointCommand( + context_phys_ + kInputSlotContextOffset, slot_index_)); + return configure_device_semaphore_; +} + +void DeviceSlot::SignalConfigureDeviceCompleted() { + configure_device_semaphore_.Signal(); +} diff --git a/sys/voyageurs/xhci/device_slot.h b/sys/voyageurs/xhci/device_slot.h index 749b243..2e3a1cf 100644 --- a/sys/voyageurs/xhci/device_slot.h +++ b/sys/voyageurs/xhci/device_slot.h @@ -11,19 +11,25 @@ #include "xhci/trb_ring.h" #include "xhci/xhci.h" +class XhciDriver; + class DeviceSlot { public: DeviceSlot() = default; DeviceSlot(const DeviceSlot&) = delete; DeviceSlot(DeviceSlot&&) = delete; - void EnableAndInitializeDataStructures(uint8_t slot_index_, + void EnableAndInitializeDataStructures(XhciDriver* driver, + uint8_t slot_index_, uint64_t* output_context, volatile uint32_t* doorbell); XhciTrb CreateAddressDeviceCommand(uint8_t root_port, uint32_t route_string, uint16_t max_packet_size); + mmth::Semaphore IssueConfigureDeviceCommand(uint8_t config_value); + void SignalConfigureDeviceCompleted(); + // Caller must keep the command in scope until it completes. template void ExecuteReadControlCommand(ReadControlCommand& command); @@ -35,6 +41,7 @@ class DeviceSlot { private: bool enabled_ = false; + XhciDriver* xhci_driver_; uint8_t slot_index_ = 0; volatile uint32_t* doorbell_ = nullptr; @@ -49,6 +56,10 @@ class DeviceSlot { glcr::UniquePtr control_endpoint_transfer_trb_; glcr::HashMap> control_completion_sempahores_; + + mmth::Semaphore configure_device_semaphore_; + + glcr::UniquePtr other_endpoint_transfer_trb_; }; template diff --git a/sys/voyageurs/xhci/trb.cpp b/sys/voyageurs/xhci/trb.cpp index 09743fc..039ac2f 100644 --- a/sys/voyageurs/xhci/trb.cpp +++ b/sys/voyageurs/xhci/trb.cpp @@ -49,6 +49,17 @@ XhciTrb CreateAddressDeviceCommand(uint64_t input_context, uint8_t slot_id) { }; } +XhciTrb CreateConfigureEndpointCommand(uint64_t input_context, + uint8_t slot_id) { + return { + .parameter = input_context, + .status = 0, + .type_and_cycle = + (uint16_t)(TypeToInt(TrbType::ConfigureEndpoint) | kTrb_Cycle), + .control = (uint16_t)(slot_id << 8), + }; +} + XhciTrb CreateNoOpCommandTrb() { return { .parameter = 0, diff --git a/sys/voyageurs/xhci/trb.h b/sys/voyageurs/xhci/trb.h index a02982a..9fbba5a 100644 --- a/sys/voyageurs/xhci/trb.h +++ b/sys/voyageurs/xhci/trb.h @@ -18,6 +18,7 @@ enum class TrbType : uint8_t { // Commands EnableSlot = 9, AddressDevice = 11, + ConfigureEndpoint = 12, NoOpCommand = 23, // Events @@ -32,4 +33,5 @@ XhciTrb CreateLinkTrb(uint64_t physical_address); XhciTrb CreateEnableSlotTrb(); XhciTrb CreateAddressDeviceCommand(uint64_t input_context, uint8_t slot_id); +XhciTrb CreateConfigureEndpointCommand(uint64_t input_context, uint8_t slot_id); XhciTrb CreateNoOpCommandTrb(); diff --git a/sys/voyageurs/xhci/xhci_driver.cpp b/sys/voyageurs/xhci/xhci_driver.cpp index ba7bafa..a37eb64 100644 --- a/sys/voyageurs/xhci/xhci_driver.cpp +++ b/sys/voyageurs/xhci/xhci_driver.cpp @@ -70,6 +70,15 @@ void configure_device(void* void_device_slot) { next_vaddr += endpoint->length; } } + + dbgln("---- Configuring with configuration: {x}", + config_descriptor->configuration_value); + + device_slot + ->IssueConfigureDeviceCommand(config_descriptor->configuration_value) + .Wait(); + + dbgln("Configured!"); } glcr::ErrorOr> XhciDriver::InitiateDriver( @@ -169,6 +178,11 @@ void XhciDriver::DumpDebugInfo() { runtime_->interrupters[0].event_ring_segment_table_base_address); } +void XhciDriver::IssueCommand(const XhciTrb& command) { + command_ring_.EnqueueTrb(command); + doorbells_->doorbell[0] = 0; +} + XhciDriver::XhciDriver(mmth::OwnedMemoryRegion&& pci_space) : pci_region_(glcr::Move(pci_space)) {} @@ -329,6 +343,11 @@ void XhciDriver::HandleCommandCompletion( dbgln("State: {x}", devices_[slot - 1].State()); Thread(configure_device, &devices_[slot - 1]); break; + case TrbType::ConfigureEndpoint: + dbgln("Device COnfigured: {x}", slot); + dbgln("State: {x}", devices_[slot - 1].State()); + devices_[slot - 1].SignalConfigureDeviceCompleted(); + break; case TrbType::NoOpCommand: dbgln("No-op Command Completed"); break; @@ -353,7 +372,7 @@ void XhciDriver::HandleTransferCompletion(const XhciTrb& transfer_event_trb) { void XhciDriver::InitializeSlot(uint8_t slot_index) { // TODO: Consider making this array one longer and ignore the first value. devices_[slot_index - 1].EnableAndInitializeDataStructures( - slot_index, &(device_context_base_array_[slot_index]), + this, slot_index, &(device_context_base_array_[slot_index]), &doorbells_->doorbell[slot_index]); XhciPort* port = reinterpret_cast(reinterpret_cast(operational_) + diff --git a/sys/voyageurs/xhci/xhci_driver.h b/sys/voyageurs/xhci/xhci_driver.h index 3beb293..2b70715 100644 --- a/sys/voyageurs/xhci/xhci_driver.h +++ b/sys/voyageurs/xhci/xhci_driver.h @@ -23,6 +23,8 @@ class XhciDriver { void InterruptLoop(); + void IssueCommand(const XhciTrb& command); + private: // MMIO Structures. mmth::OwnedMemoryRegion pci_region_;