
       Programming the Direct Memory Access Controller {DMAC}

Dear DMAC enithusiasts,

   Here is some information that might help us start programming this
 powerful chip.
   Please infrom me if you find it useful, so I know that my article
 has been read.

 Hatim Ahmed Khan.
 Computer Science & Engineering student.
 Saudi Arabia
 STUYA55@SAUPM00.BITNET

---------------------------------------------------------------------------
 The 8237A DMAC has four  channels, you can program each one independently.
 Every channel has four modes of operation :-

 1 - Single transfer : in this mode, one single data byte is transferred after
       each CPU instruction until the counter becomes zero. This is the mode
       most often used - the Sound Blaster uses this mode extensivley to play
       the background sound.
 2 - Block transfer.
 3 - Demand transfer.
 4 - Cascade mode.

 NOTE : The channel to be used must be initialized first.

-------------------------------------------------------------------------------
 STEPS FOR INITIALIZATION :-

 1 - Tell the mask register to mask the channel to be initialized.
 2 - Send 00H to the command register choosing the default.
 3 - Tell the mode register the following :
       The channel number
       Writing or reading from memory
       Autoinitialized or Nonautoinitialized
       Decrement or increment the memory address after each byte transfer
       The operation mode {Single/Block/Demand/Cascade}.
 4 - Reset the flip-flop register to zero.
 5 - Write the low byte of the memory address to the address register for
       that channel, then write the high  byte to the same register.
 6 - Send the physical memory page number to the page address register for
       that channel.
 7 - Send {the number of data byte you want to transfer - 1} to the counter
       register for that channel - the low byte then the high byte -.
 8 - Tell the mask register to unmask the channel.

-------------------------------------------------------------------------------
 THE FOLLOWING IS THE PORTS FOR DMAC : -
 0000H  Memory address register for Channel 0.
 0001H  Counter register        for Channel 0.
 0002H  Memory address register for Channel 1.
 0003H  Counter register        for Channel 1.
 0004H  Memory address register for Channel 2.
 0005H  Counter register        for Channel 2.
 0006H  Memory address register for Channel 3.
 0007H  Counter register        for Channel 3.
 0008H  Status register
          It is status register when you read the port
          Bit 0 = 1 { Counter register for channel 0 is zero }
          Bit 1 = 1 { Counter register for channel 1 is zero }
          Bit 2 = 1 { Counter register for channel 2 is zero }
          Bit 3 = 1 { Counter register for channel 3 is zero }
          Bit 4 = 1 { Channel 0 is requested }
          Bit 5 = 1 { Channel 1 is requested }
          Bit 6 = 1 { Channel 2 is requested }
          Bit 7 = 1 { Channel 3 is requested }.
 0008H  Command register
          It is command register when you write to the port
          Bit 0 = 0 { Memory-to-memory transfer disable }
                  1 { Memory-to-memory transfer enable  }
          Bit 1 = 0 { Channel 0 address-hold disable }
                  1 { Channel 0 address-hold enable  }
          Bit 2 = 0 { Pin ^CS disable - Note : ^ means a dash }
                  1 { Pin ^CS enable }
          Bit 3 = 0 { Timing normal }
                  1 { Timing compressed }
          Bit 4 = 0 { Priority fixed }
                  1 { Priority rotating }
          Bit 5 = 0 { Write pulse width normal }
                  1 { Write pulse extended }
          Bit 6 = 0 { DREQ state high }
                  1 { DREQ state low }
          Bit 7 = 0 { ^DACK state low }
                  1 { ^DACK state high }.
 000AH  Mask register
          You can mask only one channel at a time.
          Bit 1-0 = 00 { Select Channel 0 }
                    01 { Select Channel 1 }
                    10 { Select Channel 2 }
                    11 { Select Channel 3 }
          Bit 2   = 0  { Clear mask bit }
                    1  { Set mask bit   }
          Bit 7-3 = X  { Don't care }
 000BH  Mode register
          Bit 1-0 = 00 { Select Channel 0 }
                    01 { Select Channel 1 }
                    10 { Select Channel 2 }
                    11 { Select Channel 3 }
          Bit 3-2 = 00 { Verify operation }
                    01 { Write  operation }
                    10 { Read   operation }
                    11 { Illegal }
                    XX { If bits 6 and 7 = 11 }
          Bit 4   = 0  { Autoinitialized - This means that when ever the
                         counter register for the channel selected reaches
                         zero, the initial value for that register will be
                         loaded again. So, the count continues endlessly.
                         This is used mainly with memory refresh }
                    1  { Non-autoinitialized }
          Bit 7-6 = 00 { Demand mode }
                    01 { Single mode }
                    10 { Block mode  }
                    11 { Cascade mode }
 000CH  Flip-flop register
          When writing to the memory address and counter registers, set this
          register to 0 to access the low byte and to 1 to access the high
          byte. The flip-flop switches each time you access the memory
          address and counter registers.
 000DH  Master clear
 000EH  Clear mask register
 000FH  Mask register
          The difference between this register and the one on the port 000AH
          is, by using this one you can mask all the channels at a time.
          Bit 0   = 0 { Unmask Channel 0 }
                    1 { Mask Channel 0 }
          Bit 1   = 0 { Unmask Channel 1 }
                    1 { Mask Channel 1 }
          Bit 2   = 0 { Unmask Channel 2 }
                    1 { Mask Channel 2 }
          Bit 3   = 0 { Unmask Channel 3 }
                    1 { Mask Channel 3 }
          Bit 7-4 = XXXX { Don't care }
 0019H  Scratch register
 0081H  Page address register for Channel 2
 0082H  Page address register for Channel 3
 0083H  Page address register for Channel 1
 0087H  Page address register for Channel 0

 {IMPORTANT NOTE}:
   XT uses 0080H-0083H for Page address registers.
   AT and PS/2 use 0081H-0083H,0087H.

-------------------------------------------------------------------------------
 Memory Addresses :

     To give the correct memory address for your data to the 8230H+AAAAH = 1CDEAH.
            01H   is the page address
            CDEAH is the memory address.

-------------------------------------------------------------------------------
 EXAMPLE :

    You have a peripheral which utilizes the 8237A DMAC channel 1 to
 read data from memory.
    Write an assembly program to initialize channel 1 - this channel is
 used by the Sound Blaster's DSP - so that 800 bytes starting at address
 8AAAH:0000H will be transferred from memory to peripheral when the latter
 requests channel 1 from the 8237A DMAC.

 Answer :

  The 20-bit address for our data is (8AAAH*10H+0000H) = 8AAA0H.

              ; Program the 8237A DMA controller
  mov al,05H  ; Select Channel 1 and set mask bit
  out 0AH,al  ; Send to the mask register
  mov al,00H  ; The default for command register
  out 08H,al  ; Send to the command register - usually this step is excluded
  mov al,49H  ; Channel 1, Read operation, Autoinitialized,
              ; Address increment, Single transfer mode
  out 0AH,al  ; Send to the mode register
  mov al,00H  ; Reset flip-flop, low byte can be accessed
  out 0CH,al  ; Send to the flip-flop register
  mov al,08H  ; 08H is the page address
  out 83H,al  ; Send to the page address register for channel 1
  mov al,A0H  ; A0H is the low byte for the memory address
  out 02H,al  ; Send to the memory address register for channel 1
  mov al,AAH  ; AAH is the high byte for the memory address
  out 02H,al  ; Send to the memory address register for channel 1
  mov al,1FH  ; 1FH is the low byte for the number of data to be transferred
              ; remember 800-1 = 799 = 031FH
  out 03H,al  ; Send to the counter register for channel 1
  mov al,03H  ; 03H is the high byte
  out 03H,al  ; Send to the counter register for channel 1
  mov al,01H  ; Unmask Channel 1
              ; As soon as the peripheral requests channel 1, DMAC will start
              ; its job

-------------------------------------------------------------------------------
 Memory-To-Memory Transfer Mode :

    This mode is not supported by EMM386.EXE program.

-------------------------------------------------------------------------------
 REFERENCES :

 1 - SOUND BLASTER The Official Book --- Richard Heimlich with
      David M.Golden Ivan Luk and Peter M.Ridge.

 2 - Microcomputer Organization Hardware and Software --- Charles E.Holt.

 3 - Microcomputer and Microprocessors The 8080,8085, and Z-80
      Programming, Interfacing, and Troubleshooting --- John Uffenbeck.

 4 - The Programmer's PC SourceBook --- Thom Hogan.

-------------------------------------------------------------------------------
 That is all folks ...... :-)


    Hatim Ahmed Khan
    STUYA55@SAUPM00.BITNET
    Saudi Arabia
------------------------------ THE END ----------------------------------------
