欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux音频设备驱动_OSS驱动框架(二)————OSS驱动架构代码vmsnd.c

程序员文章站 2022-07-13 21:44:43
...

在vmsnd驱动模块被加载时函数init_vwsnd()被调用,音频驱动被初始化,驱动初始化过程会查找硬件配置和匹配相应的驱动程序。函数init_vwsnd()的主要内容如下:

static int __init init_vwsnd(void)
{
    int err;

    DBGXV("\n");
    DBGXV("sound::vwsnd::init_module()\n");
    /*驱动的探测函数*/
    if (!probe_vwsnd(&the_hw_config))
        return -ENODEV;
    /*驱动附着函数*/
    err = attach_vwsnd(&the_hw_config);
    if (err < 0)
        return err;
    return 0;
}

在函数attach_vwsnd()中,调用了对数字音频设备的注册函数register_sound_dsp()和对混频器接口的注册函数register_sound_mixer()。函数的主要内容如下:

static int __init attach_vwsnd(struct address_info *hw_config)
{
    vwsnd_dev_t *devc = NULL;
    int err = -ENOMEM;

    DBGEV("(hw_config=0x%p)\n", hw_config);
    /*为devc分配空间*/
    devc = kmalloc(sizeof (vwsnd_dev_t), GFP_KERNEL);
    if (devc == NULL)
        goto fail0;
    /*下面是给结构体devc各个字段赋值*/
    err = li_create(&devc->lith, hw_config->io_base);
    if (err)
        goto fail1;

    init_waitqueue_head(&devc->open_wait);

    devc->rport.hwbuf_size = HWBUF_SIZE;
    devc->rport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
    if (!devc->rport.hwbuf_vaddr)
        goto fail2;
    devc->rport.hwbuf = (void *) devc->rport.hwbuf_vaddr;
    devc->rport.hwbuf_paddr = virt_to_phys(devc->rport.hwbuf);

     *
     * We set the input side's DMA base address here.  It will remain
     * valid until the driver is unloaded.
     */
    /*设置输入侧的DMA基地址,保持它到驱动被卸载前*/
    li_writel(&devc->lith, LI_COMM1_BASE,
          devc->rport.hwbuf_paddr >> 8 | 1 << (37 - 8));

    devc->wport.hwbuf_size = HWBUF_SIZE;
    devc->wport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
    if (!devc->wport.hwbuf_vaddr)
        goto fail3;
    devc->wport.hwbuf = (void *) devc->wport.hwbuf_vaddr;
    devc->wport.hwbuf_paddr = virt_to_phys(devc->wport.hwbuf);
    DBGP("wport hwbuf = 0x%p\n", devc->wport.hwbuf);

    DBGDO(shut_up++);
    err = ad1843_init(&devc->lith);
    DBGDO(shut_up--);
    if (err)
        goto fail4;

    /* install interrupt handler */

    err = request_irq(hw_config->irq, vwsnd_audio_intr, 0, "vwsnd", devc);
    if (err)
        goto fail5;

    /* register this device's drivers. */

    devc->audio_minor = register_sound_dsp(&vwsnd_audio_fops, -1);
    if ((err = devc->audio_minor) < 0) {
        DBGDO(printk(KERN_WARNING
                 "attach_vwsnd: register_sound_dsp error %d\n",
                 err));
        goto fail6;
    }
    devc->mixer_minor = register_sound_mixer(&vwsnd_mixer_fops,
                         devc->audio_minor >> 4);
    if ((err = devc->mixer_minor) < 0) {
        DBGDO(printk(KERN_WARNING
                 "attach_vwsnd: register_sound_mixer error %d\n",
                 err));
        goto fail7;
    }

    /* Squirrel away device indices for unload routine. */

    hw_config->slots[0] = devc->audio_minor;

    /* Initialize as much of *devc as possible */

    mutex_init(&devc->open_mutex);
    mutex_init(&devc->io_mutex);
    mutex_init(&devc->mix_mutex);
    devc->open_mode = 0;
    spin_lock_init(&devc->rport.lock);
    init_waitqueue_head(&devc->rport.queue);
    devc->rport.swstate = SW_OFF;
    devc->rport.hwstate = HW_STOPPED;
    devc->rport.flags = 0;
    devc->rport.swbuf = NULL;
    spin_lock_init(&devc->wport.lock);
    init_waitqueue_head(&devc->wport.queue);
    devc->wport.swstate = SW_OFF;
    devc->wport.hwstate = HW_STOPPED;
    devc->wport.flags = 0;
    devc->wport.swbuf = NULL;

    /* Success.  Link us onto the local device list. */

    devc->next_dev = vwsnd_dev_list;
    vwsnd_dev_list = devc;
    return devc->audio_minor;

    /* So many ways to fail.  Undo what we did. */

 fail7:
    unregister_sound_dsp(devc->audio_minor);
 fail6:
    free_irq(hw_config->irq, devc);
 fail5:
 fail4:
    free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER);
 fail3:
    free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER);
 fail2:
    li_destroy(&devc->lith);
 fail1:
    kfree(devc);
 fail0:
    return err;
}

OSS驱动程序在sound/oss目录下,核心代码文件为soundcard.c。该文件中定义了打开设备文件,读设备文件(录音),写设备文件(播放),关闭设备文件等功能。