@@ -87,8 +87,13 @@ extern pci_dev_t dev_zero;
8787#define PCI_MSI_EDGETRIGGER (1 << 15)
8888#define PCI_MSI_ENABLE (1 << 16)
8989
90- #define PCI_BAR_TYPE_MEMORY 0x00
91- #define PCI_BAR_TYPE_IOPORT 0x01
90+ #define PCI_CAPABILITY_MSIX 0x11
91+
92+ #define PCI_MSIX_ENABLE (1 << 15)
93+ #define PCI_MSIX_FUNCTION_MASK (1 << 14)
94+
95+ #define PCI_BAR_TYPE_MEMORY 0x00
96+ #define PCI_BAR_TYPE_IOPORT 0x01
9297
9398#define PCI_HEADER_TYPE_DEVICE 0
9499#define PCI_HEADER_TYPE_BRIDGE 1
@@ -101,23 +106,187 @@ extern pci_dev_t dev_zero;
101106#define DEVICE_PER_BUS 32
102107#define FUNCTION_PER_DEVICE 32
103108
109+ /**
110+ * @brief Read a value from a PCI configuration space field.
111+ * @param dev PCI device descriptor.
112+ * @param field Offset of the configuration field.
113+ * @return The value read (size determined by field).
114+ */
104115uint32_t pci_read (pci_dev_t dev , uint32_t field );
116+
117+ /**
118+ * @brief Write a value into a PCI configuration space field.
119+ * @param dev PCI device descriptor.
120+ * @param field Offset of the configuration field.
121+ * @param value Value to write (size determined by field).
122+ */
105123void pci_write (pci_dev_t dev , uint32_t field , uint32_t value );
124+
125+ /**
126+ * @brief Get the PCI device class/subclass identifier.
127+ * @param dev PCI device descriptor.
128+ * @return Encoded device type (class << 8 | subclass).
129+ */
106130uint32_t get_device_type (pci_dev_t dev );
131+
132+ /**
133+ * @brief Get the secondary bus number from a PCI bridge device.
134+ * @param dev PCI bridge device descriptor.
135+ * @return Secondary bus number.
136+ */
107137uint32_t get_secondary_bus (pci_dev_t dev );
138+
139+ /**
140+ * @brief Determine if the device is a single-function endpoint.
141+ * @param dev PCI device descriptor.
142+ * @return Non-zero if endpoint, zero if multifunction/bridge.
143+ */
108144uint32_t pci_reach_end (pci_dev_t dev );
109- pci_dev_t pci_scan_function (uint16_t vendor_id , uint16_t device_id , uint32_t bus , uint32_t device , uint32_t function , int device_type );
110- pci_dev_t pci_scan_device (uint16_t vendor_id , uint16_t device_id , uint32_t bus , uint32_t device , int device_type );
111- pci_dev_t pci_scan_bus (uint16_t vendor_id , uint16_t device_id , uint32_t bus , int device_type );
112- pci_dev_t pci_get_device (uint16_t vendor_id , uint16_t device_id , int device_type );
145+
146+ /**
147+ * @brief Scan a specific PCI function for matching IDs or type.
148+ * @param vendor_id Vendor ID to match (0 = wildcard).
149+ * @param device_id Device ID to match (0 = wildcard).
150+ * @param bus Bus number.
151+ * @param device Device slot number.
152+ * @param function Function number.
153+ * @param device_type Device class/type to match (-1 = any).
154+ * @return Matching PCI device or dev_zero if none.
155+ */
156+ pci_dev_t pci_scan_function (uint16_t vendor_id , uint16_t device_id ,
157+ uint32_t bus , uint32_t device ,
158+ uint32_t function , int device_type );
159+
160+ /**
161+ * @brief Scan all functions of a given PCI device slot.
162+ * @param vendor_id Vendor ID to match (0 = wildcard).
163+ * @param device_id Device ID to match (0 = wildcard).
164+ * @param bus Bus number.
165+ * @param device Device slot number.
166+ * @param device_type Device class/type to match (-1 = any).
167+ * @return Matching PCI device or dev_zero if none.
168+ */
169+ pci_dev_t pci_scan_device (uint16_t vendor_id , uint16_t device_id ,
170+ uint32_t bus , uint32_t device ,
171+ int device_type );
172+
173+ /**
174+ * @brief Scan all devices on a given PCI bus.
175+ * @param vendor_id Vendor ID to match (0 = wildcard).
176+ * @param device_id Device ID to match (0 = wildcard).
177+ * @param bus Bus number.
178+ * @param device_type Device class/type to match (-1 = any).
179+ * @return First matching PCI device or dev_zero if none.
180+ */
181+ pci_dev_t pci_scan_bus (uint16_t vendor_id , uint16_t device_id ,
182+ uint32_t bus , int device_type );
183+
184+ /**
185+ * @brief Find a device by vendor, device, or type.
186+ * @param vendor_id Vendor ID to match (0 = any).
187+ * @param device_id Device ID to match (0 = any).
188+ * @param device_type Device class/type to match (-1 = any).
189+ * @return Matching PCI device or dev_zero if none.
190+ */
191+ pci_dev_t pci_get_device (uint16_t vendor_id , uint16_t device_id ,
192+ int device_type );
193+
194+ /**
195+ * @brief Initialise the PCI subsystem and enumerate devices.
196+ */
113197void init_pci ();
198+
199+ /**
200+ * @brief Enable bus mastering on a PCI device.
201+ * @param device PCI device descriptor.
202+ * @return True if bus mastering was newly enabled, false if already set.
203+ */
114204bool pci_bus_master (pci_dev_t device );
205+
206+ /**
207+ * @brief Get the type of a PCI Base Address Register (BAR).
208+ * @param field Raw BAR field value.
209+ * @return 0 = memory, 1 = I/O.
210+ */
115211uint8_t pci_bar_type (uint32_t field );
212+
213+ /**
214+ * @brief Extract an I/O base address from a BAR.
215+ * @param field Raw BAR field value.
216+ * @return I/O port base address.
217+ */
116218uint16_t pci_io_base (uint32_t field );
219+
220+ /**
221+ * @brief Extract a memory base address from a BAR.
222+ * @param field Raw BAR field value.
223+ * @return Memory-mapped base address.
224+ */
117225uint32_t pci_mem_base (uint32_t field );
226+
227+ /**
228+ * @brief Test whether a device descriptor represents 'not found'.
229+ * @param device PCI device descriptor.
230+ * @return True if no device, false otherwise.
231+ */
118232bool pci_not_found (pci_dev_t device );
119233
120- bool pci_enable_msi (pci_dev_t device , uint32_t vector );
234+ /**
235+ * @brief Enable MSI (Message Signalled Interrupts) on a device.
236+ * @param device PCI device descriptor.
237+ * @param vector APIC interrupt vector to use.
238+ * @param lapic_id local APIC ID of the CPU to route the vector to
239+ * @return True if MSI was enabled successfully.
240+ */
241+ bool pci_enable_msi (pci_dev_t device , uint32_t vector , uint32_t lapic_id );
242+
243+ /**
244+ * @brief Display enumerated PCI devices to the system log.
245+ */
121246void pci_display_device_list ();
247+
248+ /**
249+ * @brief Get a list of all enumerated PCI devices.
250+ * @param list Pointer to array of devices (output).
251+ * @return Number of devices in the list.
252+ */
122253size_t pci_get_device_list (pci_dev_t * * list );
123- void pci_interrupt_enable (pci_dev_t device , bool enable );
254+
255+ /**
256+ * @brief Enable or disable legacy INTx interrupt signalling.
257+ * @param device PCI device descriptor.
258+ * @param enable True = enable, False = disable.
259+ */
260+ void pci_interrupt_enable (pci_dev_t device , bool enable );
261+
262+ /**
263+ * @brief Enable MSI-X (extended message signalled interrupts).
264+ * @param device PCI device descriptor.
265+ * @param vector APIC interrupt vector to assign.
266+ * @param entry MSI-X table entry to configure.
267+ * @param lapic_id local APIC ID of the CPU to route the vector to
268+ * @return True if MSI-X was enabled successfully.
269+ */
270+ bool pci_enable_msix (pci_dev_t device , uint32_t vector , uint16_t entry , uint32_t lapic_id );
271+
272+ /**
273+ * @brief Configure an interrupt for a PCI device (MSI/MSI-X if available).
274+ *
275+ * Attempts to enable MSI/MSI-X for the given PCI device, routing the
276+ * interrupt to the specified Local APIC ID. If the device does not support
277+ * MSI/MSI-X, falls back to legacy INTx routing.
278+ *
279+ * @param name Human-readable device name (used in logs/debug output).
280+ * @param dev The PCI device handle.
281+ * @param lapic_id Local APIC ID of the target CPU that should receive the
282+ * interrupt.
283+ * @param handler Interrupt service routine to register.
284+ * @param context Opaque pointer passed to the ISR when the interrupt fires.
285+ *
286+ * @return The assigned interrupt vector (64–255 if MSI/MSI-X was used,
287+ * or IRQ_START + line if falling back to legacy INTx).
288+ *
289+ * @note Drivers should always check the returned vector to confirm which
290+ * interrupt mechanism was actually configured.
291+ */
292+ uint32_t pci_setup_interrupt (const char * name , pci_dev_t dev , uint8_t lapic_id , isr_t handler , void * context );
0 commit comments