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/ioport.h>
  40#include <linux/major.h>
  41#include <linux/delay.h>
  42#include <linux/proc_fs.h>
  43#include <linux/mutex.h>
  44#include <linux/module.h>
  45#include <linux/mm.h>
  46#include <linux/device.h>
  47
  48/*
  49 * This ought to be moved into include/asm/dma.h
  50 */
  51#ifndef valid_dma
  52#define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4)
  53#endif
  54
  55/*
  56 * Table for permanently allocated memory (used when unloading the module)
  57 */
  58void *          sound_mem_blocks[MAX_MEM_BLOCKS];
  59static DEFINE_MUTEX(soundcard_mutex);
  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 (strncmp(name, mixer_vols[i].name, 32) == 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        strncpy(mixer_vols[n].name, name, 32);
 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_inode(file));
 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        mutex_lock(&soundcard_mutex);
 156        
 157        switch (dev & 0x0f) {
 158        case SND_DEV_DSP:
 159        case SND_DEV_DSP16:
 160        case SND_DEV_AUDIO:
 161                ret = audio_read(dev, file, buf, count);
 162                break;
 163
 164        case SND_DEV_SEQ:
 165        case SND_DEV_SEQ2:
 166                ret = sequencer_read(dev, file, buf, count);
 167                break;
 168
 169        case SND_DEV_MIDIN:
 170                ret = MIDIbuf_read(dev, file, buf, count);
 171        }
 172        mutex_unlock(&soundcard_mutex);
 173        return ret;
 174}
 175
 176static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 177{
 178        int dev = iminor(file_inode(file));
 179        int ret = -EINVAL;
 180        
 181        mutex_lock(&soundcard_mutex);
 182        switch (dev & 0x0f) {
 183        case SND_DEV_SEQ:
 184        case SND_DEV_SEQ2:
 185                ret =  sequencer_write(dev, file, buf, count);
 186                break;
 187
 188        case SND_DEV_DSP:
 189        case SND_DEV_DSP16:
 190        case SND_DEV_AUDIO:
 191                ret = audio_write(dev, file, buf, count);
 192                break;
 193
 194        case SND_DEV_MIDIN:
 195                ret =  MIDIbuf_write(dev, file, buf, count);
 196                break;
 197        }
 198        mutex_unlock(&soundcard_mutex);
 199        return ret;
 200}
 201
 202static int sound_open(struct inode *inode, struct file *file)
 203{
 204        int dev = iminor(inode);
 205        int retval;
 206
 207        if ((dev >= SND_NDEVS) || (dev < 0)) {
 208                printk(KERN_ERR "Invalid minor device %d\n", dev);
 209                return -ENXIO;
 210        }
 211        mutex_lock(&soundcard_mutex);
 212        switch (dev & 0x0f) {
 213        case SND_DEV_CTL:
 214                dev >>= 4;
 215                if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
 216                        request_module("mixer%d", dev);
 217                }
 218                retval = -ENXIO;
 219                if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
 220                        break;
 221        
 222                if (!try_module_get(mixer_devs[dev]->owner))
 223                        break;
 224
 225                retval = 0;
 226                break;
 227
 228        case SND_DEV_SEQ:
 229        case SND_DEV_SEQ2:
 230                retval = sequencer_open(dev, file);
 231                break;
 232
 233        case SND_DEV_MIDIN:
 234                retval = MIDIbuf_open(dev, file);
 235                break;
 236
 237        case SND_DEV_DSP:
 238        case SND_DEV_DSP16:
 239        case SND_DEV_AUDIO:
 240                retval = audio_open(dev, file);
 241                break;
 242
 243        default:
 244                printk(KERN_ERR "Invalid minor device %d\n", dev);
 245                retval = -ENXIO;
 246        }
 247
 248        mutex_unlock(&soundcard_mutex);
 249        return retval;
 250}
 251
 252static int sound_release(struct inode *inode, struct file *file)
 253{
 254        int dev = iminor(inode);
 255
 256        mutex_lock(&soundcard_mutex);
 257        switch (dev & 0x0f) {
 258        case SND_DEV_CTL:
 259                module_put(mixer_devs[dev >> 4]->owner);
 260                break;
 261                
 262        case SND_DEV_SEQ:
 263        case SND_DEV_SEQ2:
 264                sequencer_release(dev, file);
 265                break;
 266
 267        case SND_DEV_MIDIN:
 268                MIDIbuf_release(dev, file);
 269                break;
 270
 271        case SND_DEV_DSP:
 272        case SND_DEV_DSP16:
 273        case SND_DEV_AUDIO:
 274                audio_release(dev, file);
 275                break;
 276
 277        default:
 278                printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev);
 279        }
 280        mutex_unlock(&soundcard_mutex);
 281
 282        return 0;
 283}
 284
 285static int get_mixer_info(int dev, void __user *arg)
 286{
 287        mixer_info info;
 288        memset(&info, 0, sizeof(info));
 289        strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
 290        strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
 291        info.modify_counter = mixer_devs[dev]->modify_counter;
 292        if (__copy_to_user(arg, &info,  sizeof(info)))
 293                return -EFAULT;
 294        return 0;
 295}
 296
 297static int get_old_mixer_info(int dev, void __user *arg)
 298{
 299        _old_mixer_info info;
 300        memset(&info, 0, sizeof(info));
 301        strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
 302        strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
 303        if (copy_to_user(arg, &info,  sizeof(info)))
 304                return -EFAULT;
 305        return 0;
 306}
 307
 308static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg)
 309{
 310        if (mixdev < 0 || mixdev >= MAX_MIXER_DEV)
 311                return -ENXIO;
 312        /* Try to load the mixer... */
 313        if (mixer_devs[mixdev] == NULL) {
 314                request_module("mixer%d", mixdev);
 315        }
 316        if (mixdev >= num_mixers || !mixer_devs[mixdev])
 317                return -ENXIO;
 318        if (cmd == SOUND_MIXER_INFO)
 319                return get_mixer_info(mixdev, arg);
 320        if (cmd == SOUND_OLD_MIXER_INFO)
 321                return get_old_mixer_info(mixdev, arg);
 322        if (_SIOC_DIR(cmd) & _SIOC_WRITE)
 323                mixer_devs[mixdev]->modify_counter++;
 324        if (!mixer_devs[mixdev]->ioctl)
 325                return -EINVAL;
 326        return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg);
 327}
 328
 329static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 330{
 331        int len = 0, dtype;
 332        int dev = iminor(file_inode(file));
 333        long ret = -EINVAL;
 334        void __user *p = (void __user *)arg;
 335
 336        if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) {
 337                /*
 338                 * Have to validate the address given by the process.
 339                 */
 340                len = _SIOC_SIZE(cmd);
 341                if (len < 1 || len > 65536 || !p)
 342                        return -EFAULT;
 343                if (_SIOC_DIR(cmd) & _SIOC_WRITE)
 344                        if (!access_ok(VERIFY_READ, p, len))
 345                                return -EFAULT;
 346                if (_SIOC_DIR(cmd) & _SIOC_READ)
 347                        if (!access_ok(VERIFY_WRITE, p, len))
 348                                return -EFAULT;
 349        }
 350        if (cmd == OSS_GETVERSION)
 351                return __put_user(SOUND_VERSION, (int __user *)p);
 352        
 353        mutex_lock(&soundcard_mutex);
 354        if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 &&   /* Mixer ioctl */
 355            (dev & 0x0f) != SND_DEV_CTL) {              
 356                dtype = dev & 0x0f;
 357                switch (dtype) {
 358                case SND_DEV_DSP:
 359                case SND_DEV_DSP16:
 360                case SND_DEV_AUDIO:
 361                        ret = sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev,
 362                                                 cmd, p);
 363                        break;                  
 364                default:
 365                        ret = sound_mixer_ioctl(dev >> 4, cmd, p);
 366                        break;
 367                }
 368                mutex_unlock(&soundcard_mutex);
 369                return ret;
 370        }
 371
 372        switch (dev & 0x0f) {
 373        case SND_DEV_CTL:
 374                if (cmd == SOUND_MIXER_GETLEVELS)
 375                        ret = get_mixer_levels(p);
 376                else if (cmd == SOUND_MIXER_SETLEVELS)
 377                        ret = set_mixer_levels(p);
 378                else
 379                        ret = sound_mixer_ioctl(dev >> 4, cmd, p);
 380                break;
 381
 382        case SND_DEV_SEQ:
 383        case SND_DEV_SEQ2:
 384                ret = sequencer_ioctl(dev, file, cmd, p);
 385                break;
 386
 387        case SND_DEV_DSP:
 388        case SND_DEV_DSP16:
 389        case SND_DEV_AUDIO:
 390                ret = audio_ioctl(dev, file, cmd, p);
 391                break;
 392
 393        case SND_DEV_MIDIN:
 394                ret = MIDIbuf_ioctl(dev, file, cmd, p);
 395                break;
 396
 397        }
 398        mutex_unlock(&soundcard_mutex);
 399        return ret;
 400}
 401
 402static unsigned int sound_poll(struct file *file, poll_table * wait)
 403{
 404        struct inode *inode = file_inode(file);
 405        int dev = iminor(inode);
 406
 407        switch (dev & 0x0f) {
 408        case SND_DEV_SEQ:
 409        case SND_DEV_SEQ2:
 410                return sequencer_poll(dev, file, wait);
 411
 412        case SND_DEV_MIDIN:
 413                return MIDIbuf_poll(dev, file, wait);
 414
 415        case SND_DEV_DSP:
 416        case SND_DEV_DSP16:
 417        case SND_DEV_AUDIO:
 418                return DMAbuf_poll(file, dev >> 4, wait);
 419        }
 420        return 0;
 421}
 422
 423static int sound_mmap(struct file *file, struct vm_area_struct *vma)
 424{
 425        int dev_class;
 426        unsigned long size;
 427        struct dma_buffparms *dmap = NULL;
 428        int dev = iminor(file_inode(file));
 429
 430        dev_class = dev & 0x0f;
 431        dev >>= 4;
 432
 433        if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) {
 434                printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n");
 435                return -EINVAL;
 436        }
 437        mutex_lock(&soundcard_mutex);
 438        if (vma->vm_flags & VM_WRITE)   /* Map write and read/write to the output buf */
 439                dmap = audio_devs[dev]->dmap_out;
 440        else if (vma->vm_flags & VM_READ)
 441                dmap = audio_devs[dev]->dmap_in;
 442        else {
 443                printk(KERN_ERR "Sound: Undefined mmap() access\n");
 444                mutex_unlock(&soundcard_mutex);
 445                return -EINVAL;
 446        }
 447
 448        if (dmap == NULL) {
 449                printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n");
 450                mutex_unlock(&soundcard_mutex);
 451                return -EIO;
 452        }
 453        if (dmap->raw_buf == NULL) {
 454                printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n");
 455                mutex_unlock(&soundcard_mutex);
 456                return -EIO;
 457        }
 458        if (dmap->mapping_flags) {
 459                printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n");
 460                mutex_unlock(&soundcard_mutex);
 461                return -EIO;
 462        }
 463        if (vma->vm_pgoff != 0) {
 464                printk(KERN_ERR "Sound: mmap() offset must be 0.\n");
 465                mutex_unlock(&soundcard_mutex);
 466                return -EINVAL;
 467        }
 468        size = vma->vm_end - vma->vm_start;
 469
 470        if (size != dmap->bytes_in_use) {
 471                printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use);
 472        }
 473        if (remap_pfn_range(vma, vma->vm_start,
 474                        virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT,
 475                        vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
 476                mutex_unlock(&soundcard_mutex);
 477                return -EAGAIN;
 478        }
 479
 480        dmap->mapping_flags |= DMA_MAP_MAPPED;
 481
 482        if( audio_devs[dev]->d->mmap)
 483                audio_devs[dev]->d->mmap(dev);
 484
 485        memset(dmap->raw_buf,
 486               dmap->neutral_byte,
 487               dmap->bytes_in_use);
 488        mutex_unlock(&soundcard_mutex);
 489        return 0;
 490}
 491
 492const struct file_operations oss_sound_fops = {
 493        .owner          = THIS_MODULE,
 494        .llseek         = no_llseek,
 495        .read           = sound_read,
 496        .write          = sound_write,
 497        .poll           = sound_poll,
 498        .unlocked_ioctl = sound_ioctl,
 499        .mmap           = sound_mmap,
 500        .open           = sound_open,
 501        .release        = sound_release,
 502};
 503
 504/*
 505 *      Create the required special subdevices
 506 */
 507 
 508static int create_special_devices(void)
 509{
 510        int seq1,seq2;
 511        seq1=register_sound_special(&oss_sound_fops, 1);
 512        if(seq1==-1)
 513                goto bad;
 514        seq2=register_sound_special(&oss_sound_fops, 8);
 515        if(seq2!=-1)
 516                return 0;
 517        unregister_sound_special(1);
 518bad:
 519        return -1;
 520}
 521
 522
 523static int dmabuf;
 524static int dmabug;
 525
 526module_param(dmabuf, int, 0444);
 527module_param(dmabug, int, 0444);
 528
 529/* additional minors for compatibility */
 530struct oss_minor_dev {
 531        unsigned short minor;
 532        unsigned int enabled;
 533} dev_list[] = {
 534        { SND_DEV_DSP16 },
 535        { SND_DEV_AUDIO },
 536};
 537
 538static int __init oss_init(void)
 539{
 540        int             err;
 541        int i, j;
 542        
 543#ifdef CONFIG_PCI
 544        if(dmabug)
 545                isa_dma_bridge_buggy = dmabug;
 546#endif
 547
 548        err = create_special_devices();
 549        if (err) {
 550                printk(KERN_ERR "sound: driver already loaded/included in kernel\n");
 551                return err;
 552        }
 553
 554        /* Protecting the innocent */
 555        sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 556
 557        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 558                j = 0;
 559                do {
 560                        unsigned short minor = dev_list[i].minor + j * 0x10;
 561                        if (!register_sound_special(&oss_sound_fops, minor))
 562                                dev_list[i].enabled = (1 << j);
 563                } while (++j < num_audiodevs);
 564        }
 565
 566        if (sound_nblocks >= MAX_MEM_BLOCKS - 1)
 567                printk(KERN_ERR "Sound warning: Deallocation table was too small.\n");
 568        
 569        return 0;
 570}
 571
 572static void __exit oss_cleanup(void)
 573{
 574        int i, j;
 575
 576        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 577                j = 0;
 578                do {
 579                        if (dev_list[i].enabled & (1 << j))
 580                                unregister_sound_special(dev_list[i].minor);
 581                } while (++j < num_audiodevs);
 582        }
 583        
 584        unregister_sound_special(1);
 585        unregister_sound_special(8);
 586
 587        sound_stop_timer();
 588
 589        sequencer_unload();
 590
 591        for (i = 0; i < MAX_DMA_CHANNELS; i++)
 592                if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) {
 593                        printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i);
 594                        sound_free_dma(i);
 595                }
 596
 597        for (i = 0; i < sound_nblocks; i++)
 598                vfree(sound_mem_blocks[i]);
 599
 600}
 601
 602module_init(oss_init);
 603module_exit(oss_cleanup);
 604MODULE_LICENSE("GPL");
 605MODULE_DESCRIPTION("OSS Sound subsystem");
 606MODULE_AUTHOR("Hannu Savolainen, et al.");
 607
 608
 609int sound_alloc_dma(int chn, char *deviceID)
 610{
 611        int err;
 612
 613        if ((err = request_dma(chn, deviceID)) != 0)
 614                return err;
 615
 616        dma_alloc_map[chn] = DMA_MAP_FREE;
 617
 618        return 0;
 619}
 620EXPORT_SYMBOL(sound_alloc_dma);
 621
 622int sound_open_dma(int chn, char *deviceID)
 623{
 624        if (!valid_dma(chn)) {
 625                printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn);
 626                return 1;
 627        }
 628
 629        if (dma_alloc_map[chn] != DMA_MAP_FREE) {
 630                printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]);
 631                return 1;
 632        }
 633        dma_alloc_map[chn] = DMA_MAP_BUSY;
 634        return 0;
 635}
 636EXPORT_SYMBOL(sound_open_dma);
 637
 638void sound_free_dma(int chn)
 639{
 640        if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) {
 641                /* printk( "sound_free_dma: Bad access to DMA channel %d\n",  chn); */
 642                return;
 643        }
 644        free_dma(chn);
 645        dma_alloc_map[chn] = DMA_MAP_UNAVAIL;
 646}
 647EXPORT_SYMBOL(sound_free_dma);
 648
 649void sound_close_dma(int chn)
 650{
 651        if (dma_alloc_map[chn] != DMA_MAP_BUSY) {
 652                printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn);
 653                return;
 654        }
 655        dma_alloc_map[chn] = DMA_MAP_FREE;
 656}
 657EXPORT_SYMBOL(sound_close_dma);
 658
 659static void do_sequencer_timer(unsigned long dummy)
 660{
 661        sequencer_timer(0);
 662}
 663
 664
 665static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0);
 666
 667void request_sound_timer(int count)
 668{
 669        extern unsigned long seq_time;
 670
 671        if (count < 0) {
 672                seq_timer.expires = (-count) + jiffies;
 673                add_timer(&seq_timer);
 674                return;
 675        }
 676        count += seq_time;
 677
 678        count -= jiffies;
 679
 680        if (count < 1)
 681                count = 1;
 682
 683        seq_timer.expires = (count) + jiffies;
 684        add_timer(&seq_timer);
 685}
 686
 687void sound_stop_timer(void)
 688{
 689        del_timer(&seq_timer);
 690}
 691
 692void conf_printf(char *name, struct address_info *hw_config)
 693{
 694#ifndef CONFIG_SOUND_TRACEINIT
 695        return;
 696#else
 697        printk("<%s> at 0x%03x", name, hw_config->io_base);
 698
 699        if (hw_config->irq)
 700                printk(" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq);
 701
 702        if (hw_config->dma != -1 || hw_config->dma2 != -1)
 703        {
 704                printk(" dma %d", hw_config->dma);
 705                if (hw_config->dma2 != -1)
 706                        printk(",%d", hw_config->dma2);
 707        }
 708        printk("\n");
 709#endif
 710}
 711EXPORT_SYMBOL(conf_printf);
 712
 713void conf_printf2(char *name, int base, int irq, int dma, int dma2)
 714{
 715#ifndef CONFIG_SOUND_TRACEINIT
 716        return;
 717#else
 718        printk("<%s> at 0x%03x", name, base);
 719
 720        if (irq)
 721                printk(" irq %d", (irq > 0) ? irq : -irq);
 722
 723        if (dma != -1 || dma2 != -1)
 724        {
 725                  printk(" dma %d", dma);
 726                  if (dma2 != -1)
 727                          printk(",%d", dma2);
 728        }
 729        printk("\n");
 730#endif
 731}
 732EXPORT_SYMBOL(conf_printf2);
 733
 734