source: sbliveos2/trunk/lib32/sound.c@ 172

Last change on this file since 172 was 153, checked in by sandervl, 25 years ago

update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.7 KB
Line 
1/* $Id: sound.c 153 2000-07-23 16:21:57Z sandervl $ */
2
3//******************************************************************************
4// MMPM/2 to OSS interface translation layer
5//
6// Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License as
10// published by the Free Software Foundation; either version 2 of
11// the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public
19// License along with this program; if not, write to the Free
20// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21// USA.
22//
23//******************************************************************************
24//Note: Opening and closing the mixer device for each mixer command might
25// not be a good idea if the SB Live code changes. (right now it hardly
26// matters)
27#include "hwaccess.h"
28#include <linux/init.h>
29#include <linux/poll.h>
30#include <asm/uaccess.h>
31#include <asm/hardirq.h>
32#include "..\sblive\icardmid.h"
33#include "..\sblive\cardmi.h"
34#include "..\sblive\midi.h"
35
36#define LINUX
37#include <ossidc.h>
38#include <stacktoflat.h>
39
40struct file_operations oss_devices[OSS_MAX_DEVICES] = {0};
41
42//******************************************************************************
43//******************************************************************************
44int register_sound_special(struct file_operations *fops, int unit)
45{
46 memcpy(&oss_devices[OSS_SPECIALID], fops, sizeof(struct file_operations));
47 return OSS_SPECIALID;
48}
49//******************************************************************************
50//******************************************************************************
51int register_sound_mixer(struct file_operations *fops, int dev)
52{
53 memcpy(&oss_devices[OSS_MIXERID], fops, sizeof(struct file_operations));
54 return OSS_MIXERID;
55}
56//******************************************************************************
57//******************************************************************************
58int register_sound_midi(struct file_operations *fops, int dev)
59{
60 memcpy(&oss_devices[OSS_MIDIID], fops, sizeof(struct file_operations));
61 return OSS_MIDIID;
62}
63//******************************************************************************
64//******************************************************************************
65int register_sound_dsp(struct file_operations *fops, int dev)
66{
67 memcpy(&oss_devices[OSS_DSPID], fops, sizeof(struct file_operations));
68 return OSS_DSPID;
69}
70//******************************************************************************
71//******************************************************************************
72int register_sound_synth(struct file_operations *fops, int dev)
73{
74 memcpy(&oss_devices[OSS_SYNTHID], fops, sizeof(struct file_operations));
75 return OSS_SYNTHID;
76}
77//******************************************************************************
78//******************************************************************************
79void unregister_sound_special(int unit)
80{
81 memset(&oss_devices[OSS_SPECIALID], 0, sizeof(struct file_operations));
82}
83//******************************************************************************
84//******************************************************************************
85void unregister_sound_mixer(int unit)
86{
87 memset(&oss_devices[OSS_MIXERID], 0, sizeof(struct file_operations));
88}
89//******************************************************************************
90//******************************************************************************
91void unregister_sound_midi(int unit)
92{
93 memset(&oss_devices[OSS_MIDIID], 0, sizeof(struct file_operations));
94}
95//******************************************************************************
96//******************************************************************************
97void unregister_sound_dsp(int unit)
98{
99 memset(&oss_devices[OSS_DSPID], 0, sizeof(struct file_operations));
100}
101//******************************************************************************
102//******************************************************************************
103void unregister_sound_synth(int unit)
104{
105 memset(&oss_devices[OSS_SYNTHID], 0, sizeof(struct file_operations));
106}
107//******************************************************************************
108//******************************************************************************
109ULONG OSS32_StreamOpen(ULONG streamtype)
110{
111struct inode ossinode;
112struct file ossfile;
113ULONG ossid = streamtype & OSS_IDMASK;
114
115 ossinode.i_rdev = ossid;
116 ossfile.f_flags = 0;
117
118 switch(streamtype) {
119 case OSS_STREAM_WAVEOUT:
120 ossfile.f_mode = FMODE_WRITE;
121 break;
122 case OSS_STREAM_WAVEIN:
123 ossfile.f_mode = FMODE_READ;
124 break;
125 case OSS_STREAM_MIDIOUT:
126 ossfile.f_mode = FMODE_WRITE;
127 break;
128 case OSS_STREAM_MIDIIN:
129 ossfile.f_mode = FMODE_READ;
130 break;
131 }
132
133 if(!oss_devices[ossid].open) {
134 return 0;
135 }
136 if(oss_devices[ossid].open(&ossinode, &ossfile)) {
137 DebugInt3();
138 return 0;
139 }
140 return (ULONG)ossfile.private_data;
141}
142//******************************************************************************
143//******************************************************************************
144ULONG OSS32_StreamClose(ULONG streamtype, ULONG streamid)
145{
146struct inode ossinode;
147struct file ossfile;
148ULONG ossid = streamtype & OSS_IDMASK;
149
150 ossinode.i_rdev = ossid;
151 ossfile.private_data = (void *)streamid;
152 ossfile.f_flags = 0;
153
154 switch(streamtype) {
155 case OSS_STREAM_WAVEOUT:
156 ossfile.f_mode = FMODE_WRITE;
157 break;
158 case OSS_STREAM_WAVEIN:
159 ossfile.f_mode = FMODE_READ;
160 break;
161 case OSS_STREAM_MIDIOUT:
162 ossfile.f_mode = FMODE_WRITE;
163 break;
164 case OSS_STREAM_MIDIIN:
165 ossfile.f_mode = FMODE_READ;
166 break;
167 }
168 if(!oss_devices[ossid].release) {
169 return 0;
170 }
171 if(oss_devices[ossid].release(&ossinode, &ossfile)) {
172 DebugInt3();
173 return 0;
174 }
175 return 0;
176}
177//******************************************************************************
178//******************************************************************************
179ULONG OSS32_StreamIOCtl(ULONG streamtype, ULONG streamid, ULONG cmd, char NEAR *buffer)
180{
181 struct inode ossinode;
182 struct file ossfile;
183 ULONG ossid = streamtype & OSS_IDMASK, newcmd = -1, fraginfo;
184 count_info cinfo;
185 char NEAR *tmpbuf;
186
187 ossinode.i_rdev = ossid;
188 ossfile.private_data = (void *)streamid;
189 ossfile.f_flags = 0;
190
191 switch(streamtype) {
192 case OSS_STREAM_WAVEOUT:
193 ossfile.f_mode = FMODE_WRITE;
194 break;
195 case OSS_STREAM_WAVEIN:
196 ossfile.f_mode = FMODE_READ;
197 break;
198 case OSS_STREAM_MIDIOUT:
199 ossfile.f_mode = FMODE_WRITE;
200 break;
201 case OSS_STREAM_MIDIIN:
202 ossfile.f_mode = FMODE_READ;
203 break;
204 }
205
206 if(!oss_devices[ossid].ioctl) {
207 return 0;
208 }
209 switch(cmd) {
210 case IOCTL_GETPOS:
211 if(streamtype == OSS_STREAM_WAVEOUT) {
212 newcmd = SNDCTL_DSP_GETOPTR;
213 }
214 else newcmd = SNDCTL_DSP_GETIPTR;
215#ifdef KEE
216 tmpbuf = (char NEAR *)&cinfo;
217#else
218 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&cinfo);
219#endif
220 break;
221
222 case IOCTL_SETFRAGMENT:
223 {
224 ULONG fragsize;
225
226 newcmd = SNDCTL_DSP_SETFRAGMENT;
227
228 fragsize = *(ULONG NEAR *)buffer; //fragsize
229 fraginfo = 0;
230 while(fragsize) {
231 fragsize >>= 1;
232 fraginfo++;
233 }
234 fraginfo--;
235
236#ifdef KEE
237 tmpbuf = (char NEAR *)&fraginfo;
238#else
239 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&fraginfo);
240#endif
241 break;
242 }
243 default:
244 DebugInt3();
245 return 0;
246 }
247 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, newcmd, (ULONG)tmpbuf)) {
248 return 0;
249 }
250 switch(cmd) {
251 case IOCTL_GETPOS:
252 *(ULONG NEAR *)buffer = cinfo.bytes;
253 break;
254 }
255 return 1;
256}
257//******************************************************************************
258//******************************************************************************
259ULONG OSS32_StreamSetFormat(ULONG streamtype, ULONG streamid, ULONG cmd, FORMAT_INFO NEAR *pFormatInfo)
260{
261 struct inode ossinode;
262 struct file ossfile;
263 ULONG ossid = streamtype & OSS_IDMASK;
264
265 ossinode.i_rdev = ossid;
266 ossfile.private_data = (void *)streamid;
267 ossfile.f_flags = 0;
268
269 switch(streamtype) {
270 case OSS_STREAM_WAVEOUT:
271 ossfile.f_mode = FMODE_WRITE;
272 break;
273 case OSS_STREAM_WAVEIN:
274 ossfile.f_mode = FMODE_READ;
275 break;
276 case OSS_STREAM_MIDIOUT:
277 ossfile.f_mode = FMODE_WRITE;
278 break;
279 case OSS_STREAM_MIDIIN:
280 ossfile.f_mode = FMODE_READ;
281 break;
282 }
283
284 if(!oss_devices[ossid].ioctl) {
285 return 0;
286 }
287 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SPEED, (ULONG)&pFormatInfo->ulSampleRate)) {
288 return 0;
289 }
290 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_CHANNELS, (ULONG)&pFormatInfo->ulNumChannels)) {
291 return 0;
292 }
293 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SETFMT, (ULONG)&pFormatInfo->ulBitsPerSample)) {
294 return 0;
295 }
296
297 return 1;
298}
299//******************************************************************************
300//******************************************************************************
301ULONG OSS32_StreamTrigger(ULONG streamtype, ULONG streamid, ULONG NEAR *fStart)
302{
303 struct inode ossinode;
304 struct file ossfile;
305 ULONG ossid = streamtype & OSS_IDMASK;
306 ULONG cmd;
307
308 ossinode.i_rdev = ossid;
309 ossfile.private_data = (void *)streamid;
310 ossfile.f_flags = 0;
311
312 switch(streamtype) {
313 case OSS_STREAM_WAVEOUT:
314 ossfile.f_mode = FMODE_WRITE;
315 *fStart = (*fStart) ? PCM_ENABLE_OUTPUT : 0;
316 cmd = SNDCTL_DSP_SETTRIGGER;
317 break;
318 case OSS_STREAM_WAVEIN:
319 ossfile.f_mode = FMODE_READ;
320 *fStart = (*fStart) ? PCM_ENABLE_INPUT : 0;
321 cmd = SNDCTL_DSP_SETTRIGGER;
322 break;
323 case OSS_STREAM_MIDIOUT:
324 ossfile.f_mode = FMODE_WRITE;
325 break;
326 case OSS_STREAM_MIDIIN:
327 ossfile.f_mode = FMODE_READ;
328 break;
329 }
330
331 if(!oss_devices[ossid].ioctl) {
332 return 0;
333 }
334 if(ossfile.f_mode == FMODE_READ && *fStart == PCM_ENABLE_INPUT) {
335 //need to call poll to really start the stream
336 int rc;
337 struct poll_table_struct poll = {0};
338
339 rc = oss_devices[ossid].poll(&ossfile, &poll);
340 if(rc & POLLERR)
341 return 0;
342 return 1;
343 }
344 else
345 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)fStart)) {
346 return 0;
347 }
348 return 1;
349}
350//******************************************************************************
351//******************************************************************************
352ULONG OSS32_StreamReset(ULONG streamtype, ULONG streamid)
353{
354 struct inode ossinode;
355 struct file ossfile;
356 ULONG ossid = streamtype & OSS_IDMASK;
357 ULONG cmd;
358
359 ossinode.i_rdev = ossid;
360 ossfile.private_data = (void *)streamid;
361 ossfile.f_flags = 0;
362
363 switch(streamtype) {
364 case OSS_STREAM_WAVEOUT:
365 ossfile.f_mode = FMODE_WRITE;
366 cmd = SNDCTL_DSP_RESET;
367 break;
368 case OSS_STREAM_WAVEIN:
369 ossfile.f_mode = FMODE_READ;
370 cmd = SNDCTL_DSP_RESET;
371 break;
372 case OSS_STREAM_MIDIOUT:
373 ossfile.f_mode = FMODE_WRITE;
374 break;
375 case OSS_STREAM_MIDIIN:
376 ossfile.f_mode = FMODE_READ;
377 break;
378 }
379
380 if(!oss_devices[ossid].ioctl) {
381 return 0;
382 }
383 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, 0)) {
384 return 0;
385 }
386 return 1;
387}
388//******************************************************************************
389//******************************************************************************
390ULONG OSS32_StreamAddBuffer(ULONG streamtype, ULONG streamid, ULONG buffer, ULONG size)
391{
392 struct inode ossinode;
393 struct file ossfile;
394 struct dentry ossdentry;
395 ULONG ossid = streamtype & OSS_IDMASK;
396 audio_buf_info info;
397 char NEAR *tmpbuf;
398 ULONG cmd;
399 int transferred;
400
401 ossinode.i_rdev = ossid;
402 ossfile.private_data = (void *)streamid;
403 ossfile.f_flags = 0;
404 ossfile.f_dentry = &ossdentry;
405 ossdentry.d_inode = &ossinode;
406
407 switch(streamtype) {
408 case OSS_STREAM_WAVEOUT:
409 ossfile.f_mode = FMODE_WRITE;
410 cmd = SNDCTL_DSP_GETOSPACE;
411 break;
412 case OSS_STREAM_WAVEIN:
413 ossfile.f_mode = FMODE_READ;
414 cmd = SNDCTL_DSP_GETISPACE;
415 break;
416 case OSS_STREAM_MIDIOUT:
417 ossfile.f_mode = FMODE_WRITE;
418 break;
419 case OSS_STREAM_MIDIIN:
420 ossfile.f_mode = FMODE_READ;
421 break;
422 }
423
424 if(!oss_devices[ossid].write || !oss_devices[ossid].read || !oss_devices[ossid].ioctl) {
425 return 0;
426 }
427 //check how much room is left in the circular dma buffer
428#ifdef KEE
429 tmpbuf = (char NEAR *)&info;
430#else
431 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&info);
432#endif
433 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)tmpbuf)) {
434 return 0;
435 }
436 size = min(size, info.bytes);
437
438 if(size == 0) {
439 return 0; //no room left, fail
440 }
441
442 if(streamtype == OSS_STREAM_WAVEIN) {
443 transferred = oss_devices[ossid].read(&ossfile, (char *)buffer, size, &ossfile.f_pos);
444 }
445 else transferred = oss_devices[ossid].write(&ossfile, (char *)buffer, size, &ossfile.f_pos);
446 if(transferred < 0) {
447 return 0;
448 }
449 return transferred;
450}
451//******************************************************************************
452//******************************************************************************
453ULONG OSS32_StreamGetSpace(ULONG streamtype, ULONG streamid)
454{
455 struct inode ossinode;
456 struct file ossfile;
457 struct dentry ossdentry;
458 ULONG ossid = streamtype & OSS_IDMASK;
459 audio_buf_info info;
460 char NEAR *tmpbuf;
461 ULONG cmd;
462 int transferred;
463
464 ossinode.i_rdev = ossid;
465 ossfile.private_data = (void *)streamid;
466 ossfile.f_flags = 0;
467 ossfile.f_dentry = &ossdentry;
468 ossdentry.d_inode = &ossinode;
469
470 switch(streamtype) {
471 case OSS_STREAM_WAVEOUT:
472 ossfile.f_mode = FMODE_WRITE;
473 cmd = SNDCTL_DSP_GETOSPACE;
474 break;
475 case OSS_STREAM_WAVEIN:
476 ossfile.f_mode = FMODE_READ;
477 cmd = SNDCTL_DSP_GETISPACE;
478 break;
479 case OSS_STREAM_MIDIOUT:
480 ossfile.f_mode = FMODE_WRITE;
481 break;
482 case OSS_STREAM_MIDIIN:
483 ossfile.f_mode = FMODE_READ;
484 break;
485 }
486
487 if(!oss_devices[ossid].write || !oss_devices[ossid].read || !oss_devices[ossid].ioctl) {
488 return 0;
489 }
490 //check how much room is left in the circular dma buffer
491#ifdef KEE
492 tmpbuf = (char NEAR *)&info;
493#else
494 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&info);
495#endif
496 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)tmpbuf)) {
497 return 0;
498 }
499 return info.bytes;
500}
501//******************************************************************************
502//******************************************************************************
503ULONG OSS32_SetVolume(ULONG streamtype, ULONG streamid, ULONG cmd, ULONG volume)
504{
505 struct inode ossinode;
506 struct file ossfile;
507 struct dentry ossdentry;
508 ULONG ossid = streamtype & OSS_IDMASK;
509 char NEAR *tmpbuf;
510 ULONG ioctl;
511
512 ossinode.i_rdev = OSS_MIXERID;
513 ossfile.private_data = (void *)streamid;
514 ossfile.f_flags = 0;
515 ossfile.f_dentry = &ossdentry;
516 ossfile.f_mode = FMODE_WRITE;
517 ossdentry.d_inode = &ossinode;
518
519 switch(cmd) {
520 case MIX_SETMASTERVOL:
521 ioctl = SOUND_MIXER_WRITE_VOLUME;
522 break;
523 case MIX_SETWAVEVOL:
524 ioctl = SOUND_MIXER_WRITE_PCM;
525 break;
526 case MIX_SETMIDIVOL:
527// ioctl =
528 break;
529 case MIX_SETINPUTSRC:
530 ioctl = SOUND_MIXER_WRITE_RECSRC; //todo
531 switch(volume)
532 {
533 case MIX_RECSRC_MIC:
534 volume = SOUND_MASK_MIC;
535 break;
536 case MIX_RECSRC_CD:
537 volume = SOUND_MASK_CD;
538 break;
539 case MIX_RECSRC_LINE:
540 volume = SOUND_MASK_LINE;
541 break;
542 case MIX_RECSRC_VIDEO:
543 volume = SOUND_MASK_VIDEO;
544 break;
545 case MIX_RECSRC_MIXER:
546 volume = SOUND_MASK_MONITOR;
547 break;
548 case MIX_RECSRC_AUX:
549 volume = SOUND_MASK_LINE1;
550 break;
551 default:
552 DebugInt3();
553 break;
554 }
555 break;
556 case MIX_SETINPUTGAIN:
557 ioctl = SOUND_MIXER_WRITE_RECLEV;
558 break;
559 case MIX_SETLINEINVOL:
560 ioctl = SOUND_MIXER_WRITE_LINE;
561 break;
562 case MIX_SETLINEINMUTE:
563 ioctl = SOUND_MIXER_WRITE_LINE;
564 break;
565 case MIX_SETMICVOL:
566 ioctl = SOUND_MIXER_WRITE_MIC;
567 break;
568 case MIX_SETMICMUTE:
569 ioctl = SOUND_MIXER_WRITE_MIC;
570 break;
571 case MIX_SETCDVOL:
572 ioctl = SOUND_MIXER_WRITE_CD;
573 break;
574 case MIX_SETCDMUTE:
575 ioctl = SOUND_MIXER_WRITE_CD;
576 break;
577 case MIX_SETVIDEOVOL:
578 ioctl = SOUND_MIXER_WRITE_VIDEO;
579 break;
580 case MIX_SETAUXVOL:
581 ioctl = SOUND_MIXER_LINE1;
582 break;
583 case MIX_SETBASS:
584 ioctl = SOUND_MIXER_WRITE_BASS;
585 break;
586 case MIX_SETTREBLE:
587 ioctl = SOUND_MIXER_WRITE_TREBLE;
588 break;
589 case MIX_SETSPDIFVOL:
590// ioctl =
591 break;
592 case MIX_SETSPDIFMUTE:
593// ioctl =
594 break;
595 }
596 if(!oss_devices[OSS_MIXERID].ioctl || !oss_devices[OSS_MIXERID].open || !oss_devices[OSS_MIXERID].release) {
597 return 0;
598 }
599
600 if(oss_devices[OSS_MIXERID].open(&ossinode, &ossfile)) {
601 return 0;
602 }
603
604#ifdef KEE
605 tmpbuf = (char NEAR *)&volume;
606#else
607 tmpbuf = (char NEAR *)__StackToFlat((ULONG)&volume);
608#endif
609 if(oss_devices[OSS_MIXERID].ioctl(&ossinode, &ossfile, ioctl, (ULONG)tmpbuf)) {
610 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
611 return 0;
612 }
613 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
614 return 1;
615}
616//******************************************************************************
617//******************************************************************************
618unsigned long OSS32_StreamMidiWrite(unsigned long streamid, unsigned long midiByte)
619{
620 struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *)streamid;
621
622 return emu10k1_mpu_write_data(midi_dev->card, (u8)midiByte) == 0;
623}
624//******************************************************************************
625//******************************************************************************
626unsigned long OSS32_StreamMidiRead(unsigned long streamid, char near *buffer, unsigned long bufsize)
627{
628 struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *)streamid;
629 int count = 0;
630 u8 MPUIvalue;
631
632 while(TRUE) {
633 if(emu10k1_mpu_read_data(midi_dev->card, &MPUIvalue) == 0) {
634 buffer[count] = MPUIvalue;
635 count++;
636 }
637 else break;
638
639 if(count >= bufsize) {
640 break;
641 }
642 }
643 return count;
644}
645//******************************************************************************
646//******************************************************************************
Note: See TracBrowser for help on using the repository browser.