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