[NetBSD] lockmgr () dans un pilote

Le
Vincent
Salut,
en ayant marre de la libusb, dont la version BSD ne supporte pas les
appels reset ou clear_halt, je suis en train d'écrire un pilote pour les
appareils numériques travaillant avec le protocole Sierra (Olympus,
Nikon).

J'ai juste une question : est-il possible d'utiliser un appel lockmgr
dans un pilote de périphérique, selon ce modèle (schématique) :

En particulier, quelle priorité mettre dans l'appel lockinit, vu que la
solution par défaut, getpriority (PRIO_PROCESS, 0) va retourner la
priorité du noyau au moment de l'appel de _attach.

struct foo_softc
{
struct_device sc_dev ;
struct lock usblock ;
[]
}

struct foo_dev * sc ;

foo_attach ()
{
[]
lockinit (usblock, ?? , "USB WAIT",
CAM_TIMEOUT, 0) ;
[]
}

read_or_write_camera_register ( )

{
lockmgr (usblock, LK_EXCLUSIVE , 0)
[]

read_or_write_transfer_usb (buffer)

lockmgr (usblock, LK_RELEASE, 0) ;

[]
}

[]

Merci !
Vincent
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Miod Vallat
Le #656675
J'ai juste une question : est-il possible d'utiliser un appel lockmgr
dans un pilote de périphérique, selon ce modèle (schématique) :


L'utilisation de lockmgr() n'a de sens que si tu associes le verrou à un
processus (ou en 2.0, un lwp) - par exemple parce que ton traitement
lent est provoqué par une entrée/sortie ou un ioctl depuis un processus
en userland.

En particulier, quelle priorité mettre dans l'appel lockinit, vu que la
solution par défaut, getpriority (PRIO_PROCESS, 0) va retourner la
priorité du noyau au moment de l'appel de _attach.


PWAIT, ou PRIBIO si c'est véritablement une entrée/sortie comparable à
une activité disque, me semblent adéquats.

lockmgr (usblock, LK_EXCLUSIVE , 0)


Attention, ne jamais passer un pointeur NULL à lockmgr. Au pire,
curproc() ou curlwp(), mais jamais NULL...

Vincent
Le #656674
Re-

L'utilisation de lockmgr() n'a de sens que si tu associes le verrou à
un processus (ou en 2.0, un lwp) - par exemple parce que ton
traitement lent est provoqué par une entrée/sortie ou un ioctl depuis
un processus en userland.


Oui, c'est ça. En fait, je veux bloquer si un processus 2 tente de lire
un registre de l'appareil photo alors qu'un processus 1 est déjà en
train de le faire, puis débloquer lorsque le bus est de nouveau libre.

En fait, le pilote ne supporte pas read/write. Il ne fonctionne que par
ioctls, puisque l'appareil photo lui-même ne sait faire que cela.

Une fois qu'on a crée une strcuture de type bdevsw, comment récupérer
son numéro d'ordre (et donc le majeur du périph ?)

PWAIT, ou PRIBIO si c'est véritablement une entrée/sortie comparable à
une activité disque, me semblent adéquats.


Ok merci.


lockmgr (usblock, LK_EXCLUSIVE , 0)


Attention, ne jamais passer un pointeur NULL à lockmgr. Au pire,
curproc() ou curlwp(), mais jamais NULL...


Il me semblait, d'après la man page, que le troisième argument était non
significatif, sauf dans le cas de l'emploi du flag LK_INTERLOCK...

Vincent


Miod Vallat
Le #656673
Oui, c'est ça. En fait, je veux bloquer si un processus 2 tente de lire
un registre de l'appareil photo alors qu'un processus 1 est déjà en
train de le faire, puis débloquer lorsque le bus est de nouveau libre.


Alors lockmgr() peut convenir.

Une fois qu'on a crée une strcuture de type bdevsw, comment récupérer
son numéro d'ordre (et donc le majeur du périph ?)


Pourquoi as-tu besoin de connaître ton majeur ? Tu ne verra passer les
open/ioctl/close que pour tes propres devices, tout ce que tu as à faire
est de vérifier le mineur afin de voir si tu as du matériel associé.

Quand bien même tu aurais besoin de connaître ton majeur, sous Open, on
en est encore à parcourir bdevsw[] et cdevsw[] à la mimine ; NetBSD 2 a
[bc]devsw_lookup(), mais je ne sais pas si ces fonctions étaient déjà en
1.6.

lockmgr (usblock, LK_EXCLUSIVE , 0)


Attention, ne jamais passer un pointeur NULL à lockmgr. Au pire,
curproc() ou curlwp(), mais jamais NULL...


Il me semblait, d'après la man page, que le troisième argument était non
significatif, sauf dans le cas de l'emploi du flag LK_INTERLOCK...


Au temps pour moi, je ne me souvenais plus que lockmgr() avait 4
paramètres.



Vincent
Le #656672
Miod Vallat
Alors lockmgr() peut convenir.


Hoquet :)

Pourquoi as-tu besoin de connaître ton majeur ? Tu ne verra passer les
open/ioctl/close que pour tes propres devices, tout ce que tu as à
faire est de vérifier le mineur afin de voir si tu as du matériel
associé.


À ce qu'il me semble, si je veux faire un ioctl depuis l'userland, il
faut quand même que je crée un device (donc mknod), ce qui suppose un
couple majeur, mineur.

Bon, je n'ai certes pas d'intérêt à le connaître dans le corps du
pilote, mais il faut quand même que je connaisse son numéro d'ordre dans
la table pour mknod !

Au temps pour moi, je ne me souvenais plus que lockmgr() avait 4
paramètres.


C'est agréable de lire « au temps pour moi » dans sa version correcte !
:)

Merci encore
Vincent

Miod Vallat
Le #656671
À ce qu'il me semble, si je veux faire un ioctl depuis l'userland, il
faut quand même que je crée un device (donc mknod), ce qui suppose un
couple majeur, mineur.


Certes. Dans ce cas, en 1.6 il te suffit de choisir un emplacement dans
sys/arch/<arch>/<arch>/conf.c, qui te détermine le numéro majeur. La
gestion des mineurs est laissée à ta guise. Et puis tu gagnes le droit
de te palucher le MAKEDEV à la mimine.

En 2.0, tout est plus simple, tu n'as qu'à ajouter une entrée dans
sys/arch/ découle automagiquement.

Vincent
Le #656446
En 2.0, tout est plus simple, tu n'as qu'à ajouter une entrée dans
sys/arch/ découle automagiquement.


Bien bien.
Juste une dernière question.

Pour récupérer la structure toto_softc appropriée dans un appel genre
toto_open ou toto_close, il faut bien faire :

struct toto_softc * toto_sc ;

[...]

toto_sc = toto_cd. cd_devs [dev] ;
?

Merci derechef.
Vincent

Miod Vallat
Le #656445
Pour récupérer la structure toto_softc appropriée dans un appel genre
toto_open ou toto_close, il faut bien faire :

struct toto_softc * toto_sc ;

[...]

toto_sc = toto_cd. cd_devs [dev] ;


Grossièrement, oui.

En pratique, on va aussi vérifier que l'on a bien un softc au numéro que
l'utilisateur a demandé :

int
totoopen(dev_t dev, int flag, int mode, struct proc *p)
{
struct toto_softc *sc;
unsigned int dnum;

dnum = TOTO_NUM(dev);
if (dnum >= toto_cd.cd_ndevs)
return ENODEV;

sc = (struct tot_softc *)tot_cd.cd_devs[dnum];

...

où TOTO_NUM est une macro sur le thème de getminor() & 0x42, à fournir
soi-même.

Vincent
Le #656444
Miod Vallat
où TOTO_NUM est une macro sur le thème de getminor() & 0x42, à fournir
soi-même.


Ouais, j'arrive pas à trouver la façon dont le dev_t est composé.
Y a un fichier à consulter ? Y a bien la macro minor( ) dans types.h,
mais ça ne me dit pas grand chose sur la signification des masques...

Vincent

Miod Vallat
Le #656443
Ouais, j'arrive pas à trouver la façon dont le dev_t est composé.


makedev() dans
Y a un fichier à consulter ? Y a bien la macro minor( ) dans types.h,
mais ça ne me dit pas grand chose sur la signification des masques...


Tu t'en fiches ! La numérotation est opaque de ton point de vue. Tu as
un majeur figé, et la gestion des mineurs est à ta guise.

Par exemple, un pilote pour une carte de ports parallèles peut définir
les affectations suivantes :

0-7 8 ports en polling
8-15 8 ports avec interruptions

Dans ce cas, on aurait

#define SUPERLP_UNIT(x) (minor(x) & 0x07)
#define SUPERLP_POLLING(x) (!ISSET(minor(x), 0x08))
#define SUPERLP_INTERRUPT(x) ISSET(minor(x), 0x08)

mais libre au concepteur de choisir sa propre nomenclature.

Dans ton cas, à priori simple, ou tu te contentes de gérer au plus N
appareils, une simple correspondance avec minor() suffit.

Vincent
Le #656442
Miod Vallat
Tu t'en fiches ! La numérotation est opaque de ton point de vue. Tu as
un majeur figé, et la gestion des mineurs est à ta guise.


Okay, donc, en fait, on a libre choix pour tout ce qui est signification
du mineur. Ça marche.

Merci de ton aide précieuse.

Vincent

Publicité
Poster une réponse
Anonyme