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                        file->f_flags |= O_NONBLOCK;
 437                        return 0;
 438
 439                case SNDCTL_DSP_GETCAPS:
 440                                val = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */
 441                                if (audio_devs[dev]->flags & DMA_DUPLEX &&
 442                                        audio_devs[dev]->open_mode == OPEN_READWRITE)
 443                                        val |= DSP_CAP_DUPLEX;
 444                                if (audio_devs[dev]->coproc)
 445                                        val |= DSP_CAP_COPROC;
 446                                if (audio_devs[dev]->d->local_qlen)     /* Device has hidden buffers */
 447                                        val |= DSP_CAP_BATCH;
 448                                if (audio_devs[dev]->d->trigger)        /* Supports SETTRIGGER */
 449                                        val |= DSP_CAP_TRIGGER;
 450                                break;
 451                        
 452                case SOUND_PCM_WRITE_RATE:
 453                        if (get_user(val, p))
 454                                return -EFAULT;
 455                        val = audio_devs[dev]->d->set_speed(dev, val);
 456                        break;
 457
 458                case SOUND_PCM_READ_RATE:
 459                        val = audio_devs[dev]->d->set_speed(dev, 0);
 460                        break;
 461                        
 462                case SNDCTL_DSP_STEREO:
 463                        if (get_user(val, p))
 464                                return -EFAULT;
 465                        if (val > 1 || val < 0)
 466                                return -EINVAL;
 467                        val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1;
 468                        break;
 469
 470                case SOUND_PCM_WRITE_CHANNELS:
 471                        if (get_user(val, p))
 472                                return -EFAULT;
 473                        val = audio_devs[dev]->d->set_channels(dev, val);
 474                        break;
 475
 476                case SOUND_PCM_READ_CHANNELS:
 477                        val = audio_devs[dev]->d->set_channels(dev, 0);
 478                        break;
 479                
 480                case SOUND_PCM_READ_BITS:
 481                        val = audio_devs[dev]->d->set_bits(dev, 0);
 482                        break;
 483
 484                case SNDCTL_DSP_SETDUPLEX:
 485                        if (audio_devs[dev]->open_mode != OPEN_READWRITE)
 486                                return -EPERM;
 487                        return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO;
 488
 489                case SNDCTL_DSP_PROFILE:
 490                        if (get_user(val, p))
 491                                return -EFAULT;
 492                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 493                                audio_devs[dev]->dmap_out->applic_profile = val;
 494                        if (audio_devs[dev]->open_mode & OPEN_READ)
 495                                audio_devs[dev]->dmap_in->applic_profile = val;
 496                        return 0;
 497                
 498                case SNDCTL_DSP_GETODELAY:
 499                        dmap = audio_devs[dev]->dmap_out;
 500                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 501                                return -EINVAL;
 502                        if (!(dmap->flags & DMA_ALLOC_DONE))
 503                        {
 504                                val=0;
 505                                break;
 506                        }
 507                
 508                        spin_lock_irqsave(&dmap->lock,flags);
 509                        /* Compute number of bytes that have been played */
 510                        count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
 511                        if (count < dmap->fragment_size && dmap->qhead != 0)
 512                                count += dmap->bytes_in_use;    /* Pointer wrap not handled yet */
 513                        count += dmap->byte_counter;
 514                
 515                        /* Substract current count from the number of bytes written by app */
 516                        count = dmap->user_counter - count;
 517                        if (count < 0)
 518                                count = 0;
 519                        spin_unlock_irqrestore(&dmap->lock,flags);
 520                        val = count;
 521                        break;
 522                
 523                default:
 524                        return dma_ioctl(dev, cmd, arg);
 525        }
 526        return put_user(val, p);
 527}
 528
 529void audio_init_devices(void)
 530{
 531        /*
 532         * NOTE! This routine could be called several times during boot.
 533         */
 534}
 535
 536void reorganize_buffers(int dev, struct dma_buffparms *dmap, int recording)
 537{
 538        /*
 539         * This routine breaks the physical device buffers to logical ones.
 540         */
 541
 542        struct audio_operations *dsp_dev = audio_devs[dev];
 543
 544        unsigned i, n;
 545        unsigned sr, nc, sz, bsz;
 546
 547        sr = dsp_dev->d->set_speed(dev, 0);
 548        nc = dsp_dev->d->set_channels(dev, 0);
 549        sz = dsp_dev->d->set_bits(dev, 0);
 550
 551        if (sz == 8)
 552                dmap->neutral_byte = NEUTRAL8;
 553        else
 554                dmap->neutral_byte = NEUTRAL16;
 555
 556        if (sr < 1 || nc < 1 || sz < 1)
 557        {
 558/*              printk(KERN_DEBUG "Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);*/
 559                sr = DSP_DEFAULT_SPEED;
 560                nc = 1;
 561                sz = 8;
 562        }
 563        
 564        sz = sr * nc * sz;
 565
 566        sz /= 8;                /* #bits -> #bytes */
 567        dmap->data_rate = sz;
 568
 569        if (!dmap->needs_reorg)
 570                return;
 571        dmap->needs_reorg = 0;
 572
 573        if (dmap->fragment_size == 0)
 574        {       
 575                /* Compute the fragment size using the default algorithm */
 576
 577                /*
 578                 * Compute a buffer size for time not exceeding 1 second.
 579                 * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds
 580                 * of sound (using the current speed, sample size and #channels).
 581                 */
 582
 583                bsz = dmap->buffsize;
 584                while (bsz > sz)
 585                        bsz /= 2;
 586
 587                if (bsz == dmap->buffsize)
 588                        bsz /= 2;       /* Needs at least 2 buffers */
 589
 590                /*
 591                 *    Split the computed fragment to smaller parts. After 3.5a9
 592                 *      the default subdivision is 4 which should give better
 593                 *      results when recording.
 594                 */
 595
 596                if (dmap->subdivision == 0)     /* Not already set */
 597                {
 598                        dmap->subdivision = 4;  /* Init to the default value */
 599
 600                        if ((bsz / dmap->subdivision) > 4096)
 601                                dmap->subdivision *= 2;
 602                        if ((bsz / dmap->subdivision) < 4096)
 603                                dmap->subdivision = 1;
 604                }
 605                bsz /= dmap->subdivision;
 606
 607                if (bsz < 16)
 608                        bsz = 16;       /* Just a sanity check */
 609
 610                dmap->fragment_size = bsz;
 611        }
 612        else
 613        {
 614                /*
 615                 * The process has specified the buffer size with SNDCTL_DSP_SETFRAGMENT or
 616                 * the buffer size computation has already been done.
 617                 */
 618                if (dmap->fragment_size > (dmap->buffsize / 2))
 619                        dmap->fragment_size = (dmap->buffsize / 2);
 620                bsz = dmap->fragment_size;
 621        }
 622
 623        if (audio_devs[dev]->min_fragment)
 624                if (bsz < (1 << audio_devs[dev]->min_fragment))
 625                        bsz = 1 << audio_devs[dev]->min_fragment;
 626        if (audio_devs[dev]->max_fragment)
 627                if (bsz > (1 << audio_devs[dev]->max_fragment))
 628                        bsz = 1 << audio_devs[dev]->max_fragment;
 629        bsz &= ~0x07;           /* Force size which is multiple of 8 bytes */
 630#ifdef OS_DMA_ALIGN_CHECK
 631        OS_DMA_ALIGN_CHECK(bsz);
 632#endif
 633
 634        n = dmap->buffsize / bsz;
 635        if (n > MAX_SUB_BUFFERS)
 636                n = MAX_SUB_BUFFERS;
 637        if (n > dmap->max_fragments)
 638                n = dmap->max_fragments;
 639
 640        if (n < 2)
 641        {
 642                n = 2;
 643                bsz /= 2;
 644        }
 645        dmap->nbufs = n;
 646        dmap->bytes_in_use = n * bsz;
 647        dmap->fragment_size = bsz;
 648        dmap->max_byte_counter = (dmap->data_rate * 60 * 60) +
 649                        dmap->bytes_in_use;     /* Approximately one hour */
 650
 651        if (dmap->raw_buf)
 652        {
 653                memset(dmap->raw_buf, dmap->neutral_byte, dmap->bytes_in_use);
 654        }
 655        
 656        for (i = 0; i < dmap->nbufs; i++)
 657        {
 658                dmap->counts[i] = 0;
 659        }
 660
 661        dmap->flags |= DMA_ALLOC_DONE | DMA_EMPTY;
 662}
 663
 664static int dma_subdivide(int dev, struct dma_buffparms *dmap, int fact)
 665{
 666        if (fact == 0) 
 667        {
 668                fact = dmap->subdivision;
 669                if (fact == 0)
 670                        fact = 1;
 671                return fact;
 672        }
 673        if (dmap->subdivision != 0 || dmap->fragment_size)      /* Too late to change */
 674                return -EINVAL;
 675
 676        if (fact > MAX_REALTIME_FACTOR)
 677                return -EINVAL;
 678
 679        if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
 680                return -EINVAL;
 681
 682        dmap->subdivision = fact;
 683        return fact;
 684}
 685
 686static int dma_set_fragment(int dev, struct dma_buffparms *dmap, int fact)
 687{
 688        int bytes, count;
 689
 690        if (fact == 0)
 691                return -EIO;
 692
 693        if (dmap->subdivision != 0 ||
 694            dmap->fragment_size)        /* Too late to change */
 695                return -EINVAL;
 696
 697        bytes = fact & 0xffff;
 698        count = (fact >> 16) & 0x7fff;
 699
 700        if (count == 0)
 701                count = MAX_SUB_BUFFERS;
 702        else if (count < MAX_SUB_BUFFERS)
 703                count++;
 704
 705        if (bytes < 4 || bytes > 17)    /* <16 || > 512k */
 706                return -EINVAL;
 707
 708        if (count < 2)
 709                return -EINVAL;
 710
 711        if (audio_devs[dev]->min_fragment > 0)
 712                if (bytes < audio_devs[dev]->min_fragment)
 713                        bytes = audio_devs[dev]->min_fragment;
 714
 715        if (audio_devs[dev]->max_fragment > 0)
 716                if (bytes > audio_devs[dev]->max_fragment)
 717                        bytes = audio_devs[dev]->max_fragment;
 718
 719#ifdef OS_DMA_MINBITS
 720        if (bytes < OS_DMA_MINBITS)
 721                bytes = OS_DMA_MINBITS;
 722#endif
 723
 724        dmap->fragment_size = (1 << bytes);
 725        dmap->max_fragments = count;
 726
 727        if (dmap->fragment_size > dmap->buffsize)
 728                dmap->fragment_size = dmap->buffsize;
 729
 730        if (dmap->fragment_size == dmap->buffsize &&
 731            audio_devs[dev]->flags & DMA_AUTOMODE)
 732                dmap->fragment_size /= 2;       /* Needs at least 2 buffers */
 733
 734        dmap->subdivision = 1;  /* Disable SNDCTL_DSP_SUBDIVIDE */
 735        return bytes | ((count - 1) << 16);
 736}
 737
 738static int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
 739{
 740        struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
 741        struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
 742        struct dma_buffparms *dmap;
 743        audio_buf_info info;
 744        count_info cinfo;
 745        int fact, ret, changed, bits, count, err;
 746        unsigned long flags;
 747
 748        switch (cmd) 
 749        {
 750                case SNDCTL_DSP_SUBDIVIDE:
 751                        ret = 0;
 752                        if (get_user(fact, (int __user *)arg))
 753                                return -EFAULT;
 754                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 755                                ret = dma_subdivide(dev, dmap_out, fact);
 756                        if (ret < 0)
 757                                return ret;
 758                        if (audio_devs[dev]->open_mode != OPEN_WRITE ||
 759                                (audio_devs[dev]->flags & DMA_DUPLEX &&
 760                                        audio_devs[dev]->open_mode & OPEN_READ))
 761                                ret = dma_subdivide(dev, dmap_in, fact);
 762                        if (ret < 0)
 763                                return ret;
 764                        break;
 765
 766                case SNDCTL_DSP_GETISPACE:
 767                case SNDCTL_DSP_GETOSPACE:
 768                        dmap = dmap_out;
 769                        if (cmd == SNDCTL_DSP_GETISPACE && !(audio_devs[dev]->open_mode & OPEN_READ))
 770                                return -EINVAL;
 771                        if (cmd == SNDCTL_DSP_GETOSPACE && !(audio_devs[dev]->open_mode & OPEN_WRITE))
 772                                return -EINVAL;
 773                        if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
 774                                dmap = dmap_in;
 775                        if (dmap->mapping_flags & DMA_MAP_MAPPED)
 776                                return -EINVAL;
 777                        if (!(dmap->flags & DMA_ALLOC_DONE))
 778                                reorganize_buffers(dev, dmap, (cmd == SNDCTL_DSP_GETISPACE));
 779                        info.fragstotal = dmap->nbufs;
 780                        if (cmd == SNDCTL_DSP_GETISPACE)
 781                                info.fragments = dmap->qlen;
 782                        else 
 783                        {
 784                                if (!DMAbuf_space_in_queue(dev))
 785                                        info.fragments = 0;
 786                                else
 787                                {
 788                                        info.fragments = DMAbuf_space_in_queue(dev);
 789                                        if (audio_devs[dev]->d->local_qlen) 
 790                                        {
 791                                                int tmp = audio_devs[dev]->d->local_qlen(dev);
 792                                                if (tmp && info.fragments)
 793                                                        tmp--;  /*
 794                                                                 * This buffer has been counted twice
 795                                                                 */
 796                                                info.fragments -= tmp;
 797                                        }
 798                                }
 799                        }
 800                        if (info.fragments < 0)
 801                                info.fragments = 0;
 802                        else if (info.fragments > dmap->nbufs)
 803                                info.fragments = dmap->nbufs;
 804
 805                        info.fragsize = dmap->fragment_size;
 806                        info.bytes = info.fragments * dmap->fragment_size;
 807
 808                        if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen)
 809                                info.bytes -= dmap->counts[dmap->qhead];
 810                        else 
 811                        {
 812                                info.fragments = info.bytes / dmap->fragment_size;
 813                                info.bytes -= dmap->user_counter % dmap->fragment_size;
 814                        }
 815                        if (copy_to_user(arg, &info, sizeof(info)))
 816                                return -EFAULT;
 817                        return 0;
 818
 819                case SNDCTL_DSP_SETTRIGGER:
 820                        if (get_user(bits, (int __user *)arg))
 821                                return -EFAULT;
 822                        bits &= audio_devs[dev]->open_mode;
 823                        if (audio_devs[dev]->d->trigger == NULL)
 824                                return -EINVAL;
 825                        if (!(audio_devs[dev]->flags & DMA_DUPLEX) && (bits & PCM_ENABLE_INPUT) &&
 826                                (bits & PCM_ENABLE_OUTPUT))
 827                                return -EINVAL;
 828
 829                        if (bits & PCM_ENABLE_INPUT)
 830                        {
 831                                spin_lock_irqsave(&dmap_in->lock,flags);
 832                                changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_INPUT;
 833                                if (changed && audio_devs[dev]->go) 
 834                                {
 835                                        reorganize_buffers(dev, dmap_in, 1);
 836                                        if ((err = audio_devs[dev]->d->prepare_for_input(dev,
 837                                                     dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
 838                                                spin_unlock_irqrestore(&dmap_in->lock,flags);
 839                                                return -err;
 840                                        }
 841                                        dmap_in->dma_mode = DMODE_INPUT;
 842                                        audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT;
 843                                        DMAbuf_activate_recording(dev, dmap_in);
 844                                } else
 845                                        audio_devs[dev]->enable_bits &= ~PCM_ENABLE_INPUT;
 846                                spin_unlock_irqrestore(&dmap_in->lock,flags);
 847                        }
 848                        if (bits & PCM_ENABLE_OUTPUT)
 849                        {
 850                                spin_lock_irqsave(&dmap_out->lock,flags);
 851                                changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_OUTPUT;
 852                                if (changed &&
 853                                    (dmap_out->mapping_flags & DMA_MAP_MAPPED || dmap_out->qlen > 0) &&
 854                                    audio_devs[dev]->go) 
 855                                {
 856                                        if (!(dmap_out->flags & DMA_ALLOC_DONE))
 857                                                reorganize_buffers(dev, dmap_out, 0);
 858                                        dmap_out->dma_mode = DMODE_OUTPUT;
 859                                        audio_devs[dev]->enable_bits |= PCM_ENABLE_OUTPUT;
 860                                        dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
 861                                        DMAbuf_launch_output(dev, dmap_out);
 862                                } else
 863                                        audio_devs[dev]->enable_bits &= ~PCM_ENABLE_OUTPUT;
 864                                spin_unlock_irqrestore(&dmap_out->lock,flags);
 865                        }
 866#if 0
 867                        if (changed && audio_devs[dev]->d->trigger)
 868                                audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go);
 869#endif                          
 870                        /* Falls through... */
 871
 872                case SNDCTL_DSP_GETTRIGGER:
 873                        ret = audio_devs[dev]->enable_bits;
 874                        break;
 875
 876                case SNDCTL_DSP_SETSYNCRO:
 877                        if (!audio_devs[dev]->d->trigger)
 878                                return -EINVAL;
 879                        audio_devs[dev]->d->trigger(dev, 0);
 880                        audio_devs[dev]->go = 0;
 881                        return 0;
 882
 883                case SNDCTL_DSP_GETIPTR:
 884                        if (!(audio_devs[dev]->open_mode & OPEN_READ))
 885                                return -EINVAL;
 886                        spin_lock_irqsave(&dmap_in->lock,flags);
 887                        cinfo.bytes = dmap_in->byte_counter;
 888                        cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_in, DMODE_INPUT) & ~3;
 889                        if (cinfo.ptr < dmap_in->fragment_size && dmap_in->qtail != 0)
 890                                cinfo.bytes += dmap_in->bytes_in_use;   /* Pointer wrap not handled yet */
 891                        cinfo.blocks = dmap_in->qlen;
 892                        cinfo.bytes += cinfo.ptr;
 893                        if (dmap_in->mapping_flags & DMA_MAP_MAPPED)
 894                                dmap_in->qlen = 0;      /* Reset interrupt counter */
 895                        spin_unlock_irqrestore(&dmap_in->lock,flags);
 896                        if (copy_to_user(arg, &cinfo, sizeof(cinfo)))
 897                                return -EFAULT;
 898                        return 0;
 899
 900                case SNDCTL_DSP_GETOPTR:
 901                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 902                                return -EINVAL;
 903
 904                        spin_lock_irqsave(&dmap_out->lock,flags);
 905                        cinfo.bytes = dmap_out->byte_counter;
 906                        cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_out, DMODE_OUTPUT) & ~3;
 907                        if (cinfo.ptr < dmap_out->fragment_size && dmap_out->qhead != 0)
 908                                cinfo.bytes += dmap_out->bytes_in_use;  /* Pointer wrap not handled yet */
 909                        cinfo.blocks = dmap_out->qlen;
 910                        cinfo.bytes += cinfo.ptr;
 911                        if (dmap_out->mapping_flags & DMA_MAP_MAPPED)
 912                                dmap_out->qlen = 0;     /* Reset interrupt counter */
 913                        spin_unlock_irqrestore(&dmap_out->lock,flags);
 914                        if (copy_to_user(arg, &cinfo, sizeof(cinfo)))
 915                                return -EFAULT;
 916                        return 0;
 917
 918                case SNDCTL_DSP_GETODELAY:
 919                        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 920                                return -EINVAL;
 921                        if (!(dmap_out->flags & DMA_ALLOC_DONE))
 922                        {
 923                                ret=0;
 924                                break;
 925                        }
 926                        spin_lock_irqsave(&dmap_out->lock,flags);
 927                        /* Compute number of bytes that have been played */
 928                        count = DMAbuf_get_buffer_pointer (dev, dmap_out, DMODE_OUTPUT);
 929                        if (count < dmap_out->fragment_size && dmap_out->qhead != 0)
 930                                count += dmap_out->bytes_in_use;        /* Pointer wrap not handled yet */
 931                        count += dmap_out->byte_counter;
 932                        /* Substract current count from the number of bytes written by app */
 933                        count = dmap_out->user_counter - count;
 934                        if (count < 0)
 935                                count = 0;
 936                        spin_unlock_irqrestore(&dmap_out->lock,flags);
 937                        ret = count;
 938                        break;
 939
 940                case SNDCTL_DSP_POST:
 941                        if (audio_devs[dev]->dmap_out->qlen > 0)
 942                                if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE))
 943                                        DMAbuf_launch_output(dev, audio_devs[dev]->dmap_out);
 944                        return 0;
 945
 946                case SNDCTL_DSP_GETBLKSIZE:
 947                        dmap = dmap_out;
 948                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 949                                reorganize_buffers(dev, dmap_out, (audio_devs[dev]->open_mode == OPEN_READ));
 950                        if (audio_devs[dev]->open_mode == OPEN_READ ||
 951                            (audio_devs[dev]->flags & DMA_DUPLEX &&
 952                             audio_devs[dev]->open_mode & OPEN_READ))
 953                                reorganize_buffers(dev, dmap_in, (audio_devs[dev]->open_mode == OPEN_READ));
 954                        if (audio_devs[dev]->open_mode == OPEN_READ)
 955                                dmap = dmap_in;
 956                        ret = dmap->fragment_size;
 957                        break;
 958
 959                case SNDCTL_DSP_SETFRAGMENT:
 960                        ret = 0;
 961                        if (get_user(fact, (int __user *)arg))
 962                                return -EFAULT;
 963                        if (audio_devs[dev]->open_mode & OPEN_WRITE)
 964                                ret = dma_set_fragment(dev, dmap_out, fact);
 965                        if (ret < 0)
 966                                return ret;
 967                        if (audio_devs[dev]->open_mode == OPEN_READ ||
 968                            (audio_devs[dev]->flags & DMA_DUPLEX &&
 969                             audio_devs[dev]->open_mode & OPEN_READ))
 970                                ret = dma_set_fragment(dev, dmap_in, fact);
 971                        if (ret < 0)
 972                                return ret;
 973                        if (!arg) /* don't know what this is good for, but preserve old semantics */
 974                                return 0;
 975                        break;
 976
 977                default:
 978                        if (!audio_devs[dev]->d->ioctl)
 979                                return -EINVAL;
 980                        return audio_devs[dev]->d->ioctl(dev, cmd, arg);
 981        }
 982        return put_user(ret, (int __user *)arg);
 983}
 984
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.