2
* Purpose: Audio core functionality of OSS
7
* This file is part of Open Sound System.
9
* Copyright (C) 4Front Technologies 1996-2008.
11
* This this source file is released under GPL v2 license (no other versions).
12
* See the COPYING file included in the main directory of this source
13
* distribution for the license terms and conditions.
22
/* Some debugging macros (for future use) */
24
#define DOWN_STATUS(x)
26
#include <oss_config.h>
28
extern int src_quality;
29
extern int vmix_disabled;
30
extern int excl_policy;
32
oss_mutex_t audio_global_mutex;
35
* Resizeable audio device tables
37
static oss_memblk_t *audio_global_memblk=NULL;
38
int oss_max_audio_devfiles=4;
39
int oss_max_audio_engines=8;
40
#define AUDIO_MALLOC(osdev, size) oss_memblk_malloc(&audio_global_memblk, size)
41
#define AUDIO_FREE(osdev, addr) oss_memblk_free(&audio_global_memblk, addr)
42
#define AUDIO_ENGINE_INCREMENT (oss_max_audio_engines/2)
43
#define AUDIO_DEVFILE_INCREMENT (oss_max_audio_devfiles/2)
46
* List of audio devices in the system
48
adev_t **audio_engines = NULL;
49
int num_audio_engines = 0;
51
adev_t **audio_devfiles = NULL;
52
int num_audio_devfiles = 0;
53
extern int flat_device_model;
57
* Device lists (input, output, duplex) for /dev/dsp.
60
oss_devlist_t dspinlist = { 0 };
61
oss_devlist_t dspoutlist = { 0 };
62
oss_devlist_t dspinoutlist = { 0 };
63
oss_devlist_t dspoutlist2 = { 0 }; /* 2nd priority output devices */
67
* Applications known to require special handling (mmap, etc.). These
68
* applications are listed here because they use the OSS API incorrectly and
69
* some workarounds by OSS are required to make them to work.
77
oss_specialapp_t special_apps[] = {
80
{"q3demo.x86", OF_MMAP},
81
{"wolfsp.x86", OF_MMAP},
82
{"wolfmp.x86", OF_MMAP},
86
{"artsd", OF_BLOCK | OF_NOCONV},
87
{"realplay.bin", OF_SMALLFRAGS},
88
{"hxplay.bin", OF_SMALLFRAGS},
90
{"auserver", OF_NOCONV}, /* Win4lin */
92
{"quake3.x86", OF_MMAP},
93
{"wolf.x86", OF_MMAP},
95
{"doom.x86", OF_MMAP},
96
// {"mozilla-bin", OF_MEDIUMBUF}, /* For the flash plugin */
100
#ifdef APPLIST_SUPPORT
102
* Lookup tables for applications. Use these lists to assign
103
* fixed target devices for given applications.
106
app_routing_t oss_applist[APPLIST_SIZE];
107
int oss_applist_size = 0;
110
app_lookup (int mode, const char *appname, int *open_flags)
117
for (i = 0; i < oss_applist_size; i++)
119
if (oss_applist[i].mode == mode)
120
if (strncmp (appname, oss_applist[i].name, 32) == 0)
122
dev = oss_applist[i].dev;
124
if (dev < -1 || dev >= num_audio_devfiles)
126
*open_flags |= oss_applist[i].open_flags;
137
get_open_flags (int mode, int open_flags, struct fileinfo *file)
142
if ((name = GET_PROCESS_NAME (file)) != NULL)
144
#ifdef APPLIST_SUPPORT
145
if (app_lookup (mode, name, &open_flags) >= -1)
149
for (i = 0; special_apps[i].name != NULL; i++)
150
if (strcmp (special_apps[i].name, name) == 0)
152
open_flags |= special_apps[i].open_flags;
160
#define BIGWRITE_SIZE 1024
162
#define NEUTRAL8 0x80
163
#define NEUTRAL16 0x00
164
#define OSS_PLUGIN_VERSION (0x100|oss_sample_bits)
166
int always_cooked = 0;
167
static unsigned long sync_seed = 0;
169
#define COOKED_BLOCK_SIZE 4096
171
extern oss_uint64_t oss_tmp_timer;
174
* Structure used by oss_audio_register_client()
178
oss_audio_startup_func func;
183
#define MAX_STARTUPS 5
184
static audio_startup_t audio_startups[MAX_STARTUPS];
185
static int num_audio_startups = 0;
188
dmap_get_qlen (dmap_p dmap)
192
if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
194
if (dmap->fragment_size == 0)
196
cmn_err (CE_WARN, "dmap (out) fragment_size=0, dev=%s\n",
202
(int) ((dmap->user_counter -
203
dmap->byte_counter) / dmap->fragment_size);
209
if (dmap->dma_mode == PCM_ENABLE_INPUT)
211
if (dmap->fragment_size == 0)
213
cmn_err (CE_WARN, "dmap (in) fragment_size=0, dev=%s\n",
219
(int) ((dmap->byte_counter -
220
dmap->user_counter) / dmap->fragment_size);
230
dmap_get_qhead (dmap_p dmap)
234
if (dmap->fragment_size == 0)
237
if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
239
ptr = (int) (dmap->byte_counter % dmap->bytes_in_use);
240
return ptr / dmap->fragment_size;
243
if (dmap->dma_mode == PCM_ENABLE_INPUT)
245
ptr = (int) (dmap->user_counter % dmap->bytes_in_use);
246
return ptr / dmap->fragment_size;
253
dmap_get_qtail (dmap_p dmap)
257
if (dmap->fragment_size == 0)
260
if (dmap->dma_mode == PCM_ENABLE_INPUT)
262
ptr = (int) (dmap->byte_counter % dmap->bytes_in_use);
263
return ptr / dmap->fragment_size;
266
if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
268
ptr = (int) (dmap->user_counter % dmap->bytes_in_use);
269
return ptr / dmap->fragment_size;
276
oss_audio_set_format (int dev, int fmt, int format_mask)
280
unsigned char neutral_byte;
281
audio_format_info_p fmt_info;
285
if (dev < 0 || dev >= num_audio_engines)
288
adev = audio_engines[dev];
293
return adev->user_parms.fmt;
298
* AC3 cannot tolerate any format/rate conversions so disable them.
300
adev->cooked_enable = 0;
303
* Report EIO error if the application tries to do something stupid.
304
* Otherwise buggy applications may produce loud helicopter sound.
307
if (adev->flags & ADEV_VMIX)
309
oss_audio_set_error (adev->engine_num, E_REC,
311
"AFMT_AC3 used with virtual mixing device."),
315
* Devices that support virtual or hardware mixing are
316
* probably not capable to play AC3 streams properly.
318
* Virtual mixing is enabled on the audio device. The virtual
319
* mixer driver will do voolume control that corrupts the AC3
320
* bitstream. Applications using AC3 should
321
* open the audio device with O_EXCL to make sure that virtual
322
* mixing is properly bypassed.
327
if (adev->flags & ADEV_HWMIX)
329
oss_audio_set_error (adev->engine_num, E_REC,
331
"AFMT_AC3 used with hardware mixing device."),
335
* Devices that support virtual or hardware mixing are
336
* probably not capable to play AC3 streams properly.
338
* This error may be caused by user who selected a wrong audio
344
if (adev->dmask & DMASK_OUT)
345
if (adev->dmap_out->flags & DMAP_COOKED)
347
oss_audio_set_error (adev->engine_num, E_REC,
349
"AFMT_AC3 used with format conversions enabled."),
353
* AC3 audio format (AFMT_AC3) bitstreams don't tolerate any
354
* kind of sample rate or format conversions. However it looks
355
* like conversions would be needed. The reason may be that the
356
* application had earlier requested some sample rate that is
357
* not supported by the device.
359
* Applications using AC3 should call SNDCTL_DSP_COOKEDMODE to
360
* disable format conversions.
366
ret = adev->d->adrv_set_format (dev, fmt);
368
adev->user_parms.fmt = ret;
369
adev->hw_parms.fmt = ret;
371
if ((fmt_info = oss_find_format (ret)) == NULL)
375
neutral_byte = fmt_info->neutral_byte;
378
if (adev->dmask & DMASK_OUT)
379
adev->dmap_out->neutral_byte = neutral_byte;
380
if (adev->dmask & DMASK_IN)
381
adev->dmap_in->neutral_byte = neutral_byte;
383
/* Disable format conversions if mmap() */
384
if ((adev->dmap_out->mapping_flags & DMA_MAP_MAPPED) ||
385
(adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) ||
386
(adev->open_flags & OF_MMAP))
389
#ifdef NO_COOKED_MODE
396
if (!adev->cooked_enable)
400
* We need to perform format conversions because the device
401
* doesn't support the requested format.
404
/* Convertable format? */
405
if (!(fmt & CONVERTABLE_FORMATS))
410
adev->user_parms.fmt = fmt;
411
if (adev->dmask & DMASK_OUT)
413
adev->dmap_out->flags |= DMAP_COOKED;
416
if (adev->dmask & DMASK_IN)
418
adev->dmap_in->flags |= DMAP_COOKED;
421
/* If the device is in 16 bit format then just return */
422
if (ret & (AFMT_S16_LE | AFMT_S16_BE))
425
/* Try to find a suitable format */
427
if (fmt == AFMT_MU_LAW && ret == AFMT_U8) /* mu-Law <-> 8 bit linear */
430
if (format_mask & AFMT_S16_LE)
432
newfmt = AFMT_S16_LE;
436
if (format_mask & AFMT_S16_BE)
438
newfmt = AFMT_S16_BE;
442
return fmt; /* Nothing better than the one suggested by the device */
445
ret = adev->d->adrv_set_format (dev, newfmt);
447
adev->hw_parms.fmt = ret;
454
oss_audio_set_channels (int dev, int ch)
461
if (dev < 0 || dev >= num_audio_engines)
464
adev = audio_engines[dev];
469
return adev->user_parms.channels;
471
ret = adev->d->adrv_set_channels (dev, ch);
476
"Audio engine %d: Internal error in channel setup, err=%d, ch=%d\n",
481
if (ch > 2 && ch > ret) /* Requested multi channel mode not possible */
484
adev->user_parms.channels = ret;
485
adev->hw_parms.channels = ret;
487
/* Disable format conversions if mmap() */
488
if ((adev->dmap_out->mapping_flags & DMA_MAP_MAPPED) ||
489
(adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) ||
490
(adev->open_flags & OF_MMAP))
493
if (ret > 1 && (adev->flags & ADEV_NONINTERLEAVED))
495
if (adev->dmask & DMASK_OUT)
496
adev->dmap_out->flags |= DMAP_COOKED;
498
if (adev->dmask & DMASK_IN)
499
adev->dmap_in->flags |= DMAP_COOKED;
503
#ifdef NO_COOKED_MODE
507
if (!adev->cooked_enable)
513
/* For the time being only stereo <->mono is possible */
515
if (!((ch == 1 && ret == 2) || (ch == 2 && ret == 1)))
519
* Needs to perform format conversions
522
adev->user_parms.channels = ch;
523
if (adev->dmask & DMASK_OUT)
525
adev->dmap_out->flags |= DMAP_COOKED;
528
if (adev->dmask & DMASK_IN)
530
adev->dmap_in->flags |= DMAP_COOKED;
538
oss_audio_set_rate (int dev, int rate)
545
if (dev < 0 || dev >= num_audio_engines)
548
adev = audio_engines[dev];
553
return adev->user_parms.rate;
555
ret = adev->d->adrv_set_rate (dev, rate);
559
adev->user_parms.rate = ret;
560
adev->hw_parms.rate = ret;
562
/* Disable format conversions if mmap() */
563
if ((adev->dmap_out->mapping_flags & DMA_MAP_MAPPED) ||
564
(adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) ||
565
(adev->flags & ADEV_NOSRC) || (adev->open_flags & OF_MMAP))
568
if (!adev->cooked_enable)
571
#if defined(NO_COOKED_MODE) || GRC == 0
575
if (ret == rate) /* No SRC needed */
579
* Needs to perform format conversions
582
adev->user_parms.rate = rate;
583
if (adev->dmask & DMASK_OUT)
585
adev->dmap_out->flags |= DMAP_COOKED;
588
if (adev->dmask & DMASK_IN)
590
adev->dmap_in->flags |= DMAP_COOKED;
598
reset_dmap (dmap_p dmap)
601
oss_do_timing ("Reset dmap");
604
dmap->flags &= (DMAP_FRAGFIXED | DMAP_COOKED);
605
dmap->byte_counter = dmap->user_counter = 0;
606
dmap->fragment_counter = 0;
607
dmap->interrupt_count = 0;
608
dmap->expand_factor = UNIT_EXPAND; /* 1:1 */
609
dmap->play_underruns = dmap->rec_overruns = 0;
610
dmap->num_errors = 0;
611
dmap->leftover_bytes = 0;
612
dmap->leftover_buf = NULL;
616
oss_alloc_dmabuf (int dev, dmap_p dmap, int direction)
618
adev_t *adev = dmap->adev;
622
cmn_err (CE_WARN, "oss_alloc_dmabuf: adev==NULL\n");
626
return __oss_alloc_dmabuf (dev, dmap, adev->dmabuf_alloc_flags,
627
adev->dmabuf_maxaddr, direction);
631
default_alloc_buffer (int dev, dmap_t * dmap, int direction)
635
if (dmap->dmabuf != NULL)
638
if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0)
646
default_free_buffer (int dev, dmap_t * dmap, int direction)
648
if (dmap->dmabuf == NULL)
651
oss_free_dmabuf (dev, dmap);
654
dmap->dmabuf_phys = 0;
659
init_dmap (adev_p adev, dmap_p dmap, int direction)
664
oss_native_word flags;
666
if (dmap->osdev == NULL)
668
cmn_err (CE_WARN, "dmap->osdev==NULL\n");
672
if (dmap->dmabuf == NULL)
674
if (adev->d->adrv_alloc_buffer != NULL)
677
adev->d->adrv_alloc_buffer (adev->engine_num, dmap, direction);
681
retval = default_alloc_buffer (adev->engine_num, dmap, direction);
686
"Failed to allocate DMA buffer for audio engine %d/%s\n",
687
adev->engine_num, adev->name);
691
if (dmap->dmabuf_phys == 0) /* Cannot do mmap */
692
adev->flags |= ADEV_NOMMAP;
696
if (dmap->dmabuf_phys == 0)
697
adev->flags |= ADEV_NOMMAP;
699
dmap->flags &= ~DMAP_FRAGFIXED;
702
static_len = (oss_native_word) & dmap->flags - (oss_native_word) dmap;
704
p = (char *) &dmap->flags;
707
memset (p, 0, l); /* Clear all */
709
if (!dmap->buffer_protected && dmap->dmabuf != NULL)
710
memset (dmap->dmabuf, dmap->neutral_byte, dmap->buffsize);
712
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
714
dmap->bytes_in_use = dmap->buffsize;
715
dmap->frame_size = 1;
716
dmap->user_frame_size = 1;
718
dmap->audio_callback = NULL;
720
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
726
audio_reset_adev (adev_p adev)
728
oss_native_word flags, dflags;
730
oss_do_timing ("Reset input & output\n");
737
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
739
adev->enable_bits = adev->open_mode;
740
if (adev->open_mode & OPEN_WRITE)
742
dmap_p dmap = adev->dmap_out;
743
dmap->flags &= ~DMAP_PREPARED;
744
memset (dmap->dmabuf, 0, dmap->buffsize);
747
if (adev->d->adrv_halt_input && adev->d->adrv_halt_output)
749
if (adev->open_mode & OPEN_READ)
751
dmap_p dmap = adev->dmap_in;
752
MUTEX_ENTER (dmap->mutex, dflags);
753
dmap->flags &= ~DMAP_PREPARED;
754
if ((dmap->dma_mode == PCM_ENABLE_INPUT)
755
&& (dmap->flags & DMAP_STARTED))
758
ossd_event (adev->engine_num, OSSD_EV_RESET_INPUT);
760
MUTEX_EXIT (dmap->mutex, dflags);
761
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
762
adev->d->adrv_halt_input (adev->engine_num);
763
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
764
MUTEX_ENTER (dmap->mutex, dflags);
767
MUTEX_EXIT (dmap->mutex, dflags);
769
if (adev->open_mode & OPEN_WRITE)
771
dmap_p dmap = adev->dmap_out;
772
MUTEX_ENTER (dmap->mutex, dflags);
773
if ((dmap->dma_mode == PCM_ENABLE_OUTPUT) &&
774
(dmap->flags & DMAP_STARTED))
777
ossd_event (adev->engine_num, OSSD_EV_RESET_OUTPUT);
779
MUTEX_EXIT (dmap->mutex, dflags);
780
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
781
adev->d->adrv_halt_output (adev->engine_num);
782
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
783
MUTEX_ENTER (dmap->mutex, dflags);
786
MUTEX_EXIT (dmap->mutex, dflags);
789
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
792
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
795
ossd_event (adev->engine_num, OSSD_EV_RESET_OUTPUT);
796
ossd_event (adev->engine_num, OSSD_EV_RESET_INPUT);
798
adev->d->adrv_halt_io (adev->engine_num);
800
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
801
reset_dmap (adev->dmap_out);
802
reset_dmap (adev->dmap_in);
803
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
807
audio_reset_input (adev_p adev)
809
dmap_p dmap = adev->dmap_in;
810
oss_native_word flags, dflags;
813
if (!(adev->open_mode & OPEN_READ))
816
if (dmap->dma_mode != PCM_ENABLE_INPUT)
819
if (!(dmap->flags & DMAP_STARTED))
823
oss_do_timing ("Reset input\n");
825
dmap->flags &= ~DMAP_PREPARED;
827
if (adev->d->adrv_halt_input)
830
ossd_event (adev->engine_num, OSSD_EV_RESET_INPUT);
832
adev->d->adrv_halt_input (adev->engine_num);
833
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
835
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
839
adev->d->adrv_halt_io (adev->engine_num);
840
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
841
MUTEX_ENTER (dmap->mutex, dflags);
843
MUTEX_EXIT (dmap->mutex, dflags);
844
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
848
audio_reset_output (adev_p adev)
850
dmap_p dmap = adev->dmap_out;
851
oss_native_word flags, dflags;
856
if (!(adev->open_mode & OPEN_WRITE))
859
if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
862
if (!(dmap->flags & DMAP_STARTED))
865
dmap->flags &= ~DMAP_PREPARED;
867
oss_do_timing ("Reset output\n");
870
if (adev->d->adrv_halt_output)
873
ossd_event (adev->engine_num, OSSD_EV_RESET_OUTPUT);
875
adev->d->adrv_halt_output (adev->engine_num);
876
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
878
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
882
adev->d->adrv_halt_io (adev->engine_num);
883
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
884
MUTEX_ENTER (dmap->mutex, dflags);
886
MUTEX_EXIT (dmap->mutex, dflags);
887
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
890
static int launch_output (adev_p adev, dmap_p dmap);
891
static int launch_input (adev_p adev, dmap_p dmap);
894
oss_audio_post (adev_p adev)
898
dmap_p dmap = adev->dmap_out;
900
if (!(adev->open_mode & OPEN_WRITE))
902
if (dmap->user_counter == 0)
905
if (dmap->flags & DMAP_STARTED)
909
oss_do_timing ("Post output\n");
912
/* Clean the unused buffer space (in slow way) */
913
limit = dmap->byte_counter + dmap->bytes_in_use;
914
if (limit > dmap->user_counter + dmap->bytes_in_use)
915
limit = dmap->user_counter + dmap->bytes_in_use;
916
n = (int) (limit - dmap->user_counter) + 1;
917
p = (int) (dmap->user_counter % dmap->bytes_in_use); /* Current ptr */
918
for (i = 0; i < n; i++)
920
dmap->dmabuf[p] = dmap->neutral_byte;
921
p = (p + 1) % dmap->bytes_in_use;
924
launch_output (adev, dmap);
928
oss_audio_sync (adev_p adev)
930
dmap_p dmap = adev->dmap_out;
931
oss_uint64_t uc, limit;
932
oss_native_word flags;
935
int n = 0, loops = 0, tmout = OSS_HZ, i;
938
if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
940
if (adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)
943
if (!(dmap->flags & DMAP_STARTED))
944
oss_audio_post (adev);
946
if (!(dmap->flags & DMAP_STARTED))
949
/* Don't wait if output is untriggered */
950
if (adev->go == 0 || !(adev->enable_bits & PCM_ENABLE_OUTPUT))
954
oss_do_timing ("Sync output\n");
957
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
958
dmap->flags |= DMAP_POST;
960
uc = dmap->user_counter;
961
prev_underruns = dmap->play_underruns;
962
dmap->play_underruns = 0;
964
while (dmap->play_underruns == 0 && loops++ < dmap->nfrags
965
&& dmap->byte_counter < uc)
968
adev->dmap_out->error = 0;
969
/* Clean the unused buffer space (in a slow but precise way) */
970
limit = dmap->byte_counter + dmap->bytes_in_use;
971
if (limit > dmap->user_counter + dmap->bytes_in_use)
972
limit = dmap->user_counter + dmap->bytes_in_use;
974
p = (int) (dmap->user_counter % dmap->bytes_in_use); /* Current ptr */
975
n = (int) (limit - dmap->user_counter) + 1;
976
for (i = 0; i < n; i++)
978
dmap->dmabuf[p] = dmap->neutral_byte;
979
p = (p + 1) % dmap->bytes_in_use;
982
tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
983
tmout += OSS_HZ / 10;
985
if (!oss_sleep (adev->out_wq, &dmap->mutex, tmout, &flags, &status))
988
cmn_err (CE_WARN, "Output timed out (sync) on audio engine %d\n",
991
adev->timeout_count++;
992
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
993
FMA_EREPORT(adev->osdev, DDI_FM_DEVICE_STALL, NULL, NULL, NULL);
994
FMA_IMPACT(adev->osdev, DDI_SERVICE_LOST);
998
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
1001
if (adev->d->adrv_local_qlen) /* Drain the internal queue too */
1003
adev->d->adrv_local_qlen (adev->engine_num) / dmap->fragment_size)
1005
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
1006
audio_engines[adev->engine_num]->dmap_out->error = 0;
1007
tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
1008
tmout += OSS_HZ / 10;
1009
oss_sleep (adev->out_wq, &dmap->mutex, tmout, &flags, &status);
1010
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
1012
dmap->play_underruns = prev_underruns;
1015
static int prepare_output (adev_p adev, dmap_p dmap);
1016
static int prepare_input (adev_p adev, dmap_p dmap);
1019
oss_audio_set_error (int dev, int mode, int err, int parm)
1028
oss_timing_printf ("Audio rec error code %05d/%d, engine=%d", err, parm,
1031
oss_timing_printf ("Audio play error code %05d/%d, engine=%d", err, parm,
1038
cmn_err (CE_CONT, "Audio rec error code %05d/%d, engine=%d\n", err, parm,
1041
cmn_err (CE_CONT, "Audio play error code %05d/%d, engine=%d\n", err, parm,
1048
dmap = audio_engines[dev]->dmap_out;
1051
dmap = audio_engines[dev]->dmap_in;
1055
dmap = audio_engines[dev]->dmap_out; /* Actually this would be an error */
1058
n = dmap->num_errors++;
1059
if (n > MAX_AUDIO_ERRORS)
1060
n = MAX_AUDIO_ERRORS;
1066
* Move previous errors (if any) upwards in the list.
1068
for (i = n; i > 0; i--)
1070
dmap->errors[i] = dmap->errors[i - 1];
1071
dmap->error_parms[i] = dmap->error_parms[i - 1];
1075
dmap->errors[0] = err;
1076
dmap->error_parms[0] = parm;
1082
report_errors (char *s, const char *hdr, adev_t * adev, dmap_t * dmap,
1087
if (bufsize < 30) /* No space left */
1091
s += l = strlen (s);
1094
for (i = 0; i < dmap->num_errors && i < MAX_AUDIO_ERRORS; i++)
1100
for (j = 0; !dupe && j < i; j++)
1101
if (dmap->errors[i] == dmap->errors[j])
1107
sprintf (s, " %05d:%d", dmap->errors[i], dmap->error_parms[i]);
1108
s += l = strlen (s);
1114
store_history (int dev)
1119
adev_p adev = audio_engines[dev];
1121
if (adev->pid == 0) /* Virtual mixer */
1124
if (*adev->cmd && strcmp (adev->cmd, "sndconf") == 0)
1128
oss_history_p = (oss_history_p + 1) % OSS_HISTORY_SIZE;
1130
tmp = oss_history[p];
1131
memset (tmp, 0, OSS_HISTORY_STRSIZE);
1134
sprintf (s, "%s.%02d: ", adev->devnode, adev->engine_num);
1137
if (adev->pid != -1)
1139
sprintf (s, "pid %d ", adev->pid);
1143
if (*adev->cmd != 0)
1145
sprintf (s, "cmd '%s' ", adev->cmd);
1150
strcpy (s, "cmd: Unknown ");
1154
if (adev->open_mode & OPEN_READ)
1160
if (adev->open_mode & OPEN_WRITE)
1162
sprintf (s, "OUT ");
1166
if (adev->timeout_count > 0)
1168
sprintf (s, "%d timeouts ", adev->timeout_count);
1172
if (adev->dmap_out->play_underruns > 0)
1174
sprintf (s, "%d underruns ", adev->dmap_out->play_underruns);
1178
if (adev->dmap_in->rec_overruns > 0)
1180
sprintf (s, "%d overruns ", adev->dmap_in->rec_overruns);
1184
if (adev->dmap_out->num_errors > 0)
1186
report_errors (s, "Play events:", adev, adev->dmap_out,
1187
OSS_HISTORY_STRSIZE - strlen (tmp) - 1);
1192
if (adev->dmap_in->num_errors > 0)
1194
report_errors (s, "Rec events:", adev, adev->dmap_in,
1195
OSS_HISTORY_STRSIZE - strlen (tmp) - 1);
1202
audio_show_latency (int dev)
1204
static char str[32];
1205
adev_p adev = audio_engines[dev];
1211
if (dev < 0 || dev >= num_audio_engines)
1212
return "Bad device";
1214
if (adev->open_mode == 0)
1215
return "Not opened";
1217
if (adev->open_mode == OPEN_READ)
1218
dmap = adev->dmap_in;
1220
dmap = adev->dmap_out;
1225
if (!(dmap->flags & DMAP_STARTED))
1226
return "Not started";
1228
dr = dmap->data_rate;
1229
fs = dmap->fragment_size;
1232
sprintf (str, "%d", dmap->fragment_size);
1235
int r = (fs * 10000) / dr;
1237
sprintf (str, "%d/%d (%d.%d msec)", dmap->fragment_size, dr, r / 10,
1246
oss_audio_release (int dev, struct fileinfo *file)
1250
oss_native_word flags;
1254
if (dev < 0 || dev >= num_audio_engines)
1257
mode = file->mode & O_ACCMODE;
1259
mode = OPEN_READ | OPEN_WRITE;
1261
oss_timing_printf ("=-=-=- Closing audio engine %d -=-=-=", dev);
1264
adev = audio_engines[dev];
1266
if (adev->unloaded || !adev->enabled)
1268
cmn_err (CE_CONT, "Audio device %s not available - close aborted\n",
1273
oss_audio_post (adev);
1274
oss_audio_sync (adev);
1277
ossd_event (adev->engine_num, OSSD_EV_CLOSE);
1279
adev->d->adrv_halt_io (dev);
1280
adev->d->adrv_close (dev, mode);
1281
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1282
if (adev->dmask & DMASK_OUT)
1284
adev->dmap_out->audio_callback = NULL;
1285
if (!adev->dmap_out->buffer_protected)
1286
if (adev->dmap_out->dmabuf != NULL)
1287
memset (adev->dmap_out->dmabuf, adev->dmap_out->neutral_byte,
1288
adev->dmap_out->buffsize);
1291
if (adev->dmask & DMASK_IN)
1293
adev->dmap_in->audio_callback = NULL;
1296
store_history (dev);
1298
memset (audio_engines[dev]->cmd, 0, sizeof (audio_engines[dev]->cmd));
1299
memset (audio_engines[dev]->label, 0, sizeof (audio_engines[dev]->label));
1300
memset (audio_engines[dev]->song_name, 0,
1301
sizeof (audio_engines[dev]->song_name));
1302
audio_engines[dev]->pid = -1;
1303
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1306
* Free the DMA buffer(s)
1308
if (adev->dmask & DMASK_OUT)
1309
if (adev->dmap_out->dmabuf != NULL)
1311
if (adev->d->adrv_free_buffer != NULL)
1313
adev->d->adrv_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
1316
default_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
1317
adev->dmap_out->dmabuf = NULL;
1320
if (adev->dmask & DMASK_IN)
1321
if (adev->dmap_in != adev->dmap_out && adev->dmap_in->dmabuf != NULL)
1323
if (adev->d->adrv_free_buffer != NULL)
1325
adev->d->adrv_free_buffer (dev, adev->dmap_in, OPEN_READ);
1328
default_free_buffer (dev, adev->dmap_in, OPEN_READ);
1329
adev->dmap_in->dmabuf = NULL;
1332
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1333
adev->open_mode = 0;
1334
adev->flags &= ~ADEV_OPENED;
1335
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1338
static void audio_outputintr (int dev, int intr_flags);
1339
static void audio_inputintr (int dev, int intr_flags);
1343
oss_audio_open_engine (int dev, int no_worries, struct fileinfo *file,
1344
int recursive, int open_flags, int *newdev)
1350
int retval = 0, fmt;
1354
oss_native_word flags;
1355
extern int cooked_enable; /* Config option */
1361
mode = file->mode & O_ACCMODE;
1364
mode = OPEN_READ | OPEN_WRITE;
1369
(CE_CONT, "oss_audio_open_engine(%d, mode=0x%x)\n", dev, mode));
1372
oss_timing_printf ("-----> oss_audio_open_engine(%d, mode=0x%x)", dev, mode);
1375
if (dev < 0 || dev >= num_audio_engines || audio_engines == NULL)
1378
adev = audio_engines[dev];
1384
if (adev->osdev == NULL)
1386
cmn_err (CE_WARN, "adev->osdev==NULL\n");
1390
open_flags = get_open_flags (mode, open_flags, file);
1392
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1393
if (adev->open_mode != 0)
1395
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1398
adev->open_mode = mode;
1399
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1401
adev->cooked_enable = cooked_enable; /* This must be done before drv->open() */
1403
if (adev->cooked_enable)
1404
oss_do_timing ("Initial cooked mode ON");
1406
oss_do_timing ("Initial cooked mode OFF");
1409
adev->src_quality = src_quality;
1410
if ((retval = adev->d->adrv_open (dev, mode, open_flags)) < 0)
1412
adev->open_mode = 0;
1417
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1418
adev->outputintr = audio_outputintr;
1419
adev->inputintr = audio_inputintr;
1420
adev->forced_nonblock = 0;
1421
adev->setfragment_warned = 0;
1422
adev->getispace_error_count = 0;
1423
adev->sync_next = NULL;
1424
adev->sync_group = 0;
1425
adev->sync_flags = 0;
1426
adev->open_flags = open_flags;
1427
adev->flags |= ADEV_OPENED;
1428
adev->timeout_count = 0;
1430
adev->song_name[0] = 0;
1433
if (open_flags & (OF_NOCONV | OF_MMAP))
1435
adev->cooked_enable = 0;
1437
oss_do_timing ("Forcing cooked mode OFF");
1441
memset (audio_engines[dev]->cmd, 0, sizeof (audio_engines[dev]->cmd));
1445
strcpy (audio_engines[dev]->cmd, "OSS internal");
1446
audio_engines[dev]->pid = 0;
1452
if ((cmd = GET_PROCESS_NAME (file)) != NULL)
1454
strncpy (audio_engines[dev]->cmd, cmd, 16);
1455
strncpy (audio_engines[dev]->label, cmd, 16);
1456
audio_engines[dev]->cmd[15] = '\0';
1457
audio_engines[dev]->label[15] = '\0';
1459
audio_engines[dev]->pid = GET_PROCESS_PID (file);
1464
* Find out which dmap structures are required.
1467
if (mode == OPEN_WRITE)
1468
adev->dmask = DMASK_OUT;
1469
else if (mode == OPEN_READ)
1470
adev->dmask = DMASK_IN;
1473
if (mode != (OPEN_WRITE | OPEN_READ))
1474
cmn_err (CE_NOTE, "Unrecognized open mode %x\n", mode);
1475
adev->dmask = DMASK_OUT;
1477
if ((adev->flags & ADEV_DUPLEX) && adev->dmap_out != adev->dmap_in)
1478
adev->dmask = DMASK_OUT | DMASK_IN;
1483
* Handling of non-blocking doesn't belong here. It will be handled
1486
if (file != NULL && !(open_flags & OF_BLOCK))
1487
if (ISSET_FILE_FLAG (file, O_NONBLOCK) || adev->forced_nonblock)
1490
oss_do_timing ("*** Non-blocking open ***");
1495
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1497
if (adev->dmask & DMASK_OUT)
1501
* Use small DMA buffer if requested and if the device supports it.
1503
if (SMALL_DMABUF_SIZE >= (adev->min_block * 2) &&
1504
(open_flags & OF_SMALLBUF))
1505
adev->dmap_out->flags |= DMAP_SMALLBUF;
1507
if (MEDIUM_DMABUF_SIZE >= (adev->min_block * 2) &&
1508
(open_flags & OF_MEDIUMBUF))
1509
adev->dmap_out->flags |= DMAP_MEDIUMBUF;
1511
adev->dmap_out->flags &= ~(DMAP_SMALLBUF | DMAP_MEDIUMBUF);
1513
if ((retval = init_dmap (adev, adev->dmap_out, OPEN_WRITE)) < 0)
1515
oss_audio_release (dev, file);
1520
if (adev->dmask & DMASK_IN)
1523
* Use small DMA buffer if requested and if the device supports it.
1525
if (SMALL_DMABUF_SIZE >= (adev->min_block * 2) &&
1526
(open_flags & OF_SMALLBUF))
1527
adev->dmap_in->flags |= DMAP_SMALLBUF;
1529
adev->dmap_in->flags &= ~DMAP_SMALLBUF;
1531
if ((retval = init_dmap (adev, adev->dmap_in, OPEN_READ)) < 0)
1533
oss_audio_release (dev, file);
1538
adev->dmap_out->num_errors = 0;
1539
adev->dmap_in->num_errors = 0;
1541
if ((mode & OPEN_WRITE) && !(adev->flags & ADEV_NOOUTPUT))
1543
oss_reset_wait_queue (adev->out_wq);
1545
if ((mode & OPEN_READ) && !(adev->flags & ADEV_NOINPUT))
1547
oss_reset_wait_queue (adev->in_wq);
1550
adev->xformat_mask = 0;
1552
switch (adev->dmask)
1555
adev->xformat_mask = adev->oformat_mask;
1559
adev->xformat_mask = adev->iformat_mask;
1562
case DMASK_OUT | DMASK_IN:
1563
adev->xformat_mask = adev->oformat_mask & adev->iformat_mask;
1567
cmn_err (CE_WARN, "Internal error A during open\n");
1570
fmt = DSP_DEFAULT_FMT;
1571
rate = DSP_DEFAULT_SPEED;
1573
if (adev->flags & ADEV_FIXEDRATE && adev->fixed_rate != 0)
1574
rate = adev->fixed_rate;
1576
if (adev->flags & ADEV_16BITONLY)
1580
adev->enable_bits = adev->open_mode;
1583
if (adev->flags & ADEV_STEREOONLY)
1586
saved_cooked = adev->cooked_enable;
1587
adev->cooked_enable = 0;
1588
oss_audio_set_format (dev, fmt, adev->xformat_mask);
1589
oss_audio_set_channels (dev, channels);
1590
oss_audio_set_rate (dev, rate);
1591
adev->cooked_enable = saved_cooked;
1593
/* Clear the Cooked mode to permit mmap() */
1594
if (adev->dmask & DMASK_OUT)
1595
adev->dmap_out->flags &= ~DMAP_COOKED;
1596
if (adev->dmask & DMASK_IN)
1597
adev->dmap_in->flags &= ~DMAP_COOKED;
1603
oss_timing_printf ("=-=-=- Audio device %d (%s) opened, mode %x -=-=-=",
1604
adev->engine_num, adev->name, mode);
1606
if ((proc_pid = GET_PROCESS_PID (file)) != -1)
1607
oss_timing_printf ("Opened by PID: %d", proc_pid);
1609
if ((p_name = GET_PROCESS_NAME (file)) != NULL)
1610
oss_timing_printf ("Opening process name: %s", p_name);
1615
ossd_event (adev->engine_num, OSSD_EV_OPEN);
1618
return adev->engine_num;
1623
oss_audio_open_devfile (int dev, int dev_class, struct fileinfo *file,
1624
int recursive, int open_flags, int *newdev)
1627
* Open audio device file (by calling oss_audio_open_engine).
1632
int mode = OPEN_READ | OPEN_WRITE;
1635
oss_timing_printf ("-----> oss_audio_open_devfile(%d, mode=0x%x)", dev, mode);
1640
mode = file->mode & O_ACCMODE;
1641
open_flags = get_open_flags (mode, open_flags, file);
1642
if (file->acc_flags & O_EXCL)
1644
if (excl_policy == 0) open_excl = 1;
1645
#ifdef GET_PROCESS_UID
1646
else if ((excl_policy == 1) && (GET_PROCESS_UID () == 0)) open_excl = 1;
1652
(CE_CONT, "oss_audio_open_devfile(%d, mode=0x%x, excl=%d)\n", dev,
1655
if (dev < 0 || dev >= num_audio_devfiles)
1659
adev = audio_devfiles[dev];
1660
dev = adev->engine_num;
1663
while (adev->d->adrv_redirect != NULL)
1667
if (n++ > num_audio_engines)
1669
cmn_err(CE_CONT, "Recursive audio device redirection\n");
1673
next_dev = adev->d->adrv_redirect (dev, mode, open_flags);
1675
oss_timing_printf ("Engine redirect %d -> %d\n", dev, next_dev);
1678
if (next_dev == dev) /* No change */
1681
if (next_dev < 0 || next_dev >= num_audio_engines)
1685
adev = audio_engines[dev];
1689
* Check Exclusive mode open - do not do any kind of device
1690
* sharing. For the time being this mode is not supported with devices
1691
* that do hardware mixing.
1693
if (open_excl && !(adev->flags & ADEV_HWMIX))
1696
(CE_CONT, "Exclusive open, engine=%d\n", adev->engine_num));
1697
if ((dev = oss_audio_open_engine (adev->engine_num, dev_class, file,
1698
recursive, open_flags, newdev)) < 0)
1706
#ifdef CONFIG_OSS_VMIX
1708
* Get a vmix engine if the device has vmix support enabled.
1711
if (adev->vmix_mixer != NULL) // Virtual mixer attached
1716
* Create a new vmix client instance.
1719
if ((vmix_dev=vmix_create_client(adev->vmix_mixer))>=0)
1722
oss_timing_printf ("Vmix redirect %d -> %d\n", dev, vmix_dev);
1724
if ((dev = oss_audio_open_engine (vmix_dev, dev_class, file,
1725
recursive, open_flags, newdev)) < 0)
1727
//cmn_err(CE_WARN, "Failed to open vmix engine %d, err=%d\n", vmix_dev, dev);
1731
oss_timing_printf ("Vmix engine opened %d -> %d\n", vmix_dev, dev);
1741
* Follow redirection chain for the device.
1743
* (TODO: This feature was for earlier versions of vmix/softoss and not in use for the time being. However
1744
* it is possible that some other driver finds use for it in the future).
1749
if (mode == OPEN_WRITE)
1751
redirect = adev->redirect_out;
1753
else if (mode == OPEN_READ)
1755
redirect = adev->redirect_in;
1760
* Read-write open. Check that redirection for both directions are
1763
if (adev->redirect_out == adev->redirect_in)
1764
redirect = adev->redirect_out;
1768
(CE_CONT, "Redirect=%d (%d, %d)\n", redirect, adev->redirect_out,
1769
adev->redirect_in));
1771
if (redirect >= 0 && redirect < num_audio_engines)
1773
adev = audio_engines[redirect];
1775
(CE_CONT, "Redirect devfile %d -> engine=%d\n", dev,
1781
while (adev != NULL)
1783
DDB (cmn_err (CE_CONT, "Trying engine=%d\n", adev->engine_num));
1790
*newdev = adev->engine_num;
1792
oss_audio_open_engine (adev->engine_num, dev_class, file,
1793
recursive, open_flags, newdev)) < 0)
1796
* Check if the device was busy and if it has a
1799
if (err != OSS_EBUSY || adev->next_out == NULL)
1801
adev = adev->next_out;
1805
dev = adev->engine_num;
1806
DDB (cmn_err (CE_CONT, "Engine %d opened\n", adev->engine_num));
1815
* Try to find which minor number matches this /dev/dsp# device.
1818
if ((d = oss_find_minor (OSS_DEV_DSP_ENGINE, dev)) < 0)
1820
oss_audio_release (dev, file);
1855
256 *1024, 0}, /* 10 */
1859
setup_fragments (adev_p adev, dmap_p dmap, int direction)
1861
int sz, maxfrags = 100000;
1863
extern int max_intrate;
1865
if (adev->max_intrate == 0 || adev->max_intrate > max_intrate)
1866
adev->max_intrate = max_intrate;
1868
if (dmap->flags & DMAP_FRAGFIXED)
1870
dmap->flags |= DMAP_FRAGFIXED;
1873
oss_timing_printf ("setup_fragments(%d, dir=%d)", adev->engine_num, direction);
1878
dmap->low_water_rq = 0;
1879
dmap->low_water = -1;
1881
if (dmap->fragsize_rq != 0) /* SNDCTL_DSP_SETFRAGMENT was called */
1884
v = dmap->fragsize_rq & 0xffff;
1888
if (dmap->expand_factor != UNIT_EXPAND)
1892
sz2 = (sz * dmap->expand_factor) / UNIT_EXPAND;
1909
if (sz > dmap->buffsize / 2)
1910
sz = dmap->buffsize / 2;
1912
maxfrags = (dmap->fragsize_rq >> 16) & 0x7fff;
1916
else if (maxfrags < 2)
1919
if (maxfrags < adev->min_fragments)
1920
maxfrags = adev->min_fragments;
1921
else if (adev->max_fragments >= 2 && maxfrags > adev->max_fragments)
1922
maxfrags = adev->max_fragments;
1926
* Workaround for realplay
1928
if (adev->open_flags & OF_SMALLFRAGS)
1929
while (sz > dmap->buffsize / 8)
1937
if (adev->policy >= 0 && adev->policy <= 10)
1939
sz = policies[adev->policy].sz;
1940
maxfrags = policies[adev->policy].nfrags;
1941
if (maxfrags == 0) /* Unlimited */
1946
/* Use short fragments if ossd has registered this device */
1947
if (adev->ossd_registered)
1952
if (adev->min_block && adev->max_block)
1953
if (adev->min_block > adev->max_block)
1954
adev->min_block = adev->max_block = 0;
1956
if (adev->max_block > 0 && sz > adev->max_block)
1957
sz = adev->max_block;
1958
if (adev->min_block > 0 && sz < adev->min_block)
1959
sz = adev->min_block;
1964
/* Ensure that the interrupt rate is within the limits */
1968
if (adev->max_intrate > 0)
1972
data_rate = dmap->data_rate;
1973
if (data_rate < 8000)
1974
data_rate = adev->hw_parms.rate * 4;
1976
min = data_rate / adev->max_intrate;
1978
if (min > dmap->buffsize / 2)
1979
min = dmap->buffsize / 2;
1981
oss_timing_printf ("Max intrate %d -> min buffer %d", adev->max_intrate,
1987
if (dmap->flags & DMAP_COOKED)
1992
if (adev->max_block && min > adev->max_block)
1993
min = adev->max_block;
1999
if (adev->max_block > 0 && sz > adev->max_block)
2000
sz = adev->max_block;
2003
dmap->fragment_size = sz;
2004
dmap->nfrags = dmap->buffsize / sz;
2006
if (dmap == adev->dmap_out)
2008
if (direction == OPEN_WRITE)
2010
if (dmap->nfrags > maxfrags)
2011
dmap->nfrags = maxfrags;
2015
if (adev->d->adrv_setup_fragments)
2017
adev->d->adrv_setup_fragments (adev->engine_num, dmap, direction);
2020
dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size;
2022
if (dmap->nfrags < 2)
2025
dmap->fragment_size = dmap->bytes_in_use / 2;
2028
while (dmap->nfrags < adev->min_fragments)
2031
dmap->fragment_size /= 2;
2034
if (adev->max_fragments >= 2)
2035
while (dmap->nfrags > adev->max_fragments)
2038
dmap->fragment_size *= 2;
2040
while (dmap->nfrags < adev->min_fragments)
2043
dmap->fragment_size /= 2;
2046
dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size;
2048
dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size;
2049
dmap->low_water_rq = dmap->fragment_size;
2052
if (dmap->nfrags < 4)
2054
if (dmap->low_water_rq < dmap->bytes_in_use / 4)
2055
dmap->low_water_rq = dmap->bytes_in_use / 4;
2058
oss_timing_printf ("fragsz=%d, nfrags=%d", dmap->fragment_size, dmap->nfrags);
2063
getblksize (adev_p adev)
2067
oss_native_word flags, dflags;
2070
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
2071
if (adev->dmask & DMASK_IN)
2073
dmap = adev->dmap_in;
2075
if (!(dmap->flags & DMAP_FRAGFIXED))
2077
MUTEX_ENTER (dmap->mutex, dflags);
2078
setup_fragments (adev, dmap, OPEN_READ);
2079
size = dmap->fragment_size;
2080
MUTEX_EXIT (dmap->mutex, dflags);
2084
if (adev->dmask & DMASK_OUT)
2086
dmap = adev->dmap_out;
2088
if (!(dmap->flags & DMAP_FRAGFIXED))
2090
MUTEX_ENTER (dmap->mutex, dflags);
2091
setup_fragments (adev, dmap, OPEN_WRITE);
2092
size = dmap->fragment_size;
2093
MUTEX_EXIT (dmap->mutex, dflags);
2096
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
2103
get_output_pointer (adev_p adev, dmap_p dmap, int do_adjust)
2107
if (adev->d->adrv_get_output_pointer == NULL)
2109
return dmap->fragment_counter * dmap->fragment_size;
2112
UP_STATUS (STS_PTR);
2114
adev->d->adrv_get_output_pointer (adev->engine_num, dmap,
2115
PCM_ENABLE_OUTPUT) & ~7;
2116
DOWN_STATUS (STS_PTR);
2122
get_input_pointer (adev_p adev, dmap_p dmap, int do_adjust)
2126
if (adev->d->adrv_get_input_pointer == NULL)
2127
return dmap->fragment_counter * dmap->fragment_size;
2130
adev->d->adrv_get_input_pointer (adev->engine_num, dmap,
2131
PCM_ENABLE_INPUT) & ~7;
2132
if (ptr < dmap->byte_counter)
2133
ptr += dmap->bytes_in_use;
2134
ptr %= dmap->bytes_in_use;
2138
oss_uint64_t tmp = dmap->byte_counter;
2140
tmp = (tmp / dmap->bytes_in_use) * dmap->bytes_in_use;
2141
dmap->byte_counter = tmp + ptr;
2148
get_optr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2150
count_info *info = (count_info *) arg;
2151
oss_native_word flags;
2154
memset ((char *) info, 0, sizeof (count_info));
2156
if (dmap->dma_mode != PCM_ENABLE_OUTPUT || !(dmap->flags & DMAP_STARTED))
2159
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2161
info->ptr = get_output_pointer (adev, dmap, 1);
2162
info->blocks = dmap->interrupt_count;
2163
dmap->interrupt_count = 0;
2165
bytes = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2167
if (bytes < dmap->byte_counter)
2168
bytes += dmap->bytes_in_use;
2169
info->bytes = (unsigned int) bytes;
2170
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2172
/* Adjust for format conversions */
2173
info->ptr = (info->ptr * UNIT_EXPAND) / dmap->expand_factor;
2174
info->bytes = (info->bytes / dmap->expand_factor) * UNIT_EXPAND;
2175
info->bytes &= 0x3fffffff;
2178
oss_timing_printf ("GETOPTR(%d,%d,%d)", info->bytes, info->ptr, info->blocks);
2184
get_iptr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2186
count_info *info = (count_info *) arg;
2187
oss_native_word flags;
2190
memset ((char *) info, 0, sizeof (count_info));
2192
if (dmap->dma_mode != PCM_ENABLE_INPUT || !(dmap->flags & DMAP_STARTED))
2195
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2196
info->ptr = get_input_pointer (adev, dmap, 1);
2197
info->blocks = dmap->interrupt_count;
2198
dmap->interrupt_count = 0;
2200
bytes = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2202
if (bytes < dmap->byte_counter)
2203
bytes += dmap->bytes_in_use;
2204
info->bytes = (unsigned int) bytes;
2205
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2207
/* Adjust for format conversions */
2208
info->ptr = (info->ptr * UNIT_EXPAND) / dmap->expand_factor;
2209
info->bytes = (info->bytes / dmap->expand_factor) * UNIT_EXPAND;
2210
info->bytes &= 0x3fffffff;
2213
oss_timing_printf ("GETIPTR(%d,%d,%d)", info->bytes, info->ptr, info->blocks);
2218
#ifndef OSS_NO_LONG_LONG
2220
get_long_optr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2222
oss_count_t *ptr = (oss_count_t *) arg;
2223
oss_native_word flags;
2224
oss_uint64_t pos, bytes;
2226
memset ((char *) ptr, 0, sizeof (*ptr));
2228
if (dmap->dma_mode != PCM_ENABLE_OUTPUT || !(dmap->flags & DMAP_STARTED))
2231
ptr->fifo_samples = 0;
2232
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2233
if (dmap->frame_size < 1)
2234
dmap->frame_size = 1;
2235
if (dmap->user_frame_size < 1)
2236
dmap->user_frame_size = 1;
2237
pos = get_output_pointer (adev, dmap, 1);
2238
bytes = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2240
ptr->samples = (unsigned int) (bytes / dmap->frame_size);
2242
/* Adjust for format conversions */
2243
ptr->samples = (ptr->samples * UNIT_EXPAND) / dmap->expand_factor;
2245
if (adev->d->adrv_local_qlen)
2248
adev->d->adrv_local_qlen (adev->engine_num) / dmap->frame_size;
2250
(ptr->fifo_samples * UNIT_EXPAND) / dmap->expand_factor;
2252
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2258
get_long_iptr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2260
oss_count_t *ptr = (oss_count_t *) arg;
2261
oss_native_word flags;
2262
oss_uint64_t pos, bytes;
2264
memset ((char *) ptr, 0, sizeof (*ptr));
2266
if (dmap->dma_mode != PCM_ENABLE_INPUT || !(dmap->flags & DMAP_STARTED))
2269
ptr->fifo_samples = 0;
2270
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2271
if (dmap->frame_size < 1)
2272
dmap->frame_size = 1;
2273
if (dmap->user_frame_size < 1)
2274
dmap->user_frame_size = 1;
2275
pos = get_input_pointer (adev, dmap, 1);
2276
bytes = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2278
ptr->samples = (unsigned int) (bytes / dmap->frame_size);
2280
/* Adjust for format conversions */
2281
ptr->samples = (ptr->samples / dmap->expand_factor) * UNIT_EXPAND;
2283
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2290
get_odelay (adev_p adev, dmap_p dmap, ioctl_arg arg)
2292
oss_int64_t val, pos;
2293
oss_native_word flags;
2294
if (dmap->dma_mode != PCM_ENABLE_OUTPUT ||
2295
(dmap->mapping_flags & DMA_MAP_MAPPED))
2298
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2299
pos = get_output_pointer (adev, dmap, 1);
2300
val = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2302
val = dmap->user_counter - val;
2305
if (val > dmap->bytes_in_use)
2306
val = dmap->bytes_in_use;
2308
if (adev->d->adrv_local_qlen)
2310
val += adev->d->adrv_local_qlen (adev->engine_num);
2313
val += dmap->leftover_bytes;
2314
val = (val * UNIT_EXPAND) / dmap->expand_factor;
2316
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2318
oss_timing_printf ("GETODELAY(%d, %d)", adev->engine_num, val);
2320
return *arg = (val);
2323
static int audio_space_in_queue (adev_p adev, dmap_p dmap, int count);
2326
get_ospace (adev_p adev, dmap_p dmap, ioctl_arg arg)
2328
audio_buf_info *info = (audio_buf_info *) arg;
2329
oss_native_word flags;
2331
memset ((char *) info, 0, sizeof (audio_buf_info));
2333
if (!(dmap->flags & DMAP_PREPARED))
2335
setup_fragments (adev, dmap, OPEN_WRITE);
2336
prepare_output (adev, dmap);
2338
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2339
info->fragstotal = dmap->nfrags;
2341
info->fragsize = (dmap->fragment_size * UNIT_EXPAND) / dmap->expand_factor;
2343
/* Make sure we report full samples */
2345
((info->fragsize + dmap->user_frame_size -
2346
1) / dmap->user_frame_size) * dmap->user_frame_size;
2348
if (!(adev->open_mode & OPEN_WRITE))
2350
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2352
"SNDCTL_DSP_GETOSPACE cannot be called in read-only mode.\n");
2354
oss_do_timing ("GETOSPACE: Bad access mode - return EACCES");
2359
if (dmap->mapping_flags & DMA_MAP_MAPPED)
2361
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2363
"SNDCTL_DSP_GETOSPACE cannot be called in mmap mode.\n");
2365
oss_do_timing ("GETOSPACE: mmap access mode - return EPERM");
2367
oss_audio_set_error (adev->engine_num, E_PLAY,
2368
OSSERR (1000, "GETOSPACE called in mmap mode"), 0);
2370
* Do not call SNDCTL_DSP_GETOSPACE in mmap mode. Use SNDCTL_DSP_GETOPTR
2371
* instead. SNDCTL_DSP_GETOSPACE is defined only for applications that
2372
* use the normal write() method.
2373
* Applications that use mmap can call SNDCTL_DSP_GETOSPACE before calling
2374
* mmap to get the actual buffer size.
2379
if (!(dmap->flags & DMAP_STARTED))
2382
bytes = (int) ((long long) dmap->bytes_in_use - dmap->user_counter);
2385
oss_do_timing ("GETOSPACE: Not started - ignore device count");
2386
oss_timing_printf ("bytes_in_use=%d", dmap->bytes_in_use);
2387
oss_timing_printf ("user_counter=%lld", dmap->user_counter);
2388
oss_timing_printf ("raw bytes=%d", bytes);
2391
bytes = (bytes / dmap->expand_factor) * UNIT_EXPAND; /* Round downwards */
2392
bytes = (bytes / dmap->user_frame_size) * dmap->user_frame_size; /* Truncate to frame size */
2393
info->bytes = bytes;
2394
info->fragments = info->fragstotal = dmap->nfrags;
2395
if (info->bytes > info->fragsize * info->fragstotal)
2396
info->bytes = info->fragsize * info->fragstotal;
2398
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2402
info->bytes = audio_space_in_queue (adev, dmap, 0);
2404
oss_timing_printf ("audio_space_in_queue returned %d", info->bytes);
2407
if (info->bytes < dmap->low_water)
2410
if (adev->dmap_out->flags & DMAP_COOKED)
2413
if (dmap->tmpbuf_ptr > 0)
2414
info->bytes -= dmap->tmpbuf_ptr;
2417
if ((adev->dmap_out->flags & DMAP_COOKED) && info->bytes <
2418
dmap->fragment_size / 2)
2421
oss_do_timing ("GETOSPACE: Buffer full");
2426
if (info->bytes < 0)
2429
info->bytes = (info->bytes * UNIT_EXPAND) / dmap->expand_factor;
2430
info->bytes = (info->bytes / dmap->user_frame_size) * dmap->user_frame_size; /* Truncate to frame size */
2431
if (dmap->flags & DMAP_COOKED)
2434
* Reserve some space for format conversions. Sample rate conversions
2435
* may not always be able to take the "last" sample with fractional conversion
2438
if (info->bytes >= dmap->frame_size)
2439
info->bytes -= dmap->frame_size; /* Substract one sample. */
2441
info->fragments = info->bytes / info->fragsize;
2443
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2445
if (info->bytes > info->fragsize * info->fragstotal)
2446
info->bytes = info->fragsize * info->fragstotal;
2452
get_ispace (adev_p adev, dmap_p dmap, ioctl_arg arg)
2454
audio_buf_info *info = (audio_buf_info *) arg;
2455
oss_native_word flags;
2457
memset ((char *) info, 0, sizeof (audio_buf_info));
2459
setup_fragments (adev, dmap, OPEN_READ);
2460
prepare_input (adev, dmap);
2461
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2462
info->fragstotal = dmap->nfrags;
2463
info->fragsize = (dmap->fragment_size * UNIT_EXPAND) / dmap->expand_factor;
2465
/* Make sure we report full samples */
2467
((info->fragsize + dmap->user_frame_size -
2468
1) / dmap->user_frame_size) * dmap->user_frame_size;
2470
if (!(adev->open_mode & OPEN_READ))
2472
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2474
"SNDCTL_DSP_GETISPACE cannot be called in write-only mode.\n");
2478
if (dmap->mapping_flags & DMA_MAP_MAPPED)
2480
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2482
"SNDCTL_DSP_GETISPACE cannot be called in mmap mode.\n");
2483
oss_audio_set_error (adev->engine_num, E_REC,
2484
OSSERR (1003, "GETISPACE called in mmap mode"), 0);
2486
* Do not call SNDCTL_DSP_GETISPACE in mmap mode.
2487
* SNDCTL_DSP_GETISPACE is defined only for applications that
2488
* use the normal write() method.
2489
* Applications that use mmap can call SNDCTL_DSP_GETISPACE before calling
2490
* mmap to get the actual buffer size.
2495
if (!(dmap->flags & DMAP_STARTED))
2498
* A stupid application has called GETISPACE before recording has started.
2499
* The right behaviour would definitely be returning bytes=0. However
2500
* reporting one ready fragment will keep poor programmers happy.
2501
* After all this is a minor error because no properly written application
2502
* should ever call GETISPACE before starting recording.
2504
info->bytes = info->fragsize;
2505
info->fragments = 1;
2507
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2508
if (info->bytes > info->fragsize * info->fragstotal)
2509
info->bytes = info->fragsize * info->fragstotal;
2510
if (adev->getispace_error_count++ == 1) /* Second time this happens */
2512
oss_audio_set_error (adev->engine_num, E_REC,
2514
"GETISPACE called before recording has been started"),
2518
* There is no recoded data available before recording has been started.
2519
* This would result in situation where the application waits infinitely
2520
* for recorded data that never arrives. As a workaround
2521
* SNDCTL_DSP_GETISPACE will fake that one fragment is already available
2522
* to read. This in turn makes the application to block incorrectly.
2524
* Applications must start recording before calling SNDCTL_DSP_GETISPACE
2525
* if they are trying to avoid blocking. This can be done by calling
2526
* SNDCTL_DSP_SETTRIGGER.
2528
* However applications going to use mmap can/should call
2529
* SNDCTL_DSP_GETISPACE in the beginning to find out how large buffer to
2530
* map. In such case this event is a false alarm.
2536
info->bytes = (unsigned int) (dmap->byte_counter - dmap->user_counter);
2538
if (dmap->flags & DMAP_COOKED)
2540
/* Count the already converted bytes in the tmp buffer */
2541
int nn = dmap->tmpbuf_len - dmap->tmpbuf_ptr;
2547
if (info->bytes > dmap->bytes_in_use)
2548
info->bytes = dmap->bytes_in_use;
2550
info->bytes = (info->bytes * UNIT_EXPAND) / dmap->expand_factor;
2551
info->bytes = (info->bytes / dmap->user_frame_size) * dmap->user_frame_size;
2552
info->fragments = info->bytes / info->fragsize;
2553
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2555
if (info->bytes > info->fragsize * info->fragstotal)
2556
info->bytes = info->fragsize * info->fragstotal;
2559
oss_timing_printf ("GETISPACE(%d,%d,%d,%d)", info->bytes, info->fragments,
2560
info->fragsize, info->fragstotal);
2565
#define xrand(seed) (seed=1664525*seed+1013904223)
2568
setfragment_error (int dev)
2570
if (audio_engines[dev]->setfragment_warned)
2573
oss_audio_set_error (dev, E_PLAY,
2575
"SNDCTL_DSP_SETFRAGMENT was called too late."),
2578
* Errordesc: The SNDCTL_DSP_SETFRAGMENT call is only valid immediately after
2579
* opening the device. It can only be called once without reopening
2582
* Calling read/write or certain ioctl calls will lock the fragment size/count
2583
* to some values which makes changing it impossible.
2587
oss_do_timing ("Setfragment called twice");
2590
audio_engines[dev]->setfragment_warned = 1;
2594
handle_syncgroup (adev_p adev, oss_syncgroup * group)
2599
if (adev->sync_group != 0)
2606
if (adev->engine_num > SYNC_DEVICE_MASK)
2608
cmn_err (CE_WARN, "Bad device number %d\n", adev->engine_num);
2612
id = xrand (sync_seed) & ~SYNC_DEVICE_MASK; /* Clear the engine number field */
2613
id |= adev->engine_num;
2616
sync_dev = adev->engine_num;
2617
adev->sync_next = NULL;
2622
sync_dev = id & SYNC_DEVICE_MASK;
2625
if (sync_dev < 0 || sync_dev >= num_audio_engines)
2631
sync_adev = audio_engines[sync_dev];
2633
if (sync_dev == adev->engine_num)
2634
adev->sync_flags |= SYNC_MASTER;
2637
if (!(sync_adev->sync_flags & SYNC_MASTER))
2642
if (sync_adev->sync_group != id)
2647
adev->sync_flags |= SYNC_SLAVE;
2650
group->mode &= (PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT);
2651
group->mode &= adev->open_mode;
2652
if (group->mode == 0)
2654
adev->sync_flags = 0;
2658
adev->sync_mode = group->mode;
2659
adev->sync_group = id;
2660
if (adev->d->adrv_sync_control != NULL)
2661
adev->d->adrv_sync_control (adev->engine_num, SYNC_ATTACH,
2664
if (adev != sync_adev)
2666
adev->sync_next = sync_adev->sync_next;
2667
sync_adev->sync_next = adev;
2676
handle_syncstart (int orig_dev, int group)
2678
int master_dev, arg;
2681
master_dev = group & SYNC_DEVICE_MASK;
2682
if (master_dev < 0 || master_dev >= num_audio_engines)
2685
adev = audio_engines[master_dev];
2687
if (!(adev->sync_flags & SYNC_MASTER) ||
2688
master_dev != orig_dev)
2691
* Potential attack. SYNCSTART was called on wrong file descriptor.
2696
if (adev->sync_group != group)
2700
* Pass 1: Inform all devices about the actual start command to come soon.
2703
while (adev != NULL)
2706
if (adev->sync_group == group)
2710
if (adev->d->adrv_sync_control)
2712
if (adev->sync_mode & PCM_ENABLE_INPUT)
2714
if (!(adev->dmap_in->flags & DMAP_PREPARED))
2716
adev->dmap_in->dma_mode = PCM_ENABLE_INPUT;
2717
prepare_input (adev, adev->dmap_in);
2719
launch_input (adev, adev->dmap_in);
2721
if (adev->sync_mode & PCM_ENABLE_OUTPUT)
2723
dmap_p dmap = adev->dmap_out;
2726
if (adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)
2727
dmap->dma_mode = PCM_ENABLE_OUTPUT;
2728
if ((err = prepare_output (adev, adev->dmap_out)) < 0)
2730
launch_output (adev, adev->dmap_out);
2732
adev->d->adrv_sync_control (adev->engine_num, SYNC_PREPARE,
2738
oss_audio_ioctl (adev->engine_num, NULL, SNDCTL_DSP_SETTRIGGER,
2744
cmn_err (CE_NOTE, "Broken sync chain\n");
2747
adev = adev->sync_next;
2751
* Pass 2: Deliver the actual start commands.
2754
adev = audio_engines[master_dev];
2756
while (adev != NULL)
2759
if (adev->sync_group == group)
2763
if (adev->d->adrv_sync_control)
2764
adev->d->adrv_sync_control (adev->engine_num, SYNC_TRIGGER,
2768
arg = adev->sync_mode;
2769
oss_audio_ioctl (adev->engine_num, NULL, SNDCTL_DSP_SETTRIGGER,
2776
adev = adev->sync_next;
2780
next = adev->sync_next;
2781
adev->sync_next = NULL;
2782
adev->sync_flags = 0;
2783
adev->sync_group = 0;
2792
find_ioctl_name (unsigned int cmd, ioctl_arg val)
2794
static char tmp[32];
2801
#define IOF_DEC 0x00000001
2802
#define IOF_HEX 0x00000002
2805
static ioctl_def_t call_names[] = {
2806
{SNDCTL_DSP_HALT, "SNDCTL_DSP_HALT"},
2807
{SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"},
2808
{SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED", IOF_DEC},
2809
{SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO", IOF_DEC},
2810
{SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"},
2811
{SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS", IOF_DEC},
2812
{SNDCTL_DSP_POST, "SNDCTL_DSP_POST"},
2813
{SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"},
2814
{SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT", IOF_HEX},
2815
{SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"},
2816
{SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT", IOF_HEX},
2817
{SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"},
2818
{SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"},
2819
{SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"},
2820
{SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"},
2821
{SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER", IOF_HEX},
2822
{SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"},
2823
{SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"},
2824
{SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO", IOF_HEX},
2825
{SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"},
2826
{SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"},
2827
{SNDCTL_DSP_GETPLAYVOL, "SNDCTL_DSP_GETPLAYVOL"},
2828
{SNDCTL_DSP_SETPLAYVOL, "SNDCTL_DSP_SETPLAYVOL", IOF_HEX},
2829
{SNDCTL_DSP_GETRECVOL, "SNDCTL_DSP_GETRECVOL"},
2830
{SNDCTL_DSP_SETRECVOL, "SNDCTL_DSP_SETRECVOL", IOF_HEX},
2831
{SNDCTL_DSP_GETERROR, "SNDCTL_DSP_GETERROR"},
2832
{SNDCTL_DSP_READCTL, "SNDCTL_DSP_READCTL"},
2833
{SNDCTL_DSP_WRITECTL, "SNDCTL_DSP_WRITECTL"},
2834
{SNDCTL_DSP_SYNCGROUP, "SNDCTL_DSP_SYNCGROUP"},
2835
{SNDCTL_DSP_SYNCSTART, "SNDCTL_DSP_SYNCSTART"},
2836
{SNDCTL_DSP_COOKEDMODE, "SNDCTL_DSP_COOKEDMODE", IOF_DEC},
2837
{SNDCTL_DSP_SILENCE, "SNDCTL_DSP_SILENCE"},
2838
{SNDCTL_DSP_SKIP, "SNDCTL_DSP_SKIP"},
2839
{SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"},
2840
{SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"},
2841
{SNDCTL_DSP_HALT_INPUT, "SNDCTL_DSP_HALT_INPUT"},
2842
{SNDCTL_DSP_HALT_OUTPUT, "SNDCTL_DSP_HALT_OUTPUT"},
2843
{SNDCTL_DSP_LOW_WATER, "SNDCTL_DSP_LOW_WATER"},
2844
#ifndef OSS_NO_LONG_LONG
2845
{SNDCTL_DSP_CURRENT_IPTR, "SNDCTL_DSP_CURRENT_IPTR"},
2846
{SNDCTL_DSP_CURRENT_OPTR, "SNDCTL_DSP_CURRENT_OPTR"},
2848
{SNDCTL_DSP_GET_RECSRC, "SNDCTL_DSP_GET_RECSRC"},
2849
{SNDCTL_DSP_SET_RECSRC, "SNDCTL_DSP_SET_RECSRC"},
2850
{SNDCTL_DSP_GET_RECSRC_NAMES, "SNDCTL_DSP_GET_RECSRC_NAMES"},
2851
{SNDCTL_DSP_GET_PLAYTGT, "SNDCTL_DSP_GET_PLAYTGT"},
2852
{SNDCTL_DSP_SET_PLAYTGT, "SNDCTL_DSP_SET_PLAYTGT"},
2853
{SNDCTL_DSP_GET_PLAYTGT_NAMES, "SNDCTL_DSP_GET_PLAYTGT_NAMES"},
2858
for (i = 0; call_names[i].code != 0; i++)
2859
if (call_names[i].code == cmd)
2861
int flags = call_names[i].flags;
2863
if (flags & IOF_DEC)
2865
sprintf (tmp, "%s, *%d", call_names[i].name, *val);
2869
if (flags & IOF_HEX)
2871
sprintf (tmp, "%s, *0x%08x", call_names[i].name, *val);
2875
return call_names[i].name;
2878
sprintf (tmp, "Unknown %08x", cmd);
2885
oss_encode_enum (oss_mixer_enuminfo * ei, const char *s, int version)
2890
memset (ei, 0, sizeof (*ei)); /* Wipe out everything */
2892
strncpy (ei->strings, s, sizeof (ei->strings) - 1);
2893
ei->strings[sizeof (ei->strings) - 1] = 0;
2895
ei->strindex[0] = 0;
2897
l = strlen (ei->strings);
2898
for (i = 0; i < l; i++)
2900
if (ei->strings[i] == ' ')
2902
ei->strindex[n++] = i + 1;
2913
get_legacy_recsrc_names (int dev, oss_mixer_enuminfo * ei)
2915
static const char *labels[] = SOUND_DEVICE_NAMES;
2917
int i, mixer_dev, recmask, devmask, caps, n;
2920
if (audio_engines[dev]->mixer_dev < 0) /* No mixer */
2923
mixer_dev = audio_engines[dev]->mixer_dev;
2926
if (oss_legacy_mixer_ioctl
2927
(mixer_dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
2928
caps = 0; /* Error */
2930
if (caps & SOUND_CAP_NORECSRC)
2933
if (oss_legacy_mixer_ioctl
2934
(mixer_dev, -1, SOUND_MIXER_READ_DEVMASK, (ioctl_arg) & devmask) < 0)
2935
return 0; /* Error */
2937
if (oss_legacy_mixer_ioctl
2938
(mixer_dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
2939
return 0; /* Error */
2948
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
2949
if (recmask & (1 << i)) /* This control is also recording device */
2951
/*LINTED*/ ei->strindex[n] = s - ei->strings;
2953
strcpy (s, labels[i]);
2965
get_legacy_recsrc (int dev)
2967
int i, mixer_dev, recmask, recsrc, caps, n;
2969
if (audio_engines[dev]->mixer_dev < 0) /* No mixer */
2972
mixer_dev = audio_engines[dev]->mixer_dev;
2975
if (oss_legacy_mixer_ioctl
2976
(mixer_dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
2977
caps = 0; /* Error */
2979
if (caps & SOUND_CAP_NORECSRC)
2982
if (oss_legacy_mixer_ioctl
2983
(mixer_dev, -1, SOUND_MIXER_READ_RECSRC, (ioctl_arg) & recsrc) < 0)
2984
return 0; /* Error */
2986
if (oss_legacy_mixer_ioctl
2987
(mixer_dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
2988
return 0; /* Error */
2990
if (recmask == 0 || recsrc == 0)
2995
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
2996
if (recmask & (1 << i)) /* This control is also recording device */
2998
if (recsrc & (1 << i)) /* It was this one */
3008
set_legacy_recsrc (int dev, int val)
3010
int i, mixer_dev, recmask, recsrc, caps, n;
3012
if (audio_engines[dev]->mixer_dev < 0) /* No mixer */
3015
mixer_dev = audio_engines[dev]->mixer_dev;
3018
if (oss_legacy_mixer_ioctl
3019
(mixer_dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
3020
caps = 0; /* Error */
3022
if (caps & SOUND_CAP_NORECSRC)
3025
if (oss_legacy_mixer_ioctl
3026
(mixer_dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
3027
return 0; /* Error */
3034
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
3035
if (recmask & (1 << i)) /* This control is also recording device */
3041
if (oss_legacy_mixer_ioctl
3042
(mixer_dev, -1, SOUND_MIXER_WRITE_RECSRC,
3043
(ioctl_arg) & recsrc) < 0)
3044
return 0; /* Error */
3057
oss_audio_ioctl (int dev, struct fileinfo *bogus,
3058
unsigned int cmd, ioctl_arg arg)
3064
dmap_p dmapin, dmapout;
3065
oss_native_word flags;
3067
oss_timing_printf ("oss_audio_ioctl(%d, %s)", dev, find_ioctl_name (cmd, arg));
3070
if (cmd == OSS_GETVERSION)
3071
return *arg = OSS_VERSION;
3073
UP_STATUS (STS_IOCTL);
3074
DOWN_STATUS (STS_IOCTL);
3077
if (dev < 0 || dev >= num_audio_engines)
3080
adev = audio_engines[dev];
3086
if (adev->d->adrv_ioctl_override != NULL)
3089
* Use the ioctl override function if available. However process the request
3090
* in the usual way if the override function returned OSS_EAGAIN. It may
3091
* be possible that the override function has modified the parameters
3094
if ((err = adev->d->adrv_ioctl_override(dev, cmd, arg)) != OSS_EAGAIN)
3098
dmapout = adev->dmap_out;
3099
dmapin = adev->dmap_in;
3102
* Handle mixer ioctl calls on audio fd.
3105
if (cmd == SOUND_MIXER_WRITE_PCM) cmd = SNDCTL_DSP_SETPLAYVOL;
3106
if (cmd == SOUND_MIXER_WRITE_RECLEV) cmd = SNDCTL_DSP_SETRECVOL;
3107
if (cmd == SOUND_MIXER_READ_PCM) cmd = SNDCTL_DSP_GETPLAYVOL;
3108
if (cmd == SOUND_MIXER_READ_RECLEV) cmd = SNDCTL_DSP_GETRECVOL;
3110
if ((mixdev = adev->mixer_dev) != -1)
3112
if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0) /* Mixer ioctl */
3113
if ((ret = oss_legacy_mixer_ioctl (mixdev, dev, cmd, arg)) != OSS_EINVAL)
3117
if (((cmd >> 8) & 0xff) == 'X') /* Mixer extension API */
3118
return oss_mixer_ext (adev->engine_num, OSS_DEV_DSP, cmd, arg);
3122
case SNDCTL_DSP_SYNC:
3123
oss_audio_sync (adev);
3127
case SNDCTL_DSP_POST:
3128
oss_audio_post (adev);
3132
case SNDCTL_DSP_HALT:
3133
audio_reset_adev (adev);
3137
case SNDCTL_DSP_HALT_INPUT:
3138
audio_reset_input (adev);
3142
case SNDCTL_DSP_LOW_WATER:
3144
if (adev->open_mode & OPEN_READ)
3145
adev->dmap_in->low_water = val;
3146
if (adev->open_mode & OPEN_WRITE)
3147
adev->dmap_out->low_water = val;
3151
case SNDCTL_DSP_HALT_OUTPUT:
3152
audio_reset_output (adev);
3156
case SNDCTL_DSP_GETFMTS:
3157
switch (adev->open_mode & (OPEN_READ | OPEN_WRITE))
3160
return *arg = (adev->oformat_mask);
3164
return *arg = (adev->oformat_mask);
3168
return *arg = (adev->xformat_mask);
3173
case SNDCTL_DSP_SETFMT:
3175
switch (adev->open_mode & (OPEN_READ | OPEN_WRITE))
3178
return *arg = (oss_audio_set_format (dev, val,
3180
[dev]->oformat_mask));
3184
return *arg = (oss_audio_set_format (dev, val,
3186
[dev]->iformat_mask));
3190
return *arg = (oss_audio_set_format (dev, val,
3192
[dev]->oformat_mask &
3194
[dev]->iformat_mask));
3198
case SNDCTL_DSP_GETOSPACE:
3199
if (!(adev->dmask & DMASK_OUT))
3201
oss_audio_set_error (adev->engine_num, E_PLAY,
3203
"GETOSPACE called in read-only mode"),
3205
/* Errordesc: SNDCTL_DSP_GETOSPACE is not defined in read-only access mode */
3208
ret = get_ospace (adev, dmapout, arg);
3211
audio_buf_info *info = (audio_buf_info *) arg;
3212
oss_timing_printf ("GETOSPACE(b=%d,f=%d,fsz=%d,ft=%d)=%d", info->bytes,
3213
info->fragments, info->fragsize, info->fragstotal, ret);
3214
oss_timing_printf ("Low water %d, ap flags=%x, tmpbuf=%d/%d",
3215
dmapout->low_water, adev->open_flags, dmapout->tmpbuf_ptr,
3216
dmapout->tmpbuf_len);
3222
case SNDCTL_DSP_GETISPACE:
3223
if (!(adev->dmask & DMASK_IN))
3225
oss_audio_set_error (adev->engine_num, E_REC,
3227
"GETISPACE called in write-only mode"),
3230
* Errordesc: SNDCTL_DSP_GETISPACE has no defined meaning when the audio
3231
* device is opened in write-only mode.
3236
return get_ispace (adev, dmapin, arg);
3239
case SNDCTL_DSP_GETODELAY:
3240
if (!(adev->dmask & DMASK_OUT))
3242
oss_audio_set_error (adev->engine_num, E_PLAY,
3244
"GETODELAY called in read-only mode"),
3248
return get_odelay (adev, dmapout, arg);
3251
case SNDCTL_DSP_SETDUPLEX:
3253
* Note! SNDCTL_DSP_SETDUPLEX has not been implemented by any driver for years.
3254
* The call is still implemented in audio core but it may get removed in the
3257
if (adev->open_mode != OPEN_READWRITE)
3259
oss_audio_set_error (adev->engine_num, E_PLAY,
3261
"SETDUPLEX called in non-read/write mode"),
3265
if (adev->flags & ADEV_DUPLEX)
3267
if (adev->d->adrv_ioctl == NULL)
3269
val = adev->d->adrv_ioctl (dev, cmd, arg);
3270
if (val == OSS_EINVAL)
3281
case SNDCTL_DSP_COOKEDMODE:
3284
if (adev->flags & ADEV_NONINTERLEAVED)
3287
adev->cooked_enable = !!val;
3288
if (adev->d->adrv_ioctl != NULL)
3289
adev->d->adrv_ioctl (dev, cmd, arg);
3291
if (adev->cooked_enable)
3292
oss_do_timing ("Setting cooked mode ON");
3294
oss_do_timing ("Setting cooked mode OFF");
3299
case SNDCTL_DSP_GETCAPS:
3302
info = audio_engines[dev]->caps;
3303
info |= 2; /* Revision level of this ioctl() */
3306
if (!(adev->flags & ADEV_VIRTUAL) && !adev->d->adrv_local_qlen)
3308
info |= PCM_CAP_REALTIME;
3311
if (!(adev->flags & ADEV_NOINPUT))
3312
info |= PCM_CAP_INPUT;
3314
if (!(adev->flags & ADEV_NOOUTPUT))
3315
info |= PCM_CAP_OUTPUT;
3317
if ((adev->flags & ADEV_VIRTUAL))
3318
info |= PCM_CAP_VIRTUAL;
3320
if (!(adev->flags & ADEV_NOINPUT) && !(adev->flags & ADEV_NOOUTPUT))
3321
if (adev->flags & ADEV_DUPLEX && adev->open_mode == OPEN_READWRITE)
3322
info |= PCM_CAP_DUPLEX;
3325
if (adev->flags & ADEV_SPECIAL)
3326
info |= PCM_CAP_SPECIAL;
3328
if (dev < num_audio_engines - 1)
3330
if (audio_engines[dev + 1]->flags & ADEV_SHADOW)
3331
info |= PCM_CAP_MULTI;
3334
if (adev->d->adrv_local_qlen) /* Device has hidden buffers */
3335
info |= PCM_CAP_BATCH;
3337
if (adev->d->adrv_trigger) /* Supports SETTRIGGER */
3338
info |= PCM_CAP_TRIGGER;
3340
#ifdef ALLOW_BUFFER_MAPPING
3341
info |= PCM_CAP_MMAP;
3343
if (!(adev->flags & ADEV_NOINPUT))
3344
info |= PCM_CAP_INPUT;
3346
if (!(adev->flags & ADEV_NOOUTPUT))
3347
info |= PCM_CAP_OUTPUT;
3349
if (adev->d->adrv_bind != NULL)
3350
info |= PCM_CAP_BIND;
3352
* TODO: ADEV_DEFAULT is not the right way to find out
3353
* PCM_CAP_DEFAULT devices. A new ADEV_ flag should be defined
3356
if (adev->flags & ADEV_DEFAULT)
3357
info |= PCM_CAP_DEFAULT;
3359
return *arg = (info);
3363
case SNDCTL_DSP_NONBLOCK:
3364
adev->forced_nonblock = 1;
3368
case SNDCTL_DSP_GETCHANNELMASK:
3369
case SNDCTL_DSP_BIND_CHANNEL:
3370
if (adev->d->adrv_bind == NULL)
3372
return adev->d->adrv_bind (adev->engine_num, cmd, arg);
3375
case SNDCTL_DSP_SETTRIGGER:
3379
if (!adev->d->adrv_trigger)
3381
cmn_err (CE_NOTE, "Device %d doesn't have trigger capability\n",
3387
val &= PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
3388
val &= adev->open_mode;
3390
if ((val & adev->open_mode) != (adev->enable_bits & adev->open_mode))
3392
if ((val & PCM_ENABLE_OUTPUT)
3393
&& !(adev->enable_bits & PCM_ENABLE_OUTPUT))
3395
dmap_p dmap = adev->dmap_out;
3396
oss_native_word flags;
3397
if (adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)
3398
dmap->dma_mode = PCM_ENABLE_OUTPUT;
3399
if ((err = prepare_output (adev, adev->dmap_out)) < 0)
3401
launch_output (adev, adev->dmap_out);
3402
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
3403
adev->enable_bits &= PCM_ENABLE_OUTPUT;
3404
adev->enable_bits |= val & PCM_ENABLE_OUTPUT;
3405
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
3408
if ((val & PCM_ENABLE_INPUT)
3409
&& !(adev->enable_bits & PCM_ENABLE_INPUT))
3411
dmap_p dmap = adev->dmap_in;
3412
oss_native_word flags;
3413
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
3414
dmap->dma_mode = PCM_ENABLE_INPUT;
3415
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
3416
if ((err = prepare_input (adev, adev->dmap_in)) < 0)
3418
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
3419
launch_input (adev, adev->dmap_in);
3420
adev->enable_bits &= PCM_ENABLE_INPUT;
3421
adev->enable_bits |= val & PCM_ENABLE_INPUT;
3422
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
3425
adev->enable_bits = val;
3426
if (adev->enable_bits == 0 || adev->go) /* Device is enabled */
3428
adev->d->adrv_trigger (adev->engine_num, adev->enable_bits);
3436
case SNDCTL_DSP_GETTRIGGER:
3437
if (!adev->d->adrv_trigger)
3439
cmn_err (CE_NOTE, "Device %d doesn't have trigger capability\n",
3443
return *arg = (adev->enable_bits & adev->open_mode);
3446
case SNDCTL_DSP_SETSYNCRO:
3450
case SNDCTL_DSP_SYNCGROUP:
3451
return handle_syncgroup (adev, (oss_syncgroup *) arg);
3454
case SNDCTL_DSP_SYNCSTART:
3457
MUTEX_ENTER_IRQDISABLE (audio_global_mutex, flags);
3458
ret = handle_syncstart (adev->engine_num, val);
3459
MUTEX_EXIT_IRQRESTORE (audio_global_mutex, flags);
3464
case SNDCTL_DSP_GETERROR:
3466
audio_errinfo *info = (audio_errinfo *) arg;
3468
memset ((void *) info, 0, sizeof (*info));
3470
//if (audio_engines[dev]->open_mode & OPEN_READ)
3472
dmap_t *dmap = audio_engines[dev]->dmap_in;
3474
info->rec_overruns = dmap->rec_overruns;
3475
dmap->rec_overruns = 0;
3476
info->rec_ptradjust = 0;
3477
info->rec_errorcount = dmap->num_errors;
3478
info->rec_lasterror = dmap->errors[0];
3479
info->rec_errorparm = dmap->error_parms[0];
3482
//if (audio_engines[dev]->open_mode & OPEN_WRITE)
3484
dmap_t *dmap = audio_engines[dev]->dmap_out;
3486
info->play_underruns = dmap->play_underruns;
3487
dmap->play_underruns = 0;
3488
info->play_ptradjust = 0;
3489
info->play_errorcount = dmap->num_errors;
3490
info->play_lasterror = dmap->errors[0];
3491
info->play_errorparm = dmap->error_parms[0];
3498
case SNDCTL_DSP_GETPLAYVOL:
3499
case SNDCTL_DSP_SETPLAYVOL:
3503
mixdev = adev->mixer_dev;
3504
if (cmd == SNDCTL_DSP_SETPLAYVOL && mixdev >= 0
3505
&& mixdev < num_mixers)
3506
mixer_devs[mixdev]->modify_counter++;
3508
if (adev->d->adrv_ioctl == NULL
3509
|| (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL)
3511
/* Emulate these calls using mixer API */
3513
if (mixdev < 0 || mixdev >= num_mixers)
3516
if (cmd == SNDCTL_DSP_GETPLAYVOL)
3517
cmd = SOUND_MIXER_READ_PCM;
3519
cmd = SOUND_MIXER_WRITE_PCM;
3520
return mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3526
case SNDCTL_DSP_GETRECVOL:
3527
case SNDCTL_DSP_SETRECVOL:
3531
mixdev = adev->mixer_dev;
3532
if (cmd == SNDCTL_DSP_SETRECVOL && mixdev >= 0 && mixdev < num_mixers)
3533
mixer_devs[mixdev]->modify_counter++;
3535
if (adev->d->adrv_ioctl == NULL
3536
|| (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL)
3538
/* Emulate these calls using mixer API */
3540
if (mixdev < 0 || mixdev >= num_mixers)
3543
/* Try with RECGAIN */
3544
if (cmd == SNDCTL_DSP_GETRECVOL)
3545
cmd = SOUND_MIXER_READ_RECGAIN;
3547
cmd = SOUND_MIXER_WRITE_RECGAIN;
3548
err = mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3550
/* Try with RECLEV */
3551
if (cmd == SNDCTL_DSP_GETRECVOL)
3552
cmd = SOUND_MIXER_READ_RECLEV;
3554
cmd = SOUND_MIXER_WRITE_RECLEV;
3555
err = mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3557
if (err >= 0) /* Was OK */
3560
/* Try with IGAIN */
3561
if (cmd == SNDCTL_DSP_GETRECVOL)
3562
cmd = SOUND_MIXER_READ_IGAIN;
3564
cmd = SOUND_MIXER_WRITE_IGAIN;
3565
return mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3571
case SNDCTL_DSP_GETOPTR:
3572
if (!(adev->dmask & DMASK_OUT))
3574
oss_audio_set_error (adev->engine_num, E_PLAY,
3576
"GETOPTR called in read-only mode"),
3580
return get_optr (adev, dmapout, arg);
3583
case SNDCTL_DSP_GETIPTR:
3584
if (!(adev->dmask & DMASK_IN))
3586
oss_audio_set_error (adev->engine_num, E_REC,
3588
"GETIPTR called in write-only mode"),
3592
return get_iptr (adev, dmapin, arg);
3595
#ifndef OSS_NO_LONG_LONG
3596
case SNDCTL_DSP_CURRENT_OPTR:
3597
if (!(adev->dmask & DMASK_OUT))
3599
return get_long_optr (adev, dmapout, arg);
3602
case SNDCTL_DSP_CURRENT_IPTR:
3603
if (!(adev->dmask & DMASK_IN))
3605
return get_long_iptr (adev, dmapin, arg);
3609
case SNDCTL_DSP_POLICY:
3611
if (val < 0 || val > 10)
3617
case SNDCTL_DSP_SETFRAGMENT:
3618
case SNDCTL_DSP_SUBDIVIDE:
3619
if (cmd == SNDCTL_DSP_SUBDIVIDE)
3621
oss_audio_set_error (adev->engine_num, E_PLAY,
3623
"SNDCTL_DSP_SUBDIVIDE is obsolete"),
3627
* SNDCTL_DSP_SUBDIVIDE is obsolete. It's still emulated by OSS but
3628
* the result is not precise. You need to use SNDCTL_DSP_SETFRAGMENT
3631
*arg = 0x00040008; /* Default to 4 fragments of 256 bytes */
3635
if (adev->dmask & DMASK_OUT)
3637
if (dmapout->flags & DMAP_FRAGFIXED)
3638
setfragment_error (dev);
3639
dmapout->fragsize_rq = val;
3641
if (adev->dmask & DMASK_IN)
3643
if (dmapin->flags & DMAP_FRAGFIXED)
3644
setfragment_error (dev);
3645
dmapin->fragsize_rq = val;
3650
case FREEBSD_GETBLKSIZE:
3652
case SNDCTL_DSP_GETBLKSIZE:
3653
return *arg = getblksize (adev);
3655
case SNDCTL_DSP_SPEED:
3659
return *arg = (oss_audio_set_rate (dev, val));
3661
case SNDCTL_DSP_STEREO:
3668
oss_audio_set_error (adev->engine_num, E_PLAY,
3670
"SNDCTL_DSP_STEREO called with bad agrument value"),
3673
* Errordesc: SNDCTL_DSP_STEREO is an obsolete ioctl call that
3674
* supports only mono (0) or stereo (1). For larger number of channels
3675
* you need to use SNDCTL_DSP_CHANNELS instead.
3683
v = oss_audio_set_channels (dev, n + 1);
3684
return *arg = (v - 1);
3687
case SNDCTL_DSP_CHANNELS:
3695
sprintf (tmp, "Set channels %d", (int) val);
3696
oss_do_timing2 (DFLAG_PROFILE, tmp);
3703
v = oss_audio_set_channels (dev, val);
3707
case SNDCTL_DSP_PROFILE: /* Obsolete */
3711
case SNDCTL_DSP_SILENCE:
3712
memset (dmapout->dmabuf, dmapout->neutral_byte, dmapout->buffsize);
3716
case SNDCTL_DSP_SKIP:
3720
case SNDCTL_DSP_GET_RECSRC_NAMES:
3721
if (adev->d->adrv_ioctl == NULL || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL) /* Not handled */
3723
oss_mixer_enuminfo *ei = (oss_mixer_enuminfo *) arg;
3725
memset (ei, 0, sizeof (*ei)); /* Wipe out everything */
3727
if (get_legacy_recsrc_names (dev, ei))
3730
strcpy (ei->strings, "default");
3736
case SNDCTL_DSP_GET_RECSRC:
3737
if (adev->d->adrv_ioctl == NULL || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL) /* Not handled */
3739
return *arg = (get_legacy_recsrc (dev));
3744
case SNDCTL_DSP_SET_RECSRC:
3745
if (adev->d->adrv_ioctl == NULL || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL) /* Not handled */
3748
set_legacy_recsrc (dev, val);
3749
return *arg = (get_legacy_recsrc (dev));
3754
case SNDCTL_DSP_GET_PLAYTGT_NAMES:
3755
if (adev->d->adrv_ioctl == NULL || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL) /* Not handled */
3757
oss_mixer_enuminfo *ei = (oss_mixer_enuminfo *) arg;
3758
memset (ei, 0, sizeof (*ei));
3760
strcpy (ei->strings, "default");
3766
case SNDCTL_DSP_GET_PLAYTGT:
3767
if (adev->d->adrv_ioctl == NULL || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL) /* Not handled */
3774
case SNDCTL_DSP_SET_PLAYTGT:
3775
if (adev->d->adrv_ioctl == NULL || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL) /* Not handled */
3782
case SNDCTL_SETSONG:
3783
if (adev->d->adrv_ioctl != NULL
3784
&& adev->d->adrv_ioctl (dev, cmd, arg) >= 0)
3786
strncpy (adev->song_name, (char *) arg, sizeof (adev->song_name));
3787
adev->song_name[sizeof (adev->song_name) - 1] = 0;
3791
case SNDCTL_SETLABEL:
3792
if (adev->d->adrv_ioctl != NULL
3793
&& adev->d->adrv_ioctl (dev, cmd, arg) >= 0)
3795
strncpy (adev->label, (char *) arg, sizeof (adev->label));
3796
adev->label[sizeof (adev->label) - 1] = 0;
3797
if (*adev->cmd == 0) /* Command name not known */
3798
strcpy (adev->cmd, adev->label);
3802
if (adev->d->adrv_ioctl == NULL)
3804
return adev->d->adrv_ioctl (dev, cmd, arg);
3811
prepare_output (adev_p adev, dmap_p dmap)
3813
int ret, data_rate = 0;
3814
audio_format_info_p fmt_info;
3816
if (dmap->flags & DMAP_PREPARED)
3821
dmap->flags &= ~DMAP_COOKED;
3822
adev->user_parms.convert = 0;
3823
adev->hw_parms.convert = 0;
3824
dmap->convert_func = NULL;
3825
dmap->convert_mode = 0;
3826
dmap->expand_factor = UNIT_EXPAND;
3828
if (adev->user_parms.rate != adev->hw_parms.rate)
3829
dmap->flags |= DMAP_COOKED;
3830
if (adev->user_parms.fmt != adev->hw_parms.fmt)
3831
dmap->flags |= DMAP_COOKED;
3832
if (adev->user_parms.channels != adev->hw_parms.channels)
3833
dmap->flags |= DMAP_COOKED;
3834
if ((adev->flags & ADEV_NONINTERLEAVED) && adev->hw_parms.channels > 1)
3835
dmap->flags |= DMAP_COOKED;
3838
if (always_cooked && !(dmap->mapping_flags & DMA_MAP_MAPPED))
3839
dmap->flags |= DMAP_COOKED;
3842
if ((dmap->mapping_flags & DMA_MAP_MAPPED) && (dmap->flags & DMAP_COOKED))
3844
cmn_err (CE_WARN, "Internal error in mmap() support\n");
3845
dmap->flags &= ~DMAP_COOKED;
3848
if (dmap->flags & DMAP_COOKED)
3851
oss_do_timing ("Cooked mode - Setting up conversions");
3854
setup_format_conversions (adev, dmap, &adev->user_parms,
3858
adev->oformat_mask)) < 0)
3865
DDB (cmn_err (CE_CONT, "No format conversions needed\n"));
3867
oss_do_timing ("No format conversions needed");
3872
* Compute device data rate and frame size
3874
if ((fmt_info = oss_find_format (adev->hw_parms.fmt)) != NULL)
3875
data_rate = fmt_info->bits;
3880
data_rate *= adev->hw_parms.channels;
3881
dmap->frame_size = data_rate;
3882
data_rate *= adev->hw_parms.rate;
3885
dmap->data_rate = data_rate;
3888
* Compute application/user frame_size
3891
if ((fmt_info = oss_find_format (adev->user_parms.fmt)) != NULL)
3892
data_rate = fmt_info->bits;
3897
data_rate *= adev->user_parms.channels;
3898
dmap->user_frame_size = data_rate;
3900
setup_fragments (adev, dmap, OPEN_WRITE);
3901
if (dmap->expand_factor == 0)
3903
dmap->expand_factor = UNIT_EXPAND;
3904
cmn_err (CE_WARN, "Bad expand factor for device %d\n",
3907
if (dmap->low_water == -1)
3910
(dmap->low_water_rq * UNIT_EXPAND) / dmap->expand_factor;
3914
oss_timing_printf ("Prepare output dev=%d, fragsize=%d, nfrags=%d, bytes_in_use=%d/%d",
3915
adev->engine_num, dmap->fragment_size, dmap->nfrags,
3916
dmap->bytes_in_use, dmap->buffsize);
3920
adev->d->adrv_prepare_for_output (adev->engine_num,
3921
dmap->fragment_size,
3927
dmap->flags |= DMAP_PREPARED;
3929
ossd_event (adev->engine_num, OSSD_EV_PREPARE_OUTPUT);
3936
prepare_input (adev_p adev, dmap_p dmap)
3938
int ret, data_rate = 0;
3939
audio_format_info_p fmt_info;
3941
if (dmap->flags & DMAP_PREPARED)
3946
dmap->flags &= ~DMAP_COOKED;
3947
adev->user_parms.convert = 0;
3948
adev->hw_parms.convert = 0;
3949
dmap->convert_func = NULL;
3950
dmap->convert_mode = 0;
3951
dmap->expand_factor = UNIT_EXPAND;
3953
if (adev->user_parms.rate != adev->hw_parms.rate)
3954
dmap->flags |= DMAP_COOKED;
3955
if (adev->user_parms.fmt != adev->hw_parms.fmt)
3956
dmap->flags |= DMAP_COOKED;
3957
if (adev->user_parms.channels != adev->hw_parms.channels)
3958
dmap->flags |= DMAP_COOKED;
3959
if ((adev->flags & ADEV_NONINTERLEAVED) && adev->hw_parms.channels > 1)
3960
dmap->flags |= DMAP_COOKED;
3963
if (always_cooked && !(dmap->mapping_flags & DMA_MAP_MAPPED))
3964
dmap->flags |= DMAP_COOKED;
3967
if ((dmap->mapping_flags & DMA_MAP_MAPPED) && (dmap->flags & DMAP_COOKED))
3969
cmn_err (CE_WARN, "Internal error in mmap() support\n");
3970
dmap->flags &= ~DMAP_COOKED;
3973
if (dmap->flags & DMAP_COOKED)
3976
setup_format_conversions (adev, dmap, &adev->hw_parms,
3980
adev->iformat_mask)) < 0)
3983
(CE_CONT, "setup_format_conversions failed, err=%d\n", ret));
3988
dmap->expand_factor = UNIT_EXPAND;
3991
* Compute device data rate and frame size
3993
if ((fmt_info = oss_find_format (adev->hw_parms.fmt)) != NULL)
3994
data_rate = fmt_info->bits;
3999
data_rate *= adev->hw_parms.channels;
4000
dmap->frame_size = data_rate;
4001
data_rate *= adev->hw_parms.rate;
4004
dmap->data_rate = data_rate;
4007
* Compute user/application frame size
4010
if ((fmt_info = oss_find_format (adev->user_parms.fmt)) != NULL)
4011
data_rate = fmt_info->bits;
4016
data_rate *= adev->user_parms.channels;
4017
dmap->user_frame_size = data_rate;
4019
setup_fragments (adev, dmap, OPEN_READ);
4022
/* Compute 1/expand_factor */
4024
if (dmap->expand_factor == 0)
4026
cmn_err (CE_NOTE, "Internal error (expand_factor==0)\n");
4027
dmap->expand_factor = UNIT_EXPAND;
4031
int expand = dmap->expand_factor;
4032
int expand2 = expand * 100 / UNIT_EXPAND;
4033
DDB (cmn_err (CE_CONT, "Expand factor was = %d (%d.%02d)\n", expand,
4034
expand2 / 100, expand2 % 100));
4037
dmap->expand_factor = (UNIT_EXPAND * UNIT_EXPAND) / dmap->expand_factor;
4040
int expand = dmap->expand_factor;
4041
int expand2 = expand * 100 / UNIT_EXPAND;
4043
(CE_CONT, "Expand factor inverted to = %d (%d.%02d)\n", expand,
4044
expand2 / 100, expand2 % 100));
4048
if (dmap->low_water == -1)
4051
(dmap->low_water_rq * UNIT_EXPAND) / dmap->expand_factor;
4055
oss_timing_printf ("Prepare input dev=%d, fragsize=%d, nfrags=%d, bytes_in_use=%d",
4056
adev->engine_num, dmap->fragment_size, dmap->nfrags,
4057
dmap->bytes_in_use);
4061
adev->d->adrv_prepare_for_input (adev->engine_num, dmap->fragment_size,
4065
(CE_CONT, "/dev/dsp%d: prepare_for_input failed, err=%d\n",
4066
adev->engine_num, ret));
4070
dmap->flags |= DMAP_PREPARED;
4072
ossd_event (adev->engine_num, OSSD_EV_PREPARE_INPUT);
4079
launch_input (adev_p adev, dmap_p dmap)
4082
oss_do_timing ("Launch input called");
4084
if (dmap->flags & DMAP_STARTED)
4087
if (!(dmap->flags & DMAP_PREPARED))
4089
cmn_err (CE_WARN, "launch_input while not prepared.\n");
4094
oss_do_timing ("Launch_input calling d->start_input");
4097
if (adev->d->adrv_start_input != NULL)
4099
if (adev->flags & ADEV_AUTOMODE)
4100
adev->d->adrv_start_input (adev->engine_num, dmap->dmabuf_phys,
4101
dmap->bytes_in_use, dmap->fragment_size,
4104
adev->d->adrv_start_input (adev->engine_num, dmap->dmabuf_phys,
4105
dmap->fragment_size, dmap->fragment_size,
4110
oss_do_timing ("Launch_input calling trigger");
4112
dmap->flags |= DMAP_STARTED;
4113
if (adev->d->adrv_trigger
4114
&& ((adev->enable_bits * adev->go) & PCM_ENABLE_INPUT))
4116
adev->d->adrv_trigger (adev->engine_num, adev->enable_bits * adev->go);
4123
find_raw_input_space (adev_p adev, dmap_p dmap, int *dmapos)
4127
oss_uint64_t offs, doffs;
4129
unsigned int status;
4130
oss_native_word flags;
4132
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4134
get_input_pointer (adev, dmap, 1);
4135
count = (int) (dmap->byte_counter - dmap->user_counter);
4138
if (dmap->flags & DMAP_COOKED)
4140
lim = dmap->fragment_size;
4147
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4149
oss_do_timing ("*** EAGAIN ***");
4156
cmn_err (CE_WARN, "Audio input %d doesn't get filled.\n",
4158
cmn_err (CE_CONT, "Counters %d / %d\n", count, lim);
4159
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4163
tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
4164
tmout += OSS_HZ / 2;
4170
oss_do_timing ("Sleep (in)");
4171
oss_timing_enter (DF_SLEEPREAD);
4173
audio_engines[adev->engine_num]->dmap_in->error = 0;
4174
if (!oss_sleep (adev->in_wq, &dmap->mutex, tmout, &flags, &status))
4177
oss_do_timing ("Sleep (in) timed out");
4179
adev->timeout_count++;
4180
if (adev->d->adrv_check_input)
4182
int err = adev->d->adrv_check_input (adev->engine_num);
4184
continue; /* Retry */
4185
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4189
"Input timed out on audio engine %d (count=%lld)\n",
4190
adev->engine_num, dmap->byte_counter);
4191
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4192
FMA_EREPORT(adev->osdev, DDI_FM_DEVICE_STALL, NULL, NULL, NULL);
4193
FMA_IMPACT(adev->osdev, DDI_SERVICE_LOST);
4198
oss_timing_leave (DF_SLEEPREAD);
4199
oss_do_timing ("Sleep (in) done");
4202
if (status & WK_SIGNAL)
4204
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4207
count = (int) (dmap->byte_counter - dmap->user_counter);
4209
oss_timing_printf ("User counter %d, byte_counter %d", dmap->user_counter,
4210
dmap->byte_counter);
4214
/* Now we should have some data */
4217
get_input_pointer (adev, dmap, 1);
4219
offs = dmap->user_counter % dmap->bytes_in_use;
4220
doffs = dmap->byte_counter % dmap->bytes_in_use;
4222
count = (int) (dmap->bytes_in_use - offs);
4224
count = (int) (doffs - offs);
4226
count = dmap->bytes_in_use;
4229
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4236
move_raw_rdpointer (adev_p adev, dmap_p dmap, int len)
4239
oss_native_word flags;
4241
oss_timing_printf ("Move rdpointer, offs=%d, incr %d", dmap->user_counter,
4244
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4245
dmap->user_counter += len;
4246
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4252
copy_read_noninterleaved(adev_t *adev, dmap_t *dmap, int dma_offs, unsigned char *localbuf, int local_offs, int l)
4255
* Copy audio data from non-interleaved device buffer to interleaved
4258
// TODO: This function assumes 32 bit audio DATA
4260
int ch, i, nc = adev->hw_parms.channels;
4261
int *outbuf, *inbuf;
4263
l /= sizeof(*outbuf)*nc;
4264
dma_offs /= sizeof(*outbuf);
4265
local_offs /= sizeof(*outbuf);
4267
for (ch=0;ch<nc;ch++)
4269
outbuf = (int*)(localbuf+local_offs);
4272
inbuf = (int *)(dmap->dmabuf + dmap->buffsize*ch / nc);
4273
inbuf += dma_offs / nc;
4285
find_input_space (adev_p adev, dmap_p dmap, unsigned char **dbuf)
4287
unsigned char *p, *p1 = dmap->tmpbuf1, *p2 = dmap->tmpbuf2;
4288
int err, l, l2, max, dmapos;
4290
if (!(dmap->flags & DMAP_COOKED))
4292
err=find_raw_input_space (adev, dmap, &dmapos);
4293
*dbuf=dmap->dmabuf+dmapos;
4297
if (dmap->tmpbuf_len > dmap->tmpbuf_ptr)
4299
*dbuf = dmap->tmpbuf1 + dmap->tmpbuf_ptr;
4300
return dmap->tmpbuf_len - dmap->tmpbuf_ptr;
4303
dmap->tmpbuf_len = dmap->tmpbuf_ptr = 0;
4305
if ((l = find_raw_input_space (adev, dmap, &dmapos)) < 0)
4311
if (dmap->expand_factor > UNIT_EXPAND)
4312
max = (TMP_CONVERT_MAX * UNIT_EXPAND) / dmap->expand_factor;
4314
max = TMP_CONVERT_MAX;
4316
if (max > TMP_CONVERT_MAX)
4317
max = TMP_CONVERT_MAX;
4321
l = (l / dmap->frame_size) * dmap->frame_size; /* Truncate to nearest frame size */
4324
VMEM_CHECK (p+dmapos, l);
4326
if ((adev->flags & ADEV_NONINTERLEAVED) && adev->hw_parms.channels > 1)
4327
copy_read_noninterleaved(adev, dmap, dmapos, p1, 0, l);
4329
memcpy (p1, p+dmapos, l);
4331
move_raw_rdpointer (adev, dmap, l);
4334
dmap->convert_func (adev, dmap, &p1, &l2,
4335
&p2, &adev->hw_parms,
4336
&adev->user_parms)) < 0)
4341
dmap->tmpbuf_len = l2;
4343
*dbuf = dmap->tmpbuf1;
4344
return dmap->tmpbuf_len;
4348
move_rdpointer (adev_p adev, dmap_p dmap, int len)
4350
if (!(dmap->flags & DMAP_COOKED) || dmap->tmpbuf_ptr >= dmap->tmpbuf_len)
4352
dmap->tmpbuf_ptr = 0;
4353
dmap->tmpbuf_len = 0;
4354
return move_raw_rdpointer (adev, dmap, len);
4357
if (dmap->tmpbuf_ptr < dmap->tmpbuf_len)
4359
dmap->tmpbuf_ptr += len;
4361
if (dmap->tmpbuf_ptr >= dmap->tmpbuf_len)
4362
dmap->tmpbuf_len = dmap->tmpbuf_ptr = 0;
4367
cmn_err (CE_NOTE, "Why here?\n");
4372
oss_audio_read (int dev, struct fileinfo *file, uio_t * buf, int count)
4376
int c, l, p, ret, n;
4377
unsigned char *dmabuf;
4379
oss_timing_printf ("--- audio_read(%d, %d) ---", dev, count);
4384
if (dev < 0 || dev >= num_audio_engines)
4387
adev = audio_engines[dev];
4390
if (adev->flags & ADEV_NOINPUT)
4392
dmap = adev->dmap_in;
4394
if (!(adev->open_mode & OPEN_READ))
4396
if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
4398
audio_reset_output (adev);
4405
oss_reset_wait_queue (adev->in_wq);
4409
if ((ISSET_FILE_FLAG (file, O_NONBLOCK)
4410
&& !(adev->open_flags & OF_BLOCK)) || adev->forced_nonblock)
4416
oss_do_timing ("*** NON BLOCKING READ ***");
4420
if (dmap->dma_mode != PCM_ENABLE_INPUT)
4422
if ((ret = prepare_input (adev, dmap)) < 0)
4424
DDB (cmn_err (CE_CONT, "Prepare input failed, err=%d\n", ret));
4427
dmap->dma_mode = PCM_ENABLE_INPUT;
4428
launch_input (adev, dmap);
4431
if (!(dmap->flags & DMAP_PREPARED))
4432
{ /* Not prepared. Why??? */
4433
cmn_err (CE_WARN, "Intenal error (not prepared)\n");
4441
while (c > 0 && n++ < 1000)
4443
if ((l = find_input_space (adev, dmap, &dmabuf)) < 0)
4447
if (c == count) /* Nothing read yet */
4451
if (l == OSS_EAGAIN)
4453
if (c == count) /* Nothing read yet */
4463
if (uiomove (dmabuf, l, UIO_READ, buf) != 0)
4465
cmn_err (CE_WARN, "audio: uiomove(UIO_READ) failed\n");
4468
if ((ret = move_rdpointer (adev, dmap, l)) < 0)
4478
oss_timing_printf ("-------- Audio read done (%d)", count - c);
4486
audio_space_in_queue (adev_p adev, dmap_p dmap, int count)
4490
cnt = (int) (dmap->byte_counter + dmap->bytes_in_use - dmap->user_counter);
4494
cmn_err (CE_CONT, "Buffer %d overfilled (%d)\n", adev->engine_num, cnt);
4497
if (!(dmap->mapping_flags & DMA_MAP_MAPPED))
4498
if (cnt > dmap->bytes_in_use) /* Output underrun */
4501
oss_timing_printf ("adev %d: Play underrun B", adev->engine_num);
4502
oss_timing_printf (" User=%lld", dmap->user_counter);
4503
oss_timing_printf (" Dev=%lld", dmap->byte_counter);
4504
oss_timing_printf (" Tmp=%d", dmap->tmpbuf_ptr);
4506
cnt = dmap->bytes_in_use;
4507
dmap->user_counter = dmap->byte_counter;
4508
dmap->play_underruns++;
4509
if (!dmap->underrun_flag)
4512
oss_do_timing ("Clearing the buffer");
4514
memset (dmap->dmabuf, dmap->neutral_byte, dmap->bytes_in_use);
4516
dmap->underrun_flag = 1;
4519
if ((dmap->user_counter + cnt) > (dmap->byte_counter + dmap->bytes_in_use))
4520
cmn_err (CE_CONT, "Overflow %lld+%d, %lld\n", dmap->user_counter, cnt,
4521
dmap->byte_counter);
4527
find_output_space (adev_p adev, dmap_p dmap, int *size, int count)
4530
int len, l2, n = 0, tmout;
4531
oss_native_word flags;
4533
unsigned int status;
4537
cmn_err (CE_WARN, "Internal error - dmap==NULL\n");
4541
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4542
len = audio_space_in_queue (adev, dmap, count);
4545
while (len < dmap->user_frame_size)
4546
{ /* Wait for some space */
4549
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4550
cmn_err (CE_WARN, "Internal timeout error B\n");
4554
if (adev->nonblock || !(adev->enable_bits & PCM_ENABLE_OUTPUT))
4556
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4558
oss_timing_printf ("Space=%d\n", len);
4559
oss_do_timing ("*** EAGAIN ***");
4561
if (!(adev->enable_bits & PCM_ENABLE_OUTPUT))
4563
launch_output (adev, dmap);
4564
oss_audio_set_error (adev->engine_num, E_PLAY,
4566
"Play buffer full when playback is triggered off."),
4570
* An application had written too many samples of data between
4571
* turning off the PCM_ENABLE_OUTPUT trigger bit and turning it back
4572
* again to trigger playback.
4574
* Applications using SNDCTL_DSP_SETTRIGGER should avoid filling the
4575
* available playback buffer before triggering output.
4577
* One possible error causing this is that the application has
4578
* triggered only recording on a duplex device.
4584
if (n++ > dmap->nfrags * 2)
4586
cmn_err (CE_WARN, "Audio output %d doesn't drain (%lld/%lld %d).\n",
4587
adev->engine_num, dmap->user_counter, dmap->byte_counter,
4589
cmn_err (CE_CONT, "len=%d/%d, total=%d\n", len, dmap->fragment_size,
4590
dmap->bytes_in_use);
4592
oss_do_timing ("Audio output doesn't drain");
4594
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4595
audio_reset_output (adev);
4599
tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
4605
audio_engines[adev->engine_num]->dmap_out->error = 0;
4608
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4612
oss_timing_printf ("Sleep(%d)", adev->engine_num);
4613
oss_timing_enter (DF_SLEEPWRITE);
4615
UP_STATUS (STS_SLEEP);
4616
if (!oss_sleep (adev->out_wq, &dmap->mutex, tmout, &flags, &status))
4619
oss_timing_printf ("Sleep(%d) (out) timed out", adev->engine_num);
4621
adev->timeout_count++;
4623
if (adev->d->adrv_check_output)
4625
int err = adev->d->adrv_check_output (adev->engine_num);
4627
continue; /* Retry */
4628
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4634
"Output timed out on audio engine %d/'%s' (count=%lld)\n",
4635
adev->engine_num, adev->name, dmap->byte_counter);
4637
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4638
FMA_EREPORT(adev->osdev, DDI_FM_DEVICE_STALL, NULL, NULL, NULL);
4639
FMA_IMPACT(adev->osdev, DDI_SERVICE_LOST);
4642
DOWN_STATUS (STS_SLEEP);
4645
oss_timing_leave (DF_SLEEPWRITE);
4646
oss_timing_printf ("Sleep(%d) (out) done", adev->engine_num);
4649
if (status & WK_SIGNAL)
4652
oss_do_timing ("Signal caught");
4654
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4658
len = audio_space_in_queue (adev, dmap, count);
4660
oss_timing_printf ("Free output space now %d bytes", len);
4662
} /* Wait for space */
4665
* Now we hopefully have some free space in the buffer.
4668
offs = (int) (dmap->user_counter % dmap->bytes_in_use);
4670
l2 = dmap->bytes_in_use - offs;
4673
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4679
oss_timing_printf ("Got output buffer, offs %d/%d, len %d", offs,
4680
dmap->bytes_in_use, len);
4682
if (offs < 0 || (offs + len) > dmap->bytes_in_use)
4684
cmn_err (CE_WARN, "Bad audio output buffer %d/%d\n", offs, len);
4692
launch_output (adev_p adev, dmap_p dmap)
4694
oss_native_word flags;
4697
oss_do_timing ("Launch output called");
4699
if (dmap->flags & DMAP_STARTED)
4704
if (dmap->user_counter == 0 && dmap->audio_callback == NULL
4705
&& dmap->mapping_flags == 0)
4710
if (!(dmap->flags & DMAP_PREPARED))
4712
cmn_err (CE_WARN, "launch_output while not prepared. Engine=%d\n", adev->engine_num);
4717
oss_do_timing ("Launch_output calling output_block");
4720
if (adev->d->adrv_output_block != NULL)
4722
if (adev->flags & ADEV_AUTOMODE)
4723
adev->d->adrv_output_block (adev->engine_num, dmap->dmabuf_phys,
4724
dmap->bytes_in_use, dmap->fragment_size,
4727
adev->d->adrv_output_block (adev->engine_num, dmap->dmabuf_phys,
4728
dmap->fragment_size, dmap->fragment_size,
4733
oss_do_timing ("Launch_output calling trigger");
4735
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4736
dmap->flags |= DMAP_STARTED;
4737
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4738
if (adev->d->adrv_trigger
4739
&& ((adev->enable_bits * adev->go) & PCM_ENABLE_OUTPUT))
4741
adev->d->adrv_trigger (adev->engine_num, adev->enable_bits * adev->go);
4748
move_wrpointer (adev_p adev, dmap_p dmap, int len)
4751
oss_native_word flags;
4753
oss_timing_printf ("Move wrpointer, len %d", len);
4755
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4756
dmap->underrun_flag = 0;
4758
dmap->user_counter += len;
4760
oss_timing_printf (" User=%lld", dmap->user_counter);
4761
oss_timing_printf (" Byte=%lld", dmap->byte_counter);
4762
oss_timing_printf (" Fill=%lld", dmap->user_counter - dmap->byte_counter);
4766
ossd_event (adev->engine_num, OSSD_EV_UPDATE_OUTPUT);
4769
if (ret < 0 || dmap->flags & DMAP_STARTED)
4771
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4775
if (!(adev->enable_bits & PCM_ENABLE_OUTPUT))
4778
oss_do_timing ("Output not triggered - skipping launch_output");
4780
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4784
if ((dmap->user_counter < dmap->fragment_size * 2)
4785
&& (dmap->user_counter < dmap->bytes_in_use / 2))
4788
oss_timing_printf ("dmap->user_counter=%lld, dmap->fragment_size*2=%ld",
4789
dmap->user_counter, dmap->fragment_size * 2);
4791
("Not enough data in the buffer yet - skipping launch_output");
4793
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4796
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4797
ret = launch_output (adev, dmap);
4803
store_tmp_data (adev_p adev, dmap_p dmap, unsigned char *buf, int count)
4805
dmap->leftover_buf = buf;
4806
dmap->leftover_bytes = count;
4810
copy_write_noninterleaved(adev_t *adev, dmap_t *dmap, int dma_offs, unsigned char *localbuf, int local_offs, int l)
4813
* Copy interleaved N channel data to non-interleaved device buffer.
4815
// TODO: This function assumes 32 bit audio DATA
4817
int ch, i, nc = adev->hw_parms.channels;
4818
int *inbuf, *outbuf;
4820
l /= sizeof(*inbuf)*nc;
4821
dma_offs /= sizeof(*inbuf);
4822
local_offs /= sizeof(*inbuf);
4824
for (ch=0;ch<nc;ch++)
4826
inbuf = (int*)(localbuf+local_offs);
4829
outbuf = (int *)(dmap->dmabuf + dmap->buffsize*ch / nc);
4830
outbuf += dma_offs / nc;
4842
write_copy (adev_p adev, dmap_p dmap, unsigned char *buf, int count)
4844
int err, offs, spc, l, p = 0;
4850
if ((offs = find_output_space (adev, dmap, &spc, l)) < 0)
4852
if (offs == OSS_EAGAIN)
4854
store_tmp_data (adev, dmap, buf + p, count);
4855
launch_output (adev, dmap);
4864
VMEM_CHECK (&dmap->dmabuf[offs], l);
4865
VMEM_CHECK (buf + p, l);
4867
if ((adev->flags & ADEV_NONINTERLEAVED) && adev->hw_parms.channels > 1)
4869
copy_write_noninterleaved(adev, dmap, offs, buf + p, 0, l);
4872
memcpy (&dmap->dmabuf[offs], buf + p, l);
4874
if ((err = move_wrpointer (adev, dmap, l)) < 0)
4884
oss_audio_write (int dev, struct fileinfo *file, uio_t * buf, int count)
4887
oss_native_word flags;
4890
int l, c, spc, offs, p, err;
4894
oss_timing_printf ("--- audio_write(%d, %d) ---", dev, count);
4899
if (dev < 0 || dev >= num_audio_engines)
4902
adev = audio_engines[dev];
4905
if (adev->flags & ADEV_NOOUTPUT)
4907
dmap = adev->dmap_out;
4909
if (!(adev->open_mode & OPEN_WRITE))
4912
UP_STATUS (STS_WRITE);
4914
if (dmap->dma_mode == PCM_ENABLE_INPUT)
4916
audio_reset_input (adev);
4923
oss_reset_wait_queue (adev->out_wq);
4927
if ((ISSET_FILE_FLAG (file, O_NONBLOCK)
4928
&& !(adev->open_flags & OF_BLOCK)) || adev->forced_nonblock)
4934
oss_do_timing ("*** NON BLOCKING WRITE ***");
4938
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4940
if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
4942
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4943
if ((ret = prepare_output (adev, dmap)) < 0)
4945
DOWN_STATUS (STS_WRITE);
4948
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4949
dmap->dma_mode = PCM_ENABLE_OUTPUT;
4952
if (!(dmap->flags & DMAP_PREPARED))
4953
{ /* Not prepared. Why??? */
4954
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4955
DOWN_STATUS (STS_WRITE);
4956
cmn_err (CE_WARN, "Internal error (not prepared)\n");
4960
if (dmap->leftover_bytes > 0)
4965
b = dmap->leftover_buf;
4966
l = dmap->leftover_bytes;
4967
dmap->leftover_bytes = 0;
4968
dmap->leftover_buf = NULL;
4970
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4971
if ((err = write_copy (adev, dmap, b, l)) < 0)
4973
DOWN_STATUS (STS_WRITE);
4977
dmap->leftover_bytes = 0;
4978
dmap->leftover_buf = NULL;
4979
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4982
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4986
DOWN_STATUS (STS_WRITE);
4998
oss_timing_printf ("%d/%d bytes to go", c, count);
5003
cmn_err (CE_WARN, "Internal timeout error A (%d/%d)\n", c, count);
5009
l &= ~7; /* Align it */
5011
if ((offs = find_output_space (adev, dmap, &spc, l)) < 0)
5013
if (offs == OSS_EINTR)
5015
DOWN_STATUS (STS_WRITE);
5016
if (c == count) /* Nothing written yet */
5020
if (offs == OSS_EAGAIN)
5022
DOWN_STATUS (STS_WRITE);
5023
if (c == count) /* Nothing written yet */
5029
DOWN_STATUS (STS_WRITE);
5033
if (dmap->convert_func == NULL)
5035
if (dmap->device_write != NULL)
5037
unsigned char *tmpbuf;
5040
if (dmap->tmpbuf1 == NULL)
5042
dmap->tmpbuf1 = AUDIO_MALLOC (dmap->osdev, TMP_CONVERT_BUF_SIZE+512);
5046
* Leave some room for data expansion so use just half of the available
5049
tmpbuf = dmap->tmpbuf1;
5052
if (l > TMP_CONVERT_BUF_SIZE / 2)
5053
l = TMP_CONVERT_BUF_SIZE / 2;
5056
if (uiomove (tmpbuf, l, UIO_WRITE, buf) != 0)
5059
"audio: uiomove(UIO_WRITE) failed (noconv)\n");
5060
DOWN_STATUS (STS_WRITE);
5064
dmap->device_write (adev, dmap, tmpbuf,
5065
&dmap->dmabuf[offs], spc, &l,
5068
DOWN_STATUS (STS_WRITE);
5071
if ((err = move_wrpointer (adev, dmap, l2)) < 0)
5073
DOWN_STATUS (STS_WRITE);
5081
if (uiomove (&dmap->dmabuf[offs], l, UIO_WRITE, buf) != 0)
5084
"audio: uiomove(UIO_WRITE) (noconv2) failed\n");
5087
if ((err = move_wrpointer (adev, dmap, l)) < 0)
5089
DOWN_STATUS (STS_WRITE);
5097
* Perform format conversions.
5099
unsigned char *p1 = dmap->tmpbuf1, *p2 = dmap->tmpbuf2;
5100
int l2, max, out_max;
5102
if (spc > TMP_CONVERT_MAX)
5103
spc = TMP_CONVERT_MAX / 2;
5105
if (dmap->expand_factor > UNIT_EXPAND)
5109
out_max = (spc * dmap->expand_factor) / UNIT_EXPAND; /* Output size */
5110
if (out_max > TMP_CONVERT_BUF_SIZE) /* Potential overflow */
5112
max = (TMP_CONVERT_BUF_SIZE * UNIT_EXPAND) / dmap->expand_factor;
5117
if (max < dmap->frame_size)
5118
max = dmap->frame_size;
5120
if (max > TMP_CONVERT_MAX)
5121
max = TMP_CONVERT_MAX / 2;
5125
/* Avoid leaving too short "tails" */
5129
/* Round to integer number of samples */
5131
(((l + dmap->frame_size -
5132
1) / dmap->frame_size)) * dmap->frame_size;
5139
if (uiomove (p1, l, UIO_WRITE, buf) != 0)
5140
cmn_err (CE_WARN, "audio: uiomove(UIO_WRITE) (conv) failed\n");
5141
UP_STATUS (STS_CONVERT);
5143
dmap->convert_func (adev, dmap, &p1, &l2,
5144
&p2, &adev->user_parms,
5145
&adev->hw_parms)) < 0)
5147
cmn_err (CE_WARN, "Format conversion failed (%d)\n", err);
5148
DOWN_STATUS (STS_WRITE | STS_CONVERT);
5151
DOWN_STATUS (STS_CONVERT);
5153
if ((err = write_copy (adev, dmap, p1, l2)) < 0)
5155
if (err != OSS_EAGAIN)
5157
DOWN_STATUS (STS_WRITE);
5161
/* Handle non blocking I/O */
5162
if (c == count) /* Nothing written yet */
5164
DOWN_STATUS (STS_WRITE);
5168
DOWN_STATUS (STS_WRITE);
5182
oss_do_timing ("--- Audio write done");
5184
DOWN_STATUS (STS_WRITE);
5188
#ifdef MANAGE_DEV_DSP
5191
oss_combine_write_lists (void)
5195
for (i = 0; i < dspoutlist2.ndevs; i++)
5196
dspoutlist.devices[dspoutlist.ndevs++] = dspoutlist2.devices[i];
5198
dspoutlist2.ndevs = 0;
5203
oss_open_vdsp (int dev, int dev_type, struct fileinfo *file, int recursive,
5204
int open_flags, int *newdev)
5207
int mode = file->mode & O_ACCMODE;
5209
DDB (cmn_err (CE_CONT, "oss_open_vdsp(%d, mode=%d)\n", dev, mode));
5220
/* default: Use the mode defined by O_ACCMODE */
5224
open_flags = get_open_flags (mode, open_flags, file);
5229
dev_type = OSS_DEV_DSP;
5232
case OSS_DEV_VAUDIO:
5233
dev_type = OSS_DEV_DEVAUDIO;
5237
cmn_err (CE_NOTE, "Unknown dev class %d\n", dev_type);
5241
if (audio_devfiles == NULL)
5243
cmn_err (CE_NOTE, "No audio device files available\n");
5246
#ifdef MANAGE_DEV_DSP
5248
oss_combine_write_lists ();
5252
#ifdef APPLIST_SUPPORT
5255
appname = GET_PROCESS_NAME (file);
5256
if (open_flags & OF_DEVAUDIO)
5257
appname = "Devaudio_Support";
5259
if ((dev = app_lookup (mode, appname, &open_flags)) >= 0)
5260
if (audio_devfiles[dev]->enabled && !audio_devfiles[dev]->unloaded)
5262
oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5267
(CE_CONT, "Using dsp%d configured for this application\n",
5273
DDB (cmn_err (CE_CONT, "\n"));
5274
DDB (cmn_err (CE_CONT, "Out devs: "));
5275
for (i = 0; i < dspoutlist.ndevs; i++)
5276
DDB (cmn_err (CE_CONT, "%d ", dspoutlist.devices[i]));
5277
for (i = 0; i < dspoutlist2.ndevs; i++)
5278
DDB (cmn_err (CE_CONT, "(%d) ", dspoutlist2.devices[i]));
5279
DDB (cmn_err (CE_CONT, "\n"));
5280
DDB (cmn_err (CE_CONT, "In devs: "));
5281
for (i = 0; i < dspinlist.ndevs; i++)
5282
DDB (cmn_err (CE_CONT, "%d ", dspinlist.devices[i]));
5283
DDB (cmn_err (CE_CONT, "\n"));
5284
DDB (cmn_err (CE_CONT, "In/out devs: "));
5285
for (i = 0; i < dspinoutlist.ndevs; i++)
5286
DDB (cmn_err (CE_CONT, "%d ", dspinoutlist.devices[i]));
5287
DDB (cmn_err (CE_CONT, "\n"));
5289
switch (mode & (OPEN_READ | OPEN_WRITE))
5292
DDB (cmn_err (CE_CONT, "Selecting output device: "));
5294
for (i = 0; i < dspoutlist.ndevs; i++)
5296
dev = dspoutlist.devices[i];
5297
if (!audio_devfiles[dev]->enabled || audio_devfiles[dev]->unloaded)
5303
DDB (cmn_err (CE_CONT, "%d ", dev));
5305
oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5309
DDB (cmn_err (CE_CONT, "->%d ", dev));
5317
DDB (cmn_err (CE_CONT, "Selecting input device: "));
5318
for (i = 0; i < dspinlist.ndevs; i++)
5320
dev = dspinlist.devices[i];
5321
if (!audio_devfiles[dev]->enabled || audio_devfiles[dev]->unloaded)
5326
DDB (cmn_err (CE_CONT, "%d ", dev));
5328
oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5332
DDB (cmn_err (CE_CONT, "->%d ", dev));
5340
case OPEN_WRITE | OPEN_READ:
5341
DDB (cmn_err (CE_CONT, "Selecting input/output device: "));
5342
for (i = 0; i < dspinoutlist.ndevs; i++)
5344
dev = dspinoutlist.devices[i];
5345
if (!audio_devfiles[dev]->enabled || audio_devfiles[dev]->unloaded)
5350
DDB (cmn_err (CE_CONT, "%d ", dev));
5352
oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5356
DDB (cmn_err (CE_CONT, "->%d ", dev));
5364
DDB (cmn_err (CE_CONT, " - got vdsp -> %d\n", dev));
5370
* Try to find which minor number matches this /dev/dsp# device. Note that the actual
5371
* device type doesn't matter after this point so we can use OSS_DEV_DSP.
5373
if ((d = oss_find_minor (OSS_DEV_DSP_ENGINE, dev)) < 0)
5375
oss_audio_release (dev, file);
5386
audio_init_device (int dev)
5390
sync_seed = GET_JIFFIES ();
5391
adev = audio_engines[dev];
5393
MUTEX_INIT (adev->master_osdev, adev->mutex, MH_FRAMEW);
5395
if (audio_engines[dev]->dmap_out == NULL
5396
|| audio_engines[dev]->dmap_in == NULL)
5400
dmap = AUDIO_MALLOC (adev->osdev, sizeof (dmap_t));
5403
cmn_err (CE_WARN, "Failed to allocate dmap, dev=%d\n", dev);
5407
memset ((char *) dmap, 0, sizeof (dmap_t));
5409
if (!(adev->flags & ADEV_NOOUTPUT) && adev->out_wq == NULL)
5412
oss_create_wait_queue (adev->osdev, "audio_out")) == NULL)
5414
cmn_err (CE_WARN, "Cannot create audio output wait queue\n");
5419
if (!(adev->flags & ADEV_NOINPUT) && adev->in_wq == NULL)
5422
oss_create_wait_queue (adev->osdev, "audio_in")) == NULL)
5424
cmn_err (CE_WARN, "Cannot create audio input wait queue\n");
5429
memset ((char *) dmap, 0, sizeof (dmap_t));
5430
dmap->osdev = adev->osdev;
5432
dmap->master_osdev = adev->master_osdev;
5433
MUTEX_INIT (dmap->master_osdev, dmap->mutex, MH_FRAMEW + 1);
5434
adev->dmap_out = adev->dmap_in = dmap;
5436
if (adev->flags & ADEV_DUPLEX)
5439
dmap = AUDIO_MALLOC (adev->osdev, sizeof (dmap_t));
5442
cmn_err (CE_WARN, "Failed to allocate dmap, dev=%d\n", dev);
5446
memset ((char *) dmap, 0, sizeof (dmap_t));
5447
dmap->osdev = adev->osdev;
5449
dmap->master_osdev = adev->master_osdev;
5450
MUTEX_INIT (dmap->master_osdev, dmap->mutex, MH_FRAMEW + 1);
5451
adev->dmap_in = dmap;
5459
audio_uninit_device (int dev)
5462
/* oss_native_word flags; */
5464
adev = audio_engines[dev];
5469
if (adev->dmap_out != NULL && adev->dmap_out->dmabuf != NULL)
5471
if (adev->d->adrv_free_buffer != NULL)
5473
adev->d->adrv_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
5476
default_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
5477
adev->dmap_out->dmabuf = NULL;
5480
if (adev->dmap_in != NULL
5481
&& (adev->dmap_in != adev->dmap_out && adev->dmap_in->dmabuf != NULL))
5483
if (adev->d->adrv_free_buffer != NULL)
5485
adev->d->adrv_free_buffer (dev, adev->dmap_in, OPEN_READ);
5488
default_free_buffer (dev, adev->dmap_in, OPEN_READ);
5489
adev->dmap_in->dmabuf = NULL;
5492
if (adev->in_wq != NULL)
5494
oss_remove_wait_queue (adev->in_wq);
5497
if (adev->out_wq != NULL)
5499
oss_remove_wait_queue (adev->out_wq);
5500
adev->out_wq = NULL;
5503
#ifdef CONFIG_OSS_VMIX
5504
if (adev->vmix_mixer != NULL)
5506
adev->vmix_mixer = NULL;
5510
MUTEX_CLEANUP (adev->mutex);
5512
if (adev->dmap_out != NULL)
5513
MUTEX_CLEANUP (adev->dmap_out->mutex);
5515
if (adev->flags & ADEV_DUPLEX && adev->dmap_in != NULL
5516
&& adev->dmap_out != adev->dmap_in)
5518
MUTEX_CLEANUP (adev->dmap_in->mutex);
5524
oss_audio_init (oss_device_t *osdev)
5526
MUTEX_INIT (osdev, audio_global_mutex, MH_DRV);
5530
oss_audio_uninit (void)
5533
* Release all memory/resources allocated by the audio core.
5535
oss_memblk_unalloc(&audio_global_memblk);
5537
MUTEX_CLEANUP (audio_global_mutex);
5541
oss_audio_inc_byte_counter (dmap_t * dmap, int increment)
5543
oss_uint64_t p1, p2;
5544
oss_native_word flags;
5546
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5547
p1 = dmap->byte_counter / dmap->fragment_size;
5548
dmap->byte_counter += increment;
5549
p2 = dmap->byte_counter / dmap->fragment_size;
5551
dmap->interrupt_count += (int) (p2 - p1);
5552
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5556
do_inputintr (int dev, int intr_flags)
5561
oss_native_word flags;
5563
adev = audio_engines[dev];
5564
dmap = adev->dmap_in;
5566
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5568
if (!(intr_flags & AINTR_NO_POINTER_UPDATES))
5570
dmap->byte_counter += dmap->fragment_size;
5571
dmap->interrupt_count++;
5574
while (dmap->byte_counter > dmap->user_counter &&
5575
(int) (dmap->byte_counter - dmap->user_counter) > dmap->bytes_in_use)
5577
dmap->user_counter += dmap->fragment_size;
5578
dmap->rec_overruns++;
5580
dmap->fragment_counter = (dmap->fragment_counter + 1) % dmap->nfrags;
5582
if (dmap->dmabuf_dma_handle != NULL) /* Some drivers don't use DMA */
5583
OSS_DMA_SYNC(dmap->dmabuf_dma_handle, 0, dmap->bytes_in_use, OSS_DMA_SYNC_INBOUND);
5586
oss_do_timing ("Wake up (in)");
5588
oss_wakeup (adev->in_wq, &dmap->mutex, &flags, POLLIN | POLLRDNORM);
5590
if (adev->flags & ADEV_AUTOMODE)
5595
cptr = dmap_get_qtail (dmap) * dmap->fragment_size;
5596
if (adev->d->adrv_start_input != NULL)
5597
adev->d->adrv_start_input (adev->engine_num, dmap->dmabuf_phys + cptr,
5598
dmap->fragment_size, dmap->fragment_size, 1);
5600
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5602
if (dmap->audio_callback != NULL)
5603
dmap->audio_callback (adev->engine_num, dmap->callback_parm);
5607
audio_inputintr (int dev, int intr_flags)
5614
if (dev < 0 || dev >= num_audio_engines)
5617
adev = audio_engines[dev];
5618
dmap = adev->dmap_in;
5620
if (dmap->dma_mode != PCM_ENABLE_INPUT)
5625
if (!(dmap->flags & DMAP_STARTED))
5630
oss_timing_printf ("Inputintr(%d)", dev);
5633
if (adev->d->adrv_get_input_pointer == NULL
5634
|| (intr_flags & AINTR_NO_POINTER_UPDATES))
5636
do_inputintr (dev, intr_flags);
5641
adev->d->adrv_get_input_pointer (adev->engine_num, dmap,
5642
PCM_ENABLE_INPUT) / dmap->fragment_size;
5645
while (dmap_get_qtail (dmap) != pos && n++ < dmap->nfrags)
5647
do_inputintr (dev, intr_flags);
5652
finish_output_interrupt (adev_p adev, dmap_p dmap)
5654
if (dmap->dmabuf_dma_handle != NULL) /* Some drivers don't use DMA */
5655
OSS_DMA_SYNC(dmap->dmabuf_dma_handle, 0, dmap->bytes_in_use, OSS_DMA_SYNC_OUTBOUND);
5658
ossd_event (adev->engine_num, OSSD_EV_UPDATE_OUTPUT);
5660
if (dmap->audio_callback != NULL)
5662
dmap->audio_callback (adev->engine_num, dmap->callback_parm);
5667
do_outputintr (int dev, int intr_flags)
5672
oss_native_word flags;
5674
adev = audio_engines[dev];
5675
dmap = adev->dmap_out;
5677
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5679
if (dmap->dmabuf == NULL)
5681
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5682
cmn_err (CE_WARN, "Output interrupt when no buffer is allocated\n");
5686
if (!(intr_flags & AINTR_NO_POINTER_UPDATES))
5688
dmap->byte_counter += dmap->fragment_size;
5689
dmap->interrupt_count++;
5692
dmap->fragment_counter = (dmap->fragment_counter + 1) % dmap->nfrags;
5694
if (dmap->user_counter <= dmap->byte_counter) /* Underrun */
5696
if (!(dmap->mapping_flags & DMA_MAP_MAPPED))
5699
oss_timing_printf ("adev %d: Play underrun A", dev);
5700
oss_timing_printf (" User=%lld", dmap->user_counter);
5701
oss_timing_printf (" Dev=%lld", dmap->byte_counter);
5702
oss_timing_printf (" Tmp=%d", dmap->tmpbuf_ptr);
5704
dmap->play_underruns++;
5706
if (!dmap->underrun_flag)
5709
oss_do_timing ("Clearing the buffer");
5711
memset (dmap->dmabuf, dmap->neutral_byte, dmap->buffsize);
5713
dmap->underrun_flag = 1;
5715
dmap->user_counter = dmap->byte_counter + dmap->fragment_size;
5720
if (audio_space_in_queue (adev, dmap, 0) >= 0 || adev->nonblock)
5723
oss_do_timing ("Wake up (out)");
5725
oss_wakeup (adev->out_wq, &dmap->mutex, &flags, POLLOUT | POLLWRNORM);
5728
if (adev->flags & ADEV_AUTOMODE)
5730
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5731
finish_output_interrupt (adev, dmap);
5735
cptr = dmap_get_qhead (dmap) * dmap->fragment_size;
5736
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5737
if (adev->d->adrv_output_block != NULL)
5739
adev->d->adrv_output_block (adev->engine_num, dmap->dmabuf_phys + cptr,
5740
dmap->fragment_size, dmap->fragment_size,
5743
finish_output_interrupt (adev, dmap);
5747
audio_outputintr (int dev, int intr_flags)
5754
if (dev < 0 || dev >= num_audio_engines)
5757
adev = audio_engines[dev];
5758
dmap = adev->dmap_out;
5760
if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
5765
if (!(dmap->flags & DMAP_STARTED))
5771
oss_timing_printf ("Outputintr(%d)", dev);
5773
UP_STATUS (STS_INTR);
5775
if (adev->d->adrv_get_output_pointer == NULL
5776
|| (intr_flags & AINTR_NO_POINTER_UPDATES))
5778
UP_STATUS (STS_DOINTR);
5779
do_outputintr (dev, intr_flags);
5780
DOWN_STATUS (STS_DOINTR | STS_INTR);
5784
pos = get_output_pointer (adev, dmap, 0) / dmap->fragment_size;
5787
while (dmap_get_qhead (dmap) != pos && n++ < dmap->nfrags)
5789
UP_STATUS (STS_DOINTR);
5790
do_outputintr (dev, intr_flags);
5791
DOWN_STATUS (STS_DOINTR);
5793
DOWN_STATUS (STS_INTR);
5797
oss_audio_reset (int dev)
5800
if (dev < 0 || dev >= num_audio_engines)
5802
adev = audio_engines[dev];
5804
audio_reset_adev (adev);
5806
if (adev->dmask & DMASK_OUT)
5807
reset_dmap (adev->dmap_out);
5808
if (adev->dmask & DMASK_IN)
5809
reset_dmap (adev->dmap_in);
5813
oss_audio_start_syncgroup (unsigned int syncgroup)
5816
* This routine is to be called by the /dev/midi driver to start a sync group
5817
* at the right time.
5819
oss_native_word flags;
5821
MUTEX_ENTER_IRQDISABLE (audio_global_mutex, flags);
5822
handle_syncstart (syncgroup & SYNC_DEVICE_MASK, syncgroup);
5823
MUTEX_EXIT_IRQRESTORE (audio_global_mutex, flags);
5829
chpoll_output (int dev, struct fileinfo *file, oss_poll_event_t * ev)
5831
short events = ev->events;
5834
oss_native_word flags;
5839
oss_timing_printf ("--- audio_chpoll_output(%d, %08x) ---", dev, events);
5842
if (dev < 0 || dev >= num_audio_engines)
5844
adev = audio_engines[dev];
5846
dmap = adev->dmap_out;
5847
if (dmap->mapping_flags & DMA_MAP_MAPPED)
5851
* It might actually be better to permit pollling in mmapped
5852
* mode rather than returning an error.
5854
if (dmap->interrupt_count > 0)
5855
ev->revents |= (POLLOUT | POLLWRNORM) & events;
5858
oss_audio_set_error (adev->engine_num, E_PLAY,
5860
"select/poll called for an OSS device in mmap mode."),
5864
* The select() and poll() system calls are not defined for OSS devices
5865
* when the device is in mmap mode.
5871
if (dmap->dma_mode == PCM_ENABLE_INPUT)
5873
oss_audio_set_error (adev->engine_num, E_PLAY,
5875
"select/poll called for wrong direction."),
5878
* Errordesc: The application has opened the device in read-only
5879
* mode but it tried to use select/poll to check if the device is
5880
* ready for write. This is pointless because that will never
5886
get_ospace (audio_engines[dev], dmap, (ioctl_arg) & bi);
5887
limit = bi.fragsize * bi.fragstotal / 4;
5888
if (dmap->low_water > limit)
5889
dmap->low_water = limit;
5890
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5891
if (bi.bytes < dmap->low_water)
5892
{ /* No space yet */
5894
oss_do_timing ("Output not ready yet");
5896
oss_register_poll (adev->out_wq, &dmap->mutex, &flags, ev);
5901
oss_do_timing ("Reporting output ready");
5903
ev->revents |= (POLLOUT | POLLWRNORM) & events;
5905
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5912
chpoll_input (int dev, struct fileinfo *file, oss_poll_event_t * ev)
5914
short events = ev->events;
5917
oss_native_word flags;
5922
oss_timing_printf ("--- audio_chpoll_input(%d, %08x) ---", dev, events);
5925
if (dev < 0 || dev >= num_audio_engines)
5927
adev = audio_engines[dev];
5929
dmap = adev->dmap_in;
5930
if (dmap->mapping_flags & DMA_MAP_MAPPED)
5934
* It might actually be better to permit pollling in mmapped
5935
* mode rather than returning an error.
5937
if (dmap->interrupt_count > 0)
5938
ev->revents |= (POLLOUT | POLLWRNORM) & events;
5941
oss_audio_set_error (adev->engine_num, E_REC,
5943
"select/poll called for an OSS device in mmap mode."),
5947
* The select() and poll() system calls are not defined for OSS devices
5948
* when the device is in mmap mode.
5954
if (dmap->dma_mode != PCM_ENABLE_INPUT)
5956
oss_audio_set_error (adev->engine_num, E_REC,
5958
"select/poll called for wrong direction."),
5961
* Errordesc: The application has opened the device in write-only
5962
* mode but it tried to use select/poll to check if the device has any
5963
* data available to read. This is pointless because that will never
5969
if (!(dmap->flags & DMAP_STARTED))
5971
oss_audio_set_error (adev->engine_num, E_REC,
5973
"select/poll called before recording is started."),
5977
* The application should start recording (using SNDCTL_DSP_SETTRIGGER)
5978
* before calling select/poll to wait for recorded data. If recording is
5979
* not active then recorded data will never arrive and the application
5980
* will just sit and wait without doing anything.
5984
get_ispace (audio_engines[dev], dmap, (ioctl_arg) & bi);
5985
limit = bi.fragsize * bi.fragstotal / 4;
5986
if (dmap->low_water > limit)
5987
dmap->low_water = limit;
5988
MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5989
if (bi.bytes < dmap->low_water)
5990
{ /* No space yet */
5992
oss_timing_printf ("Input not ready yet (%d/%d)\n", bi.bytes,
5995
oss_register_poll (adev->in_wq, &dmap->mutex, &flags, ev);
6000
oss_do_timing ("Reporting input ready");
6002
ev->revents |= (POLLIN | POLLRDNORM) & events;
6004
MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
6011
oss_audio_chpoll (int dev, struct fileinfo *file, oss_poll_event_t * ev)
6013
short events = ev->events;
6017
oss_timing_printf ("--- audio_chpoll(%d, %08x) ---", dev, events);
6020
if (dev < 0 || dev >= num_audio_engines)
6022
adev = audio_engines[dev];
6024
if ((events & (POLLOUT | POLLWRNORM)) && (adev->open_mode & OPEN_WRITE))
6028
if ((err=chpoll_output (dev, file, ev))<0)
6032
if ((events & (POLLIN | POLLRDNORM)) && (adev->open_mode & OPEN_READ))
6036
if ((err=chpoll_input (dev, file, ev))<0)
6046
dummy_inputintr (int dev, int intr_flags)
6048
/* Dummy input interrupt handler */
6053
dummy_outputintr (int dev, int x)
6055
/* Dummy output interrupt handler */
6058
static oss_cdev_drv_t audio_cdev_drv = {
6060
oss_audio_open_devfile,
6062
oss_audio_open_engine,
6075
#ifdef MANAGE_DEV_DSP
6077
static oss_cdev_drv_t vdsp_cdev_drv = {
6092
static oss_cdev_drv_t audio_engine_cdev_drv = {
6093
oss_audio_open_engine,
6106
oss_audio_register_client (oss_audio_startup_func func, void *devc,
6107
oss_device_t * osdev)
6110
* Register a callback for a driver that wants to be initialized after a new audio device
6114
if (num_audio_startups >= MAX_STARTUPS)
6117
audio_startups[num_audio_startups].func = func;
6118
audio_startups[num_audio_startups].devc = devc;
6119
audio_startups[num_audio_startups].osdev = osdev;
6120
num_audio_startups++;
6124
oss_add_audio_devlist (int list_id, int devfile)
6128
* Device list support is not in use at this moment
6130
oss_devlist_t *list;
6143
case OPEN_READ | OPEN_WRITE:
6144
list = &dspinoutlist;
6148
cmn_err (CE_CONT, "Bad device list ID %d\n", list_id);
6152
for (i = 0; i < list->ndevs; i++)
6153
if (list->devices[i] == devfile) /* Already there */
6157
* Add the device to the list
6159
list->devices[list->ndevs++] = devfile;
6165
add_to_devlists (adev_p adev)
6168
* Add the device to the default input, output and/or input/output lists
6172
if (!(adev->flags & ADEV_SPECIAL))
6174
if (!(adev->flags & ADEV_NOOUTPUT))
6175
{ /* Output capable */
6177
if (adev->flags & ADEV_VIRTUAL)
6179
int n = dspoutlist.ndevs++;
6181
if (adev->flags & ADEV_DEFAULT)
6185
for (i = n; i > 0; i--)
6186
dspoutlist.devices[i] = dspoutlist.devices[i - 1];
6187
dspoutlist.devices[0] = adev->audio_devfile;
6190
dspoutlist.devices[n] = adev->audio_devfile;
6194
/* Put non-virtual devices to a secondary list */
6195
int n = dspoutlist2.ndevs++;
6196
dspoutlist2.devices[n] = adev->audio_devfile;
6201
if (!(adev->flags & (ADEV_NOINPUT)))
6202
{ /* Input capable */
6204
int n = dspinlist.ndevs++;
6206
if (adev->flags & ADEV_DEFAULT)
6210
for (i = n; i > 0; i--)
6211
dspinlist.devices[i] = dspinlist.devices[i - 1];
6212
dspinlist.devices[0] = adev->audio_devfile;
6215
dspinlist.devices[n] = adev->audio_devfile;
6218
if (!(adev->flags & (ADEV_NOINPUT | ADEV_NOOUTPUT))
6219
|| (adev->flags & ADEV_DUPLEX))
6220
{ /* Input/output capable */
6222
int n = dspinoutlist.ndevs++;
6224
if (adev->flags & ADEV_DEFAULT)
6228
for (i = n; i > 0; i--)
6229
dspinoutlist.devices[i] = dspinoutlist.devices[i - 1];
6230
dspinoutlist.devices[0] = adev->audio_devfile;
6233
dspinoutlist.devices[n] = adev->audio_devfile;
6240
resize_array(oss_device_t *osdev, adev_t ***arr, int *size, int increment)
6242
adev_t **old=*arr, **new = *arr;
6243
int old_size = *size;
6244
int new_size = *size;
6246
if (new_size >= HARD_MAX_AUDIO_DEVFILES) /* Too many device files */
6249
new_size += increment;
6250
if (new_size > HARD_MAX_AUDIO_DEVFILES)
6251
new_size = HARD_MAX_AUDIO_DEVFILES;
6253
if ((new=AUDIO_MALLOC(osdev, new_size * sizeof (adev_t *)))==NULL)
6256
memset(new, 0, new_size * sizeof(adev_t *));
6258
memcpy(new, old, old_size * sizeof(adev_t *));
6264
AUDIO_FREE(osdev, old);
6270
oss_install_audiodev_with_devname (int vers,
6271
oss_device_t * osdev,
6272
oss_device_t * master_osdev,
6274
const audiodrv_t * driver,
6277
unsigned int format_mask, void *devc, int parent,
6278
const char * devfile_name)
6282
int i, num = -1, hidden_device = 0;
6283
int update_devlists = 0;
6284
int reinsterted_device = 0;
6285
int chdev_flags = 0;
6286
int devfile_num = 0;
6290
cmn_err(CE_WARN, "devc==NULL for %s. Cannot install audio device\n", name);
6295
cmn_err (CE_CONT, "Name is really NULL\n");
6296
if (master_osdev == NULL)
6297
master_osdev = osdev;
6300
if (flags & (ADEV_SHADOW | ADEV_HIDDEN))
6303
flags &= ~ADEV_HIDDEN;
6307
if (audio_engines == NULL)
6309
audio_engines = AUDIO_MALLOC (NULL, sizeof (adev_t *) * MAX_AUDIO_ENGINES);
6310
memset (audio_engines, 0, sizeof (adev_t *) * MAX_AUDIO_ENGINES);
6313
if (audio_devfiles == NULL)
6315
audio_devfiles = AUDIO_MALLOC (NULL, sizeof (adev_t *) * MAX_AUDIO_DEVFILES);
6316
memset (audio_devfiles, 0, sizeof (adev_t *) * MAX_AUDIO_DEVFILES);
6319
if (vers != OSS_AUDIO_DRIVER_VERSION)
6321
cmn_err (CE_WARN, "Incompatible audio driver for %s\n", name);
6325
if (driver_size > sizeof (audiodrv_t))
6326
driver_size = sizeof (audiodrv_t);
6328
* Try to figure out if this device has earlier been installed. Sometimes it may happen that
6329
* the low level driver gets unloaded while the osscore module still
6330
* remains loaded. Try to re-use the same audio device number if possible.
6335
for (i = 0; i < num_audio_engines; i++)
6338
if ((audio_engines[i]->flags & (ADEV_SHADOW|ADEV_HIDDEN)) !=
6339
(flags & (ADEV_SHADOW|ADEV_HIDDEN))) /* Different visibility */
6342
if (audio_engines[i]->unloaded
6343
&& audio_engines[i]->os_id == oss_get_osid (osdev))
6345
/* This audio device was previously connected to the same physical device */
6348
reinsterted_device = 1;
6350
(CE_NOTE, "Audio device %d got re-installed again.\n", i));
6358
if (num_audio_engines >= MAX_AUDIO_ENGINES)
6360
if (!resize_array(osdev, &audio_engines, &oss_max_audio_engines, AUDIO_ENGINE_INCREMENT))
6362
cmn_err (CE_CONT, "Cannot grow audio_engines[]\n");
6367
d = AUDIO_MALLOC (osdev, sizeof (audiodrv_t));
6368
op = AUDIO_MALLOC (osdev, sizeof (adev_t));
6369
memset ((char *) op, 0, sizeof (adev_t));
6370
if (driver_size < sizeof (audiodrv_t))
6371
memset ((char *) d, 0, sizeof (audiodrv_t));
6372
memcpy ((char *) d, (char *) driver, driver_size);
6373
num = num_audio_engines;
6374
audio_engines[num] = op;
6375
num_audio_engines++;
6377
update_devlists = 1;
6379
sprintf (op->handle, "%s-au%02d", osdev->handle,
6380
osdev->num_audio_engines + 1);
6381
op->port_number = osdev->num_audio_engines;
6385
op = audio_engines[num];
6386
d = audio_engines[num]->d;
6387
if (driver_size < sizeof (audiodrv_t))
6388
memset ((char *) d, 0, sizeof (audiodrv_t));
6389
memcpy ((char *) d, (char *) driver, driver_size);
6390
update_devlists = 0;
6393
if (d == NULL || op == NULL)
6395
cmn_err (CE_WARN, "Can't allocate driver for %s (adev=%p, d=%p)\n",
6400
if (d->adrv_get_input_pointer == NULL)
6401
d->adrv_get_input_pointer = d->adrv_get_buffer_pointer;
6402
if (d->adrv_get_output_pointer == NULL)
6403
d->adrv_get_output_pointer = d->adrv_get_buffer_pointer;
6406
op->os_id = oss_get_osid (osdev);
6408
op->outputintr = dummy_outputintr;
6409
op->inputintr = dummy_inputintr;
6410
op->vmix_mixer = NULL;
6412
strncpy (op->name, name, sizeof (op->name));
6413
op->name[sizeof (op->name) - 1] = 0;
6417
op->latency = -1; /* Unknown */
6419
op->oformat_mask = format_mask;
6420
op->iformat_mask = format_mask;
6422
op->min_channels = 1;
6423
op->max_channels = 2;
6424
op->min_rate = 8000;
6425
op->max_rate = 44100;
6427
op->parent_dev = parent + 1;
6429
op->dmap_out = NULL;
6430
memset (op->cmd, 0, sizeof (op->cmd));
6433
op->master_osdev = master_osdev;
6434
op->card_number = osdev->cardnum;
6435
op->engine_num = op->rate_source = num;
6437
op->redirect_in = -1;
6438
op->redirect_out = -1;
6439
op->dmabuf_alloc_flags = 0;
6440
op->dmabuf_maxaddr = MEMLIMIT_32BITS;
6442
audio_engines[num] = op;
6443
op->next_out = NULL;
6446
op->song_name[0] = 0;
6450
if ((flags & ADEV_SHADOW) && num > 0)
6452
adev_p prev = audio_engines[num - 1]; /* Previous device */
6454
prev->next_out = op;
6458
if (audio_init_device (num) < 0)
6462
* Create the device node.
6464
#ifndef VDEV_SUPPORT
6465
flat_device_model = 1;
6469
if (reinsterted_device)
6472
* A hotpluggable device has been reinserted in the system.
6473
* Update the internal tables and re-create the device file entry.
6474
* However don't create new audio engine and device file numbers.
6476
devfile_num = op->audio_devfile;
6477
chdev_flags |= CHDEV_REPLUG;
6483
if (num_audio_devfiles >= MAX_AUDIO_DEVFILES)
6485
if (!resize_array(osdev, &audio_devfiles, &oss_max_audio_devfiles, AUDIO_DEVFILE_INCREMENT))
6487
cmn_err (CE_CONT, "Cannot grow audio_devfiles[]\n");
6492
audio_devfiles[num_audio_devfiles] = op;
6493
devfile_num = num_audio_devfiles++;
6497
if (flat_device_model || !hidden_device)
6499
#ifdef NEW_DEVICE_NAMING
6503
if (*devfile_name != 0)
6506
* A name was suggested by the low level driver
6508
strcpy (tmpl, devfile_name);
6510
else if (flags & ADEV_NOOUTPUT)
6511
sprintf (tmpl, "pcmin%d", osdev->num_audiorec++);
6513
sprintf (tmpl, "pcm%d", osdev->num_audioduplex++);
6515
# ifdef USE_DEVICE_SUBDIRS
6516
sprintf (name, "oss/%s/%s", osdev->nick, tmpl);
6518
sprintf (name, "%s_%s", osdev->nick, tmpl);
6521
sprintf (name, "dsp%d", num);
6524
op->real_dev = devfile_num;
6525
op->audio_devfile = devfile_num;
6526
audio_devfiles[devfile_num] = op;
6527
sprintf (op->devnode, "/dev/%s", name);
6528
oss_install_chrdev (master_osdev, name, OSS_DEV_DSP, devfile_num,
6529
&audio_cdev_drv, chdev_flags);
6530
osdev->num_audio_engines++;
6539
if (devfile_num > 0 && (flags & ADEV_SHADOW))
6541
/* Use the device node of the parent device file */
6542
if (audio_devfiles[devfile_num - 1] != NULL)
6543
strcpy (op->devnode, audio_devfiles[devfile_num - 1]->devnode);
6545
strcpy (op->devnode, "Unknown");
6546
audio_devfiles[devfile_num] = op;
6550
strcpy (op->devnode, "HiddenAudioDevice");
6556
//#ifdef VDEV_SUPPORT
6557
oss_install_chrdev (osdev, NULL, OSS_DEV_DSP_ENGINE, num,
6558
&audio_engine_cdev_drv, chdev_flags);
6562
if (!reinsterted_device && update_devlists && !hidden_device)
6563
add_to_devlists (op);
6568
for (i = 0; i < num_audio_engines; i++)
6569
if (audio_engines[i] == NULL)
6570
cmn_err (CE_WARN, "Audio engines %d==NULL\n", i);
6571
for (i = 0; i < num_audio_devfiles; i++)
6572
if (audio_devfiles[i] == NULL)
6573
cmn_err (CE_WARN, "Audio devfiles %d==NULL\n", i);
6580
oss_install_audiodev (int vers,
6581
oss_device_t * osdev,
6582
oss_device_t * master_osdev,
6584
const audiodrv_t * driver,
6586
unsigned long long flags,
6587
unsigned int format_mask, void *devc, int parent)
6589
return oss_install_audiodev_with_devname (vers,
6596
format_mask, devc, parent,
6597
""); /* Use default device file naming */
6601
oss_audio_delayed_attach (void)
6606
* Serve possible other drivers waiting for new friends.
6608
for (i = 0; i < num_audio_startups; i++)
6610
if (audio_startups[i].osdev != NULL
6611
&& audio_startups[i].osdev->available)
6613
if (audio_startups[i].func (audio_startups[i].devc))
6614
audio_startups[i].osdev = NULL; /* Inactivate it */
6621
install_vdsp (oss_device_t * osdev)
6623
#ifdef MANAGE_DEV_DSP
6625
* Install the driver for /dev/dsp (the multiplexer device)
6627
* NOTE! Not used at this moment because /dev/dsp assignment is managed in user
6628
* space (by ossdevlinks).
6631
oss_install_chrdev (osdev, "dsp", OSS_DEV_VDSP, 0, &vdsp_cdev_drv,
6633
oss_install_chrdev (osdev, "dsp_in", OSS_DEV_VDSP, 1, &vdsp_cdev_drv,
6635
oss_install_chrdev (osdev, "dsp_out", OSS_DEV_VDSP, 2, &vdsp_cdev_drv,