home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 4 Drivers / 04-Drivers.zip / cs0929a.zip / dma.lst < prev    next >
File List  |  1999-09-29  |  28KB  |  701 lines

  1.  
  2. Module: D:\dev\csrc\os2dd\scd\dma.c
  3. Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
  4.  
  5. Segment: _TEXT  PARA   00000248 bytes  
  6.  
  7. //
  8. // dma.c
  9. // 25-Jan-99
  10. //
  11. // ULONG  dmaQueryDelta(AUDIOBUFFER *audioBufferPtr);
  12. // VOID   dmaWaitForChannel(USHORT count, AUDIOBUFFER *audioBufferPtr);
  13. // VOID   dmaStart(AUDIOBUFFER *audioBufferPtr);
  14. // VOID   dmaStop(AUDIOBUFFER *audioBufferPtr);
  15. // USHORT dmaSetModeType(AUDIOBUFFER *audioBufferPtr, USHORT mode);
  16. // USHORT dmaInit(USHORT dmaChannel, USHORT dmaType, AUDIOBUFFER *audioBufferPtr);
  17. // USHORT dmaDeinit(AUDIOBUFFER *audioBufferPtr);
  18.  
  19. #include "cs40.h"
  20.  
  21. //typedef struct _DMACHANNEL_INFO {
  22. // USHORT portAddr;       //  0
  23. // USHORT portCount;      //  2
  24. // USHORT portPage;       //  4
  25. // USHORT portMask;       //  6
  26. // USHORT portMode;       //  8
  27. // USHORT portFlipFlop;   // 10
  28. // USHORT portStatus;     // 12
  29. // UCHAR  maskStatus;     // 14
  30. // UCHAR  maskEnable;     // 15
  31. // UCHAR  maskDisable;    // 16
  32. // UCHAR  typeFdma;       // 17
  33. // USHORT rsv18;          // 18
  34. //} DMACHANNEL_INFO;      // 20 bytes
  35. //
  36. //typedef struct _DMACHANNEL {
  37. // USHORT status;         //  0
  38. // USHORT ch;             //  2 0-3, 5-7
  39. // USHORT type;           //  4 DMA_TYPE_*
  40. // UCHAR  mode;           //  6 data for DMA mode register
  41. // UCHAR  page;           //  7
  42. // UCHAR  addrHi;         //  8
  43. // UCHAR  addrLo;         //  9
  44. // UCHAR  countHi;        // 10
  45. // UCHAR  countLo;        // 11
  46. // DMACHANNEL_INFO chInfo;// 12 setup data (20 bytes)
  47. // ULONG  audioBufferSize;// 32
  48. // ULONG  lastPosition;   // 36
  49. //} DMACHANNEL;           // 40 bytes
  50.  
  51. static DMACHANNEL_INFO dmaInfo[8] = {
  52.  {0x00,0x01,0x87,0x0A,0x0B,0x0C,0x08, 0x10,0x00,0x04,0,0},
  53.  {0x02,0x03,0x83,0x0A,0x0B,0x0C,0x08, 0x20,0x01,0x05,0,0},
  54.  {0x04,0x05,0x81,0x0A,0x0B,0x0C,0x08, 0x40,0x02,0x06,0,0},
  55.  {0x06,0x07,0x82,0x0A,0x0B,0x0C,0x08, 0x80,0x03,0x07,0,0},
  56.  {0xC0,0xC2,0x8F,0xD4,0xD6,0xD8,0xD0, 0x10,0x00,0x04,0,0},
  57.  {0xC4,0xC6,0x8B,0xD4,0xD6,0xD8,0xD0, 0x20,0x01,0x05,0,0},
  58.  {0xC8,0xCA,0x89,0xD4,0xD6,0xD8,0xD0, 0x40,0x02,0x06,0,0},
  59.  {0xCC,0xCE,0x8A,0xD4,0xD6,0xD8,0xD0, 0x80,0x03,0x07,0,0},
  60. };
  61.  
  62.  
  63. // type-F DMA has bits7/6 = 0, so instead of 0x5x for dma???Mode[ch], use 0x1x
  64. // selectively modified at runtime
  65.  
  66. static UCHAR dmaPlayMode[]   = {0x58,0x59,0x5A,0x5B,0x58,0x59,0x5A,0x5B};
  67. static UCHAR dmaCaptureMode[]= {0x54,0x55,0x56,0x57,0x54,0x55,0x56,0x57};
  68.  
  69.  
  70. //-------------------
  71. // in: audioBufferPtr
  72. //out: change in data produced/consumed
  73. //nts: .lastPosition is set to 0 at start
  74.  
  75. ULONG dmaQueryDelta(AUDIOBUFFER *audioBufferPtr) {
  76.  
  77.  ULONG delta, lastPos, pos;
  78.  USHORT count;
  79.  USHORT countLo, countHi;  // use USHORT rather than UCHAR so can << 8
  80.  
  81.  0000  53                dmaQueryDelta_  push    bx
  82.  0001  51                                push    cx
  83.  0002  56                                push    si
  84.  0003  57                                push    di
  85.  0004  55                                push    bp
  86.  0005  89 e5                             mov     bp,sp
  87.  0007  83 ec 02                          sub     sp,0002H
  88.  000a  89 c3                             mov     bx,ax
  89.  
  90.  lastPos = audioBufferPtr->dmaCh.lastPosition;
  91.  
  92.  //NOTE: if autoinit mode then count register will NEVER read FFFF since it gets
  93.  //      reloaded with the base count -- that means count reaches 0 as "lowest"
  94.  //      -- here's a sample frequency distribution over 8192 trips through a 32KB
  95.  //      dma buffer, where for x=n, x is the count value and n is the freq of that count
  96.  //      (so, count reg=0 came up 60 times out of 8192...interesting that 7FFE is 0...
  97.  //      ...which is probably caused by IRQ handler being active, see second freqdist)
  98.  //
  99.  //      irq on:  0=60, 1=72, 2=45, 3=259, 7FFE=0,  7FFF=45, 8000=0, FFFF=0
  100.  //      irq off: 0=62, 1=72, 2=46, 3=259, 7FFE=55, 7FFF=248, 8000=0, FFFF=0
  101.  //
  102.  //      if it were a random event (it's not!), expect count for each
  103.  //      would be 0.25 (8192 div 32768) -- see bottom of this file for count test tracker
  104.  //
  105.  // this gets the current position of the channel, from 0 to size of dma buffer-1
  106.  // the port count register is decremented after each xfer
  107.  // it goes from 0 to FFFF at the last byte to xfer (that's why it's setup with count-1)
  108.  
  109.  000c  8b 77 44                          mov     si,[bx+44H]
  110.  000f  8b 4f 46                          mov     cx,[bx+46H]
  111.  
  112.  _cli_();
  113.  0012  9c                                pushf   
  114.  0013  fa                                cli     
  115.  0014  30 c0                             xor     al,al
  116.  
  117.  outp(audioBufferPtr->dmaCh.chInfo.portFlipFlop, 0);  // set flipflop
  118.  0016  8b 57 36                          mov     dx,[bx+36H]
  119.  0019  ee                                out     dx,al
  120.  
  121.  countLo = inp(audioBufferPtr->dmaCh.chInfo.portCount);
  122.  001a  8b 57 2e                          mov     dx,[bx+2eH]
  123.  001d  ec                                in      al,dx
  124.  001e  88 46 fe                          mov     [bp-2H],al
  125.  
  126.  countHi = inp(audioBufferPtr->dmaCh.chInfo.portCount);
  127.  0021  8b 57 2e                          mov     dx,[bx+2eH]
  128.  0024  30 e4                             xor     ah,ah
  129.  0026  ec                                in      al,dx
  130.  
  131.  _sti_();
  132.  
  133.  0027  9d                                popf    
  134.  0028  88 66 ff                          mov     [bp-1H],ah
  135.  
  136.  count = (countHi << 8) + countLo;
  137.  
  138.  002b  88 c4                             mov     ah,al
  139.  002d  8b 56 fe                          mov     dx,[bp-2H]
  140.  0030  30 c0                             xor     al,al
  141.  
  142.  if (audioBufferPtr->dmaCh.ch > 3) count = count + count;  // count as words if 16-bit channel
  143.  
  144.  0032  8b 7f 22                          mov     di,[bx+22H]
  145.  0035  01 d0                             add     ax,dx
  146.  0037  83 ff 03                          cmp     di,0003H
  147.  003a  76 02                             jbe     L1
  148.  003c  01 c0                             add     ax,ax
  149.  003e  8b 57 40          L1              mov     dx,[bx+40H]
  150.  
  151.  pos = audioBufferPtr->dmaCh.audioBufferSize - (ULONG)count;
  152.  
  153.  0041  31 ff                             xor     di,di
  154.  0043  29 c2                             sub     dx,ax
  155.  0045  8b 47 42                          mov     ax,[bx+42H]
  156.  0048  19 f8                             sbb     ax,di
  157.  
  158.  if (pos >= lastPos) {
  159.  004a  39 c8                             cmp     ax,cx
  160.  004c  77 06                             ja      L2
  161.  004e  75 12                             jne     L3
  162.  0050  39 f2                             cmp     dx,si
  163.  0052  72 0e                             jb      L3
  164.  
  165.     delta = pos - lastPos;
  166.  }
  167.  0054  89 d7             L2              mov     di,dx
  168.  0056  29 f7                             sub     di,si
  169.  0058  89 fe                             mov     si,di
  170.  005a  89 c7                             mov     di,ax
  171.  005c  19 cf                             sbb     di,cx
  172.  005e  89 f9                             mov     cx,di
  173.  
  174.  else {
  175.  0060  eb 12                             jmp     L4
  176.  
  177.     delta = (audioBufferPtr->dmaCh.audioBufferSize - lastPos) + pos;
  178.  }
  179.  
  180.  0062  8b 7f 40          L3              mov     di,[bx+40H]
  181.  0065  29 f7                             sub     di,si
  182.  0067  89 fe                             mov     si,di
  183.  0069  8b 7f 42                          mov     di,[bx+42H]
  184.  006c  19 cf                             sbb     di,cx
  185.  006e  89 f9                             mov     cx,di
  186.  0070  01 d6                             add     si,dx
  187.  0072  11 c1                             adc     cx,ax
  188.  
  189.  audioBufferPtr->dmaCh.lastPosition = pos;
  190.  
  191.  return delta;
  192.  0074  89 57 44          L4              mov     [bx+44H],dx
  193.  0077  89 47 46                          mov     [bx+46H],ax
  194.  
  195. }
  196.  
  197.  
  198. // ----------------------------------------
  199. // in: wait = uSecs to wait  (micro seconds)
  200. //     audioBufferPtr
  201. //out: n/a
  202. //nts: wait for the DRQ bit to turn off (de-assert) on this DMA channel
  203. //     since some DMA devices won't de-assert their DRQ line if they are stopped while active
  204. //
  205. //     might want to count number of loops spent here...?  but won't solve anything
  206.  
  207.  007a  89 f0                             mov     ax,si
  208.  007c  89 ca                             mov     dx,cx
  209.  007e  89 ec             L5              mov     sp,bp
  210.  0080  5d                                pop     bp
  211.  0081  5f                                pop     di
  212.  0082  5e                                pop     si
  213.  0083  59                                pop     cx
  214.  0084  5b                                pop     bx
  215.  0085  c3                                ret     
  216.  0086  89 c0                             mov     ax,ax
  217.  
  218. VOID dmaWaitForChannel(USHORT count, AUDIOBUFFER *audioBufferPtr) {
  219.  
  220.  0088                    dmaWaitForChannel_:
  221.  0088  53                                push    bx
  222.  0089  51                                push    cx
  223.  008a  56                                push    si
  224.  008b  57                                push    di
  225.  008c  55                                push    bp
  226.  008d  89 e5                             mov     bp,sp
  227.  008f  83 ec 02                          sub     sp,0002H
  228.  0092  89 c3                             mov     bx,ax
  229.  0094  89 d7                             mov     di,dx
  230.  
  231.  USHORT tPort = audioBufferPtr->dmaCh.chInfo.portStatus;
  232.  0096  8b 75 38                          mov     si,[di+38H]
  233.  
  234.  UCHAR tMask = audioBufferPtr->dmaCh.chInfo.maskStatus;
  235.  UCHAR tByte = inp(tPort);
  236.  
  237.  0099  8a 45 3a                          mov     al,[di+3aH]
  238.  
  239.  while ((tByte & tMask) && count) {
  240.  009c  bf 02 00                          mov     di,0002H
  241.  009f  89 f2                             mov     dx,si
  242.  00a1  88 46 fe                          mov     [bp-2H],al
  243.  00a4  ec                L6              in      al,dx
  244.  00a5  30 e4                             xor     ah,ah
  245.  00a7  89 c2                             mov     dx,ax
  246.  00a9  8a 46 fe                          mov     al,[bp-2H]
  247.  00ac  85 c2                             test    dx,ax
  248.  00ae  74 ce                             je      L5
  249.  00b0  85 db                             test    bx,bx
  250.  00b2  74 ca                             je      L5
  251.  
  252.     count--;
  253.     iodelay(WAIT_1US);  // was DMA_IO_WAIT (which is the same thing: 2)
  254.  00b4  4b                                dec     bx
  255.  00b5  89 f9                             mov     cx,di
  256.  
  257.     tByte = inp(tPort);
  258.  00b7  89 f2                             mov     dx,si
  259.  00b9  e8 00 00                          call    iodelay_
  260.  
  261.  }
  262.  
  263.  return;
  264. }
  265.  
  266.  
  267. // ----------------------------------------
  268. // in: audioBufferPtr
  269. //out: n/a
  270. //nts: starts the DMA channel (info setup in InitDMA())
  271.  
  272.  00bc  eb e6                             jmp     L6
  273.  00be  89 c0                             mov     ax,ax
  274.  
  275. VOID dmaStart(AUDIOBUFFER *audioBufferPtr) {
  276.  
  277.  UCHAR mode;
  278.  
  279.  00c0  53                dmaStart_       push    bx
  280.  00c1  52                                push    dx
  281.  00c2  89 c3                             mov     bx,ax
  282.  
  283.  audioBufferPtr->dmaCh.lastPosition = 0;
  284.  
  285.  mode = audioBufferPtr->dmaCh.mode;
  286.  00c4  c7 47 44 00 00                    mov     word ptr [bx+44H],0000H
  287.  00c9  c7 47 46 00 00                    mov     word ptr [bx+46H],0000H
  288.  
  289.  00ce  8a 57 3d                          mov     dl,[bx+3dH]
  290.  
  291.  if (audioBufferPtr->dmaCh.chInfo.typeFdma) mode = mode & 0x3F;  // use demand mode if typeF DMA
  292.  
  293.  00d1  8a 67 26                          mov     ah,[bx+26H]
  294.  00d4  84 d2                             test    dl,dl
  295.  00d6  74 03                             je      L7
  296.  00d8  80 e4 3f                          and     ah,3fH
  297.  
  298.  _cli_();
  299.  00db  9c                L7              pushf   
  300.  00dc  fa                                cli     
  301.  
  302.  outp(audioBufferPtr->dmaCh.chInfo.portMask, audioBufferPtr->dmaCh.chInfo.maskDisable); // disable channel
  303.  00dd  8a 47 3c                          mov     al,[bx+3cH]
  304.  00e0  8b 57 32                          mov     dx,[bx+32H]
  305.  00e3  ee                                out     dx,al
  306.  00e4  88 e0                             mov     al,ah
  307.  
  308.  outp(audioBufferPtr->dmaCh.chInfo.portMode, mode);  // set mode
  309.  00e6  8b 57 34                          mov     dx,[bx+34H]
  310.  00e9  ee                                out     dx,al
  311.  
  312.  outp(audioBufferPtr->dmaCh.chInfo.portPage, audioBufferPtr->dmaCh.page); // set page
  313.  00ea  8a 47 27                          mov     al,[bx+27H]
  314.  00ed  8b 57 30                          mov     dx,[bx+30H]
  315.  00f0  ee                                out     dx,al
  316.  
  317.  outp(audioBufferPtr->dmaCh.chInfo.portFlipFlop, 0); // set flip-flop
  318.  00f1  8b 57 36                          mov     dx,[bx+36H]
  319.  00f4  30 c0                             xor     al,al
  320.  00f6  ee                                out     dx,al
  321.  
  322.  outp(audioBufferPtr->dmaCh.chInfo.portAddr, audioBufferPtr->dmaCh.addrLo); // set low address
  323.  00f7  8a 47 29                          mov     al,[bx+29H]
  324.  00fa  8b 57 2c                          mov     dx,[bx+2cH]
  325.  00fd  ee                                out     dx,al
  326.  
  327.  outp(audioBufferPtr->dmaCh.chInfo.portAddr, audioBufferPtr->dmaCh.addrHi); // set high
  328.  00fe  8a 47 28                          mov     al,[bx+28H]
  329.  0101  8b 57 2c                          mov     dx,[bx+2cH]
  330.  0104  ee                                out     dx,al
  331.  
  332.  outp(audioBufferPtr->dmaCh.chInfo.portFlipFlop, 0); // set flip-flop
  333.  0105  8b 57 36                          mov     dx,[bx+36H]
  334.  0108  30 c0                             xor     al,al
  335.  010a  ee                                out     dx,al
  336.  
  337.  outp(audioBufferPtr->dmaCh.chInfo.portCount, audioBufferPtr->dmaCh.countLo); // set low count
  338.  010b  8a 47 2b                          mov     al,[bx+2bH]
  339.  010e  8b 57 2e                          mov     dx,[bx+2eH]
  340.  0111  ee                                out     dx,al
  341.  
  342.  outp(audioBufferPtr->dmaCh.chInfo.portCount, audioBufferPtr->dmaCh.countHi); // set high
  343.  0112  8a 47 2a                          mov     al,[bx+2aH]
  344.  0115  8b 57 2e                          mov     dx,[bx+2eH]
  345.  0118  ee                                out     dx,al
  346.  
  347.  outp(audioBufferPtr->dmaCh.chInfo.portMask, audioBufferPtr->dmaCh.chInfo.maskEnable); // enable channel
  348.  0119  8a 47 3b                          mov     al,[bx+3bH]
  349.  011c  8b 57 32                          mov     dx,[bx+32H]
  350.  011f  ee                                out     dx,al
  351.  
  352.  _sti_();
  353.  
  354.  return;
  355.  0120  9d                                popf    
  356.  
  357. }
  358.  
  359.  
  360. // ----------------------------------------
  361. // in: audioBufferPtr
  362. //out: n/a
  363. //nts: stops the DMA channel
  364.  
  365.  0121  5a                                pop     dx
  366.  0122  5b                                pop     bx
  367.  0123  c3                                ret     
  368.  
  369. VOID dmaStop(AUDIOBUFFER *audioBufferPtr) {
  370.  
  371.  0124  53                dmaStop_        push    bx
  372.  0125  52                                push    dx
  373.  0126  89 c3                             mov     bx,ax
  374.  
  375.  outp(audioBufferPtr->dmaCh.chInfo.portMask, audioBufferPtr->dmaCh.chInfo.maskDisable); // disable channel
  376.  
  377.  return;
  378.  0128  8a 47 3c                          mov     al,[bx+3cH]
  379.  012b  8b 57 32                          mov     dx,[bx+32H]
  380.  012e  ee                                out     dx,al
  381.  
  382. }
  383.  
  384.  
  385. // ----------------------------------------
  386. // in: audioBufferPtr
  387. //     mode  0=single, 1=demand
  388. //out: last mode type
  389. //nts: sets DMA mode type (demand mode or single mode)
  390.  
  391.  012f  5a                                pop     dx
  392.  0130  5b                                pop     bx
  393.  0131  c3                                ret     
  394.  0132  89 c0                             mov     ax,ax
  395.  
  396. USHORT dmaSetModeType(AUDIOBUFFER *audioBufferPtr, USHORT mode) {
  397.  
  398.  0134  53                dmaSetModeType_ push    bx
  399.  0135  89 c3                             mov     bx,ax
  400.  
  401.  USHORT lastType = audioBufferPtr->dmaCh.chInfo.typeFdma;
  402.  
  403.  0137  8a 47 3d                          mov     al,[bx+3dH]
  404.  013a  30 e4                             xor     ah,ah
  405.  
  406.  if (mode) {
  407.     audioBufferPtr->dmaCh.chInfo.typeFdma = 1;
  408.  }
  409.  else {
  410.     audioBufferPtr->dmaCh.chInfo.typeFdma = 0;
  411.  }
  412.  
  413.  return lastType;
  414.  013c  85 d2                             test    dx,dx
  415.  013e  0f 95 c2                          setne   dl
  416.  0141  88 57 3d                          mov     [bx+3dH],dl
  417.  
  418. }
  419.  
  420.  
  421. // ----------------------------------------
  422. // in: channel = 0-3,5-7
  423. //     dmaType = see cs40.h (also comes in with special flag here: bit8=1 to use type F dma)
  424. //     audioBufferPtr
  425. //out:
  426. //nts: dma constructor
  427. //     must be sure to always have dmaType piggy-backed with DMA_TYPE_FTYPE bit flag set as needed
  428. //     called more than just from init
  429.  
  430.  0144  5b                                pop     bx
  431.  0145  c3                                ret     
  432.  0146  89 c0                             mov     ax,ax
  433.  
  434. USHORT dmaInit(USHORT dmaChannel, USHORT dmaType, AUDIOBUFFER *audioBufferPtr) {
  435.  
  436.  ULONG bufferPhysAddr, count;
  437.  USHORT typeFdma;
  438.  
  439.  0148  51                dmaInit_        push    cx
  440.  0149  56                                push    si
  441.  014a  57                                push    di
  442.  014b  55                                push    bp
  443.  014c  89 e5                             mov     bp,sp
  444.  014e  83 ec 06                          sub     sp,0006H
  445.  0151  89 46 fe                          mov     [bp-2H],ax
  446.  
  447.  typeFdma = dmaType & DMA_TYPE_FTYPE;   // bit8=1
  448.  0154  89 d0                             mov     ax,dx
  449.  0156  30 d0                             xor     al,dl
  450.  0158  80 e4 01                          and     ah,01H
  451.  
  452.  dmaType = dmaType & ~DMA_TYPE_FTYPE;
  453.  
  454.  015b  80 e6 fe                          and     dh,0feH
  455.  015e  89 46 fc                          mov     [bp-4H],ax
  456.  
  457.  if ((dmaType & DMA_TYPE_ISA) == 0) return 87;  // whatever
  458.  0161  f6 c2 08                          test    dl,08H
  459.  0164  75 06                             jne     L8
  460.  0166  b8 57 00                          mov     ax,0057H
  461.  0169  e9 c3 00                          jmp     L15
  462.  
  463.  if (dmaChannel > 7 || dmaChannel == 2 || dmaChannel == 4) return 87;
  464.  
  465.  016c  8b 4e fe          L8              mov     cx,[bp-2H]
  466.  016f  83 f9 07                          cmp     cx,0007H
  467.  0172  77 0a                             ja      L9
  468.  0174  83 f9 02                          cmp     cx,0002H
  469.  0177  74 05                             je      L9
  470.  0179  83 f9 04                          cmp     cx,0004H
  471.  017c  75 0a                             jne     L10
  472.  017e  b8 57 00          L9              mov     ax,0057H
  473.  0181  89 ec                             mov     sp,bp
  474.  0183  5d                                pop     bp
  475.  0184  5f                                pop     di
  476.  0185  5e                                pop     si
  477.  0186  59                                pop     cx
  478.  0187  c3                                ret     
  479.  
  480.  audioBufferPtr->dmaCh.ch = dmaChannel;
  481.  0188  89 ce             L10             mov     si,cx
  482.  018a  89 4f 22                          mov     [bx+22H],cx
  483.  018d  8c d8                             mov     ax,ds
  484.  
  485.  audioBufferPtr->dmaCh.type = dmaType;
  486.  
  487.  018f  89 57 24                          mov     [bx+24H],dx
  488.  
  489.  audioBufferPtr->dmaCh.chInfo = dmaInfo[dmaChannel]; // whoa! structure copy
  490.  
  491.  0192  c1 e6 02                          shl     si,02H
  492.  0195  8e c0                             mov     es,ax
  493.  
  494.  if ((dmaType & DMA_TYPE_DIRECTION) == DMA_TYPE_CAPTURE) {
  495.  0197  30 f6                             xor     dh,dh
  496.  0199  01 ce                             add     si,cx
  497.  019b  8d 7f 2c                          lea     di,[bx+2cH]
  498.  019e  c1 e6 02                          shl     si,02H
  499.  01a1  b9 0a 00                          mov     cx,000aH
  500.  01a4  8d b4 00 00                       lea     si,[si+_dmaInfo]
  501.  01a8  80 e2 01                          and     dl,01H
  502.  01ab  f3 a5                             repe    movsw    
  503.  01ad  83 fa 01                          cmp     dx,0001H
  504.  01b0  75 09                             jne     L11
  505.  
  506.     audioBufferPtr->dmaCh.mode = dmaCaptureMode[dmaChannel];
  507.  }
  508.  01b2  8b 76 fe                          mov     si,[bp-2H]
  509.  01b5  8a 84 00 00                       mov     al,[si+_dmaCaptureMode]
  510.  
  511.  else {
  512.  01b9  eb 07                             jmp     L12
  513.  
  514.     audioBufferPtr->dmaCh.mode = dmaPlayMode[dmaChannel];
  515.  }
  516.  
  517.  // doing demand mode DMA instead of single improves performance a lot:
  518.  //    55% CPU use to 28% on 486
  519.  // this picked up each time dma is started, so can be changed at runtime
  520.  // just by chaning abPtr->dmaCh.chInfo.typeFdma (via dmaSetModeType())
  521.  // may also want to look at chipsetSetDTM(USHORT dtmFlag)
  522.  
  523.  01bb  8b 76 fe          L11             mov     si,[bp-2H]
  524.  01be  8a 84 00 00                       mov     al,[si+_dmaPlayMode]
  525.  01c2  88 47 26          L12             mov     [bx+26H],al
  526.  
  527.  dmaSetModeType(audioBufferPtr, typeFdma);
  528.  
  529.  // while it seems redundant to have both dmaCh.audioBufferSize and ab.bufferSize (and ws.bufferSize)
  530.  // it serves its purpose since dmaCh.audioBufferSize is only set here and so
  531.  // I can call here to re-size logical buffer size
  532.  
  533.  01c5  8b 56 fc                          mov     dx,[bp-4H]
  534.  01c8  85 d2                             test    dx,dx
  535.  01ca  0f 95 c0                          setne   al
  536.  01cd  88 47 3d                          mov     [bx+3dH],al
  537.  01d0  8b 57 12                          mov     dx,[bx+12H]
  538.  
  539.  count = audioBufferPtr->bufferSize;
  540.  audioBufferPtr->dmaCh.audioBufferSize = count;
  541.  
  542.  01d3  8b 47 10                          mov     ax,[bx+10H]
  543.  01d6  89 57 42                          mov     [bx+42H],dx
  544.  
  545.  if (dmaChannel > 3) {
  546.  01d9  8b 4e fe                          mov     cx,[bp-2H]
  547.  01dc  89 47 40                          mov     [bx+40H],ax
  548.  01df  83 f9 03                          cmp     cx,0003H
  549.  01e2  76 06                             jbe     L13
  550.  
  551.     count = count >> 1;  // word count (apparently don't need to -1 as do with 8 bit DMA channel)
  552.  }
  553.  01e4  d1 ea                             shr     dx,1
  554.  01e6  d1 d8                             rcr     ax,1
  555.  
  556.  else {
  557.  01e8  eb 06                             jmp     L14
  558.  
  559.     count = count - 1;
  560.  }
  561.  
  562.  01ea  05 ff ff          L13             add     ax,0ffffH
  563.  01ed  83 d2 ff                          adc     dx,0ffffH
  564.  
  565.  audioBufferPtr->dmaCh.countHi = (UCHAR)(count >> 8);
  566.  01f0  89 c6             L14             mov     si,ax
  567.  01f2  89 d7                             mov     di,dx
  568.  01f4  b1 08                             mov     cl,08H
  569.  01f6  d3 ee                             shr     si,cl
  570.  01f8  d3 cf                             ror     di,cl
  571.  01fa  31 fe                             xor     si,di
  572.  01fc  81 e7 ff 00                       and     di,00ffH
  573.  0200  31 fe                             xor     si,di
  574.  
  575.  audioBufferPtr->dmaCh.countLo = (UCHAR)count;
  576.  
  577.  0202  88 47 2b                          mov     [bx+2bH],al
  578.  0205  89 f2                             mov     dx,si
  579.  0207  88 57 2a                          mov     [bx+2aH],dl
  580.  
  581.  bufferPhysAddr = audioBufferPtr->bufferPhysAddr;
  582.  
  583.  020a  8b 47 0c                          mov     ax,[bx+0cH]
  584.  020d  8b 57 0e                          mov     dx,[bx+0eH]
  585.  0210  89 46 fa                          mov     [bp-6H],ax
  586.  
  587.  audioBufferPtr->dmaCh.page = (UCHAR)(bufferPhysAddr >> 16);
  588.  0213  88 57 27                          mov     [bx+27H],dl
  589.  
  590.  audioBufferPtr->dmaCh.addrHi = (UCHAR)(bufferPhysAddr >> 8);
  591.  0216  b1 08                             mov     cl,08H
  592.  0218  d3 e8                             shr     ax,cl
  593.  021a  d3 ca                             ror     dx,cl
  594.  021c  31 d0                             xor     ax,dx
  595.  021e  81 e2 ff 00                       and     dx,00ffH
  596.  0222  31 d0                             xor     ax,dx
  597.  0224  88 47 28                          mov     [bx+28H],al
  598.  
  599.  audioBufferPtr->dmaCh.addrLo = (UCHAR)bufferPhysAddr;
  600.  
  601.  0227  8a 46 fa                          mov     al,[bp-6H]
  602.  022a  88 47 29                          mov     [bx+29H],al
  603.  
  604.  return 0;
  605.  022d  31 c0                             xor     ax,ax
  606.  
  607. }
  608.  
  609.  
  610. // ----------------------------------------
  611. // in: audioBufferPtr
  612. //out:
  613. //nts: dma destructor
  614. //     assumes is running...probably doesn't matter if it isn't
  615.  
  616.  022f  89 ec             L15             mov     sp,bp
  617.  0231  5d                                pop     bp
  618.  0232  5f                                pop     di
  619.  0233  5e                                pop     si
  620.  0234  59                                pop     cx
  621.  0235  c3                                ret     
  622.  0236  89 c0                             mov     ax,ax
  623.  
  624. USHORT dmaDeinit(AUDIOBUFFER *audioBufferPtr) {
  625.  
  626.  0238  53                dmaDeinit_      push    bx
  627.  0239  52                                push    dx
  628.  023a  89 c3                             mov     bx,ax
  629.  
  630.  dmaStop(audioBufferPtr);
  631.  
  632.  return 0;
  633.  023c  8a 47 3c                          mov     al,[bx+3cH]
  634.  023f  8b 57 32                          mov     dx,[bx+32H]
  635.  0242  ee                                out     dx,al
  636.  
  637. }
  638.  
  639.  0243  31 c0                             xor     ax,ax
  640.  0245  5a                                pop     dx
  641.  0246  5b                                pop     bx
  642.  0247  c3                                ret     
  643.  
  644. No disassembly errors
  645.  
  646. List of external symbols
  647.  
  648. Symbol
  649. ----------------
  650. iodelay_         000000ba
  651. _dmaInfo         000001a6
  652. _dmaCaptureMode  000001b7
  653. _dmaPlayMode     000001c0
  654. ------------------------------------------------------------
  655.  
  656. Segment: _DATA  WORD   000000b0 bytes  
  657.  0000  00 00 01 00 87 00 0a 00 _dmaInfo        - ........
  658.  0008  0b 00 0c 00 08 00 10 00                 - ........
  659.  0010  04 00 00 00 02 00 03 00                 - ........
  660.  0018  83 00 0a 00 0b 00 0c 00                 - ........
  661.  0020  08 00 20 01 05 00 00 00                 - .. .....
  662.  0028  04 00 05 00 81 00 0a 00                 - ........
  663.  0030  0b 00 0c 00 08 00 40 02                 - ......@.
  664.  0038  06 00 00 00 06 00 07 00                 - ........
  665.  0040  82 00 0a 00 0b 00 0c 00                 - ........
  666.  0048  08 00 80 03 07 00 00 00                 - ........
  667.  0050  c0 00 c2 00 8f 00 d4 00                 - ........
  668.  0058  d6 00 d8 00 d0 00 10 00                 - ........
  669.  0060  04 00 00 00 c4 00 c6 00                 - ........
  670.  0068  8b 00 d4 00 d6 00 d8 00                 - ........
  671.  0070  d0 00 20 01 05 00 00 00                 - .. .....
  672.  0078  c8 00 ca 00 89 00 d4 00                 - ........
  673.  0080  d6 00 d8 00 d0 00 40 02                 - ......@.
  674.  0088  06 00 00 00 cc 00 ce 00                 - ........
  675.  0090  8a 00 d4 00 d6 00 d8 00                 - ........
  676.  0098  d0 00 80 03 07 00 00 00                 - ........
  677.  00a0  58 59 5a 5b 58 59 5a 5b _dmaPlayMode    - XYZ[XYZ[
  678.  00a8  54 55 56 57 54 55 56 57 _dmaCaptureMode - TUVWTUVW
  679.  
  680. No disassembly errors
  681.  
  682. ------------------------------------------------------------
  683. List of public symbols
  684.  
  685. SYMBOL          GROUP           SEGMENT          ADDRESS
  686. ---------------------------------------------------------
  687. _dmaCaptureMode DGROUP          _DATA            000000a8
  688. _dmaInfo        DGROUP          _DATA            00000000
  689. _dmaPlayMode    DGROUP          _DATA            000000a0
  690. dmaDeinit_                      _TEXT            00000238
  691. dmaInit_                        _TEXT            00000148
  692. dmaQueryDelta_                  _TEXT            00000000
  693. dmaSetModeType_                 _TEXT            00000134
  694. dmaStart_                       _TEXT            000000c0
  695. dmaStop_                        _TEXT            00000124
  696. dmaWaitForChannel_ 
  697.                                 _TEXT            00000088
  698.  
  699. ------------------------------------------------------------
  700.  
  701.