diff --git a/fr_FR.ISO8859-1/articles/ddwg/Makefile b/fr_FR.ISO8859-1/articles/ddwg/Makefile deleted file mode 100644 index 68714b471c..0000000000 --- a/fr_FR.ISO8859-1/articles/ddwg/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# The FreeBSD Documentation Project -# The FreeBSD French Documentation Project -# -# $Id: Makefile,v 1.1 2000-06-01 19:14:23 gioria Exp $ -# Original revision: 1.4 -# - -DOC?= article - -FORMATS?= html - -INSTALL_COMPRESSED?=gz -INSTALL_ONLY_COMPRESSED?= - -SRCS= article.sgml - -DOC_PREFIX?= ${.CURDIR}/../../.. - -.include "${DOC_PREFIX}/share/mk/doc.project.mk" diff --git a/fr_FR.ISO8859-1/articles/ddwg/article.sgml b/fr_FR.ISO8859-1/articles/ddwg/article.sgml deleted file mode 100644 index cb60f6477c..0000000000 --- a/fr_FR.ISO8859-1/articles/ddwg/article.sgml +++ /dev/null @@ -1,1869 +0,0 @@ - - - %man; - %urls; - %abstract; - %artheader; - %translators; - - %authors - %mailing-lists; - - - - - - - - -]> - - -
- - Le guide de l'auteur de pilotes de périphériques pour FreeBSD - - - Eric L. - Hernes - - - &artheader.copyright; - - erich@rrnet.com - 29 Mai 1996 - Ce document décrit comment ajouter un module de gestion de -périphérique à FreeBSD. Il n'est pas destiné pour être un -cours d'instruction sur des modules de gestion de périphérique -d'Unix en général. Il est destiné pour les auteurs de module de -gestion de périphérique, au courant du modèle de module de gestion -de périphérique d'Unix, pour travailler sur FreeBSD. - - &abstract.license; - &abstract.disclaimer; - &trans.a.dntt; - - - - - -Spécificité de FreeBSD2.x - -Dû aux changements de FreeBSD avec le temps, ce guide est -seulement précis en ce qui concerne FreeBSD 2.x. Un guide de -rechange pour FreeBSD 3.x et au-delà est en train d'être écrit. -Contactez Jeroen Ruigrok asmodai@wxs.nl si -vous voulez l'aider à ce sujet. - - - - - -Généralité - - Le noyau de FreeBSD est très bien -documenté, malheureusement il est entièrement écrit en `C'. - - - - -Types de pilotes de module de périphériques. - - -Caractère - - -Structures de données - -Structure cdevsw - - - -Points d'entrée - - -<function>d_open()</function> - -d_open() prend plusieurs arguments, la liste formelle ressemble à -quelque chose comme : - - - -int -d_open(dev_t dev, int flag, int mode, struct proc *p) - - -d_open() est appelé à chaque ouverture du périphérique. - -L'argument dev contient le nombre majeur et mineur du -périphérique ouvert. Ils sont disponibles par les macros -major() et minor() - - -Les arguments flag et mode sont comme décrits sur -la page de manuel de -open. -Il est recommandé que vous examiniez -ces derniers pour vous assurer des droits d'accès dans <sys/fcntl.h> -et faire ce qui est exigé. Par exemple si flag est -(O_NONBLOCK | O_EXLOCK) l'ouverture échouerait si il bloquait ou -si l'accès exclusif ne pouvait pas être accordé. - - - -L'argument p contient toutes les informations à propos du -processus actuel. - - - - -<function>d_close()</function> - d_close() prend la même liste d'argument que d_open(): - - - -int -d_close(dev_t dev , int flag , int mode , struct proc *p) - - -d_close() est seulement appelé à la dernière fermeture de votre -périphérique (par périphérique mineur). Par exemple dans le fragment -suivant de code, d_open() est appelé 3 fois, mais d_close() -seulement une fois. - - - - ... - fd1=open("/dev/mydev", O_RDONLY); - fd2=open("/dev/mydev", O_RDONLY); - fd3=open("/dev/mydev", O_RDONLY); - ... - <useful stuff with fd1, fd2, fd3 here> - ... - close(fd1); - close(fd2); - close(fd3); - ... - - -Les arguments sont semblables à ceux décrits ci-dessus pour -d_open(). - - - - -<function>d_read()</function> et <function>d_write()</function> - -d_read() et d_write prennent les listes suivantes d'argument: - - - -int -d_read(dev_t dev, struct uio *uio, int flat) -int -d_write(dev_t dev, struct uio *uio, int flat) - - - -Les points d'entrée de d_read() et de d_write() sont appelés quand -read et -write -sont appelés sur votre périphérique depuis l'espace utilisateur. Le transfert -des données peut être manipulé par la routine du noyau uiomove(). - - - - -<function>d_ioctl()</function> - - Sa liste d'argument est comme suit: - - -int -d_ioctl(dev_t dev, int cmd, caddr_t arg, int flag, struct proc *p) - - - -d_ioctl() est un fourre-tout pour les exécutions qui ne semblent -pas raisonnable dans un paradigme lecture/écriture. Le plus -célèbre de tout les ioctl est probablement celui sur des périphériques -tty, par le -stty. - -Le point d'entrée d'ioctl est appelé depuis l'ioctl() de -sys/kern/sys_generic.c - - -Il y a quatre types différents d'ioctl qui peuvent être implémentés. - -<sys/ioccom.h> contient des macros pratiques de -pour définir ces ioctls. - - - - -_IO(g, n) pour les opérations de type contrôle. - - - - - -_IOR(g, n, t) pour des opérations lisant des données d'un -périphérique. - - - - - -_IOW(g, n, t) pour les opérations écrivant des données -sur un périphérique. - - - - - -_IOWR(g,n,t) pour les opérations écrivant sur un périphérique -puis lisent les données. - - - - - - -Ici g se rapporte à un groupe /. C'est une valeur -de 8 bits, en général indicative du périphérique ; par exemple, 't' -est utilisé dans des ioctls de tty. n se -rapporte au nombre de l'ioctl dans le groupe. Sur SCO, ce seul nombre -dénote l'ioctl. t est le type de données qui sera -passé au pilote de périphérique; ceci est alors remis à un opérateur -sizeof() du noyau. L'appel système ioctl() fera soit un copyin() -soit un copyout() ou les deux à votre pilote, puis vous -renverra un pointeur à la structure de données dans l'argument -arg de l'appel d'd_ioctl. Actuellement la taille de -données est limitée à une page (4k sur l'i386). - - - - -<function>d_stop()</function> - - - - -<function>d_reset()</function> - - - - -<function>d_devtotty()</function> - - - - -<function>d_poll()</function> (3.0 et plus) ou <function>d_select()</function> (2.2) - -la liste d'argument de d_poll() est comme suit : - - - -void -d_poll(dev_t dev, int events, struct proc *p) - - - d_poll() est employé pour découvrir si un périphérique -est prêt pour les E/S. Par exemple, attendre que des données du réseau -soient disponibles, ou que l'utilisateur presse une touche. -Cela correspond à un appel de poll() dans l'espace utilisateur. - - -L'appel à d_poll() devrait vérifier les événements -indiqués dans le masque d'évènement. Si aucun des événements demandés n'est -en activité, mais qu'elles pourraient devenir actif plus tard, il -devrait enregistrer ceci pour les actions futures du noyau. -d_poll() fait ceci en appelant selrecord() avec une structure -selinfo pour ce périphérique. La somme de toutes ces activités -ressemblent à quelque chose comme ceci: - - - -static struct my_softc { - struct queue rx_queue; /* As example only - not required */ - struct queue tx_queue; /* As example only - not required */ - struct selinfo selp; /* Required */ -} my_softc[NMYDEV]; - -... - -static int -mydevpoll(dev_t dev, int events, struct proc *p) -{ - int revents = 0; /* Events we found */ - int s; - struct my_softc *sc = &my_softc[dev]; - - /* We can only check for IN and OUT */ - if ((events & (POLLIN|POLLOUT)) == 0) - return(POLLNVAL); - - s = splhigh(); - /* Writes are if the transmit queue can take them */ - if ((events & POLLOUT) && - !IF_QFULL(sc->tx_queue)) - revents |= POLLOUT; - /* ... while reads are OK if we have any data */ - if ((events & POLLIN) && - !IF_QEMPTY(sc->rx_queue)) - revents |= POLLIN; - if (revents == 0) - selrecord(p, &sc->selp); - splx(s); - return revents; -} - - - d_select() est utilisé dans la version 2.2 et -précédentes de FreeBSD. Au lieu de 'events', il prend un simple -entier 'rw', qui peut être FREAD pour la lecture (comme dans -POLLIN ci-dessus), FWRITE pour l'écriture (comme dans POLLOUT ci-dessus), -et 0 pour 'exception' - lorsque quelque chose d'exceptionnel se produit, -comme une carte étant insérée ou retirée pour le pilote de -pccard. - -Pour 'select', le fragment correspondant à la description -ci-dessus ressembleraient à ceci: - - -static int -mydevselect(dev_t dev, int rw, struct proc *p) -{ - int ret = 0; - int s; - struct my_softc *sc = &my_softc[dev]; - - s = splhigh(); - switch (rw) { - case FWRITE: - /* Writes are if the transmit queue can take them */ - if (!IF_QFULL(sc->tx_queue)) - ret = 1; - break; - case FREAD: - /* ... while reads are OK if we have any data */ - if (!IF_QEMPTY(sc->rx_queue)) - ret = 1; - break; - case 0: - /* This driver never get any exceptions */ - break; - } - if(ret == 0) - selrecord(p, &sc->selp); - splx(s); - return(revents); -} - - - - -<function>d_mmap()</function> - - - - -<function>d_strategy()</function> - - -La liste d'argument de d_strategy() est comme suit : - - - -void -d_strategy(struct buf *bp) - - -d_strategy() est utilisé pour les périphériques utilisant -des E/S de type disperser-regrouper (scatter-gather). -C'est ce qu'il y a de plus courant dans un périphérique de bloc. -C'est sensiblement différent du modèle de système V, où seulement -le pilote de bloc fait une E/S de type disperser-regrouper. -Sous BSD, les périphériques de caractère sont parfois sommé d'exécuter -une E/S de type disperser-regrouper par l'intermédiaire des appels -systèmes readv() et writev(). - - - - - -Fichiers d'en-tête - - - - - -Bloc - - -Structures de données - Structure struct bdevsw - - - Structure struct buf - - - - -Points d'entrée - - -<function>d_open()</function> - Décrit dans la section périphérique de caractère. - - - - -<function>d_close()</function> -Décrit dans la section périphérique de caractère. - - - - -<function>d_strategy()</function> -Décrit dans la section périphérique de caractère. - - - - -<function>d_ioctl()</function> -Décrit dans la section périphérique de caractère. - - - - -<function>d_dump()</function> - - - - -<function>d_psize()</function> - - - - - -Fichiers d'en-tête - - - - - -Réseau -Structure struct ifnet - - - -Points d'entrée - - -<function>if_init()</function> - - - - -<function>if_output()</function> - - - - -<function>if_start()</function> - - - - -<function>if_done()</function> - - - - -<function>if_ioctl()</function> - - - - -<function>if_watchdog()</function> - - - - - -Fichiers d'en-tête - - - - - -Protocole de communication - - -Structures de données -Structure struct linesw - - - - -Points d'entrée - - -<function>l_open()</function> - - - - -<function>l_close()</function> - - - - -<function>l_read()</function> - - - - -<function>l_write()</function> - - - - -<function>l_ioctl()</function> - - - - -<function>l_rint()</function> - - - - -<function>l_start()</function> - - - - -<function>l_modem()</function> - - - - - -Fichiers d'en-tête - - - - - - -Bus Supportés - - -ISA -- Architecture Standard d'Industrie (<foreignphrase>Industry Standard -Architecture</foreignphrase> - - -Structures de données - - -Structure <citerefentry><refentrytitle>struct isa_device</refentrytitle></citerefentry> - -Cette structure est obligatoire, mais généralement elle est créée par -config à partir du fichier de configuration de noyau. -Elle est requise pour chaque périphérique, c'est à dire que si vous avez -un pilote de périphérique contrôlant deux "serial boards", vous -aurez deux structures isa_device. Si vous construisez un périphérique -comme un LKM, vous devrez créer votre propre structure isa_device afin -de refléter votre configuration (lignes 85 - 131 de pcaudio_lkm.c). -Il y a une équivalence directe entre le fichier de configuration et la -structureisa_device. La définition de -/usr/src/sys/i386/isa/isa_device.h -est : - - - -struct isa_device { - int id_id; /* device id */ - struct isa_driver *id_driver; - int id_iobase; /* base i/o address */ - u_short id_irq; /* interrupt request */ - short id_drq; /* DMA request */ - caddr_t id_maddr; /* physical i/o memory address on bus (if any)*/ - int id_msize; /* size of i/o memory */ - inthand2_t *id_intr; /* interrupt interface routine */ - int id_unit; /* unit number */ - int id_flags; /* flags */ - int id_scsiid; /* scsi id if needed */ - int id_alive; /* device is present */ -#define RI_FAST 1 /* fast interrupt handler */ - u_int id_ri_flags; /* flags for register_intr() */ - int id_reconfig; /* hot eject device support (such as PCMCIA) */ - int id_enabled; /* is device enabled */ - int id_conflicts; /* we're allowed to conflict with things */ - struct isa_device *id_next; /* used in isa_devlist in userconfig() */ -}; - - - - -Structure <citerefentry><refentrytitle>struct isa_driver</refentrytitle></citerefentry> - -Cette structure est définie dans -/usr/src/sys/i386/isa/isa_device.h, -est est requise pour chaque pilote de périphérique. La définition -est : - - - -struct isa_driver { - int (*probe) __P((struct isa_device *idp)); - /* test whether device is present */ - int (*attach) __P((struct isa_device *idp)); - /* setup driver for a device */ - char *name; /* device name */ - int sensitive_hw; /* true if other probes confuse us */ -}; - - - -C'est la structure employée par le code sondage/attachement -(probe/attach) pour -détecter et initialiser votre périphérique. Le membre probe -est un pointeur à votre fonction permettant de sonder les périphériques. -Le membre attach est un pointeur vers votre fonction d'attache. -Le membre name est un pointeur de caractère sur le nom de deux -ou trois lettres de votre pilote. -C'est le nom enregistré pendant le processus de -sondage/attachement (et probablement aussi dans -lsdev). -Le membre sensitive_hw est un -indicateur qui aide le code de sondage à déterminer l'ordre du sondage. - - - -Un instantiation typique est: - - - -struct isa_driver mcddriver = { mcd_probe, mcd_attach, "mcd" }; - - - - - -Points d'entrée - - -<function>probe()</function> -probe() prend un pointeur sur une structure isa_device -comme argument et renvoie un int. La valeur de retour est ``zéro'' ou -``non-zéro '' quant à l'absence ou à la présence de votre périphérique. -Ce point d'entrée peut être déclaré comme -static parce qu'il -est accessible par l'intermédiaire du membre -probe de la structre -isa_driver. Cette fonction est destinée à -détecter la présence de votre périphérique seulement et ne devrait -faire aucune configuration du périphérique elle-même. - - - - -<function>attach()</function> - -attach() prend également un pointeur sur une structure -isa_device comme argument et -renvoie un int. La valeur de retour est également ``zéro'' ou -``non-zéro'' indiquant si l'attache a réussie. Cette fonction -est destinée pour faire n'importe quelle initialisation spéciale du -périphérique aussi bien que pour confirmer que le périphérique est utilisable. -Il devrait aussi être déclaré static parce qu'il est accesible -par le membre attach de la structure isa_driver . - - - - - -Fichiers d'en-tête - - - - - -EISA -- Architecture Étendue de Standard industriel (<foreignphrase>Extended Industry Standard Architecture</foreignphrase>) - - - -Structures de données - -Structure struct eisa_dev -Structure struct isa_driver - - - -Points d'entrée - - -<function>probe()</function> -Décrit dans la section de périphérique ISA. - - - -<function>attach()</function> -Décrit dans la section de périphérique ISA. - - - - -Fichiers d'en-tête - - - - - -PCI -- Bus d'interconnexion Périphérique (<foreignphrase>Peripheral Computer -Interconnect</foreignphrase>) - - -Structures de données - - Structure struct pci_device - - - - -nom : Le nom abrégé du périphérique. - - - - - sonde: Contrôle si le pilote peut supporter un périphérique avec -ce type. L'étiquette peut être employée pour obtenir plus -d'information avec pci_read_conf(). Voir ci-dessous. Elle renvoie -une chaîne de caractères avec le nom du périphérique, ou un pointeur -NULL si le pilote ne peut pas supporter ce périphérique. - - - - - attache: Assigne une structure de contrôle et la prépare. Cette -fonction peut utiliser les fonctions de mapping PCI. Voir -ci-dessous. (identification de configuration) ou type. - - - - - compte: Un pointeur sur un compteur d'unité. Il est -employé par le configurateur de PCI pour assigner des numéros. - - - - - - - -Points d'entrée - - -<function>probe()</function> - - - - -<function>attach()</function> - - - - -<function>shutdown()</function> - - - - - -Fichiers d'en-tête - - - - - -SCSI -- <foreignphrase>Small Computer Systems Interface</foreignphrase> - - -Structure de données - -Structure struct scsi_adapter -Structure struct scsi_device -Structure struct scsi_ctlr_config -Structure struct scsi_device_config -Structure struct scsi_link - - - -Points d'entrée - - -<function>attach()</function> - - - - -<function>init()</function> - - - - - -Fichiers d'en-tête - - - - - - -PCCARD (PCMCIA) - - -Structure de données - -Structure struct slot_cont -Structure struct pccard_drv -Structure struct pccard_dev -Structure struct slot - - - -Points d'entrée - - -<function>handler()</function> - - - - -<function>unload()</function> - - - - -<function>suspend()</function> - - - - -<function>init()</function> - - - - - -Fichiers d'en-tête - -<pccard/slot.h> - - - - - - - -Incorporation dans le noyau - -Dans FreeBSD, le support des bus d'ISA et EISA est spécifique à -i386. Tandis que FreeBSD lui-même est actuellement -disponible sur la plateforme i386, un certain effort a été fait pour -faire du code portable pour PCI, PCCARD, et SCSI. Le code -spécifique à ISA et EISA réside dans -/usr/src/sys/i386/isa et -/usr/src/sys/i386/eisa respectivement. Le code indépendant de la -machine de PCI, de PCCARD, et de SCSI réside dans -/usr/src/sys/{pci,pccard,scsi}. Le code spécifique i386 quand à lui -réside dans /usr/src/sys/i386/{pci, pccard, scsi}. - - - - Dans FreeBSD, un module de gestion de périphérique peut -être soit sous forme binaire soit sous forme de sources. -Il n'y a aucun endroit ``officiel'' pour mettre les binaires des -pilotes de périphériques. Les systèmes BSD utilisent quelque -chose comme sys/i386/OBJ. Puisque la plupart des pilotes sont -distribués dans les sources, la discussion suivante se rapporte à un -source pilote de périphérique. -Des binaires de pilotes de périphériques sont -parfois fournis par les constructeurs de matériel qui souhaitent -maintenir les sources de manière propriétaire. - - - Un pilote typique a son code source sous forme de fichier C, -comme dev.c. Le pilote peut également inclure des -fichiers; devreg.h contient typiquement des déclarations publiques -de registre de périphérique, des macros, et d'autres -déclarations spécifique au pilote de périphérique. -Quelques pilotes appellent parfois ce fichier devvar.h. -Quelques pilotes, tels que -le dgb (pour le Digiboard PC/Xe), exigent que du microcode soit chargé -sur la carte. Pour le pilote de dgb le microcode est compilé -et reporté dans un fichier d'en-tête par -file2c. - - - Si le pilote de périphérique a des structures de données et des -ioctl qui sont spécifiques au pilote de périphérique ou -périphérique, et -doivent être accessibles de l'espace-utilisateur, elles devraient -être mises dans un fichier d'en-tête séparé qui résidera dans -/usr/include/machine/ (certaines de ces derniers résident dans -/usr/include/sys/). Ceux-ci est typiquement nommé quelque chose comme -ioctl_dev.h ou devio.h. - - - Si un pilote écrit depuis l'espace -d'utilisateur est identique à un périphérique qui existe déjà, il faut -prendre garde à utiliser les mêmes -interfaces ioctl et structures de données. Par exemple, de l'espace -utilisateur, un lecteur de SCSI CDROM devrait être identique à un -lecteur de cdrom IDE; ou une ligne série sur une carte -intelligente multiport (Digiboard, Cyclades...) devrait être identique -à un périphérique sio. Ces périphériques ont une interface définie -relativement bonne et devraient être utilisées. - - - Il y a deux méthodes pour lier un pilote dans le -noyau, statiquement et le modèle LKM. La première méthode -est assez standard à travers la famille *BSD. L'autre -méthode a été initialement développée par Sun (je crois), et a -été mis en application dans BSD en utilisant le modèle de Sun. -Je ne crois pas que l'implémentation actuelle utilise encore le moindre -code de Sun. - - - -Modèle Standard - - Les étapes exigées pour ajouter votre pilote au -noyau standard de FreeBSD sont - - - - -Ajout à la liste des pilotes de périphérique - - - - -Ajout d'une entrée au [bc]devsw - - - - -Ajout d'une entrée du pilote de périphérique au fichier de -configuration du noyau - - - - -config, -compilation et installation du noyau - - - - -créer les fichiers spéciaux requis - - - - -redémarrage - - - - - -Ajout à la liste des pilotes de périphérique - -Le modèle standard pour ajouter un module de gestion de périphérique -au noyau de Berkeley est d'ajouter votre pilote à la liste des -périphériques connus. Cette liste dépend de l'architecture du CPU. -Si le périphérique n'est pas spécifique i386 -(PCCARD, PCI, SCSI), le fichier est dans -/usr/src/sys/conf/files. -Si le périphérique est spécifique i386, utilisez -/usr/src/sys/i386/conf/files.i386. Une ligne typique ressemblerait -à : - - - -i386/isa/joy.c optional joy device-driver - - -Le premier champ relatif est le chemin du module de pilote -par rapport à /usr/src/sys. -Pour le cas d'un pilote binaire, le chemin d'accès serait quelque -chose comme i386/OBJ/joy.o. - - -Le deuxième champ indique à -config(8) -que c'est un pilote facultatif. Quelques -périphériques sont obligatoires pour que le noyau puisse être construit. - - - -Le troisième champ est le nom du périphérique. - - -Le quatrième champ indique à config que c'est un -pilote de périphérique (par opposition à juste facultatif). Ceci -dit à config de créer des entrées pour le périphérique dans dans -des structures de /usr/src/sys/compile/KERNEL/ioconf.c. - - -Il est également possible de créer un fichier -/usr/src/sys/i386/conf/files.KERNEL dont le contenu ignorera le -fichier par défaut files.i386, mais seulement pour le noyau ``KERNEL''. - - - - -Faire de la place dans conf.c - -Maintenant vous devez éditer /usr/src/sys/i386/i386/conf.c -pour faire une entrée pour votre pilote. Quelque part au début, -vous devez déclarer vos points d'entrée. L'entrée pour -le pilote du joystick est: - - -#include "joy.h" -#if NJOY > 0 -d_open_t joyopen; -d_close_t joyclose; -d_rdwr_t joyread; -d_ioctl_t joyioctl; -#else -#define joyopen nxopen -#define joyclose nxclose -#define joyread nxread -#define joyioctl nxioctl -#endif - - - -Cela définit vos points d'entrée, ou points d'entrée nuls qui -renverront ENXIO quand appelé (clause #else). - - - -Le fichier d'en-tête ``joy.h'' est automatiquement produit par -config -quand l'arborescence de construction du noyau est -créé. Cela se réduit habituellement à une seule ligne comme : - - - -#define NJOY 1 - - - -ou - - -#define NJOY 0 - - - ce qui définit le nombre de vos périphériques dans votre noyau. - - - -Vous devez de plus ajouter un slot au cdevsw[&rsqb, ou -au bdevsw[&rsqb, selon que ce soit un périphérique caractère, -périphérique bloc, ou les deux si c'est un périphérique bloc -avec une interface brute. L'entrée pour le pilote du joystick -est: - - - -/* open, close, read, write, ioctl, stop, reset, ttys, select, mmap, strat */ -struct cdevsw cdevsw[] = -{ - ... - { joyopen, joyclose, joyread, nowrite, /*51*/ - joyioctl, nostop, nullreset, nodevtotty,/*joystick */ - seltrue, nommap, NULL}, - ... -} - - - - L'ordre est ce qui détermine le nombre majeur de votre -périphérique. C'est pourquoi il y aura toujours une entrée -pour votre pilote, que ce soit des points d'entrée nuls, -ou des points d'entrée actuels. Il est probablement intéressant de -noter que c'est -sensiblement différent de SCO et d'autres dérivés du système V, où -n'importe quel périphérique (dans la théorie) peut avoir n'importe -quel nombre majeur. C'est en grande partie un avantage sur FreeBSD, -sur la manière dont les fichiers spéciaux de périphérique sont créés. -Nous reviendrons en détail sur ceci plus tard. - - - - -Ajout de votre périphérique dans le fichier de configuration. - - Ceci ajoute simplement une ligne décrivant votre périphérique. La -ligne de description du joystick est : - -device joy0 at isa? port "IO_GAME" - -Ceci indique que nous avons un -périphérique appelé ``joy0'' sur le bus ISA en utilisant -le port E/S ``IO_GAME'' (IO_GAME est une macro définie dans -/usr/src/sys/i386/isa/isa.h). - - - -Une entrée légèrement plus compliquée est pour le pilote ``ix'' : - - -device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 -vector ixintr - - -Ceci indique que nous avons un périphérique appelé -`ix0 ' sur le bus ISA. Il utilise le port E/S 0x300. Son -interruption sera masqué par d'autres périphériques dans la classe -réseau. Il utilise l'interruption 10. Il utilise 32k de mémoire -partagée à l'adresse physique 0xd0000. Il le définit également -son pilote d'interruption comme étant ``ixintr()'' - - - - -<ulink url="http://www.freebsd.org/cgi/man.cgi?config(8)">config</ulink> -du noyau. - - Maintenant avec notre fichier de configuration en main, -nous pouvons créer un répertoire de compilation du noyau. Cela peut être -fait en tapant : - -# config KERNEL - - -où KERNEL est le nom de votre fichier de configuration. -La configuration crée un arbre de compilation -pour votre noyau dans /usr/src/sys/compile/KERNEL. Elle crée le fichier -makefile, quelques fichiers C, et quelques fichiers H avec des -macros définissant le nombre de chaque périphérique à inclure dans votre -votre noyau. - - - -Maintenant vous pouvez aller dans le répertoire de compilation et -construire votre noyau. À chaque fois que vous lancerez config, votre -arbre de construction précédent sera retiré, à moins que vous ne lancez -config avec un -n. Si vous avez configuré et compilé un noyau GENERIC, -vous pouvez faire un ``make links'' afin d'éviter de compiler certains -fichiers à chaque itération. Typiquement, je lance : - -# make depend links all - -suivi d'un ``make install'' quand le noyau me convient. - - - - -Créer les fichiers spéciaux de périphériques - - Sur FreeBSD, vous avez la responsabilité de faire vos propres fichiers -spéciaux -de périphérique. Le -nombre majeur de votre périphérique est déterminé par le nombre de -slots dans le commutateur de périphérique. Le nombre mineur est -dépendant du pilote, naturellement. Vous pouvez -soit exécuter mknod depuis la ligne de commande, soit laisser faire le -travail à /dev/MAKEDEV.local, ou même -/dev/MAKEDEV. -Je crée parfois un script MAKEDEV.dev qui peut être soit lancé -de manière autonome soit collé dans /dev/MAKEDEV.local. - - - - -Redémarrage - C'est la partie facile. Il y a un -certain nombre de méthodes pour faire ceci, reboot, fastboot, -shutdown - r, couper le courant, etc. Au démarrage, vous -devriez voir votre XXprobe() appelé, et si tout marche, -votre attach() aussi. - - - - - -Module du noyau à chargement dynamique (LKM) - -Il n'y a vraiment aucune procédure définie pour écrire un pilote de -LKM. Ce qui suit est ma propre conception après expérimentation -avec l'interface de périphérique LKM et en regardant le modèle standard -de module de gestion de périphérique, c'est une manière d'ajouter une -interface LKM à un pilote existant sans toucher aux sources (ou binaire) -initiaux de pilote . On recommande cependant, -que si vous projetez de distribuer les sources de votre pilote, -que les parties spécifiques LKM devraient faire partie du pilote -lui-même, compilé de manière conditionnelle par la macro LKM -(c.-à-d. #ifdef LKM). - - - -Cette section se concentrera sur la manière d'écrire la partie spécifique -LKM du pilote. Nous supposerons que nous avons écrit un -pilote qui atterrira dans le modèle standard de -gestion de périphérique, que nous voudrions maintenant mettre en -application comme étant LKM. Nous utiliserons le pilote de pcaudio -comme pilote d'exemple, et développerons une entrée LKM. La -source et le fichier makefile pour le LKM pcaudio , ``pcaudio_lkm.c'' -et ``Makefile'', devraient être dans placé /usr/src/lkm/pcaudio. -Ce qui suit est le code commenté de pcaudio_lkm.c. - - - -Lignes 17 - 26 - - - -Ceci inclut le fichier ``pca.h'' et fait une compilation conditionnelle -du reste de LKM suivant que vous avez défini ou non le pilote de -périphérique pcaudio. -Cela imite le comportement de config. Dans un pilote de -périphérique standard, -config -produit le fichier pca.h depuis le nombre de périphériques pca -le fichier de config. - - - 17 /* - 18 * figure out how many devices we have.. - 19 */ - 20 - 21 #include "pca.h" - 22 - 23 /* - 24 * if we have at least one ... - 25 */ - 26 #if NPCA > 0 - - - -Lignes 27 - 37 - - - -Les fichiers d'en-tête requis depuis divers répertoire d'inclusion. - - - - 27 #include <sys/param.h> - 28 #include <sys/systm.h> - 29 #include <sys/exec.h> - 30 #include <sys/conf.h> - 31 #include <sys/sysent.h> - 32 #include <sys/lkm.h> - 33 #include <sys/errno.h> - 34 #include <i386/isa/isa_device.h> - 35 #include <i386/isa/isa.h> - 36 - 37 - - - -Lignes 38 - 51 - - -déclarent vos points d'entrée comme externs . - - - - 38 /* - 39 * declare your entry points as externs - 40 */ - 41 - 42 extern int pcaprobe(struct isa_device *); - 43 extern int pcaattach(struct isa_device *); - 44 extern int pcaopen(dev_t, int, int, struct proc *); - 45 extern int pcaclose(dev_t, int, int, struct proc *); - 46 extern int pcawrite(dev_t, struct uio *, int); - 47 extern int pcaioctl(dev_t, int, caddr_t); - 48 extern int pcaselect(dev_t, int, struct proc *); - 49 extern void pcaintr(struct clockframe *); - 50 extern struct isa_driver pcadriver; - 51 - - - -Lignes 52 - 70 - - - -Cela crée la table d'entrée de commutateur de périphérique pour -votre pilote. Cette table est en gros entièrement mise dans le -système de commutation de périphériques à l'emplacement indiqué par -votre nombre majeur. Dans le modèle standard, c'est dans -/usr/src/sys/i386/i386/conf.c. -NOTE: vous ne pouvez pas sélectionner -un nombre majeur de périphérique plus grand que ce qui existe dans -conf.c, par exemple -il y a 67 slots pour des périphériques caractère, vous ne pouvez pas -utiliser un périphérique (caractère) de numéro majeur 67 ou -plus, sans avoir d'abord réservé de l'espace dans conf.c. - - - - 52 /* - 53 * build your device switch entry table - 54 */ - 55 - 56 static struct cdevsw pcacdevsw = { - 57 (d_open_t *) pcaopen, /* open */ - 58 (d_close_t *) pcaclose, /* close */ - 59 (d_rdwr_t *) enodev, /* read */ - 60 (d_rdwr_t *) pcawrite, /* write */ - 61 (d_ioctl_t *) pcaioctl, /* ioctl */ - 62 (d_stop_t *) enodev, /* stop?? */ - 63 (d_reset_t *) enodev, /* reset */ - 64 (d_ttycv_t *) enodev, /* ttys */ - 65 (d_select_t *) pcaselect, /* select */ - 66 (d_mmap_t *) enodev, /* mmap */ - 67 (d_strategy_t *) enodev /* strategy */ - 68 }; - 69 - 70 - - - -Lignes 71 - 131 - - -cette section est analogue à la déclaration de fichier de configuration -de votre périphérique. Les membres de la structure isa_device sont -remplis grace à ce qu'il connaît de votre périphérique, -port E/S, segment partagé de mémoire, etc... -Nous n'aurons probablement jamais un besoin de deux périphériques -pcaudio dans le noyau, mais cet exemple montre comment -périphériques multiples peuvent être supportés. - - - - 71 /* - 72 * this lkm arbitrarily supports two - 73 * instantiations of the pc-audio device. - 74 * - 75 * this is for illustration purposes - 76 * only, it doesn't make much sense - 77 * to have two of these beasts... - 78 */ - 79 - 80 - 81 /* - 82 * these have a direct correlation to the - 83 * config file entries... - 84 */ - 85 struct isa_device pcadev[NPCA] = { - 86 { - 87 11, /* device id */ - 88 &pcadriver, /* driver pointer */ - 89 IO_TIMER1, /* base io address */ - 90 -1, /* interrupt */ - 91 -1, /* dma channel */ - 92 (caddr_t)-1, /* physical io memory */ - 93 0, /* size of io memory */ - 94 pcaintr , /* interrupt interface */ - 95 0, /* unit number */ - 96 0, /* flags */ - 97 0, /* scsi id */ - 98 0, /* is alive */ - 99 0, /* flags for register_intr */ - 100 0, /* hot eject device support */ - 101 1 /* is device enabled */ - 102 }, - 103 #if NPCA >1 - 104 { - 105 - 106 /* - 107 * these are all zeros, because it doesn't make - 108 * much sense to be here - 109 * but it may make sense for your device - 110 */ - 111 - 112 0, /* device id */ - 113 &pcadriver, /* driver pointer */ - 114 0, /* base io address */ - 115 -1, /* interrupt */ - 116 -1, /* dma channel */ - 117 -1, /* physical io memory */ - 118 0, /* size of io memory */ - 119 NULL, /* interrupt interface */ - 120 1, /* unit number */ - 121 0, /* flags */ - 122 0, /* scsi id */ - 123 0, /* is alive */ - 124 0, /* flags for register_intr */ - 125 0, /* hot eject device support */ - 126 1 /* is device enabled */ - 127 }, - 128 #endif - 129 - 130 }; - 131 - - - -Lignes 132 - 139 - - - -Ceci appelle la macro MOD_DEV du préprocesseur C, qui -installe un module de gestion de périphérique de LKM, par -opposition à un système de fichiers LKM, ou un appel système de LKM. - - - - 132 /* - 133 * this macro maps to a function which - 134 * sets the LKM up for a driver - 135 * as opposed to a filesystem, system call, or misc - 136 * LKM. - 137 */ - 138 MOD_DEV("pcaudio_mod", LM_DT_CHAR, 24, &pcacdevsw); - 139 - - - -Lignes 140 - 168 - - - -c'est la fonction qui sera appelée lorsque le pilote sera -chargé. Cette fonction essaye de fonctionner comme -/sys/i386/isa/isa.c qui fait les appels de probe/attach pour un -pilote au moment du redémarrage. La plus grande astuce ici est qu'il -met en correspondance l'adresse physique du segment partagé de mémoire, qui est -indiqué dans la structure isa_device à une adresse virtuelle du noyau. -Normalement, l'adresse physique est mise dans le fichier de configuration -qui construit la structure isa_device dans -/usr/src/sys/compile/KERNEL/ioconf.c. La séquence probe/attach de -/usr/src/sys/isa/isa.c traduit l'adresse physique en une virtuelle de -sorte que dans les sous-programmes de probe/attach vous puissiez -faire des choses comme - - -(int *)id->id_maddr = something; - - et se réfère juste au segment partagé de mémoire -par l'intermédiaire de pointeurs. - - - - 140 /* - 141 * this function is called when the module is - 142 * loaded; it tries to mimic the behavior - 143 * of the standard probe/attach stuff from - 144 * isa.c - 145 */ - 146 int - 147 pcaload(){ - 148 int i; - 149 uprintf("PC Audio Driver Loaded\n"); - 150 for (i=0; i<NPCA; i++){ - 151 /* - 152 * this maps the shared memory address - 153 * from physical to virtual, to be - 154 * consistent with the way - 155 * /usr/src/sys/i386/isa.c handles it. - 156 */ - 157 pcadev[i].id_maddr -=0xa0000; - 158 pcadev[i].id_maddr += atdevbase; - 159 if ((*pcadriver.probe)(pcadev+i)) { - 160 (*(pcadriver.attach))(pcadev+i); - 161 } else { - 162 uprintf("PC Audio Probe Failed\n"); - 163 return(1); - 164 } - 165 } - 166 return 0; - 167 } - 168 - - -Lignes 169 - 179 - - -c'est la fonction appelée quand votre pilote n'est pas -chargé; il affiche juste un message à cet effet. - - - - 169 /* - 170 * this function is called - 171 * when the module is unloaded - 172 */ - 173 - 174 int - 175 pcaunload(){ - 176 uprintf("PC Audio Driver Unloaded\n"); - 177 return 0; - 178 } - 179 - - -Lignes 180 - 190 - - -c'est le point d'entrée qui est indiqué sur la ligne de commande -de modload. Par convention il est nommé <dev>_mod. C'est -ainsi qu'il est défini dans bsd.lkm.mk, le makefile qui -construit le LKM. Si vous nommez votre module suivant cette -convention, vous pouvez faire ``make load'' et ``make unload'' -de /usr/src/lkm/pcaudio. - -Note : Il y a eu tellement de révisions entre la version 2.0 et -2.1. Il peut ou ne peut ne pas être possible d'écrire -un module qui est portable pour chacune des trois versions. - - - - - 180 /* - 181 * this is the entry point specified - 182 * on the modload command line - 183 */ - 184 - 185 int - 186 pcaudio_mod(struct lkm_table *lkmtp, int cmd, int ver) - 187 { - 188 DISPATCH(lkmtp, cmd, ver, pcaload, pcaunload, nosys); - 189 } - 190 - 191 #endif /* NICP > 0 */ - - - - -Idiosyncrasies du type périphérique - - -Caractère - - - - -Bloc - - - - -Réseau - - - - -Line discipline - - - - - -Idiosyncrasies du type bus - - -ISA - - - - -EISA - - - - -PCI - - - - -SCSI - - - - -PCCARD - - - - - - - -Support du noyau - - -Structures de données - - -Structure <citerefentry><refentrytitle>struct kern_devconf</refentrytitle></citerefentry> - -Cette structure contient quelques informations sur l'état du -périphérique et de son pilote. Elle est définie dans -/usr/src/sys/sys/devconf.h comme ci-dessous : - - - -struct devconf { - char dc_name[MAXDEVNAME]; /* name */ - char dc_descr[MAXDEVDESCR]; /* description */ - int dc_unit; /* unit number */ - int dc_number; /* unique id */ - char dc_pname[MAXDEVNAME]; /* name of the parent device */ - int dc_punit; /* unit number of the parent */ - int dc_pnumber; /* unique id of the parent */ - struct machdep_devconf dc_md; /* machine-dependent stuff */ - enum dc_state dc_state; /* state of the device (see above) */ - enum dc_class dc_class; /* type of device (see above) */ - size_t dc_datalen; /* length of data */ - char dc_data[1]; /* variable-length data */ -}; - - - - -Structure <citerefentry><refentrytitle>struct proc</refentrytitle></citerefentry> - - Cette structure contient toutes les informations sur un processus. -Elle est dans définie /usr/src/sys/sys/proc.h: - - - -/* - * Description of a process. - * - * This structure contains the information needed to manage a thread of - * control, known in UN*X as a process; it has references to -substructures - * containing descriptions of things that the process uses, but may -share - * with related processes. The process structure and the substructures - * are always addressable except for those marked "(PROC ONLY)" below, - * which might be addressable only on a processor on which the process - * is running. - */ -struct proc { - struct proc *p_forw; /* Doubly-linked run/sleep queue. */ - struct proc *p_back; - struct proc *p_next; /* Linked list of active procs */ - struct proc **p_prev; /* and zombies. */ - - /* substructures: */ - struct pcred *p_cred; /* Process owner's identity. */ - struct filedesc *p_fd; /* Ptr to open files structure. */ - struct pstats *p_stats; /* Accounting/statistics (PROC ONLY). */ - struct plimit *p_limit; /* Process limits. */ - struct vmspace *p_vmspace; /* Address space. */ - struct sigacts *p_sigacts; /* Signal actions, state (PROC ONLY). */ - -#define p_ucred p_cred->pc_ucred -#define p_rlimit p_limit->pl_rlimit - - int p_flag; /* P_* flags. */ - char p_stat; /* S* process status. */ - char p_pad1[3]; - - pid_t p_pid; /* Process identifier. */ - struct proc *p_hash; /* Hashed based on p_pid for kill+exit+... */ - struct proc *p_pgrpnxt; /* Pointer to next process in process group. */ - struct proc *p_pptr; /* Pointer to process structure of parent. */ - struct proc *p_osptr; /* Pointer to older sibling processes. */ - -/* The following fields are all zeroed upon creation in fork. */ -#define p_startzero p_ysptr - struct proc *p_ysptr; /* Pointer to younger siblings. */ - struct proc *p_cptr; /* Pointer to youngest living child. */ - pid_t p_oppid; /* Save parent pid during ptrace. XXX */ - int p_dupfd; /* Sideways return value from fdopen. XXX */ - - /* scheduling */ - u_int p_estcpu; /* Time averaged value of p_cpticks. */ - int p_cpticks; /* Ticks of cpu time. */ - fixpt_t p_pctcpu; /* %cpu for this process during p_swtime */ - void *p_wchan; /* Sleep address. */ - char *p_wmesg; /* Reason for sleep. */ - u_int p_swtime; /* Time swapped in or out. */ - u_int p_slptime; /* Time since last blocked. */ - - struct itimerval p_realtimer; /* Alarm timer. */ - struct timeval p_rtime; /* Real time. */ - u_quad_t p_uticks; /* Statclock hits in user mode. */ - u_quad_t p_sticks; /* Statclock hits in system mode. */ - u_quad_t p_iticks; /* Statclock hits processing intr. */ - - int p_traceflag; /* Kernel trace points. */ - struct vnode *p_tracep; /* Trace to vnode. */ - - int p_siglist; /* Signals arrived but not delivered. */ - - struct vnode *p_textvp; /* Vnode of executable. */ - - char p_lock; /* Process lock (prevent swap) count. */ - char p_pad2[3]; /* alignment */ - -/* End area that is zeroed on creation. */ -#define p_endzero p_startcopy - -/* The following fields are all copied upon creation in fork. */ -#define p_startcopy p_sigmask - - sigset_t p_sigmask; /* Current signal mask. */ - sigset_t p_sigignore; /* Signals being ignored. */ - sigset_t p_sigcatch; /* Signals being caught by user. */ - - u_char p_priority; /* Process priority. */ - u_char p_usrpri; /* User-priority based on p_cpu and p_nice. */ - char p_nice; /* Process "nice" value. */ - char p_comm[MAXCOMLEN+1]; - - struct pgrp *p_pgrp; /* Pointer to process group. */ - - struct sysentvec *p_sysent; /* System call dispatch information. */ - - struct rtprio p_rtprio; /* Realtime priority. */ -/* End area that is copied on creation. */ -#define p_endcopy p_addr - struct user *p_addr; /* Kernel virtual addr of u-area (PROC ONLY). */ - struct mdproc p_md; /* Any machine-dependent fields. */ - - u_short p_xstat; /* Exit status for wait; also stop signal. */ - u_short p_acflag; /* Accounting flags. */ - struct rusage *p_ru; /* Exit information. XXX */ -}; - - - - -Structure <citerefentry><refentrytitle>struct buf</refentrytitle></citerefentry> -La structure struct buf est employée pour s'interfacer -avec le cache de la mémoire tampon. Elle est dans -définie /usr/src/sys/sys/buf.h : - - - -/* - * The buffer header describes an I/O operation in the kernel. - */ -struct buf { - LIST_ENTRY(buf) b_hash; /* Hash chain. */ - LIST_ENTRY(buf) b_vnbufs; /* Buffer's associated vnode. */ - TAILQ_ENTRY(buf) b_freelist; /* Free list position if not active. */ - struct buf *b_actf, **b_actb; /* Device driver queue when active. */ - struct proc *b_proc; /* Associated proc; NULL if kernel. */ - volatile long b_flags; /* B_* flags. */ - int b_qindex; /* buffer queue index */ - int b_error; /* Errno value. */ - long b_bufsize; /* Allocated buffer size. */ - long b_bcount; /* Valid bytes in buffer. */ - long b_resid; /* Remaining I/O. */ - dev_t b_dev; /* Device associated with buffer. */ - struct { - caddr_t b_addr; /* Memory, superblocks, indirect etc. */ - } b_un; - void *b_saveaddr; /* Original b_addr for physio. */ - daddr_t b_lblkno; /* Logical block number. */ - daddr_t b_blkno; /* Underlying physical block number. */ - /* Function to call upon completion. */ - void (*b_iodone) __P((struct buf *)); - /* For nested b_iodone's. */ - struct iodone_chain *b_iodone_chain; - struct vnode *b_vp; /* Device vnode. */ - int b_pfcent; /* Center page when swapping cluster. */ - int b_dirtyoff; /* Offset in buffer of dirty region. */ - int b_dirtyend; /* Offset of end of dirty region. */ - struct ucred *b_rcred; /* Read credentials reference. */ - struct ucred *b_wcred; /* Write credentials reference. */ - int b_validoff; /* Offset in buffer of valid region. */ - int b_validend; /* Offset of end of valid region. */ - daddr_t b_pblkno; /* physical block number */ - caddr_t b_savekva; /* saved kva for transfer while bouncing */ - void *b_driver1; /* for private use by the driver */ - void *b_driver2; /* for private use by the driver */ - void *b_spc; - struct vm_page *b_pages[(MAXPHYS + PAGE_SIZE - 1)/PAGE_SIZE]; - int b_npages; -}; - - - - - -Structure <citerefentry><refentrytitle>struct uio</refentrytitle></citerefentry> - -Cette structure est utilisée pour déplacer des données entre le noyau et -les espaces utilisateur par les appels système de read() et de write(). -Il est dans défini /usr/src/sys/sys/uio.h : - - - -struct uio { - struct iovec *uio_iov; - int uio_iovcnt; - off_t uio_offset; - int uio_resid; - enum uio_seg uio_segflg; - enum uio_rw uio_rw; - struct proc *uio_procp; -}; - - - - - - -Fonctions -plein - - - -Références. - - FreeBSD Kernel Sources http://www.freebsd.org - - - NetBSD Kernel Sources http://www.netbsd.org - - - Writing Device Drivers: Tutorial and Reference; -Tim Burke, Mark A. Parenti, Al, Wojtas; -Digital Press, ISBN 1-55558-141-2. - - - Writing A Unix Device Driver; -Janet I. Egan, Thomas J. Teixeira; -John Wiley & Sons, ISBN 0-471-62859-X. - - - Writing Device Drivers for SCO Unix; -Peter Kettle; - - - -