[denali] Get Ahci device address from yellowstone.
This commit is contained in:
parent
02e6b49d90
commit
16dd675828
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue