forked from Bananymous/banan-os
101 lines
2.6 KiB
C++
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 {};
|
|
}
|
|
|
|
}
|