kernel: Handle device BARs properly
This commit is contained in:
parent
6307b01689
commit
5d16754632
@ -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 };
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user