La programmation du DMA (8237)
Le DMA (Direct Memory Access) permet de transférer des données de la mémoire vers un périphérique ou d'un périphérique vers la mémoire sans passer par le CPU (sauf pour sa programation).
Au début les PC (XT) n'avaient qu'un seul contrôleur DMA et permettaient de faire des transferts 8 bits.
De nos jours les PC (AT) ont 2 contrôleurs DMA qui, utilisés ensemble, permettent de faire des transferts 16 bits.
La taille du transfert maximum (en 1 seul fois) est de 64 KO (65536 octet) pour les transfert 8 bits et 128 KO pour les transferts 16 bits.
Remarque : il est impossible d'utiliser le DMA 2 pour faire des transfert 8 bits.
Chaque DMA possede 4 caneaux :
DMA |
CANEAUX |
DESCRIPTION |
DMA 1
(8 bits) |
CANAL 0
CANAL 1
CANAL 2
CANAL 3 |
Liber (Ram-refresh pour vieux PC)
libre (souvent carte son)
lecteur de disquette
IMPRIMANTE (Disque Dur ) |
DMA 2
16 bits) |
CANAL 4(0)
CANAL 5(1)
CANAL 6(2)
CANAL 7(3) |
Cascade DMA 1 => DMA 2
libre (carte son-16 bits)
libre
libre |
Le DMA possède 27 registres :
CANAL |
REGISTRE |
port DMA
8 bits
|
port DMA
16 bits
|
RW |
TAILLE
en bit |
0 (4)0 (4)0 (4)0 (4) |
adresse de début
adresse en cours
longueur transfert -1
longueur restante -1 |
00h00h01h01h |
0C0h0C0h0C2h0C2h |
WRWR |
16161616 |
1 (5)1 (5)1 (5)1 (5) |
adresse de début
adresse en cours
longueur transfert -1
longueur restante -1 |
02h02h03h03h |
0C4h0C4h0C6h0C6h |
WRWR |
16161616 |
2 (6)2 (6)2 (6)2 (6) |
adresse de début
adresse en cours
longueur transfert -1
longueur restante -1 |
04h04h05h05h |
0C8h0C8h0CAh0CAh |
WRWR |
16161616 |
3 (7)3 (7)3 (7)3 (7) |
adresse de début
adresse en cours
longueur transfert -1
longueur restante -1 |
06h06h07h07h |
0CCh0CCh0CEh0CEh |
WRWR |
16161616 |
0 (4)1 (5)2 (6)3 (7) |
REGISTRE DE PAGE
REGISTRE DE PAGE
lREGISTRE DE PAGE
REGISTRE DE PAGE |
087083081082 |
08Fh08Bh089h08Ah |
RWRWRWRW |
8888 |
R C E D O G E N I T S R T Ô R L E E
|
STATUT
COMMANDE
REQUÊTE
MASQUE 1
MODE
FLIPFLOP
MÉMOIRE TEMPORAIRE
RESET
RESET DE MASQUE
MASQUE 2 |
08h08h09h0Ah0Bh0Ch0Dh0Dh0Eh0Fh |
0D0h0D0h0D2h0D4h0D6h0D8h0DAh0DAh0DCh0DEh |
RWWWWWRWWW |
8888888888 |
ADRESSE DE DEBUT :
C'est l'adresse à partir de laquelle le transfert débute .
Cette adresse est codée sur 24 bits (20 pour le XT), ici il
n'y a que les 16 bits inférieurs de l'adresse.
REGISTRE DE PAGE :
Les 8 bits (4 pour le XT) supérieurs de l'adresse sont
"stockés" dans le registre de PAGE .
ADRESSE EN COURS :
Quand on lit ce registre on obtient l'adresse ou le transfert
est arrivé au moment de la lecture du registre.
LONGUEUR DU TRANFERT -1: (=compteur)
C'est ici qu'on indique la taille du transfert -1 .
LONGUEUR RESTANTE -1: (=compteur)
Quand on lit ce registre (pendant le transfert) on obtient le
nombre d'octet -1 qu'il reste à transférer .
ATTENTION :
Le DMA ne peut pas changer de segment (c'est dû à
un défaut de conception).
Prenons un exemple pour être plus clair :
L'adresse de début du transfert est 7000:F000 et
on veut transfÉrer 16Ko (4000H) en DMA 8 bits .
Le registre de PAGE aura pour valeur 07h, le registre
d'adresse de début aura pour valeur 0F000h et le compteur
(longueur) aura pour valeur 3FFFh.
Quand le transfert sera arrivé à 7000:ffff, normalement le
registre de page doit s'incrementer (= 08) pour continuer à 8000:0000,
mais il ne le fait pas (c'est la le défaut conception), si bien
que le transfert continu à l'adresse 7000:0000 jusqu'à 7000:3000.
Pour faire ce transfert correctement , il faut s'y prendre à 2 fois :
Le registre de PAGE aura pour valeur 07h, le registre
d'adresse aura pour valeur 0F000h et le compteur (longueur)
aura pour valeur 0FFFh.
Arrivé là, on doit reconfigurer le DMA :
Le registre de PAGE aura pour valeur 08h, le registre
d'adresse aura pour valeur 0000h et le compteur (longueur)
aura pour valeur 2FFFh.
Et voila, le transfert est correctement éffectué :
de 7000:F000 à 8000:3000
Remarque : Si vous avez un driver EMS (EMM386.exe ou autre)
installé, vous n'avez pas besoin de faire ce transfert en 2
fois et certains modes DMA se sont plus suportés .
Pour faire des transferts 16 bits, il faut mettre dans le
registre d'adresse, une adresse PAIRE.
En 16 bits la longueur ne correspond plus à des octets, mais
à des mots.
----------------------------------------------------
VOICI UN TABLEAU RECAPITULATIF :
-----------------------------------------------------
CANAL
DMA |
Reg de page
= SEGMENT |
Adresse
= OFFSET |
Longueur du
transfert -1
= COMPTEUR |
0123 |
87H83H81H82H |
00H02H04H06H |
01H03H05H07H |
4567 |
8FH8BH89H8AH |
C0HC4HC8HCCH |
C2HC6HCAHCEH |
DESCRIPTION DES REGISTRES DE CONTRÔLE :
STATUT (SR) : 08h (DMA1) ou D0h (DMA2) /R
Ce registre indique qu'un transfert est finit.
Lorsque le compteur passe de 0000 à FFFF, le flag
TC (Terminal Count) est mis à 1.
DREQ indique une requête matériel (d'un périphérique).
SR est remis à 0 à sa lecture .
|
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
|
|
R- |
|D3| |
|D2| |
|D1| |
|D0| |
|TC3| |
|TC2| |
|TC1| |
|TC0| |
08H |
(D0H) |
Bit 0 = 1 TC atteint pour le canal 0(transfert finit)
Bit 1 = 1 TC atteint pour le canal 1
Bit 2 = 1 TC atteint pour le canal 2
Bit 3 = 1 TC atteint pour le canal 3
Bit 4 = 1 Requête DMA via DREQ 0 pour le canal 0
Bit 5 = 1 Requête DMA via DREQ 1 pour le canal 1
Bit 6 = 1 Requête DMA via DREQ 2 pour le canal 2
Bit 7 = 1 Requête DMA via DREQ 3 pour le canal 3
COMMANDE : 08h (DMA1) ou D0h (DMA2) /W
|
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
|
|
-W |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
08H |
(D0H) |
Bit 0 = 0 Transfert entre Mémoire et Périphérique = 1 Transfert entre Mémoire et Mémoire (impossible?)
Bit 1 = 0 le canal déborde de la mémoire = 1 le canal reste figé à l'adresse de début
Bit 2 = 0 Active le contrôleur = 1 Désactive le contrôleur
Bit 3 = 0 Accès ordinaire = 1 Accès compressé
Bit 4 = 0 Priorité static (priorité max => canal 0 et priorité min => canal 3 ) = 1 Priorité rotative
Bit 5 = 0 Signal write retardé (si b3=1) = 1 Signal write rallongé (si b3=1)
Bit 6 = 0 Requête DRQ si ligne high = 1 Requête DRQ si ligne low
Bit 7 = 0 Confirmation DACK via ligne low = 1 Confirmation DACK via ligne high
En principe vous ne devez jamais toucher à ce registre. Valeur par défaut = 00h
REQUÊTE
: 09h (DMA1) ou D2h (DMA2) /W
Permet de simuler une requête DMA par logiciel .
|
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
|
|
-W |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| M | |
| C | |
| C | |
09H |
(D2H) |
Bit 7-3 = 0 Reservé
Bit 2 = 0 Pas de requete 1 Simulation de requÊte via la ligne DREQx
Bit 1-0 = 00 Sélectionne le canal 0 01 Sélectionne le canal 1 10 Sélectionne le canal 2 11 Sélectionne le canal 3
MASQUE1
: 0Ah (DMA1) ou D4h (DMA2) /W
Les 2 registres de MASQUE servent à masquer un ou plusieurs
canaux pour permettre leur initialisation. (Vous devez en
utiliser qu'un seul, celui que vous voulez)
|
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
|
|
-W |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| M | |
| C | |
| C | |
0AH |
(D4H) |
Bit 7-3 = 0 Réservé
Bit 2 = 0 Pas de masque sur le canal sélectionner 1 Masque le canal sélectionner
Bit 1-0 = 00 Sélectionne le canal 0 01 Sélectionne le canal 1 10 Sélectionne le canal 2 11 Sélectionne le canal 3
MASQUE2
: 0Fh (DMA1) ou DEh (DMA2) /W
Le registre de MASQUE2 sert exactement à la même chose
mais il fonctionne différement .
|
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
|
|
-W |
| 0 | |
| 0 | |
| 0 | |
| 0 | |
| C3 | |
| C2| |
| C1 | |
| C0 | |
0FH |
(DEH) |
Bit 7-4 = 0 réservé
Bit 3 = 0 Pas de masque sur le canal 3 1 Masque le canal 3
Bit 2 = 0 Pas de masque sur le canal 2 1 Masque le canal 2
Bit 1 = 0 Pas de masque sur le canal 1 1 Masque le canal 1
Bit 0 = 0 Pas de masque sur le canal 0 1 Masque le canal 0
MODE
: 0Bh (DMA1) ou D6h (DMA2) /W
Permet de sélectionner le fonctionnement du transfert.
|
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
|
|
-W |
| MT | |
| MT | |
| ID | |
| TC | |
| TT | |
|TT| |
| C | |
| C | |
0BH |
(D6H) |
Bit 1-0 = 00 sélectionne le canal 0 01 sélectionne le canal 1 10 sélectionne le canal 2 11 sélectionne le canal 3
Bit 3-2 = 00 Vérifie (utilisé pour RAM REFRESH ) 01 Ecriture (du périphérique vers la mémoire) 10 Lecture (de la mémoire vers le périphérique) 11 Réservé
Bit 4 = 0 auto initialisation inactif 1 auto initialisation actif
L'auto initialisation permet à la fin d'un transfert (quelque soit le mode) de réinitialiser le DMA avec les valeurs (compteur,adresse ...) déja programmées lors du transfert précédent (on a plus besoin de reprogrammer le DMA ).
Bit 5 = 0 Incrémentation de l'adresse (de transfert) 1 Décrémentation de l'adresse
ATTENTION
:
* Si vous choisissez INCREMENTATION de l'adresse , vous
devez placer l'adresse de DÉBUT du transfert au DÉBUT
du bloc à transferer.
* Si vous choisissez DÉCRÉMENTATION de l'adresse , vous
devez placer l'adresse de DÉBUT du transfert à la FIN
du bloc à transferer.
MODE : INCRÉMENTATION DÉCRÉMENTATION MÉMOIRE MÉMOIRE 0000:0000+--------+ 0000:0000+-------+ | | | | | | | | adr de ->+--------+ +-------+ début de | |<-- Bloc à --> | | Transfert+--------+ transferé +-------+<-- Adresse de | | | | début de | | | | transfert | | | | FFFF:FFFF+--------+ FFFF:FFFF+-------+
Bit 7-6 = 00 Mode transfert à la demande 01 Mode transfert unique 10 Mode transfert en bloc 11 Mode CASCADE
TRANSFERT EN BLOC :
Le transfert en bloc correspond au transfert complet des
données sans interruption jusqu'à ce que le compteur passe
de 0000 à FFFF ( = TC ) ou que le péripherique interrompt le
transfert(/EOP). (Pendant ce temps le CPU ne peut acceder au BUS)
Le transfert débute par envoie d'un signal (bref)
d'un péripherique sur la ligne DREQ .
TRANSFERT UNIQUE :
Avec le transfert unique, le DMA ne transfert qu'un seul octet
(ou mot si cascade) à la fois et nécessite une nouvelle
commande venant du matériel (ou logiciel) pour déclencher
le transfert DMA de l'octet (ou mot) suivant.
C'est ce mode de transfert qui est utilisé pour jouer de la ZIK .
TRANSFERT A LA DEMANDE :
Le transfert à la demande est identique au transfert en bloc,
mais contrairement à ce dernier (qui necessite un bref signal
sur DREQ pour débuter le transfert complet),il faut ici que
le péripherique maintienne ce signal sur la ligne DREQ
pendant la totalité du transfert.
Remarquez que le péripherique peut interrompre le transfert
(quand il veut) en arrêtant ce signal .
TRANSFERT EN CASCADE :
Le transfert en cascade permet grâce à 2 DMA de réaliser
des transferts 16 bits .
FLIPFLOP : 0Ch (DMA1) ou D8h (DMA2) /W
Ce registre sert à initialiser une bascule interne pour
selectionner l'octet de poid faible / octet de poid fort
des registres 16 bits (adresse de début,longueur ...).
En effet on ne peut pas lire ou écrire directement des
valeurs de 16 bits dans ces registres.Il faut écrire
d'abord 0 dans le registre FLIPFLOP pour indiquer
qu'on va écrire le poid faible du MOT (16 bits):
Il faut écrire l'octet de poids faible (8 bits inférieurs)
dans le registre.
A ce moment le FLIPFLOP bascule automatiquement pour
permettre d'écrire le poid fort .
Ensuite, il faut écrire l'octet de poids fort dans
ce registre .
Remarque : le FLIPFLOP bascule sur le poids faible à nouveau .
TAMPON : 0Ch (DMA1) ou D8h (DMA2) R/
C'est l'octet qui en cours de transfert ??
dans le mode memory to memory, je crois.
RESET : 0Dh (DMA1) ou DAh (DMA2) /W
Reset du contrôleur DMA
RESET de masque : 0Eh (DMA1) ou DCh (DMA2) /W
Reset des masque : tous les masque sont enlevés.
-------------------------------------------------------------------
Voiçi les étapes à respecter pour programmer le DMA:
1) MASQUER LE CANAL DMA (à programmer)
2) ECRIRE DANS LE REGISTRE DE COMMANDE (FACULTATIF)
3) INDIQUER LE MODE DE TRANSFERT
4) ECRIRE LA PAGE (SEGMENT)
5) 0 => FLIPFLOP
6) ECRIRE L'OCTET DE POIDS FAIBLE DE L'ADRESSE DE DEBUT
7) ECRIRE L'OCTET DE POIDS FORT DE L'ADRESSE DE DEBUT
8) ECRIRE L'OCTET DE POIDS FAIBLE DE LA LONGUEUR -1 (COMPTEUR)
9) ECRIRE L'OCTET DE POIDS FORT DE LA LONGUEUR -1 (COMPTEUR)
10) LIBERER LE CANAL DMA
-------------------------------------------------------------------- |