C'est en quelque sorte un réseau Plug-and-Play développé par Microsoft mais utilisable sous Linux. Vous connectez quelque chose sur un réseau et ce quelque chose n'a pas besoin d'être configuré mais ne va communiquer qu'avec des périphériques UPnP du réseau. Ici, « configurer » est utilisé dans le sens large et ne signifie pas simplement configurer les ressources bus. Un des objectifs est de permettre au gens connaissant peu de choses sur les réseaux ou sur la configuration et l'installation d'un routeur, d'une passerelle, d'une imprimante réseau, et cætera de le faire. Une utilisation majeure de UPnP serait dans les réseaux sans-fil.
UPnP utilise :
un protocole de découverte des services (Simple Service Discovery Protocol) pour trouver les périphériques,
une architecture de notification générale d'événements (General Event Notification Architecture),
un protocole d'accès aux objets (Simple Object Access Protocol) pour assurer le contrôle des périphériques.
Ce guide pratique ne couvre pas UPnP. UPnP pour Linux est supporté par Intel qui a développé un logiciel spécifique. Il existe d'autres programmes qui font à peu près la même chose que UPnP. Une comparaison de ceux-ci est disponible sur http://www.cs.umbc.edu/~dchakr1/papers/mcommerce.html. Un projet UPnP pour Linux se trouve sur Sourceforge : Kit UPnP pour Linux
Il existe trois types d'adresses : adresses en mémoire principale, adresses d'entrées/sorties (ports) et adresses de configuration. Sur le bus PCI, les adresses de configuration constituent une plage d'adresses séparée un peu comme les adresses d'entrées/sorties. Sauf dans le cas compliqué des adresses de configuration ISA, qu'une adresse sur le bus soit ou non une adresse en mémoire principale, une adresse d'entrées/sorties ou une adresse de configuration dépend seulement du voltage sur certains fils du bus. Pour plus de détails sur les adresses de configuration du bus ISA, voir la section intitulée « Adresses de configuration du bus ISA (Port de lecture et cætera) ».
Le terme « adresse » est quelque fois utilisé dans ce document
pour
signifier un ensemble contigu d'adresses. Les adresses sont en unité d'octets.
Donc, par exemple, un port série sur l'espace d'adressage 3F8-3FF sera souvent
juste référencé par son adresse de base, 3F8. 3F8 est l'emplacement du premier
octet de la plage (espace d'adressage). Pour visualiser les espaces d'adressage,
jetez un œil à /proc/iomem
et
/proc/ioports
.
Pour accéder à la fois aux espaces d'adresses mémoire principale et d'entrées/sorties, le même bus d'adresses est utilisé (les fils utilisés pour l'adresse sont partagés). Comment le périphérique sait-il si l'adresse apparaissant sur le bus est une adresse mémoire ou d'entrées/sorties ? En fait, pour l'ISA (pour le PCI, lisez aussi ceci), il existe quatre fils dédiés sur le bus qui amènent ce type d'informations. Si un de ces quatre fils est « activé », cela indique que le CPU veut lire une adresse d'entrées/sorties et la mémoire principale ignore l'adresse sur le bus. En tout, les fils de lecture et écriture existent à la fois pour les adresses de mémoire principale et pour les adresses d'entrées/sorties (quatre fils en tout).
Pour le bus PCI, il s'agit de la même idée de base (utilisant aussi quatre fils) mais réalisée un peu différemment. Au lieu d'avoir un seul des quatre fils activé, un nombre binaire est placé sur les fils (d'où 16 possibilités différentes). Donc, il est possible de véhiculer plus d'informations sur ces quatres fils. Quatre de ces 16 nombres sont utilisés pour les espaces en mémoire principale et d'entrées/sorties comme indiqué dans le paragraphe ci-dessus. En plus, il existe aussi un espace d'adressage de configuration qui utilise plus de deux chiffres supplémentaires. Cela laisse dix autres nombres disponibles pour d'autres utilisations.
Ceci est différent des espaces d'adresses mémoire et d'entrées/sorties parce que l'espace d'adresses de configuration est « géographique ». Chaque emplacement d'une carte a un numéro d'emplacement faisant parti de l'adresse. De cette façon, Linux (ou le BIOS) peut adresser un certain emplacement et trouver le type de carte fiché dans cet emplacement. Chaque périphérique a des registres standards de 64 bits et quelques uns d'entre eux contiennent des numéros qui peuvent identifier de façon non ambiguë le périphérique. Comme le nombre d'emplacements est limité comme le sont le nombre de périphériques PCI construit dans la carte mère, Linux (ou le BIOS) a besoin de vérifier un nombre limité d'adresses pour trouver tous les périphériques PCI. S'il ne lit que des uns (0xFF en hexadécimal) à partir du premier registre d'un périphérique, alors cela signifie qu'aucun périphérique n'est présent. Comme il n'y a aucune carte ou périphérique fournissant tous les numéros un (0xFF), le « host bridge » PCI sur la carte mère fournit ce numéro pour tous les périphériques inexistants.
Le numéro d'emplacement PCI est appelé (dans le jargon PCI le numéro de périphérique et comme une carte peut avoir au plus huit périphériques sur elle, un numéro de fonction (allant de 0 à 7) identifie le périphérique qui se trouve sur une carte PCI. Ces numéros font partie de l'adresse géographique. Les développeurs Linux l'appellent pci-slot-name. Du coup, ce que Linux appelle un périphérique est en fait une fonction dans le jargon PCI. Le numéro du bus PCI (souvent 00) devient aussi une partie de l'adresse géographique. Par exemple, 0000:00:0d.2 correspond au bus PCI 0, emplacement 0, fonction 2. Pour l'adresse géographique complète, vous devez inclure le numéro sur deux mots des registres de configuration du périphérique auquel on veut l'accès. Les 0000 en tête (en 1999) étaient réservés pour une utilisation future.
Comment le processeur désigne-t-il qu'une lecture ou une écriture doit se faire dans l'espace de configuration PCI ? Il ne le fait pas, en tout cas pas directement. À la place lorsque l'accès à l'espace de configuration est désiré, il fait une écriture sur 32 bits (un mot double) pour écrire 0cf8-0cfb en espace d'entrées/sorties et écrit l'adresse géographique complète ici. Le host bridge PCI écoute à cette adresse et nous assure que la prochaine écriture de données sera 0cfc-0cff. C'est enregistré dans des registres de configuration du périphérique spécifié. Le pont fait les deux en envoyant un signal spécial à la carte PCI spécifiée (ou ce qui y ressemble) sur un fil dédié qui va seulement à l'emplacement où la carte est connectée. Il place aussi des bits sur le bus de contrôle indiquant que ce qui est sur le bus d'adresse maintenant est une adresse géographique de l'espace de configuration.
Pourquoi ne pas faire simple et demander simplement au processeur de placer les bits sur le bus de contrôle pour indiquer que l'adresse sur le bus principal est une adresse géographique pour la configuration du PCI ? Et bien, la plupart des processeurs ne sont pas capables de le faire donc le « host bridge » PCI le fait à la place.
Sur le bus ISA, il existe une méthode intégrée dans chaque carte PnP pour vérifier qu'aucune autre carte n'utilise la même adresse d'entrées/sorties. Si deux cartes ou plus utilisent la même adresse d'entrées/sorties, les cartes ont peu de chance de fonctionner correctement (voire de fonctionner tout court). Un bon logiciel PnP devrait allouer les ressources bus de manière à éviter ce conflit, mais même dans ce cas, une carte non PnP pourrait avoir la même adresse.
Le test fonctionne par une carte plaçant un nombre de test connu dans ses propres registres d'entrées/sorties. Puis, le logiciel PnP le lit et vérifie que ce qu'il lit correspond bien au numéro de test connu. Il répète le même test avec un autre numéro. Comme il vérifie l'ensemble des adresses d'entrées/sorties allouées à la carte, il est appelé un vérificateur de plage. Il pourrait être appelé plus logiquement un testeur de conflit d'adresses. Si un conflit est détecté, vous obtenez un message d'erreur.
Traditionnellement, la plupart des périphériques d'entrées/sorties utilisent seulement la mémoire d'entrées/sorties pour communiquer avec le processeur (CPU). Le pilote de périphérique, exécuté sur le processeur lira et écrira des données de/vers l'espace d'adressage des entrées/sorties et la mémoire principale. Malheureusement, cela nécessite deux étapes. Par exemple, 1. lire les données à partir d'un périphérique (en espace d'adressage) et les stocker temporairement dans le CPU ; 2. écrire ces données en mémoire principale. Une façon plus rapide serait que le périphérique place lui-même les données directement en mémoire principale. Une façon de faire ceci est d'utiliser la section intitulée « DMA (accès direct à la mémoire) ou maîtrise du bus » ISA ou la maîtrise du bus PCI. Le périphérique physique peut aussi détenir un peu de mémoire principale (aux adresses supérieures pour éviter les conflits avec les adresses des composants de la mémoire principale). De cette façon, le périphérique lit et écrit directement dans son espace mémoire interne sans avoir à s'embêter avec le DMA ou la maîtrise du bus. De tels périphériques pourraient aussi utiliser des adresses d'entrées/sorties.
Ces adresses sont aussi connues comme les « ports d'auto-configuration ». Pour le bus ISA, il n'existe pas techniquement de plage d'adresses de configuration, mais le CPU utilise une façon spéciale d'accéder aux registres de configuration PnP sur les cartes PnP. Dans ce but, trois adresses d'entrées/sorties sont allouées et chacune adresse un seul octet (il n'y a pas à proprement parler d'espace ou de plage). Il ne s'agit pas de trois adresses pour chaque carte mais de trois adresses partagées par toutes les cartes ISA-PnP.
Ces trois adresses sont nommées port de lecture (read-port), port d'écriture (write-port) et port d'adresse (address-port). Chaque port a une taille d'un octet. Chaque carte PnP dispose d'un grand nombre de registres de configuration, donc même les trois adresses ne sont pas suffisantes pour les registres de configuration d'une seule carte. Pour résoudre ce problème, chaque carte se voit affecter un numéro de carte en utilisant une technique appelée « isolation ». Voir la section intitulée « Isolation ISA » pour des détails plus complexes.
Ensuite, pour configurer une certaine carte, son numéro de carte est envoyé via l'adresse du port d'écriture pour indiquer à cette carte qu'elle doit écouter sur son port d'adresse. Toutes les autres cartes notent que ce n'est pas leur numéro de carte et donc n'écoutent pas. Ensuite, l'adresse d'un registre de configuration est envoyé sur le port d'adresse (à toutes les cartes, mais une seule écoute). Enfin, le transfert de données prend place avec ce registre de configuration sur cette carte soit en faisant une lecture sur le port de lecture soit en faisant une écriture sur le port d'écriture.
Le port d'écriture est toujours A79 et le port d'adresse est toujours 279 (en hexadécimal). Le port de lecture n'est pas fixe mais dépend du logiciel de configuration (tout en restant dans la plage 203-3FF) qui avec un peu de chance n'entrera pas en conflit avec les autres cartes ISA. Si un conflit se déclare, il changera l'adresse. Toutes les cartes PnP sont « programmées » avec cette adresse. Donc, si vous utilisez isapnp pour enregistrer ou connaître la configuration, celui-ci doit d'abord déterminer l'adresse du port de lecture.
Il a été dit précédemment qu'il existe un fil pour chaque interruption. Mais l'interruption sérialisée (ou interruption série) est une exception. Un seul fil est utilisé pour toutes les interruptions qui sont multiplexées sur ce fil. Chaque interruption a un créneau horaire sur la ligne d'interruption. Il est utilisé sur le bus LPC mais aussi sur le bus PCI bien que cela soit plus rare pour ce dernier ?
Avant de se plonger dans le détail des interruptions, il existe une autre façon pour que les périphériques initient la communication en dehors de l'envoi d'une interruption. Cette méthode est une requête DMA (Direct Memory Access) pour prendre le contrôle de l'ordinateur à partir du CPU pour un temps limité. Sur le bus PCI, il n'utilise aucune ressource. Tous les périphériques ne sont pas capables de faire du DMA. Voir la section intitulée « DMA (accès direct à la mémoire) ou maîtrise du bus ».
Il existe aussi un autre type d'interruption nommée « interruption logicielle », non couverte par ce guide pratique et n'utilisant pas de ressources. Alors qu'une interruption matérielle est générée par le matériel, une interruption logicielle est initiée par le logiciel. Il existe plusieurs façons pour ce faire. Une façon est que le logiciel dise au processeur d'exécuter une interruption (une instruction d'interruption). Une autre façon consiste, pour le logiciel, à envoyer des messages aux autres processus pour les interrompre même s'il n'est pas clair qu'on puisse appeler ça une interruption. Le processus ksoftirq process, que vous pouvez trouver dans la liste des processus sur un PC Linux, est un programme qui lance ce type d'interruption pour gérer les pilotes de périphériques. Le pilote de périphérique commence à s'exécuter à cause d'une interruption matérielle mais, plus tard, des interruptions logicielles sont utilisées pour la deuxième moitié de la routine d'interruption du pilote. Donc, le processus ksoftirq est aussi connu comme la « seconde moitié ». Pour plus de détails, voir la documentation du noyau.
Les interruptions amènent beaucoup d'informations mais seulement indirectement. Le signal de demande d'interruption (un voltage sur un fil) envoyé par un matériel indique seulement au composant, appelé le contrôleur d'interruption, qu'un certain périphérique demande l'attention. Le contrôleur d'interruption envoie le signal au CPU. Le CPU s'interrompt dans ce qu'il faisait, trouve le pilote de ce périphérique et exécute une partie de celui-ci nommée « routine d'interruption » (ou « gestionnaire d'interruption »). Cette « routine » essaie de trouver ce qui est arrivé et gère ensuite le problème. Par exemple, le périphérique peut avoir besoin d'envoyer/recevoir des octets. Ce programme (cette routine) peut facilement comprendre ce qui s'est passé car le périphérique dispose de registres disponibles sur des adresses connues par le pilote (à condition que le numéro d'IRQ et que les adresses d'entrées/sorties soient correctement configurés). Ces registres contiennent l'état du périphérique. Le logiciel lit le contenu de ces registres et en inspectant le contenu, trouve ce qui est arrivé et réalise l'action appropriée.
Donc, chaque pilote de périphérique a besoin de savoir le numéro d'interruption (IRQ) où écouter. Sur le bus PCI (et dans certains cas spéciaux, sur le bus ISA), il est possible que deux (voire plus) périphériques partagent le même numéro d'IRQ. Notez que vous ne pouvez pas partager une interruption PCI avec une interruption ISA (y a-t'il des exceptions ?). Quand une interruption partagée est lancée, le processeur exécute toutes les routines du service d'interruption séquentiellement pour tous les périphériques utilisant cette interruption. La première action qu'entreprend la première routine lancée est de vérifier les registres du périphérique pour voir si une interruption a été générée par son périphérique. S'il se trouve que ce n'est pas le cas (fausse alarme), il s'arrêtera immédiatement et la prochaine routine commence pour le deuxième périphérique qui utilise cette même interruption, et cætera. Il vérifie le périphérique comme décrit ci-dessus. Cette séquence est répétée jusqu'à la découverte du périphérique qui a lancé cette interruption. Toutes les routines d'interruption pour une interruption constituent une chaîne. Donc, la chaîne est traversée jusqu'à ce qu'une routine de la chaîne réclame l'interruption en disant : cette interruption est pour moi. Après avoir géré l'interruption, les routines suivantes du service d'interruption ne sont pas exécutées.
Mettre un certain voltage sur une ligne IRQ revient seulement à demander que le CPU s'interrompe de façon à exécuter la routine du pilote du périphérique. Dans pratiquement tous les cas, le CPU est interrompu par la requête. Mais les interruptions du CPU peuvent être temporairement désactivées ou « faire la queue », et donc, dans de rares cas, une interruption peut ne pas être gérée (ou peut subir un certain délai). Donc, ce qui a été auparavant appelé une interruption est plus précisément une « demande d'interruption », ce qui explique l'acronyme d'IRQ (« Interrupt ReQuest », c'est-à-dire ReQuête d'Interruption).
L'indication précédente, à savoir que les pilotes de périphérique écoutent leur interruption, était une explication très simplifiée. En fait, il s'agit d'un composant (ou d'une partie d'un composant) embarqué sur la carte-mère, appelé le contrôleur d'interruptions. Il va écouter toutes les interruptions. Quand le contrôleur récupère une interruption, il envoie un signal au CPU pour lancer la routine du service d'interruption du pilote de périphérique approprié pour gérer cette interruption.
Il existe différents types de contrôleurs d'interruptions. L'un d'entre eux est l'APIC (acronyme de Advanced Programmable Interrupt Controller) qui a habituellement des broches en entrée pour un grand nombre d'interruptions, y compris les interruptions PCI. Les anciens contrôleurs ont seulement des broches pour les interruptions ISA mais ils peuvent toujours gérer les interruptions PCI car il s'agit d'un routeur programmable d'interruptions qui convertit les interruptions PCI en interruptions ISA et les envoie vers certaines broches (c'est-à-dire vers certaines IRQ).
C'est uniquement pour l'ancien bus ISA. L'isolation est une méthode complexe d'affectation d'un point temporaire (numéro d'identifiant ou CSN, Card Select Number) à chaque périphérique PnP du bus ISA. Comme il existe des moyens plus efficaces (mais plus complexes) de le faire, certains pourraient dire qu'il s'agit d'une méthode simple. Seule une adresse d'écriture est utilisée pour les écritures PnP vers tous les périphériques pour que toutes les écritures vers cette adresse aillent sur tous les périphériques PnP. Cette adresse d'écriture est utilisé pour envoyer (affecter) un numéro de carte unique à chaque périphérique PnP. Pour être assigné, ce numéro de carte nécessite qu'un seul périphérique soit en écoute lorsque le numéro de carte est envoyé (écrit) à cette adresse commune. Tous les périphériques PnP ont un numéro de série unique qu'ils utilisent lors du processus d'isolation. Faire l'isolation est comme un jeu. Cela se fait en utilisant l'équivalent d'un bus commun de fils connectant tous les périphériques PnP au programme d'isolation.
Pour le premier tour du « jeu », tous les périphériques PnP écoutent sur ce fil et envoient simultanément une séquence de bits sur le fil. Les bits autorisés sont soit un 1 (voltage positif) soit un « 0 ouvert » sans voltage (circuit ouvert ou trois-états). Pour cela, chaque périphérique PnP commence à envoyer séquentiellement son numéro de série sur ce fil, voltage (circuit ouvert ou trois-états). Pour faire cela, chaque périphérique PnP lance simplement son numéro de série sur les fils, bit à bit, en commençant par le plus haut. Si un périphérique envoie un 1, un 1 sera entendu par tous les autres périphériques. Si tous les périphériques envoient un « 0 ouvert », rien ne sera entendu sur le fil. Le but est d'éliminer (à la fin du premier tour) tous les périphériques sauf celui possédant le numéro de série le plus important. « Éliminer » signifie enlever de ce tour du jeu et donc cesser temporairement d'écouter tout ce qui passe sur le fil. (Notez que tous les numéros de série ont la même taille.) Quand il ne reste qu'un seul périphérique en écoute, un numéro de carte lui est donné.
Tout d'abord, considérez seulement le bit le plus haut du numéro de série qui est placé sur le fil par tous les périphériques qui n'ont pas encore de numéro de carte. Si un périphérique PnP envoie un 0 (0 ouvert) mais entend un 1, cela signifie qu'un ou plusieurs autres périphériques PnP a un numéro de série plus important, donc il se supprime temporairement pour ce tour. Maintenant, les périphériques restant en jeu (pour ce tour) ont tous le même bit de haut niveau (un 1), donc nous pouvons supprimer ce bit et continuer avec le « reste du numéro de série » pour la suite du tour. Ensuite, recommencez depuis le début de ce paragraphe et répétez jusqu'à ce que le numéro de série soit examiné en entier pour chaque périphérique (voir plus bas pour les cas « tous à 0 »).
Donc, il est clair que seules les cartes avec un petit numéro de série sont éliminées lors d'un tour. Mais qu'arrive-t-il si tous les périphériques du jeu envoient un 0 comme leur bit de haut niveau ? Dans ce cas, un « 0 ouvert » est envoyé sur la ligne et tous les participants restent en lice. S'ils ont tous un 0 au début, alors les 0 sont supprimés comme les 1 du paragraphe ci-dessus. Le jeu continue alors avec le bit suivant du numéro de série).
A la fin du tour (après que le dernier bit ait été envoyé), seul un périphérique PnP, celui possédant le plus haut numéro de série, reste en jeu. Il se voit attribuer un numéro de carte et quitte le jeu définitivement. Ensuite, tous les autres périphériques du tour précédent (qui n'ont donc pas de numéro de carte) reviennent dans le jeu et un nouveau tour commence, avec un participant en moins. Éventuellement, tous les périphériques PnP se voient assigner un numéro de carte. Il est facile de prouver que cet algorithme fonctionne. L'algorithme actuel est un peu plus complexe que celui présenté ci-dessus car chaque étape est répétée deux fois pour s'assurer, et ces répétitions sont faites d'une façon un peu différente (mais en utilisant la même idée de base).
Une fois tous les numéros de carte assignés, ils sont utilisés pour s'adresser à chaque périphérique PnP pour envoyer/lire des données de configuration. Notez que ces numéros de carte sont seulement utilisés pour la configuration PnP et ne sont pas utilisés pour les communications normales avec le périphérique PnP. Lorsque l'ordinateur démarre, un BIOS PnP fera l'isolation puis s'occupera de la configuration PnP. Après ça, tous les numéros de carte sont « perdus » d'une telle façon que si quelqu'un veut changer (ou inspecter) la configuration une nouvelle fois, l'isolation devra être refaite intégralement.
Si un bus dispose d'une fonctionnalité de maîtrise du bus, il est peu probable que des ressources seront nécessaires pour le DMA sur ce bus. Par exemple, le bus PCI n'a pas besoin des ressources DMA car il dispose de cette fonctionnalité. Néanmoins, la « maîtrise du bus » est souvent appelée DMA. Mais, comme il ne s'agit pas strictement de DMA, il ne nécessite aucune ressource DMA. Les bus locaux ISA et VESA n'ont pas de maîtrise du bus. Les anciens bus MCU et EISA l'avaient.
Vous devez donner l'adresse d'entrée/sortie, l'IRQ et le canal DMA comme paramètres au module ou les compiler dans le noyau. Mais certaines cartes PCI seront automatiquement détectées. RedHat fournit un programme sndconfig qui détecte les cartes ISA PnP et configure automatiquement les modules en chargeant les ressources bus détectées.
Ceci détectera la carte par des méthodes PnP, puis sélectionnera le pilote et le chargera. Il configurera aussi les ressources bus sur les cartes ISA-PnP et sur les cartes PCI. Il remplace OSS (Open Sound System), auparavant populaire.
Windows NT4 ne supportait pas ISAPNP mais dispose d' un programme PNPISA que vous pouvez utiliser « à vos risques et périls ». Pour NT4, les utilisateurs se sont vus conseiller de ne pas configurer le BIOS avec l'indication que le système d'exploitation est PnP de façon à ce que le BIOS s'occupe de la configuration des ressources. Du coup, MS Windows et Linux étaient auparavant dépendants de la configuration du BIOS (et le sont toujours).