in 104-quad-8.c [397:452]
static int quad8_events_configure(struct counter_device *counter)
{
struct quad8 *const priv = counter_priv(counter);
unsigned long irq_enabled = 0;
unsigned long irqflags;
struct counter_event_node *event_node;
unsigned int next_irq_trigger;
unsigned long ior_cfg;
unsigned long base_offset;
spin_lock_irqsave(&priv->lock, irqflags);
list_for_each_entry(event_node, &counter->events_list, l) {
switch (event_node->event) {
case COUNTER_EVENT_OVERFLOW:
next_irq_trigger = QUAD8_EVENT_CARRY;
break;
case COUNTER_EVENT_THRESHOLD:
next_irq_trigger = QUAD8_EVENT_COMPARE;
break;
case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
next_irq_trigger = QUAD8_EVENT_CARRY_BORROW;
break;
case COUNTER_EVENT_INDEX:
next_irq_trigger = QUAD8_EVENT_INDEX;
break;
default:
/* should never reach this path */
spin_unlock_irqrestore(&priv->lock, irqflags);
return -EINVAL;
}
/* Skip configuration if it is the same as previously set */
if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
continue;
/* Save new IRQ function configuration */
priv->irq_trigger[event_node->channel] = next_irq_trigger;
/* Load configuration to I/O Control Register */
ior_cfg = priv->ab_enable[event_node->channel] |
priv->preset_enable[event_node->channel] << 1 |
priv->irq_trigger[event_node->channel] << 3;
base_offset = priv->base + 2 * event_node->channel + 1;
outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
/* Enable IRQ line */
irq_enabled |= BIT(event_node->channel);
}
outb(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT);
spin_unlock_irqrestore(&priv->lock, irqflags);
return 0;
}