Kernel/PCI: Convert PCI BAR number to a strong typed enum class

This commit is contained in:
Liav A 2022-09-02 19:59:08 +03:00 committed by Linus Groh
parent f510c0ba04
commit bb6f61ee5d
10 changed files with 26 additions and 17 deletions

View file

@ -94,10 +94,10 @@ u32 get_BAR5(Address address)
return read32(address, PCI::RegisterOffset::BAR5);
}
u32 get_BAR(Address address, u8 bar)
u32 get_BAR(Address address, HeaderType0BaseRegister pci_bar)
{
VERIFY(bar <= 5);
switch (bar) {
VERIFY(to_underlying(pci_bar) <= 5);
switch (to_underlying(pci_bar)) {
case 0:
return get_BAR0(address);
case 1:
@ -138,11 +138,11 @@ static u8 read8_offsetted(Address address, u32 field) { return Access::the().rea
static u16 read16_offsetted(Address address, u32 field) { return Access::the().read16_field(address, field); }
static u32 read32_offsetted(Address address, u32 field) { return Access::the().read32_field(address, field); }
size_t get_BAR_space_size(Address address, u8 bar_number)
size_t get_BAR_space_size(Address address, HeaderType0BaseRegister pci_bar)
{
// See PCI Spec 2.3, Page 222
VERIFY(bar_number < 6);
u8 field = to_underlying(PCI::RegisterOffset::BAR0) + (bar_number << 2);
VERIFY(to_underlying(pci_bar) < 6);
u8 field = to_underlying(PCI::RegisterOffset::BAR0) + (to_underlying(pci_bar) << 2);
u32 bar_reserved = read32_offsetted(address, field);
write32_offsetted(address, field, 0xFFFFFFFF);
u32 space_size = read32_offsetted(address, field);

View file

@ -31,8 +31,8 @@ u32 get_BAR2(Address);
u32 get_BAR3(Address);
u32 get_BAR4(Address);
u32 get_BAR5(Address);
u32 get_BAR(Address address, u8 bar);
size_t get_BAR_space_size(Address, u8);
u32 get_BAR(Address address, HeaderType0BaseRegister);
size_t get_BAR_space_size(Address, HeaderType0BaseRegister);
void enable_bus_mastering(Address);
void disable_bus_mastering(Address);
void enable_io_space(Address);

View file

@ -21,6 +21,15 @@ enum class HeaderType {
Bridge = 1,
};
enum class HeaderType0BaseRegister {
BAR0 = 0,
BAR1,
BAR2,
BAR3,
BAR4,
BAR5,
};
enum class RegisterOffset {
VENDOR_ID = 0x00, // word
DEVICE_ID = 0x02, // word

View file

@ -129,14 +129,14 @@ UNMAP_AFTER_INIT void Device::initialize()
if (m_use_mmio) {
for (auto& cfg : m_configs) {
auto& mapping = m_mmio[cfg.bar];
mapping.size = PCI::get_BAR_space_size(pci_address(), cfg.bar);
mapping.size = PCI::get_BAR_space_size(pci_address(), static_cast<PCI::HeaderType0BaseRegister>(cfg.bar));
if (!mapping.base && mapping.size) {
auto region_size_or_error = Memory::page_round_up(mapping.size);
if (region_size_or_error.is_error()) {
dbgln_if(VIRTIO_DEBUG, "{}: Failed to round up size={} to pages", m_class_name, mapping.size);
continue;
}
auto region_or_error = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR(pci_address(), cfg.bar))), region_size_or_error.value(), "VirtIO MMIO"sv, Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No);
auto region_or_error = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR(pci_address(), static_cast<PCI::HeaderType0BaseRegister>(cfg.bar)))), region_size_or_error.value(), "VirtIO MMIO"sv, Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No);
if (region_or_error.is_error()) {
dbgln_if(VIRTIO_DEBUG, "{}: Failed to map bar {} - (size={}) {}", m_class_name, cfg.bar, mapping.size, region_or_error.error());
} else {

View file

@ -20,7 +20,7 @@ UNMAP_AFTER_INIT void PCISerialDevice::detect()
if (board_definition.device_id != device_identifier.hardware_id())
continue;
auto bar_base = PCI::get_BAR(device_identifier.address(), board_definition.pci_bar) & ~1;
auto bar_base = PCI::get_BAR(device_identifier.address(), static_cast<PCI::HeaderType0BaseRegister>(board_definition.pci_bar)) & ~1;
auto port_base = IOAddress(bar_base + board_definition.first_offset);
for (size_t i = 0; i < board_definition.port_count; i++) {
auto serial_device = new SerialDevice(port_base.offset(board_definition.port_size * i), current_device_minor++);

View file

@ -41,7 +41,7 @@ UNMAP_AFTER_INIT ErrorOr<void> BochsGraphicsAdapter::initialize_adapter(PCI::Dev
// Note: Bochs (the real bochs graphics adapter in the Bochs emulator) uses revision ID of 0x0
// and doesn't support memory-mapped IO registers.
bool virtual_box_hardware = (pci_device_identifier.hardware_id().vendor_id == 0x80ee && pci_device_identifier.hardware_id().device_id == 0xbeef);
auto bar0_space_size = PCI::get_BAR_space_size(pci_device_identifier.address(), 0);
auto bar0_space_size = PCI::get_BAR_space_size(pci_device_identifier.address(), PCI::HeaderType0BaseRegister::BAR0);
if (pci_device_identifier.revision_id().value() == 0x0 || virtual_box_hardware) {
m_display_connector = BochsDisplayConnector::must_create(PhysicalAddress(PCI::get_BAR0(pci_device_identifier.address()) & 0xfffffff0), bar0_space_size, virtual_box_hardware);
} else {

View file

@ -40,9 +40,9 @@ ErrorOr<void> IntelNativeGraphicsAdapter::initialize_adapter()
{
auto address = pci_address();
dbgln_if(INTEL_GRAPHICS_DEBUG, "Intel Native Graphics Adapter @ {}", address);
auto bar0_space_size = PCI::get_BAR_space_size(address, 0);
auto bar0_space_size = PCI::get_BAR_space_size(address, PCI::HeaderType0BaseRegister::BAR0);
VERIFY(bar0_space_size == 0x80000);
auto bar2_space_size = PCI::get_BAR_space_size(address, 2);
auto bar2_space_size = PCI::get_BAR_space_size(address, PCI::HeaderType0BaseRegister::BAR2);
dmesgln("Intel Native Graphics Adapter @ {}, MMIO @ {}, space size is {:x} bytes", address, PhysicalAddress(PCI::get_BAR0(address)), bar0_space_size);
dmesgln("Intel Native Graphics Adapter @ {}, framebuffer @ {}", address, PhysicalAddress(PCI::get_BAR2(address)));
PCI::enable_bus_mastering(address);

View file

@ -180,7 +180,7 @@ UNMAP_AFTER_INIT ErrorOr<void> VMWareGraphicsAdapter::initialize_adapter()
// Note: enable the device by modesetting the primary screen resolution
modeset_primary_screen_resolution(640, 480);
auto bar1_space_size = PCI::get_BAR_space_size(pci_address(), 1);
auto bar1_space_size = PCI::get_BAR_space_size(pci_address(), PCI::HeaderType0BaseRegister::BAR1);
m_display_connector = VMWareDisplayConnector::must_create(*this, PhysicalAddress(PCI::get_BAR1(pci_address()) & 0xfffffff0), bar1_space_size);
TRY(m_display_connector->set_safe_mode_setting());

View file

@ -208,7 +208,7 @@ UNMAP_AFTER_INIT bool E1000ENetworkAdapter::initialize()
enable_bus_mastering(pci_address());
size_t mmio_base_size = PCI::get_BAR_space_size(pci_address(), 0);
size_t mmio_base_size = PCI::get_BAR_space_size(pci_address(), PCI::HeaderType0BaseRegister::BAR0);
auto region_or_error = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(pci_address()))), Memory::page_round_up(mmio_base_size).release_value_but_fixme_should_propagate_errors(), "E1000e MMIO"sv, Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No);
if (region_or_error.is_error())
return false;

View file

@ -199,7 +199,7 @@ UNMAP_AFTER_INIT bool E1000NetworkAdapter::initialize()
m_io_base = IOAddress(PCI::get_BAR1(pci_address()) & ~1);
size_t mmio_base_size = PCI::get_BAR_space_size(pci_address(), 0);
size_t mmio_base_size = PCI::get_BAR_space_size(pci_address(), PCI::HeaderType0BaseRegister::BAR0);
auto region_or_error = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR0(pci_address()))), Memory::page_round_up(mmio_base_size).release_value_but_fixme_should_propagate_errors(), "E1000 MMIO"sv, Memory::Region::Access::ReadWrite, Memory::Region::Cacheable::No);
if (region_or_error.is_error())
return false;