[denali] Get Ahci device address from yellowstone.

This commit is contained in:
Drew Galbraith 2023-06-26 17:01:59 -07:00
parent 02e6b49d90
commit 16dd675828
11 changed files with 125 additions and 52 deletions

View File

@ -15,7 +15,10 @@ class EndpointClient {
static glcr::UniquePtr<EndpointClient> AdoptEndpoint(z_cap_t cap); static glcr::UniquePtr<EndpointClient> AdoptEndpoint(z_cap_t cap);
template <typename Req, typename Resp> template <typename Req, typename Resp>
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> CallEndpoint(const Req& req); glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> CallEndpointGetCap(const Req& req);
template <typename Req, typename Resp>
glcr::ErrorOr<Resp> CallEndpoint(const Req& req);
z_cap_t GetCap() { return cap_; } z_cap_t GetCap() { return cap_; }
@ -25,7 +28,7 @@ class EndpointClient {
}; };
template <typename Req, typename Resp> template <typename Req, typename Resp>
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> EndpointClient::CallEndpoint( glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> EndpointClient::CallEndpointGetCap(
const Req& req) { const Req& req) {
uint64_t reply_port_cap; uint64_t reply_port_cap;
RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, &reply_port_cap)); RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, &reply_port_cap));
@ -42,3 +45,21 @@ glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> EndpointClient::CallEndpoint(
return glcr::Pair{resp, cap}; return glcr::Pair{resp, cap};
} }
template <typename Req, typename Resp>
glcr::ErrorOr<Resp> 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;
}

View File

@ -8,7 +8,6 @@
namespace { namespace {
const uint64_t kSataPciPhys = 0xB00FA000;
const uint64_t kPciSize = 0x1000; const uint64_t kPciSize = 0x1000;
const uint64_t kGhc_InteruptEnable = 0x2; const uint64_t kGhc_InteruptEnable = 0x2;
@ -155,7 +154,7 @@ void AhciDriver::InterruptLoop() {
} }
glcr::ErrorCode AhciDriver::LoadPciDeviceHeader() { glcr::ErrorCode AhciDriver::LoadPciDeviceHeader() {
pci_region_ = MappedMemoryRegion::DirectPhysical(kSataPciPhys, kPciSize); pci_region_ = MappedMemoryRegion::DirectPhysical(ahci_phys_, kPciSize);
pci_device_header_ = reinterpret_cast<PciDeviceHeader*>(pci_region_.vaddr()); pci_device_header_ = reinterpret_cast<PciDeviceHeader*>(pci_region_.vaddr());
return glcr::OK; return glcr::OK;
} }

View File

@ -9,6 +9,7 @@
class AhciDriver { class AhciDriver {
public: public:
AhciDriver(uint64_t ahci_phys) : ahci_phys_(ahci_phys) {}
glcr::ErrorCode Init(); glcr::ErrorCode Init();
void InterruptLoop(); void InterruptLoop();
@ -19,6 +20,7 @@ class AhciDriver {
void DumpPorts(); void DumpPorts();
private: private:
uint64_t ahci_phys_;
MappedMemoryRegion pci_region_; MappedMemoryRegion pci_region_;
PciDeviceHeader* pci_device_header_ = nullptr; PciDeviceHeader* pci_device_header_ = nullptr;
MappedMemoryRegion ahci_region_; MappedMemoryRegion ahci_region_;

View File

@ -11,7 +11,8 @@ glcr::ErrorOr<MappedMemoryRegion> DenaliClient::ReadSectors(
.lba = lba, .lba = lba,
.size = num_sectors, .size = num_sectors,
}; };
auto pair_or = endpoint_->CallEndpoint<DenaliRead, DenaliReadResponse>(read); auto pair_or =
endpoint_->CallEndpointGetCap<DenaliRead, DenaliReadResponse>(read);
if (!pair_or) { if (!pair_or) {
return pair_or.error(); return pair_or.error();
} }

View File

@ -11,18 +11,28 @@
uint64_t main(uint64_t init_port_cap) { uint64_t main(uint64_t init_port_cap) {
check(ParseInitPort(init_port_cap)); check(ParseInitPort(init_port_cap));
AhciDriver driver;
RET_ERR(driver.Init());
glcr::UniquePtr<EndpointClient> yellowstone = glcr::UniquePtr<EndpointClient> yellowstone =
EndpointClient::AdoptEndpoint(gInitEndpointCap); EndpointClient::AdoptEndpoint(gInitEndpointCap);
YellowstoneGetReq ahci_req{
.type = kYellowstoneGetAhci,
};
auto resp_or =
yellowstone->CallEndpoint<YellowstoneGetReq, YellowstoneGetAhciResp>(
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{ YellowstoneGetReq req{
.type = kYellowstoneGetRegistration, .type = kYellowstoneGetRegistration,
}; };
auto resp_cap_or = auto resp_cap_or =
yellowstone yellowstone->CallEndpointGetCap<YellowstoneGetReq,
->CallEndpoint<YellowstoneGetReq, YellowstoneGetRegistrationResp>( YellowstoneGetRegistrationResp>(req);
req);
if (!resp_cap_or.ok()) { if (!resp_cap_or.ok()) {
dbgln("Bad call"); dbgln("Bad call");
check(resp_cap_or.error()); check(resp_cap_or.error());

View File

@ -6,28 +6,37 @@
namespace { 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, PciDeviceHeader* PciHeader(uint64_t base, uint64_t bus, uint64_t dev,
uint64_t fun) { uint64_t fun) {
return reinterpret_cast<PciDeviceHeader*>(base + (bus << 20) + (dev << 15) + return reinterpret_cast<PciDeviceHeader*>(base + (bus << 20) + (dev << 15) +
(fun << 12)); (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); PciDeviceHeader* hdr = PciHeader(base, bus, dev, fun);
if (hdr->vendor_id == 0xFFFF) { if (hdr->vendor_id == 0xFFFF) {
return; return;
@ -43,10 +52,11 @@ void FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun) {
} }
if (hdr->class_code == 0x1) { if (hdr->class_code == 0x1) {
dbgln("SATA Device at: %lx", reinterpret_cast<uint64_t>(hdr) - base); dbgln("SATA Device at: %lx", reinterpret_cast<uint64_t>(hdr) - base);
achi_device_offset_ = reinterpret_cast<uint64_t>(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); PciDeviceHeader* hdr = PciHeader(base, bus, dev, 0);
if (hdr->vendor_id == 0xFFFF) { if (hdr->vendor_id == 0xFFFF) {
return; 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++) { for (uint64_t dev = 0; dev < 0x20; dev++) {
DeviceDump(base, bus, dev); DeviceDump(base, bus, dev);
} }
} }
void PciDump(uint64_t base) { void PciReader::PciDump(uint64_t base) {
PciDeviceHeader* hdr = PciHeader(base, 0, 0, 0); PciDeviceHeader* hdr = PciHeader(base, 0, 0, 0);
if ((hdr->header_type & 0x80) == 0) { if ((hdr->header_type & 0x80) == 0) {
// Single bus system. // 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");
}

View File

@ -1,3 +1,37 @@
#pragma once #pragma once
void DumpPciEDevices(); #include <stdint.h>
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);
};

View File

@ -2,11 +2,15 @@
#include <stdint.h> #include <stdint.h>
const uint64_t kYellowstoneGetAhci = 0x01; const uint64_t kYellowstoneGetRegistration = 0x01;
const uint64_t kYellowstoneGetRegistration = 0x02; const uint64_t kYellowstoneGetAhci = 0x02;
struct YellowstoneGetReq { struct YellowstoneGetReq {
uint64_t type; uint64_t type;
}; };
struct YellowstoneGetRegistrationResp {}; struct YellowstoneGetRegistrationResp {};
struct YellowstoneGetAhciResp {
uint64_t type;
uint64_t ahci_phys_offset;
};

View File

@ -15,7 +15,6 @@ uint64_t main(uint64_t port_cap) {
ASSIGN_OR_RETURN(auto server, YellowstoneServer::Create()); ASSIGN_OR_RETURN(auto server, YellowstoneServer::Create());
Thread server_thread = server->RunServer(); Thread server_thread = server->RunServer();
Thread registration_thread = server->RunRegistration(); Thread registration_thread = server->RunRegistration();
DumpPciEDevices();
uint64_t vaddr; uint64_t vaddr;
check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr)); check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr));

View File

@ -57,9 +57,15 @@ void YellowstoneServer::ServerThread() {
YellowstoneGetReq* req = YellowstoneGetReq* req =
reinterpret_cast<YellowstoneGetReq*>(server_buffer_); reinterpret_cast<YellowstoneGetReq*>(server_buffer_);
switch (req->type) { switch (req->type) {
case kYellowstoneGetAhci: case kYellowstoneGetAhci: {
dbgln("Yellowstone::GetAHCI"); dbgln("Yellowstone::GetAHCI");
YellowstoneGetAhciResp resp{
.type = kYellowstoneGetAhci,
.ahci_phys_offset = pci_reader_.GetAhciPhysical(),
};
check(ZReplyPortSend(reply_port_cap, sizeof(resp), &resp, 0, nullptr));
break; break;
}
case kYellowstoneGetRegistration: { case kYellowstoneGetRegistration: {
dbgln("Yellowstone::GetRegistration"); dbgln("Yellowstone::GetRegistration");
auto client_or = register_port_.CreateClient(); auto client_or = register_port_.CreateClient();

View File

@ -6,6 +6,8 @@
#include <mammoth/port_server.h> #include <mammoth/port_server.h>
#include <mammoth/thread.h> #include <mammoth/thread.h>
#include "hw/pcie.h"
class YellowstoneServer { class YellowstoneServer {
public: public:
static glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> Create(); static glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> Create();
@ -30,5 +32,7 @@ class YellowstoneServer {
z_cap_t denali_cap_ = 0; z_cap_t denali_cap_ = 0;
z_cap_t victoria_falls_cap_ = 0; z_cap_t victoria_falls_cap_ = 0;
PciReader pci_reader_;
YellowstoneServer(glcr::UniquePtr<EndpointServer> server, PortServer port); YellowstoneServer(glcr::UniquePtr<EndpointServer> server, PortServer port);
}; };