mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	Kernel/PCI: Cache more details about PCI devices when enumerating them
There's no good reason to fetch these values each time we need them.
This commit is contained in:
		
							parent
							
								
									e22d9dc360
								
							
						
					
					
						commit
						82bb08a15c
					
				
					 14 changed files with 85 additions and 41 deletions
				
			
		|  | @ -17,7 +17,7 @@ u8 read8(Address address, u32 field) { return Access::the().read8_field(address, | |||
| u16 read16(Address address, u32 field) { return Access::the().read16_field(address, field); } | ||||
| u32 read32(Address address, u32 field) { return Access::the().read32_field(address, field); } | ||||
| 
 | ||||
| void enumerate(Function<void(Address, ID)> callback) | ||||
| void enumerate(Function<void(Address, PhysicalID const&)> callback) | ||||
| { | ||||
|     Access::the().fast_enumerate(callback); | ||||
| } | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ u32 read32(Address address, u32 field); | |||
| 
 | ||||
| ID get_id(PCI::Address); | ||||
| bool is_io_space_enabled(Address); | ||||
| void enumerate(Function<void(Address, ID)> callback); | ||||
| void enumerate(Function<void(Address, PhysicalID const&)> callback); | ||||
| void enable_interrupt_line(Address); | ||||
| void disable_interrupt_line(Address); | ||||
| u8 get_interrupt_line(Address); | ||||
|  |  | |||
|  | @ -381,7 +381,14 @@ UNMAP_AFTER_INIT void Access::enumerate_functions(int type, u8 bus, u8 device, u | |||
|     Address address(0, bus, device, function); | ||||
|     auto read_type = (read8_field(address, PCI_CLASS) << 8u) | read8_field(address, PCI_SUBCLASS); | ||||
|     if (type == -1 || type == read_type) { | ||||
|         m_physical_ids.append(PhysicalID { address, { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) }, get_capabilities(address) }); | ||||
|         PCI::ID id = { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) }; | ||||
|         ClassCode class_code = read8_field(address, PCI_CLASS); | ||||
|         SubclassCode subclass_code = read8_field(address, PCI_SUBCLASS); | ||||
|         ProgrammingInterface prog_if = read8_field(address, PCI_PROG_IF); | ||||
|         RevisionID revision_id = read8_field(address, PCI_REVISION_ID); | ||||
|         SubsystemID subsystem_id = read16_field(address, PCI_SUBSYSTEM_ID); | ||||
|         SubsystemVendorID subsystem_vendor_id = read16_field(address, PCI_SUBSYSTEM_VENDOR_ID); | ||||
|         m_physical_ids.append(PhysicalID { address, id, revision_id, class_code, subclass_code, prog_if, subsystem_id, subsystem_vendor_id, get_capabilities(address) }); | ||||
|     } | ||||
| 
 | ||||
|     if (read_type == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(read8_field(address, PCI_SECONDARY_BUS)))) { | ||||
|  | @ -416,12 +423,12 @@ UNMAP_AFTER_INIT void Access::enumerate_bus(int type, u8 bus, bool recursive) | |||
|         enumerate_device(type, bus, device, recursive); | ||||
| } | ||||
| 
 | ||||
| void Access::fast_enumerate(Function<void(Address, ID)>& callback) const | ||||
| void Access::fast_enumerate(Function<void(Address, PhysicalID const&)>& callback) const | ||||
| { | ||||
|     MutexLocker locker(m_scan_lock); | ||||
|     VERIFY(!m_physical_ids.is_empty()); | ||||
|     for (auto& physical_id : m_physical_ids) { | ||||
|         callback(physical_id.address(), physical_id.id()); | ||||
|         callback(physical_id.address(), physical_id); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ public: | |||
|     static bool initialize_for_memory_access(PhysicalAddress mcfg_table); | ||||
|     static bool initialize_for_io_access(); | ||||
| 
 | ||||
|     void fast_enumerate(Function<void(Address, ID)>&) const; | ||||
|     void fast_enumerate(Function<void(Address, PhysicalID const&)>&) const; | ||||
|     void rescan_hardware(); | ||||
| 
 | ||||
|     static Access& the(); | ||||
|  |  | |||
|  | @ -181,11 +181,25 @@ private: | |||
|     const u8 m_ptr; | ||||
| }; | ||||
| 
 | ||||
| TYPEDEF_DISTINCT_ORDERED_ID(u8, ClassCode); | ||||
| TYPEDEF_DISTINCT_ORDERED_ID(u8, SubclassCode); | ||||
| TYPEDEF_DISTINCT_ORDERED_ID(u8, ProgrammingInterface); | ||||
| TYPEDEF_DISTINCT_ORDERED_ID(u8, RevisionID); | ||||
| TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemID); | ||||
| TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemVendorID); | ||||
| 
 | ||||
| class Access; | ||||
| class PhysicalID { | ||||
| public: | ||||
|     PhysicalID(Address address, ID id, Vector<Capability> capabilities) | ||||
|     PhysicalID(Address address, ID id, RevisionID revision_id, ClassCode class_code, SubclassCode subclass_code, ProgrammingInterface prog_if, SubsystemID subsystem_id, SubsystemVendorID subsystem_vendor_id, Vector<Capability> capabilities) | ||||
|         : m_address(address) | ||||
|         , m_id(id) | ||||
|         , m_revision_id(revision_id) | ||||
|         , m_class_code(class_code) | ||||
|         , m_subclass_code(subclass_code) | ||||
|         , m_prog_if(prog_if) | ||||
|         , m_subsystem_id(subsystem_id) | ||||
|         , m_subsystem_vendor_id(subsystem_vendor_id) | ||||
|         , m_capabilities(capabilities) | ||||
|     { | ||||
|         if constexpr (PCI_DEBUG) { | ||||
|  | @ -198,13 +212,36 @@ public: | |||
|     const ID& id() const { return m_id; } | ||||
|     const Address& address() const { return m_address; } | ||||
| 
 | ||||
|     RevisionID revision_id() const { return m_revision_id; } | ||||
|     ClassCode class_code() const { return m_class_code; } | ||||
|     SubclassCode subclass_code() const { return m_subclass_code; } | ||||
|     ProgrammingInterface prog_if() const { return m_prog_if; } | ||||
|     SubsystemID subsystem_id() const { return m_subsystem_id; } | ||||
|     SubsystemVendorID subsystem_vendor_id() const { return m_subsystem_vendor_id; } | ||||
| 
 | ||||
|     void apply_subclass_code_change(Badge<Access>, SubclassCode new_subclass) | ||||
|     { | ||||
|         m_subclass_code = new_subclass; | ||||
|     } | ||||
|     void apply_prog_if_change(Badge<Access>, ProgrammingInterface new_progif) | ||||
|     { | ||||
|         m_prog_if = new_progif; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     Address m_address; | ||||
|     ID m_id; | ||||
| 
 | ||||
|     RevisionID m_revision_id; | ||||
|     ClassCode m_class_code; | ||||
|     SubclassCode m_subclass_code; | ||||
|     ProgrammingInterface m_prog_if; | ||||
|     SubsystemID m_subsystem_id; | ||||
|     SubsystemVendorID m_subsystem_vendor_id; | ||||
| 
 | ||||
|     Vector<Capability> m_capabilities; | ||||
| }; | ||||
| 
 | ||||
| class Access; | ||||
| class Domain; | ||||
| class Device; | ||||
| } | ||||
|  |  | |||
|  | @ -56,8 +56,8 @@ UNMAP_AFTER_INIT void initialize() | |||
| 
 | ||||
|     PCI::PCIBusSysFSDirectory::initialize(); | ||||
| 
 | ||||
|     PCI::enumerate([&](const Address& address, ID id) { | ||||
|         dmesgln("{} {}", address, id); | ||||
|     PCI::enumerate([&](const Address& address, PhysicalID const& physical_id) { | ||||
|         dmesgln("{} {}", address, physical_id.id()); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ UNMAP_AFTER_INIT void PCIBusSysFSDirectory::initialize() | |||
| UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory() | ||||
|     : SysFSDirectory("pci", SysFSComponentRegistry::the().buses_directory()) | ||||
| { | ||||
|     PCI::enumerate([&](const Address& address, ID) { | ||||
|     PCI::enumerate([&](const Address& address, PhysicalID const&) { | ||||
|         auto pci_device = PCI::PCIDeviceSysFSDirectory::create(*this, address); | ||||
|         m_components.append(pci_device); | ||||
|     }); | ||||
|  |  | |||
|  | @ -27,10 +27,10 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers() | |||
|     if (kernel_command_line().disable_usb()) | ||||
|         return; | ||||
| 
 | ||||
|     PCI::enumerate([this](PCI::Address const& address, PCI::ID) { | ||||
|         if (!(PCI::get_class(address) == 0xc && PCI::get_subclass(address) == 0x3)) | ||||
|     PCI::enumerate([this](PCI::Address const& address, PCI::PhysicalID const& physical_id) { | ||||
|         if (!(physical_id.class_code().value() == 0xc && physical_id.subclass_code().value() == 0x3)) | ||||
|             return; | ||||
|         if (PCI::get_programming_interface(address) == 0x0) { | ||||
|         if (physical_id.prog_if().value() == 0x0) { | ||||
|             if (kernel_command_line().disable_uhci_controller()) | ||||
|                 return; | ||||
| 
 | ||||
|  | @ -40,22 +40,22 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers() | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (PCI::get_programming_interface(address) == 0x10) { | ||||
|         if (physical_id.prog_if().value() == 0x10) { | ||||
|             dmesgln("USBManagement: OHCI controller found at {} is not currently supported.", address); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (PCI::get_programming_interface(address) == 0x20) { | ||||
|         if (physical_id.prog_if().value() == 0x20) { | ||||
|             dmesgln("USBManagement: EHCI controller found at {} is not currently supported.", address); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (PCI::get_programming_interface(address) == 0x30) { | ||||
|         if (physical_id.prog_if().value() == 0x30) { | ||||
|             dmesgln("USBManagement: xHCI controller found at {} is not currently supported.", address); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, PCI::get_programming_interface(address)); | ||||
|         dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, physical_id.prog_if().value()); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,13 +18,13 @@ UNMAP_AFTER_INIT void detect() | |||
| { | ||||
|     if (kernel_command_line().disable_virtio()) | ||||
|         return; | ||||
|     PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { | ||||
|         if (address.is_null() || id.is_null()) | ||||
|     PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) { | ||||
|         if (address.is_null() || physical_id.id().is_null()) | ||||
|             return; | ||||
|         // TODO: We should also be checking that the device_id is in between 0x1000 - 0x107F inclusive
 | ||||
|         if (id.vendor_id != PCI::VendorID::VirtIO) | ||||
|         if (physical_id.id().vendor_id != PCI::VendorID::VirtIO) | ||||
|             return; | ||||
|         switch (id.device_id) { | ||||
|         switch (physical_id.id().device_id) { | ||||
|         case PCI::DeviceID::VirtIOConsole: { | ||||
|             auto& console = Console::must_create(address).leak_ref(); | ||||
|             console.initialize(); | ||||
|  | @ -40,7 +40,7 @@ UNMAP_AFTER_INIT void detect() | |||
|             break; | ||||
|         } | ||||
|         default: | ||||
|             dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", id.device_id); | ||||
|             dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", physical_id.id().device_id); | ||||
|             break; | ||||
|         } | ||||
|     }); | ||||
|  |  | |||
|  | @ -15,12 +15,12 @@ static SerialDevice* s_the = nullptr; | |||
| UNMAP_AFTER_INIT void PCISerialDevice::detect() | ||||
| { | ||||
|     size_t current_device_minor = 68; | ||||
|     PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { | ||||
|     PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) { | ||||
|         if (address.is_null()) | ||||
|             return; | ||||
| 
 | ||||
|         for (auto& board_definition : board_definitions) { | ||||
|             if (board_definition.device_id != id) | ||||
|             if (board_definition.device_id != physical_id.id()) | ||||
|                 continue; | ||||
| 
 | ||||
|             auto bar_base = PCI::get_BAR(address, board_definition.pci_bar) & ~1; | ||||
|  |  | |||
|  | @ -614,19 +614,19 @@ private: | |||
|     virtual KResult try_generate(KBufferBuilder& builder) override | ||||
|     { | ||||
|         JsonArraySerializer array { builder }; | ||||
|         PCI::enumerate([&array](PCI::Address address, PCI::ID id) { | ||||
|         PCI::enumerate([&array](PCI::Address address, PCI::PhysicalID const& physical_id) { | ||||
|             auto obj = array.add_object(); | ||||
|             obj.add("domain", address.domain()); | ||||
|             obj.add("bus", address.bus()); | ||||
|             obj.add("device", address.device()); | ||||
|             obj.add("function", address.function()); | ||||
|             obj.add("vendor_id", id.vendor_id); | ||||
|             obj.add("device_id", id.device_id); | ||||
|             obj.add("revision_id", PCI::get_revision_id(address)); | ||||
|             obj.add("subclass", PCI::get_subclass(address)); | ||||
|             obj.add("class", PCI::get_class(address)); | ||||
|             obj.add("subsystem_id", PCI::get_subsystem_id(address)); | ||||
|             obj.add("subsystem_vendor_id", PCI::get_subsystem_vendor_id(address)); | ||||
|             obj.add("vendor_id", physical_id.id().vendor_id); | ||||
|             obj.add("device_id", physical_id.id().device_id); | ||||
|             obj.add("revision_id", physical_id.revision_id().value()); | ||||
|             obj.add("subclass", physical_id.subclass_code().value()); | ||||
|             obj.add("class", physical_id.class_code().value()); | ||||
|             obj.add("subsystem_id", physical_id.subsystem_id().value()); | ||||
|             obj.add("subsystem_vendor_id", physical_id.subsystem_vendor_id().value()); | ||||
|         }); | ||||
|         array.finish(); | ||||
|         return KSuccess; | ||||
|  |  | |||
|  | @ -179,13 +179,13 @@ UNMAP_AFTER_INIT bool GraphicsManagement::initialize() | |||
|         dbgln("Forcing no initialization of framebuffer devices"); | ||||
|     } | ||||
| 
 | ||||
|     PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { | ||||
|     PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) { | ||||
|         // Note: Each graphics controller will try to set its native screen resolution
 | ||||
|         // upon creation. Later on, if we don't want to have framebuffer devices, a
 | ||||
|         // framebuffer console will take the control instead.
 | ||||
|         if (!is_vga_compatible_pci_device(address) && !is_display_controller_pci_device(address)) | ||||
|             return; | ||||
|         determine_and_initialize_graphics_device(address, id); | ||||
|         determine_and_initialize_graphics_device(address, physical_id.id()); | ||||
|     }); | ||||
| 
 | ||||
|     if (m_graphics_devices.is_empty()) { | ||||
|  |  | |||
|  | @ -91,9 +91,9 @@ UNMAP_AFTER_INIT RefPtr<NetworkAdapter> NetworkingManagement::determine_network_ | |||
| bool NetworkingManagement::initialize() | ||||
| { | ||||
|     if (!kernel_command_line().is_physical_networking_disabled()) { | ||||
|         PCI::enumerate([&](const PCI::Address& address, PCI::ID) { | ||||
|         PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) { | ||||
|             // Note: PCI class 2 is the class of Network devices
 | ||||
|             if (PCI::get_class(address) != 0x02) | ||||
|             if (physical_id.class_code().value() != 0x02) | ||||
|                 return; | ||||
|             if (auto adapter = determine_network_device(address); !adapter.is_null()) | ||||
|                 m_adapters.append(adapter.release_nonnull()); | ||||
|  |  | |||
|  | @ -44,14 +44,14 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio) | |||
|     VERIFY(m_controllers.is_empty()); | ||||
|     if (!kernel_command_line().disable_physical_storage()) { | ||||
|         if (kernel_command_line().is_ide_enabled()) { | ||||
|             PCI::enumerate([&](const PCI::Address& address, PCI::ID) { | ||||
|                 if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_IDE_CTRL_SUBCLASS_ID) { | ||||
|             PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) { | ||||
|                 if (physical_id.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && physical_id.subclass_code().value() == PCI_IDE_CTRL_SUBCLASS_ID) { | ||||
|                     m_controllers.append(IDEController::initialize(address, force_pio)); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         PCI::enumerate([&](const PCI::Address& address, PCI::ID) { | ||||
|             if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_SATA_CTRL_SUBCLASS_ID && PCI::get_programming_interface(address) == PCI_AHCI_IF_PROGIF) { | ||||
|         PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) { | ||||
|             if (physical_id.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && physical_id.subclass_code().value() == PCI_SATA_CTRL_SUBCLASS_ID && physical_id.prog_if().value() == PCI_AHCI_IF_PROGIF) { | ||||
|                 m_controllers.append(AHCIController::initialize(address)); | ||||
|             } | ||||
|         }); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Liav A
						Liav A