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