kernel: Handle device BARs properly

This commit is contained in:
apio 2023-05-13 17:54:02 +02:00
parent 6307b01689
commit 5d16754632
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 74 additions and 8 deletions

View File

@ -9,6 +9,10 @@ struct ScanInfo
namespace PCI namespace PCI
{ {
BAR::BAR(u32 raw) : m_raw(raw)
{
}
Device::ID read_id(const Device::Address& address) Device::ID read_id(const Device::Address& address)
{ {
const u16 vendor = read16(address, Field::VendorID); 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, 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 Device
{ {
struct ID struct ID
@ -49,6 +88,8 @@ namespace PCI
u32 function; u32 function;
}; };
BAR getBAR(u8 index) const;
ID id; ID id;
Type type; Type type;
Address address; Address address;

View File

@ -156,15 +156,27 @@ namespace ATA
int offset = m_channel_index ? 2 : 0; int offset = m_channel_index ? 2 : 0;
m_is_pci_native_mode = m_controller->device().type.prog_if & (1 << offset); m_is_pci_native_mode = m_controller->device().type.prog_if & (1 << offset);
u32 control_port_base_address; u16 control_port_base_address;
u32 io_base_address; u16 io_base_address;
if (m_is_pci_native_mode) if (m_is_pci_native_mode)
{ {
// FIXME: Properly decode BARs. auto io_base = m_controller->device().getBAR(m_channel_index ? 2 : 0);
io_base_address = PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR2 : PCI::BAR0); if (!io_base.is_iospace())
control_port_base_address = {
PCI::read32(m_controller->device().address, m_channel_index ? PCI::BAR3 : PCI::BAR1); 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 else
{ {
@ -172,8 +184,8 @@ namespace ATA
control_port_base_address = m_channel_index ? 0x376 : 0x3f6; control_port_base_address = m_channel_index ? 0x376 : 0x3f6;
} }
m_io_base = (u16)io_base_address; m_io_base = io_base_address;
m_control_base = (u16)control_port_base_address + 2; 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); if (m_is_pci_native_mode) m_interrupt_line = PCI::read8(m_controller->device().address, PCI::InterruptLine);
else else