Skip to content

Instantly share code, notes, and snippets.

@landonf
Created September 16, 2017 00:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save landonf/3321f5e1ca75f33708c42ddac619d5ec to your computer and use it in GitHub Desktop.
Save landonf/3321f5e1ca75f33708c42ddac619d5ec to your computer and use it in GitHub Desktop.
/**
* A unique PIC-specific interrupt source.
*/
struct intr_irqsrc {
device_t isrc_dev; /**< PIC that registered this isrc */
u_int isrc_irq; /**< globally unique abstract IRQ number */
u_int isrc_flags; /**< interrupt flags. see INTR_ISRCF_* */
char isrc_name[INTR_ISRC_NAMELEN]; /**< interrupt name (assigned in intr_isrc_register()) */
cpuset_t isrc_cpu; /**< on which CPUs is enabled */
u_int isrc_index; /**< base index into the global intrcnt array; isrc_count
points at the same location */
u_long * isrc_count; /**< pointer to global interrupt counter array */
u_int isrc_handlers; /**< the number of handlers associated with the interrupt
source via intr_setup_irq() */
struct intr_event * isrc_event; /**< the backing interrupt event, or NULL if the event has
not yet been allocated (no handlers are attached).
Could be destroyed with isrc_event_destroy(), but
isrc_event_destroy() is not used anywhere */
};
/**
* Known interrupt mapping types.
*/
enum intr_map_data_type {
INTR_MAP_DATA_ACPI = 0,
INTR_MAP_DATA_FDT,
INTR_MAP_DATA_GPIO,
INTR_MAP_DATA_MSI,
/* Placeholders for platform specific types */
INTR_MAP_DATA_PLAT_1 = 1000,
INTR_MAP_DATA_PLAT_2,
INTR_MAP_DATA_PLAT_3,
INTR_MAP_DATA_PLAT_4,
INTR_MAP_DATA_PLAT_5,
};
/**
* Semi-opaque interrupt mapping data used by a PIC.
*/
struct intr_map_data {
size_t len; /**< size of allocation */
enum intr_map_data_type type; /**< type of mapping */
};
/**
* Return the interrupt source associated with the given interrupt number.
*
* This will be NULL if the interrupt source has not been activated.
*/
static struct intr_irqsrc *intr_map_get_isrc(u_int res_id);
/** Set the interrupt source associated with the given interrupt number. */
static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc);
/**
* Resolve an interrupt's interrupt source from its associated map data.
*
* @param dev The PIC responsible for @p data.
* @param xref The PIC's xref.
* @param data The map data registered by @p dev.
* @param[out] isrc On success, the isrc associated with @p data.
*
* If @p data has a type of INTR_MAP_DATA_MSI, the isrc will be resolved internally by the interrupt code. Otherwise,
* PIC_MAP_INTR() will be called to map the isrc.
*/
static int intr_resolve_irq(device_t dev, intptr_t xref, struct intr_map_data *data, struct intr_irqsrc **isrc)
/**
* Locate the interrupt associated with the given interrupt number, and return a copy of its struct intr_map_data structure in @p data.
*
* @param res_id The interrupt number to look up.
* @param[out] map_dev The PIC associated with @p res_id.
* @param[out] map_xref The PIX xref associated with @p res_id.
* @param[out] data A caller-owned buffer containing the given @p res_id's mapping data, or NULL if no intr_map_data
* is associated with @p res_id. The caller is responsible for freeing this data via
* intr_free_intr_map_data()
*
* @see intr_map_irq
*/
static void intr_map_copy_map_data(u_int res_id, device_t *map_dev, intptr_t *map_xref, struct intr_map_data **data);
/**
* Allocate an interrupt map data structure of @p type and @p len with @p flags.
*
* Currently, @p flags is ignored.
*/
struct intr_map_data *intr_alloc_map_data(enum intr_map_data_type type, size_t len, int flags);
/**
* Allocate a new mapping entry in the global interrupt table; the entry will not have an associated interrupt source.
*
* @param dev The PIC with which the new entry will be associated, or NULL if unknown/unavailable.
* @param xref The xref phandle of the PIC, or a unique PIC identifier on non-OFW/FDT architectures.
* @param data Opaque mapping data.
*
* @retval The new entry's unique interrupt number.
*/
u_int intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data);
/**
* Remove and free an interrupt mapping entry.
*
* @param res_id The interrupt number (e.g. as returned by intr_map_irq()) of the mapping entry to be removed and freed.
*
* XXX: What happens if the entry has an associated isrc?
*/
void intr_unmap_irq(u_int res_id);
/**
* Activate interrupt resource @p res.
*
* @param dev The requesting device.
* @param res The resource to be activated.
*
* If @p res has already been activated (e.g. has an associated isrc), this function will panic.
*
* @retval 0 success
* @retval non-zero if activation fails, a regular unix error will be returned.
*
* @internal
* this will:
* - Request a corresponding isrc from the PIC via PIC_MAP_INTR().
* - Associate the isrc with the interrupt via intr_map_set_isrc().
* - Associate a copy of the interrupt isrc's mapping data with the resource via rman_set_virtual().
* - Call PIC_ACTIVATE_INTR() to perform actual activation.
*/
int intr_activate_irq(device_t dev, struct resource *res);
/**
* Deactivate interrupt resource @p res.
*
* @param dev The requesting device.
* @param res The resource to be deactivated.
*
* If @p res has already been deactivated (e.g. has no associated isrc), this function will panic.
*
* @retval 0 success
* @retval non-zero if activation fails, a regular unix error will be returned.
*
* @internal
* This will:
* - Call PIC_DEACTIVATE_INTR() to perform deactivation.
* - Clear the isrc associated with the interrupt via intr_map_set_isrc().
* - Free the mapping data copied in intr_activate_irq(), and clear the resource's pointer to it via rman_set_virtual().
*/
int intr_deactivate_irq(device_t dev, struct resource *res);
/**
* Create and attach an interrupt handler to interrupt resource @p res.
*
* @param dev The requesting device.
* @param res The active interrupt resource to which the interrupt handler should be attached.
* @param filt The filter routine (see BUS_SETUP_INTR(9)), or NULL.
* @param hand The interrupt handler ithread (see BUS_SETUP_INTR(9)), or NULL.
* @param arg An opaque pointer to be passed to the interrupt handler.
* @param flags Interrupt flags (INTR_*, see BUS_SETUP_INTR(9)).
* @param[out] cookiep On success, a cookie pointer that must be passed to irq_teardown_intr().
*
* @retval 0 success
* @retval non-zero if setup fails, a regular unix error will be returned.
*
* @internal
* This will:
* - Call intr_map_get_isrc() to fetch the associated interrupt source.
* - Call isrc_add_handler() to register the handler with the interrupt source.
* - Call PIC_SETUP_INTR() to perform any additional setup.
* - If this is the first attached handler, call PIC_ENABLE_ENTR() to enable the interrupt.
*/
int intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, driver_intr_t ithread,
void *arg, int flags, void **cookiep);
/**
* Detach an interrupt handler from interrupt resource @p res.
*
* @param dev The requesting device.
* @param res The interrupt resource from which the interrupt handler should be attached.
* @param cookie The cookie value previously returned by intr_setup_irq().
*
* @retval 0 success
* @retval non-zero if setup fails, a regular unix error will be returned.
*
* @internal
* This will:
* - Call intr_map_get_isrc() to fetch the associated interrupt source.
* - Call intr_event_remove_handler() to detach the interrupt handler.
* - If this is the last attached handler, call PIC_DISABLE_ENTR() to disable the interrupt.
* - Call PIC_TEARDOWN_INTR() to perform any additional teardown.
*/
int intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment