Opened 14 years ago

Last modified 14 years ago

#59 new enhancement

Devices irqs handling and irqs topology — at Initial Version

Reported by: becoulet Owned by: Nicolas Pouillon
Priority: major Milestone: Topology handling
Component: drivers Keywords:
Cc:

Description

Change devices IRQ handling and use an IRQ lines topology graph.

API proposal in pseudo C:

struct irq_source_ep_s
{
  /** link to device which may generate irq */
  struct device_s *dev;
  /** list of sink ep which can recieve the irq signal */
  ep_list_root_t   links;

  CLIST            list_entry;
};

struct irq_sink_ep_s
{
  /** link to device which can handle irq */
  struct device_s *dev;
  /** list of source ep which can relay this irq */
  ep_list_root_t   links;

  CLIST            list_entry;
};

/* FIXME both endpoints have the same structure, should we merge?*/

/********** devices drivers API */

/**
   @this is handling function of device node.

   @param src end point which relayed the irq
   @param id local identifier of irq line for relaying device,
          must be updated to next local id by icu devs.
          Must be changed to -1 when no irq were pending.
          Non-icu devices only set to -1 or 0.
   @return pointer to next icu device or NULL

   The next sink endpoint may be found from icu registers or passed
   id.  On some systems the icu passes the decoded vector id to the
   processor in hardware and we need a way to pass the value back to
   icu handler from processor handler. */
#define IRQ_EVENT(n) struct irq_sink_ep_s (*n)(struct irq_source_ep_s *src, \
                                               intptr_t *id)

typedef IRQ_EVENT(irq_event_t);

/**
   irq ack function for *icu devs* only
*/
#define IRQ_ACK(n) void (*n)(struct irq_source_ep_s *src,       \
                             intptr_t id)

typedef IRQ_ACK(irq_ack_t);


/********** global irq processing code */

/**
   @return true if irq were generated by this device
 */
bool_t irq_process(struct irq_source_ep_s *src, intptr_t id)
{
  /* FIXME may use a non-recursive implementation */

  /* process irq and get next sink */
  intptr_t             next_id = id;
  struct irq_sink_ep_s *sink = src->dev->irq_event(src, &next_id);

  if (sink == NULL)
    return next_id == 0;                /* not an icu device */

  bool_t done = 0;

  /* for all source connected to icu sink, process */
  FOREACH(sink->links)
    done |= irq_process(next_src, next_id);

  /* for icu devs only */
  src->dev->irq_ack(src, id);

  return done;
}


/********** cpu irq handling code */

static irq_source_ep_s cpu_irq_sources[CPU_LINES_COUNT];

CPU_INTERRUPT_HANDLER(irq_handler)
{
  irq_process(cpu_irq_sources + irq, irq);
  /* may check for lost irqs here */
}

Change History (0)

Note: See TracTickets for help on using tickets.