Compare commits
2 Commits
27c39d05e8
...
2228b5b52e
Author | SHA1 | Date |
---|---|---|
|
2228b5b52e | |
|
3bacfea183 |
|
@ -20,7 +20,7 @@ if [[ $1 == "debug" ]]; then
|
|||
fi
|
||||
|
||||
# Use machine q35 to access PCI devices.
|
||||
qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda disk.img ${QEMU_ARGS}
|
||||
qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda disk.img ${QEMU_ARGS} -device nec-usb-xhci,id=xhci -device usb-kbd,bus=xhci.0
|
||||
popd
|
||||
|
||||
# Extra options to add to this script in the future.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
add_executable(voyageurs
|
||||
keyboard/keyboard_driver.cpp
|
||||
xhci/xhci_driver.cpp
|
||||
voyageurs_server.cpp
|
||||
voyageurs.cpp)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "keyboard/keyboard_driver.h"
|
||||
#include "voyageurs_server.h"
|
||||
#include "xhci/xhci_driver.h"
|
||||
|
||||
using yellowstone::RegisterEndpointRequest;
|
||||
using yellowstone::YellowstoneClient;
|
||||
|
@ -12,6 +13,10 @@ using yellowstone::YellowstoneClient;
|
|||
uint64_t main(uint64_t init_port) {
|
||||
ParseInitPort(init_port);
|
||||
|
||||
YellowstoneClient yellowstone(gInitEndpointCap);
|
||||
|
||||
ASSIGN_OR_RETURN(XhciDriver xhci, XhciDriver::InitiateDriver(yellowstone));
|
||||
|
||||
dbgln("Initializing PS/2 Driver.");
|
||||
KeyboardDriver driver;
|
||||
|
||||
|
@ -24,8 +29,6 @@ uint64_t main(uint64_t init_port) {
|
|||
|
||||
Thread server_thread = server->RunServer();
|
||||
|
||||
YellowstoneClient yellowstone(gInitEndpointCap);
|
||||
|
||||
RegisterEndpointRequest req;
|
||||
req.set_endpoint_name("voyageurs");
|
||||
ASSIGN_OR_RETURN(z_cap_t client_cap, server->CreateClientCap());
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// TODO: Move to shared lib for denali and voyageurs.
|
||||
struct PciDeviceHeader {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint16_t command_reg;
|
||||
uint16_t status_reg;
|
||||
uint8_t revision;
|
||||
uint8_t prog_interface;
|
||||
uint8_t subclass;
|
||||
uint8_t class_code;
|
||||
uint8_t cache_line_size;
|
||||
uint8_t latency_timer;
|
||||
uint8_t header_type;
|
||||
uint8_t bist;
|
||||
uint32_t bars[5];
|
||||
uint32_t abar;
|
||||
uint32_t reserved0;
|
||||
uint32_t subsystem_id;
|
||||
uint32_t expansion_rom;
|
||||
uint8_t cap_ptr;
|
||||
uint8_t reserved1[7];
|
||||
uint8_t interrupt_line;
|
||||
uint8_t interrupt_pin;
|
||||
uint8_t min_grant;
|
||||
uint8_t max_latency;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciCapabilities {
|
||||
// NOTE: In qemu access these addresses at anything other than a 32bit offset
|
||||
// seems to give bogus values so we group the fields more than necessary.
|
||||
uint32_t length_and_version;
|
||||
uint32_t hcs_params_1;
|
||||
uint32_t hcs_params_2;
|
||||
uint32_t hcs_params_3;
|
||||
uint16_t capabilites;
|
||||
uint16_t ext_capabilities_pointer;
|
||||
uint32_t doorbell_offset;
|
||||
uint32_t runtime_offset;
|
||||
uint32_t capabilities2;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciOperational {
|
||||
uint32_t usb_command;
|
||||
uint32_t usb_status;
|
||||
uint32_t page_size;
|
||||
uint32_t reserved;
|
||||
uint32_t reserved2;
|
||||
uint32_t device_notification_control;
|
||||
uint64_t command_ring_control;
|
||||
uint64_t reserved3;
|
||||
uint64_t reserved4;
|
||||
uint64_t device_context_base;
|
||||
uint32_t configure;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciInterrupter {
|
||||
uint32_t management;
|
||||
uint32_t moderation;
|
||||
uint32_t event_ring_segment_table_size;
|
||||
uint32_t reserved;
|
||||
uint64_t event_ring_segment_table_base_address;
|
||||
uint64_t event_ring_dequeue_pointer;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciRuntime {
|
||||
uint32_t microframe_index;
|
||||
uint32_t reserved1;
|
||||
uint64_t reserved2;
|
||||
uint64_t reserved3;
|
||||
uint64_t reserved4;
|
||||
XhciInterrupter interrupters[1024];
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciPort {
|
||||
uint32_t status_and_control;
|
||||
uint32_t power_management;
|
||||
uint32_t link_info;
|
||||
uint32_t lpm_control;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciSlotContext {
|
||||
uint32_t route_speed_entries;
|
||||
uint32_t latency_port_number;
|
||||
uint32_t parent_and_interrupt;
|
||||
uint32_t address_and_state;
|
||||
uint64_t reserved1;
|
||||
uint64_t reserved2;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciEndpointContext {
|
||||
uint32_t state;
|
||||
uint32_t error_and_type;
|
||||
uint64_t tr_dequeue_ptr;
|
||||
uint32_t average_trb_length;
|
||||
uint32_t reserved1;
|
||||
uint64_t reserved2;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciDeviceContext {
|
||||
XhciSlotContext slot_context;
|
||||
XhciEndpointContext endpoint_contexts[31];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciCommandTrb {
|
||||
uint64_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint16_t type_and_cycle;
|
||||
uint16_t slot_type;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciLinkTrb {
|
||||
uint64_t link_address;
|
||||
uint32_t interrupter_target;
|
||||
uint16_t type_and_cycle;
|
||||
uint16_t reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct XhciEventRingSegmentTableEntry {
|
||||
uint64_t ring_segment_base;
|
||||
uint16_t ring_segment_size;
|
||||
uint16_t reserved1;
|
||||
uint32_t reserved2;
|
||||
} __attribute__((packed));
|
|
@ -0,0 +1,186 @@
|
|||
#include "xhci/xhci_driver.h"
|
||||
|
||||
#include <mammoth/proc/thread.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#include "xhci/xhci.h"
|
||||
|
||||
glcr::ErrorOr<XhciDriver> XhciDriver::InitiateDriver(
|
||||
yellowstone::YellowstoneClient& yellowstone) {
|
||||
yellowstone::XhciInfo info;
|
||||
check(yellowstone.GetXhciInfo(info));
|
||||
|
||||
mmth::OwnedMemoryRegion pci_region =
|
||||
mmth::OwnedMemoryRegion::FromCapability(info.mutable_xhci_region());
|
||||
XhciDriver driver(glcr::Move(pci_region));
|
||||
driver.ParseMmioStructures();
|
||||
driver.DumpDebugInfo();
|
||||
driver.FreeExistingMemoryStructures();
|
||||
driver.ResetController();
|
||||
dbgln("XHCI CONTROLLER RESET");
|
||||
driver.DumpDebugInfo();
|
||||
check(ZThreadSleep(100));
|
||||
driver.DumpDebugInfo();
|
||||
return driver;
|
||||
}
|
||||
|
||||
void XhciDriver::DumpDebugInfo() {
|
||||
dbgln("Code: {x} {x} {x}", pci_device_header_->class_code,
|
||||
pci_device_header_->subclass, pci_device_header_->prog_interface);
|
||||
|
||||
dbgln("BAR: {x}", pci_device_header_->bars[0] & ~0xFFF);
|
||||
dbgln("In P: {x} L: {x}", pci_device_header_->interrupt_pin,
|
||||
pci_device_header_->interrupt_line);
|
||||
|
||||
dbgln("Cap length: {x}", capabilities_->length_and_version & 0xFF);
|
||||
dbgln("XHCI Version: {x}",
|
||||
(capabilities_->length_and_version & 0xFFFF0000) >> 16);
|
||||
dbgln("Max Slots: {x}", capabilities_->hcs_params_1 & 0xFF);
|
||||
dbgln("Max Interrupters: {x}", (capabilities_->hcs_params_1 & 0x3FF00) >> 8);
|
||||
uint64_t max_ports = (capabilities_->hcs_params_1 & 0xFF00'0000) >> 24;
|
||||
dbgln("Params 2: {x}", capabilities_->hcs_params_2);
|
||||
dbgln("Params 3: {x}", capabilities_->hcs_params_3);
|
||||
dbgln("Max Ports: {x}", max_ports);
|
||||
dbgln("Capabilities: {x}", capabilities_->capabilites);
|
||||
dbgln("Doorbell: {x}", capabilities_->doorbell_offset);
|
||||
dbgln("Runtime: {x}", capabilities_->runtime_offset);
|
||||
|
||||
dbgln("Op cmd: {x} sts: {x}", operational_->usb_command,
|
||||
operational_->usb_status);
|
||||
dbgln("Page size: {x}", operational_->page_size);
|
||||
dbgln("Device Context Base Array: {x}", operational_->device_context_base);
|
||||
dbgln("Command Ring Control: {x}", operational_->command_ring_control);
|
||||
dbgln("Config: {x}", operational_->configure);
|
||||
|
||||
for (uint64_t i = 0; i < max_ports; i++) {
|
||||
XhciPort* port = reinterpret_cast<XhciPort*>(
|
||||
reinterpret_cast<uint64_t>(operational_) + 0x400 + (0x10 * i));
|
||||
port->status_and_control &= ~0x10000;
|
||||
dbgln("Port {x}: {x}", i, port->status_and_control);
|
||||
if ((port->status_and_control & 0x3) == 0x1) {
|
||||
dbgln("Resetting: {x}", i);
|
||||
port->status_and_control |= 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
dbgln("Int 0 ES: {x}",
|
||||
runtime_->interrupters[0].event_ring_segment_table_base_address);
|
||||
}
|
||||
|
||||
XhciDriver::XhciDriver(mmth::OwnedMemoryRegion&& pci_space)
|
||||
: pci_region_(glcr::Move(pci_space)) {}
|
||||
|
||||
glcr::ErrorCode XhciDriver::ParseMmioStructures() {
|
||||
pci_device_header_ = reinterpret_cast<PciDeviceHeader*>(pci_region_.vaddr());
|
||||
|
||||
// TODO: Officially determine the size of this memory.
|
||||
mmio_regions_ = mmth::OwnedMemoryRegion::DirectPhysical(
|
||||
pci_device_header_->bars[0] & ~0xFFF, 0x3000);
|
||||
|
||||
capabilities_ = reinterpret_cast<XhciCapabilities*>(mmio_regions_.vaddr());
|
||||
|
||||
uint64_t op_base =
|
||||
mmio_regions_.vaddr() + (capabilities_->length_and_version & 0xFF);
|
||||
operational_ = reinterpret_cast<XhciOperational*>(op_base);
|
||||
|
||||
runtime_ = reinterpret_cast<XhciRuntime*>(mmio_regions_.vaddr() +
|
||||
capabilities_->runtime_offset);
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorCode XhciDriver::ResetController() {
|
||||
// Host Controller Reset
|
||||
operational_->usb_command |= 0x2;
|
||||
|
||||
while (operational_->usb_command & 0x2) {
|
||||
dbgln("Waiting Reset");
|
||||
RET_ERR(ZThreadSleep(50));
|
||||
}
|
||||
|
||||
while (operational_->usb_command & (0x1 << 11)) {
|
||||
dbgln("Waiting controller ready");
|
||||
RET_ERR(ZThreadSleep(50));
|
||||
}
|
||||
|
||||
InitiateCommandRing();
|
||||
InitiateDeviceContextBaseArray();
|
||||
InitiateEventRingSegmentTable();
|
||||
|
||||
// Run the controller.
|
||||
operational_->usb_command |= 0x1;
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorCode XhciDriver::InitiateCommandRing() {
|
||||
uint64_t command_ring_phys;
|
||||
command_ring_mem_ =
|
||||
mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &command_ring_phys);
|
||||
command_trb_ = reinterpret_cast<XhciCommandTrb*>(command_ring_mem_.vaddr());
|
||||
|
||||
uint64_t number_trbs = 0x1000 / sizeof(XhciCommandTrb);
|
||||
|
||||
// Point the end of the command ring back to the start.
|
||||
auto* link_trb =
|
||||
reinterpret_cast<XhciLinkTrb*>(command_trb_ + number_trbs - 1);
|
||||
link_trb->link_address = command_ring_phys;
|
||||
// TODO: Cleaner interface for specifying a command type.
|
||||
link_trb->type_and_cycle = 0x6 << 10;
|
||||
|
||||
operational_->command_ring_control = command_ring_phys;
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorCode XhciDriver::InitiateDeviceContextBaseArray() {
|
||||
uint64_t dcba_phys;
|
||||
device_context_base_array_mem_ =
|
||||
mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &dcba_phys);
|
||||
device_context_base_array_ =
|
||||
reinterpret_cast<uint64_t*>(device_context_base_array_mem_.vaddr());
|
||||
|
||||
operational_->device_context_base = dcba_phys;
|
||||
|
||||
uint64_t max_slots = (0x1000 / sizeof(uint64_t)) - 1;
|
||||
|
||||
if (max_slots > (capabilities_->hcs_params_1 & 0xFF)) {
|
||||
max_slots = capabilities_->hcs_params_1 & 0xFF;
|
||||
}
|
||||
operational_->configure =
|
||||
(operational_->configure & ~0xFF) | (max_slots & 0xFF);
|
||||
|
||||
// TODO: Initialize scratchpad if that is needed by the controller.
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorCode XhciDriver::InitiateEventRingSegmentTable() {
|
||||
uint64_t erst_phys;
|
||||
event_ring_segment_table_mem_ =
|
||||
mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &erst_phys);
|
||||
|
||||
event_ring_segment_table_ = reinterpret_cast<XhciEventRingSegmentTableEntry*>(
|
||||
event_ring_segment_table_mem_.vaddr());
|
||||
|
||||
uint64_t ers_phys;
|
||||
event_ring_segment_mem_ =
|
||||
mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &ers_phys);
|
||||
uint64_t ers_size = 0x1000 / sizeof(XhciCommandTrb);
|
||||
|
||||
event_ring_segment_ =
|
||||
reinterpret_cast<XhciCommandTrb*>(event_ring_segment_mem_.vaddr());
|
||||
|
||||
event_ring_segment_table_[0].ring_segment_base = ers_phys;
|
||||
event_ring_segment_table_[0].ring_segment_size = ers_size & 0xFFFF;
|
||||
|
||||
runtime_->interrupters[0].event_ring_segment_table_base_address = erst_phys;
|
||||
runtime_->interrupters[0].event_ring_dequeue_pointer = erst_phys;
|
||||
runtime_->interrupters[0].event_ring_segment_table_size = 1;
|
||||
// Enable interrupts.
|
||||
runtime_->interrupters[0].management |= 0x2;
|
||||
operational_->usb_command |= 0x4;
|
||||
return glcr::OK;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <yellowstone/yellowstone.yunq.client.h>
|
||||
|
||||
#include "xhci/xhci.h"
|
||||
|
||||
class XhciDriver {
|
||||
public:
|
||||
static glcr::ErrorOr<XhciDriver> InitiateDriver(
|
||||
yellowstone::YellowstoneClient& yellowstone);
|
||||
|
||||
void DumpDebugInfo();
|
||||
|
||||
private:
|
||||
// MMIO Structures.
|
||||
mmth::OwnedMemoryRegion pci_region_;
|
||||
PciDeviceHeader* pci_device_header_;
|
||||
|
||||
mmth::OwnedMemoryRegion mmio_regions_;
|
||||
XhciCapabilities* capabilities_;
|
||||
XhciOperational* operational_;
|
||||
// TODO: Extended Capabilities.
|
||||
XhciRuntime* runtime_;
|
||||
// TODO: Doorbell Array.
|
||||
|
||||
// Host Memory Regions.
|
||||
mmth::OwnedMemoryRegion command_ring_mem_;
|
||||
XhciCommandTrb* command_trb_;
|
||||
|
||||
mmth::OwnedMemoryRegion device_context_base_array_mem_;
|
||||
uint64_t* device_context_base_array_;
|
||||
|
||||
mmth::OwnedMemoryRegion event_ring_segment_table_mem_;
|
||||
XhciEventRingSegmentTableEntry* event_ring_segment_table_;
|
||||
|
||||
mmth::OwnedMemoryRegion event_ring_segment_mem_;
|
||||
XhciCommandTrb* event_ring_segment_;
|
||||
|
||||
XhciDriver(mmth::OwnedMemoryRegion&& pci_space);
|
||||
|
||||
glcr::ErrorCode ParseMmioStructures();
|
||||
glcr::ErrorCode FreeExistingMemoryStructures() { return glcr::OK; }
|
||||
|
||||
glcr::ErrorCode ResetController();
|
||||
|
||||
glcr::ErrorCode InitiateCommandRing();
|
||||
glcr::ErrorCode InitiateDeviceContextBaseArray();
|
||||
glcr::ErrorCode InitiateEventRingSegmentTable();
|
||||
};
|
|
@ -4,7 +4,7 @@
|
|||
#include <mammoth/util/init.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#define PCI_DEBUG 0
|
||||
#define PCI_DEBUG 1
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -32,6 +32,13 @@ z_cap_t PciReader::GetAhciVmmo() {
|
|||
return new_cap;
|
||||
}
|
||||
|
||||
z_cap_t PciReader::GetXhciVmmo() {
|
||||
uint64_t new_cap;
|
||||
check(ZMemoryObjectDuplicate(gBootPciVmmoCap, xhci_device_offset_,
|
||||
kPcieConfigurationSize, &new_cap));
|
||||
return new_cap;
|
||||
}
|
||||
|
||||
void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev,
|
||||
uint64_t fun) {
|
||||
PciDeviceHeader* hdr = PciHeader(base, bus, dev, fun);
|
||||
|
@ -55,6 +62,14 @@ void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev,
|
|||
#endif
|
||||
achi_device_offset_ = reinterpret_cast<uint64_t>(hdr) - base;
|
||||
}
|
||||
|
||||
if (hdr->class_code == 0xC && hdr->subclass == 0x3) {
|
||||
if (hdr->prog_interface == 0x30) {
|
||||
xhci_device_offset_ = reinterpret_cast<uint64_t>(hdr) - base;
|
||||
} else {
|
||||
dbgln("WARN: Non-XHCI USB Controller found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PciReader::DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) {
|
||||
|
|
|
@ -28,11 +28,13 @@ class PciReader {
|
|||
PciReader();
|
||||
|
||||
z_cap_t GetAhciVmmo();
|
||||
z_cap_t GetXhciVmmo();
|
||||
|
||||
private:
|
||||
PciDeviceHeader* header_;
|
||||
|
||||
uint64_t achi_device_offset_ = 0;
|
||||
uint64_t xhci_device_offset_ = 0;
|
||||
|
||||
void PciDump(uint64_t vaddr);
|
||||
void BusDump(uint64_t base, uint64_t bus);
|
||||
|
|
|
@ -4,6 +4,7 @@ interface Yellowstone {
|
|||
method RegisterEndpoint(RegisterEndpointRequest) -> ();
|
||||
method GetEndpoint(GetEndpointRequest) -> (Endpoint);
|
||||
method GetAhciInfo() -> (AhciInfo);
|
||||
method GetXhciInfo() -> (XhciInfo);
|
||||
method GetFramebufferInfo() -> (FramebufferInfo);
|
||||
method GetDenali() -> (DenaliInfo);
|
||||
}
|
||||
|
@ -26,6 +27,11 @@ message AhciInfo {
|
|||
u64 region_length;
|
||||
}
|
||||
|
||||
message XhciInfo {
|
||||
capability xhci_region;
|
||||
u64 region_length;
|
||||
}
|
||||
|
||||
message FramebufferInfo {
|
||||
u64 address_phys;
|
||||
u64 width;
|
||||
|
|
|
@ -137,7 +137,7 @@ glcr::Status YellowstoneClient::GetAhciInfo(AhciInfo& response) {
|
|||
|
||||
|
||||
|
||||
glcr::Status YellowstoneClient::GetFramebufferInfo(FramebufferInfo& response) {
|
||||
glcr::Status YellowstoneClient::GetXhciInfo(XhciInfo& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
@ -177,7 +177,7 @@ glcr::Status YellowstoneClient::GetFramebufferInfo(FramebufferInfo& response) {
|
|||
|
||||
|
||||
|
||||
glcr::Status YellowstoneClient::GetDenali(DenaliInfo& response) {
|
||||
glcr::Status YellowstoneClient::GetFramebufferInfo(FramebufferInfo& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
@ -217,5 +217,45 @@ glcr::Status YellowstoneClient::GetDenali(DenaliInfo& response) {
|
|||
|
||||
|
||||
|
||||
glcr::Status YellowstoneClient::GetDenali(DenaliInfo& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
buffer_.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer_.WriteAt<uint64_t>(8, 5);
|
||||
|
||||
cap_buffer_.Reset();
|
||||
|
||||
uint64_t length = 0;
|
||||
|
||||
|
||||
buffer_.WriteAt<uint32_t>(4, 16 + length);
|
||||
|
||||
z_cap_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap));
|
||||
|
||||
// FIXME: Add a way to zero out the first buffer.
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
|
||||
|
||||
if (buffer_.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidResponse("Got an invalid response from server.");
|
||||
}
|
||||
|
||||
// Check Response Code.
|
||||
RET_ERR(buffer_.At<uint64_t>(8));
|
||||
|
||||
|
||||
yunq::MessageView resp_view(buffer_, 16);
|
||||
RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_));
|
||||
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namepace yellowstone
|
||||
|
|
|
@ -34,6 +34,10 @@ class YellowstoneClient {
|
|||
|
||||
|
||||
|
||||
[[nodiscard]] glcr::Status GetXhciInfo(XhciInfo& response);
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] glcr::Status GetFramebufferInfo(FramebufferInfo& response);
|
||||
|
||||
|
||||
|
|
|
@ -178,6 +178,49 @@ uint64_t AhciInfo::SerializeInternal(yunq::Serializer& serializer) const {
|
|||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status XhciInfo::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
// Parse xhci_region.
|
||||
ASSIGN_OR_RETURN(xhci_region_, message.ReadCapability(0));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status XhciInfo::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
// Parse xhci_region.
|
||||
ASSIGN_OR_RETURN(xhci_region_, message.ReadCapability(0, caps));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status XhciInfo::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse xhci_region.
|
||||
// Parse region_length.
|
||||
ASSIGN_OR_RETURN(region_length_, message.ReadField<uint64_t>(1));
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t XhciInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t XhciInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t XhciInfo::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write xhci_region.
|
||||
serializer.WriteCapability(0, xhci_region_);
|
||||
// Write region_length.
|
||||
serializer.WriteField<uint64_t>(1, region_length_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status FramebufferInfo::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
|
|
|
@ -123,6 +123,36 @@ class AhciInfo {
|
|||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class XhciInfo {
|
||||
public:
|
||||
XhciInfo() {}
|
||||
// Delete copy and move until implemented.
|
||||
XhciInfo(const XhciInfo&) = delete;
|
||||
XhciInfo(XhciInfo&&) = default;
|
||||
XhciInfo& operator=(XhciInfo&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const z_cap_t& xhci_region() const { return xhci_region_; }
|
||||
z_cap_t& mutable_xhci_region() { return xhci_region_; }
|
||||
void set_xhci_region(const z_cap_t& value) { xhci_region_ = value; }
|
||||
|
||||
const uint64_t& region_length() const { return region_length_; }
|
||||
uint64_t& mutable_region_length() { return region_length_; }
|
||||
void set_region_length(const uint64_t& value) { region_length_ = value; }
|
||||
|
||||
private:
|
||||
z_cap_t xhci_region_;
|
||||
uint64_t region_length_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class FramebufferInfo {
|
||||
public:
|
||||
FramebufferInfo() {}
|
||||
|
|
|
@ -164,6 +164,23 @@ glcr::Status YellowstoneServerBase::HandleRequest(const glcr::ByteBuffer& reques
|
|||
|
||||
|
||||
|
||||
XhciInfo yunq_response;
|
||||
|
||||
|
||||
|
||||
RETURN_ERROR(HandleGetXhciInfo(yunq_response));
|
||||
|
||||
|
||||
|
||||
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
|
||||
|
||||
|
||||
|
||||
FramebufferInfo yunq_response;
|
||||
|
||||
|
||||
|
@ -176,7 +193,7 @@ glcr::Status YellowstoneServerBase::HandleRequest(const glcr::ByteBuffer& reques
|
|||
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
case 5: {
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ class YellowstoneServerBase {
|
|||
|
||||
|
||||
|
||||
[[nodiscard]] virtual glcr::Status HandleGetXhciInfo(XhciInfo&) = 0;
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] virtual glcr::Status HandleGetFramebufferInfo(FramebufferInfo&) = 0;
|
||||
|
||||
|
||||
|
|
|
@ -52,6 +52,12 @@ glcr::Status YellowstoneServer::HandleGetAhciInfo(AhciInfo& info) {
|
|||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetXhciInfo(XhciInfo& info) {
|
||||
info.set_xhci_region(pci_reader_.GetXhciVmmo());
|
||||
info.set_region_length(kPcieConfigurationSize);
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetFramebufferInfo(
|
||||
FramebufferInfo& info) {
|
||||
// FIXME: Don't do this for each request.
|
||||
|
|
|
@ -17,6 +17,7 @@ class YellowstoneServer : public YellowstoneServerBase {
|
|||
static glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> Create();
|
||||
|
||||
glcr::Status HandleGetAhciInfo(AhciInfo&) override;
|
||||
glcr::Status HandleGetXhciInfo(XhciInfo&) override;
|
||||
glcr::Status HandleGetFramebufferInfo(FramebufferInfo&) override;
|
||||
glcr::Status HandleGetDenali(DenaliInfo&) override;
|
||||
glcr::Status HandleRegisterEndpoint(const RegisterEndpointRequest&) override;
|
||||
|
|
Loading…
Reference in New Issue