Der DMA-Controller des HD64180

Helmut Bernhardt

Der On Chip DMAC (Direct Memory Access Controller) des HD64180 bietet
gegenber einem eigenständigen DMAC (z.B. Z80-DMAC) gewisse Vorteile

1) beim RESET liegen definierte Einstellungen vor; ein Hängen des Sys-
tems kommt nicht vor
2) entsprechend den Adressierungmöglichkeiten der CPU kann auch der
DMAC 512K adressieren
3) da CPU und DMAC auf einem Chip und dadurch beide auf dem CPU-Bord
sitzen, kann eine aufwendige  DMA-fähige Steuerung der Bustreiber
entfallen, ohne auf DNA verzichten zu müssen

Der DMAC des HD64180 verfügt  über 2 Kanäle mit unterschiedlichen
Eigenschaften:


Kanal 0 kann
   Speicher <-> Spejcher -
   Speicher <-> I/O -  und
   Speicher <-> memory mapped I/O - Transfers durchführen

   Dabei kann bei jedem Speicherzugriff die Adresse  inkrementiert,
   dekrementiert oder unverändert belassen werden. Dje Speicher <->
   Speicher - Übertragung kann im Burst- oder im Cycle Steal Mode er-
   folgen. Die beiden Chip-internen seriellen Schnittstellen (ASCI)
   können über den DMA-Kanal 0 mit Handshake bedient werden

Kanal 1 kann nur Memory <-> I/O - Transfers durchführen.  Dabei Xenn
   die Speicheadresse nach jedem Zugriff inkrementiert oder dekremen-
   tiert werden.


Die Ports des DMA-Controllers

Kanal 0
  20H SAROL   Source Address Register Channel 0 low        A0 - A7
  21H SAROH   Source Address Register Channel 0 high       A8 - A15
  22H SAROB   Source Address Register Channel 0 bank      A16 - A18
  23H DAROL   Destination Address Register Channel 0 low   A0 - A7
  24H DAROH   Destination Address Register Channel 0 high  A8 - A15
  25H DAROB   Destination Address Register Cnannel 0 bank A16 - A18
  26H BCROL   Byte Count Register Channel 0 low            D0 - D7
  27H BCROH   Byte Count Register Channel 0 high           D8 - D15
Kanal 1
  28H MAR1L   Memory Address Register Channel 1 low        A0 - k7
  29H MAR1H   Memory Address Register Channel 1 high       A8 - A15
  2AH MAR1B   Memory Address Register Channel 1 bank      A16 - A18
  2BH IAR1L   I/O Address Register Channel 1 low           A0 - A7
  2CH IAR1H   I/O Address Register Channel 1 high          A8 - A15
  2DH       reserved
  2EH BCR1L   Byte Count Register Channel 1 low            D0 - D7
  2FH BCR1H   Byte Count Register Channel 1 high           D8 - D15
für beide Kanäle
  30H DSTAT   Status Register
  31H DMODE   Mode Register
  32H DCNTL   DMA/WAIT Control Register

Für Kanal 0 ist vorgegeben, wo die Adressen für 'Quelle' und 'Ziel'
einzutrage sind. Dabei ist es in beiden Fällen möglich, Speichera-
dessen oder Ports anzugeben. Bei Ports ist dann der Inhalt des Zu-
satzadreßregisters (A16-A18) ohne Bedeutung. Memory mapped I/O unter-
scheidet sich von normalen Speicheradressen nur dadurch, daß dort auch
ein Hardware-Handshaking möglich ist.

Kanal 1 legt fest, daß unabhängig von der Funktion 'Qelle' oder
'Ziel' die Speicheradresse in die Ports 28H-2AH und die I/O-Adresse in
die Ports 2BH, 2CH eingetragen wird. Die Übertragungsrichtung sowie
der Modus (Inkrementieren, Dekrementieren oder feste Adresse für Ziel
und Quelle) werden in Port 32H (DCNTL), Bits O-3 festgelegt.

Für beide Kanäle kann durch die Vorgaben in den jeweiligen Byte Count
Registern (16 Bit) eine Übertragung von bis zu 64K am Stück vorgegeben
werden.

Für allgemeine Steuervorgaben (write) und Statusinforationen (read)
sind die Ports 30H-32H zuständig:

DMA Status Register, DSTAT, Port 30H

    Bit       7     6     5    4     3     2    1    O
    Name     DE1   DE0  /DW1 /DWE0  DIE1  DIE0  -   DME
   Zugriff   R/W   R/W    W    W    R/W   R/W        R

DE1 : DMA Enable Channel 1
      Ein DMA-Transfer über Kanal 1  wird durch Ausgabe von DE1=1 ge-
      startet. Um DE1 zu setzen, muß gleichzeitig /DWE1 ausgegeben
      werden; nur dann wird der Wert für DE1 übernommen. Wenn DE1=1
      gesetzt wird, wird automatisch gleichzeitig auch DME gesetzt.

DE0 : DMA Enable Channel 0
      Um einen DMA-Transfer über Kanal 0 zu starten, müssen gleich-
      zeitig DE0=1 und /DEW0=0 an DSTAT ausgegeben werden. DME wird
      dabei automatisch gesetzt.

Der DMA-Transfer läßt sich (im Cycle Steal Mode) bei beiden Kanälen
unterbrechen, wenn DEx=0 und /DWEx=0 an DSTAT ausgegeben werden. Mit
der Ausgabe von DEx=1 und /DWEx=0 kann der Transfer dann weitergeführt
werden. Nach beendetem Transfer wird DEx automatisch =1 gesetzt.

/DWE1, /DWE0: DMA Bit Write Enable Channel 1, -Channel 0
      Um DE1 oder DE0 zu setzen oder zu löschen, muß gleichzeitig das
      entsprechende Bit /DWE1 bzw. /BWE0 low ausgegeben werden.

DIE1, DIE0: DMA Interrupt Enable Channel 1, -Channel 0
      Wenn DIEx für Kanal x als 1 gesetzt wird, erfolt nach Beenden
      des DMA-Tansfers ein CPU-Interrupt. DIEx = 0 (nach RESET vor-
      eingestellt) verhindert den Interrupt.

DMA Mode Register, DMODE, Port 31H

   Bit       7   6    5    4    3    2    1    0   
   Name      -   -   DM1  DM0  SM1  SM0  MOD   -
   Zugriff           R/W  R/W  R/W  R/W  R/W

Über DODE wrrd derÜbertraungs-Modus  für ausschließlich Kanal 0
vorgegeben. DM1 und DM0 geben für das Ziel und SM1 und SM0 für die
Quelle die Übertragungsbedingungen vor:

   DM1  DM0     Ziel und Bedingungen
   ---------------------------------------------
    0    0      Memory mit Adreßinkrement
    0    1      Memory mit Adreßdekrement
    1    0      Memory mit feststehender Adresse
    1    1      I/O mit feststehender Adresse

   SM1  SM0     Quelle und Bedingungen
   ---------------------------------------------
    0    0      Memory mit Adreßinkrement
    0    1      Memory mit Adreßdekrement                                
    1    0      Memory mit feststehender Adresse
    1    1      I/O mit feststehender Adresse

DM1, DM0, SM1 und SM0 werden bei RESET auf 0 gesetzt.
KMODE hat keine Funktion, wenn Quelle oder Ziel als I/O festgelegt
werden. Dann bestimmt der Triggerimpuls am Pin /DREQ0 das Timing. Bei
Memory <-> Memory-Transfers bestimmt KMODE die Transferart.

MMOD=0 : Cycle Steal Mode; Nach jedem DMA-Transfer darf die CPU einen
         Zyclus ausführen.

MMOD=1 : Burst Mode; die CPU erhält die Kontrolle über den Bus erst
         dann wieder, wenn die gesamte DMA-Übertragung beendet ist.

DMA/WAIT Control Register, DCNTL, Port 32H

   Bit      7     6     5     4     3     2     1     0
   Name    MWI1  MWI0  IWI1  IWI0  DMS1  DMS0  DIM1  DIM0
   Zugriff  R/W   R/W   R/W   R/W   R/W   R/W   R/W   R/W

MWI1, MWI0, IWI1 und IWI0 steuern die Anzahl WAITs für Memory- und
Port-Zugriffe durch die CPU und den DMAC.Diese Bits wurden bereits im
im letzten Teil besprochen.

DMS1, DMS0, DIM1 und DIM0 sind Steuerbits für den Kanal 1 der aus-
schließlich Memory <-> I/O- und I/O <-> Memory-Übertragungen steu-
ert. Diese Übertragungen werden durch DERQ1 getriggert. Da auch beim
Kanal 0 getriggerte Übertragungen möglich sind, kann mit DMS0 auch
hier die Triggerart festgelegt werden.

DMS1, DMS0 : DMA Request Sense
   legen die Art des Triggerns für DERQ1 (Kanal 1) und DERQ0 (Kanal 0)
   fest. Wenn das Bit auf 0 gesetzt ist,wird durch einen Low-Pegel am
   DERQ-Pin getriggert. Der DERQ-Pin wird zu Beginn des zweiten Taktes
   eines CPU-Maschinen-Zyklus übernommen. Wenn zu diesem Zeitpunkt am
   DERQ-Pin Low-Pegel anliegt, wird der Maschinen-Zyklus noch beendet
   und dann ein DMA-Transfer durchgeführt.
   Wenn DMSx auf 1 gesetzt ist, wird die DMA-Übertragungdurch eine
   negative Flanke am DERQx-Pin getriggert.

DIM1, DIM0 : Channel 1 I/O and Memorx Mode
   Festlegen von Quelle und Ziel und Inkrementieren/Dekrementieren von
   Speicheradressen.

   DIM1 DIM0  Transfer-Richtung    Inc./Dec.
   ----------------------------------------------
     0    0   Memory -> I/O        Inkrementieren
     0    1   Memory -> I/O        Dekrementieren
     1    0   I/O -> Memory        Inkrementieren
     1    1   I/O -> Memory        Dekrementieren

   Die I/O-Adresse wird in allen Fällen nicht verändert.


Programmieren der DMA-Kanäle

Kanal 0, Memory <-> Memory

Die reine Memory<->Memory- Übertragung wird nicht durch den DERQ0-Pin
getriggert. Das Timing erfolgt je nach Modus (Burst- oder Cicle Steal)
inzwei verschiedenen Arten. In beiden Fällen hält die DMA-Übertragung
an, bis der Byte Count Zähler auf 0 heruntergezählt. Im Burst Mode
werden alle Bytes nacheinander übertragen und die CPU erhält erst dann
wieder die Kontrolle über den Bus. Im Cycle Steal Mode wird immer ab-
wechselnd ein Maschinen-Zyklus der CPU und eine Übertragung des DMAC
durchgeführt.

Es werden nacheinander folgende Register programmiert:
1) Laden der Memory Adress Source- und Destination-Register
2) in DMODE: Memory<->Memory und Adreß-Inkrement/Dekrement über SM1,
   SM0, DM1, DM0 festlegen
3) Anzahl zu übertragender Bytes in die Byte Count Regjster schreiben
4) Burst- oder Cycle Steal Mode in  MMOD von DCNTL vorgeben
5) Übertragung mit DE0=1 und geichzeitig /DWE0=0 in DSTAT starten


Kanal 0, Memory <-> I/O oder memory mapped I/O

Das Timing des DMA-Transfers wird durch die Pins /DREQ0 und /TEND0 des
HD64180 gesteuert.
/DREQ0 : über diesen Eingang wird ein DMA-Transfer getriggert.
TEMD0  : über diesen Ausgang wrrd das Ende eines DMA-Blocktransfers
         (BRC0=OOH) angezeigt.
Diese Pins sind mit den Clock Inputs/Outputs CKA0 und CKA1 der ASCI-
-Schnittstelle gemultiplext. Wenn der DMA-Kanal 0 für Memory <-> I/O
oder memory mapped I/O programmiert wird, fungieren diese Pins als DMA
Handshake-signale. CKA1D in CNTLA1 wird automatisch high gesetzt.

Wenn vor der ansteigenden Flanke von T3 eines CPU-Maschinenzyklus eine
fallende Flanke von /DREQ0 auftrat (wenn taktflanken-getriggert pro-
grammiert) bzw. bei der steigenden Flanke von T3 Low-Pegel an
DREQ0 vorliegt (wenn pegel-getriggert  programmiert), wird anstelle
des nächsten CPU-Maschinenzyklus ein DMA-Transfer ennes Bytes (Lesen
und Schreiben) durchgeführt.

Initialisierung:
1) Memry- und (memory-mapped) I/O- Quell- und Ziel-Adressen in SAR0
   und DAR0 eintragen. I/O-Adressen sind 16 Bit breit, A16 und A17
   sind als 0 einzutragen.
2) durch Setzen von SM0, SM1, DM0 und DM1 in DMODE vorgeben, ob
   Memory <-> I/O oder Memory <-> memory mapped I/O und ob Adressen
   inrementiert oder dekrementiert werden sollen.
3) Anzahl zu übertragender Bytes in CCR0 einragen
4) durch DMS0 in DCNTL flanken- oder pegelgetriggert an /DREQ0 vor-
   geben
5) durch DIE0 in DSTAT DMA-Ende-Interrupt freigeben oder sperren
6) DE0=1 und gleichzeitig /DWE0=0 in DSTAT eintragen
/DREQ0 steuert dann die DMA-Übertragung.


Kanal 0, Memory <-> ASCI

Bei Übertragungen über die 2-Kanal-ASCI-Schnittstelle wird das Timing;
nicht über /DREQ0 gesteuert. Die ASCI-Statusbits erzeugen intern ein
/DREQ0. Es sind dies die Bits TDRE (Transmmt Data Register Empty) und
RDRF (Receive Data Register Full).

Initiaisierung:
1) Quell- und Ziel-Adressen in SAR0 und DAR0 vorgeben. Die I/O-Adresse-
   ist ein ASCI-Register (06H-09H), das mit A0 - k7 vorgegeben wird.
   A8 - A15 sind low zu sezten. A18 ist ohne Bedeutung.
   16 und A17 steuern das Timing über die ASCI-Statusbits:

   bei Empfangen über ASCI:    '
   A17 A16   D-Transfer-Request durch
   ------------------------------------------------
    0   0    /DREQ0 bei Übertragung nicht über ASCI
    0   1    RDRF (ASCI, Kanal 0)
    1   0    RDRF (ASCI, Kanal 1)
    1   1      reserviert

   bei Senden über ASCI
   A17 A16   DMA-Transfer-Request durch
   ------------------------------------------------
    0   0    /DREQ0 bei Übertragung nicht über ASCI
    0   1    TDRE (ASCI Kanal 0)
    1   0    TDRE (ASCI Kanal 1)
    1   1       reserviert

2) durch SM0, SM1, DM0 und DM1 in DMODE Memory <-> I/O - Transfer und
   Inkrementieren oder Dekrementielen der Memory-Adressen vorgeben
3) Anahl zu übertragender Bytes in BCR0 vorgeben
4) DMS0 in DCNTL muß für "flankengetriggert" programmiert werden
5) DIE0 in DSTAT kann DMA-Ende-Interrupt zulassen oder sperren
6) Mit DE0=1 und gleichzeitig /DWE0=0 an DSTAT wird der DMA-Transfer
   Jnitialisiert und dann durch die ASCI-Statusbits gesteuert

Die ASCI-Empfänger/ -Sender müssen initialisiert werden, um den ersten
DMA-Transfer zu starten. Der ASCI-Empfänger muß leer sein (RDRF=0)
bzw. der ASCI-Sender muß mit einem ersten Byte geladen sein (TDRE=0).
Das erste Byteß muß von der CPU an den ASCI-Sender gegeben werden; alle
weiteren Bytes werden per DMA übertragen.

Kanal 1, Memory <-> I/O

bis auf einige unterschiedliche Register und Status-/Control-Bits
funktioniert ier DMA-Transfer über Kanal 1 wie der Memory  <-> I/O
Transfer über Kanal 0

Initialisierung:
1) Memory-Adresse (19 Bit) in MAR1 ff eintragen
2) I/O-Adresse (16 Bit) in IAR1 ff eintragen
3) mit DIM0 und DIM1 von DCNTL Quelle und Ziel sowie Dekrementieren
   oder Inkrementieren der Memory-Adresse festlegen
4) in DMS1 von DCNTL vorgeben, ob /DREQ1 flanken- oder pegel-getrig-
   gert arbeiten soll
5) über DIE1=1 in STAT einen DMA-Ende-Interrupt zulassen oder sperren
6) DE1=1 und gleichzetig /DWE1=0 in DSTAT eintragen

Das Timing wird dann über /DREQ1 gesteuert; /TEMD1 gibt das Ende eines
DMA-Blocktransfers dem I/O-Gerät bekannt.

Diese kurze Übersicht der Programmierng berücksichtig die Reihen-
folge der eizelnen Schritte, wie sie von Hitachi im HD64180-Datenbuch
vorgechlagen ist. Solange man das Register DSTAT immer zuletzt be-
schreib, kann in der Reihenfolge des Befüllens der anderen Ports eine
sinnvollere Ordnung eingebracht werden. So lassen sich z.B. beim Memo-
ry <-> Memory DMA-Transfer über Kanal 0 die hintereinander liegenden
Ports für Qell- und Zieladressen und Übertrgungslänge mit dem Befehl
OTIMR aus einer entsprechenden Tabelle im Speicher befüllen und nur
noch DMODE und DSTAT sind mit einelnen OUT0-Befehlen zu versorgen.

Die Nutzung der DMA-Kanäle für Memory <-> I/O oder memory mapped I/O
Übertragungen setzt voraus, daß die Hardware die Signale /DREQ0 bzw.
/DREQ1 unu /TEND0 bzw. /TEND berücksichtigt. Der Prof180 wickelt z.B.
den Datenaustausch mit dem µPD765-Floppy-Controller über den DMA-Kanal
1 ab und hat entsrrechend die Signale /DREQ1 und /TEND1 über Inverter
zwischen CPU und FDC verbunden.