Vous êtes ici : Logram >> Les tutoriels >> Créer des pilotes

Créer des pilotes

Ca marche !
avatar
Auteur : steckdenis
Difficulté : 3/10
Date : le 14/09/2008 à 19:31

Commenter ce tutoriel

Le tutoriel que vous vous apprêtez à lire a été écrit par un bénévole, qui a mis à disposition gratuitement son savoir. Malgré le passage à la validation de ce tutoriel, nous ne pouvons garantir la véricité des informations contenues dedans. Merci de garder ceci à l'esprit pendant votre lecture
Bonjour,

Vous allez ici apprendre à créer vos propres pilotes. Ceci est vraiment un tutoriel, comparé aux autres, qui se rapprochent plus de la documentation. Vous allez apprendre de A à Z à créer un pilote.

Table des matières

  1. Qu'est qu'un pilote ?
  2. Les matériels ne se ressemblent pas : les classes de pilotes
  3. Un pilote, une extension
  4. Fonctions spécifiques aux pilotes
  5. Fonctions du pilote CHAR
  6. On y vas, codons !
  7. Exporter les fonctions nécessaires
  8. Un exemple complet : le pilote de disque

Qu'est qu'un pilote ?

Un pilote est une extension particulière au système qui lui permet de dialoguer avec un matériel spécial, comme par exemple une souris, une carte graphique, les haut-parleurs, la carte réseau.

Il y a deux moyens de créer des pilotes : créer une norme, ou une émulation. Quand on crée une norme, on dit par exemple que le pilote de disque doit retourner ceci quand on appelle cela, ou qu'une imprimante doit imprimer ceci quand on lui envoie cela. Une émulation est différente, et plus simple : on dit par exemple que le disque, même SCSI, doit se comporter comme s'il était IDE, qu'une imprimante, même Epson, doit se comporter comme une HP, et ainsi de suite.

Dans Logram, c'est l'émulation qui a été choisie. Par exemple, Logram adressera des données à un disque dur comme s'il était IDE, c'est à dire une adresse de secteur, et des données de 512 octets.

Les matériels ne se ressemblent pas : les classes de pilotes

Tous les matériels sont différents, mais on peut les classer suivant leur méthode de fonctionnement. Une souris n'est pas un écran, mais peut être assimilée à une tablette graphique. Une imprimante n'est pas un modem, etc.

Les pilotes ont donc été divisés en classe. Chaque classe de pilote fonctionne de manière différente, mais peut servir pour un certain nombre de matériel. Voici donc la liste des classes de pilotes sous Logram :



Maintenant que vous connaissez les lignes principales des pilotes, nous allons pouvoir commencer !

Un pilote, une extension

Une pilote est avant tout une extension.

Vous devez savoir créer une extension, même si c'est assez simple. Vous devez aussi savoir comment importer des fonctions, ou en exporter. Si vous n'avez pas tout compris, ce n'est rien, il ne faut que les bases, et je vais encore tout expliquer.

Nous allons donc créer notre petite extension qui contiendra une seule fonction : ExtMain(), la fonction d'entrée. Voici :

Code : c
  1. /* Mon premier pilote ! */
  2. #include <types.h>      // Types de Logram
  3. #include <logram.h>
  4. #include <drivers.h>    // Qui est aussi un pilote
  5.  
  6. // Déclaration des fonctions
  7.  
  8. /* Fonction ExtMain : l'entrée */
  9. int ExtMain (void *ext, void *kernAddr, void *efAddr, lint message, lint param)
  10. {
  11.     switch (msg)
  12.     {
  13.         case EXT_LOAD:
  14.             break;
  15.         case EXT_ATTACH:
  16.             break;
  17.         case EXT_DETACH:
  18.             break;
  19.         case EXT_CLOSE:
  20.             break;
  21.     }
  22.  
  23.     return 1;
  24. }
  25.  

Voilà, notre base d'extension est prête.

Fonctions spécifiques aux pilotes

Je vais tout de suite le dire : nous allons faire un pilote CHAR, car ils sont très faciles à faire.

Pour faire un pilote, il faut certaines fonctions spécifiques. Certaines fonctions sont communes à tous les pilotes, d'autres sont spécifiques à certaines classes.

Pour qu'un pilote soit pilote, il faut une chose : la structure Driver. Cette structure permet au système de connaître le pilote, et de lui parler.

N'oubliez donc pas de ne pas utiliser de fonction GDI ou dépendante d'autres pilotes, sauf si vous êtres sur qu'il sera chargé avant (vous pouvez utiliser le pilote de disque, ou FSL).

Voici donc la fameuse structure :

Code : c
  1. DEVICE  device =
  2.         {
  3.                 sizeof(DEVICE),
  4.                 DRIVERCLASS_CHAR,
  5.                 0,
  6.                 { /* Nom du pilote */ }
  7.         };

Fonctions du pilote CHAR

Je ne peux malheureusement pas lister toutes les fonctions de toutes les classes, car ce serait beaucoup trop long, et je ne sais même pas ce que je vais mettre dans certaines classes.

Voici donc les fonctions des pilotes CHAR:

Code : c
  1. char ReadChar();                                                //Lit un caractère (attention, c'est un octet, pas un caractère UNICODE. Il faut en lire deux pour avoir l'unicode).
  2. int  WriteChar(char c);                                         //Ecrit un caractère dans le flux
  3. int Seek(lint pos, lint orig);                                  //Se positionne dans le flux par rapport à orig. Ne fonctionne pas pour tous les pilotes (port série par exemple)
  4. char PeekChar();                                                //Lit aussi un caractère, mais n'avance pas dans le flux.
  5. void CloseDevice();                                             //Est appelée à l'arrêt du système. Le code de cette fonction peut servir à couper une connection, à vider des buffers, etc
  6. lint ioctl(int code, void *in, lint in, void *out, lint out);   //Gère le pilote (définis par exemple la vitesse de transmission).

On y vas, codons !

Voilà, vous savez tout. Nous allons maintenant coder l'extension.

Premièrement : préparer l'espace de travail. Nous allons donc aller dans le dossier drivers/ de Logram, et créer le dossier, par exemple, serial.ext.

Une fois cela fait, il va falloir créer 2 fichiers : serialcore.c et Makefile

Je donne le dernier, qui est court :

Makefile (il est un peu plus complexe) :

Code : Makefile
  1. OBJS = serial.o
  2. EXT = serial
  3. all: $(OBJS)
  4.         @echo "Building $(EXT).ext ..."
  5.         @$(LD) $(LDFLAGS) -e ExtMain -Tdata 0x0 -Ttext 0x1000 -o $(EXT).b $(OBJS)
  6.         @objcopy -R .note -R .comment -R .eh_frame -S -O binary $(EXT).b $(EXT).ext
  7.         @cp $(EXT).ext $(DESTDIR)/Logram/sys64/$(EXT).ext
  8. %.o: %.c
  9.         @$(CC) $(CFLAGS) -o $*.o $*.c
  10. %.o: %.s
  11.         @$(AS) $(ASMFLAGS) -o $*.o $*.s
  12. clean:
  13.         @rm -f *.b
  14.         @rm -f *.o
  15.         @rm -f *.ext

Après, il faut modifier le Makefile parent au notre afin que le compilateur n'oublie pas de rentrer dans notre dossier de pilote. Ajoutez dans la partie "all:" : "@(cd serial.ext && $(MAKE))" et dans la partie "clean:" : "@(cd serial.ext && $(MAKE) clean)". Attention, il ne faut pas oublier les tabulations sinon le Makefile planterait !

Et il ne faut pas oublier de modifier les fichier logram/disk/Logram/sys64/drivers/__dircontents et logram/disk/Logram/sys64/drivers/drivers.lst afin que le driver soit reconnu plus tard par le kernel. Pour les modifier, il suffit d'incrémenter le premier nombre de chaque fichier puis d'ajouter à la suite des noms des autres fichiers "serial.ext".


Voilà, nous avons nos fichiers indispensables. Maintenant, nous pouvons créer l'extension.

Voici un exemple de driver :

Code : c
  1. // Inclusions
  2. #include <types.h>
  3. #include <logram.h>
  4. #include <driver.h>
  5.  
  6.  
  7.  
  8. //En-tête du fichier d'extension
  9.  
  10. exports exps[];
  11. section sections[];
  12. void    *nxtDrv;
  13. DEVICE  device;
  14.  
  15. resext head =
  16.         {
  17.                 sizeof(resext),
  18.                 MAGIC_EXT,
  19.                 exps,
  20.                 sections
  21.         };
  22.  
  23. exports exps[] =
  24.         {
  25.                 {&amp;ExtMain, L"ExtMain"},
  26.                 {&amp;nxtDrv, L"NextDriver"},
  27.                 {&amp;device, L"DriverStruct"},
  28.                 { 0, 0}                                         //Fin des exportations
  29.         };
  30.  
  31. section sections[] =
  32.         {
  33.                 { 0, 0x1000, SECTION_DATA },                    //Données
  34.                 { (void *) 0x1000, 0x1000, SECTION_CODE },      //Code
  35.                 { 0, 0, 0}                                      //Section de fin
  36.         };
  37.  
  38. void    *nxtDrv = (void*) 0;
  39.  
  40. DEVICE  device =
  41.         {
  42.                 sizeof(DEVICE),
  43.                 DRIVERCLASS_MISC,
  44.                 0,
  45.                 {0,0}
  46.         };
  47.  
  48. /* Code du fichier */
  49.  
  50. int ExtMain (void *ext, void *kernAddr, void *efAddr, lint message, lint param)
  51. {
  52.         switch (message)
  53.         {
  54.                 case EXT_LOAD:
  55.                         //On a chargé l'extension à partir du disque
  56.                         break;
  57.  
  58.                 case EXT_ATTACH:
  59.                         //On a attaché l'extension à un processus
  60.                         break;
  61.  
  62.                 case EXT_DETACH:
  63.                         //On a détaché l'extension d'un processus
  64.                         break;
  65.  
  66.                 case EXT_CLOSE:
  67.                         //On a déchargé l'extension de la mémoire
  68.                         break;
  69.         }
  70.  
  71.         return 1;       //Tout marche !
  72. }

Voilà, nous avons les bases.

Exporter les fonctions nécessaires

Voilà, vous avez un beau fichier source, mais qui ne fait rien. :(

Nous devons maintenant rajouter l'exportation des fonctions.

Premièrement, créer ces fonctions. Pour cela, rien de plus simple : rajouter ceci à la fin de notre fichier :

Code : c
  1. char ReadChar(){
  2.  
  3. }
  4.  
  5. int  WriteChar(char c){
  6.  
  7. }
  8.  
  9. int Seek(lint pos, lint orig){
  10.  
  11. }
  12.  
  13. char PeekChar(){
  14.  
  15. }
  16.  
  17. void CloseDevice(){
  18.  
  19. }
  20.  
  21. lint ioctl(int code, void *in, lint uin, void *out, lint uout){
  22.  
  23. }

Ces fonctions ne servent qu'à utiliser une adresse en mémoire. Vous pouvez rajouter dedans "kprintf("le nom de la fonction", 0x07);", pour voir ce qui est appelé.

Maintenant que les fonctions existent, il faut les exporter. Pour cela, il suffit de remplir le tableaux exps[], qui contient normalement déjà quelques exportations.

Code : c
  1. //Exportations
  2. exports exp[] = {
  3.         /* Exportations en place */
  4.         {&amp;ReadChar, L"ReadChar"},
  5.         {&amp;WriteChar, L"WriteChar"},
  6.         {&amp;Seek, L"Seek"},
  7.         {&amp;PeekChar, L"PeekChar"},
  8.         {&amp;CloseDevice, L"CloseDevice"},
  9.  
  10.         {0, 0}
  11. };

Attention à ne pas oublier le "{0, 0}" après les nom et adresses des fonctions à exporter, car cela permet de signaler la fin du tableau.

Voilà, nos fonctions sont exportées, plus qu'à les remplir.

Un exemple complet : le pilote de disque

Si tout ceci a été flou, voici un bon résumé, le pilote IDE, un pilote Block. Il est un peu complexe, et je ne vais pas tout détailler, c'est juste pour voir où doivent se trouver les différents éléments.

Code : c
  1. /*
  2.  * idecore.c
  3.  * This file is part of Logram
  4.  *
  5.  * Copyright (C) 2008 - Denis Steckelmacher
  6.  *                    - Bruno Régaldo
  7.  *
  8.  * Logram is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * Logram is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with Logram; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin St, Fifth Floor,
  21.  * Boston, MA  02110-1301  USA
  22.  */
  23.  
  24. /*
  25.         Fichier principal du pilote ide.ext.
  26.         Ce pilote est chargé de gérer les accès sur les disques durs IDE.
  27. */
  28.  
  29. // Inclusions
  30. #include <types.h>
  31. #include <logram.h>
  32. #include <driver.h>
  33. #include <asm.h>
  34. #include <drivers/ide_driver.h>
  35.  
  36. #include "ide.h"
  37.  
  38. // Variables globales
  39. exports exps[];
  40. section sections[];
  41. void    *nxtDrv;
  42. DEVICE  device;
  43.  
  44. //Prototypes
  45.  
  46. void    DetectDrives(void *ext);
  47.  
  48. //En-tête
  49.  
  50. resext head =
  51.         {
  52.                 sizeof(resext),
  53.                 MAGIC_EXT,
  54.                 exps,
  55.                 sections
  56.         };
  57.  
  58. exports exps[] =
  59.         {
  60.                 {&amp;ExtMain,  L"ExtMain"},
  61.                 {&amp;nxtDrv,   L"NextDriver"},
  62.                 {&amp;device,   L"DriverStruct"},
  63.                 {&amp;ReadBlock,        L"ReadBlock"},
  64.                 {&amp;WriteBlock,       L"WriteBlcok"},
  65.                 { 0, 0}                                         //Fin des exportations
  66.         };
  67.  
  68. section sections[] =
  69.         {
  70.                 { 0, 0x1000, SECTION_DATA },                    //Données
  71.                 { (void *) 0x1000, 0x1000, SECTION_CODE },      //Code
  72.                 { 0, 0, 0}                                      //Section de fin
  73.         };
  74.        
  75. void    *nxtDrv = (void *) 0;
  76.  
  77. DEVICE  device =
  78.         {
  79.                 sizeof(DEVICE),
  80.                 DRIVERCLASS_BLOCK,
  81.                 2,
  82.                 { L'I', L'D', L'E', 0, 0, 0, 0, 0 }
  83.         };
  84.        
  85. /* Importations */
  86.  
  87. void*   (*FindDriver)   (lchar *nom);
  88. void*   (*ExtFind)      (void *ext, lchar *nom);
  89. void    (*kprintf)      (char *str, char attr);
  90.  
  91. void    (*addVol)       (void *ReadBlock, void *WriteBlock, int device);
  92.  
  93. /* Variables globales */
  94.  
  95. void    *Volume = (void *) 0;   //Adresse de volume.ext
  96.        
  97. // Fonction principale de l'extension
  98. int ExtMain (void *ext, void *kernAddr, void *efAddr, lint message, lint param)
  99. {
  100.         switch (message)
  101.         {
  102.                 case EXT_LOAD:
  103.                         //Détecter les disques et les enregistrer dans volume.ext
  104.                         ExtFind = efAddr;
  105.                         FindDriver = ExtFind(kernAddr, STRING(ext, L"FindDriver"));
  106.                         kprintf = ExtFind(kernAddr, STRING(ext, L"kprintf"));
  107.                        
  108.                         Volume = FindDriver(STRING(ext, L"VOLUME"));
  109.                        
  110.                         addVol = ExtFind(Volume, STRING(ext, L"AddVolume"));
  111.                        
  112.                         //Détecter les disques
  113.                         DetectDrives(ext);
  114.                         break;
  115.                 case EXT_ATTACH:
  116.                         //On a attaché l'extension à un processus
  117.                         break;
  118.                 case EXT_DETACH:
  119.                         //On a détaché l'extension d'un processus
  120.                         break;
  121.                 case EXT_CLOSE:
  122.                         //On a déchargé l'extension de la mémoire
  123.                         break;
  124.         }
  125.         return 1;
  126. }
  127.  
  128. void    DetectDrives(void *ext)
  129. {
  130.         int i, j, portControl, port;
  131.         unsigned char a, b, byte1, byte2, status;
  132.        
  133.         // Tester les ports IDE
  134.         for (i = 0; i < 4; i++)
  135.         {
  136.                 a = 0;
  137.                 b = 0;
  138.                
  139.                 // Déterminer quel port sera utilisé pour cette itération
  140.                 if (i == 0) { port = 0x1F0; portControl = 0x3F0; }
  141.                 if (i == 1) { port = 0x170; portControl = 0x370; }
  142.                 if (i == 2) { port = 0xF0; portControl = 0x2F0; }
  143.                 if (i == 3) { port = 0x70; portControl = 0x270; }
  144.  
  145.                 // Regarde si le contrôleur est présent
  146.                 char byte1 = inb (port + 6);
  147.                 char byte2 = (byte1 &amp; 0x10) >> 4;
  148.                 if(byte2 == 0)
  149.                 {
  150.                         byte1 |= 0x10;
  151.                         outb(port + 6, byte1);
  152.                 }
  153.                 else
  154.                 {
  155.                         byte1 = byte1 &amp; 0xEF;
  156.                         outb(port + 6, byte1);
  157.                 }
  158.                 byte1 = inb(port + 6);
  159.                 byte1 = (byte1 &amp; 0x10) >> 4;
  160.                 if(byte1 != byte2)
  161.                 {
  162.                         //Le contrôleur existe
  163.                        
  164.                         //Voir si le disque maitre existe
  165.                         outb(port + 6, 0xa0);   //Master
  166.                         outb(port + 7, 0xec);   //Commande d'indentification
  167.                         for (j = 0; j < 30000; j++)
  168.                         {
  169.                                 status = inb(port + ATA_STATUS);
  170.                                 if(!(status &amp; ATA_S_BSY))
  171.                                 {
  172.                                         //Le disque existe, l'ajouter
  173.                                         for (j=0;j<256;j++) inw(port + ATA_DATA); //On ne s'en sert pas
  174.                                                
  175.                                         //On ajoute
  176.                                         addVol(STRING(ext, &amp;ReadBlock), STRING(ext, &amp;WriteBlock), i*2);
  177.                                        
  178.                                         goto disksuiv;
  179.                                 }
  180.                                 iowait();
  181.                         }
  182.                        
  183.                         disksuiv:
  184.                        
  185.                         //Voir si le disque esclave existe
  186.                         outb(port + 6, 0xb0);   //Master
  187.                         outb(port + 7, 0xec);   //Commande d'indentification
  188.                         for (j = 0; j < 30000; j++)
  189.                         {
  190.                                 status = inb(port + ATA_STATUS);
  191.                                 if(!(status &amp; ATA_S_BSY))
  192.                                 {
  193.                                         //Le disque existe, l'ajouter
  194.                                         for (j=0;j<256;j++) inw(port + ATA_DATA); //On ne s'en sert pas
  195.                                                
  196.                                         //On ajoute
  197.                                         addVol(STRING(ext, &amp;ReadBlock), STRING(ext, &amp;WriteBlock), (i*2)+1);
  198.                                        
  199.                                         goto finverif;
  200.                                 }
  201.                                 iowait();
  202.                         }
  203.                        
  204.                         finverif: ;
  205.                 }
  206.         }
  207. }
  208.  
  209. // Fonction ReadBlock qui permet la lecture d'un secteur sur le disque
  210. // Paramètres : - int device : permet la sélection du bon disque
  211. //              - lint block : numéro de secteur à lire
  212. //              - void *buf  : buffer de sortie qui contiendra la lecture du secteur
  213. lint    ReadBlock(int device, lint block, void *buf) {
  214.         unsigned char cyl_lo, cyl_hi, sect, head, status;
  215.         int devselect, i, timeout;
  216.         int16 *buffer;
  217.         int16 port; // Port du contrôleur
  218.  
  219.         if (device&amp;1) { // On veut le disque esclave
  220.                 devselect = ATA_D_SLAVE;
  221.         } else {        // On veut le disque maître
  222.                 devselect = ATA_D_MASTER;
  223.         }
  224.  
  225.         if (device&amp;2) { // On veut le second contrôleur IDE
  226.                 port = 0x170;
  227.         } else {        // On veut le premier contrôleur IDE
  228.                 port = 0x1F0;
  229.         }
  230.  
  231.         // Initialise le contrôleur
  232.         outb(port + ATA_DEVICE_CONTROL, ATA_A_nIEN | ATA_A_4BIT);
  233.         iowait();
  234.  
  235.         // Convertit l'adresse LBA en adresse CHS
  236.         sect   = (block &amp; 0xff);
  237.         cyl_lo = (block >> 8) &amp; 0xff;
  238.         cyl_hi = (block >> 16) &amp; 0xff;
  239.         head   = ((block >> 24) &amp; 0x7) | 0x40;
  240.  
  241.         // Sélectionne le disque
  242.         outb(port + ATA_DRIVE, ATA_D_IBM | devselect);
  243.         iowait();
  244.  
  245.         // Positionne le disque pour la lecture
  246.         outb(port + ATA_DEVICE_CONTROL, ATA_A_4BIT);
  247.         outb(port + ATA_ERROR, 1);
  248.         outb(port + ATA_PRECOMP, 0);
  249.         outb(port + ATA_SECTOR_COUNT, 1);
  250.         outb(port + ATA_SECTOR_NUMBER, sect);
  251.         outb(port + ATA_CYL_LSB, cyl_lo);
  252.         outb(port + ATA_CYL_MSB, cyl_hi);
  253.         outb(port + ATA_DRIVE, (ATA_D_IBM | devselect | head));
  254.  
  255.         // On envoie la commande de lecture
  256.         outb(port + ATA_CMD, ATA_C_READ);
  257.  
  258.         // Attend la disponibilité du contrôleur
  259.         for(timeout = 0; timeout < 30000; timeout++) {
  260.                 status = inb(port + ATA_STATUS);
  261.                 if(!(status &amp; ATA_S_BSY))
  262.                         break;
  263.  
  264.                 iowait();
  265.         }
  266.        
  267.         // Récupère la lecture du disque
  268.         buffer = (int16 *) buf;
  269.         for (i = 0; i<256; i++) buffer[i] = inw(port + ATA_DATA);
  270.  
  271.         return 0; // Pas d'erreur
  272. }
  273.  
  274. // Fonction WriteBlock qui permet d'écrire un secteur sur le disque
  275. // Paramètres : - int device : permet la sélection du bon disque
  276. //              - lint block : numéro de secteur spécifiant l'emplacement de l'écriture
  277. //              - void *buf  : buffer contenant ce qu'il devra être écrit
  278. lint    WriteBlock(int device, lint block, void *buf) {
  279.         unsigned char cyl_lo, cyl_hi, sect, head, status;
  280.         int devselect, i, timeout;
  281.         int16 *buffer;
  282.         int16 port; // Port du contrôleur
  283.  
  284.         if (device&amp;1) { // On veut le disque esclave
  285.                 devselect = ATA_D_SLAVE;
  286.         } else { // On veut le disque maître
  287.                 devselect = ATA_D_MASTER;
  288.         }
  289.  
  290.         if (device&amp;2) { // On veut le second contrôleur IDE
  291.                 port = 0x170;
  292.         } else { // On veut le premier contrôleur IDE
  293.                 port = 0x1F0;
  294.         }
  295.  
  296.         // Initialise le contrôleur
  297.         outb(port + ATA_DEVICE_CONTROL, ATA_A_nIEN | ATA_A_4BIT);
  298.         iowait();
  299.  
  300.         // Convertit l'adresse LBA en adresse CHS
  301.         sect   = (block &amp; 0xff);
  302.         cyl_lo = (block >> 8) &amp; 0xff;
  303.         cyl_hi = (block >> 16) &amp; 0xff;
  304.         head   = ((block >> 24) &amp; 0x7) | 0x40;
  305.  
  306.         // Sélectionne le disque
  307.         outb(port + ATA_DRIVE, ATA_D_IBM | devselect);
  308.         iowait();
  309.  
  310.         // Positionne le disque pour la lecture
  311.         outb(port + ATA_DEVICE_CONTROL, ATA_A_4BIT);
  312.         outb(port + ATA_ERROR, 1);
  313.         outb(port + ATA_PRECOMP, 0);
  314.         outb(port + ATA_SECTOR_COUNT, 1);
  315.         outb(port + ATA_SECTOR_NUMBER, sect);
  316.         outb(port + ATA_CYL_LSB, cyl_lo);
  317.         outb(port + ATA_CYL_MSB, cyl_hi);
  318.         outb(port + ATA_DRIVE, (ATA_D_IBM | devselect | head));
  319.  
  320.         // Envoie au contrôleur la commande d'écriture
  321.         outb(port + ATA_CMD, ATA_C_WRITE);
  322.  
  323.         // Attend que la disponibilité du contrôleur
  324.         for(timeout = 0; timeout < 30000; timeout++) {
  325.                 status = inb(port + ATA_STATUS);
  326.                 if(!(status &amp; ATA_S_BSY))
  327.                         break;
  328.  
  329.                 iowait();
  330.         }
  331.        
  332.         // On écrit les données sur le disque
  333.         buffer = (int16 *) buf;
  334.         for (i = 0; i<256; i++) outw(port + ATA_DATA, buffer[i]);
  335.  
  336.         return 0; // Pas d'erreur
  337. }

Je vous félicite, vous êtes arrivé à la fin :p !
Ca marche !
avatar

Retour en haut

Auteur : steckdenis
Difficulté : 3/10
Date : le 14/09/2008 à 19:31

Commenter ce tutoriel