~ubuntu-branches/ubuntu/vivid/oss4/vivid-proposed

« back to all changes in this revision

Viewing changes to .pc/kfreebsd-gnu.patch/kernel/framework/audio/oss_audio_core.c

  • Committer: Package Import Robot
  • Author(s): Sebastien NOEL
  • Date: 2012-11-19 11:47:24 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20121119114724-svu8mq7x3pk64nez
Tags: 4.2-build2007-1
* New upstream release.
* Acknowledge NMU, thanks Michael Gilbert.
* Add debian/patches/110_ld-as-needed.patch: Rearrange order of linker
  arguments to fix building with "ld --as-needed" (closes: #630737).
* Add missing dependency on dpkg-dev to oss4-dkms and oss4-source
  (closes: #687086).
* Fix typo in the changelog (closes: #628876, #675933)
* Add debian/patches/002_fix-linux-oss_native_word.patch (closes: #693657).
  Thanks to Ben Hutchings.
* Add debian/patches/003_linux-error-logging-fixes.patch (closes: #693657).
  Thanks to Ben Hutchings.
* check for /lib/modules/${kernelver}/build in addition of
  /lib/modules/${kernelver}/source (closes: #587191).
* oss4-dkms.dkms.in: fix 'CLEAN' rules (closes: #653374).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Purpose: Audio core functionality of OSS
3
 
 */
4
 
 
5
 
/*
6
 
 *
7
 
 * This file is part of Open Sound System.
8
 
 *
9
 
 * Copyright (C) 4Front Technologies 1996-2008.
10
 
 *
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.
14
 
 *
15
 
 */
16
 
 
17
 
#undef  NO_COOKED_MODE
18
 
#define AUDIO_C
19
 
 
20
 
#define GRC     3
21
 
 
22
 
/* Some debugging macros (for future use) */
23
 
#define UP_STATUS(x)
24
 
#define DOWN_STATUS(x)
25
 
 
26
 
#include <oss_config.h>
27
 
 
28
 
extern int src_quality;
29
 
extern int vmix_disabled;
30
 
extern int excl_policy;
31
 
 
32
 
oss_mutex_t audio_global_mutex;
33
 
 
34
 
/*
35
 
 * Resizeable audio device tables
36
 
 */
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)
44
 
 
45
 
/*
46
 
 * List of audio devices in the system
47
 
 */
48
 
adev_t **audio_engines = NULL;
49
 
int num_audio_engines = 0;
50
 
 
51
 
adev_t **audio_devfiles = NULL;
52
 
int num_audio_devfiles = 0;
53
 
extern int flat_device_model;
54
 
 
55
 
#if 0
56
 
/*
57
 
 * Device lists (input, output, duplex) for /dev/dsp.
58
 
 */
59
 
 
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 */
64
 
#endif
65
 
 
66
 
/*
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.
70
 
 */
71
 
typedef struct
72
 
{
73
 
  char *name;
74
 
  int open_flags;
75
 
} oss_specialapp_t;
76
 
 
77
 
oss_specialapp_t special_apps[] = {
78
 
  {"quake", OF_MMAP},
79
 
  {"quake2", OF_MMAP},
80
 
  {"q3demo.x86", OF_MMAP},
81
 
  {"wolfsp.x86", OF_MMAP},
82
 
  {"wolfmp.x86", OF_MMAP},
83
 
  {"quake3", OF_MMAP},
84
 
  {"wolf3d", OF_MMAP},
85
 
  {"rtcw", OF_MMAP},
86
 
  {"artsd", OF_BLOCK | OF_NOCONV},
87
 
  {"realplay.bin", OF_SMALLFRAGS},
88
 
  {"hxplay.bin", OF_SMALLFRAGS},
89
 
#if 1
90
 
  {"auserver", OF_NOCONV},      /* Win4lin */
91
 
#endif
92
 
  {"quake3.x86", OF_MMAP},
93
 
  {"wolf.x86", OF_MMAP},
94
 
  {"et.x86", OF_MMAP},
95
 
  {"doom.x86", OF_MMAP},
96
 
  // {"mozilla-bin", OF_MEDIUMBUF}, /* For the flash plugin */
97
 
  {NULL, 0}
98
 
};
99
 
 
100
 
#ifdef APPLIST_SUPPORT
101
 
/*
102
 
 * Lookup tables for applications. Use these lists to assign
103
 
 * fixed target devices for given applications.
104
 
 */
105
 
 
106
 
app_routing_t oss_applist[APPLIST_SIZE];
107
 
int oss_applist_size = 0;
108
 
 
109
 
static int
110
 
app_lookup (int mode, const char *appname, int *open_flags)
111
 
{
112
 
  int i, dev;
113
 
 
114
 
  if (appname == NULL)
115
 
    return -2;
116
 
 
117
 
  for (i = 0; i < oss_applist_size; i++)
118
 
    {
119
 
      if (oss_applist[i].mode == mode)
120
 
        if (strncmp (appname, oss_applist[i].name, 32) == 0)
121
 
          {
122
 
            dev = oss_applist[i].dev;
123
 
 
124
 
            if (dev < -1 || dev >= num_audio_devfiles)
125
 
              return -1;
126
 
            *open_flags |= oss_applist[i].open_flags;
127
 
            return dev;
128
 
          }
129
 
    }
130
 
 
131
 
  return -2;
132
 
}
133
 
#endif
134
 
 
135
 
/*ARGSUSED*/
136
 
static int
137
 
get_open_flags (int mode, int open_flags, struct fileinfo *file)
138
 
{
139
 
  char *name;
140
 
  int i;
141
 
 
142
 
  if ((name = GET_PROCESS_NAME (file)) != NULL)
143
 
    {
144
 
#ifdef APPLIST_SUPPORT
145
 
      if (app_lookup (mode, name, &open_flags) >= -1)
146
 
        return open_flags;
147
 
#endif
148
 
 
149
 
      for (i = 0; special_apps[i].name != NULL; i++)
150
 
        if (strcmp (special_apps[i].name, name) == 0)
151
 
          {
152
 
            open_flags |= special_apps[i].open_flags;
153
 
            return open_flags;
154
 
          }
155
 
    }
156
 
 
157
 
  return open_flags;
158
 
}
159
 
 
160
 
#define BIGWRITE_SIZE   1024
161
 
 
162
 
#define NEUTRAL8        0x80
163
 
#define NEUTRAL16       0x00
164
 
#define OSS_PLUGIN_VERSION              (0x100|oss_sample_bits)
165
 
 
166
 
int always_cooked = 0;
167
 
static unsigned long sync_seed = 0;
168
 
 
169
 
#define COOKED_BLOCK_SIZE 4096
170
 
 
171
 
extern oss_uint64_t oss_tmp_timer;
172
 
 
173
 
/*
174
 
 * Structure used by oss_audio_register_client()
175
 
 */
176
 
typedef struct
177
 
{
178
 
  oss_audio_startup_func func;
179
 
  void *devc;
180
 
  oss_device_t *osdev;
181
 
} audio_startup_t;
182
 
 
183
 
#define MAX_STARTUPS    5
184
 
static audio_startup_t audio_startups[MAX_STARTUPS];
185
 
static int num_audio_startups = 0;
186
 
 
187
 
int
188
 
dmap_get_qlen (dmap_p dmap)
189
 
{
190
 
  int len;
191
 
 
192
 
  if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
193
 
    {
194
 
      if (dmap->fragment_size == 0)
195
 
        {
196
 
          cmn_err (CE_WARN, "dmap (out) fragment_size=0, dev=%s\n",
197
 
                   dmap->adev->name);
198
 
          return 0;
199
 
        }
200
 
 
201
 
      len =
202
 
        (int) ((dmap->user_counter -
203
 
                dmap->byte_counter) / dmap->fragment_size);
204
 
      if (len < 0)
205
 
        len = 0;
206
 
      return len;
207
 
    }
208
 
 
209
 
  if (dmap->dma_mode == PCM_ENABLE_INPUT)
210
 
    {
211
 
      if (dmap->fragment_size == 0)
212
 
        {
213
 
          cmn_err (CE_WARN, "dmap (in) fragment_size=0, dev=%s\n",
214
 
                   dmap->adev->name);
215
 
          return 0;
216
 
        }
217
 
 
218
 
      len =
219
 
        (int) ((dmap->byte_counter -
220
 
                dmap->user_counter) / dmap->fragment_size);
221
 
      if (len < 0)
222
 
        len = 0;
223
 
      return len;
224
 
    }
225
 
 
226
 
  return 0;
227
 
}
228
 
 
229
 
int
230
 
dmap_get_qhead (dmap_p dmap)
231
 
{
232
 
  unsigned int ptr;
233
 
 
234
 
  if (dmap->fragment_size == 0)
235
 
    return 0;
236
 
 
237
 
  if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
238
 
    {
239
 
      ptr = (int) (dmap->byte_counter % dmap->bytes_in_use);
240
 
      return ptr / dmap->fragment_size;
241
 
    }
242
 
 
243
 
  if (dmap->dma_mode == PCM_ENABLE_INPUT)
244
 
    {
245
 
      ptr = (int) (dmap->user_counter % dmap->bytes_in_use);
246
 
      return ptr / dmap->fragment_size;
247
 
    }
248
 
 
249
 
  return 0;
250
 
}
251
 
 
252
 
int
253
 
dmap_get_qtail (dmap_p dmap)
254
 
{
255
 
  unsigned int ptr;
256
 
 
257
 
  if (dmap->fragment_size == 0)
258
 
    return 0;
259
 
 
260
 
  if (dmap->dma_mode == PCM_ENABLE_INPUT)
261
 
    {
262
 
      ptr = (int) (dmap->byte_counter % dmap->bytes_in_use);
263
 
      return ptr / dmap->fragment_size;
264
 
    }
265
 
 
266
 
  if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
267
 
    {
268
 
      ptr = (int) (dmap->user_counter % dmap->bytes_in_use);
269
 
      return ptr / dmap->fragment_size;
270
 
    }
271
 
 
272
 
  return 0;
273
 
}
274
 
 
275
 
int
276
 
oss_audio_set_format (int dev, int fmt, int format_mask)
277
 
{
278
 
  adev_p adev;
279
 
  int ret, newfmt;
280
 
  unsigned char neutral_byte;
281
 
  audio_format_info_p fmt_info;
282
 
 
283
 
  sync_seed++;
284
 
 
285
 
  if (dev < 0 || dev >= num_audio_engines)
286
 
    return OSS_ENXIO;
287
 
 
288
 
  adev = audio_engines[dev];
289
 
  if (!adev->enabled)
290
 
    return OSS_ENXIO;
291
 
 
292
 
  if (fmt == 0)
293
 
    return adev->user_parms.fmt;
294
 
 
295
 
  if (fmt == AFMT_AC3)
296
 
    {
297
 
      /*
298
 
       * AC3 cannot tolerate any format/rate conversions so disable them.
299
 
       */
300
 
      adev->cooked_enable = 0;
301
 
 
302
 
      /*
303
 
       * Report EIO error if the application tries to do something stupid. 
304
 
       * Otherwise buggy applications may produce loud helicopter sound.
305
 
       */
306
 
 
307
 
      if (adev->flags & ADEV_VMIX)
308
 
        {
309
 
          oss_audio_set_error (adev->engine_num, E_REC,
310
 
                               OSSERR (1018,
311
 
                                       "AFMT_AC3 used with virtual mixing device."),
312
 
                               0);
313
 
          /*
314
 
           * Errordesc:
315
 
           * Devices that support virtual or hardware mixing are
316
 
           * probably not capable to play AC3 streams properly.
317
 
           *
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.
323
 
           */
324
 
           return OSS_EIO;
325
 
        }
326
 
 
327
 
      if (adev->flags & ADEV_HWMIX)
328
 
        {
329
 
          oss_audio_set_error (adev->engine_num, E_REC,
330
 
                               OSSERR (1019,
331
 
                                       "AFMT_AC3 used with hardware mixing device."),
332
 
                               0);
333
 
          /*
334
 
           * Errordesc:
335
 
           * Devices that support virtual or hardware mixing are
336
 
           * probably not capable to play AC3 streams properly.
337
 
           *
338
 
           * This error may be caused by user who selected a wrong audio
339
 
           * device. 
340
 
           */
341
 
           return OSS_EIO;
342
 
        }
343
 
 
344
 
      if (adev->dmask & DMASK_OUT)
345
 
        if (adev->dmap_out->flags & DMAP_COOKED)
346
 
          {
347
 
            oss_audio_set_error (adev->engine_num, E_REC,
348
 
                                 OSSERR (1020,
349
 
                                         "AFMT_AC3 used with format conversions enabled."),
350
 
                                 0);
351
 
            /*
352
 
             * Errordesc:
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.
358
 
             *
359
 
             * Applications using AC3 should call SNDCTL_DSP_COOKEDMODE to
360
 
             * disable format conversions.
361
 
             */
362
 
           return OSS_EIO;
363
 
          }
364
 
    }
365
 
 
366
 
  ret = adev->d->adrv_set_format (dev, fmt);
367
 
 
368
 
  adev->user_parms.fmt = ret;
369
 
  adev->hw_parms.fmt = ret;
370
 
 
371
 
  if ((fmt_info = oss_find_format (ret)) == NULL)
372
 
    neutral_byte = 0;
373
 
  else
374
 
    {
375
 
      neutral_byte = fmt_info->neutral_byte;
376
 
    }
377
 
 
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;
382
 
 
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))
387
 
    return ret;
388
 
 
389
 
#ifdef NO_COOKED_MODE
390
 
  return ret;
391
 
#else
392
 
 
393
 
  if (ret == fmt)
394
 
    return ret;
395
 
 
396
 
  if (!adev->cooked_enable)
397
 
    return ret;
398
 
 
399
 
/*
400
 
 * We need to perform format conversions because the device
401
 
 * doesn't support the requested format.
402
 
 */
403
 
 
404
 
  /* Convertable format? */
405
 
  if (!(fmt & CONVERTABLE_FORMATS))
406
 
    {
407
 
      return ret;
408
 
    }
409
 
 
410
 
  adev->user_parms.fmt = fmt;
411
 
  if (adev->dmask & DMASK_OUT)
412
 
    {
413
 
      adev->dmap_out->flags |= DMAP_COOKED;
414
 
    }
415
 
 
416
 
  if (adev->dmask & DMASK_IN)
417
 
    {
418
 
      adev->dmap_in->flags |= DMAP_COOKED;
419
 
    }
420
 
 
421
 
  /* If the device is in 16 bit format then just return */
422
 
  if (ret & (AFMT_S16_LE | AFMT_S16_BE))
423
 
    return fmt;
424
 
 
425
 
  /* Try to find a suitable format */
426
 
 
427
 
  if (fmt == AFMT_MU_LAW && ret == AFMT_U8)     /* mu-Law <-> 8 bit linear */
428
 
    return fmt;
429
 
 
430
 
  if (format_mask & AFMT_S16_LE)
431
 
    {
432
 
      newfmt = AFMT_S16_LE;
433
 
      goto got_it;
434
 
    }
435
 
 
436
 
  if (format_mask & AFMT_S16_BE)
437
 
    {
438
 
      newfmt = AFMT_S16_BE;
439
 
      goto got_it;
440
 
    }
441
 
 
442
 
  return fmt;                   /* Nothing better than the one suggested by the device */
443
 
got_it:
444
 
 
445
 
  ret = adev->d->adrv_set_format (dev, newfmt);
446
 
 
447
 
  adev->hw_parms.fmt = ret;
448
 
 
449
 
  return fmt;
450
 
#endif
451
 
}
452
 
 
453
 
int
454
 
oss_audio_set_channels (int dev, int ch)
455
 
{
456
 
  adev_p adev;
457
 
  int ret;
458
 
 
459
 
  sync_seed++;
460
 
 
461
 
  if (dev < 0 || dev >= num_audio_engines)
462
 
    return OSS_ENXIO;
463
 
 
464
 
  adev = audio_engines[dev];
465
 
  if (!adev->enabled)
466
 
    return OSS_ENXIO;
467
 
 
468
 
  if (ch == 0)
469
 
    return adev->user_parms.channels;
470
 
 
471
 
  ret = adev->d->adrv_set_channels (dev, ch);
472
 
 
473
 
  if (ret < 1)
474
 
    {
475
 
      cmn_err (CE_WARN,
476
 
               "Audio engine %d: Internal error in channel setup, err=%d, ch=%d\n",
477
 
               dev, ret, ch);
478
 
      return OSS_EIO;
479
 
    }
480
 
 
481
 
  if (ch > 2 && ch > ret)       /* Requested multi channel mode not possible */
482
 
    ch = ret;
483
 
 
484
 
  adev->user_parms.channels = ret;
485
 
  adev->hw_parms.channels = ret;
486
 
 
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))
491
 
    return ret;
492
 
 
493
 
  if (ret > 1 && (adev->flags & ADEV_NONINTERLEAVED))
494
 
  {
495
 
          if (adev->dmask & DMASK_OUT)
496
 
              adev->dmap_out->flags |= DMAP_COOKED;
497
 
        
498
 
          if (adev->dmask & DMASK_IN)
499
 
              adev->dmap_in->flags |= DMAP_COOKED;
500
 
  }
501
 
     
502
 
 
503
 
#ifdef NO_COOKED_MODE
504
 
  return ret;
505
 
#else
506
 
 
507
 
  if (!adev->cooked_enable)
508
 
    return ret;
509
 
 
510
 
  if (ret == ch)
511
 
    return ret;
512
 
 
513
 
  /* For the time being only stereo <->mono is possible */
514
 
  if (ch != ret)
515
 
    if (!((ch == 1 && ret == 2) || (ch == 2 && ret == 1)))
516
 
      return ret;
517
 
 
518
 
/*
519
 
 * Needs to perform format conversions
520
 
 */
521
 
 
522
 
  adev->user_parms.channels = ch;
523
 
  if (adev->dmask & DMASK_OUT)
524
 
    {
525
 
      adev->dmap_out->flags |= DMAP_COOKED;
526
 
    }
527
 
 
528
 
  if (adev->dmask & DMASK_IN)
529
 
    {
530
 
      adev->dmap_in->flags |= DMAP_COOKED;
531
 
    }
532
 
 
533
 
  return ch;
534
 
#endif
535
 
}
536
 
 
537
 
int
538
 
oss_audio_set_rate (int dev, int rate)
539
 
{
540
 
  adev_p adev;
541
 
  int ret;
542
 
 
543
 
  sync_seed++;
544
 
 
545
 
  if (dev < 0 || dev >= num_audio_engines)
546
 
    return OSS_ENXIO;
547
 
 
548
 
  adev = audio_engines[dev];
549
 
  if (!adev->enabled)
550
 
    return OSS_ENXIO;
551
 
 
552
 
  if (rate == 0)
553
 
    return adev->user_parms.rate;
554
 
 
555
 
  ret = adev->d->adrv_set_rate (dev, rate);
556
 
  if (ret < 0)
557
 
    return ret;
558
 
 
559
 
  adev->user_parms.rate = ret;
560
 
  adev->hw_parms.rate = ret;
561
 
 
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))
566
 
    return ret;
567
 
 
568
 
  if (!adev->cooked_enable)
569
 
    return ret;
570
 
 
571
 
#if defined(NO_COOKED_MODE) || GRC == 0
572
 
  return ret;
573
 
#else
574
 
 
575
 
  if (ret == rate)              /* No SRC needed */
576
 
    return ret;
577
 
 
578
 
/*
579
 
 * Needs to perform format conversions
580
 
 */
581
 
 
582
 
  adev->user_parms.rate = rate;
583
 
  if (adev->dmask & DMASK_OUT)
584
 
    {
585
 
      adev->dmap_out->flags |= DMAP_COOKED;
586
 
    }
587
 
 
588
 
  if (adev->dmask & DMASK_IN)
589
 
    {
590
 
      adev->dmap_in->flags |= DMAP_COOKED;
591
 
    }
592
 
 
593
 
  return rate;
594
 
#endif
595
 
}
596
 
 
597
 
static void
598
 
reset_dmap (dmap_p dmap)
599
 
{
600
 
#ifdef DO_TIMINGS
601
 
  oss_do_timing ("Reset dmap");
602
 
#endif
603
 
  dmap->dma_mode = 0;
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;
613
 
}
614
 
 
615
 
int
616
 
oss_alloc_dmabuf (int dev, dmap_p dmap, int direction)
617
 
{
618
 
  adev_t *adev = dmap->adev;
619
 
 
620
 
  if (adev == NULL)
621
 
    {
622
 
      cmn_err (CE_WARN, "oss_alloc_dmabuf: adev==NULL\n");
623
 
      return OSS_EIO;
624
 
    }
625
 
 
626
 
  return __oss_alloc_dmabuf (dev, dmap, adev->dmabuf_alloc_flags,
627
 
                             adev->dmabuf_maxaddr, direction);
628
 
}
629
 
 
630
 
static int
631
 
default_alloc_buffer (int dev, dmap_t * dmap, int direction)
632
 
{
633
 
  int err;
634
 
 
635
 
  if (dmap->dmabuf != NULL)
636
 
    return 0;
637
 
 
638
 
  if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0)
639
 
    return err;
640
 
 
641
 
  return 0;
642
 
}
643
 
 
644
 
/*ARGSUSED*/
645
 
static int
646
 
default_free_buffer (int dev, dmap_t * dmap, int direction)
647
 
{
648
 
  if (dmap->dmabuf == NULL)
649
 
    return 0;
650
 
 
651
 
  oss_free_dmabuf (dev, dmap);
652
 
 
653
 
  dmap->dmabuf = NULL;
654
 
  dmap->dmabuf_phys = 0;
655
 
  return 0;
656
 
}
657
 
 
658
 
static int
659
 
init_dmap (adev_p adev, dmap_p dmap, int direction)
660
 
{
661
 
  int retval;
662
 
  int l, static_len;
663
 
  char *p;
664
 
  oss_native_word flags;
665
 
 
666
 
  if (dmap->osdev == NULL)
667
 
    {
668
 
      cmn_err (CE_WARN, "dmap->osdev==NULL\n");
669
 
      return OSS_EIO;
670
 
    }
671
 
 
672
 
  if (dmap->dmabuf == NULL)
673
 
    {
674
 
      if (adev->d->adrv_alloc_buffer != NULL)
675
 
        {
676
 
          retval =
677
 
            adev->d->adrv_alloc_buffer (adev->engine_num, dmap, direction);
678
 
        }
679
 
      else
680
 
        {
681
 
          retval = default_alloc_buffer (adev->engine_num, dmap, direction);
682
 
        }
683
 
      if (retval < 0)
684
 
        {
685
 
          cmn_err (CE_WARN,
686
 
                   "Failed to allocate DMA buffer for audio engine %d/%s\n",
687
 
                   adev->engine_num, adev->name);
688
 
          return retval;
689
 
        }
690
 
 
691
 
      if (dmap->dmabuf_phys == 0)       /* Cannot do mmap */
692
 
        adev->flags |= ADEV_NOMMAP;
693
 
    }
694
 
 
695
 
#ifdef linux
696
 
  if (dmap->dmabuf_phys == 0)
697
 
    adev->flags |= ADEV_NOMMAP;
698
 
#endif
699
 
  dmap->flags &= ~DMAP_FRAGFIXED;
700
 
 
701
 
  l = sizeof (dmap_t);
702
 
  static_len = (oss_native_word) & dmap->flags - (oss_native_word) dmap;
703
 
 
704
 
  p = (char *) &dmap->flags;
705
 
  l -= static_len;
706
 
  if (p != NULL)
707
 
    memset (p, 0, l);           /* Clear all */
708
 
 
709
 
  if (!dmap->buffer_protected && dmap->dmabuf != NULL)
710
 
    memset (dmap->dmabuf, dmap->neutral_byte, dmap->buffsize);
711
 
 
712
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
713
 
  reset_dmap (dmap);
714
 
  dmap->bytes_in_use = dmap->buffsize;
715
 
  dmap->frame_size = 1;
716
 
  dmap->user_frame_size = 1;
717
 
  dmap->flags = 0;
718
 
  dmap->audio_callback = NULL;
719
 
 
720
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
721
 
 
722
 
  return 0;
723
 
}
724
 
 
725
 
void
726
 
audio_reset_adev (adev_p adev)
727
 
{
728
 
  oss_native_word flags, dflags;
729
 
#ifdef DO_TIMINGS
730
 
  oss_do_timing ("Reset input & output\n");
731
 
#endif
732
 
  sync_seed++;
733
 
  if (!adev->enabled)
734
 
    return;
735
 
 
736
 
  dflags = 0;
737
 
  MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
738
 
  adev->go = 1;
739
 
  adev->enable_bits = adev->open_mode;
740
 
  if (adev->open_mode & OPEN_WRITE)
741
 
    {
742
 
      dmap_p dmap = adev->dmap_out;
743
 
      dmap->flags &= ~DMAP_PREPARED;
744
 
      memset (dmap->dmabuf, 0, dmap->buffsize);
745
 
    }
746
 
 
747
 
  if (adev->d->adrv_halt_input && adev->d->adrv_halt_output)
748
 
    {
749
 
      if (adev->open_mode & OPEN_READ)
750
 
        {
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))
756
 
            {
757
 
#ifdef CONFIG_OSSD
758
 
              ossd_event (adev->engine_num, OSSD_EV_RESET_INPUT);
759
 
#endif
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);
765
 
              reset_dmap (dmap);
766
 
            }
767
 
          MUTEX_EXIT (dmap->mutex, dflags);
768
 
        }
769
 
      if (adev->open_mode & OPEN_WRITE)
770
 
        {
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))
775
 
            {
776
 
#ifdef CONFIG_OSSD
777
 
              ossd_event (adev->engine_num, OSSD_EV_RESET_OUTPUT);
778
 
#endif
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);
784
 
              reset_dmap (dmap);
785
 
            }
786
 
          MUTEX_EXIT (dmap->mutex, dflags);
787
 
        }
788
 
 
789
 
      MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
790
 
      return;
791
 
    }
792
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
793
 
 
794
 
#ifdef CONFIG_OSSD
795
 
  ossd_event (adev->engine_num, OSSD_EV_RESET_OUTPUT);
796
 
  ossd_event (adev->engine_num, OSSD_EV_RESET_INPUT);
797
 
#endif
798
 
  adev->d->adrv_halt_io (adev->engine_num);
799
 
 
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);
804
 
}
805
 
 
806
 
static void
807
 
audio_reset_input (adev_p adev)
808
 
{
809
 
  dmap_p dmap = adev->dmap_in;
810
 
  oss_native_word flags, dflags;
811
 
 
812
 
  dflags = 0;
813
 
  if (!(adev->open_mode & OPEN_READ))
814
 
    return;
815
 
 
816
 
  if (dmap->dma_mode != PCM_ENABLE_INPUT)
817
 
    return;
818
 
 
819
 
  if (!(dmap->flags & DMAP_STARTED))
820
 
    return;
821
 
 
822
 
#ifdef DO_TIMINGS
823
 
  oss_do_timing ("Reset input\n");
824
 
#endif
825
 
  dmap->flags &= ~DMAP_PREPARED;
826
 
 
827
 
  if (adev->d->adrv_halt_input)
828
 
    {
829
 
#ifdef CONFIG_OSSD
830
 
      ossd_event (adev->engine_num, OSSD_EV_RESET_INPUT);
831
 
#endif
832
 
      adev->d->adrv_halt_input (adev->engine_num);
833
 
      MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
834
 
      reset_dmap (dmap);
835
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
836
 
      return;
837
 
    }
838
 
 
839
 
  adev->d->adrv_halt_io (adev->engine_num);
840
 
  MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
841
 
  MUTEX_ENTER (dmap->mutex, dflags);
842
 
  reset_dmap (dmap);
843
 
  MUTEX_EXIT (dmap->mutex, dflags);
844
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
845
 
}
846
 
 
847
 
static void
848
 
audio_reset_output (adev_p adev)
849
 
{
850
 
  dmap_p dmap = adev->dmap_out;
851
 
  oss_native_word flags, dflags;
852
 
  dflags = 0;
853
 
 
854
 
  sync_seed++;
855
 
 
856
 
  if (!(adev->open_mode & OPEN_WRITE))
857
 
    return;
858
 
 
859
 
  if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
860
 
    return;
861
 
 
862
 
  if (!(dmap->flags & DMAP_STARTED))
863
 
    return;
864
 
 
865
 
  dmap->flags &= ~DMAP_PREPARED;
866
 
#ifdef DO_TIMINGS
867
 
  oss_do_timing ("Reset output\n");
868
 
#endif
869
 
 
870
 
  if (adev->d->adrv_halt_output)
871
 
    {
872
 
#ifdef CONFIG_OSSD
873
 
      ossd_event (adev->engine_num, OSSD_EV_RESET_OUTPUT);
874
 
#endif
875
 
      adev->d->adrv_halt_output (adev->engine_num);
876
 
      MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
877
 
      reset_dmap (dmap);
878
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
879
 
      return;
880
 
    }
881
 
 
882
 
  adev->d->adrv_halt_io (adev->engine_num);
883
 
  MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
884
 
  MUTEX_ENTER (dmap->mutex, dflags);
885
 
  reset_dmap (dmap);
886
 
  MUTEX_EXIT (dmap->mutex, dflags);
887
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
888
 
}
889
 
 
890
 
static int launch_output (adev_p adev, dmap_p dmap);
891
 
static int launch_input (adev_p adev, dmap_p dmap);
892
 
 
893
 
static void
894
 
oss_audio_post (adev_p adev)
895
 
{
896
 
  int i, n, p;
897
 
  oss_uint64_t limit;
898
 
  dmap_p dmap = adev->dmap_out;
899
 
 
900
 
  if (!(adev->open_mode & OPEN_WRITE))
901
 
    return;
902
 
  if (dmap->user_counter == 0)
903
 
    return;
904
 
 
905
 
  if (dmap->flags & DMAP_STARTED)
906
 
    return;
907
 
 
908
 
#ifdef DO_TIMINGS
909
 
  oss_do_timing ("Post output\n");
910
 
#endif
911
 
 
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++)
919
 
    {
920
 
      dmap->dmabuf[p] = dmap->neutral_byte;
921
 
      p = (p + 1) % dmap->bytes_in_use;
922
 
    }
923
 
 
924
 
  launch_output (adev, dmap);
925
 
}
926
 
 
927
 
static void
928
 
oss_audio_sync (adev_p adev)
929
 
{
930
 
  dmap_p dmap = adev->dmap_out;
931
 
  oss_uint64_t uc, limit;
932
 
  oss_native_word flags;
933
 
  unsigned int status;
934
 
 
935
 
  int n = 0, loops = 0, tmout = OSS_HZ, i;
936
 
  int prev_underruns;
937
 
 
938
 
  if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
939
 
    return;
940
 
  if (adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)
941
 
    return;
942
 
 
943
 
  if (!(dmap->flags & DMAP_STARTED))
944
 
    oss_audio_post (adev);
945
 
 
946
 
  if (!(dmap->flags & DMAP_STARTED))
947
 
    return;
948
 
 
949
 
  /* Don't wait if output is untriggered */
950
 
  if (adev->go == 0 || !(adev->enable_bits & PCM_ENABLE_OUTPUT))
951
 
    return;
952
 
 
953
 
#ifdef DO_TIMINGS
954
 
  oss_do_timing ("Sync output\n");
955
 
#endif
956
 
 
957
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
958
 
  dmap->flags |= DMAP_POST;
959
 
 
960
 
  uc = dmap->user_counter;
961
 
  prev_underruns = dmap->play_underruns;
962
 
  dmap->play_underruns = 0;
963
 
 
964
 
  while (dmap->play_underruns == 0 && loops++ < dmap->nfrags
965
 
         && dmap->byte_counter < uc)
966
 
    {
967
 
      int p;
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;
973
 
 
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++)
977
 
        {
978
 
          dmap->dmabuf[p] = dmap->neutral_byte;
979
 
          p = (p + 1) % dmap->bytes_in_use;
980
 
        }
981
 
 
982
 
      tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
983
 
      tmout += OSS_HZ / 10;
984
 
 
985
 
      if (!oss_sleep (adev->out_wq, &dmap->mutex, tmout, &flags, &status))
986
 
        {
987
 
#ifndef __FreeBSD__
988
 
          cmn_err (CE_WARN, "Output timed out (sync) on audio engine %d\n",
989
 
                   adev->engine_num);
990
 
#endif
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);
995
 
          return;
996
 
        }
997
 
    }
998
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
999
 
 
1000
 
  n = 0;
1001
 
  if (adev->d->adrv_local_qlen) /* Drain the internal queue too */
1002
 
    while (n++ <=
1003
 
           adev->d->adrv_local_qlen (adev->engine_num) / dmap->fragment_size)
1004
 
      {
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);
1011
 
      }
1012
 
  dmap->play_underruns = prev_underruns;
1013
 
}
1014
 
 
1015
 
static int prepare_output (adev_p adev, dmap_p dmap);
1016
 
static int prepare_input (adev_p adev, dmap_p dmap);
1017
 
 
1018
 
void
1019
 
oss_audio_set_error (int dev, int mode, int err, int parm)
1020
 
{
1021
 
  int i, n;
1022
 
 
1023
 
  dmap_t *dmap;
1024
 
 
1025
 
#ifdef DO_TIMINGS
1026
 
  {
1027
 
    if (mode == E_REC)
1028
 
      oss_timing_printf ("Audio rec error code %05d/%d, engine=%d", err, parm,
1029
 
               mode);
1030
 
    else
1031
 
      oss_timing_printf ("Audio play error code %05d/%d, engine=%d", err, parm,
1032
 
               mode);
1033
 
  }
1034
 
#endif
1035
 
 
1036
 
#if 0
1037
 
  if (mode == E_REC)
1038
 
    cmn_err (CE_CONT, "Audio rec error code %05d/%d, engine=%d\n", err, parm,
1039
 
             mode);
1040
 
  else
1041
 
    cmn_err (CE_CONT, "Audio play error code %05d/%d, engine=%d\n", err, parm,
1042
 
             mode);
1043
 
#endif
1044
 
 
1045
 
  switch (mode)
1046
 
    {
1047
 
    case E_PLAY:
1048
 
      dmap = audio_engines[dev]->dmap_out;
1049
 
      break;
1050
 
    case E_REC:
1051
 
      dmap = audio_engines[dev]->dmap_in;
1052
 
      break;
1053
 
 
1054
 
    default:
1055
 
      dmap = audio_engines[dev]->dmap_out;      /* Actually this would be an error */
1056
 
    }
1057
 
 
1058
 
  n = dmap->num_errors++;
1059
 
  if (n > MAX_AUDIO_ERRORS)
1060
 
    n = MAX_AUDIO_ERRORS;
1061
 
 
1062
 
  if (n > 0)
1063
 
    {
1064
 
 
1065
 
/*
1066
 
 * Move previous errors (if any) upwards in the list.
1067
 
 */
1068
 
      for (i = n; i > 0; i--)
1069
 
        {
1070
 
          dmap->errors[i] = dmap->errors[i - 1];
1071
 
          dmap->error_parms[i] = dmap->error_parms[i - 1];
1072
 
        }
1073
 
    }
1074
 
 
1075
 
  dmap->errors[0] = err;
1076
 
  dmap->error_parms[0] = parm;
1077
 
 
1078
 
}
1079
 
 
1080
 
/*ARGSUSED*/
1081
 
static void
1082
 
report_errors (char *s, const char *hdr, adev_t * adev, dmap_t * dmap,
1083
 
               int bufsize)
1084
 
{
1085
 
  int i, l, j;
1086
 
 
1087
 
  if (bufsize < 30)             /* No space left */
1088
 
    return;
1089
 
 
1090
 
  strcpy (s, hdr);
1091
 
  s += l = strlen (s);
1092
 
  bufsize -= l;
1093
 
 
1094
 
  for (i = 0; i < dmap->num_errors && i < MAX_AUDIO_ERRORS; i++)
1095
 
    {
1096
 
      int dupe = 0;
1097
 
 
1098
 
      if (bufsize < 30)
1099
 
        return;
1100
 
      for (j = 0; !dupe && j < i; j++)
1101
 
        if (dmap->errors[i] == dmap->errors[j])
1102
 
          dupe = 1;
1103
 
 
1104
 
      if (dupe)
1105
 
        continue;
1106
 
 
1107
 
      sprintf (s, " %05d:%d", dmap->errors[i], dmap->error_parms[i]);
1108
 
      s += l = strlen (s);
1109
 
      bufsize -= l;
1110
 
    }
1111
 
}
1112
 
 
1113
 
static void
1114
 
store_history (int dev)
1115
 
{
1116
 
  int p;
1117
 
  char *tmp, *s;
1118
 
 
1119
 
  adev_p adev = audio_engines[dev];
1120
 
 
1121
 
  if (adev->pid == 0)           /* Virtual mixer */
1122
 
    return;
1123
 
 
1124
 
  if (*adev->cmd && strcmp (adev->cmd, "sndconf") == 0)
1125
 
    return;
1126
 
 
1127
 
  p = oss_history_p;
1128
 
  oss_history_p = (oss_history_p + 1) % OSS_HISTORY_SIZE;
1129
 
 
1130
 
  tmp = oss_history[p];
1131
 
  memset (tmp, 0, OSS_HISTORY_STRSIZE);
1132
 
  s = tmp;
1133
 
 
1134
 
  sprintf (s, "%s.%02d: ", adev->devnode, adev->engine_num);
1135
 
  s += strlen (s);
1136
 
 
1137
 
  if (adev->pid != -1)
1138
 
    {
1139
 
      sprintf (s, "pid %d ", adev->pid);
1140
 
      s += strlen (s);
1141
 
    }
1142
 
 
1143
 
  if (*adev->cmd != 0)
1144
 
    {
1145
 
      sprintf (s, "cmd '%s' ", adev->cmd);
1146
 
      s += strlen (s);
1147
 
    }
1148
 
  else
1149
 
    {
1150
 
      strcpy (s, "cmd: Unknown ");
1151
 
      s += strlen (s);
1152
 
    }
1153
 
 
1154
 
  if (adev->open_mode & OPEN_READ)
1155
 
    {
1156
 
      sprintf (s, "IN ");
1157
 
      s += strlen (s);
1158
 
    }
1159
 
 
1160
 
  if (adev->open_mode & OPEN_WRITE)
1161
 
    {
1162
 
      sprintf (s, "OUT ");
1163
 
      s += strlen (s);
1164
 
    }
1165
 
 
1166
 
  if (adev->timeout_count > 0)
1167
 
    {
1168
 
      sprintf (s, "%d timeouts ", adev->timeout_count);
1169
 
      s += strlen (s);
1170
 
    }
1171
 
 
1172
 
  if (adev->dmap_out->play_underruns > 0)
1173
 
    {
1174
 
      sprintf (s, "%d underruns ", adev->dmap_out->play_underruns);
1175
 
      s += strlen (s);
1176
 
    }
1177
 
 
1178
 
  if (adev->dmap_in->rec_overruns > 0)
1179
 
    {
1180
 
      sprintf (s, "%d overruns ", adev->dmap_in->rec_overruns);
1181
 
      s += strlen (s);
1182
 
    }
1183
 
 
1184
 
  if (adev->dmap_out->num_errors > 0)
1185
 
    {
1186
 
      report_errors (s, "Play events:", adev, adev->dmap_out,
1187
 
                     OSS_HISTORY_STRSIZE - strlen (tmp) - 1);
1188
 
      s += strlen (s);
1189
 
      *s++ = ' ';
1190
 
    }
1191
 
 
1192
 
  if (adev->dmap_in->num_errors > 0)
1193
 
    {
1194
 
      report_errors (s, "Rec events:", adev, adev->dmap_in,
1195
 
                     OSS_HISTORY_STRSIZE - strlen (tmp) - 1);
1196
 
      s += strlen (s);
1197
 
      *s++ = ' ';
1198
 
    }
1199
 
}
1200
 
 
1201
 
char *
1202
 
audio_show_latency (int dev)
1203
 
{
1204
 
  static char str[32];
1205
 
  adev_p adev = audio_engines[dev];
1206
 
  dmap_p dmap;
1207
 
  int dr, fs;
1208
 
 
1209
 
  *str = 0;
1210
 
 
1211
 
  if (dev < 0 || dev >= num_audio_engines)
1212
 
    return "Bad device";
1213
 
 
1214
 
  if (adev->open_mode == 0)
1215
 
    return "Not opened";
1216
 
 
1217
 
  if (adev->open_mode == OPEN_READ)
1218
 
    dmap = adev->dmap_in;
1219
 
  else
1220
 
    dmap = adev->dmap_out;
1221
 
 
1222
 
  if (dmap == NULL)
1223
 
    return "Unknown";
1224
 
 
1225
 
  if (!(dmap->flags & DMAP_STARTED))
1226
 
    return "Not started";
1227
 
 
1228
 
  dr = dmap->data_rate;
1229
 
  fs = dmap->fragment_size;
1230
 
 
1231
 
  if (dr <= 0)
1232
 
    sprintf (str, "%d", dmap->fragment_size);
1233
 
  else
1234
 
    {
1235
 
      int r = (fs * 10000) / dr;
1236
 
 
1237
 
      sprintf (str, "%d/%d (%d.%d msec)", dmap->fragment_size, dr, r / 10,
1238
 
               r % 10);
1239
 
    }
1240
 
 
1241
 
 
1242
 
  return str;
1243
 
}
1244
 
 
1245
 
void
1246
 
oss_audio_release (int dev, struct fileinfo *file)
1247
 
{
1248
 
  adev_p adev;
1249
 
  int mode;
1250
 
  oss_native_word flags;
1251
 
 
1252
 
  sync_seed++;
1253
 
 
1254
 
  if (dev < 0 || dev >= num_audio_engines)
1255
 
    return;
1256
 
  if (file)
1257
 
    mode = file->mode & O_ACCMODE;
1258
 
  else
1259
 
    mode = OPEN_READ | OPEN_WRITE;
1260
 
#ifdef DO_TIMINGS
1261
 
    oss_timing_printf ("=-=-=- Closing audio engine %d -=-=-=", dev);
1262
 
#endif
1263
 
 
1264
 
  adev = audio_engines[dev];
1265
 
 
1266
 
  if (adev->unloaded || !adev->enabled)
1267
 
    {
1268
 
      cmn_err (CE_CONT, "Audio device %s not available - close aborted\n",
1269
 
               adev->name);
1270
 
      return;
1271
 
    }
1272
 
 
1273
 
  oss_audio_post (adev);
1274
 
  oss_audio_sync (adev);
1275
 
 
1276
 
#ifdef CONFIG_OSSD
1277
 
  ossd_event (adev->engine_num, OSSD_EV_CLOSE);
1278
 
#endif
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)
1283
 
    {
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);
1289
 
    }
1290
 
 
1291
 
  if (adev->dmask & DMASK_IN)
1292
 
    {
1293
 
      adev->dmap_in->audio_callback = NULL;
1294
 
    }
1295
 
 
1296
 
  store_history (dev);
1297
 
 
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);
1304
 
 
1305
 
  /*
1306
 
   * Free the DMA buffer(s)
1307
 
   */
1308
 
  if (adev->dmask & DMASK_OUT)
1309
 
    if (adev->dmap_out->dmabuf != NULL)
1310
 
      {
1311
 
        if (adev->d->adrv_free_buffer != NULL)
1312
 
          {
1313
 
            adev->d->adrv_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
1314
 
          }
1315
 
        else
1316
 
          default_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
1317
 
        adev->dmap_out->dmabuf = NULL;
1318
 
      }
1319
 
 
1320
 
  if (adev->dmask & DMASK_IN)
1321
 
    if (adev->dmap_in != adev->dmap_out && adev->dmap_in->dmabuf != NULL)
1322
 
      {
1323
 
        if (adev->d->adrv_free_buffer != NULL)
1324
 
          {
1325
 
            adev->d->adrv_free_buffer (dev, adev->dmap_in, OPEN_READ);
1326
 
          }
1327
 
        else
1328
 
          default_free_buffer (dev, adev->dmap_in, OPEN_READ);
1329
 
        adev->dmap_in->dmabuf = NULL;
1330
 
      }
1331
 
 
1332
 
  MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1333
 
  adev->open_mode = 0;
1334
 
  adev->flags &= ~ADEV_OPENED;
1335
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1336
 
}
1337
 
 
1338
 
static void audio_outputintr (int dev, int intr_flags);
1339
 
static void audio_inputintr (int dev, int intr_flags);
1340
 
 
1341
 
/*ARGSUSED*/
1342
 
int
1343
 
oss_audio_open_engine (int dev, int no_worries, struct fileinfo *file,
1344
 
                       int recursive, int open_flags, int *newdev)
1345
 
{
1346
 
/*
1347
 
 * Open audio engine
1348
 
 */
1349
 
  adev_p adev;
1350
 
  int retval = 0, fmt;
1351
 
  int mode;
1352
 
  int saved_cooked;
1353
 
  int channels, rate;
1354
 
  oss_native_word flags;
1355
 
  extern int cooked_enable;     /* Config option */
1356
 
 
1357
 
  DOWN_STATUS (0xff);
1358
 
 
1359
 
  if (file)
1360
 
    {
1361
 
      mode = file->mode & O_ACCMODE;
1362
 
    }
1363
 
  else
1364
 
    mode = OPEN_READ | OPEN_WRITE;
1365
 
 
1366
 
  sync_seed++;
1367
 
 
1368
 
  DDB (cmn_err
1369
 
       (CE_CONT, "oss_audio_open_engine(%d, mode=0x%x)\n", dev, mode));
1370
 
 
1371
 
#ifdef DO_TIMINGS
1372
 
    oss_timing_printf ("-----> oss_audio_open_engine(%d, mode=0x%x)", dev, mode);
1373
 
#endif
1374
 
 
1375
 
  if (dev < 0 || dev >= num_audio_engines || audio_engines == NULL)
1376
 
    return OSS_ENXIO;
1377
 
 
1378
 
  adev = audio_engines[dev];
1379
 
  if (adev->unloaded)
1380
 
    return OSS_ENODEV;
1381
 
  if (!adev->enabled)
1382
 
    return OSS_ENXIO;
1383
 
 
1384
 
  if (adev->osdev == NULL)
1385
 
    {
1386
 
      cmn_err (CE_WARN, "adev->osdev==NULL\n");
1387
 
      return OSS_EIO;
1388
 
    }
1389
 
 
1390
 
  open_flags = get_open_flags (mode, open_flags, file);
1391
 
 
1392
 
  MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1393
 
  if (adev->open_mode != 0)
1394
 
    {
1395
 
      MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1396
 
      return OSS_EBUSY;
1397
 
    }
1398
 
  adev->open_mode = mode;
1399
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1400
 
 
1401
 
  adev->cooked_enable = cooked_enable;  /* This must be done before drv->open() */
1402
 
#ifdef DO_TIMINGS
1403
 
  if (adev->cooked_enable)
1404
 
    oss_do_timing ("Initial cooked mode ON");
1405
 
  else
1406
 
    oss_do_timing ("Initial cooked mode OFF");
1407
 
#endif
1408
 
 
1409
 
  adev->src_quality = src_quality;
1410
 
  if ((retval = adev->d->adrv_open (dev, mode, open_flags)) < 0)
1411
 
    {
1412
 
      adev->open_mode = 0;
1413
 
 
1414
 
      return retval;
1415
 
    }
1416
 
 
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;
1429
 
  adev->policy = -1;
1430
 
  adev->song_name[0] = 0;
1431
 
  adev->label[0] = 0;
1432
 
 
1433
 
  if (open_flags & (OF_NOCONV | OF_MMAP))
1434
 
    {
1435
 
      adev->cooked_enable = 0;
1436
 
#ifdef DO_TIMINGS
1437
 
      oss_do_timing ("Forcing cooked mode OFF");
1438
 
#endif
1439
 
    }
1440
 
 
1441
 
  memset (audio_engines[dev]->cmd, 0, sizeof (audio_engines[dev]->cmd));
1442
 
 
1443
 
  if (recursive)
1444
 
    {
1445
 
      strcpy (audio_engines[dev]->cmd, "OSS internal");
1446
 
      audio_engines[dev]->pid = 0;
1447
 
    }
1448
 
  else
1449
 
    {
1450
 
      char *cmd;
1451
 
 
1452
 
      if ((cmd = GET_PROCESS_NAME (file)) != NULL)
1453
 
        {
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';
1458
 
        }
1459
 
      audio_engines[dev]->pid = GET_PROCESS_PID (file);
1460
 
    }
1461
 
 
1462
 
  adev->dmask = 0;
1463
 
/*
1464
 
 * Find out which dmap structures are required.
1465
 
 */
1466
 
 
1467
 
  if (mode == OPEN_WRITE)
1468
 
    adev->dmask = DMASK_OUT;
1469
 
  else if (mode == OPEN_READ)
1470
 
    adev->dmask = DMASK_IN;
1471
 
  else
1472
 
    {
1473
 
      if (mode != (OPEN_WRITE | OPEN_READ))
1474
 
        cmn_err (CE_NOTE, "Unrecognized open mode %x\n", mode);
1475
 
      adev->dmask = DMASK_OUT;
1476
 
 
1477
 
      if ((adev->flags & ADEV_DUPLEX) && adev->dmap_out != adev->dmap_in)
1478
 
        adev->dmask = DMASK_OUT | DMASK_IN;
1479
 
    }
1480
 
 
1481
 
#if 0
1482
 
/*
1483
 
 * Handling of non-blocking doesn't belong here. It will be handled
1484
 
 * by read/write.
1485
 
 */
1486
 
  if (file != NULL && !(open_flags & OF_BLOCK))
1487
 
    if (ISSET_FILE_FLAG (file, O_NONBLOCK) || adev->forced_nonblock)
1488
 
      {
1489
 
#ifdef DO_TIMINGS
1490
 
        oss_do_timing ("*** Non-blocking open ***");
1491
 
#endif
1492
 
        adev->nonblock = 1;
1493
 
      }
1494
 
#endif
1495
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1496
 
 
1497
 
  if (adev->dmask & DMASK_OUT)
1498
 
    {
1499
 
 
1500
 
      /*
1501
 
       * Use small DMA buffer if requested and if the device supports it.
1502
 
       */
1503
 
      if (SMALL_DMABUF_SIZE >= (adev->min_block * 2) &&
1504
 
          (open_flags & OF_SMALLBUF))
1505
 
        adev->dmap_out->flags |= DMAP_SMALLBUF;
1506
 
      else
1507
 
        if (MEDIUM_DMABUF_SIZE >= (adev->min_block * 2) &&
1508
 
            (open_flags & OF_MEDIUMBUF))
1509
 
        adev->dmap_out->flags |= DMAP_MEDIUMBUF;
1510
 
      else
1511
 
        adev->dmap_out->flags &= ~(DMAP_SMALLBUF | DMAP_MEDIUMBUF);
1512
 
 
1513
 
      if ((retval = init_dmap (adev, adev->dmap_out, OPEN_WRITE)) < 0)
1514
 
        {
1515
 
          oss_audio_release (dev, file);
1516
 
          return retval;
1517
 
        }
1518
 
    }
1519
 
 
1520
 
  if (adev->dmask & DMASK_IN)
1521
 
    {
1522
 
      /*
1523
 
       * Use small DMA buffer if requested and if the device supports it.
1524
 
       */
1525
 
      if (SMALL_DMABUF_SIZE >= (adev->min_block * 2) &&
1526
 
          (open_flags & OF_SMALLBUF))
1527
 
        adev->dmap_in->flags |= DMAP_SMALLBUF;
1528
 
      else
1529
 
        adev->dmap_in->flags &= ~DMAP_SMALLBUF;
1530
 
 
1531
 
      if ((retval = init_dmap (adev, adev->dmap_in, OPEN_READ)) < 0)
1532
 
        {
1533
 
          oss_audio_release (dev, file);
1534
 
          return retval;
1535
 
        }
1536
 
    }
1537
 
 
1538
 
  adev->dmap_out->num_errors = 0;
1539
 
  adev->dmap_in->num_errors = 0;
1540
 
 
1541
 
  if ((mode & OPEN_WRITE) && !(adev->flags & ADEV_NOOUTPUT))
1542
 
    {
1543
 
      oss_reset_wait_queue (adev->out_wq);
1544
 
    }
1545
 
  if ((mode & OPEN_READ) && !(adev->flags & ADEV_NOINPUT))
1546
 
    {
1547
 
      oss_reset_wait_queue (adev->in_wq);
1548
 
    }
1549
 
 
1550
 
  adev->xformat_mask = 0;
1551
 
 
1552
 
  switch (adev->dmask)
1553
 
    {
1554
 
    case DMASK_OUT:
1555
 
      adev->xformat_mask = adev->oformat_mask;
1556
 
      break;
1557
 
 
1558
 
    case DMASK_IN:
1559
 
      adev->xformat_mask = adev->iformat_mask;
1560
 
      break;
1561
 
 
1562
 
    case DMASK_OUT | DMASK_IN:
1563
 
      adev->xformat_mask = adev->oformat_mask & adev->iformat_mask;
1564
 
      break;
1565
 
 
1566
 
    default:
1567
 
      cmn_err (CE_WARN, "Internal error A during open\n");
1568
 
    }
1569
 
 
1570
 
  fmt = DSP_DEFAULT_FMT;
1571
 
  rate = DSP_DEFAULT_SPEED;
1572
 
 
1573
 
  if (adev->flags & ADEV_FIXEDRATE && adev->fixed_rate != 0)
1574
 
    rate = adev->fixed_rate;
1575
 
 
1576
 
  if (adev->flags & ADEV_16BITONLY)
1577
 
    fmt = AFMT_S16_LE;
1578
 
 
1579
 
  adev->go = 1;
1580
 
  adev->enable_bits = adev->open_mode;
1581
 
 
1582
 
  channels = 1;
1583
 
  if (adev->flags & ADEV_STEREOONLY)
1584
 
    channels = 2;
1585
 
 
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;
1592
 
 
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;
1598
 
 
1599
 
#ifdef DO_TIMINGS
1600
 
  {
1601
 
    char *p_name;
1602
 
    pid_t proc_pid;
1603
 
    oss_timing_printf ("=-=-=- Audio device %d (%s) opened, mode %x -=-=-=",
1604
 
             adev->engine_num, adev->name, mode);
1605
 
 
1606
 
    if ((proc_pid = GET_PROCESS_PID (file)) != -1)
1607
 
        oss_timing_printf ("Opened by PID: %d", proc_pid);
1608
 
 
1609
 
    if ((p_name = GET_PROCESS_NAME (file)) != NULL)
1610
 
        oss_timing_printf ("Opening process name: %s", p_name);
1611
 
  }
1612
 
#endif
1613
 
 
1614
 
#ifdef CONFIG_OSSD
1615
 
  ossd_event (adev->engine_num, OSSD_EV_OPEN);
1616
 
#endif
1617
 
 
1618
 
  return adev->engine_num;
1619
 
}
1620
 
 
1621
 
#ifdef VDEV_SUPPORT
1622
 
int
1623
 
oss_audio_open_devfile (int dev, int dev_class, struct fileinfo *file,
1624
 
                        int recursive, int open_flags, int *newdev)
1625
 
{
1626
 
/*
1627
 
 * Open audio device file (by calling oss_audio_open_engine).
1628
 
 */
1629
 
  int err, d, n;
1630
 
  int open_excl = 0;
1631
 
  adev_p adev;
1632
 
  int mode = OPEN_READ | OPEN_WRITE;
1633
 
 
1634
 
#ifdef DO_TIMINGS
1635
 
    oss_timing_printf ("-----> oss_audio_open_devfile(%d, mode=0x%x)", dev, mode);
1636
 
#endif
1637
 
 
1638
 
  if (file)
1639
 
    {
1640
 
      mode = file->mode & O_ACCMODE;
1641
 
      open_flags = get_open_flags (mode, open_flags, file);
1642
 
      if (file->acc_flags & O_EXCL)
1643
 
        {
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;
1647
 
#endif
1648
 
        }
1649
 
    }
1650
 
 
1651
 
  DDB (cmn_err
1652
 
       (CE_CONT, "oss_audio_open_devfile(%d, mode=0x%x, excl=%d)\n", dev,
1653
 
        mode, open_excl));
1654
 
 
1655
 
  if (dev < 0 || dev >= num_audio_devfiles)
1656
 
    {
1657
 
      return OSS_ENODEV;
1658
 
    }
1659
 
  adev = audio_devfiles[dev];
1660
 
  dev = adev->engine_num;
1661
 
 
1662
 
  n=0;
1663
 
  while (adev->d->adrv_redirect != NULL)
1664
 
     {
1665
 
             int next_dev = dev;
1666
 
 
1667
 
             if (n++ > num_audio_engines)
1668
 
                {
1669
 
                        cmn_err(CE_CONT, "Recursive audio device redirection\n");
1670
 
                        return OSS_ELOOP;
1671
 
                }
1672
 
 
1673
 
             next_dev = adev->d->adrv_redirect (dev, mode, open_flags);
1674
 
#ifdef DO_TIMINGS
1675
 
             oss_timing_printf ("Engine redirect %d -> %d\n", dev, next_dev);
1676
 
#endif
1677
 
 
1678
 
             if (next_dev == dev) /* No change */
1679
 
                break;
1680
 
 
1681
 
             if (next_dev < 0 || next_dev >= num_audio_engines)
1682
 
                return OSS_ENXIO;
1683
 
 
1684
 
             dev = next_dev;
1685
 
             adev = audio_engines[dev];
1686
 
     }
1687
 
 
1688
 
/*
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.
1692
 
 */
1693
 
  if (open_excl && !(adev->flags & ADEV_HWMIX))
1694
 
    {
1695
 
      DDB (cmn_err
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)
1699
 
        {
1700
 
          return dev;
1701
 
        }
1702
 
 
1703
 
      goto done;
1704
 
    }
1705
 
  
1706
 
#ifdef CONFIG_OSS_VMIX
1707
 
/*
1708
 
 * Get a vmix engine if the device has vmix support enabled.
1709
 
 */
1710
 
  if (!vmix_disabled)
1711
 
  if (adev->vmix_mixer != NULL) // Virtual mixer attached
1712
 
     {
1713
 
             int vmix_dev;
1714
 
 
1715
 
             /*
1716
 
              * Create a new vmix client instance.
1717
 
              */
1718
 
 
1719
 
             if ((vmix_dev=vmix_create_client(adev->vmix_mixer))>=0)
1720
 
                {
1721
 
#ifdef DO_TIMINGS
1722
 
             oss_timing_printf ("Vmix redirect %d -> %d\n", dev, vmix_dev);
1723
 
#endif
1724
 
                      if ((dev = oss_audio_open_engine (vmix_dev, dev_class, file,
1725
 
                                                        recursive, open_flags, newdev)) < 0)
1726
 
                        {
1727
 
                          //cmn_err(CE_WARN, "Failed to open vmix engine %d, err=%d\n", vmix_dev, dev);
1728
 
                          return dev;
1729
 
                        }
1730
 
#ifdef DO_TIMINGS
1731
 
             oss_timing_printf ("Vmix engine opened %d -> %d\n", vmix_dev, dev);
1732
 
#endif
1733
 
                
1734
 
                      goto done;
1735
 
                }
1736
 
     }
1737
 
#endif
1738
 
 
1739
 
#if 0
1740
 
/*
1741
 
 * Follow redirection chain for the device.
1742
 
 *
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).
1745
 
 */
1746
 
 
1747
 
  if (!open_excl)
1748
 
     {
1749
 
          if (mode == OPEN_WRITE)
1750
 
            {
1751
 
              redirect = adev->redirect_out;
1752
 
            }
1753
 
          else if (mode == OPEN_READ)
1754
 
            {
1755
 
              redirect = adev->redirect_in;
1756
 
            }
1757
 
          else
1758
 
            {
1759
 
              /*
1760
 
               * Read-write open. Check that redirection for both directions are
1761
 
               * identical.
1762
 
               */
1763
 
              if (adev->redirect_out == adev->redirect_in)
1764
 
                redirect = adev->redirect_out;
1765
 
            }
1766
 
     }
1767
 
  DDB (cmn_err
1768
 
       (CE_CONT, "Redirect=%d (%d, %d)\n", redirect, adev->redirect_out,
1769
 
        adev->redirect_in));
1770
 
 
1771
 
  if (redirect >= 0 && redirect < num_audio_engines)
1772
 
    {
1773
 
      adev = audio_engines[redirect];
1774
 
      DDB (cmn_err
1775
 
           (CE_CONT, "Redirect devfile %d -> engine=%d\n", dev,
1776
 
            adev->engine_num));
1777
 
      dev = redirect;
1778
 
    }
1779
 
#endif
1780
 
 
1781
 
  while (adev != NULL)
1782
 
    {
1783
 
      DDB (cmn_err (CE_CONT, "Trying engine=%d\n", adev->engine_num));
1784
 
      if (!adev->enabled)
1785
 
        return OSS_EAGAIN;
1786
 
 
1787
 
      if (adev->unloaded)
1788
 
        return OSS_EAGAIN;
1789
 
 
1790
 
      *newdev = adev->engine_num;
1791
 
      if ((err =
1792
 
           oss_audio_open_engine (adev->engine_num, dev_class, file,
1793
 
                                  recursive, open_flags, newdev)) < 0)
1794
 
        {
1795
 
          /* 
1796
 
           * Check if the device was busy and if it has a
1797
 
           * shadow device.
1798
 
           */
1799
 
          if (err != OSS_EBUSY || adev->next_out == NULL)
1800
 
            return err;
1801
 
          adev = adev->next_out;
1802
 
        }
1803
 
      else
1804
 
        {
1805
 
          dev = adev->engine_num;
1806
 
          DDB (cmn_err (CE_CONT, "Engine %d opened\n", adev->engine_num));
1807
 
          goto done;
1808
 
        }
1809
 
    }
1810
 
 
1811
 
  return OSS_EBUSY;
1812
 
 
1813
 
done:
1814
 
/*
1815
 
 * Try to find which minor number matches this /dev/dsp# device.
1816
 
 */
1817
 
 
1818
 
  if ((d = oss_find_minor (OSS_DEV_DSP_ENGINE, dev)) < 0)
1819
 
    {
1820
 
      oss_audio_release (dev, file);
1821
 
      return d;
1822
 
    }
1823
 
 
1824
 
  *newdev = d;
1825
 
  return dev;
1826
 
}
1827
 
#endif
1828
 
 
1829
 
static struct
1830
 
{
1831
 
  int sz, nfrags;
1832
 
} policies[] =
1833
 
{
1834
 
  {
1835
 
  8, 2},                        /* 0 */
1836
 
  {
1837
 
  16, 2},                       /* 1 */
1838
 
  {
1839
 
  128, 2},                      /* 2 */
1840
 
  {
1841
 
  256, 4},                      /* 3 */
1842
 
  {
1843
 
  512, 4},                      /* 4 */
1844
 
  {
1845
 
  1024, 0},                     /* 5 */
1846
 
  {
1847
 
  2048, 0},                     /* 6 */
1848
 
  {
1849
 
  4096, 0},                     /* 7 */
1850
 
  {
1851
 
  16384, 0},                    /* 8 */
1852
 
  {
1853
 
  32768, 0},                    /* 9 */
1854
 
  {
1855
 
  256 *1024, 0},                /* 10 */
1856
 
};
1857
 
 
1858
 
static void
1859
 
setup_fragments (adev_p adev, dmap_p dmap, int direction)
1860
 
{
1861
 
  int sz, maxfrags = 100000;
1862
 
  int min;
1863
 
  extern int max_intrate;
1864
 
 
1865
 
  if (adev->max_intrate == 0 || adev->max_intrate > max_intrate)
1866
 
    adev->max_intrate = max_intrate;
1867
 
 
1868
 
  if (dmap->flags & DMAP_FRAGFIXED)
1869
 
    return;
1870
 
  dmap->flags |= DMAP_FRAGFIXED;
1871
 
 
1872
 
#ifdef DO_TIMINGS
1873
 
    oss_timing_printf ("setup_fragments(%d, dir=%d)", adev->engine_num, direction);
1874
 
#endif
1875
 
 
1876
 
  sz = 1024;
1877
 
 
1878
 
  dmap->low_water_rq = 0;
1879
 
  dmap->low_water = -1;
1880
 
 
1881
 
  if (dmap->fragsize_rq != 0)   /* SNDCTL_DSP_SETFRAGMENT was called */
1882
 
    {
1883
 
      int v;
1884
 
      v = dmap->fragsize_rq & 0xffff;
1885
 
 
1886
 
      sz = (1 << v);
1887
 
 
1888
 
      if (dmap->expand_factor != UNIT_EXPAND)
1889
 
        {
1890
 
          int sz2;
1891
 
 
1892
 
          sz2 = (sz * dmap->expand_factor) / UNIT_EXPAND;
1893
 
 
1894
 
          if (sz < sz2)
1895
 
            {
1896
 
              while (sz < sz2)
1897
 
                sz *= 2;
1898
 
            }
1899
 
          else if (sz > sz2)
1900
 
            {
1901
 
              while (sz > sz2)
1902
 
                sz /= 2;
1903
 
            }
1904
 
 
1905
 
        }
1906
 
 
1907
 
      if (sz < 8)
1908
 
        sz = 8;
1909
 
      if (sz > dmap->buffsize / 2)
1910
 
        sz = dmap->buffsize / 2;
1911
 
 
1912
 
      maxfrags = (dmap->fragsize_rq >> 16) & 0x7fff;
1913
 
 
1914
 
      if (maxfrags == 0)
1915
 
        maxfrags = 0x7fff;
1916
 
      else if (maxfrags < 2)
1917
 
        maxfrags = 2;
1918
 
 
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;
1923
 
 
1924
 
#if 1
1925
 
      /*
1926
 
       * Workaround for realplay
1927
 
       */
1928
 
      if (adev->open_flags & OF_SMALLFRAGS)
1929
 
        while (sz > dmap->buffsize / 8)
1930
 
          {
1931
 
            maxfrags *= 2;
1932
 
            sz /= 2;
1933
 
          }
1934
 
#endif
1935
 
    }
1936
 
 
1937
 
  if (adev->policy >= 0 && adev->policy <= 10)
1938
 
    {
1939
 
      sz = policies[adev->policy].sz;
1940
 
      maxfrags = policies[adev->policy].nfrags;
1941
 
      if (maxfrags == 0)        /* Unlimited */
1942
 
        maxfrags = 0xffff;
1943
 
    }
1944
 
 
1945
 
#if 1
1946
 
  /* Use short fragments if ossd has registered this device */
1947
 
  if (adev->ossd_registered)
1948
 
    sz = 256;
1949
 
#endif
1950
 
 
1951
 
  /* Sanity check */
1952
 
  if (adev->min_block && adev->max_block)
1953
 
    if (adev->min_block > adev->max_block)
1954
 
      adev->min_block = adev->max_block = 0;
1955
 
 
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;
1960
 
 
1961
 
  if (sz < 8)
1962
 
    sz = 8;
1963
 
 
1964
 
  /* Ensure that the interrupt rate is within the limits */
1965
 
 
1966
 
  min = 0;
1967
 
 
1968
 
  if (adev->max_intrate > 0)
1969
 
    {
1970
 
      int data_rate;
1971
 
 
1972
 
      data_rate = dmap->data_rate;
1973
 
      if (data_rate < 8000)
1974
 
        data_rate = adev->hw_parms.rate * 4;
1975
 
 
1976
 
      min = data_rate / adev->max_intrate;
1977
 
 
1978
 
      if (min > dmap->buffsize / 2)
1979
 
        min = dmap->buffsize / 2;
1980
 
#ifdef DO_TIMINGS
1981
 
        oss_timing_printf ("Max intrate %d -> min buffer %d", adev->max_intrate,
1982
 
                 min);
1983
 
#endif
1984
 
    }
1985
 
 
1986
 
#if 1
1987
 
  if (dmap->flags & DMAP_COOKED)
1988
 
    if (min < 256)
1989
 
      min = 256;
1990
 
#endif
1991
 
 
1992
 
  if (adev->max_block && min > adev->max_block)
1993
 
    min = adev->max_block;
1994
 
 
1995
 
  if (sz < min)
1996
 
    {
1997
 
      while (sz < min)
1998
 
        sz *= 2;
1999
 
      if (adev->max_block > 0 && sz > adev->max_block)
2000
 
        sz = adev->max_block;
2001
 
    }
2002
 
 
2003
 
  dmap->fragment_size = sz;
2004
 
  dmap->nfrags = dmap->buffsize / sz;
2005
 
 
2006
 
  if (dmap == adev->dmap_out)
2007
 
    {
2008
 
      if (direction == OPEN_WRITE)
2009
 
        {
2010
 
          if (dmap->nfrags > maxfrags)
2011
 
            dmap->nfrags = maxfrags;
2012
 
        }
2013
 
    }
2014
 
 
2015
 
  if (adev->d->adrv_setup_fragments)
2016
 
    {
2017
 
      adev->d->adrv_setup_fragments (adev->engine_num, dmap, direction);
2018
 
    }
2019
 
 
2020
 
  dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size;
2021
 
 
2022
 
  if (dmap->nfrags < 2)
2023
 
    {
2024
 
      dmap->nfrags = 2;
2025
 
      dmap->fragment_size = dmap->bytes_in_use / 2;
2026
 
    }
2027
 
 
2028
 
  while (dmap->nfrags < adev->min_fragments)
2029
 
    {
2030
 
      dmap->nfrags *= 2;
2031
 
      dmap->fragment_size /= 2;
2032
 
    }
2033
 
 
2034
 
  if (adev->max_fragments >= 2)
2035
 
    while (dmap->nfrags > adev->max_fragments)
2036
 
      {
2037
 
        dmap->nfrags /= 2;
2038
 
        dmap->fragment_size *= 2;
2039
 
      }
2040
 
  while (dmap->nfrags < adev->min_fragments)
2041
 
    {
2042
 
      dmap->nfrags *= 2;
2043
 
      dmap->fragment_size /= 2;
2044
 
    }
2045
 
 
2046
 
  dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size;
2047
 
 
2048
 
  dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size;
2049
 
  dmap->low_water_rq = dmap->fragment_size;
2050
 
 
2051
 
#if 1
2052
 
  if (dmap->nfrags < 4)
2053
 
#endif
2054
 
    if (dmap->low_water_rq < dmap->bytes_in_use / 4)
2055
 
      dmap->low_water_rq = dmap->bytes_in_use / 4;
2056
 
 
2057
 
#ifdef DO_TIMINGS
2058
 
    oss_timing_printf ("fragsz=%d, nfrags=%d", dmap->fragment_size, dmap->nfrags);
2059
 
#endif
2060
 
}
2061
 
 
2062
 
static int
2063
 
getblksize (adev_p adev)
2064
 
{
2065
 
  int size = 4096;
2066
 
  dmap_p dmap;
2067
 
  oss_native_word flags, dflags;
2068
 
  dflags = 0;
2069
 
 
2070
 
  MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
2071
 
  if (adev->dmask & DMASK_IN)
2072
 
    {
2073
 
      dmap = adev->dmap_in;
2074
 
 
2075
 
      if (!(dmap->flags & DMAP_FRAGFIXED))
2076
 
        {
2077
 
          MUTEX_ENTER (dmap->mutex, dflags);
2078
 
          setup_fragments (adev, dmap, OPEN_READ);
2079
 
          size = dmap->fragment_size;
2080
 
          MUTEX_EXIT (dmap->mutex, dflags);
2081
 
        }
2082
 
    }
2083
 
 
2084
 
  if (adev->dmask & DMASK_OUT)
2085
 
    {
2086
 
      dmap = adev->dmap_out;
2087
 
 
2088
 
      if (!(dmap->flags & DMAP_FRAGFIXED))
2089
 
        {
2090
 
          MUTEX_ENTER (dmap->mutex, dflags);
2091
 
          setup_fragments (adev, dmap, OPEN_WRITE);
2092
 
          size = dmap->fragment_size;
2093
 
          MUTEX_EXIT (dmap->mutex, dflags);
2094
 
        }
2095
 
    }
2096
 
  MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
2097
 
 
2098
 
  return size;
2099
 
}
2100
 
 
2101
 
/*ARGSUSED*/
2102
 
static oss_uint64_t
2103
 
get_output_pointer (adev_p adev, dmap_p dmap, int do_adjust)
2104
 
{
2105
 
  oss_uint64_t ptr;
2106
 
 
2107
 
  if (adev->d->adrv_get_output_pointer == NULL)
2108
 
    {
2109
 
      return dmap->fragment_counter * dmap->fragment_size;
2110
 
    }
2111
 
 
2112
 
  UP_STATUS (STS_PTR);
2113
 
  ptr =
2114
 
    adev->d->adrv_get_output_pointer (adev->engine_num, dmap,
2115
 
                                      PCM_ENABLE_OUTPUT) & ~7;
2116
 
  DOWN_STATUS (STS_PTR);
2117
 
 
2118
 
  return ptr;
2119
 
}
2120
 
 
2121
 
static oss_uint64_t
2122
 
get_input_pointer (adev_p adev, dmap_p dmap, int do_adjust)
2123
 
{
2124
 
  oss_uint64_t ptr;
2125
 
 
2126
 
  if (adev->d->adrv_get_input_pointer == NULL)
2127
 
    return dmap->fragment_counter * dmap->fragment_size;
2128
 
 
2129
 
  ptr =
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;
2135
 
 
2136
 
  if (do_adjust)
2137
 
    {
2138
 
      oss_uint64_t tmp = dmap->byte_counter;
2139
 
 
2140
 
      tmp = (tmp / dmap->bytes_in_use) * dmap->bytes_in_use;
2141
 
      dmap->byte_counter = tmp + ptr;
2142
 
    }
2143
 
 
2144
 
  return ptr;
2145
 
}
2146
 
 
2147
 
static int
2148
 
get_optr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2149
 
{
2150
 
  count_info *info = (count_info *) arg;
2151
 
  oss_native_word flags;
2152
 
  oss_uint64_t bytes;
2153
 
 
2154
 
  memset ((char *) info, 0, sizeof (count_info));
2155
 
 
2156
 
  if (dmap->dma_mode != PCM_ENABLE_OUTPUT || !(dmap->flags & DMAP_STARTED))
2157
 
    return 0;
2158
 
 
2159
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2160
 
 
2161
 
  info->ptr = get_output_pointer (adev, dmap, 1);
2162
 
  info->blocks = dmap->interrupt_count;
2163
 
  dmap->interrupt_count = 0;
2164
 
 
2165
 
  bytes = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2166
 
  bytes += info->ptr;
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);
2171
 
 
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;
2176
 
 
2177
 
#ifdef DO_TIMINGS
2178
 
    oss_timing_printf ("GETOPTR(%d,%d,%d)", info->bytes, info->ptr, info->blocks);
2179
 
#endif
2180
 
  return 0;
2181
 
}
2182
 
 
2183
 
static int
2184
 
get_iptr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2185
 
{
2186
 
  count_info *info = (count_info *) arg;
2187
 
  oss_native_word flags;
2188
 
  oss_uint64_t bytes;
2189
 
 
2190
 
  memset ((char *) info, 0, sizeof (count_info));
2191
 
 
2192
 
  if (dmap->dma_mode != PCM_ENABLE_INPUT || !(dmap->flags & DMAP_STARTED))
2193
 
    return 0;
2194
 
 
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;
2199
 
 
2200
 
  bytes = (dmap->byte_counter / dmap->bytes_in_use) * dmap->bytes_in_use;
2201
 
  bytes += info->ptr;
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);
2206
 
 
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;
2211
 
 
2212
 
#ifdef DO_TIMINGS
2213
 
    oss_timing_printf ("GETIPTR(%d,%d,%d)", info->bytes, info->ptr, info->blocks);
2214
 
#endif
2215
 
  return 0;
2216
 
}
2217
 
 
2218
 
#ifndef OSS_NO_LONG_LONG
2219
 
static int
2220
 
get_long_optr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2221
 
{
2222
 
  oss_count_t *ptr = (oss_count_t *) arg;
2223
 
  oss_native_word flags;
2224
 
  oss_uint64_t pos, bytes;
2225
 
 
2226
 
  memset ((char *) ptr, 0, sizeof (*ptr));
2227
 
 
2228
 
  if (dmap->dma_mode != PCM_ENABLE_OUTPUT || !(dmap->flags & DMAP_STARTED))
2229
 
    return 0;
2230
 
 
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;
2239
 
  bytes += pos;
2240
 
  ptr->samples = (unsigned int) (bytes / dmap->frame_size);
2241
 
 
2242
 
  /* Adjust for format conversions */
2243
 
  ptr->samples = (ptr->samples * UNIT_EXPAND) / dmap->expand_factor;
2244
 
 
2245
 
  if (adev->d->adrv_local_qlen)
2246
 
    {
2247
 
      ptr->fifo_samples =
2248
 
        adev->d->adrv_local_qlen (adev->engine_num) / dmap->frame_size;
2249
 
      ptr->fifo_samples =
2250
 
        (ptr->fifo_samples * UNIT_EXPAND) / dmap->expand_factor;
2251
 
    }
2252
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2253
 
 
2254
 
  return 0;
2255
 
}
2256
 
 
2257
 
static int
2258
 
get_long_iptr (adev_p adev, dmap_p dmap, ioctl_arg arg)
2259
 
{
2260
 
  oss_count_t *ptr = (oss_count_t *) arg;
2261
 
  oss_native_word flags;
2262
 
  oss_uint64_t pos, bytes;
2263
 
 
2264
 
  memset ((char *) ptr, 0, sizeof (*ptr));
2265
 
 
2266
 
  if (dmap->dma_mode != PCM_ENABLE_INPUT || !(dmap->flags & DMAP_STARTED))
2267
 
    return 0;
2268
 
 
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;
2277
 
  bytes += pos;
2278
 
  ptr->samples = (unsigned int) (bytes / dmap->frame_size);
2279
 
 
2280
 
  /* Adjust for format conversions */
2281
 
  ptr->samples = (ptr->samples / dmap->expand_factor) * UNIT_EXPAND;
2282
 
 
2283
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2284
 
 
2285
 
  return 0;
2286
 
}
2287
 
#endif
2288
 
 
2289
 
static int
2290
 
get_odelay (adev_p adev, dmap_p dmap, ioctl_arg arg)
2291
 
{
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))
2296
 
    return *arg = (0);
2297
 
 
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;
2301
 
  val += pos;
2302
 
  val = dmap->user_counter - val;
2303
 
  if (val < 0)
2304
 
    val = 0;
2305
 
  if (val > dmap->bytes_in_use)
2306
 
    val = dmap->bytes_in_use;
2307
 
 
2308
 
  if (adev->d->adrv_local_qlen)
2309
 
    {
2310
 
      val += adev->d->adrv_local_qlen (adev->engine_num);
2311
 
    }
2312
 
 
2313
 
  val += dmap->leftover_bytes;
2314
 
  val = (val * UNIT_EXPAND) / dmap->expand_factor;
2315
 
 
2316
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2317
 
#ifdef DO_TIMINGS
2318
 
    oss_timing_printf ("GETODELAY(%d, %d)", adev->engine_num, val);
2319
 
#endif
2320
 
  return *arg = (val);
2321
 
}
2322
 
 
2323
 
static int audio_space_in_queue (adev_p adev, dmap_p dmap, int count);
2324
 
 
2325
 
static int
2326
 
get_ospace (adev_p adev, dmap_p dmap, ioctl_arg arg)
2327
 
{
2328
 
  audio_buf_info *info = (audio_buf_info *) arg;
2329
 
  oss_native_word flags;
2330
 
 
2331
 
  memset ((char *) info, 0, sizeof (audio_buf_info));
2332
 
 
2333
 
  if (!(dmap->flags & DMAP_PREPARED))
2334
 
    {
2335
 
      setup_fragments (adev, dmap, OPEN_WRITE);
2336
 
      prepare_output (adev, dmap);
2337
 
    }
2338
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
2339
 
  info->fragstotal = dmap->nfrags;
2340
 
 
2341
 
  info->fragsize = (dmap->fragment_size * UNIT_EXPAND) / dmap->expand_factor;
2342
 
 
2343
 
  /* Make sure we report full samples */
2344
 
  info->fragsize =
2345
 
    ((info->fragsize + dmap->user_frame_size -
2346
 
      1) / dmap->user_frame_size) * dmap->user_frame_size;
2347
 
 
2348
 
  if (!(adev->open_mode & OPEN_WRITE))
2349
 
    {
2350
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2351
 
      cmn_err (CE_WARN,
2352
 
               "SNDCTL_DSP_GETOSPACE cannot be called in read-only mode.\n");
2353
 
#ifdef DO_TIMINGS
2354
 
      oss_do_timing ("GETOSPACE: Bad access mode - return EACCES");
2355
 
#endif
2356
 
      return OSS_EACCES;
2357
 
    }
2358
 
 
2359
 
  if (dmap->mapping_flags & DMA_MAP_MAPPED)
2360
 
    {
2361
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2362
 
      cmn_err (CE_WARN,
2363
 
               "SNDCTL_DSP_GETOSPACE cannot be called in mmap mode.\n");
2364
 
#ifdef DO_TIMINGS
2365
 
      oss_do_timing ("GETOSPACE: mmap access mode - return EPERM");
2366
 
#endif
2367
 
      oss_audio_set_error (adev->engine_num, E_PLAY,
2368
 
                           OSSERR (1000, "GETOSPACE called in mmap mode"), 0);
2369
 
      /* Errordesc:
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.
2375
 
       */
2376
 
      return OSS_EPERM;
2377
 
    }
2378
 
 
2379
 
  if (!(dmap->flags & DMAP_STARTED))
2380
 
    {
2381
 
      int bytes;
2382
 
      bytes = (int) ((long long) dmap->bytes_in_use - dmap->user_counter);
2383
 
#ifdef DO_TIMINGS
2384
 
      {
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);
2389
 
      }
2390
 
#endif
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;
2397
 
 
2398
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2399
 
      return 0;
2400
 
    }
2401
 
 
2402
 
  info->bytes = audio_space_in_queue (adev, dmap, 0);
2403
 
#ifdef DO_TIMINGS
2404
 
    oss_timing_printf ("audio_space_in_queue returned %d", info->bytes);
2405
 
#endif
2406
 
 
2407
 
  if (info->bytes < dmap->low_water)
2408
 
    info->bytes = 0;
2409
 
 
2410
 
  if (adev->dmap_out->flags & DMAP_COOKED)
2411
 
    {
2412
 
 
2413
 
      if (dmap->tmpbuf_ptr > 0)
2414
 
        info->bytes -= dmap->tmpbuf_ptr;
2415
 
    }
2416
 
 
2417
 
  if ((adev->dmap_out->flags & DMAP_COOKED) && info->bytes <
2418
 
      dmap->fragment_size / 2)
2419
 
    {
2420
 
#ifdef DO_TIMINGS
2421
 
      oss_do_timing ("GETOSPACE: Buffer full");
2422
 
#endif
2423
 
      info->bytes = 0;
2424
 
    }
2425
 
 
2426
 
  if (info->bytes < 0)
2427
 
    info->bytes = 0;
2428
 
 
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)
2432
 
    {
2433
 
      /*
2434
 
       * Reserve some space for format conversions. Sample rate conversions
2435
 
       * may not always be able to take the "last" sample with fractional conversion
2436
 
       * ratios.
2437
 
       */
2438
 
      if (info->bytes >= dmap->frame_size)
2439
 
        info->bytes -= dmap->frame_size;        /* Substract one sample. */
2440
 
    }
2441
 
  info->fragments = info->bytes / info->fragsize;
2442
 
 
2443
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2444
 
 
2445
 
  if (info->bytes > info->fragsize * info->fragstotal)
2446
 
    info->bytes = info->fragsize * info->fragstotal;
2447
 
 
2448
 
  return 0;
2449
 
}
2450
 
 
2451
 
static int
2452
 
get_ispace (adev_p adev, dmap_p dmap, ioctl_arg arg)
2453
 
{
2454
 
  audio_buf_info *info = (audio_buf_info *) arg;
2455
 
  oss_native_word flags;
2456
 
 
2457
 
  memset ((char *) info, 0, sizeof (audio_buf_info));
2458
 
 
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;
2464
 
 
2465
 
  /* Make sure we report full samples */
2466
 
  info->fragsize =
2467
 
    ((info->fragsize + dmap->user_frame_size -
2468
 
      1) / dmap->user_frame_size) * dmap->user_frame_size;
2469
 
 
2470
 
  if (!(adev->open_mode & OPEN_READ))
2471
 
    {
2472
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2473
 
      cmn_err (CE_WARN,
2474
 
               "SNDCTL_DSP_GETISPACE cannot be called in write-only mode.\n");
2475
 
      return OSS_EACCES;
2476
 
    }
2477
 
 
2478
 
  if (dmap->mapping_flags & DMA_MAP_MAPPED)
2479
 
    {
2480
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
2481
 
      cmn_err (CE_WARN,
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);
2485
 
      /* Errordesc:
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.
2491
 
       */
2492
 
      return OSS_EPERM;
2493
 
    }
2494
 
 
2495
 
  if (!(dmap->flags & DMAP_STARTED))
2496
 
    {
2497
 
/*
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.
2503
 
 */
2504
 
      info->bytes = info->fragsize;
2505
 
      info->fragments = 1;
2506
 
 
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 */
2511
 
        {
2512
 
          oss_audio_set_error (adev->engine_num, E_REC,
2513
 
                               OSSERR (1004,
2514
 
                                       "GETISPACE called before recording has been started"),
2515
 
                               0);
2516
 
          /*
2517
 
           * Errordesc:
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.
2523
 
           *
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.
2527
 
           *
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.
2531
 
           */
2532
 
        }
2533
 
      return 0;
2534
 
    }
2535
 
 
2536
 
  info->bytes = (unsigned int) (dmap->byte_counter - dmap->user_counter);
2537
 
 
2538
 
  if (dmap->flags & DMAP_COOKED)
2539
 
    {
2540
 
      /* Count the already converted bytes in the tmp buffer */
2541
 
      int nn = dmap->tmpbuf_len - dmap->tmpbuf_ptr;
2542
 
 
2543
 
      if (nn > 0)
2544
 
        info->bytes += nn;
2545
 
    }
2546
 
 
2547
 
  if (info->bytes > dmap->bytes_in_use)
2548
 
    info->bytes = dmap->bytes_in_use;
2549
 
 
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);
2554
 
 
2555
 
  if (info->bytes > info->fragsize * info->fragstotal)
2556
 
    info->bytes = info->fragsize * info->fragstotal;
2557
 
 
2558
 
#ifdef DO_TIMINGS
2559
 
    oss_timing_printf ("GETISPACE(%d,%d,%d,%d)", info->bytes, info->fragments,
2560
 
             info->fragsize, info->fragstotal);
2561
 
#endif
2562
 
  return 0;
2563
 
}
2564
 
 
2565
 
#define xrand(seed) (seed=1664525*seed+1013904223)
2566
 
 
2567
 
static void
2568
 
setfragment_error (int dev)
2569
 
{
2570
 
  if (audio_engines[dev]->setfragment_warned)
2571
 
    return;
2572
 
 
2573
 
  oss_audio_set_error (dev, E_PLAY,
2574
 
                       OSSERR (1011,
2575
 
                               "SNDCTL_DSP_SETFRAGMENT was called too late."),
2576
 
                       0);
2577
 
  /*
2578
 
   * Errordesc: The SNDCTL_DSP_SETFRAGMENT call is only valid immediately after
2579
 
   * opening the device. It can only be called once without reopening
2580
 
   * the audio device. 
2581
 
   *
2582
 
   * Calling read/write or certain ioctl calls will lock the fragment size/count
2583
 
   * to some values which makes changing it impossible.
2584
 
   */
2585
 
 
2586
 
#ifdef DO_TIMINGS
2587
 
  oss_do_timing ("Setfragment called twice");
2588
 
#endif
2589
 
 
2590
 
  audio_engines[dev]->setfragment_warned = 1;
2591
 
}
2592
 
 
2593
 
static int
2594
 
handle_syncgroup (adev_p adev, oss_syncgroup * group)
2595
 
{
2596
 
  int id, sync_dev;
2597
 
  adev_p sync_adev;
2598
 
 
2599
 
  if (adev->sync_group != 0)
2600
 
    {
2601
 
      return OSS_EBUSY;
2602
 
    }
2603
 
 
2604
 
  if (group->id == 0)
2605
 
    {
2606
 
      if (adev->engine_num > SYNC_DEVICE_MASK)
2607
 
        {
2608
 
          cmn_err (CE_WARN, "Bad device number %d\n", adev->engine_num);
2609
 
          return OSS_EIO;
2610
 
        }
2611
 
 
2612
 
      id = xrand (sync_seed) & ~SYNC_DEVICE_MASK; /* Clear the engine number field */
2613
 
      id |= adev->engine_num;
2614
 
 
2615
 
      group->id = id;
2616
 
      sync_dev = adev->engine_num;
2617
 
      adev->sync_next = NULL;
2618
 
    }
2619
 
  else
2620
 
    {
2621
 
      id = group->id;
2622
 
      sync_dev = id & SYNC_DEVICE_MASK;
2623
 
    }
2624
 
 
2625
 
  if (sync_dev < 0 || sync_dev >= num_audio_engines)
2626
 
    {
2627
 
      group->id = 0;
2628
 
      return OSS_EINVAL;
2629
 
    }
2630
 
 
2631
 
  sync_adev = audio_engines[sync_dev];
2632
 
 
2633
 
  if (sync_dev == adev->engine_num)
2634
 
    adev->sync_flags |= SYNC_MASTER;
2635
 
  else
2636
 
    {
2637
 
      if (!(sync_adev->sync_flags & SYNC_MASTER))
2638
 
        {
2639
 
          return OSS_EINVAL;
2640
 
        }
2641
 
 
2642
 
      if (sync_adev->sync_group != id)
2643
 
        {
2644
 
          return OSS_EINVAL;
2645
 
        }
2646
 
 
2647
 
      adev->sync_flags |= SYNC_SLAVE;
2648
 
    }
2649
 
 
2650
 
  group->mode &= (PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT);
2651
 
  group->mode &= adev->open_mode;
2652
 
  if (group->mode == 0)
2653
 
    {
2654
 
      adev->sync_flags = 0;
2655
 
      return OSS_EINVAL;
2656
 
    }
2657
 
 
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,
2662
 
                                adev->sync_mode);
2663
 
 
2664
 
  if (adev != sync_adev)
2665
 
    {
2666
 
      adev->sync_next = sync_adev->sync_next;
2667
 
      sync_adev->sync_next = adev;
2668
 
    }
2669
 
 
2670
 
  adev->go = 0;
2671
 
 
2672
 
  return 0;
2673
 
}
2674
 
 
2675
 
static int
2676
 
handle_syncstart (int orig_dev, int group)
2677
 
{
2678
 
  int master_dev, arg;
2679
 
  adev_p adev, next;
2680
 
 
2681
 
  master_dev = group & SYNC_DEVICE_MASK;
2682
 
  if (master_dev < 0 || master_dev >= num_audio_engines)
2683
 
    return OSS_EINVAL;
2684
 
 
2685
 
  adev = audio_engines[master_dev];
2686
 
 
2687
 
  if (!(adev->sync_flags & SYNC_MASTER) ||
2688
 
     master_dev != orig_dev)
2689
 
     {
2690
 
        /*
2691
 
         * Potential attack. SYNCSTART was called on wrong file descriptor.
2692
 
         */
2693
 
        return OSS_EPERM;
2694
 
     }
2695
 
 
2696
 
  if (adev->sync_group != group)
2697
 
    return OSS_EINVAL;
2698
 
 
2699
 
/*
2700
 
 * Pass 1: Inform all devices about the actual start command to come soon.
2701
 
 */
2702
 
 
2703
 
  while (adev != NULL)
2704
 
    {
2705
 
 
2706
 
      if (adev->sync_group == group)
2707
 
        {
2708
 
          adev->go = 0;
2709
 
 
2710
 
          if (adev->d->adrv_sync_control)
2711
 
            {
2712
 
              if (adev->sync_mode & PCM_ENABLE_INPUT)
2713
 
                {
2714
 
                  if (!(adev->dmap_in->flags & DMAP_PREPARED))
2715
 
                    {
2716
 
                      adev->dmap_in->dma_mode = PCM_ENABLE_INPUT;
2717
 
                      prepare_input (adev, adev->dmap_in);
2718
 
                    }
2719
 
                  launch_input (adev, adev->dmap_in);
2720
 
                }
2721
 
              if (adev->sync_mode & PCM_ENABLE_OUTPUT)
2722
 
                {
2723
 
                  dmap_p dmap = adev->dmap_out;
2724
 
                  int err;
2725
 
 
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)
2729
 
                    return err;
2730
 
                  launch_output (adev, adev->dmap_out);
2731
 
                }
2732
 
              adev->d->adrv_sync_control (adev->engine_num, SYNC_PREPARE,
2733
 
                                          adev->sync_mode);
2734
 
            }
2735
 
          else
2736
 
            {
2737
 
              arg = 0;
2738
 
              oss_audio_ioctl (adev->engine_num, NULL, SNDCTL_DSP_SETTRIGGER,
2739
 
                               (ioctl_arg) & arg);
2740
 
            }
2741
 
        }
2742
 
      else
2743
 
        {
2744
 
          cmn_err (CE_NOTE, "Broken sync chain\n");
2745
 
        }
2746
 
 
2747
 
      adev = adev->sync_next;
2748
 
    }
2749
 
 
2750
 
/*
2751
 
 * Pass 2: Deliver the actual start commands.
2752
 
 */
2753
 
 
2754
 
  adev = audio_engines[master_dev];
2755
 
 
2756
 
  while (adev != NULL)
2757
 
    {
2758
 
 
2759
 
      if (adev->sync_group == group)
2760
 
        {
2761
 
          adev->go = 1;
2762
 
 
2763
 
          if (adev->d->adrv_sync_control)
2764
 
            adev->d->adrv_sync_control (adev->engine_num, SYNC_TRIGGER,
2765
 
                                        adev->sync_mode);
2766
 
          else
2767
 
            {
2768
 
              arg = adev->sync_mode;
2769
 
              oss_audio_ioctl (adev->engine_num, NULL, SNDCTL_DSP_SETTRIGGER,
2770
 
                               (ioctl_arg) & arg);
2771
 
            }
2772
 
        }
2773
 
      else
2774
 
        {
2775
 
          /* Skip this one */
2776
 
          adev = adev->sync_next;
2777
 
          continue;
2778
 
        }
2779
 
 
2780
 
      next = adev->sync_next;
2781
 
      adev->sync_next = NULL;
2782
 
      adev->sync_flags = 0;
2783
 
      adev->sync_group = 0;
2784
 
 
2785
 
      adev = next;
2786
 
    }
2787
 
  return 0;
2788
 
}
2789
 
 
2790
 
#ifdef DO_TIMINGS
2791
 
static char *
2792
 
find_ioctl_name (unsigned int cmd, ioctl_arg val)
2793
 
{
2794
 
  static char tmp[32];
2795
 
 
2796
 
  typedef struct
2797
 
  {
2798
 
    unsigned int code;
2799
 
    char *name;
2800
 
    int flags;
2801
 
#define IOF_DEC         0x00000001
2802
 
#define IOF_HEX         0x00000002
2803
 
  } ioctl_def_t;
2804
 
 
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"},
2847
 
#endif
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"},
2854
 
    {0, NULL}
2855
 
  };
2856
 
 
2857
 
  int i;
2858
 
  for (i = 0; call_names[i].code != 0; i++)
2859
 
    if (call_names[i].code == cmd)
2860
 
      {
2861
 
        int flags = call_names[i].flags;
2862
 
 
2863
 
        if (flags & IOF_DEC)
2864
 
          {
2865
 
            sprintf (tmp, "%s,  *%d", call_names[i].name, *val);
2866
 
            return tmp;
2867
 
          }
2868
 
 
2869
 
        if (flags & IOF_HEX)
2870
 
          {
2871
 
            sprintf (tmp, "%s, *0x%08x", call_names[i].name, *val);
2872
 
            return tmp;
2873
 
          }
2874
 
 
2875
 
        return call_names[i].name;
2876
 
      }
2877
 
 
2878
 
  sprintf (tmp, "Unknown %08x", cmd);
2879
 
  return tmp;
2880
 
}
2881
 
#endif
2882
 
 
2883
 
/*ARGSUSED*/
2884
 
int
2885
 
oss_encode_enum (oss_mixer_enuminfo * ei, const char *s, int version)
2886
 
{
2887
 
  int n = 1, l;
2888
 
  int i;
2889
 
 
2890
 
  memset (ei, 0, sizeof (*ei)); /* Wipe out everything */
2891
 
 
2892
 
  strncpy (ei->strings, s, sizeof (ei->strings) - 1);
2893
 
  ei->strings[sizeof (ei->strings) - 1] = 0;
2894
 
 
2895
 
  ei->strindex[0] = 0;
2896
 
 
2897
 
  l = strlen (ei->strings);
2898
 
  for (i = 0; i < l; i++)
2899
 
    {
2900
 
      if (ei->strings[i] == ' ')
2901
 
        {
2902
 
          ei->strindex[n++] = i + 1;
2903
 
          ei->strings[i] = 0;
2904
 
        }
2905
 
    }
2906
 
 
2907
 
  ei->nvalues = n;
2908
 
 
2909
 
  return 0;
2910
 
}
2911
 
 
2912
 
static int
2913
 
get_legacy_recsrc_names (int dev, oss_mixer_enuminfo * ei)
2914
 
{
2915
 
  static const char *labels[] = SOUND_DEVICE_NAMES;
2916
 
 
2917
 
  int i, mixer_dev, recmask, devmask, caps, n;
2918
 
  char *s;
2919
 
 
2920
 
  if (audio_engines[dev]->mixer_dev < 0)        /* No mixer */
2921
 
    return 0;
2922
 
 
2923
 
  mixer_dev = audio_engines[dev]->mixer_dev;
2924
 
 
2925
 
 
2926
 
  if (oss_legacy_mixer_ioctl
2927
 
      (mixer_dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
2928
 
    caps = 0;                   /* Error */
2929
 
 
2930
 
  if (caps & SOUND_CAP_NORECSRC)
2931
 
    return 0;
2932
 
 
2933
 
  if (oss_legacy_mixer_ioctl
2934
 
      (mixer_dev, -1, SOUND_MIXER_READ_DEVMASK, (ioctl_arg) & devmask) < 0)
2935
 
    return 0;                   /* Error */
2936
 
 
2937
 
  if (oss_legacy_mixer_ioctl
2938
 
      (mixer_dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
2939
 
    return 0;                   /* Error */
2940
 
 
2941
 
  recmask &= devmask;
2942
 
  if (recmask == 0)
2943
 
    return 0;
2944
 
 
2945
 
  n = 0;
2946
 
  s = ei->strings;
2947
 
 
2948
 
  for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
2949
 
    if (recmask & (1 << i))     /* This control is also recording device */
2950
 
      {
2951
 
         /*LINTED*/ ei->strindex[n] = s - ei->strings;
2952
 
 
2953
 
        strcpy (s, labels[i]);
2954
 
        s += strlen (s);
2955
 
        *s++ = 0;
2956
 
        n++;
2957
 
      }
2958
 
 
2959
 
  ei->nvalues = n;
2960
 
 
2961
 
  return (n > 0);
2962
 
}
2963
 
 
2964
 
static int
2965
 
get_legacy_recsrc (int dev)
2966
 
{
2967
 
  int i, mixer_dev, recmask, recsrc, caps, n;
2968
 
 
2969
 
  if (audio_engines[dev]->mixer_dev < 0)        /* No mixer */
2970
 
    return 0;
2971
 
 
2972
 
  mixer_dev = audio_engines[dev]->mixer_dev;
2973
 
 
2974
 
 
2975
 
  if (oss_legacy_mixer_ioctl
2976
 
      (mixer_dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
2977
 
    caps = 0;                   /* Error */
2978
 
 
2979
 
  if (caps & SOUND_CAP_NORECSRC)
2980
 
    return 0;
2981
 
 
2982
 
  if (oss_legacy_mixer_ioctl
2983
 
      (mixer_dev, -1, SOUND_MIXER_READ_RECSRC, (ioctl_arg) & recsrc) < 0)
2984
 
    return 0;                   /* Error */
2985
 
 
2986
 
  if (oss_legacy_mixer_ioctl
2987
 
      (mixer_dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
2988
 
    return 0;                   /* Error */
2989
 
 
2990
 
  if (recmask == 0 || recsrc == 0)
2991
 
    return 0;
2992
 
 
2993
 
  n = 0;
2994
 
 
2995
 
  for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
2996
 
    if (recmask & (1 << i))     /* This control is also recording device */
2997
 
      {
2998
 
        if (recsrc & (1 << i))  /* It was this one */
2999
 
          return n;
3000
 
        n++;
3001
 
      }
3002
 
 
3003
 
 
3004
 
  return 0;
3005
 
}
3006
 
 
3007
 
static int
3008
 
set_legacy_recsrc (int dev, int val)
3009
 
{
3010
 
  int i, mixer_dev, recmask, recsrc, caps, n;
3011
 
 
3012
 
  if (audio_engines[dev]->mixer_dev < 0)        /* No mixer */
3013
 
    return 0;
3014
 
 
3015
 
  mixer_dev = audio_engines[dev]->mixer_dev;
3016
 
 
3017
 
 
3018
 
  if (oss_legacy_mixer_ioctl
3019
 
      (mixer_dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
3020
 
    caps = 0;                   /* Error */
3021
 
 
3022
 
  if (caps & SOUND_CAP_NORECSRC)
3023
 
    return 0;
3024
 
 
3025
 
  if (oss_legacy_mixer_ioctl
3026
 
      (mixer_dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
3027
 
    return 0;                   /* Error */
3028
 
 
3029
 
  if (recmask == 0)
3030
 
    return 0;
3031
 
 
3032
 
  n = 0;
3033
 
 
3034
 
  for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
3035
 
    if (recmask & (1 << i))     /* This control is also recording device */
3036
 
      {
3037
 
        if (n == val)
3038
 
          {
3039
 
            recsrc = (1 << i);
3040
 
 
3041
 
            if (oss_legacy_mixer_ioctl
3042
 
                (mixer_dev, -1, SOUND_MIXER_WRITE_RECSRC,
3043
 
                 (ioctl_arg) & recsrc) < 0)
3044
 
              return 0;         /* Error */
3045
 
 
3046
 
            return 1;
3047
 
          }
3048
 
        n++;
3049
 
      }
3050
 
 
3051
 
 
3052
 
  return 0;
3053
 
}
3054
 
 
3055
 
/*ARGSUSED*/
3056
 
int
3057
 
oss_audio_ioctl (int dev, struct fileinfo *bogus,
3058
 
                 unsigned int cmd, ioctl_arg arg)
3059
 
{
3060
 
  int val, err;
3061
 
  int mixdev;
3062
 
  int ret;
3063
 
  adev_p adev;
3064
 
  dmap_p dmapin, dmapout;
3065
 
  oss_native_word flags;
3066
 
#ifdef DO_TIMINGS
3067
 
  oss_timing_printf ("oss_audio_ioctl(%d, %s)", dev, find_ioctl_name (cmd, arg));
3068
 
#endif
3069
 
 
3070
 
  if (cmd == OSS_GETVERSION)
3071
 
    return *arg = OSS_VERSION;
3072
 
 
3073
 
  UP_STATUS (STS_IOCTL);
3074
 
  DOWN_STATUS (STS_IOCTL);
3075
 
  sync_seed++;
3076
 
 
3077
 
  if (dev < 0 || dev >= num_audio_engines)
3078
 
    return OSS_ENXIO;
3079
 
 
3080
 
  adev = audio_engines[dev];
3081
 
  if (adev->unloaded)
3082
 
    return OSS_ENODEV;
3083
 
  if (!adev->enabled)
3084
 
    return OSS_ENXIO;
3085
 
 
3086
 
  if (adev->d->adrv_ioctl_override != NULL)
3087
 
  {
3088
 
  /*
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
3092
 
   * before returning.
3093
 
   */
3094
 
          if ((err = adev->d->adrv_ioctl_override(dev, cmd, arg)) != OSS_EAGAIN)
3095
 
             return err;
3096
 
  }
3097
 
 
3098
 
  dmapout = adev->dmap_out;
3099
 
  dmapin = adev->dmap_in;
3100
 
 
3101
 
/*
3102
 
 * Handle mixer ioctl calls on audio fd.
3103
 
 */
3104
 
 
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;
3109
 
 
3110
 
  if ((mixdev = adev->mixer_dev) != -1)
3111
 
    {
3112
 
      if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0) /* Mixer ioctl */
3113
 
        if ((ret = oss_legacy_mixer_ioctl (mixdev, dev, cmd, arg)) != OSS_EINVAL)
3114
 
          return ret;
3115
 
    }
3116
 
 
3117
 
  if (((cmd >> 8) & 0xff) == 'X')       /* Mixer extension API */
3118
 
     return oss_mixer_ext (adev->engine_num, OSS_DEV_DSP, cmd, arg);
3119
 
 
3120
 
  switch (cmd)
3121
 
    {
3122
 
    case SNDCTL_DSP_SYNC:
3123
 
      oss_audio_sync (adev);
3124
 
      return 0;
3125
 
      break;
3126
 
 
3127
 
    case SNDCTL_DSP_POST:
3128
 
      oss_audio_post (adev);
3129
 
      return 0;
3130
 
      break;
3131
 
 
3132
 
    case SNDCTL_DSP_HALT:
3133
 
      audio_reset_adev (adev);
3134
 
      return 0;
3135
 
      break;
3136
 
 
3137
 
    case SNDCTL_DSP_HALT_INPUT:
3138
 
      audio_reset_input (adev);
3139
 
      return 0;
3140
 
      break;
3141
 
 
3142
 
    case SNDCTL_DSP_LOW_WATER:
3143
 
      val = *arg;
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;
3148
 
      return 0;
3149
 
      break;
3150
 
 
3151
 
    case SNDCTL_DSP_HALT_OUTPUT:
3152
 
      audio_reset_output (adev);
3153
 
      return 0;
3154
 
      break;
3155
 
 
3156
 
    case SNDCTL_DSP_GETFMTS:
3157
 
      switch (adev->open_mode & (OPEN_READ | OPEN_WRITE))
3158
 
        {
3159
 
        case OPEN_WRITE:
3160
 
          return *arg = (adev->oformat_mask);
3161
 
          break;
3162
 
 
3163
 
        case OPEN_READ:
3164
 
          return *arg = (adev->oformat_mask);
3165
 
          break;
3166
 
 
3167
 
        default:
3168
 
          return *arg = (adev->xformat_mask);
3169
 
          break;
3170
 
        }
3171
 
      break;
3172
 
 
3173
 
    case SNDCTL_DSP_SETFMT:
3174
 
      val = *arg;
3175
 
      switch (adev->open_mode & (OPEN_READ | OPEN_WRITE))
3176
 
        {
3177
 
        case OPEN_WRITE:
3178
 
          return *arg = (oss_audio_set_format (dev, val,
3179
 
                                               audio_engines
3180
 
                                               [dev]->oformat_mask));
3181
 
          break;
3182
 
 
3183
 
        case OPEN_READ:
3184
 
          return *arg = (oss_audio_set_format (dev, val,
3185
 
                                               audio_engines
3186
 
                                               [dev]->iformat_mask));
3187
 
          break;
3188
 
 
3189
 
        default:
3190
 
          return *arg = (oss_audio_set_format (dev, val,
3191
 
                                               audio_engines
3192
 
                                               [dev]->oformat_mask &
3193
 
                                               audio_engines
3194
 
                                               [dev]->iformat_mask));
3195
 
          break;
3196
 
        }
3197
 
 
3198
 
    case SNDCTL_DSP_GETOSPACE:
3199
 
      if (!(adev->dmask & DMASK_OUT))
3200
 
        {
3201
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
3202
 
                               OSSERR (1001,
3203
 
                                       "GETOSPACE called in read-only mode"),
3204
 
                               0);
3205
 
          /* Errordesc: SNDCTL_DSP_GETOSPACE is not defined in read-only access mode */
3206
 
          return OSS_ENOTSUP;
3207
 
        }
3208
 
      ret = get_ospace (adev, dmapout, arg);
3209
 
#ifdef DO_TIMINGS
3210
 
      {
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);
3217
 
      }
3218
 
#endif
3219
 
      return ret;
3220
 
      break;
3221
 
 
3222
 
    case SNDCTL_DSP_GETISPACE:
3223
 
      if (!(adev->dmask & DMASK_IN))
3224
 
        {
3225
 
          oss_audio_set_error (adev->engine_num, E_REC,
3226
 
                               OSSERR (1002,
3227
 
                                       "GETISPACE called in write-only mode"),
3228
 
                               0);
3229
 
          /*
3230
 
           * Errordesc: SNDCTL_DSP_GETISPACE has no defined meaning when the audio
3231
 
           * device is opened in write-only mode.
3232
 
           */
3233
 
          return OSS_ENOTSUP;
3234
 
        }
3235
 
 
3236
 
      return get_ispace (adev, dmapin, arg);
3237
 
      break;
3238
 
 
3239
 
    case SNDCTL_DSP_GETODELAY:
3240
 
      if (!(adev->dmask & DMASK_OUT))
3241
 
        {
3242
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
3243
 
                               OSSERR (1005,
3244
 
                                       "GETODELAY called in read-only mode"),
3245
 
                               0);
3246
 
          return OSS_ENOTSUP;
3247
 
        }
3248
 
      return get_odelay (adev, dmapout, arg);
3249
 
      break;
3250
 
 
3251
 
    case SNDCTL_DSP_SETDUPLEX:
3252
 
      /*
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
3255
 
       *       future.
3256
 
       */
3257
 
      if (adev->open_mode != OPEN_READWRITE)
3258
 
        {
3259
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
3260
 
                               OSSERR (1006,
3261
 
                                       "SETDUPLEX called in non-read/write mode"),
3262
 
                               0);
3263
 
          return OSS_ENOTSUP;
3264
 
        }
3265
 
      if (adev->flags & ADEV_DUPLEX)
3266
 
        {
3267
 
          if (adev->d->adrv_ioctl == NULL)
3268
 
            return 0;
3269
 
          val = adev->d->adrv_ioctl (dev, cmd, arg);
3270
 
          if (val == OSS_EINVAL)
3271
 
            return 0;
3272
 
          else
3273
 
            return val;
3274
 
        }
3275
 
      else
3276
 
        {
3277
 
          return OSS_ENOTSUP;
3278
 
        }
3279
 
      break;
3280
 
 
3281
 
    case SNDCTL_DSP_COOKEDMODE:
3282
 
      val = *arg;
3283
 
 
3284
 
      if (adev->flags & ADEV_NONINTERLEAVED)
3285
 
         val=1;
3286
 
 
3287
 
      adev->cooked_enable = !!val;
3288
 
      if (adev->d->adrv_ioctl != NULL)
3289
 
        adev->d->adrv_ioctl (dev, cmd, arg);
3290
 
#ifdef DO_TIMINGS
3291
 
      if (adev->cooked_enable)
3292
 
        oss_do_timing ("Setting cooked mode ON");
3293
 
      else
3294
 
        oss_do_timing ("Setting cooked mode OFF");
3295
 
#endif
3296
 
      return 0;
3297
 
      break;
3298
 
 
3299
 
    case SNDCTL_DSP_GETCAPS:
3300
 
      {
3301
 
        int info;
3302
 
        info = audio_engines[dev]->caps;
3303
 
        info |= 2;              /* Revision level of this ioctl() */
3304
 
 
3305
 
#if 0
3306
 
        if (!(adev->flags & ADEV_VIRTUAL) && !adev->d->adrv_local_qlen)
3307
 
#endif
3308
 
          info |= PCM_CAP_REALTIME;
3309
 
 
3310
 
 
3311
 
        if (!(adev->flags & ADEV_NOINPUT))
3312
 
          info |= PCM_CAP_INPUT;
3313
 
 
3314
 
        if (!(adev->flags & ADEV_NOOUTPUT))
3315
 
          info |= PCM_CAP_OUTPUT;
3316
 
 
3317
 
        if ((adev->flags & ADEV_VIRTUAL))
3318
 
          info |= PCM_CAP_VIRTUAL;
3319
 
 
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;
3323
 
 
3324
 
        if (dev > 0)
3325
 
          if (adev->flags & ADEV_SPECIAL)
3326
 
            info |= PCM_CAP_SPECIAL;
3327
 
 
3328
 
        if (dev < num_audio_engines - 1)
3329
 
          {
3330
 
            if (audio_engines[dev + 1]->flags & ADEV_SHADOW)
3331
 
              info |= PCM_CAP_MULTI;
3332
 
          }
3333
 
 
3334
 
        if (adev->d->adrv_local_qlen)   /* Device has hidden buffers */
3335
 
          info |= PCM_CAP_BATCH;
3336
 
 
3337
 
        if (adev->d->adrv_trigger)      /* Supports SETTRIGGER */
3338
 
          info |= PCM_CAP_TRIGGER;
3339
 
 
3340
 
#ifdef ALLOW_BUFFER_MAPPING
3341
 
        info |= PCM_CAP_MMAP;
3342
 
#endif
3343
 
        if (!(adev->flags & ADEV_NOINPUT))
3344
 
          info |= PCM_CAP_INPUT;
3345
 
 
3346
 
        if (!(adev->flags & ADEV_NOOUTPUT))
3347
 
          info |= PCM_CAP_OUTPUT;
3348
 
 
3349
 
        if (adev->d->adrv_bind != NULL)
3350
 
          info |= PCM_CAP_BIND;
3351
 
        /*
3352
 
         * TODO: ADEV_DEFAULT is not the right way to find out 
3353
 
         * PCM_CAP_DEFAULT devices. A new ADEV_ flag should be defined
3354
 
         * for this purpose.
3355
 
         */
3356
 
        if (adev->flags & ADEV_DEFAULT)
3357
 
          info |= PCM_CAP_DEFAULT;
3358
 
 
3359
 
        return *arg = (info);
3360
 
      }
3361
 
      break;
3362
 
 
3363
 
    case SNDCTL_DSP_NONBLOCK:
3364
 
      adev->forced_nonblock = 1;
3365
 
      return 0;
3366
 
      break;
3367
 
 
3368
 
    case SNDCTL_DSP_GETCHANNELMASK:
3369
 
    case SNDCTL_DSP_BIND_CHANNEL:
3370
 
      if (adev->d->adrv_bind == NULL)
3371
 
        return OSS_EINVAL;
3372
 
      return adev->d->adrv_bind (adev->engine_num, cmd, arg);
3373
 
      break;
3374
 
 
3375
 
    case SNDCTL_DSP_SETTRIGGER:
3376
 
      {
3377
 
        int val;
3378
 
 
3379
 
        if (!adev->d->adrv_trigger)
3380
 
          {
3381
 
            cmn_err (CE_NOTE, "Device %d doesn't have trigger capability\n",
3382
 
                     adev->engine_num);
3383
 
            return OSS_EIO;
3384
 
          }
3385
 
 
3386
 
        val = *arg;
3387
 
        val &= PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
3388
 
        val &= adev->open_mode;
3389
 
 
3390
 
        if ((val & adev->open_mode) != (adev->enable_bits & adev->open_mode))
3391
 
          {
3392
 
            if ((val & PCM_ENABLE_OUTPUT)
3393
 
                && !(adev->enable_bits & PCM_ENABLE_OUTPUT))
3394
 
              {
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)
3400
 
                  return err;
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);
3406
 
              }
3407
 
 
3408
 
            if ((val & PCM_ENABLE_INPUT)
3409
 
                && !(adev->enable_bits & PCM_ENABLE_INPUT))
3410
 
              {
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)
3417
 
                  return err;
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);
3423
 
              }
3424
 
 
3425
 
            adev->enable_bits = val;
3426
 
            if (adev->enable_bits == 0 || adev->go)     /* Device is enabled */
3427
 
              {
3428
 
                adev->d->adrv_trigger (adev->engine_num, adev->enable_bits);
3429
 
              }
3430
 
          }
3431
 
        *arg = val;
3432
 
        return 0;
3433
 
      }
3434
 
      break;
3435
 
 
3436
 
    case SNDCTL_DSP_GETTRIGGER:
3437
 
      if (!adev->d->adrv_trigger)
3438
 
        {
3439
 
          cmn_err (CE_NOTE, "Device %d doesn't have trigger capability\n",
3440
 
                   adev->engine_num);
3441
 
          return OSS_EIO;
3442
 
        }
3443
 
      return *arg = (adev->enable_bits & adev->open_mode);
3444
 
      break;
3445
 
 
3446
 
    case SNDCTL_DSP_SETSYNCRO:
3447
 
      adev->go = 0;
3448
 
      break;
3449
 
 
3450
 
    case SNDCTL_DSP_SYNCGROUP:
3451
 
      return handle_syncgroup (adev, (oss_syncgroup *) arg);
3452
 
      break;
3453
 
 
3454
 
    case SNDCTL_DSP_SYNCSTART:
3455
 
      val = *arg;
3456
 
 
3457
 
      MUTEX_ENTER_IRQDISABLE (audio_global_mutex, flags);
3458
 
      ret = handle_syncstart (adev->engine_num, val);
3459
 
      MUTEX_EXIT_IRQRESTORE (audio_global_mutex, flags);
3460
 
 
3461
 
      return ret;
3462
 
      break;
3463
 
 
3464
 
    case SNDCTL_DSP_GETERROR:
3465
 
      {
3466
 
        audio_errinfo *info = (audio_errinfo *) arg;
3467
 
 
3468
 
        memset ((void *) info, 0, sizeof (*info));
3469
 
 
3470
 
        //if (audio_engines[dev]->open_mode & OPEN_READ)
3471
 
        {
3472
 
          dmap_t *dmap = audio_engines[dev]->dmap_in;
3473
 
 
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];
3480
 
        }
3481
 
 
3482
 
        //if (audio_engines[dev]->open_mode & OPEN_WRITE)
3483
 
        {
3484
 
          dmap_t *dmap = audio_engines[dev]->dmap_out;
3485
 
 
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];
3492
 
        }
3493
 
 
3494
 
        return 0;
3495
 
      }
3496
 
      break;
3497
 
 
3498
 
    case SNDCTL_DSP_GETPLAYVOL:
3499
 
    case SNDCTL_DSP_SETPLAYVOL:
3500
 
      {
3501
 
        int err, mixdev;
3502
 
 
3503
 
        mixdev = adev->mixer_dev;
3504
 
        if (cmd == SNDCTL_DSP_SETPLAYVOL && mixdev >= 0
3505
 
            && mixdev < num_mixers)
3506
 
          mixer_devs[mixdev]->modify_counter++;
3507
 
 
3508
 
        if (adev->d->adrv_ioctl == NULL
3509
 
            || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL)
3510
 
          {
3511
 
            /* Emulate these calls using mixer API */
3512
 
 
3513
 
            if (mixdev < 0 || mixdev >= num_mixers)
3514
 
              return OSS_EINVAL;
3515
 
 
3516
 
            if (cmd == SNDCTL_DSP_GETPLAYVOL)
3517
 
              cmd = SOUND_MIXER_READ_PCM;
3518
 
            else
3519
 
              cmd = SOUND_MIXER_WRITE_PCM;
3520
 
            return mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3521
 
          }
3522
 
        return err;
3523
 
      }
3524
 
      break;
3525
 
 
3526
 
    case SNDCTL_DSP_GETRECVOL:
3527
 
    case SNDCTL_DSP_SETRECVOL:
3528
 
      {
3529
 
        int err, mixdev;
3530
 
 
3531
 
        mixdev = adev->mixer_dev;
3532
 
        if (cmd == SNDCTL_DSP_SETRECVOL && mixdev >= 0 && mixdev < num_mixers)
3533
 
          mixer_devs[mixdev]->modify_counter++;
3534
 
 
3535
 
        if (adev->d->adrv_ioctl == NULL
3536
 
            || (err = adev->d->adrv_ioctl (dev, cmd, arg)) == OSS_EINVAL)
3537
 
          {
3538
 
            /* Emulate these calls using mixer API */
3539
 
 
3540
 
            if (mixdev < 0 || mixdev >= num_mixers)
3541
 
              return OSS_EINVAL;
3542
 
 
3543
 
            /* Try with RECGAIN */
3544
 
            if (cmd == SNDCTL_DSP_GETRECVOL)
3545
 
              cmd = SOUND_MIXER_READ_RECGAIN;
3546
 
            else
3547
 
              cmd = SOUND_MIXER_WRITE_RECGAIN;
3548
 
            err = mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3549
 
 
3550
 
            /* Try with RECLEV */
3551
 
            if (cmd == SNDCTL_DSP_GETRECVOL)
3552
 
              cmd = SOUND_MIXER_READ_RECLEV;
3553
 
            else
3554
 
              cmd = SOUND_MIXER_WRITE_RECLEV;
3555
 
            err = mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3556
 
 
3557
 
            if (err >= 0)       /* Was OK */
3558
 
              return err;
3559
 
 
3560
 
            /* Try with IGAIN */
3561
 
            if (cmd == SNDCTL_DSP_GETRECVOL)
3562
 
              cmd = SOUND_MIXER_READ_IGAIN;
3563
 
            else
3564
 
              cmd = SOUND_MIXER_WRITE_IGAIN;
3565
 
            return mixer_devs[mixdev]->d->ioctl (mixdev, dev, cmd, arg);
3566
 
          }
3567
 
        return err;
3568
 
      }
3569
 
      break;
3570
 
 
3571
 
    case SNDCTL_DSP_GETOPTR:
3572
 
      if (!(adev->dmask & DMASK_OUT))
3573
 
        {
3574
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
3575
 
                               OSSERR (1007,
3576
 
                                       "GETOPTR called in read-only mode"),
3577
 
                               0);
3578
 
          return OSS_ENOTSUP;
3579
 
        }
3580
 
      return get_optr (adev, dmapout, arg);
3581
 
      break;
3582
 
 
3583
 
    case SNDCTL_DSP_GETIPTR:
3584
 
      if (!(adev->dmask & DMASK_IN))
3585
 
        {
3586
 
          oss_audio_set_error (adev->engine_num, E_REC,
3587
 
                               OSSERR (1008,
3588
 
                                       "GETIPTR called in write-only mode"),
3589
 
                               0);
3590
 
          return OSS_ENOTSUP;
3591
 
        }
3592
 
      return get_iptr (adev, dmapin, arg);
3593
 
      break;
3594
 
 
3595
 
#ifndef OSS_NO_LONG_LONG
3596
 
    case SNDCTL_DSP_CURRENT_OPTR:
3597
 
      if (!(adev->dmask & DMASK_OUT))
3598
 
        return OSS_ENOTSUP;
3599
 
      return get_long_optr (adev, dmapout, arg);
3600
 
      break;
3601
 
 
3602
 
    case SNDCTL_DSP_CURRENT_IPTR:
3603
 
      if (!(adev->dmask & DMASK_IN))
3604
 
        return OSS_ENOTSUP;
3605
 
      return get_long_iptr (adev, dmapin, arg);
3606
 
      break;
3607
 
#endif
3608
 
 
3609
 
    case SNDCTL_DSP_POLICY:
3610
 
      val = *arg;
3611
 
      if (val < 0 || val > 10)
3612
 
        return OSS_EIO;
3613
 
      adev->policy = val;
3614
 
      return 0;
3615
 
      break;
3616
 
 
3617
 
    case SNDCTL_DSP_SETFRAGMENT:
3618
 
    case SNDCTL_DSP_SUBDIVIDE:
3619
 
      if (cmd == SNDCTL_DSP_SUBDIVIDE)
3620
 
        {
3621
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
3622
 
                               OSSERR (1010,
3623
 
                                       "SNDCTL_DSP_SUBDIVIDE is obsolete"),
3624
 
                               0);
3625
 
          /*
3626
 
           * Errordesc:
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
3629
 
           * instead.
3630
 
           */
3631
 
          *arg = 0x00040008;    /* Default to 4 fragments of 256 bytes */
3632
 
        }
3633
 
 
3634
 
      val = *arg;
3635
 
      if (adev->dmask & DMASK_OUT)
3636
 
        {
3637
 
          if (dmapout->flags & DMAP_FRAGFIXED)
3638
 
            setfragment_error (dev);
3639
 
          dmapout->fragsize_rq = val;
3640
 
        }
3641
 
      if (adev->dmask & DMASK_IN)
3642
 
        {
3643
 
          if (dmapin->flags & DMAP_FRAGFIXED)
3644
 
            setfragment_error (dev);
3645
 
          dmapin->fragsize_rq = val;
3646
 
        }
3647
 
      return 0;
3648
 
 
3649
 
#ifdef __FreeBSD__
3650
 
    case FREEBSD_GETBLKSIZE:
3651
 
#endif
3652
 
    case SNDCTL_DSP_GETBLKSIZE:
3653
 
      return *arg = getblksize (adev);
3654
 
 
3655
 
    case SNDCTL_DSP_SPEED:
3656
 
      val = *arg;
3657
 
      if (val<0)
3658
 
         return OSS_EINVAL;
3659
 
      return *arg = (oss_audio_set_rate (dev, val));
3660
 
 
3661
 
    case SNDCTL_DSP_STEREO:
3662
 
      {
3663
 
        int n, v;
3664
 
 
3665
 
        n = *arg;
3666
 
        if (n > 1)
3667
 
          {
3668
 
            oss_audio_set_error (adev->engine_num, E_PLAY,
3669
 
                                 OSSERR (1009,
3670
 
                                         "SNDCTL_DSP_STEREO called with bad agrument value"),
3671
 
                                 n);
3672
 
            /*
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.
3676
 
             */
3677
 
            return OSS_EINVAL;
3678
 
          }
3679
 
 
3680
 
        if (n < 0)
3681
 
          return OSS_EINVAL;
3682
 
 
3683
 
        v = oss_audio_set_channels (dev, n + 1);
3684
 
        return *arg = (v - 1);
3685
 
      }
3686
 
 
3687
 
    case SNDCTL_DSP_CHANNELS:
3688
 
      {
3689
 
        int v;
3690
 
        val = *arg;
3691
 
#ifdef DO_TIMINGS
3692
 
        {
3693
 
          char tmp[128];
3694
 
 
3695
 
          sprintf (tmp, "Set channels %d", (int) val);
3696
 
          oss_do_timing2 (DFLAG_PROFILE, tmp);
3697
 
        }
3698
 
#endif
3699
 
        if (val<0)
3700
 
        {
3701
 
                return OSS_EINVAL;
3702
 
        }
3703
 
        v = oss_audio_set_channels (dev, val);
3704
 
        return *arg = v;
3705
 
      }
3706
 
 
3707
 
    case SNDCTL_DSP_PROFILE:    /* Obsolete */
3708
 
      return 0;
3709
 
      break;
3710
 
 
3711
 
    case SNDCTL_DSP_SILENCE:
3712
 
      memset (dmapout->dmabuf, dmapout->neutral_byte, dmapout->buffsize);
3713
 
      return 0;
3714
 
      break;
3715
 
 
3716
 
    case SNDCTL_DSP_SKIP:
3717
 
      return 0;
3718
 
      break;
3719
 
 
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 */
3722
 
        {
3723
 
          oss_mixer_enuminfo *ei = (oss_mixer_enuminfo *) arg;
3724
 
 
3725
 
          memset (ei, 0, sizeof (*ei)); /* Wipe out everything */
3726
 
 
3727
 
          if (get_legacy_recsrc_names (dev, ei))
3728
 
            return 0;
3729
 
          ei->nvalues = 1;
3730
 
          strcpy (ei->strings, "default");
3731
 
          return 0;
3732
 
        }
3733
 
      return err;
3734
 
      break;
3735
 
 
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 */
3738
 
        {
3739
 
          return *arg = (get_legacy_recsrc (dev));
3740
 
        }
3741
 
      return err;
3742
 
      break;
3743
 
 
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 */
3746
 
        {
3747
 
          val = *arg;
3748
 
          set_legacy_recsrc (dev, val);
3749
 
          return *arg = (get_legacy_recsrc (dev));
3750
 
        }
3751
 
      return err;
3752
 
      break;
3753
 
 
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 */
3756
 
        {
3757
 
          oss_mixer_enuminfo *ei = (oss_mixer_enuminfo *) arg;
3758
 
          memset (ei, 0, sizeof (*ei));
3759
 
          ei->nvalues = 1;
3760
 
          strcpy (ei->strings, "default");
3761
 
          return 0;
3762
 
        }
3763
 
      return err;
3764
 
      break;
3765
 
 
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 */
3768
 
        {
3769
 
          return *arg = (0);
3770
 
        }
3771
 
      return err;
3772
 
      break;
3773
 
 
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 */
3776
 
        {
3777
 
          return *arg = (0);
3778
 
        }
3779
 
      return err;
3780
 
      break;
3781
 
 
3782
 
    case SNDCTL_SETSONG:
3783
 
      if (adev->d->adrv_ioctl != NULL
3784
 
          && adev->d->adrv_ioctl (dev, cmd, arg) >= 0)
3785
 
        return 0;
3786
 
      strncpy (adev->song_name, (char *) arg, sizeof (adev->song_name));
3787
 
      adev->song_name[sizeof (adev->song_name) - 1] = 0;
3788
 
      return 0;
3789
 
      break;
3790
 
 
3791
 
    case SNDCTL_SETLABEL:
3792
 
      if (adev->d->adrv_ioctl != NULL
3793
 
          && adev->d->adrv_ioctl (dev, cmd, arg) >= 0)
3794
 
        return 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);
3799
 
      return 0;
3800
 
      break;
3801
 
    default:
3802
 
      if (adev->d->adrv_ioctl == NULL)
3803
 
        return OSS_EINVAL;
3804
 
      return adev->d->adrv_ioctl (dev, cmd, arg);
3805
 
    }
3806
 
  return OSS_EINVAL;
3807
 
}
3808
 
 
3809
 
 
3810
 
static int
3811
 
prepare_output (adev_p adev, dmap_p dmap)
3812
 
{
3813
 
  int ret, data_rate = 0;
3814
 
  audio_format_info_p fmt_info;
3815
 
 
3816
 
  if (dmap->flags & DMAP_PREPARED)
3817
 
    return 0;
3818
 
 
3819
 
  data_rate = 8;
3820
 
 
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;
3827
 
 
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;
3836
 
 
3837
 
#if 1
3838
 
  if (always_cooked && !(dmap->mapping_flags & DMA_MAP_MAPPED))
3839
 
    dmap->flags |= DMAP_COOKED;
3840
 
#endif
3841
 
 
3842
 
  if ((dmap->mapping_flags & DMA_MAP_MAPPED) && (dmap->flags & DMAP_COOKED))
3843
 
    {
3844
 
      cmn_err (CE_WARN, "Internal error in mmap() support\n");
3845
 
      dmap->flags &= ~DMAP_COOKED;
3846
 
    }
3847
 
 
3848
 
  if (dmap->flags & DMAP_COOKED)
3849
 
    {
3850
 
#ifdef DO_TIMINGS
3851
 
      oss_do_timing ("Cooked mode - Setting up conversions");
3852
 
#endif
3853
 
      if ((ret =
3854
 
           setup_format_conversions (adev, dmap, &adev->user_parms,
3855
 
                                     &adev->hw_parms,
3856
 
                                     &adev->user_parms,
3857
 
                                     &adev->hw_parms,
3858
 
                                     adev->oformat_mask)) < 0)
3859
 
        {
3860
 
          return ret;
3861
 
        }
3862
 
    }
3863
 
  else
3864
 
    {
3865
 
      DDB (cmn_err (CE_CONT, "No format conversions needed\n"));
3866
 
#ifdef DO_TIMINGS
3867
 
      oss_do_timing ("No format conversions needed");
3868
 
#endif
3869
 
    }
3870
 
 
3871
 
/*
3872
 
 * Compute device data rate and frame size
3873
 
 */
3874
 
  if ((fmt_info = oss_find_format (adev->hw_parms.fmt)) != NULL)
3875
 
    data_rate = fmt_info->bits;
3876
 
 
3877
 
  data_rate /= 8;
3878
 
  if (data_rate < 1)
3879
 
    data_rate = 1;
3880
 
  data_rate *= adev->hw_parms.channels;
3881
 
  dmap->frame_size = data_rate;
3882
 
  data_rate *= adev->hw_parms.rate;
3883
 
  if (data_rate < 1)
3884
 
    data_rate = 8000;
3885
 
  dmap->data_rate = data_rate;
3886
 
 
3887
 
/*
3888
 
 * Compute application/user frame_size
3889
 
 */
3890
 
  data_rate = 8;
3891
 
  if ((fmt_info = oss_find_format (adev->user_parms.fmt)) != NULL)
3892
 
    data_rate = fmt_info->bits;
3893
 
 
3894
 
  data_rate /= 8;
3895
 
  if (data_rate < 1)
3896
 
    data_rate = 1;
3897
 
  data_rate *= adev->user_parms.channels;
3898
 
  dmap->user_frame_size = data_rate;
3899
 
 
3900
 
  setup_fragments (adev, dmap, OPEN_WRITE);
3901
 
  if (dmap->expand_factor == 0)
3902
 
    {
3903
 
      dmap->expand_factor = UNIT_EXPAND;
3904
 
      cmn_err (CE_WARN, "Bad expand factor for device %d\n",
3905
 
               adev->engine_num);
3906
 
    }
3907
 
  if (dmap->low_water == -1)
3908
 
    {
3909
 
      dmap->low_water =
3910
 
        (dmap->low_water_rq * UNIT_EXPAND) / dmap->expand_factor;
3911
 
    }
3912
 
 
3913
 
#ifdef DO_TIMINGS
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);
3917
 
#endif
3918
 
 
3919
 
  if ((ret =
3920
 
       adev->d->adrv_prepare_for_output (adev->engine_num,
3921
 
                                         dmap->fragment_size,
3922
 
                                         dmap->nfrags)) < 0)
3923
 
    {
3924
 
      return ret;
3925
 
    }
3926
 
 
3927
 
  dmap->flags |= DMAP_PREPARED;
3928
 
#ifdef CONFIG_OSSD
3929
 
  ossd_event (adev->engine_num, OSSD_EV_PREPARE_OUTPUT);
3930
 
#endif
3931
 
 
3932
 
  return 0;
3933
 
}
3934
 
 
3935
 
static int
3936
 
prepare_input (adev_p adev, dmap_p dmap)
3937
 
{
3938
 
  int ret, data_rate = 0;
3939
 
  audio_format_info_p fmt_info;
3940
 
 
3941
 
  if (dmap->flags & DMAP_PREPARED)
3942
 
    return 0;
3943
 
 
3944
 
  data_rate = 0;
3945
 
 
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;
3952
 
 
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;
3961
 
 
3962
 
#if 1
3963
 
  if (always_cooked && !(dmap->mapping_flags & DMA_MAP_MAPPED))
3964
 
    dmap->flags |= DMAP_COOKED;
3965
 
#endif
3966
 
 
3967
 
  if ((dmap->mapping_flags & DMA_MAP_MAPPED) && (dmap->flags & DMAP_COOKED))
3968
 
    {
3969
 
      cmn_err (CE_WARN, "Internal error in mmap() support\n");
3970
 
      dmap->flags &= ~DMAP_COOKED;
3971
 
    }
3972
 
 
3973
 
  if (dmap->flags & DMAP_COOKED)
3974
 
    {
3975
 
      if ((ret =
3976
 
           setup_format_conversions (adev, dmap, &adev->hw_parms,
3977
 
                                     &adev->user_parms,
3978
 
                                     &adev->user_parms,
3979
 
                                     &adev->hw_parms,
3980
 
                                     adev->iformat_mask)) < 0)
3981
 
        {
3982
 
          DDB (cmn_err
3983
 
               (CE_CONT, "setup_format_conversions failed, err=%d\n", ret));
3984
 
          return ret;
3985
 
        }
3986
 
    }
3987
 
  else
3988
 
    dmap->expand_factor = UNIT_EXPAND;
3989
 
 
3990
 
/*
3991
 
 * Compute device data rate and frame size
3992
 
 */
3993
 
  if ((fmt_info = oss_find_format (adev->hw_parms.fmt)) != NULL)
3994
 
    data_rate = fmt_info->bits;
3995
 
 
3996
 
  data_rate /= 8;
3997
 
  if (data_rate < 1)
3998
 
    data_rate = 1;
3999
 
  data_rate *= adev->hw_parms.channels;
4000
 
  dmap->frame_size = data_rate;
4001
 
  data_rate *= adev->hw_parms.rate;
4002
 
  if (data_rate < 1)
4003
 
    data_rate = 8000;
4004
 
  dmap->data_rate = data_rate;
4005
 
 
4006
 
/*
4007
 
 * Compute user/application frame size
4008
 
 */
4009
 
  data_rate = 8;
4010
 
  if ((fmt_info = oss_find_format (adev->user_parms.fmt)) != NULL)
4011
 
    data_rate = fmt_info->bits;
4012
 
 
4013
 
  data_rate /= 8;
4014
 
  if (data_rate < 1)
4015
 
    data_rate = 1;
4016
 
  data_rate *= adev->user_parms.channels;
4017
 
  dmap->user_frame_size = data_rate;
4018
 
 
4019
 
  setup_fragments (adev, dmap, OPEN_READ);
4020
 
 
4021
 
#if 1
4022
 
  /* Compute 1/expand_factor */
4023
 
 
4024
 
  if (dmap->expand_factor == 0)
4025
 
    {
4026
 
      cmn_err (CE_NOTE, "Internal error (expand_factor==0)\n");
4027
 
      dmap->expand_factor = UNIT_EXPAND;
4028
 
    }
4029
 
 
4030
 
  {
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));
4035
 
  }
4036
 
 
4037
 
  dmap->expand_factor = (UNIT_EXPAND * UNIT_EXPAND) / dmap->expand_factor;
4038
 
 
4039
 
  {
4040
 
    int expand = dmap->expand_factor;
4041
 
    int expand2 = expand * 100 / UNIT_EXPAND;
4042
 
    DDB (cmn_err
4043
 
         (CE_CONT, "Expand factor inverted to = %d (%d.%02d)\n", expand,
4044
 
          expand2 / 100, expand2 % 100));
4045
 
  }
4046
 
#endif
4047
 
 
4048
 
  if (dmap->low_water == -1)
4049
 
    {
4050
 
      dmap->low_water =
4051
 
        (dmap->low_water_rq * UNIT_EXPAND) / dmap->expand_factor;
4052
 
    }
4053
 
 
4054
 
#ifdef DO_TIMINGS
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);
4058
 
#endif
4059
 
 
4060
 
  if ((ret =
4061
 
       adev->d->adrv_prepare_for_input (adev->engine_num, dmap->fragment_size,
4062
 
                                        dmap->nfrags)) < 0)
4063
 
    {
4064
 
      DDB (cmn_err
4065
 
           (CE_CONT, "/dev/dsp%d: prepare_for_input failed, err=%d\n",
4066
 
            adev->engine_num, ret));
4067
 
      return ret;
4068
 
    }
4069
 
 
4070
 
  dmap->flags |= DMAP_PREPARED;
4071
 
#ifdef CONFIG_OSSD
4072
 
  ossd_event (adev->engine_num, OSSD_EV_PREPARE_INPUT);
4073
 
#endif
4074
 
 
4075
 
  return 0;
4076
 
}
4077
 
 
4078
 
static int
4079
 
launch_input (adev_p adev, dmap_p dmap)
4080
 
{
4081
 
#ifdef DO_TIMINGS
4082
 
  oss_do_timing ("Launch input called");
4083
 
#endif
4084
 
  if (dmap->flags & DMAP_STARTED)
4085
 
    return 0;
4086
 
 
4087
 
  if (!(dmap->flags & DMAP_PREPARED))
4088
 
    {
4089
 
      cmn_err (CE_WARN, "launch_input while not prepared.\n");
4090
 
      return OSS_EIO;
4091
 
    }
4092
 
 
4093
 
#ifdef DO_TIMINGS
4094
 
  oss_do_timing ("Launch_input calling d->start_input");
4095
 
#endif
4096
 
 
4097
 
  if (adev->d->adrv_start_input != NULL)
4098
 
    {
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,
4102
 
                                   0);
4103
 
      else
4104
 
        adev->d->adrv_start_input (adev->engine_num, dmap->dmabuf_phys,
4105
 
                                   dmap->fragment_size, dmap->fragment_size,
4106
 
                                   0);
4107
 
    }
4108
 
 
4109
 
#ifdef DO_TIMINGS
4110
 
  oss_do_timing ("Launch_input calling trigger");
4111
 
#endif
4112
 
  dmap->flags |= DMAP_STARTED;
4113
 
  if (adev->d->adrv_trigger
4114
 
      && ((adev->enable_bits * adev->go) & PCM_ENABLE_INPUT))
4115
 
    {
4116
 
      adev->d->adrv_trigger (adev->engine_num, adev->enable_bits * adev->go);
4117
 
    }
4118
 
 
4119
 
  return 0;
4120
 
}
4121
 
 
4122
 
static int
4123
 
find_raw_input_space (adev_p adev, dmap_p dmap, int *dmapos)
4124
 
{
4125
 
  int count;
4126
 
  int tmout, n = 0;
4127
 
  oss_uint64_t offs, doffs;
4128
 
  int lim = 1;
4129
 
  unsigned int status;
4130
 
  oss_native_word flags;
4131
 
 
4132
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4133
 
  if (adev->nonblock)
4134
 
    get_input_pointer (adev, dmap, 1);
4135
 
  count = (int) (dmap->byte_counter - dmap->user_counter);
4136
 
  *dmapos=0;
4137
 
 
4138
 
  if (dmap->flags & DMAP_COOKED)
4139
 
    {
4140
 
      lim = dmap->fragment_size;
4141
 
    }
4142
 
 
4143
 
  while (count < lim)
4144
 
    {
4145
 
      if (adev->nonblock)
4146
 
        {
4147
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4148
 
#ifdef DO_TIMINGS
4149
 
          oss_do_timing ("*** EAGAIN ***");
4150
 
#endif
4151
 
          return OSS_EAGAIN;
4152
 
        }
4153
 
 
4154
 
      if (n++ > 100)
4155
 
        {
4156
 
          cmn_err (CE_WARN, "Audio input %d doesn't get filled.\n",
4157
 
                   adev->engine_num);
4158
 
          cmn_err (CE_CONT, "Counters %d / %d\n", count, lim);
4159
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4160
 
          return OSS_EIO;
4161
 
        }
4162
 
 
4163
 
      tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
4164
 
      tmout += OSS_HZ / 2;
4165
 
 
4166
 
      if (adev->go == 0)
4167
 
        tmout = 0;
4168
 
 
4169
 
#ifdef DO_TIMINGS
4170
 
      oss_do_timing ("Sleep (in)");
4171
 
      oss_timing_enter (DF_SLEEPREAD);
4172
 
#endif
4173
 
      audio_engines[adev->engine_num]->dmap_in->error = 0;
4174
 
      if (!oss_sleep (adev->in_wq, &dmap->mutex, tmout, &flags, &status))
4175
 
        {
4176
 
#ifdef DO_TIMINGS
4177
 
          oss_do_timing ("Sleep (in) timed out");
4178
 
#endif
4179
 
          adev->timeout_count++;
4180
 
          if (adev->d->adrv_check_input)
4181
 
            {
4182
 
              int err = adev->d->adrv_check_input (adev->engine_num);
4183
 
              if (err == 0)
4184
 
                continue;       /* Retry */
4185
 
              MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4186
 
              return err;
4187
 
            }
4188
 
          cmn_err (CE_NOTE,
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);
4194
 
          return OSS_EIO;
4195
 
        }                       /* Timed out */
4196
 
 
4197
 
#ifdef DO_TIMINGS
4198
 
      oss_timing_leave (DF_SLEEPREAD);
4199
 
      oss_do_timing ("Sleep (in) done");
4200
 
#endif
4201
 
 
4202
 
      if (status & WK_SIGNAL)
4203
 
        {
4204
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4205
 
          return OSS_EINTR;
4206
 
        }
4207
 
      count = (int) (dmap->byte_counter - dmap->user_counter);
4208
 
#ifdef DO_TIMINGS
4209
 
        oss_timing_printf ("User counter %d, byte_counter %d", dmap->user_counter,
4210
 
                 dmap->byte_counter);
4211
 
#endif
4212
 
    }
4213
 
 
4214
 
/* Now we should have some data */
4215
 
 
4216
 
  if (adev->nonblock)
4217
 
    get_input_pointer (adev, dmap, 1);
4218
 
 
4219
 
  offs = dmap->user_counter % dmap->bytes_in_use;
4220
 
  doffs = dmap->byte_counter % dmap->bytes_in_use;
4221
 
 
4222
 
  count = (int) (dmap->bytes_in_use - offs);
4223
 
  if (offs <= doffs)
4224
 
    count = (int) (doffs - offs);
4225
 
  if (count == 0)
4226
 
    count = dmap->bytes_in_use;
4227
 
 
4228
 
  *dmapos = offs;
4229
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4230
 
 
4231
 
  return count;
4232
 
}
4233
 
 
4234
 
/*ARGSUSED*/
4235
 
static int
4236
 
move_raw_rdpointer (adev_p adev, dmap_p dmap, int len)
4237
 
{
4238
 
  int ret = 0;
4239
 
  oss_native_word flags;
4240
 
#ifdef DO_TIMINGS
4241
 
    oss_timing_printf ("Move rdpointer, offs=%d, incr %d", dmap->user_counter,
4242
 
             len);
4243
 
#endif
4244
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4245
 
  dmap->user_counter += len;
4246
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4247
 
 
4248
 
  return ret;
4249
 
}
4250
 
 
4251
 
static void
4252
 
copy_read_noninterleaved(adev_t *adev, dmap_t *dmap, int dma_offs, unsigned char *localbuf, int local_offs, int l)
4253
 
{
4254
 
/*
4255
 
 * Copy audio data from non-interleaved device buffer to interleaved
4256
 
 * local buffer.
4257
 
 */
4258
 
// TODO: This function assumes 32 bit audio DATA
4259
 
        
4260
 
  int ch, i, nc = adev->hw_parms.channels;
4261
 
  int *outbuf, *inbuf;
4262
 
 
4263
 
  l             /= sizeof(*outbuf)*nc;
4264
 
  dma_offs      /= sizeof(*outbuf);
4265
 
  local_offs    /= sizeof(*outbuf);
4266
 
 
4267
 
  for (ch=0;ch<nc;ch++)
4268
 
  {
4269
 
        outbuf = (int*)(localbuf+local_offs);
4270
 
        outbuf += ch;
4271
 
 
4272
 
        inbuf = (int *)(dmap->dmabuf + dmap->buffsize*ch / nc);
4273
 
        inbuf += dma_offs / nc;
4274
 
 
4275
 
        for (i=0;i<l;i++)
4276
 
        {
4277
 
                *outbuf = *inbuf++;
4278
 
                outbuf += nc;
4279
 
        }
4280
 
  }
4281
 
 
4282
 
}
4283
 
 
4284
 
static int
4285
 
find_input_space (adev_p adev, dmap_p dmap, unsigned char **dbuf)
4286
 
{
4287
 
  unsigned char *p, *p1 = dmap->tmpbuf1, *p2 = dmap->tmpbuf2;
4288
 
  int err, l, l2, max, dmapos;
4289
 
 
4290
 
  if (!(dmap->flags & DMAP_COOKED))
4291
 
    {
4292
 
      err=find_raw_input_space (adev, dmap, &dmapos);
4293
 
      *dbuf=dmap->dmabuf+dmapos;
4294
 
      return err;
4295
 
    }
4296
 
 
4297
 
  if (dmap->tmpbuf_len > dmap->tmpbuf_ptr)
4298
 
    {
4299
 
      *dbuf = dmap->tmpbuf1 + dmap->tmpbuf_ptr;
4300
 
      return dmap->tmpbuf_len - dmap->tmpbuf_ptr;
4301
 
    }
4302
 
 
4303
 
  dmap->tmpbuf_len = dmap->tmpbuf_ptr = 0;
4304
 
 
4305
 
  if ((l = find_raw_input_space (adev, dmap, &dmapos)) < 0)
4306
 
    {
4307
 
      return l;
4308
 
    }
4309
 
  p=dmap->dmabuf;
4310
 
 
4311
 
  if (dmap->expand_factor > UNIT_EXPAND)
4312
 
    max = (TMP_CONVERT_MAX * UNIT_EXPAND) / dmap->expand_factor;
4313
 
  else
4314
 
    max = TMP_CONVERT_MAX;
4315
 
 
4316
 
  if (max > TMP_CONVERT_MAX)
4317
 
    max = TMP_CONVERT_MAX;
4318
 
 
4319
 
  if (l > max)
4320
 
    l = max;
4321
 
  l = (l / dmap->frame_size) * dmap->frame_size;        /* Truncate to nearest frame size */
4322
 
  l2 = l;
4323
 
  VMEM_CHECK (p1, l);
4324
 
  VMEM_CHECK (p+dmapos, l);
4325
 
 
4326
 
  if ((adev->flags & ADEV_NONINTERLEAVED) && adev->hw_parms.channels > 1)
4327
 
     copy_read_noninterleaved(adev, dmap, dmapos, p1, 0, l);
4328
 
  else
4329
 
     memcpy (p1, p+dmapos, l);
4330
 
 
4331
 
  move_raw_rdpointer (adev, dmap, l);
4332
 
 
4333
 
  if ((err =
4334
 
       dmap->convert_func (adev, dmap, &p1, &l2,
4335
 
                           &p2, &adev->hw_parms,
4336
 
                           &adev->user_parms)) < 0)
4337
 
    return err;
4338
 
 
4339
 
  dmap->tmpbuf1 = p1;
4340
 
  dmap->tmpbuf2 = p2;
4341
 
  dmap->tmpbuf_len = l2;
4342
 
 
4343
 
  *dbuf = dmap->tmpbuf1;
4344
 
  return dmap->tmpbuf_len;
4345
 
}
4346
 
 
4347
 
static int
4348
 
move_rdpointer (adev_p adev, dmap_p dmap, int len)
4349
 
{
4350
 
  if (!(dmap->flags & DMAP_COOKED) || dmap->tmpbuf_ptr >= dmap->tmpbuf_len)
4351
 
    {
4352
 
      dmap->tmpbuf_ptr = 0;
4353
 
      dmap->tmpbuf_len = 0;
4354
 
      return move_raw_rdpointer (adev, dmap, len);
4355
 
    }
4356
 
 
4357
 
  if (dmap->tmpbuf_ptr < dmap->tmpbuf_len)
4358
 
    {
4359
 
      dmap->tmpbuf_ptr += len;
4360
 
 
4361
 
      if (dmap->tmpbuf_ptr >= dmap->tmpbuf_len)
4362
 
        dmap->tmpbuf_len = dmap->tmpbuf_ptr = 0;
4363
 
 
4364
 
      return 0;
4365
 
    }
4366
 
 
4367
 
  cmn_err (CE_NOTE, "Why here?\n");
4368
 
  return OSS_EIO;
4369
 
}
4370
 
 
4371
 
int
4372
 
oss_audio_read (int dev, struct fileinfo *file, uio_t * buf, int count)
4373
 
{
4374
 
  adev_p adev;
4375
 
  dmap_p dmap;
4376
 
  int c, l, p, ret, n;
4377
 
  unsigned char *dmabuf;
4378
 
#ifdef DO_TIMINGS
4379
 
    oss_timing_printf ("--- audio_read(%d, %d) ---", dev, count);
4380
 
#endif
4381
 
 
4382
 
  sync_seed++;
4383
 
 
4384
 
  if (dev < 0 || dev >= num_audio_engines)
4385
 
    return OSS_ENXIO;
4386
 
 
4387
 
  adev = audio_engines[dev];
4388
 
  if (!adev->enabled)
4389
 
    return OSS_ENXIO;
4390
 
  if (adev->flags & ADEV_NOINPUT)
4391
 
    return OSS_EACCES;
4392
 
  dmap = adev->dmap_in;
4393
 
 
4394
 
  if (!(adev->open_mode & OPEN_READ))
4395
 
    return OSS_ENOTSUP;
4396
 
  if (dmap->dma_mode == PCM_ENABLE_OUTPUT)
4397
 
    {
4398
 
      audio_reset_output (adev);
4399
 
      reset_dmap (dmap);
4400
 
    }
4401
 
 
4402
 
/*
4403
 
 * Initial setup 
4404
 
 */
4405
 
  oss_reset_wait_queue (adev->in_wq);
4406
 
 
4407
 
  if (file != NULL)
4408
 
    {
4409
 
      if ((ISSET_FILE_FLAG (file, O_NONBLOCK)
4410
 
           && !(adev->open_flags & OF_BLOCK)) || adev->forced_nonblock)
4411
 
        adev->nonblock = 1;
4412
 
      else
4413
 
        adev->nonblock = 0;
4414
 
#ifdef DO_TIMINGS
4415
 
      if (adev->nonblock)
4416
 
        oss_do_timing ("*** NON BLOCKING READ ***");
4417
 
#endif
4418
 
    }
4419
 
 
4420
 
  if (dmap->dma_mode != PCM_ENABLE_INPUT)
4421
 
    {
4422
 
      if ((ret = prepare_input (adev, dmap)) < 0)
4423
 
        {
4424
 
          DDB (cmn_err (CE_CONT, "Prepare input failed, err=%d\n", ret));
4425
 
          return ret;
4426
 
        }
4427
 
      dmap->dma_mode = PCM_ENABLE_INPUT;
4428
 
      launch_input (adev, dmap);
4429
 
    }
4430
 
 
4431
 
  if (!(dmap->flags & DMAP_PREPARED))
4432
 
    {                           /* Not prepared. Why??? */
4433
 
      cmn_err (CE_WARN, "Intenal error (not prepared)\n");
4434
 
      return OSS_EIO;
4435
 
    }
4436
 
 
4437
 
  c = count;
4438
 
  p = 0;
4439
 
  n = 0;
4440
 
 
4441
 
  while (c > 0 && n++ < 1000)
4442
 
    {
4443
 
      if ((l = find_input_space (adev, dmap, &dmabuf)) < 0)
4444
 
        {
4445
 
          if (l == OSS_EINTR)
4446
 
            {
4447
 
              if (c == count)   /* Nothing read yet */
4448
 
                return OSS_EINTR;
4449
 
              return count - c;
4450
 
            }
4451
 
          if (l == OSS_EAGAIN)
4452
 
            {
4453
 
              if (c == count)   /* Nothing read yet */
4454
 
                return OSS_EAGAIN;
4455
 
              return count - c;
4456
 
            }
4457
 
          return l;
4458
 
        }
4459
 
 
4460
 
      if (l > c)
4461
 
        l = c;
4462
 
 
4463
 
      if (uiomove (dmabuf, l, UIO_READ, buf) != 0)
4464
 
        {
4465
 
          cmn_err (CE_WARN, "audio: uiomove(UIO_READ) failed\n");
4466
 
          return OSS_EFAULT;
4467
 
        }
4468
 
      if ((ret = move_rdpointer (adev, dmap, l)) < 0)
4469
 
        {
4470
 
          return ret;
4471
 
        }
4472
 
 
4473
 
      c -= l;
4474
 
      p += l;
4475
 
    }
4476
 
 
4477
 
#ifdef DO_TIMINGS
4478
 
    oss_timing_printf ("-------- Audio read done (%d)", count - c);
4479
 
#endif
4480
 
 
4481
 
  return count - c;
4482
 
}
4483
 
 
4484
 
/*ARGSUSED*/
4485
 
static int
4486
 
audio_space_in_queue (adev_p adev, dmap_p dmap, int count)
4487
 
{
4488
 
  int cnt;
4489
 
 
4490
 
  cnt = (int) (dmap->byte_counter + dmap->bytes_in_use - dmap->user_counter);
4491
 
 
4492
 
  if (cnt < 0)
4493
 
    {
4494
 
      cmn_err (CE_CONT, "Buffer %d overfilled (%d)\n", adev->engine_num, cnt);
4495
 
    }
4496
 
 
4497
 
  if (!(dmap->mapping_flags & DMA_MAP_MAPPED))
4498
 
    if (cnt > dmap->bytes_in_use)       /* Output underrun */
4499
 
      {
4500
 
#ifdef DO_TIMINGS
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);
4505
 
#endif
4506
 
        cnt = dmap->bytes_in_use;
4507
 
        dmap->user_counter = dmap->byte_counter;
4508
 
        dmap->play_underruns++;
4509
 
        if (!dmap->underrun_flag)
4510
 
          {
4511
 
#ifdef DO_TIMINGS
4512
 
            oss_do_timing ("Clearing the buffer");
4513
 
#endif
4514
 
            memset (dmap->dmabuf, dmap->neutral_byte, dmap->bytes_in_use);
4515
 
          }
4516
 
        dmap->underrun_flag = 1;
4517
 
      }
4518
 
 
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);
4522
 
 
4523
 
  return cnt;
4524
 
}
4525
 
 
4526
 
static int
4527
 
find_output_space (adev_p adev, dmap_p dmap, int *size, int count)
4528
 
{
4529
 
  int offs;
4530
 
  int len, l2, n = 0, tmout;
4531
 
  oss_native_word flags;
4532
 
  int tout;
4533
 
  unsigned int status;
4534
 
 
4535
 
  if (dmap == NULL)
4536
 
    {
4537
 
      cmn_err (CE_WARN, "Internal error - dmap==NULL\n");
4538
 
      return OSS_EIO;
4539
 
    }
4540
 
 
4541
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4542
 
  len = audio_space_in_queue (adev, dmap, count);
4543
 
 
4544
 
  tout = 0;
4545
 
  while (len < dmap->user_frame_size)
4546
 
    {                           /* Wait for some space */
4547
 
      if (tout++ > 10000)
4548
 
        {
4549
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4550
 
          cmn_err (CE_WARN, "Internal timeout error B\n");
4551
 
          return OSS_EIO;
4552
 
        }
4553
 
 
4554
 
      if (adev->nonblock || !(adev->enable_bits & PCM_ENABLE_OUTPUT))
4555
 
        {
4556
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4557
 
#ifdef DO_TIMINGS
4558
 
            oss_timing_printf ("Space=%d\n", len);
4559
 
            oss_do_timing ("*** EAGAIN ***");
4560
 
#endif
4561
 
          if (!(adev->enable_bits & PCM_ENABLE_OUTPUT))
4562
 
            {
4563
 
              launch_output (adev, dmap);
4564
 
              oss_audio_set_error (adev->engine_num, E_PLAY,
4565
 
                                   OSSERR (1021,
4566
 
                                           "Play buffer full when playback is triggered off."),
4567
 
                                   0);
4568
 
              /*
4569
 
               * Errordesc:
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.
4573
 
               *
4574
 
               * Applications using SNDCTL_DSP_SETTRIGGER should avoid filling the 
4575
 
               * available playback buffer before triggering output.
4576
 
               *
4577
 
               * One possible error causing this is that the application has
4578
 
               * triggered only recording on a duplex device.
4579
 
               */
4580
 
            }
4581
 
          return OSS_EAGAIN;
4582
 
        }
4583
 
 
4584
 
      if (n++ > dmap->nfrags * 2)
4585
 
        {
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,
4588
 
                   len);
4589
 
          cmn_err (CE_CONT, "len=%d/%d, total=%d\n", len, dmap->fragment_size,
4590
 
                   dmap->bytes_in_use);
4591
 
#ifdef DO_TIMINGS
4592
 
          oss_do_timing ("Audio output doesn't drain");
4593
 
#endif
4594
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4595
 
          audio_reset_output (adev);
4596
 
          return OSS_EIO;
4597
 
        }
4598
 
 
4599
 
      tmout = (dmap->fragment_size * OSS_HZ) / dmap->data_rate;
4600
 
      tmout += OSS_HZ;
4601
 
 
4602
 
      if (adev->go == 0)
4603
 
        tmout = 0;
4604
 
 
4605
 
      audio_engines[adev->engine_num]->dmap_out->error = 0;
4606
 
      if (adev->go == 0)
4607
 
        {
4608
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4609
 
          return OSS_EAGAIN;
4610
 
        }
4611
 
#ifdef DO_TIMINGS
4612
 
      oss_timing_printf ("Sleep(%d)", adev->engine_num);
4613
 
      oss_timing_enter (DF_SLEEPWRITE);
4614
 
#endif
4615
 
      UP_STATUS (STS_SLEEP);
4616
 
      if (!oss_sleep (adev->out_wq, &dmap->mutex, tmout, &flags, &status))
4617
 
        {
4618
 
#ifdef DO_TIMINGS
4619
 
          oss_timing_printf ("Sleep(%d) (out) timed out", adev->engine_num);
4620
 
#endif
4621
 
          adev->timeout_count++;
4622
 
 
4623
 
          if (adev->d->adrv_check_output)
4624
 
            {
4625
 
              int err = adev->d->adrv_check_output (adev->engine_num);
4626
 
              if (err == 0)
4627
 
                continue;       /* Retry */
4628
 
              MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4629
 
              return err;
4630
 
            }
4631
 
          else
4632
 
            {
4633
 
              cmn_err (CE_NOTE,
4634
 
                       "Output timed out on audio engine %d/'%s' (count=%lld)\n",
4635
 
                       adev->engine_num, adev->name, dmap->byte_counter);
4636
 
            }
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);
4640
 
          return OSS_EIO;
4641
 
        }                       /* Timed out */
4642
 
      DOWN_STATUS (STS_SLEEP);
4643
 
 
4644
 
#ifdef DO_TIMINGS
4645
 
      oss_timing_leave (DF_SLEEPWRITE);
4646
 
      oss_timing_printf ("Sleep(%d) (out) done", adev->engine_num);
4647
 
#endif
4648
 
 
4649
 
      if (status & WK_SIGNAL)
4650
 
        {
4651
 
#ifdef DO_TIMINGS
4652
 
          oss_do_timing ("Signal caught");
4653
 
#endif
4654
 
          MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4655
 
          return OSS_EINTR;
4656
 
        }
4657
 
 
4658
 
      len = audio_space_in_queue (adev, dmap, count);
4659
 
#ifdef DO_TIMINGS
4660
 
      oss_timing_printf ("Free output space now %d bytes", len);
4661
 
#endif
4662
 
    }                           /* Wait for space */
4663
 
 
4664
 
/*
4665
 
 * Now we hopefully have some free space in the buffer.
4666
 
 */
4667
 
 
4668
 
  offs = (int) (dmap->user_counter % dmap->bytes_in_use);
4669
 
 
4670
 
  l2 = dmap->bytes_in_use - offs;
4671
 
  if (len > l2)
4672
 
    len = l2;
4673
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4674
 
  if (len < 0)
4675
 
    len = 0;
4676
 
 
4677
 
  *size = len;
4678
 
#ifdef DO_TIMINGS
4679
 
  oss_timing_printf ("Got output buffer, offs %d/%d, len %d", offs,
4680
 
             dmap->bytes_in_use, len);
4681
 
#endif
4682
 
  if (offs < 0 || (offs + len) > dmap->bytes_in_use)
4683
 
    {
4684
 
      cmn_err (CE_WARN, "Bad audio output buffer %d/%d\n", offs, len);
4685
 
      return OSS_EIO;
4686
 
    }
4687
 
 
4688
 
  return offs;
4689
 
}
4690
 
 
4691
 
static int
4692
 
launch_output (adev_p adev, dmap_p dmap)
4693
 
{
4694
 
  oss_native_word flags;
4695
 
 
4696
 
#ifdef DO_TIMINGS
4697
 
  oss_do_timing ("Launch output called");
4698
 
#endif
4699
 
  if (dmap->flags & DMAP_STARTED)
4700
 
    {
4701
 
      return 0;
4702
 
    }
4703
 
 
4704
 
  if (dmap->user_counter == 0 && dmap->audio_callback == NULL
4705
 
      && dmap->mapping_flags == 0)
4706
 
    {
4707
 
      return 0;
4708
 
    }
4709
 
 
4710
 
  if (!(dmap->flags & DMAP_PREPARED))
4711
 
    {
4712
 
      cmn_err (CE_WARN, "launch_output while not prepared. Engine=%d\n", adev->engine_num);
4713
 
      return OSS_EIO;
4714
 
    }
4715
 
 
4716
 
#ifdef DO_TIMINGS
4717
 
  oss_do_timing ("Launch_output calling output_block");
4718
 
#endif
4719
 
 
4720
 
  if (adev->d->adrv_output_block != NULL)
4721
 
    {
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,
4725
 
                                    0);
4726
 
      else
4727
 
        adev->d->adrv_output_block (adev->engine_num, dmap->dmabuf_phys,
4728
 
                                    dmap->fragment_size, dmap->fragment_size,
4729
 
                                    0);
4730
 
    }
4731
 
 
4732
 
#ifdef DO_TIMINGS
4733
 
  oss_do_timing ("Launch_output calling trigger");
4734
 
#endif
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))
4740
 
    {
4741
 
      adev->d->adrv_trigger (adev->engine_num, adev->enable_bits * adev->go);
4742
 
    }
4743
 
 
4744
 
  return 0;
4745
 
}
4746
 
 
4747
 
static int
4748
 
move_wrpointer (adev_p adev, dmap_p dmap, int len)
4749
 
{
4750
 
  int ret = 0;
4751
 
  oss_native_word flags;
4752
 
#ifdef DO_TIMINGS
4753
 
  oss_timing_printf ("Move wrpointer, len %d", len);
4754
 
#endif
4755
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4756
 
  dmap->underrun_flag = 0;
4757
 
 
4758
 
  dmap->user_counter += len;
4759
 
#ifdef DO_TIMINGS
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);
4763
 
#endif
4764
 
 
4765
 
#ifdef CONFIG_OSSD
4766
 
  ossd_event (adev->engine_num, OSSD_EV_UPDATE_OUTPUT);
4767
 
#endif
4768
 
 
4769
 
  if (ret < 0 || dmap->flags & DMAP_STARTED)
4770
 
    {
4771
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4772
 
      return ret;
4773
 
    }
4774
 
 
4775
 
  if (!(adev->enable_bits & PCM_ENABLE_OUTPUT))
4776
 
    {
4777
 
#ifdef DO_TIMINGS
4778
 
      oss_do_timing ("Output not triggered - skipping launch_output");
4779
 
#endif
4780
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4781
 
      return ret;
4782
 
    }
4783
 
 
4784
 
  if ((dmap->user_counter < dmap->fragment_size * 2)
4785
 
      && (dmap->user_counter < dmap->bytes_in_use / 2))
4786
 
    {
4787
 
#ifdef DO_TIMINGS
4788
 
      oss_timing_printf ("dmap->user_counter=%lld, dmap->fragment_size*2=%ld",
4789
 
               dmap->user_counter, dmap->fragment_size * 2);
4790
 
      oss_do_timing
4791
 
        ("Not enough data in the buffer yet - skipping launch_output");
4792
 
#endif
4793
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4794
 
      return ret;
4795
 
    }
4796
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4797
 
  ret = launch_output (adev, dmap);
4798
 
  return ret;
4799
 
}
4800
 
 
4801
 
/*ARGSUSED*/
4802
 
static void
4803
 
store_tmp_data (adev_p adev, dmap_p dmap, unsigned char *buf, int count)
4804
 
{
4805
 
  dmap->leftover_buf = buf;
4806
 
  dmap->leftover_bytes = count;
4807
 
}
4808
 
 
4809
 
static void
4810
 
copy_write_noninterleaved(adev_t *adev, dmap_t *dmap, int dma_offs, unsigned char *localbuf, int local_offs, int l)
4811
 
{
4812
 
/*
4813
 
 * Copy interleaved N channel data to non-interleaved device buffer.
4814
 
 */
4815
 
// TODO: This function assumes 32 bit audio DATA
4816
 
        
4817
 
  int ch, i, nc = adev->hw_parms.channels;
4818
 
  int *inbuf, *outbuf;
4819
 
 
4820
 
  l             /= sizeof(*inbuf)*nc;
4821
 
  dma_offs      /= sizeof(*inbuf);
4822
 
  local_offs    /= sizeof(*inbuf);
4823
 
 
4824
 
  for (ch=0;ch<nc;ch++)
4825
 
  {
4826
 
        inbuf = (int*)(localbuf+local_offs);
4827
 
        inbuf += ch;
4828
 
 
4829
 
        outbuf = (int *)(dmap->dmabuf + dmap->buffsize*ch / nc);
4830
 
        outbuf += dma_offs / nc;
4831
 
 
4832
 
        for (i=0;i<l;i++)
4833
 
        {
4834
 
                *outbuf++ = *inbuf;
4835
 
                inbuf += nc;
4836
 
        }
4837
 
  }
4838
 
 
4839
 
}
4840
 
 
4841
 
static int
4842
 
write_copy (adev_p adev, dmap_p dmap, unsigned char *buf, int count)
4843
 
{
4844
 
  int err, offs, spc, l, p = 0;
4845
 
 
4846
 
  while (count)
4847
 
    {
4848
 
      l = count;
4849
 
 
4850
 
      if ((offs = find_output_space (adev, dmap, &spc, l)) < 0)
4851
 
        {
4852
 
          if (offs == OSS_EAGAIN)
4853
 
            {
4854
 
              store_tmp_data (adev, dmap, buf + p, count);
4855
 
              launch_output (adev, dmap);
4856
 
              return OSS_EAGAIN;
4857
 
            }
4858
 
          return offs;
4859
 
        }
4860
 
 
4861
 
      if (l > spc)
4862
 
        l = spc;
4863
 
 
4864
 
      VMEM_CHECK (&dmap->dmabuf[offs], l);
4865
 
      VMEM_CHECK (buf + p, l);
4866
 
 
4867
 
      if ((adev->flags & ADEV_NONINTERLEAVED) && adev->hw_parms.channels > 1)
4868
 
         {
4869
 
            copy_write_noninterleaved(adev, dmap, offs, buf + p, 0, l);
4870
 
         }
4871
 
      else
4872
 
         memcpy (&dmap->dmabuf[offs], buf + p, l);
4873
 
 
4874
 
      if ((err = move_wrpointer (adev, dmap, l)) < 0)
4875
 
        return err;
4876
 
 
4877
 
      count -= l;
4878
 
      p += l;
4879
 
    }
4880
 
  return 0;
4881
 
}
4882
 
 
4883
 
int
4884
 
oss_audio_write (int dev, struct fileinfo *file, uio_t * buf, int count)
4885
 
{
4886
 
  adev_p adev;
4887
 
  oss_native_word flags;
4888
 
  dmap_p dmap;
4889
 
  int ret;
4890
 
  int l, c, spc, offs, p, err;
4891
 
  int tmout;
4892
 
 
4893
 
#ifdef DO_TIMINGS
4894
 
  oss_timing_printf ("--- audio_write(%d, %d) ---", dev, count);
4895
 
#endif
4896
 
 
4897
 
  sync_seed++;
4898
 
 
4899
 
  if (dev < 0 || dev >= num_audio_engines)
4900
 
    return OSS_ENXIO;
4901
 
 
4902
 
  adev = audio_engines[dev];
4903
 
  if (!adev->enabled)
4904
 
    return OSS_ENXIO;
4905
 
  if (adev->flags & ADEV_NOOUTPUT)
4906
 
    return OSS_EACCES;
4907
 
  dmap = adev->dmap_out;
4908
 
 
4909
 
  if (!(adev->open_mode & OPEN_WRITE))
4910
 
    return OSS_ENOTSUP;
4911
 
 
4912
 
  UP_STATUS (STS_WRITE);
4913
 
 
4914
 
  if (dmap->dma_mode == PCM_ENABLE_INPUT)
4915
 
    {
4916
 
      audio_reset_input (adev);
4917
 
      reset_dmap (dmap);
4918
 
    }
4919
 
 
4920
 
/*
4921
 
 * Initial setup 
4922
 
 */
4923
 
  oss_reset_wait_queue (adev->out_wq);
4924
 
 
4925
 
  if (file != NULL)
4926
 
    {
4927
 
      if ((ISSET_FILE_FLAG (file, O_NONBLOCK)
4928
 
           && !(adev->open_flags & OF_BLOCK)) || adev->forced_nonblock)
4929
 
        adev->nonblock = 1;
4930
 
      else
4931
 
        adev->nonblock = 0;
4932
 
#ifdef DO_TIMINGS
4933
 
      if (adev->nonblock)
4934
 
        oss_do_timing ("*** NON BLOCKING WRITE ***");
4935
 
#endif
4936
 
    }
4937
 
 
4938
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4939
 
 
4940
 
  if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
4941
 
    {
4942
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4943
 
      if ((ret = prepare_output (adev, dmap)) < 0)
4944
 
        {
4945
 
          DOWN_STATUS (STS_WRITE);
4946
 
          return ret;
4947
 
        }
4948
 
      MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4949
 
      dmap->dma_mode = PCM_ENABLE_OUTPUT;
4950
 
    }
4951
 
 
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");
4957
 
      return OSS_EIO;
4958
 
    }
4959
 
#if 1
4960
 
  if (dmap->leftover_bytes > 0)
4961
 
    {
4962
 
      unsigned char *b;
4963
 
      int l;
4964
 
 
4965
 
      b = dmap->leftover_buf;
4966
 
      l = dmap->leftover_bytes;
4967
 
      dmap->leftover_bytes = 0;
4968
 
      dmap->leftover_buf = NULL;
4969
 
 
4970
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4971
 
      if ((err = write_copy (adev, dmap, b, l)) < 0)
4972
 
        {
4973
 
          DOWN_STATUS (STS_WRITE);
4974
 
          return err;
4975
 
        }
4976
 
 
4977
 
      dmap->leftover_bytes = 0;
4978
 
      dmap->leftover_buf = NULL;
4979
 
      MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
4980
 
    }
4981
 
#endif
4982
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
4983
 
 
4984
 
  if (count <= 0)
4985
 
    {
4986
 
      DOWN_STATUS (STS_WRITE);
4987
 
      return 0;
4988
 
    }
4989
 
 
4990
 
  c = count;
4991
 
  p = 0;
4992
 
 
4993
 
  tmout = 0;
4994
 
 
4995
 
  while (c > 0)
4996
 
    {
4997
 
#ifdef DO_TIMINGS
4998
 
        oss_timing_printf ("%d/%d bytes to go", c, count);
4999
 
#endif
5000
 
 
5001
 
      if (tmout++ > 1000)
5002
 
        {
5003
 
          cmn_err (CE_WARN, "Internal timeout error A (%d/%d)\n", c, count);
5004
 
          return OSS_EIO;
5005
 
        }
5006
 
 
5007
 
      l = c;
5008
 
      if (l > 8)
5009
 
        l &= ~7;                /* Align it */
5010
 
 
5011
 
      if ((offs = find_output_space (adev, dmap, &spc, l)) < 0)
5012
 
        {
5013
 
          if (offs == OSS_EINTR)
5014
 
            {
5015
 
              DOWN_STATUS (STS_WRITE);
5016
 
              if (c == count)   /* Nothing written yet */
5017
 
                return OSS_EINTR;
5018
 
              return count - c;
5019
 
            }
5020
 
          if (offs == OSS_EAGAIN)
5021
 
            {
5022
 
              DOWN_STATUS (STS_WRITE);
5023
 
              if (c == count)   /* Nothing written yet */
5024
 
                {
5025
 
                  return OSS_EAGAIN;
5026
 
                }
5027
 
              return count - c;
5028
 
            }
5029
 
          DOWN_STATUS (STS_WRITE);
5030
 
          return offs;
5031
 
        }
5032
 
 
5033
 
      if (dmap->convert_func == NULL)
5034
 
        {
5035
 
          if (dmap->device_write != NULL)
5036
 
            {
5037
 
              unsigned char *tmpbuf;
5038
 
              int l2;
5039
 
 
5040
 
              if (dmap->tmpbuf1 == NULL)
5041
 
                {
5042
 
                  dmap->tmpbuf1 = AUDIO_MALLOC (dmap->osdev, TMP_CONVERT_BUF_SIZE+512);
5043
 
                }
5044
 
 
5045
 
/*
5046
 
 * Leave some room for data expansion so use just half of the available
5047
 
 * space.
5048
 
 */
5049
 
              tmpbuf = dmap->tmpbuf1;
5050
 
              if (l > spc / 2)
5051
 
                l = spc / 2;
5052
 
              if (l > TMP_CONVERT_BUF_SIZE / 2)
5053
 
                l = TMP_CONVERT_BUF_SIZE / 2;
5054
 
 
5055
 
              l2 = l;
5056
 
              if (uiomove (tmpbuf, l, UIO_WRITE, buf) != 0)
5057
 
                {
5058
 
                  cmn_err (CE_WARN,
5059
 
                           "audio: uiomove(UIO_WRITE) failed (noconv)\n");
5060
 
                  DOWN_STATUS (STS_WRITE);
5061
 
                  return OSS_EFAULT;
5062
 
                }
5063
 
              if ((err =
5064
 
                   dmap->device_write (adev, dmap, tmpbuf,
5065
 
                                       &dmap->dmabuf[offs], spc, &l,
5066
 
                                       &l2)) < 0)
5067
 
                {
5068
 
                  DOWN_STATUS (STS_WRITE);
5069
 
                  return err;
5070
 
                }
5071
 
              if ((err = move_wrpointer (adev, dmap, l2)) < 0)
5072
 
                {
5073
 
                  DOWN_STATUS (STS_WRITE);
5074
 
                  return err;
5075
 
                }
5076
 
            }
5077
 
          else
5078
 
            {
5079
 
              if (l > spc)
5080
 
                l = spc;
5081
 
              if (uiomove (&dmap->dmabuf[offs], l, UIO_WRITE, buf) != 0)
5082
 
                {
5083
 
                  cmn_err (CE_WARN,
5084
 
                           "audio: uiomove(UIO_WRITE) (noconv2) failed\n");
5085
 
                  return OSS_EFAULT;
5086
 
                }
5087
 
              if ((err = move_wrpointer (adev, dmap, l)) < 0)
5088
 
                {
5089
 
                  DOWN_STATUS (STS_WRITE);
5090
 
                  return err;
5091
 
                }
5092
 
            }
5093
 
        }
5094
 
      else
5095
 
        {
5096
 
          /*
5097
 
           * Perform format conversions.
5098
 
           */
5099
 
          unsigned char *p1 = dmap->tmpbuf1, *p2 = dmap->tmpbuf2;
5100
 
          int l2, max, out_max;
5101
 
 
5102
 
          if (spc > TMP_CONVERT_MAX)
5103
 
            spc = TMP_CONVERT_MAX / 2;
5104
 
 
5105
 
          if (dmap->expand_factor > UNIT_EXPAND)
5106
 
             {
5107
 
                max = spc;
5108
 
 
5109
 
                out_max = (spc * dmap->expand_factor) / UNIT_EXPAND; /* Output size */
5110
 
                if (out_max > TMP_CONVERT_BUF_SIZE) /* Potential overflow */
5111
 
                   {
5112
 
                           max = (TMP_CONVERT_BUF_SIZE * UNIT_EXPAND) / dmap->expand_factor;
5113
 
                   }
5114
 
             }
5115
 
          else
5116
 
            max = spc;
5117
 
          if (max < dmap->frame_size)
5118
 
            max = dmap->frame_size;
5119
 
 
5120
 
          if (max > TMP_CONVERT_MAX)
5121
 
            max = TMP_CONVERT_MAX / 2;
5122
 
 
5123
 
          if (l > max)
5124
 
            l = max;
5125
 
          /* Avoid leaving too short "tails" */
5126
 
          if (c - l < 64)
5127
 
            l = c;
5128
 
 
5129
 
          /* Round to integer number of samples */
5130
 
          l =
5131
 
            (((l + dmap->frame_size -
5132
 
               1) / dmap->frame_size)) * dmap->frame_size;
5133
 
          if (l > c)
5134
 
            l = c;
5135
 
 
5136
 
          l2 = l;
5137
 
 
5138
 
          VMEM_CHECK (p1, l);
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);
5142
 
          if ((err =
5143
 
               dmap->convert_func (adev, dmap, &p1, &l2,
5144
 
                                   &p2, &adev->user_parms,
5145
 
                                   &adev->hw_parms)) < 0)
5146
 
            {
5147
 
              cmn_err (CE_WARN, "Format conversion failed (%d)\n", err);
5148
 
              DOWN_STATUS (STS_WRITE | STS_CONVERT);
5149
 
              return err;
5150
 
            }
5151
 
          DOWN_STATUS (STS_CONVERT);
5152
 
 
5153
 
          if ((err = write_copy (adev, dmap, p1, l2)) < 0)
5154
 
            {
5155
 
              if (err != OSS_EAGAIN)
5156
 
                {
5157
 
                  DOWN_STATUS (STS_WRITE);
5158
 
                  return err;
5159
 
                }
5160
 
 
5161
 
              /* Handle non blocking I/O */
5162
 
              if (c == count)   /* Nothing written yet */
5163
 
                {
5164
 
                  DOWN_STATUS (STS_WRITE);
5165
 
                  return OSS_EAGAIN;
5166
 
                }
5167
 
 
5168
 
              DOWN_STATUS (STS_WRITE);
5169
 
              return count - c;
5170
 
 
5171
 
            }
5172
 
        }
5173
 
 
5174
 
      c -= l;
5175
 
      p += l;
5176
 
 
5177
 
      if (l > 0)
5178
 
        tmout = 0;
5179
 
    }
5180
 
 
5181
 
#ifdef DO_TIMINGS
5182
 
  oss_do_timing ("--- Audio write done");
5183
 
#endif
5184
 
  DOWN_STATUS (STS_WRITE);
5185
 
  return count - c;
5186
 
}
5187
 
 
5188
 
#ifdef MANAGE_DEV_DSP
5189
 
#ifdef VDEV_SUPPORT
5190
 
void
5191
 
oss_combine_write_lists (void)
5192
 
{
5193
 
  int i;
5194
 
 
5195
 
  for (i = 0; i < dspoutlist2.ndevs; i++)
5196
 
    dspoutlist.devices[dspoutlist.ndevs++] = dspoutlist2.devices[i];
5197
 
 
5198
 
  dspoutlist2.ndevs = 0;
5199
 
}
5200
 
 
5201
 
/*ARGSUSED*/
5202
 
int
5203
 
oss_open_vdsp (int dev, int dev_type, struct fileinfo *file, int recursive,
5204
 
               int open_flags, int *newdev)
5205
 
{
5206
 
  int ret, i, d;
5207
 
  int mode = file->mode & O_ACCMODE;
5208
 
 
5209
 
  DDB (cmn_err (CE_CONT, "oss_open_vdsp(%d, mode=%d)\n", dev, mode));
5210
 
 
5211
 
  switch (dev)
5212
 
    {
5213
 
    case 1:
5214
 
      mode = OPEN_READ;
5215
 
      break;
5216
 
    case 2:
5217
 
      mode = OPEN_WRITE;
5218
 
      break;
5219
 
 
5220
 
      /* default: Use the mode defined by O_ACCMODE */
5221
 
    }
5222
 
 
5223
 
  dev = -1;
5224
 
  open_flags = get_open_flags (mode, open_flags, file);
5225
 
 
5226
 
  switch (dev_type)
5227
 
    {
5228
 
    case OSS_DEV_VDSP:
5229
 
      dev_type = OSS_DEV_DSP;
5230
 
      break;
5231
 
#if 0
5232
 
    case OSS_DEV_VAUDIO:
5233
 
      dev_type = OSS_DEV_DEVAUDIO;
5234
 
      break;
5235
 
#endif
5236
 
    default:
5237
 
      cmn_err (CE_NOTE, "Unknown dev class %d\n", dev_type);
5238
 
      break;
5239
 
    }
5240
 
 
5241
 
  if (audio_devfiles == NULL)
5242
 
    {
5243
 
      cmn_err (CE_NOTE, "No audio device files available\n");
5244
 
      return OSS_ENXIO;
5245
 
    }
5246
 
#ifdef MANAGE_DEV_DSP
5247
 
#ifdef VDEV_SUPPORT
5248
 
  oss_combine_write_lists ();
5249
 
#endif
5250
 
#endif
5251
 
 
5252
 
#ifdef APPLIST_SUPPORT
5253
 
  {
5254
 
    char *appname;
5255
 
    appname = GET_PROCESS_NAME (file);
5256
 
    if (open_flags & OF_DEVAUDIO)
5257
 
      appname = "Devaudio_Support";
5258
 
 
5259
 
    if ((dev = app_lookup (mode, appname, &open_flags)) >= 0)
5260
 
      if (audio_devfiles[dev]->enabled && !audio_devfiles[dev]->unloaded)
5261
 
        if ((ret =
5262
 
             oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5263
 
                                     newdev)) >= 0)
5264
 
          {
5265
 
            dev = ret;
5266
 
            DDB (cmn_err
5267
 
                 (CE_CONT, "Using dsp%d configured for this application\n",
5268
 
                  dev));
5269
 
            goto done;
5270
 
          }
5271
 
  }
5272
 
#endif
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"));
5288
 
 
5289
 
  switch (mode & (OPEN_READ | OPEN_WRITE))
5290
 
    {
5291
 
    case OPEN_WRITE:
5292
 
      DDB (cmn_err (CE_CONT, "Selecting output device: "));
5293
 
 
5294
 
      for (i = 0; i < dspoutlist.ndevs; i++)
5295
 
        {
5296
 
          dev = dspoutlist.devices[i];
5297
 
          if (!audio_devfiles[dev]->enabled || audio_devfiles[dev]->unloaded)
5298
 
            {
5299
 
              dev = -1;
5300
 
              continue;
5301
 
            }
5302
 
 
5303
 
          DDB (cmn_err (CE_CONT, "%d ", dev));
5304
 
          if ((ret =
5305
 
               oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5306
 
                                       newdev)) >= 0)
5307
 
            {
5308
 
              dev = ret;
5309
 
              DDB (cmn_err (CE_CONT, "->%d ", dev));
5310
 
              break;
5311
 
            }
5312
 
          dev = -1;
5313
 
        }
5314
 
      break;
5315
 
 
5316
 
    case OPEN_READ:
5317
 
      DDB (cmn_err (CE_CONT, "Selecting input device: "));
5318
 
      for (i = 0; i < dspinlist.ndevs; i++)
5319
 
        {
5320
 
          dev = dspinlist.devices[i];
5321
 
          if (!audio_devfiles[dev]->enabled || audio_devfiles[dev]->unloaded)
5322
 
            {
5323
 
              dev = -1;
5324
 
              continue;
5325
 
            }
5326
 
          DDB (cmn_err (CE_CONT, "%d ", dev));
5327
 
          if ((ret =
5328
 
               oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5329
 
                                       newdev)) >= 0)
5330
 
            {
5331
 
              dev = ret;
5332
 
              DDB (cmn_err (CE_CONT, "->%d ", dev));
5333
 
              break;
5334
 
            }
5335
 
 
5336
 
          dev = -1;
5337
 
        }
5338
 
      break;
5339
 
 
5340
 
    case OPEN_WRITE | OPEN_READ:
5341
 
      DDB (cmn_err (CE_CONT, "Selecting input/output device: "));
5342
 
      for (i = 0; i < dspinoutlist.ndevs; i++)
5343
 
        {
5344
 
          dev = dspinoutlist.devices[i];
5345
 
          if (!audio_devfiles[dev]->enabled || audio_devfiles[dev]->unloaded)
5346
 
            {
5347
 
              dev = -1;
5348
 
              continue;
5349
 
            }
5350
 
          DDB (cmn_err (CE_CONT, "%d ", dev));
5351
 
          if ((ret =
5352
 
               oss_audio_open_devfile (dev, dev_type, file, 0, open_flags,
5353
 
                                       newdev)) >= 0)
5354
 
            {
5355
 
              dev = ret;
5356
 
              DDB (cmn_err (CE_CONT, "->%d ", dev));
5357
 
              break;
5358
 
            }
5359
 
          dev = -1;
5360
 
        }
5361
 
      break;
5362
 
    }
5363
 
 
5364
 
  DDB (cmn_err (CE_CONT, " - got vdsp -> %d\n", dev));
5365
 
  if (dev == -1)
5366
 
    return OSS_EBUSY;
5367
 
 
5368
 
done:
5369
 
/*
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.
5372
 
 */
5373
 
  if ((d = oss_find_minor (OSS_DEV_DSP_ENGINE, dev)) < 0)
5374
 
    {
5375
 
      oss_audio_release (dev, file);
5376
 
      return d;
5377
 
    }
5378
 
 
5379
 
  *newdev = d;
5380
 
  return dev;
5381
 
}
5382
 
#endif
5383
 
#endif
5384
 
 
5385
 
static int
5386
 
audio_init_device (int dev)
5387
 
{
5388
 
  adev_p adev;
5389
 
 
5390
 
  sync_seed = GET_JIFFIES ();
5391
 
  adev = audio_engines[dev];
5392
 
 
5393
 
  MUTEX_INIT (adev->master_osdev, adev->mutex, MH_FRAMEW);
5394
 
 
5395
 
  if (audio_engines[dev]->dmap_out == NULL
5396
 
      || audio_engines[dev]->dmap_in == NULL)
5397
 
    {
5398
 
      dmap_p dmap;
5399
 
 
5400
 
      dmap = AUDIO_MALLOC (adev->osdev, sizeof (dmap_t));
5401
 
      if (dmap == NULL)
5402
 
        {
5403
 
          cmn_err (CE_WARN, "Failed to allocate dmap, dev=%d\n", dev);
5404
 
          return OSS_ENOMEM;
5405
 
        }
5406
 
 
5407
 
      memset ((char *) dmap, 0, sizeof (dmap_t));
5408
 
 
5409
 
      if (!(adev->flags & ADEV_NOOUTPUT) && adev->out_wq == NULL)
5410
 
        {
5411
 
          if ((adev->out_wq =
5412
 
               oss_create_wait_queue (adev->osdev, "audio_out")) == NULL)
5413
 
            {
5414
 
              cmn_err (CE_WARN, "Cannot create audio output wait queue\n");
5415
 
              return OSS_ENOMEM;
5416
 
            }
5417
 
        }
5418
 
 
5419
 
      if (!(adev->flags & ADEV_NOINPUT) && adev->in_wq == NULL)
5420
 
        {
5421
 
          if ((adev->in_wq =
5422
 
               oss_create_wait_queue (adev->osdev, "audio_in")) == NULL)
5423
 
            {
5424
 
              cmn_err (CE_WARN, "Cannot create audio input wait queue\n");
5425
 
              return OSS_ENOMEM;
5426
 
            }
5427
 
        }
5428
 
 
5429
 
      memset ((char *) dmap, 0, sizeof (dmap_t));
5430
 
      dmap->osdev = adev->osdev;
5431
 
      dmap->adev = adev;
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;
5435
 
 
5436
 
      if (adev->flags & ADEV_DUPLEX)
5437
 
        {
5438
 
 
5439
 
          dmap = AUDIO_MALLOC (adev->osdev, sizeof (dmap_t));
5440
 
          if (dmap == NULL)
5441
 
            {
5442
 
              cmn_err (CE_WARN, "Failed to allocate dmap, dev=%d\n", dev);
5443
 
              return OSS_ENOMEM;
5444
 
            }
5445
 
 
5446
 
          memset ((char *) dmap, 0, sizeof (dmap_t));
5447
 
          dmap->osdev = adev->osdev;
5448
 
          dmap->adev = adev;
5449
 
          dmap->master_osdev = adev->master_osdev;
5450
 
          MUTEX_INIT (dmap->master_osdev, dmap->mutex, MH_FRAMEW + 1);
5451
 
          adev->dmap_in = dmap;
5452
 
        }
5453
 
    }
5454
 
 
5455
 
  return 0;
5456
 
}
5457
 
 
5458
 
void
5459
 
audio_uninit_device (int dev)
5460
 
{
5461
 
  adev_p adev;
5462
 
  /* oss_native_word flags; */
5463
 
 
5464
 
  adev = audio_engines[dev];
5465
 
 
5466
 
  if (adev->unloaded)
5467
 
    return;
5468
 
 
5469
 
  if (adev->dmap_out != NULL && adev->dmap_out->dmabuf != NULL)
5470
 
    {
5471
 
      if (adev->d->adrv_free_buffer != NULL)
5472
 
        {
5473
 
          adev->d->adrv_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
5474
 
        }
5475
 
      else
5476
 
        default_free_buffer (dev, adev->dmap_out, OPEN_WRITE);
5477
 
      adev->dmap_out->dmabuf = NULL;
5478
 
    }
5479
 
 
5480
 
  if (adev->dmap_in != NULL
5481
 
      && (adev->dmap_in != adev->dmap_out && adev->dmap_in->dmabuf != NULL))
5482
 
    {
5483
 
      if (adev->d->adrv_free_buffer != NULL)
5484
 
        {
5485
 
          adev->d->adrv_free_buffer (dev, adev->dmap_in, OPEN_READ);
5486
 
        }
5487
 
      else
5488
 
        default_free_buffer (dev, adev->dmap_in, OPEN_READ);
5489
 
      adev->dmap_in->dmabuf = NULL;
5490
 
    }
5491
 
 
5492
 
  if (adev->in_wq != NULL)
5493
 
    {
5494
 
      oss_remove_wait_queue (adev->in_wq);
5495
 
      adev->in_wq = NULL;
5496
 
    }
5497
 
  if (adev->out_wq != NULL)
5498
 
    {
5499
 
      oss_remove_wait_queue (adev->out_wq);
5500
 
      adev->out_wq = NULL;
5501
 
    }
5502
 
 
5503
 
#ifdef CONFIG_OSS_VMIX
5504
 
  if (adev->vmix_mixer != NULL)
5505
 
     {
5506
 
             adev->vmix_mixer = NULL;
5507
 
     }
5508
 
#endif
5509
 
 
5510
 
  MUTEX_CLEANUP (adev->mutex);
5511
 
 
5512
 
  if (adev->dmap_out != NULL)
5513
 
    MUTEX_CLEANUP (adev->dmap_out->mutex);
5514
 
 
5515
 
  if (adev->flags & ADEV_DUPLEX && adev->dmap_in != NULL
5516
 
      && adev->dmap_out != adev->dmap_in)
5517
 
    {
5518
 
      MUTEX_CLEANUP (adev->dmap_in->mutex);
5519
 
    }
5520
 
  adev->unloaded = 1;
5521
 
}
5522
 
 
5523
 
void
5524
 
oss_audio_init (oss_device_t *osdev)
5525
 
{
5526
 
        MUTEX_INIT (osdev, audio_global_mutex, MH_DRV);
5527
 
}
5528
 
 
5529
 
void
5530
 
oss_audio_uninit (void)
5531
 
{
5532
 
/*
5533
 
 * Release all memory/resources allocated by the audio core.
5534
 
 */
5535
 
  oss_memblk_unalloc(&audio_global_memblk);
5536
 
 
5537
 
  MUTEX_CLEANUP (audio_global_mutex);
5538
 
}
5539
 
 
5540
 
void
5541
 
oss_audio_inc_byte_counter (dmap_t * dmap, int increment)
5542
 
{
5543
 
  oss_uint64_t p1, p2;
5544
 
  oss_native_word flags;
5545
 
 
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;
5550
 
 
5551
 
  dmap->interrupt_count += (int) (p2 - p1);
5552
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5553
 
}
5554
 
 
5555
 
static void
5556
 
do_inputintr (int dev, int intr_flags)
5557
 
{
5558
 
  adev_p adev;
5559
 
  dmap_p dmap;
5560
 
  int cptr;
5561
 
  oss_native_word flags;
5562
 
 
5563
 
  adev = audio_engines[dev];
5564
 
  dmap = adev->dmap_in;
5565
 
 
5566
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5567
 
 
5568
 
  if (!(intr_flags & AINTR_NO_POINTER_UPDATES))
5569
 
    {
5570
 
      dmap->byte_counter += dmap->fragment_size;
5571
 
      dmap->interrupt_count++;
5572
 
    }
5573
 
 
5574
 
  while (dmap->byte_counter > dmap->user_counter &&
5575
 
         (int) (dmap->byte_counter - dmap->user_counter) > dmap->bytes_in_use)
5576
 
    {
5577
 
      dmap->user_counter += dmap->fragment_size;
5578
 
      dmap->rec_overruns++;
5579
 
    }
5580
 
  dmap->fragment_counter = (dmap->fragment_counter + 1) % dmap->nfrags;
5581
 
 
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);
5584
 
 
5585
 
#ifdef DO_TIMINGS
5586
 
  oss_do_timing ("Wake up (in)");
5587
 
#endif
5588
 
  oss_wakeup (adev->in_wq, &dmap->mutex, &flags, POLLIN | POLLRDNORM);
5589
 
 
5590
 
  if (adev->flags & ADEV_AUTOMODE)
5591
 
    {
5592
 
      goto finish;
5593
 
    }
5594
 
 
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);
5599
 
finish:
5600
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5601
 
 
5602
 
  if (dmap->audio_callback != NULL)
5603
 
    dmap->audio_callback (adev->engine_num, dmap->callback_parm);
5604
 
}
5605
 
 
5606
 
static void
5607
 
audio_inputintr (int dev, int intr_flags)
5608
 
{
5609
 
  adev_p adev;
5610
 
  dmap_p dmap;
5611
 
  int n;
5612
 
  oss_uint64_t pos;
5613
 
 
5614
 
  if (dev < 0 || dev >= num_audio_engines)
5615
 
    return;
5616
 
 
5617
 
  adev = audio_engines[dev];
5618
 
  dmap = adev->dmap_in;
5619
 
 
5620
 
  if (dmap->dma_mode != PCM_ENABLE_INPUT)
5621
 
    {
5622
 
      return;
5623
 
    }
5624
 
 
5625
 
  if (!(dmap->flags & DMAP_STARTED))
5626
 
    {
5627
 
      return;
5628
 
    }
5629
 
#ifdef DO_TIMINGS
5630
 
  oss_timing_printf ("Inputintr(%d)", dev);
5631
 
#endif
5632
 
 
5633
 
  if (adev->d->adrv_get_input_pointer == NULL
5634
 
      || (intr_flags & AINTR_NO_POINTER_UPDATES))
5635
 
    {
5636
 
      do_inputintr (dev, intr_flags);
5637
 
      return;
5638
 
    }
5639
 
 
5640
 
  pos =
5641
 
    adev->d->adrv_get_input_pointer (adev->engine_num, dmap,
5642
 
                                     PCM_ENABLE_INPUT) / dmap->fragment_size;
5643
 
  n = 0;
5644
 
 
5645
 
  while (dmap_get_qtail (dmap) != pos && n++ < dmap->nfrags)
5646
 
    {
5647
 
      do_inputintr (dev, intr_flags);
5648
 
    }
5649
 
}
5650
 
 
5651
 
static void
5652
 
finish_output_interrupt (adev_p adev, dmap_p dmap)
5653
 
{
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);
5656
 
 
5657
 
#ifdef CONFIG_OSSD
5658
 
  ossd_event (adev->engine_num, OSSD_EV_UPDATE_OUTPUT);
5659
 
#endif
5660
 
  if (dmap->audio_callback != NULL)
5661
 
    {
5662
 
      dmap->audio_callback (adev->engine_num, dmap->callback_parm);
5663
 
    }
5664
 
}
5665
 
 
5666
 
static void
5667
 
do_outputintr (int dev, int intr_flags)
5668
 
{
5669
 
  adev_p adev;
5670
 
  dmap_p dmap;
5671
 
  int cptr;
5672
 
  oss_native_word flags;
5673
 
 
5674
 
  adev = audio_engines[dev];
5675
 
  dmap = adev->dmap_out;
5676
 
 
5677
 
  MUTEX_ENTER_IRQDISABLE (dmap->mutex, flags);
5678
 
 
5679
 
  if (dmap->dmabuf == NULL)
5680
 
    {
5681
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5682
 
      cmn_err (CE_WARN, "Output interrupt when no buffer is allocated\n");
5683
 
      return;
5684
 
    }
5685
 
 
5686
 
  if (!(intr_flags & AINTR_NO_POINTER_UPDATES))
5687
 
    {
5688
 
      dmap->byte_counter += dmap->fragment_size;
5689
 
      dmap->interrupt_count++;
5690
 
    }
5691
 
 
5692
 
  dmap->fragment_counter = (dmap->fragment_counter + 1) % dmap->nfrags;
5693
 
 
5694
 
  if (dmap->user_counter <= dmap->byte_counter) /* Underrun */
5695
 
    {
5696
 
      if (!(dmap->mapping_flags & DMA_MAP_MAPPED))
5697
 
        {
5698
 
#ifdef DO_TIMINGS
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);
5703
 
#endif
5704
 
          dmap->play_underruns++;
5705
 
 
5706
 
          if (!dmap->underrun_flag)
5707
 
            {
5708
 
#ifdef DO_TIMINGS
5709
 
              oss_do_timing ("Clearing the buffer");
5710
 
#endif
5711
 
              memset (dmap->dmabuf, dmap->neutral_byte, dmap->buffsize);
5712
 
            }
5713
 
          dmap->underrun_flag = 1;
5714
 
#if 1
5715
 
          dmap->user_counter = dmap->byte_counter + dmap->fragment_size;
5716
 
#endif
5717
 
        }
5718
 
    }
5719
 
 
5720
 
  if (audio_space_in_queue (adev, dmap, 0) >= 0 || adev->nonblock)
5721
 
    {
5722
 
#ifdef DO_TIMINGS
5723
 
      oss_do_timing ("Wake up (out)");
5724
 
#endif
5725
 
      oss_wakeup (adev->out_wq, &dmap->mutex, &flags, POLLOUT | POLLWRNORM);
5726
 
    }
5727
 
 
5728
 
  if (adev->flags & ADEV_AUTOMODE)
5729
 
    {
5730
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5731
 
      finish_output_interrupt (adev, dmap);
5732
 
      return;
5733
 
    }
5734
 
 
5735
 
  cptr = dmap_get_qhead (dmap) * dmap->fragment_size;
5736
 
  MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5737
 
  if (adev->d->adrv_output_block != NULL)
5738
 
    {
5739
 
      adev->d->adrv_output_block (adev->engine_num, dmap->dmabuf_phys + cptr,
5740
 
                                  dmap->fragment_size, dmap->fragment_size,
5741
 
                                  1);
5742
 
    }
5743
 
  finish_output_interrupt (adev, dmap);
5744
 
}
5745
 
 
5746
 
static void
5747
 
audio_outputintr (int dev, int intr_flags)
5748
 
{
5749
 
  adev_p adev;
5750
 
  dmap_p dmap;
5751
 
  int n;
5752
 
  oss_uint64_t pos;
5753
 
 
5754
 
  if (dev < 0 || dev >= num_audio_engines)
5755
 
    return;
5756
 
 
5757
 
  adev = audio_engines[dev];
5758
 
  dmap = adev->dmap_out;
5759
 
 
5760
 
  if (dmap->dma_mode != PCM_ENABLE_OUTPUT)
5761
 
    {
5762
 
      return;
5763
 
    }
5764
 
 
5765
 
  if (!(dmap->flags & DMAP_STARTED))
5766
 
    {
5767
 
      return;
5768
 
    }
5769
 
 
5770
 
#ifdef DO_TIMINGS
5771
 
  oss_timing_printf ("Outputintr(%d)", dev);
5772
 
#endif
5773
 
  UP_STATUS (STS_INTR);
5774
 
 
5775
 
  if (adev->d->adrv_get_output_pointer == NULL
5776
 
      || (intr_flags & AINTR_NO_POINTER_UPDATES))
5777
 
    {
5778
 
      UP_STATUS (STS_DOINTR);
5779
 
      do_outputintr (dev, intr_flags);
5780
 
      DOWN_STATUS (STS_DOINTR | STS_INTR);
5781
 
      return;
5782
 
    }
5783
 
 
5784
 
  pos = get_output_pointer (adev, dmap, 0) / dmap->fragment_size;
5785
 
  n = 0;
5786
 
 
5787
 
  while (dmap_get_qhead (dmap) != pos && n++ < dmap->nfrags)
5788
 
    {
5789
 
      UP_STATUS (STS_DOINTR);
5790
 
      do_outputintr (dev, intr_flags);
5791
 
      DOWN_STATUS (STS_DOINTR);
5792
 
    }
5793
 
  DOWN_STATUS (STS_INTR);
5794
 
}
5795
 
 
5796
 
void
5797
 
oss_audio_reset (int dev)
5798
 
{
5799
 
  adev_p adev;
5800
 
  if (dev < 0 || dev >= num_audio_engines)
5801
 
    return;
5802
 
  adev = audio_engines[dev];
5803
 
 
5804
 
  audio_reset_adev (adev);
5805
 
 
5806
 
  if (adev->dmask & DMASK_OUT)
5807
 
    reset_dmap (adev->dmap_out);
5808
 
  if (adev->dmask & DMASK_IN)
5809
 
    reset_dmap (adev->dmap_in);
5810
 
}
5811
 
 
5812
 
void
5813
 
oss_audio_start_syncgroup (unsigned int syncgroup)
5814
 
{
5815
 
/*
5816
 
 * This routine is to be called by the /dev/midi driver to start a sync group
5817
 
 * at the right time.
5818
 
 */
5819
 
  oss_native_word flags;
5820
 
 
5821
 
  MUTEX_ENTER_IRQDISABLE (audio_global_mutex, flags);
5822
 
  handle_syncstart (syncgroup & SYNC_DEVICE_MASK, syncgroup);
5823
 
  MUTEX_EXIT_IRQRESTORE (audio_global_mutex, flags);
5824
 
}
5825
 
 
5826
 
#ifdef ALLOW_SELECT
5827
 
/*ARGSUSED*/
5828
 
static int
5829
 
chpoll_output (int dev, struct fileinfo *file, oss_poll_event_t * ev)
5830
 
{
5831
 
  short events = ev->events;
5832
 
  adev_p adev;
5833
 
  dmap_p dmap;
5834
 
  oss_native_word flags;
5835
 
  audio_buf_info bi;
5836
 
  int limit;
5837
 
 
5838
 
#ifdef DO_TIMINGS
5839
 
  oss_timing_printf ("--- audio_chpoll_output(%d, %08x) ---", dev, events);
5840
 
#endif
5841
 
 
5842
 
  if (dev < 0 || dev >= num_audio_engines)
5843
 
    return OSS_ENXIO;
5844
 
  adev = audio_engines[dev];
5845
 
 
5846
 
      dmap = adev->dmap_out;
5847
 
      if (dmap->mapping_flags & DMA_MAP_MAPPED)
5848
 
        {
5849
 
#if 1
5850
 
      /*
5851
 
       * It might actually be better to permit pollling in mmapped
5852
 
       * mode rather than returning an error.
5853
 
       */
5854
 
      if (dmap->interrupt_count > 0)
5855
 
         ev->revents |= (POLLOUT | POLLWRNORM) & events;
5856
 
      return 0;
5857
 
#else
5858
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
5859
 
                               OSSERR (1014,
5860
 
                                       "select/poll called for an OSS device in mmap mode."),
5861
 
                               0);
5862
 
          /*
5863
 
           * Errordesc:
5864
 
           * The select() and poll() system calls are not defined for OSS devices
5865
 
           * when the device is in mmap mode.
5866
 
           */
5867
 
          return OSS_EPERM;
5868
 
#endif
5869
 
        }
5870
 
 
5871
 
      if (dmap->dma_mode == PCM_ENABLE_INPUT)
5872
 
        {
5873
 
          oss_audio_set_error (adev->engine_num, E_PLAY,
5874
 
                               OSSERR (1015,
5875
 
                                       "select/poll called for wrong direction."),
5876
 
                               0);
5877
 
          /*
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
5881
 
           * happen.
5882
 
           */
5883
 
          return 0;
5884
 
        }
5885
 
 
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 */
5893
 
#ifdef DO_TIMINGS
5894
 
          oss_do_timing ("Output not ready yet");
5895
 
#endif
5896
 
          oss_register_poll (adev->out_wq, &dmap->mutex, &flags, ev);
5897
 
        }
5898
 
      else
5899
 
        {
5900
 
#ifdef DO_TIMINGS
5901
 
          oss_do_timing ("Reporting output ready");
5902
 
#endif
5903
 
          ev->revents |= (POLLOUT | POLLWRNORM) & events;
5904
 
        }
5905
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
5906
 
 
5907
 
  return 0;
5908
 
}
5909
 
 
5910
 
/*ARGSUSED*/
5911
 
static int
5912
 
chpoll_input (int dev, struct fileinfo *file, oss_poll_event_t * ev)
5913
 
{
5914
 
  short events = ev->events;
5915
 
  adev_p adev;
5916
 
  dmap_p dmap;
5917
 
  oss_native_word flags;
5918
 
  audio_buf_info bi;
5919
 
  int limit;
5920
 
 
5921
 
#ifdef DO_TIMINGS
5922
 
  oss_timing_printf ("--- audio_chpoll_input(%d, %08x) ---", dev, events);
5923
 
#endif
5924
 
 
5925
 
  if (dev < 0 || dev >= num_audio_engines)
5926
 
    return OSS_ENXIO;
5927
 
  adev = audio_engines[dev];
5928
 
 
5929
 
  dmap = adev->dmap_in;
5930
 
      if (dmap->mapping_flags & DMA_MAP_MAPPED)
5931
 
        {
5932
 
#if 1
5933
 
      /*
5934
 
       * It might actually be better to permit pollling in mmapped
5935
 
       * mode rather than returning an error.
5936
 
       */
5937
 
      if (dmap->interrupt_count > 0)
5938
 
         ev->revents |= (POLLOUT | POLLWRNORM) & events;
5939
 
      return 0;
5940
 
#else
5941
 
          oss_audio_set_error (adev->engine_num, E_REC,
5942
 
                               OSSERR (1013,
5943
 
                                       "select/poll called for an OSS device in mmap mode."),
5944
 
                               0);
5945
 
          /*
5946
 
           * Errordesc:
5947
 
           * The select() and poll() system calls are not defined for OSS devices
5948
 
           * when the device is in mmap mode.
5949
 
           */
5950
 
          return OSS_EIO;
5951
 
#endif
5952
 
        }
5953
 
 
5954
 
      if (dmap->dma_mode != PCM_ENABLE_INPUT)
5955
 
        {
5956
 
          oss_audio_set_error (adev->engine_num, E_REC,
5957
 
                               OSSERR (1016,
5958
 
                                       "select/poll called for wrong direction."),
5959
 
                               0);
5960
 
          /*
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
5964
 
           * happen.
5965
 
           */
5966
 
          return 0;
5967
 
        }
5968
 
 
5969
 
      if (!(dmap->flags & DMAP_STARTED))
5970
 
        {
5971
 
          oss_audio_set_error (adev->engine_num, E_REC,
5972
 
                               OSSERR (1017,
5973
 
                                       "select/poll called before recording is started."),
5974
 
                               0);
5975
 
          /*
5976
 
           * Errordesc:
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.
5981
 
           */
5982
 
        }
5983
 
 
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 */
5991
 
#ifdef DO_TIMINGS
5992
 
          oss_timing_printf ("Input not ready yet (%d/%d)\n", bi.bytes,
5993
 
                   dmap->low_water);
5994
 
#endif
5995
 
          oss_register_poll (adev->in_wq, &dmap->mutex, &flags, ev);
5996
 
        }
5997
 
      else
5998
 
        {
5999
 
#ifdef DO_TIMINGS
6000
 
          oss_do_timing ("Reporting input ready");
6001
 
#endif
6002
 
          ev->revents |= (POLLIN | POLLRDNORM) & events;
6003
 
        }
6004
 
      MUTEX_EXIT_IRQRESTORE (dmap->mutex, flags);
6005
 
 
6006
 
  return 0;
6007
 
}
6008
 
 
6009
 
/*ARGSUSED*/
6010
 
int
6011
 
oss_audio_chpoll (int dev, struct fileinfo *file, oss_poll_event_t * ev)
6012
 
{
6013
 
  short events = ev->events;
6014
 
  adev_p adev;
6015
 
 
6016
 
#ifdef DO_TIMINGS
6017
 
  oss_timing_printf ("--- audio_chpoll(%d, %08x) ---", dev, events);
6018
 
#endif
6019
 
 
6020
 
  if (dev < 0 || dev >= num_audio_engines)
6021
 
    return OSS_ENXIO;
6022
 
  adev = audio_engines[dev];
6023
 
 
6024
 
  if ((events & (POLLOUT | POLLWRNORM)) && (adev->open_mode & OPEN_WRITE))
6025
 
    {
6026
 
            int err;
6027
 
 
6028
 
            if ((err=chpoll_output (dev, file, ev))<0)
6029
 
               return err;
6030
 
    }
6031
 
 
6032
 
  if ((events & (POLLIN | POLLRDNORM)) && (adev->open_mode & OPEN_READ))
6033
 
    {
6034
 
            int err;
6035
 
 
6036
 
            if ((err=chpoll_input (dev, file, ev))<0)
6037
 
               return err;
6038
 
    }
6039
 
 
6040
 
  return 0;
6041
 
}
6042
 
#endif
6043
 
 
6044
 
/*ARGSUSED*/
6045
 
static void
6046
 
dummy_inputintr (int dev, int intr_flags)
6047
 
{
6048
 
  /* Dummy input interrupt handler */
6049
 
}
6050
 
 
6051
 
/*ARGSUSED*/
6052
 
static void
6053
 
dummy_outputintr (int dev, int x)
6054
 
{
6055
 
  /* Dummy output interrupt handler */
6056
 
}
6057
 
 
6058
 
static oss_cdev_drv_t audio_cdev_drv = {
6059
 
#ifdef VDEV_SUPPORT
6060
 
  oss_audio_open_devfile,
6061
 
#else
6062
 
  oss_audio_open_engine,
6063
 
#endif
6064
 
  oss_audio_release,
6065
 
  oss_audio_read,
6066
 
  oss_audio_write,
6067
 
  oss_audio_ioctl,
6068
 
#ifdef ALLOW_SELECT
6069
 
  oss_audio_chpoll
6070
 
#else
6071
 
  NULL
6072
 
#endif
6073
 
};
6074
 
 
6075
 
#ifdef MANAGE_DEV_DSP
6076
 
#ifdef VDEV_SUPPORT
6077
 
static oss_cdev_drv_t vdsp_cdev_drv = {
6078
 
  oss_open_vdsp,
6079
 
  oss_audio_release,
6080
 
  oss_audio_read,
6081
 
  oss_audio_write,
6082
 
  oss_audio_ioctl,
6083
 
#ifdef ALLOW_SELECT
6084
 
  oss_audio_chpoll
6085
 
#else
6086
 
  NULL
6087
 
#endif
6088
 
};
6089
 
#endif
6090
 
#endif
6091
 
 
6092
 
static oss_cdev_drv_t audio_engine_cdev_drv = {
6093
 
  oss_audio_open_engine,
6094
 
  oss_audio_release,
6095
 
  oss_audio_read,
6096
 
  oss_audio_write,
6097
 
  oss_audio_ioctl,
6098
 
#ifdef ALLOW_SELECT
6099
 
  oss_audio_chpoll
6100
 
#else
6101
 
  NULL
6102
 
#endif
6103
 
};
6104
 
 
6105
 
void
6106
 
oss_audio_register_client (oss_audio_startup_func func, void *devc,
6107
 
                           oss_device_t * osdev)
6108
 
{
6109
 
/*
6110
 
 * Register a callback for a driver that wants to be initialized after a new audio device
6111
 
 * is installed.
6112
 
 */
6113
 
 
6114
 
  if (num_audio_startups >= MAX_STARTUPS)
6115
 
    return;
6116
 
 
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++;
6121
 
}
6122
 
 
6123
 
void
6124
 
oss_add_audio_devlist (int list_id, int devfile)
6125
 
{
6126
 
#if 0
6127
 
/*
6128
 
 * Device list support is not in use at this moment
6129
 
 */
6130
 
  oss_devlist_t *list;
6131
 
  int i;
6132
 
 
6133
 
  switch (list_id)
6134
 
    {
6135
 
    case OPEN_READ:
6136
 
      list = &dspinlist;
6137
 
      break;
6138
 
 
6139
 
    case OPEN_WRITE:
6140
 
      list = &dspoutlist;
6141
 
      break;
6142
 
 
6143
 
    case OPEN_READ | OPEN_WRITE:
6144
 
      list = &dspinoutlist;
6145
 
      break;
6146
 
 
6147
 
    default:
6148
 
      cmn_err (CE_CONT, "Bad device list ID %d\n", list_id);
6149
 
      return;
6150
 
    }
6151
 
 
6152
 
  for (i = 0; i < list->ndevs; i++)
6153
 
    if (list->devices[i] == devfile)    /* Already there */
6154
 
      return;
6155
 
 
6156
 
  /*
6157
 
   * Add the device to the list
6158
 
   */
6159
 
  list->devices[list->ndevs++] = devfile;
6160
 
#endif
6161
 
}
6162
 
 
6163
 
#if 0
6164
 
static void
6165
 
add_to_devlists (adev_p adev)
6166
 
{
6167
 
/*
6168
 
 * Add the device to the default input, output and/or input/output lists
6169
 
 * for /dev/dsp.
6170
 
 */
6171
 
 
6172
 
  if (!(adev->flags & ADEV_SPECIAL))
6173
 
    {
6174
 
      if (!(adev->flags & ADEV_NOOUTPUT))
6175
 
        {                       /* Output capable */
6176
 
 
6177
 
          if (adev->flags & ADEV_VIRTUAL)
6178
 
            {
6179
 
              int n = dspoutlist.ndevs++;
6180
 
 
6181
 
              if (adev->flags & ADEV_DEFAULT)
6182
 
                {
6183
 
                  int i;
6184
 
 
6185
 
                  for (i = n; i > 0; i--)
6186
 
                    dspoutlist.devices[i] = dspoutlist.devices[i - 1];
6187
 
                  dspoutlist.devices[0] = adev->audio_devfile;
6188
 
                }
6189
 
              else
6190
 
                dspoutlist.devices[n] = adev->audio_devfile;
6191
 
            }
6192
 
          else
6193
 
            {
6194
 
              /* Put non-virtual devices to a secondary list */
6195
 
              int n = dspoutlist2.ndevs++;
6196
 
              dspoutlist2.devices[n] = adev->audio_devfile;
6197
 
            }
6198
 
 
6199
 
        }
6200
 
 
6201
 
      if (!(adev->flags & (ADEV_NOINPUT)))
6202
 
        {                       /* Input capable */
6203
 
 
6204
 
          int n = dspinlist.ndevs++;
6205
 
 
6206
 
          if (adev->flags & ADEV_DEFAULT)
6207
 
            {
6208
 
              int i;
6209
 
 
6210
 
              for (i = n; i > 0; i--)
6211
 
                dspinlist.devices[i] = dspinlist.devices[i - 1];
6212
 
              dspinlist.devices[0] = adev->audio_devfile;
6213
 
            }
6214
 
          else
6215
 
            dspinlist.devices[n] = adev->audio_devfile;
6216
 
        }
6217
 
 
6218
 
      if (!(adev->flags & (ADEV_NOINPUT | ADEV_NOOUTPUT))
6219
 
          || (adev->flags & ADEV_DUPLEX))
6220
 
        {                       /* Input/output capable */
6221
 
 
6222
 
          int n = dspinoutlist.ndevs++;
6223
 
 
6224
 
          if (adev->flags & ADEV_DEFAULT)
6225
 
            {
6226
 
              int i;
6227
 
 
6228
 
              for (i = n; i > 0; i--)
6229
 
                dspinoutlist.devices[i] = dspinoutlist.devices[i - 1];
6230
 
              dspinoutlist.devices[0] = adev->audio_devfile;
6231
 
            }
6232
 
          else
6233
 
            dspinoutlist.devices[n] = adev->audio_devfile;
6234
 
        }
6235
 
    }
6236
 
}
6237
 
#endif
6238
 
 
6239
 
static int
6240
 
resize_array(oss_device_t *osdev, adev_t ***arr, int *size, int increment)
6241
 
{
6242
 
        adev_t **old=*arr, **new = *arr;
6243
 
        int old_size = *size;
6244
 
        int new_size = *size;
6245
 
                
6246
 
        if (new_size >= HARD_MAX_AUDIO_DEVFILES) /* Too many device files */
6247
 
           return 0;
6248
 
 
6249
 
        new_size += increment;
6250
 
        if (new_size > HARD_MAX_AUDIO_DEVFILES)
6251
 
           new_size = HARD_MAX_AUDIO_DEVFILES;
6252
 
 
6253
 
        if ((new=AUDIO_MALLOC(osdev, new_size * sizeof (adev_t *)))==NULL)
6254
 
           return 0;
6255
 
 
6256
 
        memset(new, 0, new_size * sizeof(adev_t *));
6257
 
        if (old != NULL)
6258
 
           memcpy(new, old, old_size * sizeof(adev_t *));
6259
 
 
6260
 
        *size = new_size;
6261
 
        *arr = new;
6262
 
 
6263
 
        if (old != NULL)
6264
 
           AUDIO_FREE(osdev, old);
6265
 
 
6266
 
        return 1;
6267
 
}
6268
 
 
6269
 
int
6270
 
oss_install_audiodev_with_devname (int vers,
6271
 
                      oss_device_t * osdev,
6272
 
                      oss_device_t * master_osdev,
6273
 
                      char *name,
6274
 
                      const audiodrv_t * driver,
6275
 
                      int driver_size,
6276
 
                      int flags,
6277
 
                      unsigned int format_mask, void *devc, int parent,
6278
 
                      const char * devfile_name)
6279
 
{
6280
 
  audiodrv_t *d;
6281
 
  adev_t *op;
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;
6287
 
 
6288
 
  if (devc == NULL)
6289
 
     {
6290
 
             cmn_err(CE_WARN, "devc==NULL for %s. Cannot install audio device\n", name);
6291
 
             return OSS_EINVAL;
6292
 
     }
6293
 
 
6294
 
  if (name == NULL)
6295
 
    cmn_err (CE_CONT, "Name is really NULL\n");
6296
 
  if (master_osdev == NULL)
6297
 
    master_osdev = osdev;
6298
 
 
6299
 
#ifdef VDEV_SUPPORT
6300
 
  if (flags & (ADEV_SHADOW | ADEV_HIDDEN))
6301
 
    hidden_device = 1;
6302
 
#else
6303
 
  flags &= ~ADEV_HIDDEN;
6304
 
  hidden_device = 0;
6305
 
#endif
6306
 
 
6307
 
  if (audio_engines == NULL)
6308
 
    {
6309
 
      audio_engines = AUDIO_MALLOC (NULL, sizeof (adev_t *) * MAX_AUDIO_ENGINES);
6310
 
      memset (audio_engines, 0, sizeof (adev_t *) * MAX_AUDIO_ENGINES);
6311
 
    }
6312
 
 
6313
 
  if (audio_devfiles == NULL)
6314
 
    {
6315
 
      audio_devfiles = AUDIO_MALLOC (NULL, sizeof (adev_t *) * MAX_AUDIO_DEVFILES);
6316
 
      memset (audio_devfiles, 0, sizeof (adev_t *) * MAX_AUDIO_DEVFILES);
6317
 
    }
6318
 
 
6319
 
  if (vers != OSS_AUDIO_DRIVER_VERSION)
6320
 
    {
6321
 
      cmn_err (CE_WARN, "Incompatible audio driver for %s\n", name);
6322
 
      return OSS_EIO;
6323
 
    }
6324
 
 
6325
 
  if (driver_size > sizeof (audiodrv_t))
6326
 
    driver_size = sizeof (audiodrv_t);
6327
 
/*
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.
6331
 
 */
6332
 
 
6333
 
  num = -1;
6334
 
 
6335
 
  for (i = 0; i < num_audio_engines; i++)
6336
 
    {
6337
 
 
6338
 
      if ((audio_engines[i]->flags & (ADEV_SHADOW|ADEV_HIDDEN)) !=
6339
 
                      (flags & (ADEV_SHADOW|ADEV_HIDDEN))) /* Different visibility */
6340
 
         continue;
6341
 
 
6342
 
      if (audio_engines[i]->unloaded
6343
 
          && audio_engines[i]->os_id == oss_get_osid (osdev))
6344
 
        {
6345
 
          /* This audio device was previously connected to the same physical device */
6346
 
 
6347
 
          num = i;
6348
 
          reinsterted_device = 1;
6349
 
          DDB (cmn_err
6350
 
               (CE_NOTE, "Audio device %d got re-installed again.\n", i));
6351
 
          break;
6352
 
        }
6353
 
    }
6354
 
 
6355
 
  if (num == -1)
6356
 
    {
6357
 
 
6358
 
      if (num_audio_engines >= MAX_AUDIO_ENGINES)
6359
 
        {
6360
 
                if (!resize_array(osdev, &audio_engines, &oss_max_audio_engines, AUDIO_ENGINE_INCREMENT))
6361
 
                   {
6362
 
                        cmn_err (CE_CONT, "Cannot grow audio_engines[]\n");
6363
 
                        return OSS_EIO;
6364
 
                   }
6365
 
        }
6366
 
 
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++;
6376
 
 
6377
 
      update_devlists = 1;
6378
 
 
6379
 
      sprintf (op->handle, "%s-au%02d", osdev->handle,
6380
 
               osdev->num_audio_engines + 1);
6381
 
      op->port_number = osdev->num_audio_engines;
6382
 
    }
6383
 
  else
6384
 
    {
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;
6391
 
    }
6392
 
 
6393
 
  if (d == NULL || op == NULL)
6394
 
    {
6395
 
      cmn_err (CE_WARN, "Can't allocate driver for %s (adev=%p, d=%p)\n",
6396
 
               name, op, d);
6397
 
      return OSS_ENOSPC;
6398
 
    }
6399
 
 
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;
6404
 
 
6405
 
  op->d = d;
6406
 
  op->os_id = oss_get_osid (osdev);
6407
 
  op->enabled = 0;
6408
 
  op->outputintr = dummy_outputintr;
6409
 
  op->inputintr = dummy_inputintr;
6410
 
  op->vmix_mixer = NULL;
6411
 
 
6412
 
  strncpy (op->name, name, sizeof (op->name));
6413
 
  op->name[sizeof (op->name) - 1] = 0;
6414
 
  op->caps = 0;
6415
 
 
6416
 
  op->flags = flags;
6417
 
  op->latency = -1;             /* Unknown */
6418
 
 
6419
 
  op->oformat_mask = format_mask;
6420
 
  op->iformat_mask = format_mask;
6421
 
  op->mixer_dev = -1;
6422
 
  op->min_channels = 1;
6423
 
  op->max_channels = 2;
6424
 
  op->min_rate = 8000;
6425
 
  op->max_rate = 44100;
6426
 
  op->devc = devc;
6427
 
  op->parent_dev = parent + 1;
6428
 
  op->dmap_in = NULL;
6429
 
  op->dmap_out = NULL;
6430
 
  memset (op->cmd, 0, sizeof (op->cmd));
6431
 
  op->pid = -1;
6432
 
  op->osdev = osdev;
6433
 
  op->master_osdev = master_osdev;
6434
 
  op->card_number = osdev->cardnum;
6435
 
  op->engine_num = op->rate_source = num;
6436
 
  op->real_dev = num;
6437
 
  op->redirect_in = -1;
6438
 
  op->redirect_out = -1;
6439
 
  op->dmabuf_alloc_flags = 0;
6440
 
  op->dmabuf_maxaddr = MEMLIMIT_32BITS;
6441
 
 
6442
 
  audio_engines[num] = op;
6443
 
  op->next_out = NULL;
6444
 
  op->next_in = NULL;
6445
 
 
6446
 
  op->song_name[0] = 0;
6447
 
  op->label[0] = 0;
6448
 
  op->nrates=0;
6449
 
 
6450
 
  if ((flags & ADEV_SHADOW) && num > 0)
6451
 
    {
6452
 
      adev_p prev = audio_engines[num - 1];     /* Previous device */
6453
 
 
6454
 
      prev->next_out = op;
6455
 
      prev->next_in = op;
6456
 
    }
6457
 
 
6458
 
  if (audio_init_device (num) < 0)
6459
 
    return OSS_ENOMEM;
6460
 
 
6461
 
/*
6462
 
 * Create the device node.
6463
 
 */
6464
 
#ifndef VDEV_SUPPORT
6465
 
  flat_device_model = 1;
6466
 
  hidden_device = 0;
6467
 
#endif
6468
 
 
6469
 
  if (reinsterted_device)
6470
 
    {
6471
 
      /*
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.
6475
 
       */
6476
 
      devfile_num = op->audio_devfile;
6477
 
      chdev_flags |= CHDEV_REPLUG;
6478
 
    }
6479
 
  else
6480
 
    {
6481
 
      if (!hidden_device)
6482
 
        {
6483
 
          if (num_audio_devfiles >= MAX_AUDIO_DEVFILES)
6484
 
             {
6485
 
                if (!resize_array(osdev, &audio_devfiles, &oss_max_audio_devfiles, AUDIO_DEVFILE_INCREMENT))
6486
 
                   {
6487
 
                        cmn_err (CE_CONT, "Cannot grow audio_devfiles[]\n");
6488
 
                        return num;
6489
 
                   }
6490
 
             }
6491
 
 
6492
 
             audio_devfiles[num_audio_devfiles] = op;
6493
 
             devfile_num = num_audio_devfiles++;
6494
 
        }
6495
 
    }
6496
 
 
6497
 
  if (flat_device_model || !hidden_device)
6498
 
    {
6499
 
#ifdef NEW_DEVICE_NAMING
6500
 
      oss_devnode_t name;
6501
 
      char tmpl[32];
6502
 
 
6503
 
      if (*devfile_name != 0)
6504
 
        {
6505
 
          /*
6506
 
           * A name was suggested by the low level driver
6507
 
           */
6508
 
          strcpy (tmpl, devfile_name);
6509
 
        }
6510
 
      else if (flags & ADEV_NOOUTPUT)
6511
 
        sprintf (tmpl, "pcmin%d", osdev->num_audiorec++);
6512
 
      else
6513
 
        sprintf (tmpl, "pcm%d", osdev->num_audioduplex++);
6514
 
 
6515
 
# ifdef USE_DEVICE_SUBDIRS
6516
 
      sprintf (name, "oss/%s/%s", osdev->nick, tmpl);
6517
 
# else
6518
 
      sprintf (name, "%s_%s", osdev->nick, tmpl);
6519
 
# endif
6520
 
#else
6521
 
      sprintf (name, "dsp%d", num);
6522
 
#endif
6523
 
 
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++;
6531
 
 
6532
 
      op->enabled = 1;
6533
 
      op->unloaded = 0;
6534
 
 
6535
 
    }
6536
 
  else
6537
 
    {
6538
 
      op->real_dev = -1;
6539
 
      if (devfile_num > 0 && (flags & ADEV_SHADOW))
6540
 
        {
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);
6544
 
          else
6545
 
            strcpy (op->devnode, "Unknown");
6546
 
          audio_devfiles[devfile_num] = op;
6547
 
        }
6548
 
      else
6549
 
        {
6550
 
          strcpy (op->devnode, "HiddenAudioDevice");
6551
 
        }
6552
 
      op->enabled = 1;
6553
 
      op->unloaded = 0;
6554
 
    }
6555
 
 
6556
 
//#ifdef VDEV_SUPPORT
6557
 
  oss_install_chrdev (osdev, NULL, OSS_DEV_DSP_ENGINE, num,
6558
 
                      &audio_engine_cdev_drv, chdev_flags);
6559
 
//#endif
6560
 
 
6561
 
#if 0
6562
 
  if (!reinsterted_device && update_devlists && !hidden_device)
6563
 
    add_to_devlists (op);
6564
 
#endif
6565
 
 
6566
 
  {
6567
 
    int i;
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);
6574
 
  }
6575
 
 
6576
 
  return num;
6577
 
}
6578
 
 
6579
 
int
6580
 
oss_install_audiodev (int vers,
6581
 
                      oss_device_t * osdev,
6582
 
                      oss_device_t * master_osdev,
6583
 
                      char *name,
6584
 
                      const audiodrv_t * driver,
6585
 
                      int driver_size,
6586
 
                      unsigned long long flags,
6587
 
                      unsigned int format_mask, void *devc, int parent)
6588
 
{
6589
 
 return oss_install_audiodev_with_devname (vers,
6590
 
                      osdev,
6591
 
                      master_osdev,
6592
 
                      name,
6593
 
                      driver,
6594
 
                      driver_size,
6595
 
                      flags,
6596
 
                      format_mask, devc, parent,
6597
 
                      ""); /* Use default device file naming */
6598
 
}
6599
 
 
6600
 
void
6601
 
oss_audio_delayed_attach (void)
6602
 
{
6603
 
  int i;
6604
 
 
6605
 
  /*
6606
 
   * Serve possible other drivers waiting for new friends.
6607
 
   */
6608
 
  for (i = 0; i < num_audio_startups; i++)
6609
 
    {
6610
 
      if (audio_startups[i].osdev != NULL
6611
 
          && audio_startups[i].osdev->available)
6612
 
        {
6613
 
          if (audio_startups[i].func (audio_startups[i].devc))
6614
 
            audio_startups[i].osdev = NULL;     /* Inactivate it */
6615
 
        }
6616
 
    }
6617
 
}
6618
 
 
6619
 
/*ARGSUSED*/
6620
 
void
6621
 
install_vdsp (oss_device_t * osdev)
6622
 
{
6623
 
#ifdef MANAGE_DEV_DSP
6624
 
/*
6625
 
 * Install the driver for /dev/dsp (the multiplexer device)
6626
 
 *
6627
 
 * NOTE! Not used at this moment because /dev/dsp assignment is managed in user
6628
 
 *       space (by ossdevlinks).
6629
 
 */
6630
 
#ifdef VDEV_SUPPORT
6631
 
  oss_install_chrdev (osdev, "dsp", OSS_DEV_VDSP, 0, &vdsp_cdev_drv,
6632
 
                      CHDEV_VIRTUAL);
6633
 
  oss_install_chrdev (osdev, "dsp_in", OSS_DEV_VDSP, 1, &vdsp_cdev_drv,
6634
 
                      CHDEV_VIRTUAL);
6635
 
  oss_install_chrdev (osdev, "dsp_out", OSS_DEV_VDSP, 2, &vdsp_cdev_drv,
6636
 
                      CHDEV_VIRTUAL);
6637
 
#endif
6638
 
#endif
6639
 
}