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