mirror of
https://github.com/RGBCube/serenity
synced 2025-05-15 06:34:59 +00:00

This abstraction layer is mainly for ATA ports (AHCI ports, IDE ports). The goal is to create a convenient and flexible framework so it's possible to expand to support other types of controller (e.g. Intel PIIX and ICH IDE controllers) and to abstract operations that are possible on each component. Currently only the ATA IDE code is affected by this, making it much cleaner and readable - the ATA bus mastering code is moved to the ATAPort code so more implementations in the near future can take advantage of such functionality easily. In addition to that, the hierarchy of the ATA IDE code resembles more of the SATA AHCI code now, which means the IDEChannel class is solely responsible for getting interrupts, passing them for further processing in the ATAPort code to take care of the rest of the handling logic.
101 lines
2.5 KiB
C++
101 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) 2020-2022, Liav A. <liavalb@hotmail.co.il>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/OwnPtr.h>
|
|
#include <AK/RefPtr.h>
|
|
#include <AK/Types.h>
|
|
#include <Kernel/Bus/PCI/API.h>
|
|
#include <Kernel/FileSystem/ProcFS.h>
|
|
#include <Kernel/Sections.h>
|
|
#include <Kernel/Storage/ATA/ATADiskDevice.h>
|
|
#include <Kernel/Storage/ATA/GenericIDE/Channel.h>
|
|
#include <Kernel/Storage/ATA/GenericIDE/Controller.h>
|
|
|
|
namespace Kernel {
|
|
|
|
UNMAP_AFTER_INIT NonnullRefPtr<IDEController> IDEController::initialize()
|
|
{
|
|
return adopt_ref(*new IDEController());
|
|
}
|
|
|
|
bool IDEController::reset()
|
|
{
|
|
TODO();
|
|
}
|
|
|
|
bool IDEController::shutdown()
|
|
{
|
|
TODO();
|
|
}
|
|
|
|
size_t IDEController::devices_count() const
|
|
{
|
|
size_t count = 0;
|
|
for (u32 index = 0; index < 4; index++) {
|
|
if (!device(index).is_null())
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
void IDEController::start_request(ATADevice const& device, AsyncBlockDeviceRequest& request)
|
|
{
|
|
auto& address = device.ata_address();
|
|
VERIFY(address.subport < 2);
|
|
switch (address.port) {
|
|
case 0: {
|
|
auto result = m_channels[0].start_request(device, request);
|
|
// FIXME: Propagate errors properly
|
|
VERIFY(!result.is_error());
|
|
return;
|
|
}
|
|
case 1: {
|
|
auto result = m_channels[1].start_request(device, request);
|
|
// FIXME: Propagate errors properly
|
|
VERIFY(!result.is_error());
|
|
return;
|
|
}
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
void IDEController::complete_current_request(AsyncDeviceRequest::RequestResult)
|
|
{
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
UNMAP_AFTER_INIT IDEController::IDEController() = default;
|
|
UNMAP_AFTER_INIT IDEController::~IDEController() = default;
|
|
|
|
RefPtr<StorageDevice> IDEController::device_by_channel_and_position(u32 index) const
|
|
{
|
|
switch (index) {
|
|
case 0:
|
|
return m_channels[0].connected_device(0);
|
|
case 1:
|
|
return m_channels[0].connected_device(1);
|
|
case 2:
|
|
return m_channels[1].connected_device(0);
|
|
case 3:
|
|
return m_channels[1].connected_device(1);
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
RefPtr<StorageDevice> IDEController::device(u32 index) const
|
|
{
|
|
NonnullRefPtrVector<StorageDevice> connected_devices;
|
|
for (size_t index = 0; index < 4; index++) {
|
|
auto checked_device = device_by_channel_and_position(index);
|
|
if (checked_device.is_null())
|
|
continue;
|
|
connected_devices.append(checked_device.release_nonnull());
|
|
}
|
|
if (index >= connected_devices.size())
|
|
return nullptr;
|
|
return connected_devices[index];
|
|
}
|
|
}
|