[Denali] Move signaling out of the command class.
This commit is contained in:
parent
d7c1022b7f
commit
28a0f02b05
|
@ -243,12 +243,8 @@ glcr::ErrorCode AhciController::LoadDevices() {
|
|||
}
|
||||
|
||||
devices_[i] = new AhciPort(reinterpret_cast<AhciPortHba*>(port_addr));
|
||||
|
||||
if (devices_[i]->IsSata()) {
|
||||
IdentifyDeviceCommand identify(devices_[i].get());
|
||||
devices_[i]->IssueCommand(&identify);
|
||||
identify.WaitComplete();
|
||||
}
|
||||
// TODO: Maybe continue to the next device if this fails.
|
||||
RET_ERR(devices_[i]->Identify());
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ AhciPort::AhciPort(AhciPortHba* port) : port_struct_(port) {
|
|||
command_tables_ = glcr::ArrayView(
|
||||
reinterpret_cast<CommandTable*>(command_structures_.vaddr() + 0x500), 32);
|
||||
|
||||
command_signals_ = glcr::Array<mmth::Semaphore>(32);
|
||||
for (uint64_t i = 0; i < 32; i++) {
|
||||
// This leaves space for 2 prdt entries.
|
||||
command_list_->command_headers[i].command_table_base_addr =
|
||||
|
@ -41,7 +42,17 @@ AhciPort::AhciPort(AhciPortHba* port) : port_struct_(port) {
|
|||
port_struct_->command |= kCommand_Start;
|
||||
}
|
||||
|
||||
glcr::ErrorCode AhciPort::IssueCommand(Command* command) {
|
||||
glcr::ErrorCode AhciPort::Identify() {
|
||||
if (IsSata()) {
|
||||
IdentifyDeviceCommand identify(this);
|
||||
ASSIGN_OR_RETURN(auto* sem, IssueCommand(&identify));
|
||||
sem->Wait();
|
||||
identify.OnComplete();
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorOr<mmth::Semaphore*> AhciPort::IssueCommand(Command* command) {
|
||||
uint64_t slot;
|
||||
for (slot = 0; slot < 32; slot++) {
|
||||
if (commands_[slot] == nullptr) {
|
||||
|
@ -65,7 +76,7 @@ glcr::ErrorCode AhciPort::IssueCommand(Command* command) {
|
|||
commands_issued_ |= (1 << slot);
|
||||
port_struct_->command_issue |= (1 << slot);
|
||||
|
||||
return glcr::OK;
|
||||
return &command_signals_[slot];
|
||||
}
|
||||
|
||||
void AhciPort::DumpInfo() {
|
||||
|
@ -152,7 +163,7 @@ void AhciPort::HandleIrq() {
|
|||
if (commands_finished & (1 << i)) {
|
||||
commands_issued_ &= ~(1 << i);
|
||||
// FIXME: Pass error codes to the callback.
|
||||
commands_[i]->SignalComplete();
|
||||
command_signals_[i].Signal();
|
||||
commands_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/array.h>
|
||||
#include <glacier/container/array_view.h>
|
||||
#include <glacier/status/error.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
|
@ -19,7 +21,9 @@ class AhciPort {
|
|||
bool IsSata() { return port_struct_->signature == 0x101; }
|
||||
bool IsInit() { return port_struct_ != nullptr && command_structures_; }
|
||||
|
||||
glcr::ErrorCode IssueCommand(Command* command);
|
||||
glcr::ErrorCode Identify();
|
||||
|
||||
glcr::ErrorOr<mmth::Semaphore*> IssueCommand(Command* command);
|
||||
|
||||
void HandleIrq();
|
||||
|
||||
|
@ -35,5 +39,6 @@ class AhciPort {
|
|||
glcr::ArrayView<CommandTable> command_tables_;
|
||||
|
||||
Command* commands_[32];
|
||||
glcr::Array<mmth::Semaphore> command_signals_;
|
||||
uint32_t commands_issued_ = 0;
|
||||
};
|
||||
|
|
|
@ -19,12 +19,6 @@ void* memcpy(void* dest, const void* src, uint64_t count) {
|
|||
|
||||
Command::~Command() {}
|
||||
|
||||
void Command::SignalComplete() {
|
||||
OnComplete();
|
||||
callback_semaphore_.Signal();
|
||||
}
|
||||
void Command::WaitComplete() { callback_semaphore_.Wait(); }
|
||||
|
||||
void IdentifyDeviceCommand::PopulateFis(uint8_t* command_fis) {
|
||||
HostToDeviceRegisterFis fis __attribute__((aligned(16))){
|
||||
.fis_type = FIS_TYPE_REG_H2D,
|
||||
|
|
|
@ -14,15 +14,6 @@ class Command {
|
|||
virtual ~Command();
|
||||
virtual void PopulateFis(uint8_t* command_fis) = 0;
|
||||
virtual void PopulatePrdt(PhysicalRegionDescriptor* prdt) = 0;
|
||||
void WaitComplete();
|
||||
void SignalComplete();
|
||||
|
||||
virtual void OnComplete() {}
|
||||
|
||||
private:
|
||||
// TODO: Make this owned by the device so that we don't have to create a new
|
||||
// one with the kernel every time a command is issued.
|
||||
mmth::Semaphore callback_semaphore_;
|
||||
};
|
||||
|
||||
class IdentifyDeviceCommand : public Command {
|
||||
|
@ -31,7 +22,7 @@ class IdentifyDeviceCommand : public Command {
|
|||
virtual void PopulateFis(uint8_t* command_fis) override;
|
||||
virtual void PopulatePrdt(PhysicalRegionDescriptor* prdt) override;
|
||||
|
||||
virtual void OnComplete() override;
|
||||
void OnComplete();
|
||||
|
||||
private:
|
||||
AhciPort* port_;
|
||||
|
|
|
@ -21,9 +21,8 @@ glcr::Status DenaliServer::HandleRead(const ReadRequest& req,
|
|||
mmth::OwnedMemoryRegion::ContiguousPhysical(req.size() * 512, &paddr);
|
||||
|
||||
DmaReadCommand command(req.lba(), req.size(), paddr);
|
||||
device->IssueCommand(&command);
|
||||
|
||||
command.WaitComplete();
|
||||
ASSIGN_OR_RETURN(auto semaphore, device->IssueCommand(&command));
|
||||
semaphore->Wait();
|
||||
|
||||
resp.set_device_id(req.device_id());
|
||||
resp.set_size(req.size());
|
||||
|
@ -51,8 +50,8 @@ glcr::Status DenaliServer::HandleReadMany(const ReadManyRequest& req,
|
|||
uint64_t lba = req.lba().at(i);
|
||||
uint64_t size = req.sector_cnt().at(i);
|
||||
DmaReadCommand command(lba, size, region_paddr);
|
||||
device->IssueCommand(&command);
|
||||
command.WaitComplete();
|
||||
ASSIGN_OR_RETURN(auto semaphore, device->IssueCommand(&command));
|
||||
semaphore->Wait();
|
||||
|
||||
region_paddr += size * 512;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue