home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / sys / ibm / pc / programm / 594 < prev    next >
Encoding:
Internet Message Format  |  1992-11-18  |  22.6 KB

  1. Xref: sparky comp.sys.ibm.pc.programmer:594 alt.msdos.programmer:2785
  2. Path: sparky!uunet!cs.utexas.edu!wupost!sdd.hp.com!sgiblab!public!heard
  3. From: heard@public.BTR.COM (Charles M. Heard  heard@btr.com)
  4. Newsgroups: comp.sys.ibm.pc.programmer,alt.msdos.programmer
  5. Subject: Re: DMA-- *HOW?* (long)
  6. Summary: Discussion of two-cycle vs fly-by plus sample working code
  7. Keywords: DMA
  8. Message-ID: <8332@public.BTR.COM>
  9. Date: 19 Nov 92 04:54:42 GMT
  10. References: <im14u2c.721884439@camelot> <1992Nov17.084050.9545@cs.joensuu.fi> <1992Nov17.162107.15828@athena.cs.uga.edu>
  11. Followup-To: comp.sys.ibm.pc.programmer
  12. Organization: BTR Public Access UNIX, MtnView CA. For info contact: info@BTR.COM
  13. Lines: 507
  14.  
  15. In article <im14u2c.721730126@camelot> im14u2c@camelot.bradley.edu
  16. (Joseph Zbiciak) writes:
  17.  
  18. > I would like to know HOW to program the DMA controller to do such
  19. > aweful tasks as moving a screen-size hunk of memory out to the
  20. > display, or repeatedly "sampling" an input port to a bank of
  21. > memory.
  22.  
  23. This posting is relatively long owing to the number of requests for this
  24. information.  It discusses the following topics:
  25.  
  26. 1.)  The difference between fly-by and two-cycle transfers, and why it is
  27. usually a waste of time to use a DMA for memory-to-memory moves.
  28.  
  29. 2.)  Sample DMA routines that were actually used to download program overlays
  30. and upload measurement results between a PC/XT compatible computer board and
  31. an expansion card with an on-board processor doing data acquisition.
  32.  
  33. ----------------------------------------------------------------------------
  34.  
  35. 1.)  Fly-by and two-cycle transfers --
  36.  
  37.  In the PC/XT/AT the 8237 DMA controller is ordinarily set up to transfer data
  38. between an I/O mapped peripheral and main memory. The PC/AT actually has two
  39. DMA controllers, one of which does eight-bit transfers and one of which does
  40. sixteen-bit transfers.  These transfers are called single-cycle or fly-by
  41. transfers  because a memory read and an I/O write (for a READ TRANSFER
  42. operation) or an I/O read and a memory write are both performed in the same
  43. bus cycle and the data is not stored within the DMA but rather "flies by" on
  44. the computer bus.  This is accomplished in the following way.  The peripheral
  45. indicates that it is ready to send or receive a byte (or word) of data by
  46. asserting a DMA request line which is attached to the DREQ input pin of one
  47. of the DMA channels.  The DMA chip then asserts the CPU's hold request (HREQ)
  48. line.  At the next opportunity (typically when it has finished whatever bus
  49. operation that is in progress) the CPU asserts hold acknowledge (HACK) and
  50. tri-states its bus control lines (i.e. relinquishes control of the bus).  The
  51. DMA, upon sensing this, asserts the DMA acknowledge (DACK) line of the highest
  52. priority unmasked channel, and after a predictable amount of delay will place
  53. a memory address on the bus (determined by the contents of the channel's
  54. address register) and will assert -MEMRD (memory read) and -IOWR (I/O write)
  55. (for a read transfer) or -IORD (I/O read) and -MEMWR simultaneously.  It does
  56. not drive the data bus -- that is up to the memory or peripheral.  In effect
  57. the DMA is just a traffic cop.  After the operation is complete, the address
  58. register mey be incremented, decremented, or held, and the count register is
  59. decremented.  When the latter expires, the channel is masked and no further
  60. transfers take place until it is reprogrammed.
  61.  
  62.  Note that the DACK signal is used in place of an I/O address to select the
  63. peripheral device which will participate in the transfer.  One can see that
  64. this will not work if the peripheral device is the video memory, for example,
  65. because one MUST use an address to select the byte or word to be accessed,
  66. and the DMA cannot put two addresses on the bus simultaneously (and get
  67. sensible results, anyway!).  For this reason memory-to-memory transfers
  68. are usually implemented as two-cycle transfers.  In the 8237 this is
  69. accomplished by linking channels 0 and 1 together, and using one channel
  70. to perform a memory read and store the data in a temporary register;  the
  71. other channel writes the data from the temporary register to a different
  72. memory address during a subsequent bus cycle.  Since memories usually
  73. don't have any way to assert a DREQ line, the transfer is typically
  74. initiated by the CPU setting a request bit in one of the DMA controller's
  75. internal registers.  Such a transfer will run until completion (only one
  76. DMA channel's count register is actually used), and the CPU will be in a
  77. bus hold state for the duration.  Unless the CPU has a cache (as do all
  78. 80486 PC's and some 80386 PC's) it will just idle while this is happening.
  79. The 80X86 family block move instruction, however, will generally do a
  80. memory-to-memory move just as fast as the DMA can -- after all, this is
  81. limited mainly by memory speed, and the same number of bus cycles are run
  82. (i.e., one memory read and one memory write).  And this is a LOT easier
  83. to program than fiddling with the 8237's linked channel programming.  Even
  84. the more advanced DMA devices (such as the Intel 82380 integrated peripheral,
  85. which mates with the 80386-DX) that can do a two-cycle transfer with a
  86. single channel are typically not any faster than the CPU at doing block
  87. moves and are much more troublesome to program.
  88.  
  89. LESSON 1:  UNLESS YOU HAVE A CACHE, YOU MIGHT AS WELL USE A BLOCK MOVE
  90.            INSTRUCTION FOR SUCH TASKS AS MOVING A SCREEN-SIZED CHUNK OF
  91.            DATA FROM MAIN MEMORY TO VIDEO DISPLAY ADAPTER MEMORY.
  92. ---------------------------------------------------------------------------
  93.  
  94. 2.)  Sample DMA routines that were actually used to download program overlays
  95. and upload measurement results between a PC/XT compatible computer board and
  96. an expansion card with an on-board processor doing data acquisition -- this
  97. is an application for fly-by transfers where the DMA is actually helpful.
  98. The slave board in the example below has a Zilog Z8038 Z-FIO fifo with which
  99. it transfers data to or from the PC/XT host, and it produces or consumes data
  100. at a rather slow rate relative to the bus speed.  Rather than interrupting the
  101. CPU whenever a byte is needed (or available) it pays to let the DMA steal a
  102. bus cycle every now and then rather than enduring the interrupt overhead;
  103. and anyway it's a fly-by transfer so it's faster than programmed block I/O
  104. instructions would be.  The DREQ and DACK lines are hooked up to the FIO,
  105. and we set up the DMA for single transfers (i.e., it transfers one byte
  106. then gives up the bus again).
  107.  
  108. In order to make the program a little more comprehensible, here are the
  109. bit definitions for the 8237 command and mode registers.  I/O address
  110. equates are in the source (author's note:  these equates are little more
  111. than documentation as they were added to the source ex post facto -- the
  112. routines use literals, unfortunately).
  113.  
  114.  
  115. DMA_CMD_REG record  DACK_SENSE:1,    ; active high or low
  116. &                   DREQ_SENSE:1,    ; "                "
  117. &                   WRT_SEL:1,        ;normal or late write
  118. &                   PRIO_SEL:1,        ;rotating or fixed
  119. &                   TIMING_SEL:1,    ;compressed or normal
  120. &                   DEV_ENA:1,        ;disable/enable HREQ to CPU
  121. &                   CH0_ADR_HOLD:1,    ;address hold (memory-to-memory xfr)
  122. &                   MM_ENA:1        ;use CH0/CH1 for memory-to-memory xfr
  123.  
  124. DMA_MODE_REG record  MODE_SEL:2,    ;demand, single, block, or cascade
  125. &                    ADDR_INCR:1,    ;increment or decrement address reg.
  126. &                    AUTO_INIT:1,    ;restart or mask chnl when cnt expires
  127. &                    XFER_TYPE:2,    ;read, write, or verify xfr
  128. &                    CHNL_SEL:2        ;0, 1, 2, or 3 (binary encoded)
  129.  
  130. Note that the commands to mask single channels put the channel number in the
  131. two LSB's (bits 0 & 1) as in the mode register and the mask bit in bit 2.
  132. See the code below for more details.  It is also STRONGLY recommended that
  133. you get the 8237 data sheet from Intel or from Harris Semiconductor.
  134.  
  135.  
  136. PAGE    ,132
  137. NAME    DMA_XFER
  138. TITLE   DMA Channel 1 Init'zation Routines
  139. ;***************************************************************
  140. ;*    DOS SEGMENT ORDER                                        *
  141. ;***************************************************************
  142.         DOSSEG
  143. ;***************************************************************
  144. ;*    MEMORY MODEL                                             *
  145. ;***************************************************************
  146.         .MODEL small
  147. ;***************************************************************
  148. ;*    DATA SEGMENT                                             *
  149. ;***************************************************************
  150.         .DATA
  151.  
  152. STATS_SIZE      EQU 640+32          ; 16*20*2+32
  153. ALARM_SIZE      EQU 576+32          ; 16*18*2+32
  154. XFR_SIZE        EQU STATS_SIZE+ALARM_SIZE+2
  155.  
  156.                 EVEN
  157. _DMA_BUFFER     DB  1A00H DUP (?)
  158. DMA_BUF_SEG     DW  ?
  159. DMA_BUF_START   DW  ?
  160. DMA_BUF_END     DW  ?
  161. OV_BUF1_PTR     DW  ?
  162. OV_BUF2_PTR     DW  ?
  163. EXPORT_DMA_PTR  DW  ?
  164.  
  165. ; ---------- equates related to 8237 DMA
  166.  
  167. DMA             equ     00H     ;base for DMA channel address & count registers
  168. DMA_STATUS_PORT equ     08H     ;read status of DMA channels
  169. DMA_CMD_PORT    equ     08H     ;write global init'zation commands
  170. DMA_RQST_PORT   equ     09H     ;software request port -- not used
  171. DMA_MASK_PORT   equ     0AH     ;write single mask bit
  172. DMA_MODE_PORT   equ     0BH     ;write channel mode registers
  173. DMA_CLFL_PORT   equ     0CH     ;clear first/last flip-flop
  174. DMA_MCLR_PORT   equ     0DH     ;master clear (equiv to hdw reset)
  175. DMA_MSK_ALL_CH  equ     0FH     ;write all mask register bits
  176.  
  177. DMA_PAGE        equ     80H     ;DMA page registers base address
  178. ; ---------- record definitions for 8237 internal registers
  179.  
  180. DMA_CMD_REG record  DACK_SENSE:1,DREQ_SENSE:1,WRT_SEL:1,PRIO_SEL:1,TIMING_SEL:1,DEV_ENA:1,CH0_ADR_HOLD:1,MM_ENA:1
  181. DMA_MODE_REG record  MODE_SEL:2,ADDR_INCR:1,AUTO_INIT:1,XFER_TYPE:2,CHNL_SEL:2
  182.  
  183.         PAGE
  184. ;***************************************************************
  185. ;*    CODE SEGMENT                                             *
  186. ;***************************************************************
  187.         .CODE
  188.  
  189. ;***************************************************************
  190. ;*                                                             *
  191. ;*    PUBLICS                                                  *
  192. ;*                                                             *
  193. ;***************************************************************
  194.  
  195. PUBLIC  _SETUP_DMA_FOR_STATS
  196. PUBLIC  _SETUP_DMA_FOR_OVLOAD
  197. PUBLIC  _START_DMA_FIFO_TXFER
  198. PUBLIC  _SETUP_EXPORT_DMA
  199. PUBLIC  _START_EXPORT_DMA
  200. PUBLIC  _SHUT_OFF_DMA
  201.  
  202.         PAGE
  203. ;***************************************************************
  204. ;*                                                             *
  205. ;*    NAME:      _SETUP_DMA_FOR_STATS                          *
  206. ;*                                                             *
  207. ;*    FUNCTION:  To setup DMA channel 1 for transfer of stats  *
  208. ;*          blocks from TMS FIFO into a circular buffer.       *
  209. ;*                                                             *
  210. ;*    INPUT:     None                                          *
  211. ;*                                                             *
  212. ;*    OUTPUT:    None                                          *
  213. ;*                                                             *
  214. ;***************************************************************
  215.  
  216. _SETUP_DMA_FOR_STATS    PROC    NEAR
  217.  
  218. ; partition dma transfer buffer so that we get at least 4 256-byte blocks
  219. ; that don't cross 64K boundary
  220.  
  221.     PUSH    DI
  222.     PUSH    BP
  223.     MOV     BP,SP
  224.  
  225.     CALL    _SHUT_OFF_DMA
  226.  
  227.     MOV     AX,DS           ;convert DMA buffer address to 20-bit value
  228.     SUB     DX,DX
  229.     MOV     DL,AH
  230.     MOV     CL,4
  231.     SHR     DX,CL
  232.     SHL     AX,CL
  233.     ADD     AX,OFFSET DGROUP:_DMA_BUFFER
  234.     ADC     DX,0            ;DX:AX=20-bit address of DMA buffer
  235.     MOV     DMA_BUF_SEG,DX  ;save segment part (in "compressed" format )
  236.     MOV     DMA_BUF_START,AX; and provisionally save offset part
  237.     NEG     AX              ;AX=amount of memory left in this 64K segment
  238.     CMP     AX, XFR_SIZE    ;less than size of stats array ?
  239.     JA      SETUP_DMA_S2    ;jump if not
  240.     MOV     DMA_BUF_START,0 ;start at offset 0
  241.     INC     DMA_BUF_SEG     ; in next 64K segment
  242.     PAGE
  243. SETUP_DMA_S2:
  244.     MOV     AX,DMA_BUF_START
  245.     ADD     AX, XFR_SIZE
  246.     MOV     DMA_BUF_END,AX  ;save end address of dma buffer
  247.  
  248.     MOV     AX,DMA_BUF_SEG  ;fill buffer with all 0's
  249.     MOV     CL,4
  250.     ROR     AX,CL
  251.     MOV     ES,AX
  252.     MOV     DI,DMA_BUF_START
  253.     CLD
  254.     MOV     AX,0H
  255.     MOV     CX, XFR_SIZE    ; Number of bytes
  256.     SHR     CX, 1           ; Number of words
  257.     REP STOSW
  258.  
  259. ; set up DMA to continuously transfer data out of TMS FIFO to the DMA buffer
  260.     CLI                     ;interrupts off
  261.     MOV     AL,55H          ;set mode: single,auto-inc,I/O -> mem on Ch. 1
  262.     OUT     DMA+11,AL
  263.     OUT     DMA+12,AL       ;set first/last F/F
  264.     MOV     AX,DMA_BUF_START
  265.     OUT     DMA+2,AL        ;output start address (low byte)
  266.     MOV     AL,AH
  267.     OUT     DMA+2,AL        ;and high byte
  268.     MOV     AX,DMA_BUF_SEG
  269.     AND     AX,0FH
  270.     OUT     DMA_PAGE+3,AL   ;output high 4 bits of 20-bit addr to page reg
  271.     MOV     AX, XFR_SIZE    ;count output to DMA should be ONE LESS than
  272.                             ; ACTUAL COUNT !!!!!!
  273.     DEC     AX
  274.     OUT     DMA+3,AL        ;output byte count (low byte)
  275.     MOV     AL,AH
  276.     OUT     DMA+3,AL        ;and high byte
  277.     MOV     AL,1            ;unmask DMA channel 1
  278.     OUT     DMA+10,AL
  279.     STI
  280.     MOV     SP,BP
  281.     POP     BP
  282.     POP     DI
  283.     RET
  284. _SETUP_DMA_FOR_STATS    ENDP
  285.         PAGE
  286. ;***************************************************************
  287. ;*                                                             *
  288. ;*    NAME:      _SHUT_OFF_DMA                                 *
  289. ;*                                                             *
  290. ;*    FUNCTION:  To shut off DMA channel 1                     *
  291. ;*                                                             *
  292. ;*    INPUT:     None                                          *
  293. ;*                                                             *
  294. ;*    OUTPUT:    None                                          *
  295. ;*                                                             *
  296. ;***************************************************************
  297. _SHUT_OFF_DMA   PROC    NEAR
  298.     CLI
  299.     MOV     AL,5            ;mask DMA channel 1
  300.     OUT     DMA+10,AL
  301.     STI
  302.     RET
  303. _SHUT_OFF_DMA   ENDP
  304.     PAGE
  305. ;***************************************************************
  306. ;*                                                             *
  307. ;*    NAME:      _SETUP_DMA_FOR_OVLOAD                         *
  308. ;*                                                             *
  309. ;*    FUNCTION:  To setup DMA channel 1 for loading overlay    *
  310. ;*          to the TMS through the FIFO.                       *
  311. ;*                                                             *
  312. ;*    INPUT:     None                                          *
  313. ;*                                                             *
  314. ;*    OUTPUT:    None                                          *
  315. ;*                                                             *
  316. ;*      NOTE: We use the same transfer buffer that is used     *
  317. ;*      for statistics blocks transfer. This makes stats       *
  318. ;*      collection and overlay load mutually exclusive activi- *
  319. ;*      ties.                                                  *
  320. ;***************************************************************
  321.  
  322. _SETUP_DMA_FOR_OVLOAD   PROC    NEAR
  323.  
  324. ; partition dma transfer buffer so that we get at least 2 128-byte blocks
  325. ; that don't cross 64K boundary
  326.  
  327.     PUSH    DI
  328.     PUSH    BP
  329.     MOV     BP,SP
  330.  
  331.     CALL    _SHUT_OFF_DMA
  332.  
  333.     MOV     AX,DS           ;convert DMA buffer address to 20-bit value
  334.     SUB     DX,DX
  335.     MOV     DL,AH
  336.     MOV     CL,4
  337.     SHR     DX,CL
  338.     SHL     AX,CL
  339.     ADD     AX,OFFSET DGROUP:_DMA_BUFFER
  340.     ADC     DX,0            ;DX:AX=20-bit address of DMA buffer
  341.     MOV     DMA_BUF_SEG,DX  ;save segment part (in "compressed" format )
  342.     MOV     DMA_BUF_START,AX; and provisionally save offset part
  343.     NEG     AX              ;AX=amount of memory left in this 64K segment
  344.     CMP     AX,100H         ;less than 256 bytes (2 128-byte blocks) ?
  345.     JA      SETUP_DMA_O2    ;jump if not
  346.     MOV     DMA_BUF_START,0 ;start at offset 0
  347.     INC     DMA_BUF_SEG     ; in next 64K segment
  348. SETUP_DMA_O2:
  349.     MOV     AX,DMA_BUF_START
  350.     MOV     OV_BUF1_PTR,AX  ;save start pointer as overlay buffer 1 ptr
  351.     ADD     AX,80H
  352.     MOV     OV_BUF2_PTR,AX  ;save overlay buffer 2 ptr
  353.     PAGE
  354.     MOV     AX,DMA_BUF_SEG  ;fill buffer with all 0's
  355.     MOV     CL,4
  356.     ROR     AX,CL
  357.     MOV     ES,AX
  358.     MOV     DI,DMA_BUF_START
  359.     CLD
  360.     MOV     AX,0
  361.     MOV     CX,100H/2
  362.     REP STOSW
  363.  
  364. ; set up DMA for transfer data out of DMA buffer to the TMS FIFO
  365.     CLI                     ;interrupts off
  366.     MOV     AL,49H          ;set mode: single,no auto,inc,mem->I/O on Ch. 1
  367.     OUT     DMA+11,AL
  368.     MOV     AX,DMA_BUF_SEG
  369.     AND     AX,0FH
  370.     OUT     DMA_PAGE+3,AL   ;output high 4 bits of 20-bit addr to page reg
  371.     STI
  372.     MOV     SP,BP
  373.     POP     BP
  374.     POP     DI
  375.     RET
  376. _SETUP_DMA_FOR_OVLOAD   ENDP
  377.     PAGE
  378. ;***************************************************************
  379. ;*                                                             *
  380. ;*    NAME:      _START_DMA_FIFO_TXFER                         *
  381. ;*                                                             *
  382. ;*    FUNCTION:  To start DMA-FIFO transfer.                   *
  383. ;*                                                             *
  384. ;*    INPUT:     [BP+4] = Buffer # (0 or 1)                    *
  385. ;*                                                             *
  386. ;*    OUTPUT:    None                                          *
  387. ;*                                                             *
  388. ;*      NOTE: DMA should have been previously setup in         *
  389. ;*      _SETUP_DMA_FOR_OVLOAD. FIFO should be held CLEAR       *
  390. ;*      while DMA is being reprogrammed.                       *
  391. ;***************************************************************
  392.  
  393. _START_DMA_FIFO_TXFER   PROC    NEAR
  394.  
  395.     PUSH    BP
  396.     MOV     BP,SP
  397.  
  398.     CALL    _SHUT_OFF_DMA
  399.  
  400.     CLI                     ;interrupts off
  401.     MOV     AX,OV_BUF1_PTR  ;decide which overlay buffer to use
  402.     CMP     WORD PTR [BP+4],0
  403.     JE      START_DMA2
  404.     MOV     AX,OV_BUF2_PTR
  405. START_DMA2:
  406.     OUT     DMA+12,AL       ;set first/last F/F
  407.     OUT     DMA+2,AL        ;output start address (low byte)
  408.     MOV     AL,AH
  409.     OUT     DMA+2,AL        ;and high byte
  410.     MOV     AX,80H-1        ;count output to DMA should be ONE LESS than
  411.                             ; ACTUAL COUNT !!!!!!
  412.     OUT     DMA+3,AL        ;output byte count (low byte)
  413.     MOV     AL,AH
  414.     OUT     DMA+3,AL        ;and high byte
  415.     MOV     AL,1            ;unmask DMA channel 1
  416.     OUT     DMA+10,AL
  417.     STI
  418.     MOV     SP,BP
  419.     POP     BP
  420.     RET
  421. _START_DMA_FIFO_TXFER   ENDP
  422.     PAGE
  423. ;***************************************************************
  424. ;*                                                             *
  425. ;*    NAME:      _SETUP_EXPORT_DMA                             *
  426. ;*                                                             *
  427. ;*    FUNCTION:  To setup DMA channel 1 for export to 186      *
  428. ;*               through the FIFO.                             *
  429. ;*                                                             *
  430. ;*    INPUT:     None                                          *
  431. ;*                                                             *
  432. ;*    OUTPUT:    None                                          *
  433. ;*                                                             *
  434. ;*      NOTE: We use the same transfer buffer that is used     *
  435. ;*      for statistics blocks transfer. This makes stats       *
  436. ;*      collection and DMA export mutually exclusive activi-   *
  437. ;*      ties.                                                  *
  438. ;***************************************************************
  439.  
  440. _SETUP_EXPORT_DMA   PROC    NEAR
  441.  
  442. ; partition dma transfer buffer so that we get at least 2 128-byte blocks
  443. ; that don't cross 64K boundary
  444.  
  445.         PUSH    DI
  446.         PUSH    BP
  447.         MOV     BP,SP
  448.  
  449.         CALL    _SHUT_OFF_DMA
  450.  
  451.         MOV     AX,DS           ;convert DMA buffer address to 20-bit value
  452.         SUB     DX,DX
  453.         MOV     DL,AH
  454.         MOV     CL,4
  455.         SHR     DX,CL
  456.         SHL     AX,CL
  457.         ADD     AX,OFFSET DGROUP:_DMA_BUFFER
  458.         ADC     DX,0            ;DX:AX=20-bit address of DMA buffer
  459.         MOV     DMA_BUF_SEG,DX  ;save segment part (in "compressed" format )
  460.         MOV     DMA_BUF_START,AX; and provisionally save offset part
  461.         MOV     EXPORT_DMA_PTR,AX   ;save start pointer
  462. ;
  463. ; set up DMA for transfer data out of DMA buffer to the 186 FIFO
  464. ;
  465.         CLI                     ;interrupts off
  466.         MOV     AL,49H          ;set mode: single,no auto,inc,mem->I/O on Ch. 1
  467.         OUT     DMA+11,AL
  468.         MOV     AX,DMA_BUF_SEG
  469.         AND     AX,0FH
  470.         OUT     DMA_PAGE+3,AL   ;output high 4 bits of 20-bit addr to page reg
  471.         STI
  472.         MOV     SP,BP
  473.         POP     BP
  474.         POP     DI
  475.         RET
  476.  
  477. _SETUP_EXPORT_DMA   ENDP
  478.         PAGE
  479. ;***************************************************************
  480. ;*                                                             *
  481. ;*    NAME:      _START_EXPORT_DMA                             *
  482. ;*                                                             *
  483. ;*    FUNCTION:  To start Export DMA-FIFO transfer.            *
  484. ;*                                                             *
  485. ;*    INPUT:     [BP+4] = Number of bytes                      *
  486. ;*                                                             *
  487. ;*    OUTPUT:    None                                          *
  488. ;*                                                             *
  489. ;*      NOTE: DMA should have been previously setup in         *
  490. ;*      _SETUP_EXPORT_DMA.     FIFO should be held CLEAR       *
  491. ;*      while DMA is being reprogrammed.                       *
  492. ;***************************************************************
  493.  
  494. _START_EXPORT_DMA   PROC    NEAR
  495.  
  496.         PUSH    BP
  497.         MOV     BP,SP
  498.  
  499.         CALL    _SHUT_OFF_DMA
  500.  
  501.         CLI                     ;interrupts off
  502.         MOV     AX,EXPORT_DMA_PTR   ;Get Export pointer buffer to use
  503.         OUT     DMA+12,AL       ;set first/last F/F
  504.         OUT     DMA+2,AL        ;output start address (low byte)
  505.         MOV     AL,AH
  506.         OUT     DMA+2,AL        ;and high byte
  507.         MOV     AX, WORD PTR [BP+4]     ;count output to DMA should be ONE LESS than
  508.         DEC     AX                      ; ACTUAL COUNT !!!!!!
  509.         OUT     DMA+3,AL        ;output byte count (low byte)
  510.         MOV     AL,AH
  511.         OUT     DMA+3,AL        ;and high byte
  512.         MOV     AL,1            ;unmask DMA channel 1
  513.         OUT     DMA+10,AL
  514.         STI
  515.         MOV     SP,BP
  516.         POP     BP
  517.         RET
  518.  
  519. _START_EXPORT_DMA   ENDP
  520.  
  521.         END
  522.