|
Documentation NetBSD :Programmation noyau |
options DDB» et que votre fichier ait «#include "opt_ddb.h"» puis utilisez «Debugger()».
xxxattach(), routine qui configure et rattache le périphérique.Une fois que les routines probe et attach sont écrites, ajoutez une entrée au fichier
/usr/src/sys/arch/<votre-arch>/<votre-arch>/conf.c.
Il existe deux tables :
cdevsw pour les périphériques par caractères.bdevsw pour les périphériques par blocs (pour ceux qui effectuent aussi des E/S par «blocs» et utilisent une routine stratégique).
La plupart des entrées se présenteront sous la forme cdev_xxx_init() qui correspond à une macro gérant les prototypes standards d'Unix des routines de changements de périphériques.
Les routines probe/attach sont appelées au démarrage. Les routines open(), close(), read() et write() sont appelées lorsque vous sollicitez le fichier du périphérique dont le nombre majeur correspond à l'index de cette table. Par exemple, si vous sollicitez le périphérique dont le nombre majeur est 18, la routine «open» du périphérique 18 dans cdevsw[]/bdevsw sera appelée.
La plupart des pilotes sont divisés en deux parties : l'une spécifique au bus et l'autre indépendante de la machine. Par exemple, le pilote ethernet lance PCI possède des entrées dans les fichiers suivants :
La première chose à faire est de choisir un offset quelconque pour votre interface mmap. Quelque chose comme «mmap offset 0-M gives object A, N-O gives object B», etc...
Ensuite, votre routine mmap ressemblera à :
int
foommap(dev, off, prot)
dev_t dev;
int off, prot;
{
if (off & PAGE_MASK)
panic("foommap");
if ((u_int)off >= FOO_REGION1_MMAP_OFFSET &&
(u_int)off < (FOO_REGION1_MMAP_OFFSET + FOO_REGION1_SIZE))
return (atop(FOO_REGION1_ADDR + ((u_int)off -
FOO_REGION1_MMAP_OFFSET)));
if ((u_int)off >= FOO_REGION2_MMAP_OFFSET &&
(u_int)off < (FOO_REGION2_MMAP_OFFSET + FOO_REGION2_SIZE))
return (atop(FOO_REGION1_ADDR + ((u_int)off -
FOO_REGION2_MMAP_OFFSET)));
/* Page non trouvée. */
return (-1);
}
Les choses vont maintenant se corser car vous allez «mmapper» ce qui n'est que des objets mémoire du noyau (c'est un pseudo-périphérique, n'est-ce pas ?).
Pour que cela marche, vous allez vous assurer que vous allouez les objets mémoire à mmapper à des limites alignées sur les pages. Ce sera toujours le cas si vous allouez une taille >= PAGE_SIZE. Autrement, vous devrez utiliser uvm_km_alloc() et arrondir la taille pour remplir la page.
Vous aurez alors quelque chose comme :
int
foommap(dev, off, prot)
dev_t dev;
int off, prot;
{
paddr_t pa;
if (off & PAGE_MASK)
panic("foommap: offset not page aligned");
if ((u_int)off >= FOO_REGION1_MMAP_OFFSET &&
(u_int)off < (FOO_REGION1_MMAP_OFFSET + FOO_REGION1_SIZE)) {
if ((vaddr_t)foo_object1 & PAGE_MASK)
panic("foommap: foo_object1 not page aligned");
if (pmap_extract(pmap_kernel(), foo_object1 +
(u_int)off - FOO_REGION1_MMAP_OFFSET, &pa) == FALSE)
panic("foommap: foo_object1 page not mapped");
return (atop(pa));
}
if ((u_int)off >= FOO_REGION2_MMAP_OFFSET &&
(u_int)off < (FOO_REGION2_MMAP_OFFSET + FOO_REGION2_SIZE)) {
if ((vaddr_t)foo_object2 & PAGE_MASK)
panic("foommap: foo_object2 not page aligned");
if (pmap_extract(pmap_kernel(), foo_object2 +
(u_int)off - FOO_REGION2_MMAP_OFFSET, &pa) == FALSE)
panic("foommap: foo_object2 page not mapped");
return (atop(pa));
}
/* Page non trouvée. */
return (-1);
}
|
|