request_irq

Autres langues

Langue: fr

Version: 1997/08/14 07:53:47 (fedora - 16/08/07)

Section: 9 (Appels noyau Linux)

NOM

request_irq, free_irq - déclare un gestionnaire d'interruptions

SYNOPSIS

#include <asm/irq.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
int request_irq(unsigned int irq, void (*gest)(int, void *, struct pt_regs *), unsigned long drap_interrupt, const char *devname, void *dev_id);

void free_irq(unsigned int irq, void *dev_id);

DESCRIPTION

Usage

La fonction request_irq() demande que la fonction indiquée (le gestionnaire) soit appellée à chaque fois que le noyau reçoit une certaine interruption. Le gestionnaiore peut lui-même enregistrer un gestionnaire bas, chargé de réaliser le gros du traitement de manière asynchrone. Consultez init_bh(9) pour plus d'information sur les gestionnaires d'interruptions asynchrones.

Le paramètres irq est le numéro de l'interruption à gérer. Il doit ête inférieur à NR_IRQS (16 sur les sytèmes à base d'architecture Intel ix86 alias ia32) ; il peut y avoir d'autres limitations sur cette valeur. Consultez arch/*/kernel/irq.c (intr.c pour les machines à base de Motorola 680x0 : m68k) pour plus d'informations.

gest est un pointeur sur la fonction chargée de gérer les interruptions. Le gestionnaire se verra passer les paramètres suivants lors de son exécution :

int irq
Le numéro d'interruption. En testant la valeur de ce paramètre, il est possible d'associer la gestion de plusieurs interruptions différentes à une même fonction.
void *dev_id
Le numéro de périphérique de ce gestionnaire (voir plus bas).
struct pt_regs *regs
Les registres stockés sur la pile du processus qui a été interrompu. Normalement, personne ne devrait avoir à s'en préoccuper ; cependant ils peuvent être lus pour, par exemple, déterminer si le processus suspendu était en mode utilisateur ou noyau.

drap_interrupt est, comme l'indique son nom, un masque de drapeaux (chacun représenté par un bit) relatifs à ce gestionnaire d'interruption. Les bits prédéfinis sont :

SA_INTERRUPT
Ce bit indique que le gestionnaire d'interruptions est un gestionnaire rapide. La sémantique de ce drapeau est défini plus loin.
SA_SHIRQ
Ce bit indique que le gestionnaire supporte le partage de l'interruption avec d'autres gestionnaires (voir aussi *dev_id plus loin).
SA_SAMPLE_RANDOM
Ce bit indique que cette interruption peut être utilisée comme générateur d'entropie pour /dev/random et /dev/urandom (voir drivers/char/random.c). [Ndt : voir aussi random(4), urandom(4)]
SA_PROBE
Ce bit indique que cette interruption est autodétectée et que le gestionnaire installé est bidon. Cette valeur était prévue pour être utilisée en interne par probe_irq_on() (q.v.), mais n'est plus utilisée dans les noyaux 2.1.x. En fait, même dans les noyaux 2.0.x, elle n'était déja plus utilisée dans l'architecture MIPS. Vous ne devriez donc pas utiliser cette valeur à moins que vous ne sachiez ce que vous faites.
SA_STATIC_ALLOC
(Sparc/Sparc64 seulement). Ce bit demande à ce que la structure struct irqaction (voir plus loin) soit ajoutée à une tableau statiquement préalloué de quatre gestionnaires plutôt que dans la table habituelle irq_action[] . Ceci est utilisé pour les interruptions qui doivent être utilisées tôt dans le processus d'initialisation du système, avant que kmalloc_init() soit appelé.

Le paramètre devname est un nom court pour le périphérique et est affiché dans la liste /proc/interrupts.

Le paramètre dev_id est le numéro d'identification du périphérique. Ce paramètre est fréquemment initialisé à NULL, mais ne devrait pas l'être dans le cas des interruptions partagées. Cela n'a aucune importance en utilisation courante, mais quand free_irq() est appelée, le pilote correct est appelé. Comme son type est void *, il peut pointer sur n'importe quoi, comme une structure spécifique à un périphérique, ou même un espace mémoire vide, mais soyez certain de passer le même pointeur à free_irq().

La fonction free_irq() libère un gestionnaire d'interruption. Elle prend en paramètres, le numéro d'interruptions à désenregistrer et le numéro de périphérique à désenregistrer. Vous devriez passer la même valeur que celle passée à request_irq(). Vous ne devriez probablement jamais désenregistrer un autre gestionnaire à moins de savoir ce que vous faites.

Opération

Sur la plupart des architectures, request_irq() alloue de la mémoire pour une structure de type struct irqaction, remplit ses champs, et l'ajoute à la table irq_action[] . enable_irq() est ensuite appelée pour signaler au noyau de commencer à délivrer les interruptions au gestionnaire nouvellement installé. Ce processus est très différent sur les machines à base de m68k, où il dépend du sous-type de machine (Amiga, Atari, etc.). free_irq() enlève simplement les entrées que request_irq() a ajoutées. NB : certains de ces noms changent sur certaines architectures (par exemple, struct irqaction est appelée struct irq_action sur les Power PC). Si vous désirez approfondir vos connaissances sur le fonctionnement interne de ces fonctions, vous devriez lire les sources, car une partie de ces informations peut avoir changé lorsque vous lirez cette page (dans ce cas, signalez-le moi afin que je mette à jour cette page).

Gestionnaire d'Interruption Rapides

Un gestionnaire d'inrruption « rapide » (dont le bit SA_INTERRUPT est positionné) a un comportement différent d'un gestionnaire « lent » :

Sur ix86 et MIPS, durant l'exécution du gestionnaire, les interruptions sont désactivées (elles sont activées par défaut sur ces machines et désactivées sur les autres).
Sur MIPS, le retour est plus rapide.
Sur Alpha, MIPS, Sparc et Sparc64, un gestionnaire lent et un gestionnaire rapide ne peuvent pas partager la même interruption.
Sur toutes les architectures, exceptés les m68k et les ix86, un `+' est affiché entre le compteur d'interruptions et le nom du périphérique dans /proc/interrupts.

La distinction d'interruptions lente/rapide est lentement dépréciée. Par exemple, sous 2.0.x sur ix86, SA_INTERRUPT activait un retour rapide comme il le fait encore sur le MIPS ; Cette distinction a été supprimée dans le 2.1.x.

VALEUR RENVOYÉE

En cas de succès, request_irq() renvoie 0 si tout s'est déroulé normalement. Votre gestionnaire d'interruptions commencera à recevoir des interruptions immédiatement. En cas d'échec, request_irq() renvoie :
-EINVAL
Le numéro d'interruption indiqué n'est pas valide ou est réservé, ou alors, un pointeur NULL a été passé pour le paramètre gest() .
-ENOMEM
request_irq() ne peut pas allouer suffisamment de mémoire pour quelque chose (probablement la structure struct irqaction).
-EBUSY
L'interruption indiquée est déjà gérée, et ne peut être partagée entre plusieurs gestionnaires. Cette erreur se produit lorque le gestionnaire en cours d'enregistrement ou celui déja enregistré n'a pas le bit SA_SHIRQ activé dans son champ drap_interrupt . De plus, sur la plupart des architectures, tous les gestionnaires partageant la même interruption doivent avoir la même « vitesse », c'est-à-dire être soit tous soit aucun d'entre eux ont le bit SA_INTERRUPT positionné. Enfin, il est possible que votre architecture ne supporte pas le partage de l'interruption que vous voulez utiliser.
-ENXIO
Sur m68k, cette valeur de retour indique un mauvais numéro d'interruption.

free_irq() ne renvoie aucune valeur.

DISPONIBILITÉ

Linux 2.1+. Les informations de cette page devraient fonctionner avec un noyau 2.0.x, mais de légères différences d'implémentation peuvent être rencontrées (particulièrement dans le comportement de SA_INTERRUPT sur les machines à base d'ix86). Les versions plus anciennes que la 2.0.0 possèdent ces fonctions mais ne passent pas le paramètre dev_id . Si vous voulez voir votre code fonctionner sur des versions plus anciennes et plus récentes que le 2.0, vous devriez protéger votre code avec des macros du préprocesseur utilisant LINUX_VERSION_CODE.

VOIR AUSSI

init_bh(9), probe_irq_on(9), arch/*/kernel/irq.c, arch/*/kernel/entry.S, include/linux/interrupt.h, include/asm*/signal.h.

AUTEUR

Neil Moore <amethyst@maxwell.ml.org>

TRADUCTION

Thierry Vignaud <tvignaud@mandrakesoft.com>, 2000

BOGUES

Ce n'est pas exactement un bug, mais request_irq() ne fontionne pas tout à fait
 sur m68k comme sur les autres architectures. Vous devriez lire arch/m68k/kernel/ints.c, arch/m68k/atari/ataints.c, arch/m68k/amiga/amiints.c, et arch/m68k/amiga/cia.c si vous souhaitez écrire un pilote pour l'un de ces systèmes.