IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

x86 32-bits / 64-bits Assembleur Discussion :

Énumérer les bus PCI


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2014
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2014
    Messages : 25
    Points : 12
    Points
    12
    Par défaut Énumérer les bus PCI
    Salut à tous,
    Dans le cadre d'un projet scolaire portant sur l'architecture des ordinateurs, je dois réaliser un programme pouvant énumérer les bus PCI d'un ordinateur.
    Ce programme est divisé en deux "couches" :
    - Une couche d'énumération qui se charge d'énumérer les différents bus ainsi que les devices dans chacun de ces bus. Elle doit ensuite utiliser une structure de données pour stocker ces informations (Tree ?) ainsi que différentes informations sur le device (vendor id, device id, functions). Elle doit générer un arbre pour représenter toutes ces données (bus + devices). Cette couche sera intégré dans le kernel land (fictif).

    - Une couche d'affichage qui doit prendre la structure de données en question et l'afficher (en utilisant des points, des tirets, des couleurs, des espaces, bref que ça ressemble à quelque chose).

    Pour réaliser ce projet, je peux utiliser les langages assembleurs ou le langage C. Je n'ai le doit d'utiliser aucune API. Je dois m'adresser directement au matériel ou en utilisant des routines BIOS. Je dois rendre le projet sous forme de binaire exécutable sur win32 ou linux.

    N'ayant que des notions d'assembleur (hello world :/), je ne vois pas du tout comment entamer ce projet. Je me suis renseigné sur OsDev et j'ai plus ou moins compris le fonctionnement (utiliser deux boucles imbriqués qui parcourent les bus et les devices et vérifier pour chaque device/bus s'il existe et s'il a des functions). Mais je ne vois pas comment mettre ça en place d'un point de vue code.

    C'est pourquoi je m'adresse à vous pour recevoir un peu d'aide. Bien entendu, je ne demande pas de code pré-fait, je suis très motivé pour apprendre.

    Merci.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Salut, eh bien déjà ton programme devra être en 16-bits, de plus tu n'auras le droit d'utiliser que l'API du BIOS et les instructions in/out sont strictement interdites, car que ça soit Windows ou Linux, ils ne te laisseront pas le faire en user land (crash) ^^

    Ensuite pour ton problème, comme je ne me suis jamais attaqué à cette partie du kernel, je te conseille d'aller pêcher de l'aide en live sur l'irc d'osdev, freenode server, #osdev, car il n'y a pas beaucoup de programmeurs d'OS en France x)

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2014
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2014
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Je viens de visiter leur channel et c'est pas très actif malgré 250 personnes :/

  4. #4
    Invité
    Invité(e)
    Par défaut
    Euh non détrompe-toi, pour la plupart ce sont des Américains, donc décalage honoraire ^^

    Donc c'est très actif par moments, ça parle non-stop
    Patiente un peu ^^

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2014
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2014
    Messages : 25
    Points : 12
    Points
    12
    Par défaut
    Ah oui je suis con, j'avais complétement oublié ce détail :p

  6. #6
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 427
    Points : 43 044
    Points
    43 044
    Par défaut
    Si t'arrives à glaner des infos, ça m’intéresse, ce serait sympa de mettre dans le post.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Je me suis amusé à faire cela il y a trois ans, également. Le but était de partir complètement de zéro et de gravir les échelons pour atteindre un objectif donné à l'avance : gérer un de mes périphériques USB. En l'occurrence mon système audio 5.1 qui ne fonctionnait pas bien et que je voulais tripatouiller directement sans passer par l'OS pour avoir les infos qui m'intéressaient. C'était également un très bon sujet d'exercice. C'était en substance un programme assembleur bootable que j'ai fini par transcrire en PXE pour pouvoir démarrer par le réseau sur mon vieux laptop (donc une vraie machine, pas une VM) sans avoir à copier le code en langage machine sur une clé USB voire une disquette à chaque modification car ça devenait vite ingérable.

    Il a donc fallu écrire un à un les pilotes de chaque couche mais sans réécrire l'OS entier, c'est-à-dire sans définir d'API ni de couches d'abstraction, et en se restreignant à chaque fois au strict nécessaire. Je n'ai pas pu aller au bout parce que l'USB reste un monument en soi et parce que réécrire le pilote du hub représentait une quantité de travail qui n'en valait plus la chandelle, mais j'ai quand même fait quelques essais sur la carte réseau (une Intel 82.801 ICH3) et pour, cela, il a fallu piloter le bus PCI.

    OSDev a effectivement une page consacrée à cela. Concrètement, un périphérique PCI peut être mappé dans le plan mémoire conventionnel si nécessaire mais avant qu'il le soit, le bus PCI gère son propre espace d'adressage, dans lequel chaque périphérique occupe une des plages consécutives de 256 octets, qui doivent correspondre à un format spécial documenté dans la page en question. Pour y accéder, PCI n'utilise que 8 octets dans le plan conventionnel des entrées/sorties, soit en fait deux registres de 32 bits en cf8h et cfch. L'un sert à spécifier l'adresse dans le plan PCI, l'autre à y lire ou écrire une donnée. Et il se trouve que pour énumérer les périphériques en question, il suffit de lire le début de cettee plage, soit le premier mot de 32 bits à chaque fois, qui contient les vendor et product ids. S'ils sont différent de FFFFh, c'est qu'il y a quelque chose à cet emplacement.

  8. #8
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 427
    Points : 43 044
    Points
    43 044
    Par défaut
    Obsidian,

    Tu pourrais fournir le source ?

    Ce serait sympa et permettrait d'avoir une exemple concret.

    Merci d'avance.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Ça n'aurait pas beaucoup d'intérêt parce qu'en fait, c'est un projet qui se scinde en de nombreux modules. Il faudrait que je fasse une grosse archive ou que j'ouvre un dépôt Github pour un projet qui ne concernait que moi initialement. Par ailleurs, beaucoup du code en question était directement lié à la machine sur laquelle je travaillais : un Toshiba Satellite 2410-303 de 2003, environ (avec un P4 et une GeForce 4). Enfin, les tout premiers bootstraps sont 100 % assembleur, d'abord en 16 bits puis en 32, avec initialisation du mode protégé, etc. ce qui était très intéressant mais qui s'éloignait un peu du sujet.

    Enfin, très vite mon projet embraye sur le C. Là encore, c'était passionnant parce qu'il a fallu réimplémenter quelques fonctions de la bibliothèques standard, comme printf, puisque par définition celle-ci n'existe pas sur la cible. Et pour ce faire, il a également fallu réimplémenter une console en écrivant les caractères à la main dans la mémoire et en ajoutant des fonctions spéciales pour faire défiler l'écran quand on atteint la fin. Même cela n'était pas disponible. Cela m'a également poussé à ré-implémenter quelques codes Ecma-48 dont on avait parlé dans un autre fil.

    Toutefois, voici « pci.h » et « pci.c ».

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    /*
     *  pci.h       - Fonctions relatives à la gestion du bus PCI.
     *
     *                Obsidian, le ven. 12 oct. 2012 01:15:17 CEST
     */
     
    #ifndef PCI_H
    #define PCI_H
     
    #include <stdint.h>
     
    #define PCI_CONFIG_ADDRESS  (0xcf8)
    #define PCI_CONFIG_DATA     (0xcfc)
     
    typedef struct PCIInfos
    {
        uint16_t        device_id;
        uint16_t        vendor_id;
        uint16_t        status;
        uint16_t        command;
        uint32_t        class_code;
        uint8_t         revision_id;
    } PCIInfos;
     
    __attribute ((noinline))
    PCIInfos        PCIEnumerate    (uint8_t,uint8_t,uint8_t);
    uint32_t        PCIPeek         (uint32_t);
    int             PCIPoke         (uint32_t,uint32_t);
    uint32_t        PCIDevicePeek   (uint8_t,uint8_t,uint8_t,uint8_t);
    uint32_t        PCIDevicePoke   (uint8_t,uint8_t,uint8_t,uint8_t,uint32_t);
    uint32_t        PCIBDFToAddress (uint8_t,uint8_t,uint8_t,uint8_t);
     
    void            EnumPCIDevices              (void);
    void            MapEthernetInterface        (void);
    void            MapUSBInterface             (void);
     
     
    /*
        Toshiba Satellite 2410 - 303
        Périphériques PCI :
     
     0, 0: 8086:1a30 : 82845 845 [Brookdale] Chipset Host Bridge
     0, 1: 8086:1a31 : 82845 845 [Brookdale] Chipset AGP Bridge
     0,29: 8086:2482 : 82801CA/CAM USB Controller #1
     0,30: 8086:2448 : 82801 Mobile PCI Bridge
     1, 0: 10de:0175 : NV17 [GeForce4 420 Go]
     2, 7: 104c:8023 : TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx]
     2, 8: 8086:1031 : 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller
     2,11: 1179:0617 : ToPIC100 PCI to Cardbus Bridge with ZV Support
     2,13: 1179:0805 : SD TypA Controller
     
    */
                                                                                                                                                                          1,1          Haut
    #endif

    et :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    /*
     *  pci.c       - Fonctions relatives à la gestion du bus PCI.
     *
     *                Obsidian, le ven. 12 oct. 2012 01:15:17 CEST
     */
     
    #include "pci.h"
    #include "stdlib.h"
     
    __attribute ((noinline)) PCIInfos PCIEnumerate (uint8_t bus,uint8_t device,uint8_t function)
    {
        PCIInfos    infos;
        uint32_t    address;
        uint32_t    resultat;
     
        device      &= 0x1f;
        function    &= 0x07;
     
        /* Note: les bits 0 et 1 de l'offset sont toujours nuls,
         * nous obligeant à spécifier une adresse alignée sur 
         * un multiple de 32 bits. */
     
        /* Le bit 31 est le « Enable bit » pour les « configuration
         * cycles », nécessaire pour pouvoir lire l'espace du périphérique
         * à travers le port I/O et le configurer, comme un Chip Select.
         * (à relire). */
     
        /*  address = 0x80000000
                | ((uint32_t)bus      << 16) 
                | ((uint32_t)device   << 11)
                | ((uint32_t)function <<  8)
                | 0; */ /* Offset */
     
        address = PCIBDFToAddress (bus,device,function,0);
     
        resultat = PCIPeek (address);
     
        infos.device_id     = resultat >> 16;
        infos.vendor_id     = resultat & 0xffff;
     
        if (infos.device_id != 0xffff || infos.vendor_id != 0xffff)
        {
            address += 4;
            resultat = PCIPeek(address);
            infos.status        = resultat >> 16;
            infos.command       = resultat & 0xffff;
     
            address += 4;
            resultat = PCIPeek(address);
            infos.class_code    = resultat >> 8;
            infos.revision_id   = resultat & 0xff;
        }
     
        address &= 0x7fffff00;
        __asm ( "out %%eax,%%dx\n"
            :
            : "a" (address), "d" (PCI_CONFIG_ADDRESS)
            : );
     
        return infos;
    }
     
    uint32_t PCIPeek(uint32_t address)
    {
        uint32_t resultat;
     
        __asm ( "out %%eax,%%dx;\n"
            :
            : "a" (address), "d" (PCI_CONFIG_ADDRESS)
            : );
     
        __asm ( "in  %%dx,%%eax\n"
            : "=a" (resultat)
            : "d"  (PCI_CONFIG_DATA)
            : );
     
        return resultat;
    }
     
    int PCIPoke (uint32_t address,uint32_t value)
    {
        __asm ( "out %%eax,%%dx;\n"
            :
            : "a" (address), "d" (PCI_CONFIG_ADDRESS)
            : );
     
        __asm ( "out %%eax,%%dx;\n"
            :
            : "a" (value), "d" (PCI_CONFIG_DATA)
            : );
     
        return 0;
    }
     
    uint32_t PCIDevicePeek (uint8_t bus,uint8_t device,uint8_t function,uint8_t offset)
    {
        return PCIPeek (PCIBDFToAddress(bus,device,function,offset));
    }
     
    uint32_t PCIDevicePoke (uint8_t bus,uint8_t device,uint8_t function,uint8_t offset,uint32_t value)
    {
        return PCIPoke (PCIBDFToAddress(bus,device,function,offset),value);
    }
     
    uint32_t PCIBDFToAddress (uint8_t bus,uint8_t device,uint8_t function,uint8_t offset)
    {
        return     (uint32_t)0x80000000
                | ((uint32_t)bus      << 16) 
                | ((uint32_t)device   << 11)
                | ((uint32_t)function <<  8)
                |  (uint32_t)offset;
    }
     
    void EnumPCIDevices (void)
    {
        int x,y;
     
        printf ("PCI bus device enumeration:\n");
        for (x=0;x<256;++x) /* Bus */
        for (y=0;y<32 ;++y) /* Device */
        {
            PCIInfos infos;
     
            infos = PCIEnumerate (x,y,0);
     
            if (infos.device_id != 0xffff || infos.vendor_id != 0xffff)
            printf ("Bus %3d, Device %2d: %04x:%04x (class: 0x%02x, subclass 0x%04x, rev %3d)\n",
                     x,y,
                     infos.vendor_id, infos.device_id,
                     infos.class_code >> 16,
                     infos.class_code & 0xffff,
                     infos.revision_id);
        }
        printf ("PCI enumeration done.\n\n");
    }
     
    void MapEthernetInterface (void)
    {
        /* Spécifications Ethernet du Chipset Intel 82801CAM ICH3 */
        /* 29071601.pdf Section 7-6 */
        printf ("Mapping ethernet interface (\"2:8:0 8086:1031\") into memory.\n");
        PCIDevicePoke (2,8,0,0x10,0x00400000);  /* b32-12. Mem position */
        PCIDevicePoke (2,8,0,0x14,0x00004000);  /* b15-06. I/O position */
        printf ("Device now supposed to be mapped at 0x%08x.\n",0x400000);
    }
     
    void MapUSBInterface (void)
    {
        /* Spécifications Ethernet du Chipset Intel 82801CAM ICH3 */
        /* 29071601.pdf Section 5-16 */
        printf ("Mapping USB interface (\"0:29:0 8086:2482\") into memory.\n");
        PCIDevicePoke (0,29,0,0x10,0x00500000);  /* b32-12. Mem position */
        PCIDevicePoke (0,29,0,0x14,0x00005000);  /* b15-06. I/O position */
        printf ("Device now supposed to be mapped at 0x%08x.\n",0x500000);
    }

    La page citée ci-dessus précise qu'il y a deux manières de configurer les périphériques du port PCI : l'une, obsolète mais que j'utilise pourtant et qui n'utilise que deux ports 32 bits dans le plan I/O : CF8h et CFCh, soit en fait la plage de 8 octets s'étendant de CF8h à CFFh (deux fois 32 bits, donc). Ces ports s'appellent PCI_CONFIG_ADDRESS et PCI_CONFIG_DATA : on fait un « out » dans le premier pour dire quelle adresse dans plan de configuration on veut lire ou écrire, puis on lit ou écrit dans PCI_CONFIG_DATA. Comme on le voit, il y a :

    • 8 bits pour le numéro de bus ;
      5 bits pour le numéro de périphérique (soit 31 périphériques max par bus) ;
      3 bits pour le numéro de fonction du périphérique (de 0 à 7, donc) parce qu'il peut remplir plusieurs tâches distinctes à la fois, par exemple webcam + micro, qui doivent chacun être considérés comme des périphériques distincts ;
      6 bits pour le numéro de registre (de 00 à 3F, donc) correspondant aux registres hardware proprement dits et qui doivent correspondre à la table concernée


    Comme l'unité de mémoire est l'octet dans le plan mémoire ordinaire du x86, dans ses ports I/O et dans l'espace de configuration du bus PCI, mais que l'on fait des accès 32 au travers des ports de configuration, alors les adresses doivent toujours être alignées sur des multiples de 4 et, par conséquent, avoir leur deux bits de poids faible toujours à zéro.

    Le registre 00 (le premier mot 32 bits de configuration de chaque fonction) donne les vendor id et product id sur seize bits chacun, c'est-à-dire les fameux identifiants style « 8086:2940 » qui permettent d'identifier précisément un équipement indépendamment de sa dénomination commerciale. C'est en lisant ce mot et en vérifiant qu'il n'est pas vide (FFFFh:FFFFh) que l'on sait qu'il y a quelque chose à cet endroit.


    Cette procédure est marquée comme obsolète car comme le port PCI s'est démocratisé assez vite, on a réservé les ports I/O de C000h to CFFFh pour faire la même chose directement, sans avoir à passer à chaque fois par CF8h et CFCh pour indiquer où on souhaitait taper. En principe, quand on conçoit une machine, faire ce genre de chose est une hérésie (il est vital de rester aussi sobre que possible avec les ports I/O) mais comme tous les autres périphériques à venir sont censés venir se connecter ensuite au port PCI, on peut dire que c'est à eux qu'on les attribue en définitive et que ça se justifie.

  10. #10
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    17 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 17 427
    Points : 43 044
    Points
    43 044
    Par défaut
    Merci Obsidian,

    Je vais décanter ça quand j'aurais un peu de temps.

    Je comprend globalement le principe. Tu testes la présence d'un périphérique avec un adressage à 3 niveaux n°de bus, n° de périphérique, et n° de fonction pouvant être considéré comme numéro de service. Je pense qu'on peut savoir à quoi correspond tel ou tel périphérique par son identifiant, dispo dans un fichier .txt il me semble (je l'ai déjà vu mais me rappelle plus ) ou sinon ici :http://www.pcidatabase.com/reports.p...=tab-delimeted
    Je ne sais pas si on peut savoir facilement si il s'agit d'une carte video, d'une carte son, etc ...

    Cette procédure est marquée comme obsolète car comme le port PCI s'est démocratisé assez vite, on a réservé les ports I/O de C000h to CFFFh pour faire la même chose directement
    Là j'ai pas compris comment on passe de cf8h cffh et à C000h to CFFFh, ça sera peut-être plus clair en rentrant dans le truc.

    Il y a 8 bits pour le numéro de bus, il peut donc y avoir 256 bus ?
    pour tester la présence des équipements pci il faut scanner 256*31*3 adresses ?
    En ayant lu ton code en diagonale, ça semble être ce que tu fais dans la fonction EnumPCIDevices

    En tout cas merci pour le code.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Merci Obsidian,

    Je vais décanter ça quand j'aurais un peu de temps.

    Je comprend globalement le principe. Tu testes la présence d'un périphérique avec un adressage à 3 niveaux n°de bus, n° de périphérique, et n° de fonction pouvant être considéré comme numéro de service. Je pense qu'on peut savoir à quoi correspond tel ou tel périphérique par son identifiant, dispo dans un fichier .txt il me semble (je l'ai déjà vu mais me rappelle plus ) ou sinon ici :http://www.pcidatabase.com/reports.p...=tab-delimeted
    Absolument, et la base exhaustive existe forcément auprès du consortium PCI puisque les numéros sont réservés et attribués sur demande (et moyennant finance, bien sûr). Par contre, je ne sais pas si cette base est accessible au public. En principe, l'identifiant concerne uniquement le pilote qui, lui, renseigne le nom complet du périphérique s'il le trouve. Sauf que d'une part, beaucoup d'OS comme Linux proposent leurs propres pilotes et, d'autre part, il est intéressant de garder la trace d'un périphérique connu officiellement pour savoir de quoi il s'agit. Ne serait-ce que pour trouver le bon pilote, d'ailleurs.

    Du coup, Linux en particulier laisse le choix à celui qui le compile d'intégrer cette base directement dans le noyau ou de la déporter dans un fichier sur le FS.

    Je ne sais pas si on peut savoir facilement si il s'agit d'une carte video, d'une carte son, etc ...
    Si, parce que tout comme l'USB après lui, PCI a défini des classes de périphériques, qui sont détaillées toujours sur la même page.

    Là j'ai pas compris comment on passe de cf8h cffh et à C000h to CFFFh, ça sera peut-être plus clair en rentrant dans le truc.
    Ce sont deux plages complètement différentes : il y a 16 octets de 0CF8h à 0CFFh et 4096 octets de C000h à CFFFh.

    Je m'aperçois que j'ai dit une grosse ânerie : la page dit en fait que c'est cette deuxième méthode qui est dépréciée depuis au moins le Pentium 2. Donc il faut suivre le modèle que l'on a expliqué au départ et que j'ai suivi dans mon code.

    Il y a 8 bits pour le numéro de bus, il peut donc y avoir 256 bus ?
    Oui. En théorie.
    C'est nécessaire parce que tu peux chaîner les bus en cascade. Le pont qui permet de passer de l'un à l'autre est alors considéré comme un périphérique à part entière.

    pour tester la présence des équipements pci il faut scanner 256*31*3 adresses ?
    Non : 256×32×8, en réalité, soit 65536 emplacements. Ce qui reste à la portée du plus petit des ordinateurs.

    En ayant lu ton code en diagonale, ça semble être ce que tu fais dans la fonction EnumPCIDevices
    En effet.

    En tout cas merci pour le code.
    À ton service.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Différence entre les Endpoints du Bus PCI express
    Par Delaready dans le forum Embarqué
    Réponses: 2
    Dernier message: 31/01/2013, 01h44
  2. Envoyer/recevoir avec les bus USB, PCI, etc en Assembleur
    Par Lucas Panny dans le forum x86 32-bits / 64-bits
    Réponses: 10
    Dernier message: 05/01/2008, 15h38
  3. Réponses: 5
    Dernier message: 18/02/2005, 16h36
  4. Programmation du bus PCI
    Par mikevador02 dans le forum Assembleur
    Réponses: 8
    Dernier message: 11/03/2004, 14h56
  5. [TP] Gestion des bus PCI en pascal
    Par prodexys dans le forum Turbo Pascal
    Réponses: 12
    Dernier message: 18/04/2003, 22h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo