Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_intr.c
Show First 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | |||||
void intr_irq_handler(struct trapframe *tf); | void intr_irq_handler(struct trapframe *tf); | ||||
/* Root interrupt controller stuff. */ | /* Root interrupt controller stuff. */ | ||||
device_t intr_irq_root_dev; | device_t intr_irq_root_dev; | ||||
static intr_irq_filter_t *irq_root_filter; | static intr_irq_filter_t *irq_root_filter; | ||||
static void *irq_root_arg; | static void *irq_root_arg; | ||||
static u_int irq_root_ipicount; | static u_int irq_root_ipicount; | ||||
struct intr_pic_child { | |||||
SLIST_ENTRY(intr_pic_child) pc_next; | |||||
struct intr_pic *pc_pic; | |||||
intr_child_irq_filter_t *pc_filter; | |||||
void *pc_filter_arg; | |||||
uintptr_t pc_start; | |||||
uintptr_t pc_length; | |||||
}; | |||||
/* Interrupt controller definition. */ | /* Interrupt controller definition. */ | ||||
struct intr_pic { | struct intr_pic { | ||||
SLIST_ENTRY(intr_pic) pic_next; | SLIST_ENTRY(intr_pic) pic_next; | ||||
intptr_t pic_xref; /* hardware identification */ | intptr_t pic_xref; /* hardware identification */ | ||||
device_t pic_dev; | device_t pic_dev; | ||||
#define FLAG_PIC (1 << 0) | #define FLAG_PIC (1 << 0) | ||||
#define FLAG_MSI (1 << 1) | #define FLAG_MSI (1 << 1) | ||||
u_int pic_flags; | u_int pic_flags; | ||||
struct mtx pic_child_lock; | |||||
SLIST_HEAD(, intr_pic_child) pic_children; | |||||
}; | }; | ||||
static struct mtx pic_list_lock; | static struct mtx pic_list_lock; | ||||
static SLIST_HEAD(, intr_pic) pic_list; | static SLIST_HEAD(, intr_pic) pic_list; | ||||
static struct intr_pic *pic_lookup(device_t dev, intptr_t xref); | static struct intr_pic *pic_lookup(device_t dev, intptr_t xref); | ||||
/* Interrupt source definition. */ | /* Interrupt source definition. */ | ||||
▲ Show 20 Lines • Show All 196 Lines • ▼ Show 20 Lines | intr_irq_handler(struct trapframe *tf) | ||||
td = curthread; | td = curthread; | ||||
oldframe = td->td_intr_frame; | oldframe = td->td_intr_frame; | ||||
td->td_intr_frame = tf; | td->td_intr_frame = tf; | ||||
irq_root_filter(irq_root_arg); | irq_root_filter(irq_root_arg); | ||||
td->td_intr_frame = oldframe; | td->td_intr_frame = oldframe; | ||||
critical_exit(); | critical_exit(); | ||||
} | } | ||||
int | |||||
intr_child_irq_handler(struct intr_pic *parent, uintptr_t irq) | |||||
{ | |||||
struct intr_pic_child *child; | |||||
bool found; | |||||
found = false; | |||||
mtx_lock_spin(&parent->pic_child_lock); | |||||
SLIST_FOREACH(child, &parent->pic_children, pc_next) { | |||||
if (child->pc_start <= irq && | |||||
irq < (child->pc_start + child->pc_length)) { | |||||
found = true; | |||||
break; | |||||
} | |||||
} | |||||
mtx_unlock_spin(&parent->pic_child_lock); | |||||
if (found) | |||||
return (child->pc_filter(child->pc_filter_arg, irq)); | |||||
return (FILTER_STRAY); | |||||
} | |||||
/* | /* | ||||
* interrupt controller dispatch function for interrupts. It should | * interrupt controller dispatch function for interrupts. It should | ||||
* be called straight from the interrupt controller, when associated interrupt | * be called straight from the interrupt controller, when associated interrupt | ||||
* source is learned. | * source is learned. | ||||
*/ | */ | ||||
int | int | ||||
intr_isrc_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf) | intr_isrc_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 553 Lines • ▼ Show 20 Lines | pic_create(device_t dev, intptr_t xref) | ||||
} | } | ||||
pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); | pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); | ||||
if (pic == NULL) { | if (pic == NULL) { | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
pic->pic_xref = xref; | pic->pic_xref = xref; | ||||
pic->pic_dev = dev; | pic->pic_dev = dev; | ||||
mtx_init(&pic->pic_child_lock, "pic child lock", NULL, MTX_SPIN); | |||||
SLIST_INSERT_HEAD(&pic_list, pic, pic_next); | SLIST_INSERT_HEAD(&pic_list, pic, pic_next); | ||||
mtx_unlock(&pic_list_lock); | mtx_unlock(&pic_list_lock); | ||||
return (pic); | return (pic); | ||||
} | } | ||||
#ifdef notyet | #ifdef notyet | ||||
/* | /* | ||||
* Destroy interrupt controller. | * Destroy interrupt controller. | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, | ||||
intr_irq_root_dev = dev; | intr_irq_root_dev = dev; | ||||
irq_root_filter = filter; | irq_root_filter = filter; | ||||
irq_root_arg = arg; | irq_root_arg = arg; | ||||
irq_root_ipicount = ipicount; | irq_root_ipicount = ipicount; | ||||
debugf("irq root set to %s\n", device_get_nameunit(dev)); | debugf("irq root set to %s\n", device_get_nameunit(dev)); | ||||
return (0); | return (0); | ||||
} | |||||
/* | |||||
* Add a handler to manage a sub range of a parents interrupts. | |||||
*/ | |||||
struct intr_pic * | |||||
intr_pic_add_handler(device_t parent, struct intr_pic *pic, | |||||
intr_child_irq_filter_t *filter, void *arg, uintptr_t start, | |||||
uintptr_t length) | |||||
{ | |||||
struct intr_pic *parent_pic; | |||||
struct intr_pic_child *newchild; | |||||
#ifdef INVARIANTS | |||||
struct intr_pic_child *child; | |||||
#endif | |||||
parent_pic = pic_lookup(parent, 0); | |||||
if (parent_pic == NULL) | |||||
return (NULL); | |||||
newchild = malloc(sizeof(*newchild), M_INTRNG, M_WAITOK | M_ZERO); | |||||
newchild->pc_pic = pic; | |||||
newchild->pc_filter = filter; | |||||
newchild->pc_filter_arg = arg; | |||||
newchild->pc_start = start; | |||||
newchild->pc_length = length; | |||||
mtx_lock_spin(&parent_pic->pic_child_lock); | |||||
#ifdef INVARIANTS | |||||
SLIST_FOREACH(child, &parent_pic->pic_children, pc_next) { | |||||
KASSERT(child->pc_pic != pic, ("%s: Adding a child PIC twice", | |||||
__func__)); | |||||
} | |||||
#endif | |||||
SLIST_INSERT_HEAD(&parent_pic->pic_children, newchild, pc_next); | |||||
mtx_unlock_spin(&parent_pic->pic_child_lock); | |||||
return (pic); | |||||
} | } | ||||
int | int | ||||
intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data, | intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data, | ||||
u_int *irqp) | u_int *irqp) | ||||
{ | { | ||||
int error; | int error; | ||||
struct intr_irqsrc *isrc; | struct intr_irqsrc *isrc; | ||||
▲ Show 20 Lines • Show All 480 Lines • Show Last 20 Lines |