[Programmation d'un OS] Pourquoi mon transfert DMA ne se fait pas ?

Pourquoi mon transfert DMA ne se fait pas ? [Programmation d'un OS] - C++ - Programmation

Marsh Posté le 13-12-2002 à 15:34:15    

Salut...
 
Je réalise un système d'exploitation en mode protégé, et j'ai jarté toutes les fonctions du BIOS. Je dois donc reprogrammer les fonctions de lecture sur le lecteur de disquette. J'ai les commandes à envoyer au lecteur de disquettes, et je le fais avec le DMA. J'ai tout programmé, et ça ne marche pas, je ne sais pas pk...
 
Je vous montre les sources, si vous pouviez m'éclaircir sur le sujet...
 

Code :
  1. // Fonctions pour le DMA
  2. /* Quick-access registers and ports for each DMA channel. */
  3. unsigned char MaskReg[8]   = { 0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4 };
  4. unsigned char ModeReg[8]   = { 0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6 };
  5. unsigned char ClearReg[8]  = { 0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8 };
  6. unsigned char PagePort[8]  = { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A };
  7. unsigned char AddrPort[8]  = { 0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC };
  8. unsigned char CountPort[8] = { 0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE };
  9. void _dma_xfer(unsigned char DMA_channel, unsigned char page, unsigned int offset, unsigned int length, unsigned char mode);
  10. //extern unsigned long _virt_to_phys;
  11. void dma_xfer(unsigned char channel, unsigned long address, unsigned int length, unsigned char read)
  12. {
  13. //   address += _virt_to_phys;
  14. unsigned char page=0, mode=0;
  15. unsigned int offset = 0;
  16. if(read)
  17.  mode = 0x48 + channel;
  18. else
  19.  mode = 0x44 + channel;
  20. page = address >> 16;
  21. offset = address & 0xFFFF;
  22. length--;
  23. _dma_xfer(channel, page, offset, length, mode);
  24. }
  25. void _dma_xfer(unsigned char DMA_channel, unsigned char page, unsigned int offset, unsigned int length, unsigned char mode)
  26. {
  27.     /* Don't let anyone else mess up what we're doing. */
  28.     //asm("cli" );
  29.   cli;
  30.     /* Set up the DMA channel so we can use it.  This tells the DMA */
  31.     /* that we're going to be using this channel.  (It's masked) */
  32.     outb(MaskReg[DMA_channel], 0x04 | DMA_channel);
  33.     /* Clear any data transfers that are currently executing. */
  34.     outb(ClearReg[DMA_channel], 0x00);
  35.     /* Send the specified mode to the DMA. */
  36.     outb(ModeReg[DMA_channel], mode);
  37.     /* Send the offset address.  The first byte is the low base offset, the */
  38.     /* second byte is the high offset. */
  39.     outb(AddrPort[DMA_channel], LOW_BYTE(offset));
  40.     outb(AddrPort[DMA_channel], HI_BYTE(offset));
  41.     /* Send the physical page that the data lies on. */
  42.     outb(PagePort[DMA_channel], page);
  43.     /* Send the length of the data.  Again, low byte first. */
  44.     outb(CountPort[DMA_channel], LOW_BYTE(length));
  45.     outb(CountPort[DMA_channel], HI_BYTE(length));
  46.     /* Ok, we're done.  Enable the DMA channel (clear the mask). */
  47.     outb(MaskReg[DMA_channel], DMA_channel);
  48.     /* Re-enable interrupts before we leave. */
  49.     sti;
  50. }
  51. //Fonctions pour le lecteur de disquettes
  52. #define FD_DMA 0x8000
  53. unsigned int flp=0x3F0; // Base des ports du controleur de disquettes
  54. unsigned char motorp = 2;
  55. unsigned char op_seek = 0x0F;
  56. unsigned char cur_head=0;
  57. unsigned char cur_track=0;
  58. unsigned char cur_cyl=0;
  59. unsigned char zero=0;
  60. unsigned char mask;
  61. unsigned int sr0;
  62. unsigned int current_track;
  63. unsigned char done=0;
  64. unsigned char status[7];
  65. unsigned short int nb_stat;
  66. void floppy_irq(void)
  67. {
  68. done=1;
  69. //outb(0x20,0x20);
  70. }
  71. int fd_out(unsigned char val)
  72. {
  73.    unsigned int c=128;
  74.    do {
  75.       if( (inb(0x3f4) & 0xc0) == 0x80 )
  76. {
  77.    outb(0x3f5, val);
  78.    return 0;
  79. }
  80.    } while(c--);
  81.    return -1;
  82. }
  83. unsigned int fd_in(void)
  84. {
  85.    unsigned int c=128;
  86.    do {
  87.       if( (inb(0x3f4) & 0xc0) == 0xc0 )
  88. return inb(0x3f5);
  89.    } while(c--);
  90.    return -1;
  91. }
  92. int get_status(int check)
  93. {
  94. unsigned char tmp;
  95. unsigned int i;
  96. debug (1, "GET_STATUS\n" );
  97. i=1000;
  98. while (!done && i)
  99. {
  100.  delay(10);
  101.  i--;
  102. }
  103. /*print("\n" );
  104. printNb(i);
  105. print("\n" );*/
  106. if (i==0)
  107. {
  108.  print("FAILED TO GET STATUS\n" );
  109.  return -1;
  110. }
  111. nb_stat=0;
  112. while (nb_stat<9 && (inb(0x3f4)) & (1<<4))
  113. {
  114.  status[nb_stat++] = inb(0x3f5);
  115. }
  116. /*for(i=0; i<nb_stat; i++)
  117. {
  118.  print("st" );
  119.  printNb(i);
  120.  print("=" );
  121.  printNb(status[i]);
  122.  print(" ; " );
  123. }
  124. print("\n" );*/
  125. if (!check)
  126.  return;
  127. if (fd_out(0x08)!=-1) //check interrupt status
  128. {
  129.  sr0=fd_in();
  130.  current_track=fd_in();
  131. }
  132. done=0;
  133. }
  134. void seek(unsigned int track)
  135. {
  136. debug(1, "SEEK\n" );
  137. fd_out(0x0f);
  138. fd_out(zero);
  139. fd_out(track);
  140. delay(15);
  141. get_status(1);
  142. /*print("sr0=" ); printNb(sr0);
  143. print("\n" );*/
  144. }
  145. void moteur(int etat) //détermine l'état du moteur du lecteur A
  146. {
  147. debug(1, "MOTOR " );
  148. /*if (etat==0 || etat==1)
  149. {
  150.  mask = etat * 0x10;
  151.  outbp(0x3f2, mask|0x0C);
  152. }*/
  153. if(etat==0)
  154. {
  155.  debug(1,"OFF\n" );
  156.  outb(0x3F2, 0);
  157. }
  158. if(etat==1)
  159. {
  160.  debug(1,"ON\n" );
  161.  outb(0x3F2, 0x1C);
  162. }
  163. }
  164. void reset() //reset du lecteur A
  165. {
  166. debug (1, "RESET\n" );
  167. outb(0x3f2,0);
  168. outb(0x3f4,0);
  169. outb(0x3f2,0x0c);
  170. done=1;
  171. get_status(1);
  172. fd_out(0x03);
  173. fd_out(0xdf);     // SRT = 3ms, HUT = 240ms
  174. fd_out(0x02);     // HLT = 16ms, ND = 0
  175. seek(1);
  176. }
  177. void recalibrate()
  178. {
  179. debug (1, "RECALIBRATE\n" );
  180. moteur(1);
  181. // send actual command bytes
  182. fd_out(0x07);
  183. fd_out(0);
  184. // wait until seek finished
  185. get_status(1);;
  186. // turn the motor off
  187. moteur(0);
  188. }
  189. int read_one_sector(unsigned char head, unsigned char track, unsigned char sect, char * out)
  190. {
  191. debug(1,"READ\n" );
  192. moteur(1);
  193. seek(track);
  194. outb(0x3f7,0);
  195. dma_xfer(2, FD_DMA, 512, 0);
  196. if(fd_out(0xe6)==-1)      // commande de lecture
  197. {
  198.  print("1:Sending command failed\n" );
  199.  return;
  200. }
  201. if(fd_out(head << 2)==-1) //tête
  202. {
  203.  print("2:Sending command failed\n" );
  204.  return;
  205. }
  206. if(fd_out(track)==-1)       //cyl
  207. {
  208.  print("3:Sending command failed\n" );
  209.  return;
  210. }
  211. if(fd_out(head)==-1)      //tête
  212. {
  213.  print("4:Sending command failed\n" );
  214.  return;
  215. }
  216. if(fd_out(sect)==-1)      //secteur
  217. {
  218.  print("5:Sending command failed\n" );
  219.  return;
  220. }
  221. if(fd_out(2)==-1)         //octets/secteur / 128
  222. {
  223.  print("6:Sending command failed\n" );
  224.  return;
  225. }
  226. if(fd_out(18)==-1)        // 18 secteurs/piste
  227. {
  228.  print("7:Sending command failed\n" );
  229.  return;
  230. }
  231. if(fd_out(0x1d)==-1)      // la taille du GAP 3 en lecture/écriture
  232. {
  233.  print("8:Sending command failed\n" );
  234.  return;
  235. }
  236. if(fd_out(0xFF)==-1)         //longueur des données si cmd byte 5=0)
  237. {
  238.  print("9:Sending command failed\n" );
  239.  return;
  240. }
  241. get_status(1);
  242. memcpy(out, FD_DMA, 512);
  243. moteur(0);
  244. return 0;
  245. }

 
Merci
 :hello:


Message édité par robotniktareum le 13-12-2002 à 21:15:45

---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 13-12-2002 à 15:34:15   

Reply

Marsh Posté le 13-12-2002 à 21:16:09    

up please...


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 13-12-2002 à 21:20:28    

:ouch:

Reply

Marsh Posté le 13-12-2002 à 21:21:57    

c la qu'on se sent petit petit.... (up deguise)

Reply

Marsh Posté le 13-12-2002 à 21:22:31    

jfait la meme en php [:mlc]

Reply

Marsh Posté le 13-12-2002 à 21:29:00    

donc y'a personne qui sait ici !?  :sweat:


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 14-12-2002 à 01:18:22    

J'ai souvenir d'une très vielle limitation du DMA ( à l'époque ou je me suis codé mes drivers de carte SoundBlaster sur un 486 sous DOS :D ). En gros, la bande mémoire sur lequel le DMA agit devait se trouver sur une seule page mémoire. Je n'ai aucune idée si ce genre de limitation agit encore.
 
Sinon, quand on touche à des choses si bas niveau, c'est normal qu'il y ait des difficultées. Regarde le code source d'un noyau Linux ou BSD si tu en as le courage. Ca doit pouvoir t'aider quand même.

Reply

Marsh Posté le 14-12-2002 à 02:49:02    

Ben, heuh... je suis comme largué sur ce coup-là.
Tu essayes de remonter le niveau du forum après la vague des 'exercice, comprends po' ?
 
 
Peut-être que tout ce code gagnerait à utiliser des énumérations et un peu d'objet.
 
Just un truc qui me chiffone:

Code :
  1. void _dma_xfer(unsigned char DMA_channel, unsigned char page, unsigned int offset, unsigned int length, unsigned char mode)
  2. {
  3. cli;
  4. //...
  5. sti;
  6. }


C'est symbolique ?
Parce que ça ne peut pas avoir d'effet...


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 14-12-2002 à 07:20:47    

Kristoph a écrit :

J'ai souvenir d'une très vielle limitation du DMA ( à l'époque ou je me suis codé mes drivers de carte SoundBlaster sur un 486 sous DOS :D ). En gros, la bande mémoire sur lequel le DMA agit devait se trouver sur une seule page mémoire. Je n'ai aucune idée si ce genre de limitation agit encore.
 
Sinon, quand on touche à des choses si bas niveau, c'est normal qu'il y ait des difficultées. Regarde le code source d'un noyau Linux ou BSD si tu en as le courage. Ca doit pouvoir t'aider quand même.

Effectivement, les transferts DMA doivent se faire dans le 1er Mo de la RAM, et c'est toujours d'actualité !!!! Mais ça n'est pas un problème vu que je l'ai mis en 0x8000... Ou alors, je me suis planté qq part. En fait, une vois que tout s'est bien passé, le lecteur de disquettes doit m'envoyer l'IRQ6. Apparemment, à partir d'un débogage avec bochs, la commande de lecture est bien envoyée au floppy, mais le dma ne semble pas avoir reçu de données, ce qui me laisse supposer que si le transfert des données n'a pas pu se faire, le floppy ne renvoie pas l'IRQ. Tu as encore tes drivers pour ton 486 sur toi ? Sinon, je mate les srcs de minix, linux 0.9, et divers OS, et je ne vois rien ki chie... Si qqn veut les srcs complètes de l'OS pour voir d'un peu plus prêt, je suis prêt à lui envoyer...
Merci :hello:


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 14-12-2002 à 07:26:03    

Musaran a écrit :

Ben, heuh... je suis comme largué sur ce coup-là.
Tu essayes de remonter le niveau du forum après la vague des 'exercice, comprends po' ?
 
 
Peut-être que tout ce code gagnerait à utiliser des énumérations et un peu d'objet.
 
Just un truc qui me chiffone:

Code :
  1. void _dma_xfer(unsigned char DMA_channel, unsigned char page, unsigned int offset, unsigned int length, unsigned char mode)
  2. {
  3. cli;
  4. //...
  5. sti;
  6. }


C'est symbolique ?
Parce que ça ne peut pas avoir d'effet...

bah il faut bien remonter le niveau... Je voyais ke le forum courait à sa perte :D
Sinon cette fonction a un effet : j'indique au controleur DMA ce qu'il doit faire, et ça se fait par une succession d'écritures sur les ports du contrôleur. Je lui indique si il doit lire ou écrire, sur quel canal il doit travailler, quel endroit en mémoire il doit utiliser, ... Ce code me semble correct, car je l'ai trouvé sur des cours : http://www.nondot.org/sabre/os/articles
bon je v en cours... Ad'taleur


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 14-12-2002 à 07:26:03   

Reply

Marsh Posté le 14-12-2002 à 11:18:12    

Code :
  1. while (!done && i)
  2.      {
  3.         delay(10);
  4.         i--;
  5.      }


 
C'est cette boucle qui bloque ? Tu devrais absolument definir done comme etant un volatile. J'ai eu exactement le meme probleme à l'époque, sauf que pour moi ça ne marchais pas en mode optimise. En mode normal, le compilo ne mettait pas done dans un registre et donc il devait lire sa valeur à chaque fois de la mémoire => bon comportement.
 
Il est possible qu'avec un compilateur moderne, meme sans optimisations particulieres le compilateur decide de mettre done dans un registre


Message édité par Kristoph le 14-12-2002 à 11:18:36
Reply

Marsh Posté le 14-12-2002 à 14:05:58    

Merci, je vais tester ça de ce pas.
Sinon, euh... En fait apparemment, je ne reçois pas l'irq6. J'ai créé un irq handler, et j'ai mis un print dedans pour que ça m'affiche un texte quand il reçoit l'IRQ, puis il met done à 1. Et justement, le problème c'est qu'il ne m'affiche pas le texte de l'IRQ 6 !!!


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 14-12-2002 à 14:18:57    

D'abord, est tu sur que printf peut etre utilise à partir d'une interrupt ?
 
Sinon, je ne vois pas le code qui indique au DMA que c'est l'IRQ 6 qu'il doit prevenir à la fin du transfert.

Reply

Marsh Posté le 14-12-2002 à 16:13:02    

Kristoph a écrit :

D'abord, est tu sur que printf peut etre utilise à partir d'une interrupt ?
 
Sinon, je ne vois pas le code qui indique au DMA que c'est l'IRQ 6 qu'il doit prevenir à la fin du transfert.
 

c le DMA ki renvoie l'IRQ 6 !? :heink: je pensais ke ct le floppy, quand il avait fini de tout faire..... :??:


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 14-12-2002 à 18:52:50    

En fait, je n'en ai aucune idée. D'apres ton document c'est le floppy qui le fait, mais dans le cas de copie mémoire à mémoire ca doit etre le DMA.
 
Enfin, si c'est vraiment le floppy qui lance l'interruption, il faut que regarde de ce cote du code et pas de celui du DMA ;)

Reply

Marsh Posté le 15-12-2002 à 01:41:06    

tout à fait d'accord pour le volatile.
 
je me souviens avec le watcom c ou je mixais de l'asm et du C, avec une varible globale dans le C, modifié dans l'ASM, le compilateur me tégais des boucles car il supposais que la variable restait dans son état initialisé...

Reply

Marsh Posté le 15-12-2002 à 04:17:45    

robotniktareum a écrit :

bah il faut bien remonter le niveau... Je voyais ke le forum courait à sa perte :D

Y'a pas photo, ca change des 'le prog quitte trop vite' et autres 'tableau variable'.
 
En fait, c'est ça exactement qui me chiffone:

Code :
  1. {
  2. cli;
  3. //...
  4. sti;
  5. }


keskecé ?
(je connais le principe de CLear/SeT Interrupt)
 
Si c'est des noms de type ou d'objets, ça ne fait strictement rien.
Ça pourrait être des macros, mais on les mets en majuscules d'habitude.
Et si c'est une extension de langage, c'est maladroit.
 
Juste par curiosité, ça m'étonnerait beaucoup que ce soit l'origine du problème !
 
Peut-être que les newsgroup sauraient mieux te répondre...


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 15-12-2002 à 11:09:23    

robotniktareum a écrit :

bah il faut bien remonter le niveau... Je voyais ke le forum courait à sa perte :D
Sinon cette fonction a un effet : j'indique au controleur DMA ce qu'il doit faire, et ça se fait par une succession d'écritures sur les ports du contrôleur. Je lui indique si il doit lire ou écrire, sur quel canal il doit travailler, quel endroit en mémoire il doit utiliser, ... Ce code me semble correct, car je l'ai trouvé sur des cours : http://www.nondot.org/sabre/os/articles
bon je v en cours... Ad'taleur


 
beurk t as cours le samedi now !!! :sweat:
 
bon sinon bonne continuation !!!

Reply

Marsh Posté le 15-12-2002 à 11:30:01    

Musaran a écrit :

Y'a pas photo, ca change des 'le prog quitte trop vite' et autres 'tableau variable'.
 
En fait, c'est ça exactement qui me chiffone:

Code :
  1. {
  2. cli;
  3. //...
  4. sti;
  5. }


keskecé ?
(je connais le principe de CLear/SeT Interrupt)
 
Si c'est des noms de type ou d'objets, ça ne fait strictement rien.
Ça pourrait être des macros, mais on les mets en majuscules d'habitude.
Et si c'est une extension de langage, c'est maladroit.
 
Juste par curiosité, ça m'étonnerait beaucoup que ce soit l'origine du problème !
 
Peut-être que les newsgroup sauraient mieux te répondre...


 
c des instructions asm pour masquer ou pas les interruptions coté cpu.

Reply

Marsh Posté le 15-12-2002 à 12:26:19    

bjone a écrit :


 
c des instructions asm pour masquer ou pas les interruptions coté cpu.


Les bouquins intel me disent :
CLI - Clear Interrupt Flag
OPCode : 0xFA
Interrupts disabled when interrupt flag cleared.
 
STI - Set Interrupt Flag
OPCode : 0xFB
external, maskable interrupts enabled at the end of the next instruction
 
The IF flag and IF Flag and the STI and CLI instructions have no affect an the generation of the execptions and NMI interrupts.
 
EDIT : bien entendu, j'ai déclaré ceci :  
#ifndef cli
#define cli             asm("cli":: )
#endif
 
#ifndef sti
#define sti             asm("sti":: )
#endif
 
EDIT2 : 'font chier ces smileys ;)
 
 :hello:


Message édité par robotniktareum le 15-12-2002 à 12:30:52

---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 15-12-2002 à 12:33:16    

asphro a écrit :


 
beurk t as cours le samedi now !!! :sweat:
 
bon sinon bonne continuation !!!

putain m'en parle pas... En plus pour des cours d'adélia de merde qu'on pige même pas ce kon veut nous faire faire et arrivés en TP on nous dit : "bon bah faîtes pas ça marche pas" ou bien encore "n'ouvrez pas tous l'as/400 en même temps, sinon ça va planter ace ke il est vieux", merci... Enfin, encore 2 fois à supporter ça, après, c'est C++ :p


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 15-12-2002 à 13:44:57    

robotniktareum a écrit :

putain m'en parle pas... En plus pour des cours d'adélia de merde qu'on pige même pas ce kon veut nous faire faire et arrivés en TP on nous dit : "bon bah faîtes pas ça marche pas" ou bien encore "n'ouvrez pas tous l'as/400 en même temps, sinon ça va planter ace ke il est vieux", merci... Enfin, encore 2 fois à supporter ça, après, c'est C++ :p


 
mouahahha ayez l as400 devient poussif !!
 
c la fin :sweat:  

Reply

Marsh Posté le 15-12-2002 à 16:30:40    

J'ai une très bonne nouvelle : j'arrive à le faire marcher.
Pour ceux que ça intéresse, j'ai mis les srcs à disposition :
http://dszczyt.free.fr/dossier/BoOSt.tar.gz
 
Merci @ tous...
 :hello:


---------------
si t déçu d'être dessous, tu iras dessus kom ça tu seras plus déçu ni dessous... Si tu piges pas c ke t saoul, c sûr...
Reply

Marsh Posté le 15-12-2002 à 19:42:43    

Super question à 2 balles (même pas)
 
Ça sert à quoi tout ça ?
 
Merci
 
(oui, c'était court comme intervention)
 

Reply

Marsh Posté le 15-12-2002 à 19:44:27    

ça sert à transfert des données de/vers le lecteur de disquette.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed