banan-os/kernel/kernel/Storage/ATA/ATAController.cpp

101 lines
2.6 KiB
C++

#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/InterruptController.h>
#include <kernel/Storage/ATA/AHCI/Controller.h>
#include <kernel/Storage/ATA/ATABus.h>
#include <kernel/Storage/ATA/ATAController.h>
#include <kernel/Storage/ATA/ATADefinitions.h>
#include <kernel/Storage/ATA/ATADevice.h>
namespace Kernel
{
BAN::ErrorOr<BAN::RefPtr<StorageController>> ATAController::create(PCI::Device& pci_device)
{
StorageController* controller_ptr = nullptr;
switch (pci_device.subclass())
{
case 0x01:
controller_ptr = new ATAController(pci_device);
break;
case 0x05:
dwarnln("unsupported DMA ATA Controller");
return BAN::Error::from_errno(ENOTSUP);
case 0x06:
controller_ptr = new AHCIController(pci_device);
break;
default:
ASSERT_NOT_REACHED();
}
if (controller_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto controller = BAN::RefPtr<StorageController>::adopt(controller_ptr);
TRY(controller->initialize());
return controller;
}
BAN::ErrorOr<void> ATAController::initialize()
{
BAN::Vector<BAN::RefPtr<ATABus>> buses;
uint8_t prog_if = m_pci_device.read_byte(0x09);
// FIXME: support native mode
if ((prog_if & ATA_PROGIF_CAN_MODIFY_PRIMARY_NATIVE) && (prog_if & ATA_PROGIF_PRIMARY_NATIVE))
{
prog_if &= ~ATA_PROGIF_PRIMARY_NATIVE;
m_pci_device.write_byte(0x09, prog_if);
dprintln("enabling compatibility mode for bus 1");
}
if ((prog_if & ATA_PROGIF_CAN_MODIFY_SECONDARY_NATIVE) && (prog_if & ATA_PROGIF_SECONDARY_NATIVE))
{
prog_if &= ~ATA_PROGIF_SECONDARY_NATIVE;
m_pci_device.write_byte(0x09, prog_if);
dprintln("enabling compatibility mode for bus 2");
}
if (!(prog_if & ATA_PROGIF_PRIMARY_NATIVE))
{
if (InterruptController::get().reserve_irq(14).is_error())
dwarnln("Could not reserve interrupt {} for ATA device", 14);
else
{
auto bus_or_error = ATABus::create(0x1F0, 0x3F6, 14);
if (bus_or_error.is_error())
dprintln("IDE ATABus: {}", bus_or_error.error());
else
TRY(buses.push_back(bus_or_error.release_value()));
}
}
else
{
dprintln("unsupported IDE ATABus in native mode");
}
if (!(prog_if & ATA_PROGIF_SECONDARY_NATIVE))
{
if (InterruptController::get().reserve_irq(15).is_error())
dwarnln("Could not reserver interrupt {} for ATA device", 15);
else
{
auto bus_or_error = ATABus::create(0x170, 0x376, 15);
if (bus_or_error.is_error())
dprintln("IDE ATABus: {}", bus_or_error.error());
else
TRY(buses.push_back(bus_or_error.release_value()));
}
}
else
{
dprintln("unsupported IDE ATABus in native mode");
}
return {};
}
}