Add ATA drive support #27

Merged
apio merged 28 commits from please-read-my-ata-drive into main 2023-06-16 19:40:11 +00:00
3 changed files with 74 additions and 8 deletions
Showing only changes of commit 5d16754632 - Show all commits

View File

@ -9,6 +9,10 @@ struct ScanInfo
namespace PCI
{
BAR::BAR(u32 raw) : m_raw(raw)
{
}
Device::ID read_id(const Device::Address& address)
{
const u16 vendor = read16(address, Field::VendorID);
@ -108,4 +112,13 @@ namespace PCI
}
}
}
BAR Device::getBAR(u8 index) const
{
check(index < 6);
u32 raw = read32(address, 0x10 + (index * 4));
return { raw };
}
}

View File

@ -27,6 +27,45 @@ namespace PCI
InterruptLine = 0x3c,
};
struct BAR
{
public:
BAR(u32 raw);
bool is_iospace()
{
return m_raw & 0x01;
}
bool is_memory_space()
{
return !is_iospace();
}
u16 port()
{
return (u16)(m_raw & 0xfffffffc);
}
u8 type()
{
return (m_raw >> 1) & 0x03;
}
bool is_prefetchable()
{
return m_raw & (1 << 3);
}
u32 address_32bit()
{
return m_raw & 0xFFFFFFF0;
}
private:
u32 m_raw;
};
struct Device
{
struct ID
@ -49,6 +88,8 @@ namespace PCI
u32 function;
};
BAR getBAR(u8 index) const;
ID id;
Type type;
Address address;

View File

@ -156,15 +156,27 @@ namespace ATA
int offset = m_channel_index ? 2 : 0;
m_is_pci_native_mode = m_controller->device().type.prog_if & (1 << offset);
u32 control_port_base_address;
u32 io_base_address;
u16 control_port_base_address;
u16 io_base_address;
if (m_is_pci_native_mode)
{
// FIXME: Properly decode BARs.
io_base_address = PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR2 : PCI::BAR0);
control_port_base_address =
PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR3 : PCI::BAR1);
auto io_base = m_controller->device().getBAR(m_channel_index ? 2 : 0);
if (!io_base.is_iospace())
{
kwarnln("ata: Channel %d's IO base BAR is not in IO space", m_channel_index);
return false;
}
io_base_address = io_base.port();
auto io_control = m_controller->device().getBAR(m_channel_index ? 3 : 1);
if (!io_control.is_iospace())
{
kwarnln("ata: Channel %d's control base BAR is not in IO space", m_channel_index);
return false;
}
control_port_base_address = io_control.port();
}
else
{
@ -172,8 +184,8 @@ namespace ATA
control_port_base_address = m_channel_index ? 0x376 : 0x3f6;
}
m_io_base = (u16)io_base_address;
m_control_base = (u16)control_port_base_address + 2;
m_io_base = io_base_address;
m_control_base = control_port_base_address + 2;
if (m_is_pci_native_mode) m_interrupt_line = PCI::read8(m_controller->device().address, PCI::InterruptLine);
else