blob: 17aa660680d605184b852badfca3c53c6993baa1 [file] [log] [blame]
/*
* Copyright 2014, NICTA
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(NICTA_BSD)
*/
/**
* The IRQ server helps to manage the IRQs in a system. There are 3 API levels
* in the design
* 1. [irq server node] The IRQ server node is a set of IRQs and their
* associated handlers. It is a passive system, hence,
* the application is responsible for waiting on the
* appropriate notification endpoint for events.
* The AEP binding feature of the seL4 kernel may be used
* here to listen to both synchronous IPC and IRQ
* notification events.
* 2. [irq server thread] An IRQ server node is a standalone thread which waits
* for the arrival of any IRQ that is being managed by a
* particular irq server node. When an IRQ is received,
* the irq server thread will either forward the irq
* information to a registered synchronous endpoint, or
* call the appropriate handler function directly.
* 3. [irq server] A dynamic collection of server threads. When
* registering an IRQ call back function, the irq server
* will attempt to deligate the IRQ to an irq server node
* that has not yet reached capacity. If no node can accept
* the IRQ, a new irq server thread will be created to
* support the additional demand.
*
* ++ Special notes ++
*
* Performance
* The application can achieve greater performance by configuring the irq server,
* or irq server threads, to call the IRQ handler functions directly. In this
* case, the application must take care to ensure that all concurrency issues are
* addressed.
*
* Resource availability
* The irq server API family accept resource allocators as arguments to some
* function calls. In a dynamic system design, these resource allocators
* must be kept available indefinitely, or until the system reaches a known
* steady state.
*/
#ifndef SEL4UTILS_IRQ_SERVER_H
#define SEL4UTILS_IRQ_SERVER_H
#include <autoconf.h>
#if (defined CONFIG_LIB_SEL4_VKA && defined CONFIG_LIB_SEL4_VSPACE && defined CONFIG_LIB_SEL4_SIMPLE)
#include <sel4/sel4.h>
#include <vspace/vspace.h>
#include <vka/vka.h>
#include <simple/simple.h>
typedef int irq_t;
struct irq_data;
/**
* @return non-zero if the IRQ should be ACKed
*/
typedef void (*irq_handler_fn)(struct irq_data* irq);
struct irq_data {
/// irq number
irq_t irq;
/// The capability for this irq number
seL4_CPtr cap;
/// Client data: function to call when the IRQ arrives
irq_handler_fn cb;
/// Client specific handle to pass to the callback function
void* token;
};
/**
* Allows a client to acknowledge an IRQ
* @param[in] irq The IRQ to acknowledge
*/
void irq_data_ack_irq(struct irq_data* irq);
/*********************************
*** IRQ server node functions ***
*********************************/
typedef struct irq_server_node* irq_server_node_t;
/**
* Create a new IRQ server node.
* @param[in] aep An async endpoint that can be used for binding IRQ notification
* @param[in] badge_mask A mask for the available badge. Bits NOT set in the mask are
* considered reserved and will not be used for IRQ identification.
* This does, however, reduce the number of IRQs that this node can
* manage. One may choose to reserve badge bits for the
* identification of other notifications to the same endpoint.
* @return A handle to the created IRQ server node, or NULL on failure.
*/
irq_server_node_t irq_server_node_new(seL4_CPtr aep, seL4_Word badge_mask);
/**
* Register an IRQ with a server node.
* @param[in] n The irq server node to register the IRQ with.
* @param[in] irq The IRQ number of the IRQ to be registered
* @param[in] cb A callback function to be called when the IRQ event occurs
* @param[in] token A token to be passed, unmodified, to te callback function
* @param[in] vka An allocator for for kernel objects
* @param[in] cspace The current capability space
* @param[in] simple A simple interface for creating the irq handler
* @return A handle to the irq structure that was created.
*/
struct irq_data* irq_server_node_register_irq(irq_server_node_t n, irq_t irq,
irq_handler_fn cb, void* token,
vka_t* vka, seL4_CPtr cspace,
simple_t* simple);
/****************************
*** IRQ server functions ***
****************************/
typedef struct irq_server* irq_server_t;
/**
* Initialises an IRQ server.
* The server will spawn threads to handle incoming IRQs. The function of the
* threads is to IPC the provided synchronous enpoint with IRQ information. When the IPC
* arrives, the application should call \ref{irq_server_handle_irq_ipc} while IPC
* registers are still valid. \ref{irq_server_handle_irq_ipc} will decode the provided
* information and redirect control to the appropriate IRQ handler.
* @param[in] vspace The current vspace
* @param[in] vka Allocator for creating kernel objects. If the server is
* configured to support a dynamic number of irqs, this
* resource allocator must remain available until the system
* reaches a steady state.
* @param[in] cspace The cspace of the current thread
* @param[in] priority The priority of spawned threads.
* @param[in] simple A simple interface for creating IRQ caps
* @param[in] sync_ep The synchronous endpoint to send IRQ's to
* @param[in] label A label to use when sending a synchronous IPC
* @param[in] nirqs The maximum number of irqs to support.
* -1 will set up a dynamic system, however, the
* approriate resource managers must remain valid for
* the life of the server.
* @param[out] irq_server An IRQ server structure to initialise.
* @return 0 on success
*/
int irq_server_new(vspace_t* vspace, vka_t* vka, seL4_CPtr cspace, seL4_Word priority,
simple_t *simple, seL4_CPtr sync_ep, seL4_Word label,
int nirqs, irq_server_t* irq_server);
/**
* Enable an IRQ and register a callback function
* @param[in] irq_server The IRQ server which shall be responsible for the IRQ.
* @param[in] irq The IRQ number to register for
* @param[in] cb A callback function to call when the requested IRQ arrives.
* @param[in] token Client data which should be passed to the registered call
* back function.
* @return On success, returns a handle to the irq data. Otherwise,
* returns NULL
*/
struct irq_data* irq_server_register_irq(irq_server_t irq_server, irq_t irq,
irq_handler_fn cb, void* token);
/**
* Redirects control to the IRQ subsystem to process an arriving IRQ.
* The server will read the appropriate message registers to retrieve the
* information that it needs.
* @param[in] irq_server The IRQ server which is responsible for the received IRQ.
*/
void irq_server_handle_irq_ipc(irq_server_t irq_server);
#endif /* (defined CONFIG_LIB_SEL4_VKA && defined CONFIG_LIB_SEL4_VSPACE) */
#endif /* SEL4UTILS_IRQ_SERVER_H */