Map PCI device memory regions
This commit is contained in:
parent
5179b5881b
commit
2935903bae
@ -2,6 +2,7 @@ module hulk.pci;
|
||||
|
||||
import hulk.cpu;
|
||||
import hulk.klog;
|
||||
import hulk.hurl;
|
||||
import hulk.hurl.a1;
|
||||
|
||||
struct Pci
|
||||
@ -37,6 +38,7 @@ struct Pci
|
||||
|
||||
void initialize(Address address, ushort vendor_id, ushort device_id)
|
||||
{
|
||||
this.address = address;
|
||||
this.vendor_id = vendor_id;
|
||||
this.device_id = device_id;
|
||||
uint reg2 = read_config_register(address, 2u);
|
||||
@ -50,6 +52,72 @@ struct Pci
|
||||
uint reg3 = read_config_register(address, 3u);
|
||||
header_type = (reg3 >> 16u) & 0x7Fu;
|
||||
multifunction = (address.function_nr == 0u) && ((reg3 & (1u << 23u)) != 0u);
|
||||
|
||||
if (header_type == 0u)
|
||||
{
|
||||
map_memory_regions();
|
||||
}
|
||||
}
|
||||
|
||||
private void map_memory_regions()
|
||||
{
|
||||
uint[2] r;
|
||||
uint[2] s;
|
||||
for (uint reg_no = 4u; reg_no <= 9u; reg_no++)
|
||||
{
|
||||
/* Read the BAR. */
|
||||
r[0] = read_config_register(address, reg_no);
|
||||
/* Skip zeroed BARs. */
|
||||
if (r[0] == 0u)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Skip I/O BARs. */
|
||||
if ((r[0] & 1u) != 0u)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool is_64bit;
|
||||
uint bar_type = (r[0] >> 1u) & 0x3u;
|
||||
if (bar_type == 0u)
|
||||
{
|
||||
/* 32-bit region. */
|
||||
r[1] = 0u;
|
||||
}
|
||||
else if ((bar_type == 2u) && (reg_no < 9u))
|
||||
{
|
||||
/* 64-bit region. */
|
||||
is_64bit = true;
|
||||
r[1] = read_config_register(address, reg_no + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine the region length. */
|
||||
write_config_register(address, reg_no, 0xFFFF_FFFFu);
|
||||
s[0] = read_config_register(address, reg_no);
|
||||
write_config_register(address, reg_no, r[0]);
|
||||
if (is_64bit)
|
||||
{
|
||||
write_config_register(address, reg_no + 1, 0xFFFF_FFFFu);
|
||||
s[1] = read_config_register(address, reg_no + 1);
|
||||
write_config_register(address, reg_no + 1, r[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s[1] = 0xFFFF_FFFFu;
|
||||
}
|
||||
ulong addr = (cast(ulong)r[0] & 0xFFFF_FFF0u) | (cast(ulong)r[1] << 32u);
|
||||
ulong length = ~((cast(ulong)s[0] & 0xFFFF_FFF0u) | (cast(ulong)s[1] << 32u)) + 1u;
|
||||
ulong flags = (r[0] & 0x8) != 0u ? PT_WRITE_THROUGH : 0u;
|
||||
Hurl.identity_map_range(addr, length, flags);
|
||||
if (is_64bit)
|
||||
{
|
||||
reg_no++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user