FreeBSD/sys/x86/xen/xen_intr.c
/**
 * Associate an interrupt handler with an already allocated local Xen
 * event channel port.
 *
 * \param isrcp       The returned Xen interrupt object associated with
 *                    the specified local port.
 * \param local_port  The event channel to bind.
 * \param type        The event channel type of local_port.
 * \param intr_owner  The device making this bind request.
 * \param filter      An interrupt filter handler.  Specify NULL
 *                    to always dispatch to the ithread handler.
 * \param handler     An interrupt ithread handler.  Optional (can
 *                    specify NULL) if all necessary event actions
 *                    are performed by filter.
 * \param arg         Argument to present to both filter and handler.
 * \param irqflags    Interrupt handler flags.  See sys/bus.h.
 * \param handlep     Pointer to an opaque handle used to manage this
 *                    registration.
 *
 * \returns  0 on success, otherwise an errno.
 */
Associate an interrupt handler with an already allocated local Xen
event channel port.

\param isrcp       The returned Xen interrupt object associated with
the specified local port.
\param local_port  The event channel to bind.
\param type        The event channel type of local_port.
\param intr_owner  The device making this bind request.
\param filter      An interrupt filter handler.  Specify NULL
to always dispatch to the ithread handler.
\param handler     An interrupt ithread handler.  Optional (can
specify NULL) if all necessary event actions
are performed by filter.
\param arg         Argument to present to both filter and handler.
\param irqflags    Interrupt handler flags.

\returns  0 on success, otherwise an errno.
Associate an interrupt handler with an already allocated local Xen event channel port . \ param isrcp The returned Xen interrupt object associated with the specified local port . \ param local_port The event channel to bind . \ param type The event channel type of local_port . \ param intr_owner The device making this bind request . \ param filter An interrupt filter handler . Specify NULL to always dispatch to the ithread handler . \ param handler An interrupt ithread handler . Optional ( can specify NULL ) if all necessary event actions are performed by filter . \ param arg Argument to present to both filter and handler . \ param irqflags Interrupt handler flags . \ returns 0 on success otherwise an errno .
static int
xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port,
    enum evtchn_type type, device_t intr_owner, driver_filter_t filter,
    driver_intr_t handler, void *arg, enum intr_type flags,
    xen_intr_handle_t *port_handlep)
{
	struct xenisrc *isrc;
	int error;
	*isrcp = NULL;
	if (port_handlep == NULL) {
		device_printf(intr_owner,
			      "xen_intr_bind_isrc: Bad event handle\n");
		return (EINVAL);
	}
	mtx_lock(&xen_intr_isrc_lock);
	isrc = xen_intr_find_unused_isrc(type);
	if (isrc == NULL) {
		isrc = xen_intr_alloc_isrc(type, XEN_ALLOCATE_VECTOR);
		if (isrc == NULL) {
			mtx_unlock(&xen_intr_isrc_lock);
			return (ENOSPC);
		}
	}
	isrc->xi_port = local_port;
	xen_intr_port_to_isrc[local_port] = isrc;
	mtx_unlock(&xen_intr_isrc_lock);
	*port_handlep = &isrc->xi_vector;
#ifdef SMP
	if (type == EVTCHN_TYPE_PORT) {
		xen_intr_assign_cpu(&isrc->xi_intsrc, intr_next_cpu());
	}
#endif
	if (filter == NULL && handler == NULL) {
		*isrcp = isrc;
		return (0);
	}
	error = xen_intr_add_handler(intr_owner, filter, handler, arg, flags,
	    *port_handlep);
	if (error != 0) {
		xen_intr_release_isrc(isrc);
		return (error);
	}
	*isrcp = isrc;
	return (0);
}
static int xen_intr_bind_isrc ( struct xenisrc * * isrcp , evtchn_port_t local_port , enum evtchn_type type , device_t intr_owner , driver_filter_t filter , driver_intr_t handler , void * arg , enum intr_type flags , xen_intr_handle_t * port_handlep ) { struct xenisrc * isrc ; int error ; * isrcp = NULL ; if ( port_handlep == NULL ) { device_printf ( intr_owner , " \n " ) ; return ( EINVAL ) ; } mtx_lock ( & xen_intr_isrc_lock ) ; isrc = xen_intr_find_unused_isrc ( type ) ; if ( isrc == NULL ) { isrc = xen_intr_alloc_isrc ( type , XEN_ALLOCATE_VECTOR ) ; if ( isrc == NULL ) { mtx_unlock ( & xen_intr_isrc_lock ) ; return ( ENOSPC ) ; } } isrc -> xi_port = local_port ; xen_intr_port_to_isrc [ local_port ] = isrc ; mtx_unlock ( & xen_intr_isrc_lock ) ; * port_handlep = & isrc -> xi_vector ; #ifdef SMP if ( type == EVTCHN_TYPE_PORT ) { xen_intr_assign_cpu ( & isrc -> xi_intsrc , intr_next_cpu ( ) ) ; } #endif if ( filter == NULL && handler == NULL ) { * isrcp = isrc ; return ( 0 ) ; } error = xen_intr_add_handler ( intr_owner , filter , handler , arg , flags , * port_handlep ) ; if ( error != 0 ) { xen_intr_release_isrc ( isrc ) ; return ( error ) ; } * isrcp = isrc ; return ( 0 ) ; }
Associate an interrupt handler with an already allocated local Xen
 event channel port.
Associate an interrupt handler with an already allocated local Xen event channel port .
/* Assign the opaque handler (the event channel port) */ /*
		 * By default all interrupts are assigned to vCPU#0
		 * unless specified otherwise, so shuffle them to balance
		 * the interrupt load.
		 */ /*
		 * No filter/handler provided, leave the event channel
		 * masked and without a valid handler, the caller is
		 * in charge of setting that up.
		 */