Subversion Repositories Kolibri OS

Rev

Rev 802 | Blame | Last modification | View Log | Download | RSS feed

  1. ;--------------------------------
  2. ;        program dma
  3. ;--------------------------------
  4. sb_set_dma:
  5.          mov ebx,[sound_dma]
  6.          lea eax,[ebx+4] ;mask required channel
  7.          cmp bl,4
  8.          ja  .use_second_dma_controller
  9.          jb  @f
  10. .dma_setup_error:
  11. if DEBUG
  12.          mov esi,msgErrDMAsetup
  13.          call SysMsgBoardStr
  14. end if
  15.          mov dword[esp],START.stop
  16.          ret
  17. @@:
  18. if use_cli_sti
  19.          cli        ;here to minimize time with disabled ints
  20. end if
  21.          out 0xA,al ;mask required channel
  22.  
  23.          xor eax,eax
  24.          out 0xC,al ;clear byte pointer flip-flop register
  25.  
  26.          lea eax,[ebx+0x58] ;auto-init mode for channel (ebx)
  27.          out 0xB,al ;DMA channel 0-3 mode register
  28.  
  29.          movzx edx,byte[ebx+dma_table] ;page register
  30.          mov   al,DMAPage
  31.          out   dx,al
  32.  
  33.          lea edx,[ebx*2] ;DMA channel 0-3 base address
  34.  
  35.          mov al,0   ;LSB is 0
  36.          out dx,al
  37.  
  38. ;        mov al,0   ;MSB is 0 too
  39.          out dx,al
  40.  
  41.          inc edx    ;DMA channel 0-3 byte count
  42.  
  43.          mov al,((sb_buffer_size-1) and 0xff)
  44.          out dx,al
  45.  
  46.          mov al,((sb_buffer_size-1) shr 8) ;it is the same
  47.          out dx,al
  48.  
  49.          mov eax,ebx ;unmask DMA channel
  50.          out 0xA,al
  51.  
  52. if use_cli_sti
  53.          sti
  54. end if
  55.          ret
  56.  
  57. .use_second_dma_controller:
  58.          cmp bl,7
  59.          ja .dma_setup_error
  60.  
  61.          sub bl,4
  62.          sub al,4
  63. if use_cli_sti
  64.          cli        ;here to minimize time with disabled ints
  65. end if
  66.          out 0xD4,al ;mask required channel
  67.  
  68.          xor eax,eax
  69.          out 0xD8,al ;clear byte pointer flip-flop register
  70.  
  71.          lea eax,[ebx+0x58] ;auto-init mode for channel (ebx+4)
  72.          out 0xD6,al ;DMA channel 4-7 mode register
  73.  
  74.          movzx edx,byte[ebx+dma_table+4] ;page register
  75.          mov   al,DMAPage
  76.          out   dx,al
  77.  
  78.          lea edx,[ebx*4+0xC0] ;DMA channel 4-7 base address
  79.  
  80.          mov al,0   ;LSB is 0 ;for 16bit DMA this contains
  81.          out dx,al  ;A1-A8 lines of address bus, A0 is zero
  82.  
  83. ;        mov al,0   ;MSB is 0 too ;for 16bit DMA this contains
  84.          out dx,al  ;A9-A16 lines of address bus
  85.  
  86.          inc edx
  87.          inc edx    ;DMA channel 4-7 16bit word count
  88.  
  89.          mov al,(((sb_buffer_size/2)-1) and 0xff)
  90.          out dx,al
  91.  
  92.          mov al,(((sb_buffer_size/2)-1) shr 8)
  93.          out dx,al
  94.  
  95.          mov eax,ebx ;unmask DMA channel
  96.          out 0xD4,al
  97.  
  98. if use_cli_sti
  99.          sti
  100. end if
  101.          ret
  102. ;-------------------------------------------------------------------------------
  103. ;       out byte to SB DSP's write port
  104. ;-------------------------------------------------------------------------------
  105. macro   sb_out data_to_out {
  106. @@:
  107.         in   al,dx
  108.         test al,al  ;is DSP busy?
  109.         js   @b     ;it's busy
  110.         mov  al,data_to_out ;it's free
  111.         out  dx,al
  112. }
  113. ;-------------------------------------------------------------------------------
  114. ;       stop playing
  115. ;-------------------------------------------------------------------------------
  116. proc sb_stop
  117.         mov  edx,[sb_base_port]
  118.         add  dl,0xC
  119.         sb_out 0xD3 ;turn the speaker off
  120.         sb_out 0xDA ;exit 8bit DMA
  121.         sb_out 0xD9 ;exit 16bit DMA
  122.         ret
  123. endp
  124. ;-------------------------------------------------------------------------------
  125. ;       start playing
  126. ;-------------------------------------------------------------------------------
  127. proc sb_play
  128.         and  [int_flip_flop],0
  129.         mov  edx,[sb_base_port]
  130.         add  dl,0xC
  131.         sb_out 0xD1 ;turn speaker on
  132. ;        sb_out 0x48 ;set DSP transfer size  ;for older cards, not supported
  133. ;                                            ;in this version
  134. ;        mov  ax,32767 ;(64k)/2-1
  135. ;@@:                 ;out the low byte...
  136. ;        in   al,dx
  137. ;        test al,al  ;is DSP busy?
  138. ;        js   @b     ;it's busy
  139. ;        out  dx,al
  140.  
  141. ;        mov  al,ah  ;...then the high byte
  142. ;@@:
  143. ;        in   al,dx
  144. ;        test al,al  ;is DSP busy?
  145. ;        js   @b     ;it's busy
  146. ;        out  dx,al
  147.  
  148. ;        sb_out 0x1C ;auto-init 8bit playback
  149.  
  150. ;              0xBXh - 16 bit DMA mode
  151. ;              ||||
  152.         sb_out 10110110b ;bCommand
  153. ;                  ||||
  154. ;                  |||+-reserved
  155. ;                  ||+--turn FIFO on (0 for off)
  156. ;                  |+---auto-init mode on (0 for off)
  157. ;                  +----A/D: 0-output, 1-input
  158. ;                +------stereo on
  159. ;                |+-----unsigned (1 for signed)
  160. ;                ||
  161.         sb_out 00110000b ;bMode
  162. ;              ||  ||||
  163. ;              ---------reserved
  164. ;wSize is a number of 16bit samples less 1. For auto-init mode each half
  165. ;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples
  166.         sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte
  167.         sb_out (((sb_buffer_size/2/2)-1) shr 8)    ;wSize.HighByte
  168.         ret
  169. endp
  170. ;-------------------------------------------------------------------------------
  171. ;       reset DSP
  172. ;-------------------------------------------------------------------------------
  173. proc sb_reset
  174.         and  [int_flip_flop],0
  175.         mov  edx,[sb_base_port]
  176.         add  dl,6
  177.         mov  al,1   ;start DSP reset
  178.  
  179. if use_cli_sti
  180.         cli         ;here to minimize time with disabled ints
  181. end if
  182.         out  dx,al
  183.         mov  ecx,40 ;wait at least 3 microsec.
  184. @@:
  185.         in   al,dx
  186.         loop @b
  187.  
  188.         xor  eax,eax    ;stop DSP reset
  189. if use_cli_sti
  190.         sti
  191. end if
  192.         out  dx,al
  193.         ret
  194. endp
  195.  
  196. ;-------------------------------------------------------------------------------
  197. ;       set the rate for playing, enable stereo
  198. ;-------------------------------------------------------------------------------
  199. proc sb_setup
  200.         mov  edx,[sb_base_port]
  201.         add  dl,0xC
  202.         sb_out 40h  ;set time constant, this is for old cards
  203.         sb_out sb_tc
  204.  
  205.         sb_out 41h  ;set sound rate, this can only SB16
  206.         sb_out (sb_out_rate shr 8)    ;first high byte (MSB)
  207.         sb_out (sb_out_rate and 0xff) ;then low byte (LSB)
  208.  
  209. ;        mov  al,0xE  ;for older cards, not supported in this version
  210. ;        sub  dl,(0xC-4) ;talk to SB's mixer
  211. ;        out  dx,al      ;select this register of the mixer
  212. ;        mov  ecx,6      ;wait for the chip
  213. ;@@:
  214. ;        in   al,dx
  215. ;        loop @b
  216.  
  217. ;        inc  edx        ;now read the data port
  218. ;        in   al,dx
  219. ;        or   al,22h     ;turn on stereo
  220. ;        mov  ah,al
  221.  
  222. ;        mov  al,0xE
  223. ;        dec  edx        ;talk to SB's mixer
  224. ;        out  dx,al      ;select this register of the mixer
  225.  
  226. ;        mov  ecx,6      ;wait for the chip
  227. ;@@:
  228. ;        in   al,dx
  229. ;        loop @b
  230.  
  231. ;        inc  edx        ;now send data to the data port
  232. ;        mov  al,ah
  233. ;        out  dx,al
  234.  
  235. ;        dec   edx
  236. ;        mov   ecx,35     ;wait for the chip
  237. ;@@:
  238. ;        in   al,dx
  239. ;        loop @b
  240.         ret
  241. endp
  242.  
  243. ;-------------------------------------------------------------------------------
  244. ;       set master volume of SB mixer, note, not only SB16 but SBPro and older
  245. ;       this is the first step to more full support for hardware
  246. ;-------------------------------------------------------------------------------
  247. ;in: eax in range [-10000;0] - master volume for _both_ channels
  248. ;note that x*3*17/2000 and x*3/2000*17 are not the same numbers,
  249. ;because we count in integers
  250. proc sb_set_master_vol
  251.         mov  [sb_master_vol],eax
  252.         add  eax,10000 ;SB sound level rise from 0 to MAX_LEVEL
  253.         lea  eax,[eax+eax*2] ;*3
  254.         mov  ebx,2000  ;divisor
  255.         xor  edx,edx
  256.         cmp  byte[sb_DSP_version_int],4
  257.         jae  @f       ;SBPro's MAX_LEVEL is 15, but we *11 because
  258.                       ;volume byte looks like that: 0xLR, where L - left
  259.                       ;channel volume, R - right, 0<=R,L<=15
  260.         div  ebx
  261.         imul eax,17
  262.         mov  edx,[sb_base_port]
  263.         push eax      ;here for optimisation
  264.         add  dl,4
  265.         mov  al,0x22  ;write mixer register 0x22
  266.         out  dx,al
  267.         in   al,dx    ;wait for the chip ;6
  268.         in   al,dx    ;wait for the chip ;5
  269.         in   al,dx    ;wait for the chip ;4
  270.         in   al,dx    ;wait for the chip ;3
  271.         in   al,dx    ;wait for the chip ;2
  272.         in   al,dx    ;wait for the chip ;1
  273.         pop  eax                         ;go!
  274.         inc  edx
  275.         out  dx,al
  276.         ret
  277. @@:                   ;SB16's MAX_LEVEL is 255
  278.         imul eax,17
  279.         div  ebx
  280.         mov  edx,[sb_base_port]
  281.         push eax      ;here for optimisation
  282.         add  dl,4
  283.         mov  al,0x30  ;left speaker
  284.         out  dx,al
  285.         pop  eax      ;<--+
  286.         inc  edx      ;   \/
  287.         push eax      ;here for optimisation
  288.         out  dx,al    ;write
  289.         dec  edx
  290.         mov  al,0x31  ;right speaker
  291.         out  dx,al
  292.         pop  eax
  293.         inc  edx
  294.         out  dx,al    ;write
  295.         ret
  296. endp
  297. ;-------------------------------------------------------------------------------
  298.