linux/sound/oss/soundcard.c
<<
>>
Prefs
   1/*
   2 * linux/sound/oss/soundcard.c
   3 *
   4 * Sound card driver for Linux
   5 *
   6 *
   7 * Copyright (C) by Hannu Savolainen 1993-1997
   8 *
   9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  10 * Version 2 (June 1991). See the "COPYING" file distributed with this software
  11 * for more info.
  12 *
  13 *
  14 * Thomas Sailer     : ioctl code reworked (vmalloc/vfree removed)
  15 *                   integrated sound_switch.c
  16 * Stefan Reinauer   : integrated /proc/sound (equals to /dev/sndstat,
  17 *                   which should disappear in the near future)
  18 * Eric Dumas        : devfs support (22-Jan-98) <dumas@linux.eu.org> with
  19 *                   fixups by C. Scott Ananian <cananian@alumni.princeton.edu>
  20 * Richard Gooch     : moved common (non OSS-specific) devices to sound_core.c
  21 * Rob Riggs         : Added persistent DMA buffers support (1998/10/17)
  22 * Christoph Hellwig : Some cleanup work (2000/03/01)
  23 */
  24
  25
  26#include "sound_config.h"
  27#include <linux/init.h>
  28#include <linux/types.h>
  29#include <linux/errno.h>
  30#include <linux/signal.h>
  31#include <linux/fcntl.h>
  32#include <linux/ctype.h>
  33#include <linux/stddef.h>
  34#include <linux/kmod.h>
  35#include <linux/kernel.h>
  36#include <asm/dma.h>
  37#include <asm/io.h>
  38#include <linux/wait.h>
  39#include <linux/slab.h>
  40#include <linux/ioport.h>
  41#include <linux/major.h>
  42#include <linux/delay.h>
  43#include <linux/proc_fs.h>
  44#include <linux/smp_lock.h>
  45#include <linux/module.h>
  46#include <linux/mm.h>
  47#include <linux/device.h>
  48
  49/*
  50 * This ought to be moved into include/asm/dma.h
  51 */
  52#ifndef valid_dma
  53#define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4)
  54#endif
  55
  56/*
  57 * Table for permanently allocated memory (used when unloading the module)
  58 */
  59void *          sound_mem_blocks[1024];
  60int             sound_nblocks = 0;
  61
  62/* Persistent DMA buffers */
  63#ifdef CONFIG_SOUND_DMAP
  64int             sound_dmap_flag = 1;
  65#else
  66int             sound_dmap_flag = 0;
  67#endif
  68
  69static char     dma_alloc_map[MAX_DMA_CHANNELS];
  70
  71#define DMA_MAP_UNAVAIL         0
  72#define DMA_MAP_FREE            1
  73#define DMA_MAP_BUSY            2
  74
  75
  76unsigned long seq_time = 0;     /* Time for /dev/sequencer */
  77extern struct class *sound_class;
  78
  79/*
  80 * Table for configurable mixer volume handling
  81 */
  82static mixer_vol_table mixer_vols[MAX_MIXER_DEV];
  83static int num_mixer_volumes;
  84
  85int *load_mixer_volumes(char *name, int *levels, int present)
  86{
  87        int             i, n;
  88
  89        for (i = 0; i < num_mixer_volumes; i++) {
  90                if (strcmp(name, mixer_vols[i].name) == 0) {
  91                        if (present)
  92                                mixer_vols[i].num = i;
  93                        return mixer_vols[i].levels;
  94                }
  95        }
  96        if (num_mixer_volumes >= MAX_MIXER_DEV) {
  97                printk(KERN_ERR "Sound: Too many mixers (%s)\n", name);
  98                return levels;
  99        }
 100        n = num_mixer_volumes++;
 101
 102        strcpy(mixer_vols[n].name, name);
 103
 104        if (present)
 105                mixer_vols[n].num = n;
 106        else
 107                mixer_vols[n].num = -1;
 108
 109        for (i = 0; i < 32; i++)
 110                mixer_vols[n].levels[i] = levels[i];
 111        return mixer_vols[n].levels;
 112}
 113EXPORT_SYMBOL(load_mixer_volumes);
 114
 115static int set_mixer_levels(void __user * arg)
 116{
 117        /* mixer_vol_table is 174 bytes, so IMHO no reason to not allocate it on the stack */
 118        mixer_vol_table buf;   
 119
 120        if (__copy_from_user(&buf, arg, sizeof(buf)))
 121                return -EFAULT;
 122        load_mixer_volumes(buf.name, buf.levels, 0);
 123        if (__copy_to_user(arg, &buf, sizeof(buf)))
 124                return -EFAULT;
 125        return 0;
 126}
 127
 128static int get_mixer_levels(void __user * arg)
 129{
 130        int n;
 131
 132        if (__get_user(n, (int __user *)(&(((mixer_vol_table __user *)arg)->num))))
 133                return -EFAULT;
 134        if (n < 0 || n >= num_mixer_volumes)
 135                return -EINVAL;
 136        if (__copy_to_user(arg, &mixer_vols[n], sizeof(mixer_vol_table)))
 137                return -EFAULT;
 138        return 0;
 139}
 140
 141/* 4K page size but our output routines use some slack for overruns */
 142#define PROC_BLOCK_SIZE (3*1024)
 143
 144static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 145{
 146        int dev = iminor(file->f_path.dentry->d_inode);
 147        int ret = -EINVAL;
 148
 149        /*
 150         *      The OSS drivers aren't remotely happy without this locking,
 151         *      and unless someone fixes them when they are about to bite the
 152         *      big one anyway, we might as well bandage here..
 153         */
 154         
 155        lock_kernel();
 156        
 157        DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count));
 158        switch (dev & 0x0f) {
 159        case SND_DEV_DSP:
 160        case SND_DEV_DSP16:
 161        case SND_DEV_AUDIO:
 162                ret = audio_read(dev, file, buf, count);
 163                break;
 164
 165        case SND_DEV_SEQ:
 166        case SND_DEV_SEQ2:
 167                ret = sequencer_read(dev, file, buf, count);
 168                break;
 169
 170        case SND_DEV_MIDIN:
 171                ret = MIDIbuf_read(dev, file, buf, count);
 172        }
 173        unlock_kernel();
 174        return ret;
 175}
 176
 177static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 178{
 179        int dev = iminor(file->f_path.dentry->d_inode);
 180        int ret = -EINVAL;
 181        
 182        lock_kernel();
 183        DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count));
 184        switch (dev & 0x0f) {
 185        case SND_DEV_SEQ:
 186        case SND_DEV_SEQ2:
 187                ret =  sequencer_write(dev, file, buf, count);
 188                break;
 189
 190        case SND_DEV_DSP:
 191        case SND_DEV_DSP16:
 192        case SND_DEV_AUDIO:
 193                ret = audio_write(dev, file, buf, count);
 194                break;
 195
 196        case SND_DEV_MIDIN:
 197                ret =  MIDIbuf_write(dev, file, buf, count);
 198                break;
 199        }
 200        unlock_kernel();
 201        return ret;
 202}
 203
 204static int sound_open(struct inode *inode, struct file *file)
 205{
 206        int dev = iminor(inode);
 207        int retval;
 208
 209        DEB(printk("sound_open(dev=%d)\n", dev));
 210        if ((dev >= SND_NDEVS) || (dev < 0)) {
 211                printk(KERN_ERR "Invalid minor device %d\n", dev);
 212                return -ENXIO;
 213        }
 214        switch (dev & 0x0f) {
 215        case SND_DEV_CTL:
 216                dev >>= 4;
 217                if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
 218                        request_module("mixer%d", dev);
 219                }
 220                if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
 221                        return -ENXIO;
 222        
 223                if (!try_module_get(mixer_devs[dev]->owner))
 224                        return -ENXIO;
 225                break;
 226
 227        case SND_DEV_SEQ:
 228        case SND_DEV_SEQ2:
 229                if ((retval = sequencer_open(dev, file)) < 0)
 230                        return retval;
 231                break;
 232
 233        case SND_DEV_MIDIN:
 234                if ((retval = MIDIbuf_open(dev, file)) < 0)
 235                        return retval;
 236                break;
 237
 238        case SND_DEV_DSP:
 239        case SND_DEV_DSP16:
 240        case SND_DEV_AUDIO:
 241                if ((retval = audio_open(dev, file)) < 0)
 242                        return retval;
 243                break;
 244
 245        default:
 246                printk(KERN_ERR "Invalid minor device %d\n", dev);
 247                return -ENXIO;
 248        }
 249
 250        return 0;
 251}
 252
 253static int sound_release(struct inode *inode, struct file *file)
 254{
 255        int dev = iminor(inode);
 256
 257        lock_kernel();
 258        DEB(printk("sound_release(dev=%d)\n", dev));
 259        switch (dev & 0x0f) {
 260        case SND_DEV_CTL:
 261                module_put(mixer_devs[dev >> 4]->owner);
 262                break;
 263                
 264        case SND_DEV_SEQ:
 265        case SND_DEV_SEQ2:
 266                sequencer_release(dev, file);
 267                break;
 268
 269        case SND_DEV_MIDIN:
 270                MIDIbuf_release(dev, file);
 271                break;
 272
 273        case SND_DEV_DSP:
 274        case SND_DEV_DSP16:
 275        case SND_DEV_AUDIO:
 276                audio_release(dev, file);
 277                break;
 278
 279        default:
 280                printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev);
 281        }
 282        unlock_kernel();
 283
 284        return 0;
 285}
 286
 287static int get_mixer_info(int dev, void __user *arg)
 288{
 289        mixer_info info;
 290        memset(&info, 0, sizeof(info));
 291        strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
 292        strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
 293        info.modify_counter = mixer_devs[dev]->modify_counter;
 294        if (__copy_to_user(arg, &info,  sizeof(info)))
 295                return -EFAULT;
 296        return 0;
 297}
 298
 299static int get_old_mixer_info(int dev, void __user *arg)
 300{
 301        _old_mixer_info info;
 302        memset(&info, 0, sizeof(info));
 303        strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
 304        strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
 305        if (copy_to_user(arg, &info,  sizeof(info)))
 306                return -EFAULT;
 307        return 0;
 308}
 309
 310static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg)
 311{
 312        if (mixdev < 0 || mixdev >= MAX_MIXER_DEV)
 313                return -ENXIO;
 314        /* Try to load the mixer... */
 315        if (mixer_devs[mixdev] == NULL) {
 316                request_module("mixer%d", mixdev);
 317        }
 318        if (mixdev >= num_mixers || !mixer_devs[mixdev])
 319                return -ENXIO;
 320        if (cmd == SOUND_MIXER_INFO)
 321                return get_mixer_info(mixdev, arg);
 322        if (cmd == SOUND_OLD_MIXER_INFO)
 323                return get_old_mixer_info(mixdev, arg);
 324        if (_SIOC_DIR(cmd) & _SIOC_WRITE)
 325                mixer_devs[mixdev]->modify_counter++;
 326        if (!mixer_devs[mixdev]->ioctl)
 327                return -EINVAL;
 328        return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg);
 329}
 330
 331static int sound_ioctl(struct inode *inode, struct file *file,
 332                       unsigned int cmd, unsigned long arg)
 333{
 334        int len = 0, dtype;
 335        int dev = iminor(inode);
 336        void __user *p = (void __user *)arg;
 337
 338        if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) {
 339                /*
 340                 * Have to validate the address given by the process.
 341                 */
 342                len = _SIOC_SIZE(cmd);
 343                if (len < 1 || len > 65536 || !p)
 344                        return -EFAULT;
 345                if (_SIOC_DIR(cmd) & _SIOC_WRITE)
 346                        if (!access_ok(VERIFY_READ, p, len))
 347                                return -EFAULT;
 348                if (_SIOC_DIR(cmd) & _SIOC_READ)
 349                        if (!access_ok(VERIFY_WRITE, p, len))
 350                                return -EFAULT;
 351        }
 352        DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 353        if (cmd == OSS_GETVERSION)
 354                return __put_user(SOUND_VERSION, (int __user *)p);
 355        
 356        if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 &&   /* Mixer ioctl */
 357            (dev & 0x0f) != SND_DEV_CTL) {              
 358                dtype = dev & 0x0f;
 359                switch (dtype) {
 360                case SND_DEV_DSP:
 361                case SND_DEV_DSP16:
 362                case SND_DEV_AUDIO:
 363                        return sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev,
 364                                                 cmd, p);
 365                        
 366                default:
 367                        return sound_mixer_ioctl(dev >> 4, cmd, p);
 368                }
 369        }
 370        switch (dev & 0x0f) {
 371        case SND_DEV_CTL:
 372                if (cmd == SOUND_MIXER_GETLEVELS)
 373                        return get_mixer_levels(p);
 374                if (cmd == SOUND_MIXER_SETLEVELS)
 375                        return set_mixer_levels(p);
 376                return sound_mixer_ioctl(dev >> 4, cmd, p);
 377
 378        case SND_DEV_SEQ:
 379        case SND_DEV_SEQ2:
 380                return sequencer_ioctl(dev, file, cmd, p);
 381
 382        case SND_DEV_DSP:
 383        case SND_DEV_DSP16:
 384        case SND_DEV_AUDIO:
 385                return audio_ioctl(dev, file, cmd, p);
 386                break;
 387
 388        case SND_DEV_MIDIN:
 389                return MIDIbuf_ioctl(dev, file, cmd, p);
 390                break;
 391
 392        }
 393        return -EINVAL;
 394}
 395
 396static unsigned int sound_poll(struct file *file, poll_table * wait)
 397{
 398        struct inode *inode = file->f_path.dentry->d_inode;
 399        int dev = iminor(inode);
 400
 401        DEB(printk("sound_poll(dev=%d)\n", dev));
 402        switch (dev & 0x0f) {
 403        case SND_DEV_SEQ:
 404        case SND_DEV_SEQ2:
 405                return sequencer_poll(dev, file, wait);
 406
 407        case SND_DEV_MIDIN:
 408                return MIDIbuf_poll(dev, file, wait);
 409
 410        case SND_DEV_DSP:
 411        case SND_DEV_DSP16:
 412        case SND_DEV_AUDIO:
 413                return DMAbuf_poll(file, dev >> 4, wait);
 414        }
 415        return 0;
 416}
 417
 418static int sound_mmap(struct file *file, struct vm_area_struct *vma)
 419{
 420        int dev_class;
 421        unsigned long size;
 422        struct dma_buffparms *dmap = NULL;
 423        int dev = iminor(file->f_path.dentry->d_inode);
 424
 425        dev_class = dev & 0x0f;
 426        dev >>= 4;
 427
 428        if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) {
 429                printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n");
 430                return -EINVAL;
 431        }
 432        lock_kernel();
 433        if (vma->vm_flags & VM_WRITE)   /* Map write and read/write to the output buf */
 434                dmap = audio_devs[dev]->dmap_out;
 435        else if (vma->vm_flags & VM_READ)
 436                dmap = audio_devs[dev]->dmap_in;
 437        else {
 438                printk(KERN_ERR "Sound: Undefined mmap() access\n");
 439                unlock_kernel();
 440                return -EINVAL;
 441        }
 442
 443        if (dmap == NULL) {
 444                printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n");
 445                unlock_kernel();
 446                return -EIO;
 447        }
 448        if (dmap->raw_buf == NULL) {
 449                printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n");
 450                unlock_kernel();
 451                return -EIO;
 452        }
 453        if (dmap->mapping_flags) {
 454                printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n");
 455                unlock_kernel();
 456                return -EIO;
 457        }
 458        if (vma->vm_pgoff != 0) {
 459                printk(KERN_ERR "Sound: mmap() offset must be 0.\n");
 460                unlock_kernel();
 461                return -EINVAL;
 462        }
 463        size = vma->vm_end - vma->vm_start;
 464
 465        if (size != dmap->bytes_in_use) {
 466                printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use);
 467        }
 468        if (remap_pfn_range(vma, vma->vm_start,
 469                        virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT,
 470                        vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
 471                unlock_kernel();
 472                return -EAGAIN;
 473        }
 474
 475        dmap->mapping_flags |= DMA_MAP_MAPPED;
 476
 477        if( audio_devs[dev]->d->mmap)
 478                audio_devs[dev]->d->mmap(dev);
 479
 480        memset(dmap->raw_buf,
 481               dmap->neutral_byte,
 482               dmap->bytes_in_use);
 483        unlock_kernel();
 484        return 0;
 485}
 486
 487const struct file_operations oss_sound_fops = {
 488        .owner          = THIS_MODULE,
 489        .llseek         = no_llseek,
 490        .read           = sound_read,
 491        .write          = sound_write,
 492        .poll           = sound_poll,
 493        .ioctl          = sound_ioctl,
 494        .mmap           = sound_mmap,
 495        .open           = sound_open,
 496        .release        = sound_release,
 497};
 498
 499/*
 500 *      Create the required special subdevices
 501 */
 502 
 503static int create_special_devices(void)
 504{
 505        int seq1,seq2;
 506        seq1=register_sound_special(&oss_sound_fops, 1);
 507        if(seq1==-1)
 508                goto bad;
 509        seq2=register_sound_special(&oss_sound_fops, 8);
 510        if(seq2!=-1)
 511                return 0;
 512        unregister_sound_special(1);
 513bad:
 514        return -1;
 515}
 516
 517
 518/* These device names follow the official Linux device list,
 519 * Documentation/devices.txt.  Let us know if there are other
 520 * common names we should support for compatibility.
 521 * Only those devices not created by the generic code in sound_core.c are
 522 * registered here.
 523 */
 524static const struct {
 525        unsigned short minor;
 526        char *name;
 527        umode_t mode;
 528        int *num;
 529} dev_list[] = { /* list of minor devices */
 530/* seems to be some confusion here -- this device is not in the device list */
 531        {SND_DEV_DSP16,     "dspW",      S_IWUGO | S_IRUSR | S_IRGRP,
 532         &num_audiodevs},
 533        {SND_DEV_AUDIO,     "audio",     S_IWUGO | S_IRUSR | S_IRGRP,
 534         &num_audiodevs},
 535};
 536
 537static int dmabuf;
 538static int dmabug;
 539
 540module_param(dmabuf, int, 0444);
 541module_param(dmabug, int, 0444);
 542
 543static int __init oss_init(void)
 544{
 545        int             err;
 546        int i, j;
 547        
 548#ifdef CONFIG_PCI
 549        if(dmabug)
 550                isa_dma_bridge_buggy = dmabug;
 551#endif
 552
 553        err = create_special_devices();
 554        if (err) {
 555                printk(KERN_ERR "sound: driver already loaded/included in kernel\n");
 556                return err;
 557        }
 558
 559        /* Protecting the innocent */
 560        sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 561
 562        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 563                device_create(sound_class, NULL,
 564                              MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
 565                              "%s", dev_list[i].name);
 566
 567                if (!dev_list[i].num)
 568                        continue;
 569
 570                for (j = 1; j < *dev_list[i].num; j++)
 571                        device_create(sound_class, NULL,
 572                                      MKDEV(SOUND_MAJOR,
 573                                            dev_list[i].minor + (j*0x10)),
 574                                      NULL, "%s%d", dev_list[i].name, j);
 575        }
 576
 577        if (sound_nblocks >= 1024)
 578                printk(KERN_ERR "Sound warning: Deallocation table was too small.\n");
 579        
 580        return 0;
 581}
 582
 583static void __exit oss_cleanup(void)
 584{
 585        int i, j;
 586
 587        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 588                device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
 589                if (!dev_list[i].num)
 590                        continue;
 591                for (j = 1; j < *dev_list[i].num; j++)
 592                        device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
 593        }
 594        
 595        unregister_sound_special(1);
 596        unregister_sound_special(8);
 597
 598        sound_stop_timer();
 599
 600        sequencer_unload();
 601
 602        for (i = 0; i < MAX_DMA_CHANNELS; i++)
 603                if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) {
 604                        printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i);
 605                        sound_free_dma(i);
 606                }
 607
 608        for (i = 0; i < sound_nblocks; i++)
 609                vfree(sound_mem_blocks[i]);
 610
 611}
 612
 613module_init(oss_init);
 614module_exit(oss_cleanup);
 615MODULE_LICENSE("GPL");
 616MODULE_DESCRIPTION("OSS Sound subsystem");
 617MODULE_AUTHOR("Hannu Savolainen, et al.");
 618
 619
 620int sound_alloc_dma(int chn, char *deviceID)
 621{
 622        int err;
 623
 624        if ((err = request_dma(chn, deviceID)) != 0)
 625                return err;
 626
 627        dma_alloc_map[chn] = DMA_MAP_FREE;
 628
 629        return 0;
 630}
 631EXPORT_SYMBOL(sound_alloc_dma);
 632
 633int sound_open_dma(int chn, char *deviceID)
 634{
 635        if (!valid_dma(chn)) {
 636                printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn);
 637                return 1;
 638        }
 639
 640        if (dma_alloc_map[chn] != DMA_MAP_FREE) {
 641                printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]);
 642                return 1;
 643        }
 644        dma_alloc_map[chn] = DMA_MAP_BUSY;
 645        return 0;
 646}
 647EXPORT_SYMBOL(sound_open_dma);
 648
 649void sound_free_dma(int chn)
 650{
 651        if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) {
 652                /* printk( "sound_free_dma: Bad access to DMA channel %d\n",  chn); */
 653                return;
 654        }
 655        free_dma(chn);
 656        dma_alloc_map[chn] = DMA_MAP_UNAVAIL;
 657}
 658EXPORT_SYMBOL(sound_free_dma);
 659
 660void sound_close_dma(int chn)
 661{
 662        if (dma_alloc_map[chn] != DMA_MAP_BUSY) {
 663                printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn);
 664                return;
 665        }
 666        dma_alloc_map[chn] = DMA_MAP_FREE;
 667}
 668EXPORT_SYMBOL(sound_close_dma);
 669
 670static void do_sequencer_timer(unsigned long dummy)
 671{
 672        sequencer_timer(0);
 673}
 674
 675
 676static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0);
 677
 678void request_sound_timer(int count)
 679{
 680        extern unsigned long seq_time;
 681
 682        if (count < 0) {
 683                seq_timer.expires = (-count) + jiffies;
 684                add_timer(&seq_timer);
 685                return;
 686        }
 687        count += seq_time;
 688
 689        count -= jiffies;
 690
 691        if (count < 1)
 692                count = 1;
 693
 694        seq_timer.expires = (count) + jiffies;
 695        add_timer(&seq_timer);
 696}
 697
 698void sound_stop_timer(void)
 699{
 700        del_timer(&seq_timer);
 701}
 702
 703void conf_printf(char *name, struct address_info *hw_config)
 704{
 705#ifndef CONFIG_SOUND_TRACEINIT
 706        return;
 707#else
 708        printk("<%s> at 0x%03x", name, hw_config->io_base);
 709
 710        if (hw_config->irq)
 711                printk(" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq);
 712
 713        if (hw_config->dma != -1 || hw_config->dma2 != -1)
 714        {
 715                printk(" dma %d", hw_config->dma);
 716                if (hw_config->dma2 != -1)
 717                        printk(",%d", hw_config->dma2);
 718        }
 719        printk("\n");
 720#endif
 721}
 722EXPORT_SYMBOL(conf_printf);
 723
 724void conf_printf2(char *name, int base, int irq, int dma, int dma2)
 725{
 726#ifndef CONFIG_SOUND_TRACEINIT
 727        return;
 728#else
 729        printk("<%s> at 0x%03x", name, base);
 730
 731        if (irq)
 732                printk(" irq %d", (irq > 0) ? irq : -irq);
 733
 734        if (dma != -1 || dma2 != -1)
 735        {
 736                  printk(" dma %d", dma);
 737                  if (dma2 != -1)
 738                          printk(",%d", dma2);
 739        }
 740        printk("\n");
 741#endif
 742}
 743EXPORT_SYMBOL(conf_printf2);
 744
 745