aboutsummaryrefslogtreecommitdiff
path: root/fr_FR.ISO8859-1/articles/ddwg/article.sgml
diff options
context:
space:
mode:
Diffstat (limited to 'fr_FR.ISO8859-1/articles/ddwg/article.sgml')
-rw-r--r--fr_FR.ISO8859-1/articles/ddwg/article.sgml1861
1 files changed, 0 insertions, 1861 deletions
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 f1959dc256..0000000000
--- a/fr_FR.ISO8859-1/articles/ddwg/article.sgml
+++ /dev/null
@@ -1,1861 +0,0 @@
-<!--
- The FreeBSD Documentation Project
- The FreeBSD French Documentation Project
-
- $Id: article.sgml,v 1.4 2001-07-13 15:48:38 nik Exp $
- Original revision: n.nn
--->
-
-<!DOCTYPE ARTICLE PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
-<!ENTITY % man PUBLIC "-//FreeBSD//ENTITIES DocBook Manual Page Entities//EN"> %man;
-<!ENTITY % urls PUBLIC "-//FreeBSD//ENTITIES Common Document URL Entities//FR"> %urls;
-<!ENTITY % abstract PUBLIC "-//FreeBSD//ENTITIES DocBook Abstract Entities//FR"> %abstract;
-<!ENTITY % artheader PUBLIC "-//FreeBSD//ENTITIES DocBook ArtHeader Entities//FR"> %artheader;
-<!ENTITY % translators PUBLIC "-//FreeBSD//ENTITIES DocBook Translator Entities//FR"> %translators;
-
-<!ENTITY % authors SYSTEM "../../../en_US.ISO8859-1/books/handbook/authors.ent"> %authors;
-<!ENTITY % mailing-lists PUBLIC "-//FreeBSD//ENTITIES DocBook Mailing List Entities//FR"> %mailing-lists;
- <!ENTITY rel.current CDATA "3.2">
-]>
-
-
-<article lang="fr">
- <articleinfo>
- <title>Le guide de l'auteur de pilotes de p&eacute;riph&eacute;riques pour FreeBSD</title>
- <authorgroup>
- <author>
- <firstname>Eric L.</firstname>
- <surname>Hernes</surname>
- </author>
- </authorgroup>
- &artheader.copyright;
- <abstract>
- <para><email>erich@rrnet.com</email></para>
- <para>29 Mai 1996</para>
- <para>Ce document d&eacute;crit comment ajouter un module de gestion de
-p&eacute;riph&eacute;rique &agrave; FreeBSD. Il <emphasis>n'est pas</emphasis> destin&eacute; pour &ecirc;tre un
-cours d'instruction sur des modules de gestion de p&eacute;riph&eacute;rique
-d'Unix en g&eacute;n&eacute;ral. Il est destin&eacute; pour les auteurs de module de
-gestion de p&eacute;riph&eacute;rique, au courant du mod&egrave;le de module de gestion
-de p&eacute;riph&eacute;rique d'Unix, pour travailler sur FreeBSD.
- </para>
- &abstract.license;
- &abstract.disclaimer;
- &trans.a.dntt;
- </abstract>
- </articleinfo>
-
-
-<sect1>
-<title>Sp&eacute;cificit&eacute; de FreeBSD2.x</title>
-
-<para>Dû aux changements de FreeBSD avec le temps, ce guide est
-seulement pr&eacute;cis en ce qui concerne FreeBSD 2.x. Un guide de
-rechange pour FreeBSD 3.x et au-del&agrave; est en train d'&ecirc;tre &eacute;crit.
-Contactez Jeroen Ruigrok <email>asmodai@wxs.nl</email> si
-vous voulez l'aider &agrave; ce sujet.
-</para>
-</sect1>
-
-
-<sect1>
-<title>G&eacute;n&eacute;ralit&eacute;</title>
-
-<para> <emphasis>Le noyau de FreeBSD est tr&egrave;s bien
-document&eacute;, malheureusement il est enti&egrave;rement &eacute;crit en `C'.</emphasis>
-</para>
-</sect1>
-
-<sect1>
-<title>Types de pilotes de module de p&eacute;riph&eacute;riques.</title>
-
-<sect2>
-<title>Caract&egrave;re</title>
-
-<sect3>
-<title>Structures de donn&eacute;es</title>
-
-<para>Structure <citerefentry><refentrytitle>cdevsw</refentrytitle></citerefentry></para>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>d_open()</function></title>
-<para>
-<function>d_open()</function> prend plusieurs arguments, la liste formelle ressemble &agrave;
-quelque chose comme :
-</para>
-
-<programlisting>
-int
-d_open(dev_t dev, int flag, int mode, struct proc *p)
-</programlisting>
-
-<para><function>d_open()</function> est appel&eacute; &agrave; <emphasis>chaque</emphasis> ouverture du p&eacute;riph&eacute;rique.</para>
-
-<para>L'argument <citerefentry><refentrytitle>dev</refentrytitle></citerefentry> contient le nombre majeur et mineur du
-p&eacute;riph&eacute;rique ouvert. Ils sont disponibles par les macros
-<citerefentry><refentrytitle><function>major()</function></refentrytitle></citerefentry> et <citerefentry><refentrytitle><function>minor()</function></refentrytitle></citerefentry>
-</para>
-
-<para>Les arguments <citerefentry><refentrytitle>flag</refentrytitle></citerefentry> et <citerefentry><refentrytitle>mode</refentrytitle></citerefentry> sont comme d&eacute;crits sur
-la page de manuel de
-<ulink url="http://www.freebsd.org/cgi/man.cgi?open(2)">open</ulink>.
-Il est recommand&eacute; que vous examiniez
-ces derniers pour vous assurer des droits d'acc&egrave;s dans &lt;sys/fcntl.h>
-et faire ce qui est exig&eacute;. Par exemple si <citerefentry><refentrytitle>flag </refentrytitle></citerefentry> est
-(O_NONBLOCK | O_EXLOCK) l'ouverture &eacute;chouerait si il bloquait ou
-si l'acc&egrave;s exclusif ne pouvait pas &ecirc;tre accord&eacute;.
-</para>
-
-<para>
-L'argument <citerefentry><refentrytitle>p</refentrytitle></citerefentry> contient toutes les informations &agrave; propos du
-processus actuel.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_close()</function></title>
-<para> <function>d_close()</function> prend la m&ecirc;me liste d'argument que <function>d_open()</function>:
-</para>
-
-<programlisting>
-int
-d_close(dev_t dev , int flag , int mode , struct proc *p)
-</programlisting>
-
-<para><function>d_close()</function> est seulement appel&eacute; &agrave; la derni&egrave;re fermeture de votre
-p&eacute;riph&eacute;rique (par p&eacute;riph&eacute;rique mineur). Par exemple dans le fragment
-suivant de code, <function>d_open()</function> est appel&eacute; 3 fois, mais <function>d_close()</function>
-seulement une fois.
-</para>
-
-<programlisting>
- ...
- fd1=open("/dev/mydev", O_RDONLY);
- fd2=open("/dev/mydev", O_RDONLY);
- fd3=open("/dev/mydev", O_RDONLY);
- ...
- &lt;useful stuff with fd1, fd2, fd3 here>
- ...
- close(fd1);
- close(fd2);
- close(fd3);
- ...
-</programlisting>
-
-<para>Les arguments sont semblables &agrave; ceux d&eacute;crits ci-dessus pour
-<function>d_open()</function>.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_read()</function> et <function>d_write()</function></title>
-
-<para><function>d_read()</function> et d_write prennent les listes suivantes d'argument:
-</para>
-
-<programlisting>
-int
-d_read(dev_t dev, struct uio *uio, int flat)
-int
-d_write(dev_t dev, struct uio *uio, int flat)
-</programlisting>
-
-<para>
-Les points d'entr&eacute;e de <function>d_read()</function> et de <function>d_write()</function> sont appel&eacute;s quand
-<ulink url="http://www.freebsd.org/cgi/man.cgi?read(2)">read</ulink> et
-<ulink url="http://www.freebsd.org/cgi/man.cgi?write(2)">write</ulink>
-sont appel&eacute;s sur votre p&eacute;riph&eacute;rique depuis l'espace utilisateur. Le transfert
-des donn&eacute;es peut &ecirc;tre manipul&eacute; par la routine du noyau <function>uiomove()</function>.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_ioctl()</function></title>
-
-<para> Sa liste d'argument est comme suit:
-</para>
-<programlisting>
-int
-d_ioctl(dev_t dev, int cmd, caddr_t arg, int flag, struct proc *p)
-</programlisting>
-
-<para>
-<function>d_ioctl()</function> est un fourre-tout pour les ex&eacute;cutions qui ne semblent
-pas raisonnable dans un paradigme lecture/&eacute;criture. Le plus
-c&eacute;l&egrave;bre de tout les ioctl est probablement celui sur des p&eacute;riph&eacute;riques
-tty, par le
-<ulink url="http://www.freebsd.org/cgi/man.cgi?stty(1)">stty</ulink>.
-
-Le point d'entr&eacute;e d'ioctl est appel&eacute; depuis l'<function>ioctl()</function> de
-<filename>sys/kern/sys_generic.c</filename></para>
-
-<para>
-Il y a quatre types diff&eacute;rents d'ioctl qui peuvent &ecirc;tre impl&eacute;ment&eacute;s.
-
-&lt;sys/ioccom.h> contient des macros pratiques de
-pour d&eacute;finir ces ioctls.
-</para>
-
-<itemizedlist>
-<listitem>
-<para><citerefentry><refentrytitle>_IO(g, n) </refentrytitle></citerefentry> pour les op&eacute;rations de type contr&ocirc;le.
-</para>
-</listitem>
-
-<listitem>
-<para>
-<citerefentry><refentrytitle>_IOR(g, n, t) </refentrytitle></citerefentry> pour des op&eacute;rations lisant des donn&eacute;es d'un
-p&eacute;riph&eacute;rique.
-</para>
-</listitem>
-
-<listitem>
-<para>
-<citerefentry><refentrytitle>_IOW(g, n, t) </refentrytitle></citerefentry> pour les op&eacute;rations &eacute;crivant des donn&eacute;es
-sur un p&eacute;riph&eacute;rique.
-</para>
-</listitem>
-
-<listitem>
-<para>
-<citerefentry><refentrytitle>_IOWR(g,n,t)</refentrytitle></citerefentry> pour les op&eacute;rations &eacute;crivant sur un p&eacute;riph&eacute;rique
-puis lisent les donn&eacute;es.
-</para>
-</listitem>
-</itemizedlist>
-
-
-<para>
-Ici <citerefentry><refentrytitle>g </refentrytitle></citerefentry> se rapporte &agrave; un <emphasis>groupe </emphasis>/. C'est une valeur
-de 8 bits, en g&eacute;n&eacute;ral indicative du p&eacute;riph&eacute;rique ; par exemple, 't'
-est utilis&eacute; dans des ioctls de tty. <citerefentry><refentrytitle>n</refentrytitle></citerefentry> se
-rapporte au nombre de l'ioctl dans le groupe. Sur SCO, ce seul nombre
-d&eacute;note l'ioctl. <citerefentry><refentrytitle>t</refentrytitle></citerefentry> est le type de donn&eacute;es qui sera
-pass&eacute; au pilote de p&eacute;riph&eacute;rique; ceci est alors remis &agrave; un op&eacute;rateur
-<function>sizeof()</function> du noyau. L'appel syst&egrave;me <function>ioctl()</function> fera soit un <function>copyin()</function>
-soit un <function>copyout()</function> ou les deux &agrave; votre pilote, puis vous
-renverra un pointeur &agrave; la structure de donn&eacute;es dans l'argument
-<citerefentry><refentrytitle>arg</refentrytitle></citerefentry> de l'appel d'd_ioctl. Actuellement la taille de
-donn&eacute;es est limit&eacute;e &agrave; une page (4k sur l'i386).
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_stop()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>d_reset()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>d_devtotty()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>d_poll()</function> (3.0 et plus) ou <function>d_select()</function> (2.2)</title>
-
-<para>la liste d'argument de <function>d_poll()</function> est comme suit :
-</para>
-
-<programlisting>
-void
-d_poll(dev_t dev, int events, struct proc *p)
-</programlisting>
-
-<para> <function>d_poll()</function> est employ&eacute; pour d&eacute;couvrir si un p&eacute;riph&eacute;rique
-est pr&ecirc;t pour les E/S. Par exemple, attendre que des donn&eacute;es du r&eacute;seau
-soient dispnibles, ou que l'utilisateur presse une touche.
-Cela correspond &agrave; un appel de <function>poll()</function> dans l'espace utilisateur.
-</para>
-
-<para>L'appel &agrave; <function>d_poll()</function> devrait v&eacute;rifier les &eacute;v&eacute;nements
-indiqu&eacute;s dans le masque d'&eacute;v&egrave;nement. Si aucun des &eacute;v&eacute;nements demand&eacute;s n'est
-en activit&eacute;, mais qu'elles pourraient devenir actif plus tard, il
-devrait enregistrer ceci pour les actions futures du noyau.
-<function>d_poll()</function> fait ceci en appelant <function>selrecord()</function> avec une structure
-selinfo pour ce p&eacute;riph&eacute;rique. La somme de toutes ces activit&eacute;s
-ressemblent &agrave; quelque chose comme ceci:
-</para>
-
-<programlisting>
-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 = &amp;my_softc[dev];
-
- /* We can only check for IN and OUT */
- if ((events &amp; (POLLIN|POLLOUT)) == 0)
- return(POLLNVAL);
-
- s = <function>splhigh()</function>;
- /* Writes are if the transmit queue can take them */
- if ((events &amp; POLLOUT) &amp;&amp;
- !IF_QFULL(sc->tx_queue))
- revents |= POLLOUT;
- /* ... while reads are OK if we have any data */
- if ((events &amp; POLLIN) &amp;&amp;
- !IF_QEMPTY(sc->rx_queue))
- revents |= POLLIN;
- if (revents == 0)
- selrecord(p, &amp;sc->selp);
- splx(s);
- return revents;
-}
-</programlisting>
-
-<para> <function>d_select()</function> est utilis&eacute; dans la version 2.2 et
-pr&eacute;c&eacute;dentes de FreeBSD. Au lieu de 'events', il prend un simple
-entier 'rw', qui peut &ecirc;tre FREAD pour la lecture (comme dans
-POLLIN ci-dessus), FWRITE pour l'&eacute;criture (comme dans POLLOUT ci-dessus),
-et 0 pour 'exception' - lorsque quelque chose d'exceptionnel se produit,
-comme une carte &eacute;tant ins&eacute;r&eacute;e ou retir&eacute;e pour le pilote de
-pccard.
-</para>
-<para>Pour 'select', le fragment correspondant &agrave; la description
-ci-dessus ressembleraient &agrave; ceci:
-</para>
-<programlisting>
-static int
-mydevselect(dev_t dev, int rw, struct proc *p)
-{
- int ret = 0;
- int s;
- struct my_softc *sc = &amp;my_softc[dev];
-
- s = <function>splhigh()</function>;
- 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, &amp;sc->selp);
- splx(s);
- return(revents);
-}
-</programlisting>
-</sect4>
-
-<sect4>
-<title><function>d_mmap()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>d_strategy()</function></title>
-
-<para>
-La liste d'argument de <function>d_strategy()</function> est comme suit :
-</para>
-
-<programlisting>
-void
-d_strategy(struct buf *bp)
-</programlisting>
-
-<para><function>d_strategy()</function> est utilis&eacute; pour les p&eacute;riph&eacute;riques utilisant
-des E/S de type disperser-regrouper (<foreignphrase>scatter-gather</foreignphrase>).
-C'est ce qu'il y a de plus courant dans un p&eacute;riph&eacute;rique de bloc.
-C'est sensiblement diff&eacute;rent du mod&egrave;le de syst&egrave;me V, o&ugrave; seulement
-le pilote de bloc fait une E/S de type disperser-regrouper.
-Sous BSD, les p&eacute;riph&eacute;riques de caract&egrave;re sont parfois somm&eacute; d'ex&eacute;cuter
-une E/S de type disperser-regrouper par l'interm&eacute;diaire des appels
-syst&egrave;mes <function>readv()</function> et <function>writev()</function>.
-</para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>Bloc</title>
-
-<sect3>
-<title>Structures de donn&eacute;es</title>
-<para> Structure <citerefentry><refentrytitle>struct bdevsw</refentrytitle></citerefentry>
-</para>
-
-<para> Structure <citerefentry><refentrytitle>struct buf</refentrytitle></citerefentry>
-</para>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>d_open()</function></title>
-<para> D&eacute;crit dans la section p&eacute;riph&eacute;rique de caract&egrave;re.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_close()</function></title>
-<para>D&eacute;crit dans la section p&eacute;riph&eacute;rique de caract&egrave;re.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_strategy()</function></title>
-<para>D&eacute;crit dans la section p&eacute;riph&eacute;rique de caract&egrave;re.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_ioctl()</function></title>
-<para>D&eacute;crit dans la section p&eacute;riph&eacute;rique de caract&egrave;re.
-</para>
-</sect4>
-
-<sect4>
-<title><function>d_dump()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>d_psize()</function></title>
-<para></para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>R&eacute;seau</title>
-<para>Structure <citerefentry><refentrytitle>struct ifnet</refentrytitle></citerefentry>
-</para>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>if_init()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>if_output()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>if_start()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>if_done()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>if_ioctl()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>if_watchdog()</function></title>
-<para></para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>Protocole de communication</title>
-
-<sect3>
-<title>Structures de donn&eacute;es</title>
-<para>Structure <citerefentry><refentrytitle>struct linesw</refentrytitle></citerefentry>
-</para>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>l_open()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_close()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_read()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_write()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_ioctl()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_rint()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_start()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>l_modem()</function></title>
-<para></para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-</sect1>
-
-<sect1>
-<title>Bus Support&eacute;s</title>
-
-<sect2>
-<title>ISA -- Architecture Standard d'Industrie (<foreignphrase>Industry Standard
-Architecture</foreignphrase></title>
-
-<sect3>
-<title>Structures de donn&eacute;es</title>
-
-<sect4>
-<title>Structure <citerefentry><refentrytitle>struct isa_device</refentrytitle></citerefentry></title>
-
-<para>Cette structure est obligatoire, mais g&eacute;n&eacute;ralement elle est cr&eacute;&eacute;e par
-<ulink url="http://www.freebsd.org/cgi/man.cgi?config(8)">config</ulink> &agrave; partir du fichier de configuration de noyau.
-Elle est requise pour chaque p&eacute;riph&eacute;rique, c'est &agrave; dire que si vous avez
-un pilote de p&eacute;riph&eacute;rique contr&ocirc;lant deux "serial boards", vous
-aurez deux structures isa_device. Si vous construisez un p&eacute;riph&eacute;rique
-comme un LKM, vous devrez cr&eacute;er votre propre structure isa_device afin
-de refl&eacute;ter votre configuration (lignes 85 - 131 de pcaudio_lkm.c).
-Il y a un &eacute;quivalence directe ebtre le fichier de configuration et la
-structureisa_device. La d&eacute;finition de
-<filename>/usr/src/sys/i386/isa/isa_device.h</filename>
-est :
-</para>
-
-<programlisting>
-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 <function>register_intr()</function> */
- 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 <function>userconfig()</function> */
-};
-</programlisting>
-</sect4>
-
-<sect4>
-<title>Structure <citerefentry><refentrytitle>struct isa_driver</refentrytitle></citerefentry></title>
-
-<para>Cette structure est d&eacute;finie dans
-<filename>/usr/src/sys/i386/isa/isa_device.h</filename>,
-est est requise pour chaque pilote de p&eacute;riph&eacute;rique. La d&eacute;finition
-est :
-</para>
-
-<programlisting>
-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 */
-};
-</programlisting>
-
-<para>
-C'est la structure employ&eacute;e par le code sondage/attachement
-(<foreignphrase>probe/attach</foreignphrase>) pour
-d&eacute;tecter et initialiser votre p&eacute;riph&eacute;rique. Le membre <citerefentry><refentrytitle>probe</refentrytitle></citerefentry>
-est un pointeur &agrave; votre fonction permettant de sonder les p&eacute;riph&eacute;riques.
-Le membre <citerefentry><refentrytitle>attach</refentrytitle></citerefentry> est un pointeur vers votre fonction d'attache.
-Le membre <citerefentry><refentrytitle>name</refentrytitle></citerefentry> est un pointeur de caract&egrave;re sur le nom de deux
-ou trois lettres de votre pilote.
-C'est le nom enregistr&eacute; pendant le processus de
-sondage/attachement (et probablement aussi dans
-<ulink url="http://www.freebsd.org/cgi/man.cgi?lsdev(8)">lsdev</ulink>).
-Le membre <citerefentry><refentrytitle>sensitive_hw </refentrytitle></citerefentry> est un
-indicateur qui aide le code de sondage &agrave; d&eacute;terminer l'ordre du sondage.
-</para>
-
-<para>
-Un instantiation typique est:
-</para>
-
-<programlisting>
-struct isa_driver mcddriver = { mcd_probe, mcd_attach, "mcd" };
-</programlisting>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>probe()</function></title>
-<para><function>probe()</function> prend un pointeur sur une structure isa_device
-comme argument et renvoie un int. La valeur de retour est ``z&eacute;ro'' ou
-``non-z&eacute;ro '' quant &agrave; l'absence ou &agrave; la pr&eacute;sence de votre p&eacute;riph&eacute;rique.
-Ce point d'entr&eacute;e peut &ecirc;tre d&eacute;clar&eacute; comme
-<citerefentry><refentrytitle>static</refentrytitle></citerefentry> parce qu'il
-est accessible par l'interm&eacute;diaire du membre
-<citerefentry><refentrytitle>probe</refentrytitle></citerefentry> de la structre
-isa_driver. Cette fonction est destin&eacute;e &agrave;
-d&eacute;tecter la pr&eacute;sence de votre p&eacute;riph&eacute;rique seulement et ne devrait
-faire aucune configuration du p&eacute;riph&eacute;rique elle-m&ecirc;me.
-</para>
-</sect4>
-
-<sect4>
-<title><function>attach()</function></title>
-<para>
-<function>attach()</function> prend &eacute;galement un pointeur sur une structure
-isa_device comme argument et
-renvoie un int. La valeur de retour est &eacute;galement ``z&eacute;ro'' ou
-``non-z&eacute;ro'' indiquant si l'attache a r&eacute;ussie. Cette fonction
-est destin&eacute;e pour faire n'importe quelle initialisation sp&eacute;ciale du
-p&eacute;riph&eacute;rique aussi bien que pour confirmer que le p&eacute;riph&eacute;rique est utilisable.
-Il devrait aussi &ecirc;tre d&eacute;clar&eacute; <citerefentry><refentrytitle>static</refentrytitle></citerefentry> parce qu'il est accesible
-par le membre <citerefentry><refentrytitle>attach</refentrytitle></citerefentry> de la structure <citerefentry><refentrytitle>isa_driver </refentrytitle></citerefentry>.
-</para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>EISA -- Architecture Étendue de Standard industriel (<foreignphrase>Extended Industry Standard Architecture</foreignphrase>)</title>
-<para></para>
-
-<sect3>
-<title>Structures de donn&eacute;es</title>
-
-<para>Structure <citerefentry><refentrytitle>struct eisa_dev </refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct isa_driver</refentrytitle></citerefentry> </para>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>probe()</function></title>
-<para>D&eacute;crit dans la section de p&eacute;riph&eacute;rique ISA.</para>
-</sect4>
-
-<sect4>
-<title><function>attach()</function></title>
-<para>D&eacute;crit dans la section de p&eacute;riph&eacute;rique ISA.</para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>PCI -- Bus d'interconnexion P&eacute;riph&eacute;rique (<foreignphrase>Peripheral Computer
-Interconnect</foreignphrase>)</title>
-
-<sect3>
-<title>Structures de donn&eacute;es</title>
-
-<para> Structure <citerefentry><refentrytitle>struct pci_device</refentrytitle></citerefentry>
-</para>
-
-<itemizedlist>
-<listitem>
-<para>nom : Le nom abr&eacute;g&eacute; du p&eacute;riph&eacute;rique.
-</para>
-</listitem>
-
-<listitem>
-<para> sonde: Contr&ocirc;le si le pilote peut supporter un p&eacute;riph&eacute;rique avec
-ce type. L'&eacute;tiquette peut &ecirc;tre employ&eacute;e pour obtenir plus
-d'information avec <function>pci_read_conf()</function>. Voir ci-dessous. Elle renvoie
-une cha&icirc;ne de caract&egrave;res avec le nom du p&eacute;riph&eacute;rique, ou un pointeur
-NULL si le pilote ne peut pas supporter ce p&eacute;riph&eacute;rique.
-</para>
-</listitem>
-
-<listitem>
-<para> attache: Assigne une structure de contr&ocirc;le et la pr&eacute;pare. Cette
-fonction peut utiliser les fonctions de mapping PCI. Voir
-ci-dessous. (identification de configuration) ou type.
-</para>
-</listitem>
-
-<listitem>
-<para> compte: Un pointeur sur un compteur d'unit&eacute;. Il est
-employ&eacute; par le configurateur de PCI pour assigner des num&eacute;ros.
-</para>
-</listitem>
-</itemizedlist>
-
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>probe()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>attach()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>shutdown()</function></title>
-<para></para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>SCSI -- <foreignphrase>Small Computer Systems Interface</foreignphrase></title>
-
-<sect3>
-<title>Structure de donn&eacute;es</title>
-
-<para>Structure <citerefentry><refentrytitle>struct scsi_adapter</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct scsi_device</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct scsi_ctlr_config</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct scsi_device_config</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct scsi_link</refentrytitle></citerefentry> </para>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>attach()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>init()</function></title>
-<para></para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-<para></para>
-</sect3>
-</sect2>
-
-
-<sect2>
-<title>PCCARD (PCMCIA)</title>
-
-<sect3>
-<title>Structure de donn&eacute;es</title>
-
-<para>Structure <citerefentry><refentrytitle>struct slot_cont</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct pccard_drv</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct pccard_dev</refentrytitle></citerefentry> </para>
-<para>Structure <citerefentry><refentrytitle>struct slot</refentrytitle></citerefentry> </para>
-</sect3>
-
-<sect3>
-<title>Points d'entr&eacute;e</title>
-
-<sect4>
-<title><function>handler()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>unload()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>suspend()</function></title>
-<para></para>
-</sect4>
-
-<sect4>
-<title><function>init()</function></title>
-<para></para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Fichiers d'en-t&ecirc;te</title>
-
-<para>&lt;pccard/slot.h>
-</para>
-</sect3>
-</sect2>
-</sect1>
-
-
-<sect1>
-<title>Incorporation dans le noyau</title>
-
-<para>Dans FreeBSD, le support des bus d'ISA et EISA est sp&eacute;cifique &agrave;
-i386. Tandis que FreeBSD lui-m&ecirc;me est actuellement
-disponible sur la plateforme i386, un certain effort a &eacute;t&eacute; fait pour
-faire du code portable pour PCI, PCCARD, et SCSI. Le code
-sp&eacute;cifique &agrave; ISA et EISA r&eacute;side dans
-<filename>/usr/src/sys/i386/isa</filename> et
-<filename>/usr/src/sys/i386/eisa</filename> respectivement. Le code ind&eacute;pendant de la
-machine de PCI, de PCCARD, et de SCSI r&eacute;side dans
-<filename>/usr/src/sys/{pci,pccard,scsi</filename>}. Le code sp&eacute;cifique i386 quand &agrave; lui
-r&eacute;side dans <filename>/usr/src/sys/i386/{pci, pccard, scsi}</filename>.
-</para>
-
-
-<para> Dans FreeBSD, un module de gestion de p&eacute;riph&eacute;rique peut
-&ecirc;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&eacute;riph&eacute;riques. les syst&egrave;mes BSD utilise quelque
-chose comme sys/i386/OBJ. Puisque la plupart des pilotes sont
-distribu&eacute;s dans les sources, la discussion suivante se rapporte &agrave; un
-source pilote de p&eacute;riph&eacute;rique.
-Des binaires de pilotes de p&eacute;riph&eacute;riques sont
-parfois fournis par les constructeurs de mat&eacute;riel qui souhaitent
-maintenir les sources de mani&egrave;re propri&eacute;taire.
-</para>
-
-<para> Un pilote typique a son code source sous forme de fichier C,
-comme dev.c. Le pilote peut &eacute;galement inclure des
-fichiers; devreg.h contient typiquement des d&eacute;clarations publiques
-de registre de p&eacute;riph&eacute;rique, des macros, et d'autres
-d&eacute;clarations sp&eacute;cifique au pilote de p&eacute;riph&eacute;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&eacute;
-sur la carte. Pour le pilote de dgb le microcode est compil&eacute;
-et report&eacute; dans un fichier d'en-t&ecirc;te par
-<ulink url="http://www.freebsd.org/cgi/man.cgi?file2c(1)">file2c</ulink>.
-</para>
-
-<para> Si le pilote de p&eacute;riph&eacute;rique a des structures de donn&eacute;es et des
-ioctl qui sont sp&eacute;cifiques au pilote de p&eacute;riph&eacute;rique ou
-p&eacute;riph&eacute;rique, et
-doivent &ecirc;tre accessibles de l'espace-utilisateur, elles devraient
-&ecirc;tre mises dans un fichier d'en-t&ecirc;te s&eacute;par&eacute; qui r&eacute;sidera dans
-<filename>/usr/include/machine/</filename> (certaines de ces derniers r&eacute;sident dans
-<filename>/usr/include/sys/</filename>). Ceux-ci est typiquement nomm&eacute; quelque chose comme
-ioctl_dev.h ou devio.h.
-</para>
-
-<para> Si un pilote &eacute;crit depuis l'espace
-d'utilisateur est identique &agrave; un p&eacute;riph&eacute;rique qui existe d&eacute;j&agrave;, il faut
-prendre garde &agrave; utiliser les m&ecirc;mes
-interfaces ioctl et structures de donn&eacute;es. Par exemple, de l'espace
-utilisateur, un lecteur de SCSI CDROM devrait &ecirc;tre identique &agrave; un
-lecteur de cdrom IDE; ou une ligne s&eacute;rie sur une carte
-intelligente multiport (Digiboard, Cyclades...) devrait &ecirc;tre identique
-&agrave; un p&eacute;riph&eacute;rique sio. Ces p&eacute;riph&eacute;riques ont une interface d&eacute;finie
-relativement bonne et devraient &ecirc;tre utilis&eacute;es.
-</para>
-
-<para> Il y a deux m&eacute;thodes pour lier un pilote dans le
-noyau, statiquement et le mod&egrave;le LKM. La premi&egrave;re m&eacute;thode
-est assez standard &agrave; travers la famille *BSD. L'autre
-m&eacute;thode a &eacute;t&eacute; initialement d&eacute;velopp&eacute;e par Sun (je crois), et a
-&eacute;t&eacute; mis en application dans BSD en utilisant le mod&egrave;le de Sun.
-Je ne crois pas que l'impl&eacute;mentation actuelle utilise encore le moindre
-code de Sun.
-</para>
-
-<sect2>
-<title>Mod&egrave;le Standard</title>
-
-<para> Les &eacute;tapes exig&eacute;es pour ajouter votre pilote au
-noyau standard de FreeBSD sont
-</para>
-
-<itemizedlist>
-<listitem>
-<para>Ajout &agrave; la liste des pilotes de p&eacute;riph&eacute;rique
-</para>
-</listitem>
-
-<listitem>
-<para>Ajout d'une entr&eacute;e au &lsqb;bc&rsqb;devsw
-</para>
-</listitem>
-
-<listitem>
-<para>Ajout d'une entr&eacute;e du pilote de p&eacute;riph&eacute;rique au fichier de
-configuration du noyau
-</para>
-</listitem>
-
-<listitem>
-<para><ulink
-url="http://www.freebsd.org/cgi/man.cgi?config(8)">config</ulink>,
-compilation et installation du noyau
-</para>
-</listitem>
-
-<listitem>
-<para>cr&eacute;er les fichiers sp&eacute;ciaux requis
-</para>
-</listitem>
-
-<listitem>
-<para>red&eacute;marrage
-</para>
-</listitem>
-</itemizedlist>
-
-<sect3>
-<title>Ajout &agrave; la liste des pilotes de p&eacute;riph&eacute;rique</title>
-
-<para>Le mod&egrave;le standard pour ajouter un module de gestion de p&eacute;riph&eacute;rique
-au noyau de Berkeley est d'ajouter votre pilote &agrave; la liste des
-p&eacute;riph&eacute;riques connus. Cette liste d&eacute;pend de l'architecture du CPU.
-Si le p&eacute;riph&eacute;rique n'est pas sp&eacute;cifique i386
-(PCCARD, PCI, SCSI), le fichier est dans
-<filename>/usr/src/sys/conf/files</filename>.
-Si le p&eacute;riph&eacute;rique est sp&eacute;cifique i386, utilisez
-<filename>/usr/src/sys/i386/conf/files.i386</filename>. Une ligne typique ressemblerait
-&agrave; :
-</para>
-
-<programlisting>
-i386/isa/joy.c optional joy device-driver
-</programlisting>
-
-<para>Le premier champ relatif est le chemin du module de pilote
-par rapport &agrave; <filename>/usr/src/sys</filename>.
-Pour le cas d'un pilote binaire, le chemin d'acc&egrave;s serait quelque
-chose comme <filename>i386/OBJ/joy.o</filename>.
-</para>
-
-<para>Le deuxi&egrave;me champ indique &agrave;
-<ulink url="http://www.freebsd.org/cgi/man.cgi?config(8)">config(8)</ulink>
-que c'est un pilote facultatif. Quelques
-p&eacute;riph&eacute;riques sont obligatoires pour que le noyau puisse &ecirc;tre construit.
-</para>
-
-<para>
-Le troisi&egrave;me champ est le nom du p&eacute;riph&eacute;rique.
-</para>
-
-<para>Le quatri&egrave;me champ indique &agrave; config que c'est un
-pilote de p&eacute;riph&eacute;rique (par opposition &agrave; juste facultatif). Ceci
-dit &agrave; config de cr&eacute;er des entr&eacute;es pour le p&eacute;riph&eacute;rique dans dans
-des structures de <filename>/usr/src/sys/compile/KERNEL/ioconf.c</filename>.
-</para>
-
-<para>Il est &eacute;galement possible de cr&eacute;er un fichier
-<filename>/usr/src/sys/i386/conf/files.KERNEL</filename> dont le contenu ignorera le
-fichier par d&eacute;faut files.i386, mais seulement pour le noyau ``KERNEL''.
-</para>
-</sect3>
-
-<sect3>
-<title>Faire de la place dans conf.c</title>
-
-<para>Maintenant vous devez &eacute;diter <filename>/usr/src/sys/i386/i386/conf.c</filename>
-pour faire une entr&eacute;e pour votre pilote. Quelque part au d&eacute;but,
-vous devez d&eacute;clarer vos points d'entr&eacute;e. L'entr&eacute;e pour
-le pilote du joystick est: </para>
-
-<programlisting>
-#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
-</programlisting>
-
-<para>
-Cela d&eacute;finit vos points d'entr&eacute;e, ou points d'entr&eacute;e nuls qui
-renverront ENXIO quand appel&eacute; (clause #else).
-</para>
-
-<para>
-Le fichier d'en-t&ecirc;te ``joy.h'' est automatiquement produit par
-<ulink url="http://www.freebsd.org/cgi/man.cgi?config(8)">config</ulink>
-quand l'arborescence de construction du noyau est
-cr&eacute;&eacute;. Cela se r&eacute;duit habituellement &agrave; une seule ligne comme :
-</para>
-
-<programlisting>
-#define NJOY 1
-</programlisting>
-
-<para>
-ou
-</para>
-<programlisting>
-#define NJOY 0
-</programlisting>
-
-<para> ce qui d&eacute;finit le nombre de vos p&eacute;riph&eacute;riques dans votre noyau.
-</para>
-
-<para>
-Vous devez additionnellement ajouter un slot au cdevsw&lsqb;&rsqb, ou
-au bdevsw&lsqb;&rsqb, selon que ce soit un p&eacute;riph&eacute;rique caract&egrave;re,
-p&eacute;riph&eacute;rique bloc, ou les deux si c'est un p&eacute;riph&eacute;rique bloc
-avec une interface brute. L'entr&eacute;e pour le pilote du joystick
-est:
-</para>
-
-<programlisting>
-/* 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},
- ...
-}
-</programlisting>
-
-<para>
- L'ordre est ce qui d&eacute;termine le nombre majeur de votre
-p&eacute;riph&eacute;rique. C'est pourquoi il y aura toujours une entr&eacute;e
-pour votre pilote, que ce soit des points d'entr&eacute;e nuls,
-ou des points d'entr&eacute;e actuels. Il est probablement int&eacute;ressant de
-noter que c'est
-sensiblement diff&eacute;rent de SCO et d'autres d&eacute;riv&eacute;s du syst&egrave;me V, o&ugrave;
-n'importe quel p&eacute;riph&eacute;rique (dans la th&eacute;orie) peut avoir n'importe
-quel nombre majeur. C'est en grande partie un avantage sur FreeBSD,
-sur la mani&egrave;re dont les fichiers sp&eacute;ciaux de p&eacute;riph&eacute;rique sont cr&eacute;&eacute;s.
-Nous reviendrons en d&eacute;tail sur ceci plus tard.
-</para>
-</sect3>
-
-<sect3>
-<title>Ajout de votre p&eacute;riph&eacute;rique dans le fichier de configuration.</title>
-
-<para> Ceci ajoute simplement une ligne d&eacute;crivant votre p&eacute;riph&eacute;rique. La
-ligne de description du joystick est :
-<programlisting>
-device joy0 at isa? port "IO_GAME"
-</programlisting>
-Ceci indique que nous avons un
-p&eacute;riph&eacute;rique appel&eacute; ``joy0'' sur le bus ISA en utilisant
-le port E/S ``IO_GAME'' (IO_GAME est une macro d&eacute;finie dans
-<filename>/usr/src/sys/i386/isa/isa.h</filename>).
-</para>
-
-<para>
-Une entr&eacute;e l&eacute;g&egrave;rement plus compliqu&eacute;e est pour le pilote ``ix'' :
-
-<programlisting>
-device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768
-vector ixintr
-</programlisting>
-
-Ceci indique que nous avons un p&eacute;riph&eacute;rique appel&eacute;
-`ix0 ' sur le bus ISA. Il utilise le port E/S 0x300. Son
-interruption sera masqu&eacute; par d'autres p&eacute;riph&eacute;riques dans la classe
-r&eacute;seau. Il utilise l'interruption 10. Il utilise 32k de m&eacute;moire
-partag&eacute;e &agrave; l'adresse physique 0xd0000. Il le d&eacute;finit &eacute;galement
-son pilote d'interruption comme &eacute;tant ``<function>ixintr()</function>''
-</para>
-</sect3>
-
-<sect3>
-<title><ulink url="http://www.freebsd.org/cgi/man.cgi?config(8)">config</ulink>
-du noyau.</title>
-
-<para> Maintenant avec notre fichier de configuration en main,
-nous pouvons cr&eacute;er un r&eacute;pertoire de compilation du noyau. Cela peut &ecirc;tre
-fait en tapant :
-<programlisting>
-# config KERNEL
-</programlisting>
-
-o&ugrave; KERNEL est le nom de votre fichier de configuration.
-La configuration cr&eacute;e un arbre de compilation
-pour votre noyau dans <filename>/usr/src/sys/compile/KERNEL</filename>. Elle cr&eacute;e le fichier
-makefile, quelques fichiers C, et quelques fichiers H avec des
-macros d&eacute;finissant le nombre de chaque p&eacute;riph&eacute;rique &agrave; inclure dans votre
-votre noyau.
-</para>
-
-<para>
-Maintenant vous pouvez aller dans le r&eacute;pertoire de compilation et
-construire votre noyau. À chaque fois que vous lancerez config, votre
-arbre de construction pr&eacute;c&eacute;dent sera retir&eacute;, &agrave; moins que vous ne lancez
-config avec un -n. Si vous avez configur&eacute; et compil&eacute; un noyau GENERIC,
-vous pouvez faire un ``make links'' afin d'&eacute;viter de compiler certains
-fichiers &agrave; chaque it&eacute;ration. Typiquement, je lance :
-<programlisting>
-# make depend links all
-</programlisting>
-suivi d'un ``make install'' quand le noyau me convient.
-</para>
-</sect3>
-
-<sect3>
-<title>Cr&eacute;er les fichiers sp&eacute;ciaux de p&eacute;riph&eacute;riques</title>
-
-<para> Sur FreeBSD, vous avez la responsabilit&eacute; de faire vos propres fichiers
-sp&eacute;ciaux
-de p&eacute;riph&eacute;rique. Le
-nombre majeur de votre p&eacute;riph&eacute;rique est d&eacute;termin&eacute; par le nombre de
-slots dans le commutateur de p&eacute;riph&eacute;rique. Le nombre mineur est
-d&eacute;pendant du pilote, naturellement. Vous pouvez
-soit ex&eacute;cuter mknod depuis la ligne de commande, soit liasser faire le
-travail &agrave; <filename>/dev/MAKEDEV.local</filename>, ou m&ecirc;me
-<filename>/dev/MAKEDEV</filename>.
-Je cr&eacute;e parfois un script MAKEDEV.dev qui peut &ecirc;tre soit lanc&eacute;
-de mani&egrave;re autonome soit coll&eacute; dans <filename>/dev/MAKEDEV.local</filename>.
-</para>
-</sect3>
-
-<sect3>
-<title>Red&eacute;marrage</title>
-<para> C'est la partie facile. Il y a un
-certain nombre de m&eacute;thodes pour faire ceci, reboot, fastboot,
-shutdown - r, couper le courant, etc. Au d&eacute;marrage, vous
-devriez voir votre XX<function>probe()</function> appel&eacute;, et si tout marche,
-votre <function>attach()</function> aussi.
-</para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>Module du noyau &agrave; chargement dynamique (LKM)</title>
-
-<para>Il n'y a vraiment aucune proc&eacute;dure d&eacute;finie pour &eacute;crire un pilote de
-LKM. Ce qui suit est ma propre conception apr&egrave;s exp&eacute;rimentation
-avec l'interface de p&eacute;riph&eacute;rique LKM et en regardant le mod&egrave;le standard
-de module de gestion de p&eacute;riph&eacute;rique, c'est une mani&egrave;re d'ajouter une
-interface LKM &agrave; 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&eacute;cifiques LKM devraient faire partie du pilote
-lui-m&ecirc;me, compil&eacute; de mani&egrave;re conditionnelle par la macro LKM
-(c.-&agrave;-d. #ifdef LKM).
-</para>
-
-<para>
-Cette section se concentrera sur la mani&egrave;re d'&eacute;crire la partie sp&eacute;cifique
-LKM du pilote. Nous supposerons que nous avons &eacute;crit un
-pilote qui atterrira dans le mod&egrave;le standard de
-gestion de p&eacute;riph&eacute;rique, que nous voudrions maintenant mettre en
-application comme &eacute;tant LKM. Nous utiliserons le pilote de pcaudio
-comme pilote d'exemple, et d&eacute;velopperons une entr&eacute;e LKM. La
-source et le fichier makefile pour le LKM pcaudio , ``pcaudio_lkm.c''
-et ``Makefile'', devraient &ecirc;tre dans plac&eacute; <filename>/usr/src/lkm/pcaudio</filename>.
-Ce qui suit est le code comment&eacute; de pcaudio_lkm.c.
-</para>
-
-<para>
-Lignes 17 - 26
-</para>
-
-<para>
-Ceci inclut le fichier ``pca.h'' et fait une compilation conditionnelle
-du reste de LKM suivant que vous avez d&eacute;fini ou non le pilote de
-p&eacute;riph&eacute;rique pcaudio.
-Cela imite le comportement de config. Dans un pilote de
-p&eacute;riph&eacute;rique standard,
-<ulink url="http://www.freebsd.org/cgi/man.cgi?config(8)">config</ulink>
-produit le fichier pca.h depuis le nombre de p&eacute;riph&eacute;riques pca
-le fichier de config. </para>
-
-<programlisting>
- 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
-</programlisting>
-
-<para>
-Lignes 27 - 37
-</para>
-
-<para>
-Les fichiers d'en-t&ecirc;te requis depuis divers r&eacute;pertoire d'inclusion.
-</para>
-
-<programlisting>
- 27 #include &lt;sys/param.h>
- 28 #include &lt;sys/systm.h>
- 29 #include &lt;sys/exec.h>
- 30 #include &lt;sys/conf.h>
- 31 #include &lt;sys/sysent.h>
- 32 #include &lt;sys/lkm.h>
- 33 #include &lt;sys/errno.h>
- 34 #include &lt;i386/isa/isa_device.h>
- 35 #include &lt;i386/isa/isa.h>
- 36
- 37
-</programlisting>
-
-<para>
-Lignes 38 - 51
-</para>
-
-<para>d&eacute;clarent vos points d'entr&eacute;e comme externs .
-</para>
-
-<programlisting>
- 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
-</programlisting>
-
-<para>
-Lignes 52 - 70
-</para>
-
-<para>
-Cela cr&eacute;e la table d'entr&eacute;e de commutateur de p&eacute;riph&eacute;rique pour
-votre pilote. Cette table est en gros enti&egrave;rement mise dans le
-syst&egrave;me de commutation de p&eacute;riph&eacute;riques &agrave; l'emplacement indiqu&eacute; par
-votre nombre majeur. Dans le mod&egrave;le standard, c'est dans
-<filename>/usr/src/sys/i386/i386/conf.c</filename>.
-NOTE: vous ne pouvez pas s&eacute;lectionner
-un nombre majeur de p&eacute;riph&eacute;rique plus grand que ce qui existe dans
-conf.c, par exemple
-il y a 67 slots pour des p&eacute;riph&eacute;riques caract&egrave;re, vous ne popuvez pas
-utiliser un p&eacute;riph&eacute;rique (caract&egrave;re) de num&eacute;ro majeur 67 ou
-plus, sans avoir d'abord r&eacute;serv&eacute; de l'espace dans conf.c.
-</para>
-
-<programlisting>
- 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
-</programlisting>
-
-<para>
-Lignes 71 - 131
-</para>
-<para>
-cette section est analogue &agrave; la d&eacute;claration de fichier de configuration
-de votre p&eacute;riph&eacute;rique. Les membres de la structure isa_device sont
-remplis grace &agrave; ce qu'il connait de votre p&eacute;riph&eacute;rique,
-port E/S, segment partag&eacute; de m&eacute;moire, etc...
-Nous n'aurons probablement jamais un besoin de deux p&eacute;riph&eacute;riques
-pcaudio dans le noyau, mais cet exemple montre comment
-p&eacute;riph&eacute;riques multiples peuvent &ecirc;tre support&eacute;s.
-</para>
-
-<programlisting>
- 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 &amp;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 &amp;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
-</programlisting>
-
-<para>
-Lignes 132 - 139
-</para>
-
-<para>
-Ceci appelle la macro MOD_DEV du pr&eacute;processeur C, qui
-installe un module de gestion de p&eacute;riph&eacute;rique de LKM, par
-opposition &agrave; un syst&egrave;me de fichiers LKM, ou un appel syst&egrave;me de LKM.
-</para>
-
-<programlisting>
- 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, &amp;pcacdevsw);
- 139
-</programlisting>
-
-<para>
-Lignes 140 - 168
-</para>
-
-<para>
-c'est la fonction qui sera appel&eacute;e lorsque le pilote sera
-charg&eacute;. Cette fonction essaye de fonctionner comme
-<filename>/sys/i386/isa/isa.c</filename> qui fait les appels de probe/attach pour un
-pilote au moment du red&eacute;marrage. La plus grande astuce ici est qu'il
-met en correspondance l'adresse physique du segment partag&eacute; de m&eacute;moire, qui est
-indiqu&eacute; dans la structure isa_device &agrave; une adresse virtuelle du noyau.
-Normalement, l'adresse physique est mise dans le fichier de configuration
-qui construit la structure isa_device dans
-<filename>/usr/src/sys/compile/KERNEL/ioconf.c</filename>. La s&eacute;quence probe/attach de
-<filename>/usr/src/sys/isa/isa.c</filename> traduit l'adresse physique en une virtuelle de
-sorte que dans les sous-programmes de probe/attach vous puissiez
-faire des choses comme
-</para>
-<programlisting>
-(int *)id->id_maddr = something;
-</programlisting>
-<para> et se r&eacute;f&egrave;re juste au segment partag&eacute; de m&eacute;moire
-par l'interm&eacute;diaire de pointeurs.
-</para>
-
-<programlisting>
- 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 <function>pcaload()</function>{
- 148 int i;
- 149 uprintf("PC Audio Driver Loaded\n");
- 150 for (i=0; i&lt;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
-</programlisting>
-
-<para>Lignes 169 - 179
-</para>
-
-<para>c'est la fonction appel&eacute;e quand votre pilote n'est pas
-charg&eacute;; il affiche juste un message &agrave; cet effet.
-</para>
-
-<programlisting>
- 169 /*
- 170 * this function is called
- 171 * when the module is unloaded
- 172 */
- 173
- 174 int
- 175 <function>pcaunload()</function>{
- 176 uprintf("PC Audio Driver Unloaded\n");
- 177 return 0;
- 178 }
- 179
-</programlisting>
-
-<para>Lignes 180 - 190
-</para>
-
-<para>c'est le point d'entr&eacute;e qui est indiqu&eacute; sur la ligne de commande
-de modload. Par convention il est nomm&eacute; &lt;dev>_mod. C'est
-ainsi qu'il est d&eacute;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.</para>
-
-<para>Note : Il y a eu <emphasis>tellement</emphasis> de r&eacute;visions entre la version 2.0 et
-2.1. Il peut ou ne peut ne pas &ecirc;tre possible d'&eacute;crire
-un module qui est portable pour chacune des trois versions.
-</para>
-
-
-<programlisting>
- 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 */
-</programlisting>
-</sect2>
-
-<sect2>
-<title>Idiosyncrasies du type p&eacute;riph&eacute;rique</title>
-
-<sect3>
-<title>Caract&egrave;re</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>Bloc</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>R&eacute;seau</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>Line discipline</title>
-<para></para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>Idiosyncrasies du type bus</title>
-
-<sect3>
-<title>ISA</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>EISA</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>PCI</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>SCSI</title>
-<para></para>
-</sect3>
-
-<sect3>
-<title>PCCARD</title>
-<para></para>
-</sect3>
-</sect2>
-</sect1>
-
-
-<sect1>
-<title>Support du noyau</title>
-
-<sect2>
-<title>Structures de donn&eacute;es</title>
-
-<sect3>
-<title>Structure <citerefentry><refentrytitle>struct kern_devconf</refentrytitle></citerefentry></title>
-
-<para>Cette structure contient quelques informations sur l'&eacute;tat du
-p&eacute;riph&eacute;rique et de son pilote. Elle est d&eacute;finie dans
-<filename>/usr/src/sys/sys/devconf.h</filename> comme ci-dessous :
-</para>
-
-<programlisting>
-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 */
-};
-</programlisting>
-</sect3>
-
-<sect3>
-<title>Structure <citerefentry><refentrytitle>struct proc</refentrytitle></citerefentry></title>
-
-<para> Cette structure contient toutes les informations sur un processus.
-Elle est dans d&eacute;finie <filename>/usr/src/sys/sys/proc.h</filename>:
-</para>
-
-<programlisting>
-/*
- * 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 */
-};
-</programlisting>
-</sect3>
-
-<sect3>
-<title>Structure <citerefentry><refentrytitle>struct buf</refentrytitle></citerefentry></title>
-<para>La structure <citerefentry><refentrytitle>struct buf</refentrytitle></citerefentry> est employ&eacute;e pour s'interfacer
-avec le cache de la m&eacute;moire tampon. Elle est dans
-d&eacute;finie <filename>/usr/src/sys/sys/buf.h</filename> :
-</para>
-
-<programlisting>
-/*
- * 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;
-};
-</programlisting>
-</sect3>
-
-
-<sect3>
-<title>Structure <citerefentry><refentrytitle>struct uio</refentrytitle></citerefentry></title>
-
-<para>Cette structure est utilis&eacute;e pour d&eacute;placer des donn&eacute;es entre le noyau et
-les espaces utilisateur par les appels syst&egrave;me de <function>read()</function> et de <function>write()</function>.
-Il est dans d&eacute;fini <filename>/usr/src/sys/sys/uio.h</filename> :
-</para>
-
-<programlisting>
-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;
-};
-</programlisting>
-</sect3>
-</sect2>
-
-
-<sect2>
-<title>Fonctions</title>
-<para>plein</para>
-</sect2>
-
-<sect2>
-<title>R&eacute;f&eacute;rences.</title>
-
-<para> FreeBSD Kernel Sources http://www.freebsd.org
-</para>
-
-<para> NetBSD Kernel Sources http://www.netbsd.org
-</para>
-
-<para> Writing Device Drivers: Tutorial and Reference;
-Tim Burke, Mark A. Parenti, Al, Wojtas;
-Digital Press, ISBN 1-55558-141-2.
-</para>
-
-<para> Writing A Unix Device Driver;
-Janet I. Egan, Thomas J. Teixeira;
-John Wiley &amp; Sons, ISBN 0-471-62859-X.
-</para>
-
-<para> Writing Device Drivers for SCO Unix;
-Peter Kettle;
-</para>
-</sect2>
-</sect1>
-</article>