mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-27 01:50:24 +00:00
Kernel/Storage: Add a whole bunch of AHCI debug output
This commit is contained in:
parent
b7dd5dc7c3
commit
cf9ce0d857
Notes:
sideshowbarker
2024-07-18 21:14:54 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/cf9ce0d8578 Pull-request: https://github.com/SerenityOS/serenity/pull/5855
3 changed files with 52 additions and 4 deletions
|
@ -44,6 +44,8 @@ bool AHCIController::reset()
|
|||
{
|
||||
hba().control_regs.ghc = 1;
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "{}: AHCI Controller reset", pci_address());
|
||||
|
||||
full_memory_barrier();
|
||||
size_t retry = 0;
|
||||
|
||||
|
@ -110,6 +112,9 @@ AHCI::HBADefinedCapabilities AHCIController::capabilities() const
|
|||
{
|
||||
u32 capabilities = hba().control_regs.cap;
|
||||
u32 extended_capabilities = hba().control_regs.cap2;
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "{}: AHCI Controller Capabilities = 0x{:08x}, Extended Capabilities = 0x{:08x}", pci_address(), capabilities, extended_capabilities);
|
||||
|
||||
return (AHCI::HBADefinedCapabilities) {
|
||||
(capabilities & 0b11111) + 1,
|
||||
((capabilities >> 8) & 0b11111) + 1,
|
||||
|
@ -160,6 +165,10 @@ void AHCIController::initialize()
|
|||
dmesgln("{}: AHCI controller reset", pci_address());
|
||||
}
|
||||
dbgln("{}: AHCI command list entries count - {}", pci_address(), hba_capabilities().max_command_list_entries_count);
|
||||
|
||||
u32 version = hba().control_regs.version;
|
||||
dbgln_if(AHCI_DEBUG, "{}: AHCI Controller Version = 0x{:08x}", pci_address(), version);
|
||||
|
||||
hba().control_regs.ghc = 0x80000000; // Ensure that HBA knows we are AHCI aware.
|
||||
PCI::enable_interrupt_line(pci_address());
|
||||
PCI::enable_bus_mastering(pci_address());
|
||||
|
|
|
@ -68,6 +68,10 @@ AHCIPort::AHCIPort(const AHCIPortHandler& handler, volatile AHCI::PortRegisters&
|
|||
m_fis_receive_page = MM.allocate_supervisor_physical_page();
|
||||
if (m_command_list_page.is_null() || m_fis_receive_page.is_null())
|
||||
return;
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Command list page at {}", representative_port_index(), m_command_list_page->paddr());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: FIS receive page at {}", representative_port_index(), m_command_list_page->paddr());
|
||||
|
||||
for (size_t index = 0; index < 1; index++) {
|
||||
m_dma_buffers.append(MM.allocate_supervisor_physical_page().release_nonnull());
|
||||
}
|
||||
|
@ -75,11 +79,14 @@ AHCIPort::AHCIPort(const AHCIPortHandler& handler, volatile AHCI::PortRegisters&
|
|||
m_command_table_pages.append(MM.allocate_supervisor_physical_page().release_nonnull());
|
||||
}
|
||||
m_command_list_region = MM.allocate_kernel_region(m_command_list_page->paddr(), PAGE_SIZE, "AHCI Port Command List", Region::Access::Read | Region::Access::Write, Region::Cacheable::No);
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Command list region at {}", representative_port_index(), m_command_list_region->vaddr());
|
||||
|
||||
m_interrupt_enable.set_all();
|
||||
}
|
||||
|
||||
void AHCIPort::clear_sata_error_register() const
|
||||
{
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Clearing SATA error register.", representative_port_index());
|
||||
m_port_registers.serr = m_port_registers.serr;
|
||||
}
|
||||
|
||||
|
@ -196,6 +203,8 @@ bool AHCIPort::reset()
|
|||
{
|
||||
ScopedSpinLock lock(m_lock);
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Resetting", representative_port_index());
|
||||
|
||||
if (m_disabled_by_firmware) {
|
||||
dmesgln("AHCI Port {}: Disabled by firmware ", representative_port_index());
|
||||
return false;
|
||||
|
@ -224,9 +233,11 @@ bool AHCIPort::initialize_without_reset()
|
|||
bool AHCIPort::initialize()
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: SIG {:x}", representative_port_index(), static_cast<u32>(m_port_registers.sig));
|
||||
if (!is_phy_enabled())
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Initialization. Signature = 0x{:08x}", representative_port_index(), static_cast<u32>(m_port_registers.sig));
|
||||
if (!is_phy_enabled()) {
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Bailing initialization, Phy is not enabled.", representative_port_index());
|
||||
return false;
|
||||
}
|
||||
rebase();
|
||||
power_on();
|
||||
spin_up();
|
||||
|
@ -271,6 +282,8 @@ bool AHCIPort::initialize()
|
|||
// FIXME: We don't support ATAPI devices yet, so for now we don't "create" them
|
||||
if (!is_atapi_attached()) {
|
||||
m_connected_device = SATADiskDevice::create(m_parent_handler->hba_controller(), *this, logical_sector_size, max_addressable_sector);
|
||||
} else {
|
||||
dbgln("AHCI Port {}: Ignoring ATAPI devices for now as we don't currently support them.", representative_port_index());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -349,6 +362,7 @@ void AHCIPort::rebase()
|
|||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
VERIFY(!m_command_list_page.is_null() && !m_fis_receive_page.is_null());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Rebasing.", representative_port_index());
|
||||
full_memory_barrier();
|
||||
stop_command_list_processing();
|
||||
stop_fis_receiving();
|
||||
|
@ -380,6 +394,7 @@ bool AHCIPort::is_operable() const
|
|||
void AHCIPort::set_active_state() const
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Switching to active state.", representative_port_index());
|
||||
m_port_registers.cmd = (m_port_registers.cmd & 0x0ffffff) | (1 << 28);
|
||||
}
|
||||
|
||||
|
@ -420,28 +435,32 @@ void AHCIPort::start_request(AsyncBlockDeviceRequest& request)
|
|||
{
|
||||
ScopedSpinLock lock(m_lock);
|
||||
VERIFY(!m_current_scatter_list);
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Request start", representative_port_index());
|
||||
|
||||
auto result = prepare_and_set_scatter_list(request);
|
||||
if (result.has_value()) {
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Request failure.", representative_port_index());
|
||||
request.complete(result.value());
|
||||
return;
|
||||
}
|
||||
|
||||
auto success = access_device(request.request_type(), request.block_index(), request.block_count());
|
||||
if (!success) {
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Request failure.", representative_port_index());
|
||||
request.complete(AsyncDeviceRequest::Failure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.request_type() == AsyncBlockDeviceRequest::Read) {
|
||||
if (!request.write_to_buffer(request.buffer(), m_current_scatter_list->dma_region().as_ptr(), m_connected_device->block_size() * request.block_count())) {
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Request failure, memory fault occurred when reading in data.", representative_port_index());
|
||||
request.complete(AsyncDeviceRequest::MemoryFault);
|
||||
m_current_scatter_list = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_current_scatter_list = nullptr;
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Reqeust success", representative_port_index());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Request success", representative_port_index());
|
||||
request.complete(AsyncDeviceRequest::Success);
|
||||
}
|
||||
|
||||
|
@ -454,6 +473,7 @@ bool AHCIPort::spin_until_ready() const
|
|||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
size_t spin = 0;
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Spinning until ready.", representative_port_index());
|
||||
while ((m_port_registers.tfd & (ATA_SR_BSY | ATA_SR_DRQ)) && spin <= 100) {
|
||||
IO::delay(1000);
|
||||
spin++;
|
||||
|
@ -490,8 +510,13 @@ bool AHCIPort::access_device(AsyncBlockDeviceRequest::RequestType direction, u64
|
|||
// handshake error bit in PxSERR register if CFL is incorrect.
|
||||
command_list_entries[unused_command_header.value()].attributes = (size_t)FIS::DwordCount::RegisterHostToDevice | AHCI::CommandHeaderAttributes::P | AHCI::CommandHeaderAttributes::C | (is_atapi_attached() ? AHCI::CommandHeaderAttributes::A : 0) | (direction == AsyncBlockDeviceRequest::RequestType::Write ? AHCI::CommandHeaderAttributes::W : 0);
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: CLE: ctba=0x{:08x}, ctbau=0x{:08x}, prdbc=0x{:08x}, prdtl=0x{:04x}, attributes=0x{:04x}", representative_port_index(), (u32)command_list_entries[unused_command_header.value()].ctba, (u32)command_list_entries[unused_command_header.value()].ctbau, (u32)command_list_entries[unused_command_header.value()].prdbc, (u16)command_list_entries[unused_command_header.value()].prdtl, (u16)command_list_entries[unused_command_header.value()].attributes);
|
||||
|
||||
auto command_table_region = MM.allocate_kernel_region(m_command_table_pages[unused_command_header.value()].paddr().page_base(), page_round_up(sizeof(AHCI::CommandTable)), "AHCI Command Table", Region::Access::Read | Region::Access::Write, Region::Cacheable::No);
|
||||
auto& command_table = *(volatile AHCI::CommandTable*)command_table_region->vaddr().as_ptr();
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Allocated command table at {}", representative_port_index(), command_table_region->vaddr());
|
||||
|
||||
memset(const_cast<u8*>(command_table.command_fis), 0, 64);
|
||||
|
||||
size_t scatter_entry_index = 0;
|
||||
|
@ -626,6 +651,7 @@ void AHCIPort::start_command_list_processing() const
|
|||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
VERIFY(is_operable());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Starting command list processing.", representative_port_index());
|
||||
m_port_registers.cmd = m_port_registers.cmd | 1;
|
||||
}
|
||||
|
||||
|
@ -633,47 +659,55 @@ void AHCIPort::mark_command_header_ready_to_process(u8 command_header_index) con
|
|||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
VERIFY(is_operable());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Marking command header at index {} as ready to process.", representative_port_index(), command_header_index);
|
||||
m_port_registers.ci = 1 << command_header_index;
|
||||
}
|
||||
|
||||
void AHCIPort::stop_command_list_processing() const
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Stopping command list processing.", representative_port_index());
|
||||
m_port_registers.cmd = m_port_registers.cmd & 0xfffffffe;
|
||||
}
|
||||
|
||||
void AHCIPort::start_fis_receiving() const
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Starting FIS receiving.", representative_port_index());
|
||||
m_port_registers.cmd = m_port_registers.cmd | (1 << 4);
|
||||
}
|
||||
|
||||
void AHCIPort::power_on() const
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Power on. Cold presence detection? {}", representative_port_index(), (bool)(m_port_registers.cmd & (1 << 20)));
|
||||
if (!(m_port_registers.cmd & (1 << 20)))
|
||||
return;
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Powering on device.", representative_port_index());
|
||||
m_port_registers.cmd = m_port_registers.cmd | (1 << 2);
|
||||
}
|
||||
|
||||
void AHCIPort::spin_up() const
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}, staggered spin up? {}", representative_port_index(), m_parent_handler->hba_capabilities().staggered_spin_up_supported);
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Spin up. Staggered spin up? {}", representative_port_index(), m_parent_handler->hba_capabilities().staggered_spin_up_supported);
|
||||
if (!m_parent_handler->hba_capabilities().staggered_spin_up_supported)
|
||||
return;
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Spinning up device.", representative_port_index());
|
||||
m_port_registers.cmd = m_port_registers.cmd | (1 << 1);
|
||||
}
|
||||
|
||||
void AHCIPort::stop_fis_receiving() const
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Stopping FIS receiving.", representative_port_index());
|
||||
m_port_registers.cmd = m_port_registers.cmd & 0xFFFFFFEF;
|
||||
}
|
||||
|
||||
bool AHCIPort::initiate_sata_reset()
|
||||
{
|
||||
VERIFY(m_lock.is_locked());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port {}: Initiate SATA reset", representative_port_index());
|
||||
stop_command_list_processing();
|
||||
full_memory_barrier();
|
||||
size_t retry = 0;
|
||||
|
|
|
@ -44,6 +44,9 @@ AHCIPortHandler::AHCIPortHandler(AHCIController& controller, u8 irq, AHCI::Maske
|
|||
for (size_t index = 0; index < (((size_t)AHCI::Limits::MaxPorts * 512) / PAGE_SIZE); index++) {
|
||||
m_identify_metadata_pages.append(MM.allocate_supervisor_physical_page().release_nonnull());
|
||||
}
|
||||
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port Handler: IRQ {}", irq);
|
||||
|
||||
// Clear pending interrupts, if there are any!
|
||||
m_pending_ports_interrupts.set_all();
|
||||
enable_irq();
|
||||
|
@ -101,9 +104,11 @@ AHCIPortHandler::~AHCIPortHandler()
|
|||
|
||||
void AHCIPortHandler::handle_irq(const RegisterState&)
|
||||
{
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port Handler: IRQ received");
|
||||
for (auto port_index : m_pending_ports_interrupts.to_vector()) {
|
||||
auto port = m_handled_ports.get(port_index);
|
||||
VERIFY(port.has_value());
|
||||
dbgln_if(AHCI_DEBUG, "AHCI Port Handler: Handling IRQ for port {}", port_index);
|
||||
port.value()->handle_interrupt();
|
||||
// We do this to clear the pending interrupt after we handled it.
|
||||
m_pending_ports_interrupts.set_at(port_index);
|
||||
|
|
Loading…
Reference in a new issue