diff --git a/lib/mammoth/include/mammoth/endpoint_client.h b/lib/mammoth/include/mammoth/endpoint_client.h index b4bc9ef..86a16c3 100644 --- a/lib/mammoth/include/mammoth/endpoint_client.h +++ b/lib/mammoth/include/mammoth/endpoint_client.h @@ -15,7 +15,10 @@ class EndpointClient { static glcr::UniquePtr AdoptEndpoint(z_cap_t cap); template - glcr::ErrorOr> CallEndpoint(const Req& req); + glcr::ErrorOr> CallEndpointGetCap(const Req& req); + + template + glcr::ErrorOr CallEndpoint(const Req& req); z_cap_t GetCap() { return cap_; } @@ -25,7 +28,7 @@ class EndpointClient { }; template -glcr::ErrorOr> EndpointClient::CallEndpoint( +glcr::ErrorOr> EndpointClient::CallEndpointGetCap( const Req& req) { uint64_t reply_port_cap; RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, &reply_port_cap)); @@ -42,3 +45,21 @@ glcr::ErrorOr> EndpointClient::CallEndpoint( return glcr::Pair{resp, cap}; } + +template +glcr::ErrorOr EndpointClient::CallEndpoint(const Req& req) { + uint64_t reply_port_cap; + RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, &reply_port_cap)); + + Resp resp; + uint64_t num_bytes = sizeof(Resp); + uint64_t num_caps = 0; + RET_ERR( + ZReplyPortRecv(reply_port_cap, &num_bytes, &resp, &num_caps, nullptr)); + + if (num_bytes != sizeof(resp)) { + return glcr::FAILED_PRECONDITION; + } + + return resp; +} diff --git a/sys/denali/ahci/ahci_driver.cpp b/sys/denali/ahci/ahci_driver.cpp index 4d0fa0e..bf2b464 100644 --- a/sys/denali/ahci/ahci_driver.cpp +++ b/sys/denali/ahci/ahci_driver.cpp @@ -8,7 +8,6 @@ namespace { -const uint64_t kSataPciPhys = 0xB00FA000; const uint64_t kPciSize = 0x1000; const uint64_t kGhc_InteruptEnable = 0x2; @@ -155,7 +154,7 @@ void AhciDriver::InterruptLoop() { } glcr::ErrorCode AhciDriver::LoadPciDeviceHeader() { - pci_region_ = MappedMemoryRegion::DirectPhysical(kSataPciPhys, kPciSize); + pci_region_ = MappedMemoryRegion::DirectPhysical(ahci_phys_, kPciSize); pci_device_header_ = reinterpret_cast(pci_region_.vaddr()); return glcr::OK; } diff --git a/sys/denali/ahci/ahci_driver.h b/sys/denali/ahci/ahci_driver.h index c27eb1b..922f2ba 100644 --- a/sys/denali/ahci/ahci_driver.h +++ b/sys/denali/ahci/ahci_driver.h @@ -9,6 +9,7 @@ class AhciDriver { public: + AhciDriver(uint64_t ahci_phys) : ahci_phys_(ahci_phys) {} glcr::ErrorCode Init(); void InterruptLoop(); @@ -19,6 +20,7 @@ class AhciDriver { void DumpPorts(); private: + uint64_t ahci_phys_; MappedMemoryRegion pci_region_; PciDeviceHeader* pci_device_header_ = nullptr; MappedMemoryRegion ahci_region_; diff --git a/sys/denali/client/denali_client.cpp b/sys/denali/client/denali_client.cpp index 54f0859..6f870b2 100644 --- a/sys/denali/client/denali_client.cpp +++ b/sys/denali/client/denali_client.cpp @@ -11,7 +11,8 @@ glcr::ErrorOr DenaliClient::ReadSectors( .lba = lba, .size = num_sectors, }; - auto pair_or = endpoint_->CallEndpoint(read); + auto pair_or = + endpoint_->CallEndpointGetCap(read); if (!pair_or) { return pair_or.error(); } diff --git a/sys/denali/denali.cpp b/sys/denali/denali.cpp index 79ff9c1..164eff1 100644 --- a/sys/denali/denali.cpp +++ b/sys/denali/denali.cpp @@ -11,18 +11,28 @@ uint64_t main(uint64_t init_port_cap) { check(ParseInitPort(init_port_cap)); - AhciDriver driver; - RET_ERR(driver.Init()); - glcr::UniquePtr yellowstone = EndpointClient::AdoptEndpoint(gInitEndpointCap); + YellowstoneGetReq ahci_req{ + .type = kYellowstoneGetAhci, + }; + auto resp_or = + yellowstone->CallEndpoint( + ahci_req); + if (!resp_or.ok()) { + check(resp_or.error()); + } + + uint64_t ahci_addr = resp_or.value().ahci_phys_offset; + AhciDriver driver(ahci_addr); + RET_ERR(driver.Init()); + YellowstoneGetReq req{ .type = kYellowstoneGetRegistration, }; auto resp_cap_or = - yellowstone - ->CallEndpoint( - req); + yellowstone->CallEndpointGetCap(req); if (!resp_cap_or.ok()) { dbgln("Bad call"); check(resp_cap_or.error()); diff --git a/sys/yellowstone/hw/pcie.cpp b/sys/yellowstone/hw/pcie.cpp index b3d5d70..8421589 100644 --- a/sys/yellowstone/hw/pcie.cpp +++ b/sys/yellowstone/hw/pcie.cpp @@ -6,28 +6,37 @@ namespace { -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; -} __attribute__((packed)); - PciDeviceHeader* PciHeader(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun) { return reinterpret_cast(base + (bus << 20) + (dev << 15) + (fun << 12)); } -void FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun) { +} // namespace + +PciReader::PciReader() { + dbgln("Creating PCI obj"); + uint64_t vmmo_cap, vmmo_size; + check(ZTempPcieConfigObjectCreate(&vmmo_cap, &vmmo_size)); + + dbgln("Creating addr space"); + uint64_t vaddr; + check(ZAddressSpaceMap(gSelfVmasCap, 0, vmmo_cap, &vaddr)); + dbgln("Addr %lx", vaddr); + + dbgln("Dumping PCI"); + PciDump(vaddr); + dbgln("Done"); + + header_ = PciHeader(vaddr, 0, 0, 0); +} + +uint64_t PciReader::GetAhciPhysical() { + return phys_mem_offset_ + achi_device_offset_; +} + +void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, + uint64_t fun) { PciDeviceHeader* hdr = PciHeader(base, bus, dev, fun); if (hdr->vendor_id == 0xFFFF) { return; @@ -43,10 +52,11 @@ void FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun) { } if (hdr->class_code == 0x1) { dbgln("SATA Device at: %lx", reinterpret_cast(hdr) - base); + achi_device_offset_ = reinterpret_cast(hdr) - base; } } -void DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) { +void PciReader::DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) { PciDeviceHeader* hdr = PciHeader(base, bus, dev, 0); if (hdr->vendor_id == 0xFFFF) { return; @@ -62,13 +72,13 @@ void DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) { } } -void BusDump(uint64_t base, uint64_t bus) { +void PciReader::BusDump(uint64_t base, uint64_t bus) { for (uint64_t dev = 0; dev < 0x20; dev++) { DeviceDump(base, bus, dev); } } -void PciDump(uint64_t base) { +void PciReader::PciDump(uint64_t base) { PciDeviceHeader* hdr = PciHeader(base, 0, 0, 0); if ((hdr->header_type & 0x80) == 0) { // Single bus system. @@ -82,20 +92,3 @@ void PciDump(uint64_t base) { } } } - -} // namespace - -void DumpPciEDevices() { - dbgln("Creating PCI obj"); - uint64_t vmmo_cap, vmmo_size; - check(ZTempPcieConfigObjectCreate(&vmmo_cap, &vmmo_size)); - - dbgln("Creating addr space"); - uint64_t vaddr; - check(ZAddressSpaceMap(gSelfVmasCap, 0, vmmo_cap, &vaddr)); - dbgln("Addr %lx", vaddr); - - dbgln("Dumping PCI"); - PciDump(vaddr); - dbgln("Done"); -} diff --git a/sys/yellowstone/hw/pcie.h b/sys/yellowstone/hw/pcie.h index 2359bac..0f9c268 100644 --- a/sys/yellowstone/hw/pcie.h +++ b/sys/yellowstone/hw/pcie.h @@ -1,3 +1,37 @@ #pragma once -void DumpPciEDevices(); +#include + +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; +} __attribute__((packed)); + +class PciReader { + public: + PciReader(); + + uint64_t GetAhciPhysical(); + + private: + PciDeviceHeader* header_; + // FIXME: Don't hardcode this (It is available from ACPI). + uint64_t phys_mem_offset_ = 0xB000'0000; + + uint64_t achi_device_offset_ = 0; + + void PciDump(uint64_t vaddr); + void BusDump(uint64_t base, uint64_t bus); + void DeviceDump(uint64_t base, uint64_t bus, uint64_t dev); + void FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun); +}; diff --git a/sys/yellowstone/include/yellowstone.h b/sys/yellowstone/include/yellowstone.h index cfea43a..6954ab5 100644 --- a/sys/yellowstone/include/yellowstone.h +++ b/sys/yellowstone/include/yellowstone.h @@ -2,11 +2,15 @@ #include -const uint64_t kYellowstoneGetAhci = 0x01; -const uint64_t kYellowstoneGetRegistration = 0x02; +const uint64_t kYellowstoneGetRegistration = 0x01; +const uint64_t kYellowstoneGetAhci = 0x02; struct YellowstoneGetReq { uint64_t type; }; struct YellowstoneGetRegistrationResp {}; +struct YellowstoneGetAhciResp { + uint64_t type; + uint64_t ahci_phys_offset; +}; diff --git a/sys/yellowstone/yellowstone.cpp b/sys/yellowstone/yellowstone.cpp index 5f839be..ec81d97 100644 --- a/sys/yellowstone/yellowstone.cpp +++ b/sys/yellowstone/yellowstone.cpp @@ -15,7 +15,6 @@ uint64_t main(uint64_t port_cap) { ASSIGN_OR_RETURN(auto server, YellowstoneServer::Create()); Thread server_thread = server->RunServer(); Thread registration_thread = server->RunRegistration(); - DumpPciEDevices(); uint64_t vaddr; check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr)); diff --git a/sys/yellowstone/yellowstone_server.cpp b/sys/yellowstone/yellowstone_server.cpp index 0eb27a3..28bb8c8 100644 --- a/sys/yellowstone/yellowstone_server.cpp +++ b/sys/yellowstone/yellowstone_server.cpp @@ -57,9 +57,15 @@ void YellowstoneServer::ServerThread() { YellowstoneGetReq* req = reinterpret_cast(server_buffer_); switch (req->type) { - case kYellowstoneGetAhci: + case kYellowstoneGetAhci: { dbgln("Yellowstone::GetAHCI"); + YellowstoneGetAhciResp resp{ + .type = kYellowstoneGetAhci, + .ahci_phys_offset = pci_reader_.GetAhciPhysical(), + }; + check(ZReplyPortSend(reply_port_cap, sizeof(resp), &resp, 0, nullptr)); break; + } case kYellowstoneGetRegistration: { dbgln("Yellowstone::GetRegistration"); auto client_or = register_port_.CreateClient(); diff --git a/sys/yellowstone/yellowstone_server.h b/sys/yellowstone/yellowstone_server.h index f2c0ce5..dae944c 100644 --- a/sys/yellowstone/yellowstone_server.h +++ b/sys/yellowstone/yellowstone_server.h @@ -6,6 +6,8 @@ #include #include +#include "hw/pcie.h" + class YellowstoneServer { public: static glcr::ErrorOr> Create(); @@ -30,5 +32,7 @@ class YellowstoneServer { z_cap_t denali_cap_ = 0; z_cap_t victoria_falls_cap_ = 0; + PciReader pci_reader_; + YellowstoneServer(glcr::UniquePtr server, PortServer port); };