home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / midas / dma.asm < prev    next >
Assembly Source File  |  1994-08-06  |  10KB  |  368 lines

  1. ;*    DMA.ASM
  2. ;*
  3. ;* DMA handling routines, v1.10
  4. ;*
  5. ;* Copyright 1994 Petteri Kangaslampi and Jarno Paananen
  6. ;*
  7. ;* This file is part of the MIDAS Sound System, and may only be
  8. ;* used, modified and distributed under the terms of the MIDAS
  9. ;* Sound System license, LICENSE.TXT. By continuing to use,
  10. ;* modify or distribute this file you indicate that you have
  11. ;* read the license and understand and accept it fully.
  12. ;*
  13.  
  14.  
  15. IDEAL
  16. P386
  17. JUMPS
  18.  
  19. INCLUDE "lang.inc"
  20. INCLUDE "errors.inc"
  21. INCLUDE "dma.inc"
  22. INCLUDE "mmem.inc"
  23.  
  24.  
  25. DATASEG
  26.  
  27. bptr            DD      ?
  28.  
  29.  
  30.  
  31. IDATASEG
  32.  
  33.  
  34.  
  35. ;/***************************************************************************\
  36. ;*     DMA channel data
  37. ;\***************************************************************************/
  38.  
  39. dmaChns dmaChannel      < 0, 1, 000h, 001h, 009h, 00Ah, 00Bh, 00Ch, 087h >
  40.     dmaChannel    < 1, 2, 002h, 003h, 009h, 00Ah, 00Bh, 00Ch, 083h >
  41.     dmaChannel    < 2, 4, 004h, 005h, 009h, 00Ah, 00Bh, 00Ch, 081h >
  42.     dmaChannel    < 3, 8, 006h, 007h, 009h, 00Ah, 00Bh, 00Ch, 082h >
  43.     dmaChannel    < 4, 1, 0C0h, 0C2h, 0D2h, 0D4h, 0D6h, 0D8h, 08Fh >
  44.     dmaChannel    < 5, 2, 0C4h, 0C6h, 0D2h, 0D4h, 0D6h, 0D8h, 08Bh >
  45.     dmaChannel    < 6, 4, 0C8h, 0CAh, 0D2h, 0D4h, 0D6h, 0D8h, 089h >
  46.     dmaChannel    < 7, 8, 0CCh, 0CEh, 0D2h, 0D4h, 0D6h, 0D8h, 08Ah >
  47.  
  48.  
  49.  
  50. CODESEG
  51.  
  52.  
  53.  
  54. ;/***************************************************************************\
  55. ;*
  56. ;* Function:     int dmaAllocBuffer(ushort size, dmaBuffer *buf);
  57. ;*
  58. ;* Description:  Allocates a DMA buffer (totally inside a 64K physical page)
  59. ;*
  60. ;* Input:        ushort size             size of buffer in bytes
  61. ;*               dmaBuffer *buf          ptr to buffer structure to be filled
  62. ;*
  63. ;* Returns:      MIDAS error code.
  64. ;*               DMA buffer data is strored in *buf.
  65. ;*
  66. ;\***************************************************************************/
  67.  
  68. PROC    dmaAllocBuffer  FAR     bsize : word, buf : dword
  69.  
  70.     cmp    [bsize],32000        ; buffer size must not be > 32000
  71.         jbe     @@bok                   ; bytes
  72.         mov     [bsize],32000
  73.  
  74. @@bok:
  75.     mov    ax,[bsize]        ; ax = buffer size
  76.     shl    ax,1            ; multiply by two so that it can
  77.         add     ax,64                   ; always be fitted inside one 64K
  78.                                         ; page and add 64 for segment
  79.                                         ; alignment
  80.  
  81.         ; Allocate memory for buffer:
  82.         les     bx,[buf]
  83.         lea     dx,[bx+dmaBuffer.memBlk]  ; point es:dx to buffer.memBlk
  84.         push    es bx
  85.         call    memAlloc LANG, ax, es dx  ; allocate the memory
  86.         pop     bx es
  87.         test    ax,ax                   ; error? (ax non-zero)
  88.         jnz     @@err
  89.  
  90.         mov     dx,[word es:bx+2+dmaBuffer.memBlk]      ; point dx:ax to
  91.         mov     ax,[word es:bx+dmaBuffer.memBlk]        ; buffer memory
  92.  
  93.     shr    ax,4
  94.     add    dx,ax            ; dx = buffer segment
  95.     inc    dx            ; (segment + offset / 16 + 1)
  96.  
  97.     mov    ax,dx            ; ax = segment AND 0FFFh
  98.     and    ax,0FFFh
  99.  
  100.     mov    cx,[bsize]
  101.     add    cx,15
  102.     shr    cx,4            ; cx = 0FFFh - (size + 15) / 16
  103.     neg    cx
  104.         add     cx,0FFFh
  105.  
  106.         cmp     ax,cx                   ; does buffer cross a 64K page
  107.     jb    @@ok            ; boundary? (ax >= cx)
  108.  
  109.     and    dx,0F000h        ; yes, move it to the beginning of
  110.     add    dx,01000h        ; next page
  111.  
  112. @@ok:    mov    [es:bx+dmaBuffer.bsegment],dx    ; store buffer segment
  113.     movzx    eax,dx
  114.     shl    eax,4
  115.     mov    [es:bx+dmaBuffer.address],eax    ; address = segment * 16
  116.  
  117.     mov    ax,[bsize]            ; store buffer length
  118.     mov    [es:bx+dmaBuffer.blength],ax
  119.  
  120.     mov    [es:bx+dmaBuffer.channel],-1    ; buffer is not being played
  121.  
  122.         xor     ax,ax                   ; allocation succesful
  123.         jmp     @@done
  124.  
  125. @@err:
  126.         ERROR ID_dmaAllocBuffer
  127.  
  128. @@done:
  129.     ret
  130. ENDP
  131.  
  132.  
  133.  
  134.  
  135. ;/***************************************************************************\
  136. ;*
  137. ;* Function:     int dmaFreeBuffer(dmaBuffer *buf);
  138. ;*
  139. ;* Description:  Deallocates an allocated DMA buffer
  140. ;*
  141. ;* Input:        dmaBuffer *buf          ptr to buffer to be deallocated
  142. ;*
  143. ;* Returns:      MIDAS error code
  144. ;*
  145. ;\***************************************************************************/
  146.  
  147. PROC    dmaFreeBuffer    FAR    buf : dword
  148.  
  149.     les    bx,[buf]        ; point es:bx to buffer
  150.     call    memFree LANG, [es:bx+dmaBuffer.memBlk]    ; free buffer memory
  151.         test    ax,ax
  152.         jz      @@done
  153.  
  154.         ERROR ID_dmaFreeBuffer
  155.  
  156. @@done:
  157.     ret
  158. ENDP
  159.  
  160.  
  161.  
  162.  
  163. ;/***************************************************************************\
  164. ;*
  165. ;* Function:     int dmaPlayBuffer(dmaBuffer *buf, ushort channel,
  166. ;*                                 ushort autoInit);
  167. ;*
  168. ;* Description:  Plays a DMA buffer
  169. ;*
  170. ;* Input:        dmaBuffer *buf          buffer to be player
  171. ;*               ushort channel          DMA channel number
  172. ;*               ushort autoInit         use autoinitialization?
  173. ;*
  174. ;* Returns:      MIDAS error code
  175. ;*
  176. ;\***************************************************************************/
  177.  
  178. PROC    dmaPlayBuffer    FAR    buf : DWORD, channel : WORD, autoInit : WORD
  179. USES    si,di
  180.  
  181.     les    di,[buf]        ; es:di points to DMA buffer struct
  182.  
  183.         ; si is the offset to right channel structure from the
  184.         ; beginning of dmaChns:
  185.         imul    si,[channel],SIZE dmaChannel
  186.  
  187.         mov     al,[si+dmaChns.number]
  188.     xor    ah,ah
  189.     mov    [es:di+dmaBuffer.channel],ax
  190.     and    al,3                ; reset DMA request
  191.         mov     dx,[si+dmaChns.request]
  192.     out    dx,al
  193.  
  194.     or    al,4
  195.         mov     dx,[si+dmaChns.singleMask]      ; mask out the channel
  196.     out    dx,al
  197.  
  198.         mov     al,[si+dmaChns.number]
  199.     and    al,3
  200.     or    al,8 or 64        ; read mode, single mode
  201.     cmp    [autoInit],1        ; use auto-initialization?
  202.     jne    @@noai
  203.     or    al,16            ; enable auto-initialization
  204.  
  205. @@noai: mov     dx,[si+dmaChns.mode]
  206.     out    dx,al
  207.  
  208.     mov    ebx,[es:di+dmaBuffer.address]    ; physical start addr
  209.         mov     dx,[si+dmaChns.page]
  210.     mov    eax,ebx
  211.     shr    eax,16            ; al = DMA page
  212.     out    dx,al
  213.  
  214.         mov     dx,[si+dmaChns.clearFF] ; clear byte pointer flip-flop
  215.     xor    al,al            ; so that next write to a 16-bit reg
  216.     out    dx,al            ; will go to the low byte
  217.  
  218.         mov     dx,[si+dmaChns.baseAddr]
  219.         cmp     [si+dmaChns.number],3   ; 16-bit channel?
  220.     jbe    @@no16
  221.     shr    ebx,1            ; starting word instead of byte
  222.  
  223. @@no16:
  224.     mov    al,bl
  225.     out    dx,al            ; set base address low byte
  226.     mov    al,bh
  227.     out    dx,al            ; set base address high byte
  228.  
  229. @@based:
  230.     mov    bx,[es:di+dmaBuffer.blength]    ; buffer length
  231.         cmp     [si+dmaChns.number],3           ; 16-bit channel?
  232.     jbe    @@no16_2
  233.     shr    bx,1            ; convert to _word_ (16-bit) count
  234.  
  235. @@no16_2:
  236.     dec    bx            ; word count = length - 1
  237.         mov     dx,[si+dmaChns.wordCount]
  238.     mov    al,bl
  239.     out    dx,al            ; set word count low byte
  240.     mov    al,bh
  241.     out    dx,al            ; set word count high byte
  242.  
  243. @@countd:
  244.         mov     al,[si+dmaChns.number]
  245.     and    al,3
  246.         mov     dx,[si+dmaChns.singleMask]      ; enable channel
  247.     out    dx,al
  248.  
  249.         xor     ax,ax                   ; success
  250.  
  251.     ret
  252. ENDP
  253.  
  254.  
  255.  
  256.  
  257. ;/***************************************************************************\
  258. ;*
  259. ;* Function:     int dmaStop(ushort channel);
  260. ;*
  261. ;* Description:  Stops DMA playing
  262. ;*
  263. ;* Input:        ushort channel          DMA channel number
  264. ;*
  265. ;* Returns:      MIDAS error code
  266. ;*
  267. ;\***************************************************************************/
  268.  
  269. PROC    dmaStop     FAR    channel : WORD
  270. USES    si
  271.  
  272.         ; si is the offset to right channel structure from the
  273.         ; beginning of dmaChns:
  274.         imul    si,[channel],SIZE dmaChannel
  275.  
  276.         mov     dx,[si+dmaChns.singleMask]
  277.         mov     al,[si+dmaChns.number]
  278.     and    al,3            ; mask out (disable) DMA channel
  279.     or    al,4
  280.     out    dx,al
  281.  
  282.         mov     dx,[si+dmaChns.clearFF]
  283.     xor    al,al            ; clear byte pointer flip-flop
  284.     out    dx,al
  285.  
  286.     ret
  287. ENDP
  288.  
  289.  
  290.  
  291. ;/***************************************************************************\
  292. ;*
  293. ;* Function:     int dmaGetPos(dmaBuffer *buf, ushort *pos);
  294. ;*
  295. ;* Description:  Gets the DMA playing position
  296. ;*
  297. ;* Input:        dmaBuffer *buf          buffer that is being played
  298. ;*               ushort *pos             pointer to return value
  299. ;*
  300. ;* Returns:      MIDAS error code.
  301. ;*               DMA playing position from the beginning of the buffer,
  302. ;*               in bytes, is stored in *pos.
  303. ;*
  304. ;\***************************************************************************/
  305.  
  306. PROC    dmaGetPos       FAR     buf : dword, pos : dword
  307. USES    si,di
  308.  
  309.  
  310.         les     di,[buf]                ; point es:di to buffer structure
  311.     mov    bx,[es:di+dmaBuffer.channel]
  312.  
  313.         ; si is the offset to right channel structure from the
  314.         ; beginning of dmaChns:
  315.         imul    si,bx,SIZE dmaChannel
  316.  
  317.         mov     dx,[si+dmaChns.clearFF] ; clear Flip-Flop port
  318.     xor    al,al            ; clear byte-pointer flip-flop
  319.     out    dx,al
  320.  
  321.         mov     dx,[si+dmaChns.wordCount]       ; word count port
  322.     cli                ; disable interrupts for more
  323. @@read:                 ; accurate results.
  324.     in    al,dx
  325.     mov    ah,al
  326.     in    al,dx            ; bx = first word count
  327.     xchg    al,ah
  328.     mov    bx,ax
  329.  
  330.     in    al,dx
  331.     mov    ah,al            ; ax = second word count
  332.     in    al,dx
  333.     xchg    al,ah
  334.  
  335. @@countd:
  336.     sub    bx,ax            ; now compare the two results
  337.     cmp    bx,4            ; if the difference is over 4, read
  338.     jg    @@read            ; again - there might be an EMM
  339.                     ; disturbing...
  340.     cmp    bx,-4
  341.     jl    @@read
  342.  
  343.     cmp    ax,[es:di+dmaBuffer.blength]    ; check for bogus values
  344.     jae    @@read
  345.  
  346.     sti
  347.  
  348.         cmp     [si+dmaChns.number],3   ; is the DMA channel 16-bit?
  349.     jbe    @@no16
  350.     shl    ax,1            ; convert to bytes if a 16-bit chan
  351. @@no16:
  352.     neg    ax            ; position = buffer size - count
  353.     add    ax,[es:di+dmaBuffer.blength]
  354.  
  355.         les     di,[pos]                ; store position in *pos
  356.         mov     [es:di],ax
  357.  
  358.         xor     ax,ax                   ; success
  359.  
  360.     ret
  361. ENDP
  362.  
  363.  
  364.  
  365.  
  366.  
  367. END
  368.