linux/sound/oss/audio.c
<<
>>
Prefs
   1/*
   2 * sound/oss/audio.c
   3 *
   4 * Device file manager for /dev/audio
   5 */
   6
   7/*
   8 * Copyright (C) by Hannu Savolainen 1993-1997
   9 *
  10 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  11 * Version 2 (June 1991). See the "COPYING" file distributed with this software
  12 * for more info.
  13 */
  14/*
  15 * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
  16 * Thomas Sailer   : moved several static variables into struct audio_operations
  17 *                   (which is grossly misnamed btw.) because they have the same
  18 *                   lifetime as the rest in there and dynamic allocation saves
  19 *                   12k or so
  20 * Thomas Sailer   : use more logical O_NONBLOCK semantics
  21 * Daniel Rodriksson: reworked the use of the device specific copy_user
  22 *                    still generic
  23 * Horst von Brand:  Add missing #include <linux/string.h>
  24 * Chris Rankin    : Update the module-usage counter for the coprocessor,
  25 *                   and decrement the counters again if we cannot open
  26 *                   the audio device.
  27 */
  28
  29#include <linux/stddef.h>
  30#include <linux/string.h>
  31#include <linux/kmod.h>
  32
  33#include "sound_config.h"
  34#include "ulaw.h"
  35#include "coproc.h"
  36
  37#define NEUTRAL8        0x80
  38#define NEUTRAL16       0x00
  39
  40
  41static int             dma_ioctl(int dev, unsigned int cmd, void __user *arg);
  42
  43static int set_format(int dev, int fmt)
  44{
  45        if (fmt != AFMT_QUERY)
  46        {
  47                audio_devs[dev]->local_conversion = 0;
  48
  49                if (!(audio_devs[dev]->format_mask & fmt))      /* Not supported */
  50                {
  51                        if (fmt == AFMT_MU_LAW)
  52                        {
  53                                fmt = AFMT_U8;
  54                                audio_devs[dev]->local_conversion = CNV_MU_LAW;
  55                        }
  56                        else
  57                                fmt = AFMT_U8;  /* This is always supported */
  58                }
  59                audio_devs[dev]->audio_format = audio_devs[dev]->d->set_bits(dev, fmt);
  60                audio_devs[dev]->local_format = fmt;
  61        }
  62        else
  63                return audio_devs[dev]->local_format;
  64
  65        if (audio_devs[dev]->local_conversion)
  66                return audio_devs[dev]->local_conversion;
  67        else 
  68                return audio_devs[dev]->local_format;
  69}
  70
  71int audio_open(int dev, struct file *file)
  72{
  73        int ret;
  74        int bits;
  75        int dev_type = dev & 0x0f;
  76        int mode = translate_mode(file);
  77        const struct audio_driver *driver;
  78        const struct coproc_operations *coprocessor;
  79
  80        dev = dev >> 4;
  81
  82        if (dev_type == SND_DEV_DSP16)
  83                bits = 16;
  84        else
  85                bits = 8;
  86
  87        if (dev < 0 || dev >= num_audiodevs)
  88                return -ENXIO;
  89
  90        driver = audio_devs[dev]->d;
  91
  92        if (!try_module_get(driver->owner))
  93                return -ENODEV;
  94
  95        if ((ret = DMAbuf_open(dev, mode)) < 0)
  96                goto error_1;
  97
  98        if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
  99                if (!try_module_get(coprocessor->owner))
 100                        goto error_2;
 101
 102                if ((ret = coprocessor->open(coprocessor->devc, COPR_PCM)) < 0) {
 103                        printk(KERN_WARNING "Sound: Can't access coprocessor device\n");
 104                        goto error_3;
 105                }
 106        }
 107        
 108        audio_devs[dev]->local_conversion = 0;
 109
 110        if (dev_type == SND_DEV_AUDIO)
 111                set_format(dev, AFMT_MU_LAW);
 112        else 
 113                set_format(dev, bits);
 114
 115        audio_devs[dev]->audio_mode = AM_NONE;
 116
 117        return 0;
 118
 119        /*
 120         * Clean-up stack: this is what needs (un)doing if
 121         * we can't open the audio device ...
 122         */
 123        error_3:
 124        module_put(coprocessor->owner);
 125
 126        error_2:
 127        DMAbuf_release(dev, mode);
 128
 129        error_1:
 130        module_put(driver->owner);
 131
 132        return ret;
 133}
 134
 135static void sync_output(int dev)
 136{
 137        int             p, i;
 138        int             l;
 139        struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 140
 141        if (dmap->fragment_size <= 0)
 142                return;
 143        dmap->flags |= DMA_POST;
 144
 145        /* Align the write pointer with fragment boundaries */
 146        
 147        if ((l = dmap->user_counter % dmap->fragment_size) > 0)
 148        {
 149                int len;
 150                unsigned long offs = dmap->user_counter % dmap->bytes_in_use;
 151
 152                len = dmap->fragment_size - l;
 153                memset(dmap->raw_buf + offs, dmap->neutral_byte, len);
 154                DMAbuf_move_wrpointer(dev, len);
 155        }
 156        
 157        /*
 158         * Clean all unused buffer fragments.
 159         */
 160
 161        p = dmap->qtail;
 162        dmap->flags |= DMA_POST;
 163
 164        for (i = dmap->qlen + 1; i < dmap->nbufs; i++)
 165        {
 166                p = (p + 1) % dmap->nbufs;
 167                if (((dmap->raw_buf + p * dmap->fragment_size) + dmap->fragment_size) >
 168                        (dmap->raw_buf + dmap->buffsize))
 169                                printk(KERN_ERR "audio: Buffer error 2\n");
 170
 171                memset(dmap->raw_buf + p * dmap->fragment_size,
 172                        dmap->neutral_byte,
 173                        dmap->fragment_size);
 174        }
 175
 176        dmap->flags |= DMA_DIRTY;
 177}
 178
 179void audio_release(int dev, struct file *file)
 180{
 181        const struct coproc_operations *coprocessor;
 182        int mode = translate_mode(file);
 183
 184        dev = dev >> 4;
 185
 186        /*
 187         * We do this in DMAbuf_release(). Why are we doing it
 188         * here? Why don't we test the file mode before setting
 189         * both flags? DMAbuf_release() does.
 190         * ...pester...pester...pester...
 191         */
 192        audio_devs[dev]->dmap_out->closing = 1;
 193        audio_devs[dev]->dmap_in->closing = 1;
 194
 195        /*
 196         * We need to make sure we allocated the dmap_out buffer
 197         * before we go mucking around with it in sync_output().
 198         */
 199        if (mode & OPEN_WRITE)
 200                sync_output(dev);
 201
 202        if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
 203                coprocessor->close(coprocessor->devc, COPR_PCM);
 204                module_put(coprocessor->owner);
 205        }
 206        DMAbuf_release(dev, mode);
 207
 208        module_put(audio_devs[dev]->d->owner);
 209}
 210
 211static void translate_bytes(const unsigned char *table, unsigned char *buff, int n)
 212{
 213        unsigned long   i;
 214
 215        if (n <= 0)
 216                return;
 217
 218        for (i = 0; i < n; ++i)
 219                buff[i] = table[buff[i]];
 220}
 221
 222int audio_write(int dev, struct file *file, const char __user *buf, int count)
 223{
 224        int c, p, l, buf_size, used, returned;
 225        int err;
 226        char *dma_buf;
 227
 228        dev = dev >> 4;
 229
 230        p = 0;
 231        c = count;
 232        
 233        if(count < 0)
 234                return -EINVAL;
 235
 236        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 237                return -EPERM;
 238
 239        if (audio_devs[dev]->flags & DMA_DUPLEX)
 240                audio_devs[dev]->audio_mode |= AM_WRITE;
 241        else
 242                audio_devs[dev]->audio_mode = AM_WRITE;
 243
 244        if (!count)             /* Flush output */
 245        {
 246                  sync_output(dev);
 247                  return 0;
 248        }
 249        
 250        while (c)
 251        {
 252                if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, !!(file->f_flags & O_NONBLOCK))) < 0)
 253                {
 254                            /* Handle nonblocking mode */
 255                        if ((file->f_flags & O_NONBLOCK) && err == -EAGAIN)
 256                                return p? p : -EAGAIN;  /* No more space. Return # of accepted bytes */
 257                        return err;
 258                }
 259                l = c;
 260
 261                if (l > buf_size)
 262                        l = buf_size;
 263
 264                returned = l;
 265                used = l;
 266                if (!audio_devs[dev]->d->copy_user)
 267                {
 268                        if ((dma_buf + l) >
 269                                (audio_devs[dev]->dmap_out->raw_buf + audio_devs[dev]->dmap_out->buffsize))
 270                        {
 271                                printk(KERN_ERR "audio: Buffer error 3 (%lx,%d), (%lx, %d)\n", (long) dma_buf, l, (long) audio_devs[dev]->dmap_out->raw_buf, (int) audio_devs[dev]->dmap_out->buffsize);
 272                                return -EDOM;
 273                        }
 274                        if (dma_buf < audio_devs[dev]->dmap_out->raw_buf)
 275                        {
 276                                printk(KERN_ERR "audio: Buffer error 13 (%lx<%lx)\n", (long) dma_buf, (long) audio_devs[dev]->dmap_out->raw_buf);
 277                                return -EDOM;
 278                        }
 279                        if(copy_from_user(dma_buf, &(buf)[p], l))
 280                                return -EFAULT;
 281                } 
 282                else audio_devs[dev]->d->copy_user (dev,
 283                                                dma_buf, 0,
 284                                                buf, p,
 285                                                c, buf_size,
 286                                                &used, &returned,
 287                                                l);
 288                l = returned;
 289
 290                if (audio_devs[dev]->local_conversion & CNV_MU_LAW)
 291                {
 292                        translate_bytes(ulaw_dsp, (unsigned char *) dma_buf, l);
 293                }
 294                c -= used;
 295                p += used;
 296                DMAbuf_move_wrpointer(dev, l);
 297
 298        }
 299
 300        return count;
 301}
 302
 303int audio_read(int dev, struct file *file, char __user *buf, int count)
 304{
 305        int             c, p, l;
 306        char           *dmabuf;
 307        int             buf_no;
 308
 309        dev = dev >> 4;
 310        p = 0;
 311        c = count;
 312
 313        if (!(audio_devs[dev]->open_mode & OPEN_READ))
 314                return -EPERM;
 315
 316        if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 317                sync_output(dev);
 318
 319        if (audio_devs[dev]->flags & DMA_DUPLEX)
 320                audio_devs[dev]->audio_mode |= AM_READ;
 321        else
 322                audio_devs[dev]->audio_mode = AM_READ;
 323
 324        while(c)
 325        {
 326                if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l, !!(file->f_flags & O_NONBLOCK))) < 0)
 327                {
 328                        /*
 329                         *      Nonblocking mode handling. Return current # of bytes
 330                         */
 331
 332                        if (p > 0)              /* Avoid throwing away data */
 333                                return p;       /* Return it instead */
 334
 335                        if ((file->f_flags & O_NONBLOCK) && buf_no == -EAGAIN)
 336                                return -EAGAIN;
 337
 338                        return buf_no;
 339                }
 340                if (l > c)
 341                        l = c;
 342
 343                /*
 344                 * Insert any local processing here.
 345                 */
 346
 347                if (audio_devs[dev]->local_conversion & CNV_MU_LAW)
 348                {
 349                        translate_bytes(dsp_ulaw, (unsigned char *) dmabuf, l);
 350                }
 351                
 352                {
 353                        char           *fixit = dmabuf;
 354
 355                        if(copy_to_user(&(buf)[p], fixit, l))
 356                                return -EFAULT;
 357                };
 358
 359                DMAbuf_rmchars(dev, buf_no, l);
 360
 361                p += l;
 362                c -= l;
 363        }
 364
 365        return count - c;
 366}
 367
 368int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg)
 369{
 370        int val, count;
 371        unsigned long flags;
 372        struct dma_buffparms *dmap;
 373        int __user *p = arg;
 374
 375        dev = dev >> 4;
 376
 377        if (_IOC_TYPE(cmd) == 'C')      {
 378                if (audio_devs[dev]->coproc)    /* Coprocessor ioctl */
 379                        return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0);
 380                /* else
 381                        printk(KERN_DEBUG"/dev/dsp%d: No coprocessor for this device\n", dev); */
 382                return -ENXIO;
 383        }
 384        else switch (cmd) 
 385        {
 386                case SNDCTL_DSP_SYNC:
 387                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 388                                return 0;
 389                        if (audio_devs[dev]->dmap_out->fragment_size == 0)
 390                                return 0;
 391                        sync_output(dev);
 392                        DMAbuf_sync(dev);
 393                        DMAbuf_reset(dev);
 394                        return 0;
 395
 396                case SNDCTL_DSP_POST:
 397                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 398                                return 0;
 399                        if (audio_devs[dev]->dmap_out->fragment_size == 0)
 400                                return 0;
 401                        audio_devs[dev]->dmap_out->flags |= DMA_POST | DMA_DIRTY;
 402                        sync_output(dev);
 403                        dma_ioctl(dev, SNDCTL_DSP_POST, NULL);
 404                        return 0;
 405
 406                case SNDCTL_DSP_RESET:
 407                        audio_devs[dev]->audio_mode = AM_NONE;
 408                        DMAbuf_reset(dev);
 409                        return 0;
 410
 411                case SNDCTL_DSP_GETFMTS:
 412                        val = audio_devs[dev]->format_mask | AFMT_MU_LAW;
 413                        break;
 414        
 415                case SNDCTL_DSP_SETFMT:
 416                        if (get_user(val, p))
 417                                return -EFAULT;
 418                        val = set_format(dev, val);
 419                        break;
 420
 421                case SNDCTL_DSP_GETISPACE:
 422                        if (!(audio_devs[dev]->open_mode & OPEN_READ))
 423                                return 0;
 424                        if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 425                                return -EBUSY;
 426                        return dma_ioctl(dev, cmd, arg);
 427
 428                case SNDCTL_DSP_GETOSPACE:
 429                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 430                                return -EPERM;
 431                        if ((audio_devs[dev]->audio_mode & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
 432                                return -EBUSY;
 433                        return dma_ioctl(dev, cmd, arg);
 434                
 435                case SNDCTL_DSP_NONBLOCK:
 436                        spin_lock(&file->f_lock);
 437                        file->f_flags |= O_NONBLOCK;
 438                        spin_unlock(&file->f_lock);
 439                        return 0;
 440
 441                case SNDCTL_DSP_GETCAPS:
 442                                val = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */
 443                                if (audio_devs[dev]->flags & DMA_DUPLEX &&
 444                                        audio_devs[dev]->open_mode == OPEN_READWRITE)
 445                                        val |= DSP_CAP_DUPLEX;
 446                                if (audio_devs[dev]->coproc)
 447                                        val |= DSP_CAP_COPROC;
 448                                if (audio_devs[dev]->d->local_qlen)     /* Device has hidden buffers */
 449                                        val |= DSP_CAP_BATCH;
 450                                if (audio_devs[dev]->d->trigger)        /* Supports SETTRIGGER */
 451                                        val |= DSP_CAP_TRIGGER;
 452                                break;
 453                        
 454                case SOUND_PCM_WRITE_RATE:
 455                        if (get_user(val, p))
 456                                return -EFAULT;
 457                        val = audio_devs[dev]->d->set_speed(dev, val);
 458                        break;
 459
 460                case SOUND_PCM_READ_RATE:
 461                        val = audio_devs[dev]->d->set_speed(dev, 0);
 462                        break;
 463                        
 464                case SNDCTL_DSP_STEREO:
 465                        if (get_user(val, p))
 466                                return -EFAULT;
 467                        if (val > 1 || val < 0)
 468                                return -EINVAL;
 469                        val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1;
 470                        break;
 471
 472                case SOUND_PCM_WRITE_CHANNELS:
 473                        if (get_user(val, p))
 474                                return -EFAULT;
 475                        val = audio_devs[dev]->d->set_channels(dev, val);
 476                        break;
 477
 478                case SOUND_PCM_READ_CHANNELS:
 479                        val = audio_devs[dev]->d->set_channels(dev, 0);
 480                        break;
 481                
 482                case SOUND_PCM_READ_BITS:
 483                        val = audio_devs[dev]->d->set_bits(dev, 0);
 484                        break;
 485
 486                case SNDCTL_DSP_SETDUPLEX:
 487                        if (audio_devs[dev]->open_mode != OPEN_READWRITE)
 488                                return -EPERM;
 489                        return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO;
 490
 491                case SNDCTL_DSP_PROFILE:
 492                        if (get_user(val, p))
 493                                return -EFAULT;
 494                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 495                                audio_devs[dev]->dmap_out->applic_profile = val;
 496                        if (audio_devs[dev]->open_mode & OPEN_READ)
 497                                audio_devs[dev]->dmap_in->applic_profile = val;
 498                        return 0;
 499                
 500                case SNDCTL_DSP_GETODELAY:
 501                        dmap = audio_devs[dev]->dmap_out;
 502                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 503                                return -EINVAL;
 504                        if (!(dmap->flags & DMA_ALLOC_DONE))
 505                        {
 506                                val=0;
 507                                break;
 508                        }
 509                
 510                        spin_lock_irqsave(&dmap->lock,flags);
 511                        /* Compute number of bytes that have been played */
 512                        count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
 513                        if (count < dmap->fragment_size && dmap->qhead != 0)
 514                                count += dmap->bytes_in_use;    /* Pointer wrap not handled yet */
 515                        count += dmap->byte_counter;
 516                
 517                        /* Subtract current count from the number of bytes written by app */
 518                        count = dmap->user_counter - count;
 519                        if (count < 0)
 520                                count = 0;
 521                        spin_unlock_irqrestore(&dmap->lock,flags);
 522                        val = count;
 523                        break;
 524                
 525                default:
 526                        return dma_ioctl(dev, cmd, arg);
 527        }
 528        return put_user(val, p);
 529}
 530
 531void audio_init_devices(void)
 532{
 533        /*
 534         * NOTE! This routine could be called several times during boot.
 535         */
 536}
 537
 538void reorganize_buffers(int dev, struct dma_buffparms *dmap, int recording)
 539{
 540        /*
 541         * This routine breaks the physical device buffers to logical ones.
 542         */
 543
 544        struct audio_operations *dsp_dev = audio_devs[dev];
 545
 546        unsigned i, n;
 547        unsigned sr, nc, sz, bsz;
 548
 549        sr = dsp_dev->d->set_speed(dev, 0);
 550        nc = dsp_dev->d->set_channels(dev, 0);
 551        sz = dsp_dev->d->set_bits(dev, 0);
 552
 553        if (sz == 8)
 554                dmap->neutral_byte = NEUTRAL8;
 555        else
 556                dmap->neutral_byte = NEUTRAL16;
 557
 558        if (sr < 1 || nc < 1 || sz < 1)
 559        {
 560/*              printk(KERN_DEBUG "Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);*/
 561                sr = DSP_DEFAULT_SPEED;
 562                nc = 1;
 563                sz = 8;
 564        }
 565        
 566        sz = sr * nc * sz;
 567
 568        sz /= 8;                /* #bits -> #bytes */
 569        dmap->data_rate = sz;
 570
 571        if (!dmap->needs_reorg)
 572                return;
 573        dmap->needs_reorg = 0;
 574
 575        if (dmap->fragment_size == 0)
 576        {       
 577                /* Compute the fragment size using the default algorithm */
 578
 579                /*
 580                 * Compute a buffer size for time not exceeding 1 second.
 581                 * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds
 582                 * of sound (using the current speed, sample size and #channels).
 583                 */
 584
 585                bsz = dmap->buffsize;
 586                while (bsz > sz)
 587                        bsz /= 2;
 588
 589                if (bsz == dmap->buffsize)
 590                        bsz /= 2;       /* Needs at least 2 buffers */
 591
 592                /*
 593                 *    Split the computed fragment to smaller parts. After 3.5a9
 594                 *      the default subdivision is 4 which should give better
 595                 *      results when recording.
 596                 */
 597
 598                if (dmap->subdivision == 0)     /* Not already set */
 599                {
 600                        dmap->subdivision = 4;  /* Init to the default value */
 601
 602                        if ((bsz / dmap->subdivision) > 4096)
 603                                dmap->subdivision *= 2;
 604                        if ((bsz / dmap->subdivision) < 4096)
 605                                dmap->subdivision = 1;
 606                }
 607                bsz /= dmap->subdivision;
 608
 609                if (bsz < 16)
 610                        bsz = 16;       /* Just a sanity check */
 611
 612                dmap->fragment_size = bsz;
 613        }
 614        else
 615        {
 616                /*
 617                 * The process has specified the buffer size with SNDCTL_DSP_SETFRAGMENT or
 618                 * the buffer size computation has already been done.
 619                 */
 620                if (dmap->fragment_size > (dmap->buffsize / 2))
 621                        dmap->fragment_size = (dmap->buffsize / 2);
 622                bsz = dmap->fragment_size;
 623        }
 624
 625        if (audio_devs[dev]->min_fragment)
 626                if (bsz < (1 << audio_devs[dev]->min_fragment))
 627                        bsz = 1 << audio_devs[dev]->min_fragment;
 628        if (audio_devs[dev]->max_fragment)
 629                if (bsz > (1 << audio_devs[dev]->max_fragment))
 630                        bsz = 1 << audio_devs[dev]->max_fragment;
 631        bsz &= ~0x07;           /* Force size which is multiple of 8 bytes */
 632#ifdef OS_DMA_ALIGN_CHECK
 633        OS_DMA_ALIGN_CHECK(bsz);
 634#endif
 635
 636        n = dmap->buffsize / bsz;
 637        if (n > MAX_SUB_BUFFERS)
 638                n = MAX_SUB_BUFFERS;
 639        if (n > dmap->max_fragments)
 640                n = dmap->max_fragments;
 641
 642        if (n < 2)
 643        {
 644                n = 2;
 645                bsz /= 2;
 646        }
 647        dmap->nbufs = n;
 648        dmap->bytes_in_use = n * bsz;
 649        dmap->fragment_size = bsz;
 650        dmap->max_byte_counter = (dmap->data_rate * 60 * 60) +
 651                        dmap->bytes_in_use;     /* Approximately one hour */
 652
 653        if (dmap->raw_buf)
 654        {
 655                memset(dmap->raw_buf, dmap->neutral_byte, dmap->bytes_in_use);
 656        }
 657        
 658        for (i = 0; i < dmap->nbufs; i++)
 659        {
 660                dmap->counts[i] = 0;
 661        }
 662
 663        dmap->flags |= DMA_ALLOC_DONE | DMA_EMPTY;
 664}
 665
 666static int dma_subdivide(int dev, struct dma_buffparms *dmap, int fact)
 667{
 668        if (fact == 0) 
 669        {
 670                fact = dmap->subdivision;
 671                if (fact == 0)
 672                        fact = 1;
 673                return fact;
 674        }
 675        if (dmap->subdivision != 0 || dmap->fragment_size)      /* Too late to change */
 676                return -EINVAL;
 677
 678        if (fact > MAX_REALTIME_FACTOR)
 679                return -EINVAL;
 680
 681        if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
 682                return -EINVAL;
 683
 684        dmap->subdivision = fact;
 685        return fact;
 686}
 687
 688static int dma_set_fragment(int dev, struct dma_buffparms *dmap, int fact)
 689{
 690        int bytes, count;
 691
 692        if (fact == 0)
 693                return -EIO;
 694
 695        if (dmap->subdivision != 0 ||
 696            dmap->fragment_size)        /* Too late to change */
 697                return -EINVAL;
 698
 699        bytes = fact & 0xffff;
 700        count = (fact >> 16) & 0x7fff;
 701
 702        if (count == 0)
 703                count = MAX_SUB_BUFFERS;
 704        else if (count < MAX_SUB_BUFFERS)
 705                count++;
 706
 707        if (bytes < 4 || bytes > 17)    /* <16 || > 512k */
 708                return -EINVAL;
 709
 710        if (count < 2)
 711                return -EINVAL;
 712
 713        if (audio_devs[dev]->min_fragment > 0)
 714                if (bytes < audio_devs[dev]->min_fragment)
 715                        bytes = audio_devs[dev]->min_fragment;
 716
 717        if (audio_devs[dev]->max_fragment > 0)
 718                if (bytes > audio_devs[dev]->max_fragment)
 719                        bytes = audio_devs[dev]->max_fragment;
 720
 721#ifdef OS_DMA_MINBITS
 722        if (bytes < OS_DMA_MINBITS)
 723                bytes = OS_DMA_MINBITS;
 724#endif
 725
 726        dmap->fragment_size = (1 << bytes);
 727        dmap->max_fragments = count;
 728
 729        if (dmap->fragment_size > dmap->buffsize)
 730                dmap->fragment_size = dmap->buffsize;
 731
 732        if (dmap->fragment_size == dmap->buffsize &&
 733            audio_devs[dev]->flags & DMA_AUTOMODE)
 734                dmap->fragment_size /= 2;       /* Needs at least 2 buffers */
 735
 736        dmap->subdivision = 1;  /* Disable SNDCTL_DSP_SUBDIVIDE */
 737        return bytes | ((count - 1) << 16);
 738}
 739
 740static int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
 741{
 742        struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
 743        struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
 744        struct dma_buffparms *dmap;
 745        audio_buf_info info;
 746        count_info cinfo;
 747        int fact, ret, changed, bits, count, err;
 748        unsigned long flags;
 749
 750        switch (cmd) 
 751        {
 752                case SNDCTL_DSP_SUBDIVIDE:
 753                        ret = 0;
 754                        if (get_user(fact, (int __user *)arg))
 755                                return -EFAULT;
 756                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 757                                ret = dma_subdivide(dev, dmap_out, fact);
 758                        if (ret < 0)
 759                                return ret;
 760                        if (audio_devs[dev]->open_mode != OPEN_WRITE ||
 761                                (audio_devs[dev]->flags & DMA_DUPLEX &&
 762                                        audio_devs[dev]->open_mode & OPEN_READ))
 763                                ret = dma_subdivide(dev, dmap_in, fact);
 764                        if (ret < 0)
 765                                return ret;
 766                        break;
 767
 768                case SNDCTL_DSP_GETISPACE:
 769                case SNDCTL_DSP_GETOSPACE:
 770                        dmap = dmap_out;
 771                        if (cmd == SNDCTL_DSP_GETISPACE && !(audio_devs[dev]->open_mode & OPEN_READ))
 772                                return -EINVAL;
 773                        if (cmd == SNDCTL_DSP_GETOSPACE && !(audio_devs[dev]->open_mode & OPEN_WRITE))
 774                                return -EINVAL;
 775                        if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
 776                                dmap = dmap_in;
 777                        if (dmap->mapping_flags & DMA_MAP_MAPPED)
 778                                return -EINVAL;
 779                        if (!(dmap->flags & DMA_ALLOC_DONE))
 780                                reorganize_buffers(dev, dmap, (cmd == SNDCTL_DSP_GETISPACE));
 781                        info.fragstotal = dmap->nbufs;
 782                        if (cmd == SNDCTL_DSP_GETISPACE)
 783                                info.fragments = dmap->qlen;
 784                        else 
 785                        {
 786                                if (!DMAbuf_space_in_queue(dev))
 787                                        info.fragments = 0;
 788                                else
 789                                {
 790                                        info.fragments = DMAbuf_space_in_queue(dev);
 791                                        if (audio_devs[dev]->d->local_qlen) 
 792                                        {
 793                                                int tmp = audio_devs[dev]->d->local_qlen(dev);
 794                                                if (tmp && info.fragments)
 795                                                        tmp--;  /*
 796                                                                 * This buffer has been counted twice
 797                                                                 */
 798                                                info.fragments -= tmp;
 799                                        }
 800                                }
 801                        }
 802                        if (info.fragments < 0)
 803                                info.fragments = 0;
 804                        else if (info.fragments > dmap->nbufs)
 805                                info.fragments = dmap->nbufs;
 806
 807                        info.fragsize = dmap->fragment_size;
 808                        info.bytes = info.fragments * dmap->fragment_size;
 809
 810                        if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen)
 811                                info.bytes -= dmap->counts[dmap->qhead];
 812                        else 
 813                        {
 814                                info.fragments = info.bytes / dmap->fragment_size;
 815                                info.bytes -= dmap->user_counter % dmap->fragment_size;
 816                        }
 817                        if (copy_to_user(arg, &info, sizeof(info)))
 818                                return -EFAULT;
 819                        return 0;
 820
 821                case SNDCTL_DSP_SETTRIGGER:
 822                        if (get_user(bits, (int __user *)arg))
 823                                return -EFAULT;
 824                        bits &= audio_devs[dev]->open_mode;
 825                        if (audio_devs[dev]->d->trigger == NULL)
 826                                return -EINVAL;
 827                        if (!(audio_devs[dev]->flags & DMA_DUPLEX) && (bits & PCM_ENABLE_INPUT) &&
 828                                (bits & PCM_ENABLE_OUTPUT))
 829                                return -EINVAL;
 830
 831                        if (bits & PCM_ENABLE_INPUT)
 832                        {
 833                                spin_lock_irqsave(&dmap_in->lock,flags);
 834                                changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_INPUT;
 835                                if (changed && audio_devs[dev]->go) 
 836                                {
 837                                        reorganize_buffers(dev, dmap_in, 1);
 838                                        if ((err = audio_devs[dev]->d->prepare_for_input(dev,
 839                                                     dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
 840                                                spin_unlock_irqrestore(&dmap_in->lock,flags);
 841                                                return err;
 842                                        }
 843                                        dmap_in->dma_mode = DMODE_INPUT;
 844                                        audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT;
 845                                        DMAbuf_activate_recording(dev, dmap_in);
 846                                } else
 847                                        audio_devs[dev]->enable_bits &= ~PCM_ENABLE_INPUT;
 848                                spin_unlock_irqrestore(&dmap_in->lock,flags);
 849                        }
 850                        if (bits & PCM_ENABLE_OUTPUT)
 851                        {
 852                                spin_lock_irqsave(&dmap_out->lock,flags);
 853                                changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_OUTPUT;
 854                                if (changed &&
 855                                    (dmap_out->mapping_flags & DMA_MAP_MAPPED || dmap_out->qlen > 0) &&
 856                                    audio_devs[dev]->go) 
 857                                {
 858                                        if (!(dmap_out->flags & DMA_ALLOC_DONE))
 859                                                reorganize_buffers(dev, dmap_out, 0);
 860                                        dmap_out->dma_mode = DMODE_OUTPUT;
 861                                        audio_devs[dev]->enable_bits |= PCM_ENABLE_OUTPUT;
 862                                        dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
 863                                        DMAbuf_launch_output(dev, dmap_out);
 864                                } else
 865                                        audio_devs[dev]->enable_bits &= ~PCM_ENABLE_OUTPUT;
 866                                spin_unlock_irqrestore(&dmap_out->lock,flags);
 867                        }
 868#if 0
 869                        if (changed && audio_devs[dev]->d->trigger)
 870                                audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go);
 871#endif                          
 872                        /* Falls through... */
 873
 874                case SNDCTL_DSP_GETTRIGGER:
 875                        ret = audio_devs[dev]->enable_bits;
 876                        break;
 877
 878                case SNDCTL_DSP_SETSYNCRO:
 879                        if (!audio_devs[dev]->d->trigger)
 880                                return -EINVAL;
 881                        audio_devs[dev]->d->trigger(dev, 0);
 882                        audio_devs[dev]->go = 0;
 883                        return 0;
 884
 885                case SNDCTL_DSP_GETIPTR:
 886                        if (!(audio_devs[dev]->open_mode & OPEN_READ))
 887                                return -EINVAL;
 888                        spin_lock_irqsave(&dmap_in->lock,flags);
 889                        cinfo.bytes = dmap_in->byte_counter;
 890                        cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_in, DMODE_INPUT) & ~3;
 891                        if (cinfo.ptr < dmap_in->fragment_size && dmap_in->qtail != 0)
 892                                cinfo.bytes += dmap_in->bytes_in_use;   /* Pointer wrap not handled yet */
 893                        cinfo.blocks = dmap_in->qlen;
 894                        cinfo.bytes += cinfo.ptr;
 895                        if (dmap_in->mapping_flags & DMA_MAP_MAPPED)
 896                                dmap_in->qlen = 0;      /* Reset interrupt counter */
 897                        spin_unlock_irqrestore(&dmap_in->lock,flags);
 898                        if (copy_to_user(arg, &cinfo, sizeof(cinfo)))
 899                                return -EFAULT;
 900                        return 0;
 901
 902                case SNDCTL_DSP_GETOPTR:
 903                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 904                                return -EINVAL;
 905
 906                        spin_lock_irqsave(&dmap_out->lock,flags);
 907                        cinfo.bytes = dmap_out->byte_counter;
 908                        cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_out, DMODE_OUTPUT) & ~3;
 909                        if (cinfo.ptr < dmap_out->fragment_size && dmap_out->qhead != 0)
 910                                cinfo.bytes += dmap_out->bytes_in_use;  /* Pointer wrap not handled yet */
 911                        cinfo.blocks = dmap_out->qlen;
 912                        cinfo.bytes += cinfo.ptr;
 913                        if (dmap_out->mapping_flags & DMA_MAP_MAPPED)
 914                                dmap_out->qlen = 0;     /* Reset interrupt counter */
 915                        spin_unlock_irqrestore(&dmap_out->lock,flags);
 916                        if (copy_to_user(arg, &cinfo, sizeof(cinfo)))
 917                                return -EFAULT;
 918                        return 0;
 919
 920                case SNDCTL_DSP_GETODELAY:
 921                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 922                                return -EINVAL;
 923                        if (!(dmap_out->flags & DMA_ALLOC_DONE))
 924                        {
 925                                ret=0;
 926                                break;
 927                        }
 928                        spin_lock_irqsave(&dmap_out->lock,flags);
 929                        /* Compute number of bytes that have been played */
 930                        count = DMAbuf_get_buffer_pointer (dev, dmap_out, DMODE_OUTPUT);
 931                        if (count < dmap_out->fragment_size && dmap_out->qhead != 0)
 932                                count += dmap_out->bytes_in_use;        /* Pointer wrap not handled yet */
 933                        count += dmap_out->byte_counter;
 934                        /* Subtract current count from the number of bytes written by app */
 935                        count = dmap_out->user_counter - count;
 936                        if (count < 0)
 937                                count = 0;
 938                        spin_unlock_irqrestore(&dmap_out->lock,flags);
 939                        ret = count;
 940                        break;
 941
 942                case SNDCTL_DSP_POST:
 943                        if (audio_devs[dev]->dmap_out->qlen > 0)
 944                                if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE))
 945                                        DMAbuf_launch_output(dev, audio_devs[dev]->dmap_out);
 946                        return 0;
 947
 948                case SNDCTL_DSP_GETBLKSIZE:
 949                        dmap = dmap_out;
 950                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 951                                reorganize_buffers(dev, dmap_out, (audio_devs[dev]->open_mode == OPEN_READ));
 952                        if (audio_devs[dev]->open_mode == OPEN_READ ||
 953                            (audio_devs[dev]->flags & DMA_DUPLEX &&
 954                             audio_devs[dev]->open_mode & OPEN_READ))
 955                                reorganize_buffers(dev, dmap_in, (audio_devs[dev]->open_mode == OPEN_READ));
 956                        if (audio_devs[dev]->open_mode == OPEN_READ)
 957                                dmap = dmap_in;
 958                        ret = dmap->fragment_size;
 959                        break;
 960
 961                case SNDCTL_DSP_SETFRAGMENT:
 962                        ret = 0;
 963                        if (get_user(fact, (int __user *)arg))
 964                                return -EFAULT;
 965                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 966                                ret = dma_set_fragment(dev, dmap_out, fact);
 967                        if (ret < 0)
 968                                return ret;
 969                        if (audio_devs[dev]->open_mode == OPEN_READ ||
 970                            (audio_devs[dev]->flags & DMA_DUPLEX &&
 971                             audio_devs[dev]->open_mode & OPEN_READ))
 972                                ret = dma_set_fragment(dev, dmap_in, fact);
 973                        if (ret < 0)
 974                                return ret;
 975                        if (!arg) /* don't know what this is good for, but preserve old semantics */
 976                                return 0;
 977                        break;
 978
 979                default:
 980                        if (!audio_devs[dev]->d->ioctl)
 981                                return -EINVAL;
 982                        return audio_devs[dev]->d->ioctl(dev, cmd, arg);
 983        }
 984        return put_user(ret, (int __user *)arg);
 985}
 986
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.