Skip to content

Commit 7b03e58

Browse files
add pci_setup_multiple_interrupts for allocating a block of contiguous interrupts via msi, and document new functions that lack docblocks
1 parent d41a4cb commit 7b03e58

File tree

2 files changed

+398
-0
lines changed

2 files changed

+398
-0
lines changed

include/pci.h

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,18 @@ pci_dev_t pci_get_device(uint16_t vendor_id, uint16_t device_id, int device_type
206206
*/
207207
pci_dev_t pci_get_best(uint16_t vendor_id, uint16_t device_id, int device_type, pci_score_fn score, void *ctx);
208208

209+
/**
210+
* @brief Get the Nth matching PCI device by vendor/device/type.
211+
*
212+
* Scans the enumerated device list and returns the Nth match in discovery
213+
* order (0-based). Any of the match fields may be wildcarded.
214+
*
215+
* @param vendor_id Vendor ID to match (0 = any).
216+
* @param device_id Device ID to match (0 = any).
217+
* @param device_type Device class/type to match (-1 = any).
218+
* @param nth Zero-based index into the matching set.
219+
* @return Matching PCI device, or dev_zero if not found.
220+
*/
209221
pci_dev_t pci_get_device_nth(uint16_t vendor_id, uint16_t device_id, int device_type, size_t nth);
210222

211223
/**
@@ -317,14 +329,133 @@ bool pci_enable_msix(pci_dev_t device, uint32_t vector, uint16_t entry, uint32_t
317329
*/
318330
uint32_t pci_setup_interrupt(const char* name, pci_dev_t dev, uint8_t logical_cpu_id, isr_t handler, void *context);
319331

332+
/**
333+
* @brief Return the 64-bit MMIO base from a pair of BAR dwords.
334+
*
335+
* Helper for 64-bit memory BARs where both low and high dwords are available.
336+
*
337+
* @param lo Lower 32 bits of the BAR (as read from PCI configuration space).
338+
* @param hi Upper 32 bits of the BAR (as read from PCI configuration space).
339+
* @return 64-bit physical base address.
340+
*/
341+
uint64_t pci_mem_base64(uint32_t lo, uint32_t hi);
342+
343+
/**
344+
* @brief Determine if a BAR field denotes a 64-bit memory BAR.
345+
*
346+
* @param field Raw BAR field value.
347+
* @return true if the BAR is a 64-bit memory BAR, false otherwise.
348+
*/
349+
bool pci_bar_is_mem64(uint32_t field);
350+
351+
/**
352+
* @brief Probe and return the size of a BAR mapping.
353+
*
354+
* Uses the standard PCI size-probe dance on the requested BAR index to
355+
* determine the amount of address space the device decodes.
356+
*
357+
* @param dev PCI device.
358+
* @param bar_index BAR number (0..5).
359+
* @return Size in bytes (0 on failure or unsupported BAR type).
360+
*
361+
* @note May temporarily write to the device’s BAR during probing; callers
362+
* must ensure the device is idle and that probing is safe.
363+
*/
320364
uint64_t get_bar_size(pci_dev_t dev, int bar_index);
321365

366+
/**
367+
* @brief Disable PCI bus mastering on a device.
368+
*
369+
* Clears @ref PCI_COMMAND_BUS_MASTER in the device’s command register.
370+
*
371+
* @param device PCI device descriptor.
372+
* @return true if the bit was cleared by this call, false if it was already clear.
373+
*/
322374
bool pci_disable_bus_master(pci_dev_t device);
323375

376+
/**
377+
* @brief Enable I/O space decoding for a device.
378+
*
379+
* Sets @ref PCI_COMMAND_IOSPACE in the command register.
380+
*
381+
* @param device PCI device descriptor.
382+
* @return true if the bit was newly set, false if it was already set.
383+
*/
324384
bool pci_enable_iospace(pci_dev_t device);
325385

386+
/**
387+
* @brief Enable MMIO space decoding for a device.
388+
*
389+
* Sets @ref PCI_COMMAND_MEMSPACE in the command register.
390+
*
391+
* @param device PCI device descriptor.
392+
* @return true if the bit was newly set, false if it was already set.
393+
*/
326394
bool pci_enable_memspace(pci_dev_t device);
327395

396+
/**
397+
* @brief Disable I/O space decoding for a device.
398+
*
399+
* Clears @ref PCI_COMMAND_IOSPACE in the command register.
400+
*
401+
* @param device PCI device descriptor.
402+
* @return true if the bit was cleared by this call, false if it was already clear.
403+
*/
328404
bool pci_disable_iospace(pci_dev_t device);
329405

406+
/**
407+
* @brief Disable MMIO space decoding for a device.
408+
*
409+
* Clears @ref PCI_COMMAND_MEMSPACE in the command register.
410+
*
411+
* @param device PCI device descriptor.
412+
* @return true if the bit was cleared by this call, false if it was already clear.
413+
*/
330414
bool pci_disable_memspace(pci_dev_t device);
415+
416+
/**
417+
* @brief Configure one or more interrupt vectors for a PCI function.
418+
*
419+
* For @p requested_count == 1: attempts single-vector MSI and falls back to legacy INTx
420+
* if MSI cannot be enabled. On success, writes the assigned vector to @p start and @p end.
421+
*
422+
* For @p requested_count > 1: attempts to allocate a contiguous run of exactly that many
423+
* vectors and then enables plain MSI with Multiple Message Enable (MME) set via
424+
* @ref pci_enable_msi_multi. Handlers are installed before arming the device; on failure,
425+
* installed handlers are deregistered and the vectors freed. There is no legacy fallback
426+
* for multi-vector requests.
427+
*
428+
* @param name Human-readable device name (for logs).
429+
* @param dev PCI device handle.
430+
* @param logical_cpu_id Logical CPU that should receive the interrupts.
431+
* @param requested_count Number of vectors requested (caller should pass a power of two for MSI).
432+
* @param handler ISR to register on each vector.
433+
* @param context Opaque pointer passed to the ISR.
434+
* @param start [out] First vector in the assigned range.
435+
* @param end [out] Last vector in the assigned range (inclusive).
436+
* @return true on success; false if allocation/programming failed.
437+
*
438+
* @note This function does not round up non-power-of-two requests; if the device
439+
* cannot support the requested count, it fails. For multi-vector requests,
440+
* alignment and power-of-two constraints are enforced by @ref pci_enable_msi_multi.
441+
*/
442+
bool pci_setup_multiple_interrupts(const char *name, pci_dev_t dev, uint8_t logical_cpu_id, uint8_t requested_count, isr_t handler, void *context, uint32_t *start, uint32_t *end);
443+
444+
/**
445+
* @brief Enable plain MSI for a contiguous, power-of-two range of vectors.
446+
*
447+
* Programs the device’s MSI capability with Message Address/Message Data and sets
448+
* the Multiple Message Enable (MME) bits to @c log2(count), using @p base_vector
449+
* as the first message’s vector. Disables legacy INTx on success.
450+
*
451+
* @param device PCI device descriptor.
452+
* @param base_vector First vector in the contiguous block (must be aligned to @p count).
453+
* @param count Number of messages (must be a power of two, e.g., 1,2,4,8,...,128).
454+
* @param lapic_id Local APIC ID to target.
455+
* @return true if MSI was enabled with the requested range; false otherwise.
456+
*
457+
* @warning This call does not allocate vectors or install handlers. Callers must
458+
* have already reserved a contiguous block and registered handlers for
459+
* all vectors before enabling MSI on the device.
460+
*/
461+
bool pci_enable_msi_multi(pci_dev_t device, uint32_t base_vector, uint8_t count, uint32_t lapic_id);

0 commit comments

Comments
 (0)