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