    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.