[Denali] Add a simpler command method and use it to send identify.
This commit is contained in:
parent
e71017070f
commit
3e1da2bc90
|
@ -44,10 +44,21 @@ AhciPort::AhciPort(AhciPortHba* port) : port_struct_(port) {
|
|||
|
||||
glcr::ErrorCode AhciPort::Identify() {
|
||||
if (IsSata()) {
|
||||
IdentifyDeviceCommand identify(this);
|
||||
CommandInfo identify{
|
||||
.command = kIdentifyDevice,
|
||||
.lba = 0,
|
||||
.sectors = 1,
|
||||
.paddr = 0,
|
||||
};
|
||||
auto region =
|
||||
mmth::OwnedMemoryRegion::ContiguousPhysical(0x200, &identify.paddr);
|
||||
ASSIGN_OR_RETURN(auto* sem, IssueCommand(identify));
|
||||
sem->Wait();
|
||||
identify.OnComplete();
|
||||
uint16_t* ident = reinterpret_cast<uint16_t*>(region.vaddr());
|
||||
uint32_t* sector_size = reinterpret_cast<uint32_t*>(ident + 117);
|
||||
dbgln("Sector size: {}", *sector_size);
|
||||
uint64_t* lbas = reinterpret_cast<uint64_t*>(ident + 100);
|
||||
dbgln("LBA Count: {}", *lbas);
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
|
@ -77,6 +88,61 @@ glcr::ErrorOr<mmth::Semaphore*> AhciPort::IssueCommand(const Command& command) {
|
|||
return &command_signals_[slot];
|
||||
}
|
||||
|
||||
glcr::ErrorOr<mmth::Semaphore*> AhciPort::IssueCommand(
|
||||
const CommandInfo& command) {
|
||||
uint64_t slot;
|
||||
for (slot = 0; slot < 32; slot++) {
|
||||
if (!(commands_issued_ & (1 << slot))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slot == 32) {
|
||||
dbgln("All slots full");
|
||||
return glcr::INTERNAL;
|
||||
}
|
||||
|
||||
auto* fis = reinterpret_cast<HostToDeviceRegisterFis*>(
|
||||
command_tables_[slot].command_fis);
|
||||
*fis = HostToDeviceRegisterFis{
|
||||
.fis_type = FIS_TYPE_REG_H2D,
|
||||
.pmp_and_c = 0x80,
|
||||
.command = command.command,
|
||||
.featurel = 0,
|
||||
|
||||
.lba0 = static_cast<uint8_t>(command.lba & 0xFF),
|
||||
.lba1 = static_cast<uint8_t>((command.lba >> 8) & 0xFF),
|
||||
.lba2 = static_cast<uint8_t>((command.lba >> 16) & 0xFF),
|
||||
.device = (1 << 6), // ATA LBA Mode
|
||||
|
||||
.lba3 = static_cast<uint8_t>((command.lba >> 24) & 0xFF),
|
||||
.lba4 = static_cast<uint8_t>((command.lba >> 32) & 0xFF),
|
||||
.lba5 = static_cast<uint8_t>((command.lba >> 40) & 0xFF),
|
||||
.featureh = 0,
|
||||
|
||||
.count = command.sectors,
|
||||
.icc = 0,
|
||||
.control = 0,
|
||||
|
||||
.reserved = 0,
|
||||
};
|
||||
|
||||
command_tables_[slot].prdt[0].region_address = command.paddr;
|
||||
command_tables_[slot].prdt[0].byte_count = 512 * command.sectors;
|
||||
|
||||
command_list_->command_headers[slot].prd_table_length = 1;
|
||||
command_list_->command_headers[slot].command =
|
||||
(sizeof(HostToDeviceRegisterFis) / 2) & 0x1F;
|
||||
// Set prefetch bit.
|
||||
command_list_->command_headers[slot].command |= (1 << 7);
|
||||
|
||||
// TODO: Synchronization-wise we need to ensure this is set in the same
|
||||
// critical section as where we select a slot.
|
||||
commands_issued_ |= (1 << slot);
|
||||
port_struct_->command_issue |= (1 << slot);
|
||||
|
||||
return &command_signals_[slot];
|
||||
}
|
||||
|
||||
void AhciPort::DumpInfo() {
|
||||
dbgln("Comlist: {x}", port_struct_->command_list_base);
|
||||
dbgln("FIS: {x}", port_struct_->fis_base);
|
||||
|
|
|
@ -24,6 +24,7 @@ class AhciPort {
|
|||
glcr::ErrorCode Identify();
|
||||
|
||||
glcr::ErrorOr<mmth::Semaphore*> IssueCommand(const Command& command);
|
||||
glcr::ErrorOr<mmth::Semaphore*> IssueCommand(const CommandInfo& command);
|
||||
|
||||
void HandleIrq();
|
||||
|
||||
|
|
|
@ -19,37 +19,6 @@ void* memcpy(void* dest, const void* src, uint64_t count) {
|
|||
|
||||
Command::~Command() {}
|
||||
|
||||
void IdentifyDeviceCommand::PopulateFis(uint8_t* command_fis) const {
|
||||
HostToDeviceRegisterFis fis __attribute__((aligned(16))){
|
||||
.fis_type = FIS_TYPE_REG_H2D,
|
||||
.pmp_and_c = 0x80,
|
||||
.command = kIdentifyDevice,
|
||||
.device = 0,
|
||||
};
|
||||
|
||||
memcpy(command_fis, &fis, sizeof(fis));
|
||||
}
|
||||
|
||||
void IdentifyDeviceCommand::PopulatePrdt(PhysicalRegionDescriptor* prdt) const {
|
||||
prdt[0].region_address = paddr_;
|
||||
prdt[0].byte_count = 0x200 - 1;
|
||||
dbgln("paddr: {x}", paddr_);
|
||||
uint16_t* ident = reinterpret_cast<uint16_t*>(identify_.vaddr());
|
||||
dbgln("vaddr: {x}", identify_.vaddr());
|
||||
for (uint32_t i = 0; i < 256; i++) {
|
||||
ident[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void IdentifyDeviceCommand::OnComplete() {
|
||||
uint16_t* ident = reinterpret_cast<uint16_t*>(identify_.vaddr());
|
||||
uint32_t* sector_size = reinterpret_cast<uint32_t*>(ident + 117);
|
||||
dbgln("Sector size: {}", *sector_size);
|
||||
uint64_t* lbas = reinterpret_cast<uint64_t*>(ident + 100);
|
||||
dbgln("LBA Count: {}", *lbas);
|
||||
// TODO tell the port its sector size.
|
||||
}
|
||||
|
||||
DmaReadCommand::DmaReadCommand(uint64_t lba, uint64_t sector_cnt,
|
||||
uint64_t paddr)
|
||||
: lba_(lba), sector_cnt_(sector_cnt), paddr_(paddr) {}
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
|
||||
class AhciPort;
|
||||
|
||||
struct CommandInfo {
|
||||
uint8_t command;
|
||||
uint64_t lba;
|
||||
uint16_t sectors;
|
||||
uint64_t paddr;
|
||||
};
|
||||
|
||||
class Command {
|
||||
public:
|
||||
Command() = default;
|
||||
|
@ -16,21 +23,6 @@ class Command {
|
|||
virtual void PopulatePrdt(PhysicalRegionDescriptor* prdt) const = 0;
|
||||
};
|
||||
|
||||
class IdentifyDeviceCommand : public Command {
|
||||
public:
|
||||
IdentifyDeviceCommand(AhciPort* port) : port_(port) {}
|
||||
virtual void PopulateFis(uint8_t* command_fis) const override;
|
||||
virtual void PopulatePrdt(PhysicalRegionDescriptor* prdt) const override;
|
||||
|
||||
void OnComplete();
|
||||
|
||||
private:
|
||||
AhciPort* port_;
|
||||
uint64_t paddr_;
|
||||
mmth::OwnedMemoryRegion identify_ =
|
||||
mmth::OwnedMemoryRegion::ContiguousPhysical(0x200, &paddr_);
|
||||
};
|
||||
|
||||
class DmaReadCommand : public Command {
|
||||
public:
|
||||
DmaReadCommand(uint64_t lba, uint64_t sector_cnt, uint64_t dest_paddr);
|
||||
|
|
Loading…
Reference in New Issue