📄 soundcard.c
字号:
int i; if (connect_wrapper (WRAPPER_VERSION) < 0) { printk ("Sound: Incompatible kernel (wrapper) version\n"); return -EINVAL; } /* * "sound=" command line handling by Harald Milz. */ i = 0; while (i < 20 && sound[i]) ints[i + 1] = sound[i++]; ints[0] = i; if (i) sound_setup ("sound=", ints); err = module_register_chrdev (sound_major, "sound", &sound_fops); if (err) { printk ("sound: driver already loaded/included in kernel\n"); return err; } chrdev_registered = 1; soundcard_init (); if (sound_nblocks >= 1024) printk ("Sound warning: Deallocation table was too small.\n"); return 0;}#ifdef MODULEvoidcleanup_module (void){ int i; if (MOD_IN_USE) { return; } if (chrdev_registered) module_unregister_chrdev (sound_major, "sound");#ifdef CONFIG_SEQUENCER sound_stop_timer ();#endif#ifdef CONFIG_LOWLEVEL_SOUND { extern void sound_unload_lowlevel_drivers (void); sound_unload_lowlevel_drivers (); }#endif sound_unload_drivers (); for (i = 0; i < sound_nblocks; i++) vfree (sound_mem_blocks[i]); free_all_irqs (); /* If something was left allocated by accident */ for (i = 0; i < MAX_DMA_CHANNELS; i++) if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { printk ("Sound: Hmm, DMA%d was left allocated - fixed\n", i); sound_free_dma (i); }}#endifvoidtenmicrosec (int *osp){ int i; for (i = 0; i < 16; i++) inb (0x80);}intsnd_set_irq_handler (int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp){ int retcode; unsigned long flags; save_flags (flags); cli (); retcode = request_irq (interrupt_level, iproc, 0 /* SA_INTERRUPT */ , name, NULL); if (retcode < 0) { printk ("Sound: IRQ%d already in use\n", interrupt_level); } else irqs |= (1ul << interrupt_level); restore_flags (flags); return retcode;}voidsnd_release_irq (int vect){ if (!(irqs & (1ul << vect))) return; irqs &= ~(1ul << vect); free_irq (vect, NULL);}intsound_alloc_dma (int chn, char *deviceID){ int err; if ((err = request_dma (chn, deviceID)) != 0) return err; dma_alloc_map[chn] = DMA_MAP_FREE; return 0;}intsound_open_dma (int chn, char *deviceID){ unsigned long flags; if (chn < 0 || chn >= MAX_DMA_CHANNELS || chn == 4) { printk ("sound_open_dma: Invalid DMA channel %d\n", chn); return 1; } save_flags (flags); cli (); if (dma_alloc_map[chn] != DMA_MAP_FREE) { printk ("sound_open_dma: DMA channel %d busy or not allocated\n", chn); restore_flags (flags); return 1; } dma_alloc_map[chn] = DMA_MAP_BUSY; restore_flags (flags); return 0;}voidsound_free_dma (int chn){ if (dma_alloc_map[chn] != DMA_MAP_FREE) { /* printk ("sound_free_dma: Bad access to DMA channel %d\n", chn); */ return; } free_dma (chn); dma_alloc_map[chn] = DMA_MAP_UNAVAIL;}voidsound_close_dma (int chn){ unsigned long flags; save_flags (flags); cli (); if (dma_alloc_map[chn] != DMA_MAP_BUSY) { printk ("sound_close_dma: Bad access to DMA channel %d\n", chn); restore_flags (flags); return; } dma_alloc_map[chn] = DMA_MAP_FREE; restore_flags (flags);}#ifdef CONFIG_SEQUENCERstatic struct timer_list seq_timer ={NULL, NULL, 0, 0, sequencer_timer};voidrequest_sound_timer (int count){ extern unsigned long seq_time; if (count < 0) count = jiffies + (-count); else count += seq_time; ; { seq_timer.expires = ((count - jiffies)) + jiffies; add_timer (&seq_timer); };}voidsound_stop_timer (void){ del_timer (&seq_timer);;}#endif#ifdef CONFIG_AUDIO#ifdef KMALLOC_DMA_BROKENfatal_error__This_version_is_not_compatible_with_this_kernel;#endifstatic int dma_buffsize = DSP_BUFFSIZE;intsound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan){ char *start_addr, *end_addr; int i, dma_pagesize; dmap->mapping_flags &= ~DMA_MAP_MAPPED; if (dmap->raw_buf != NULL) return 0; /* Already done */ if (dma_buffsize < 4096) dma_buffsize = 4096; if (chan < 4) dma_pagesize = 64 * 1024; else dma_pagesize = 128 * 1024; dmap->raw_buf = NULL; if (debugmem) printk ("sound: buffsize[%d] = %lu\n", dev, audio_devs[dev]->buffsize); audio_devs[dev]->buffsize = dma_buffsize; if (audio_devs[dev]->buffsize > dma_pagesize) audio_devs[dev]->buffsize = dma_pagesize; start_addr = NULL;/* * Now loop until we get a free buffer. Try to get smaller buffer if * it fails. */ while (start_addr == NULL && audio_devs[dev]->buffsize > PAGE_SIZE) { int sz, size; for (sz = 0, size = PAGE_SIZE; size < audio_devs[dev]->buffsize; sz++, size <<= 1); audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz); if ((start_addr = (char *) __get_dma_pages (GFP_ATOMIC, sz)) == NULL) audio_devs[dev]->buffsize /= 2; } if (start_addr == NULL) { printk ("Sound error: Couldn't allocate DMA buffer\n"); return -(ENOMEM); } else { /* make some checks */ end_addr = start_addr + audio_devs[dev]->buffsize - 1; if (debugmem) printk ("sound: start 0x%lx, end 0x%lx\n", (long) start_addr, (long) end_addr); /* now check if it fits into the same dma-pagesize */ if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1)) || end_addr >= (char *) (MAX_DMA_ADDRESS)) { printk ( "sound: Got invalid address 0x%lx for %ldb DMA-buffer\n", (long) start_addr, audio_devs[dev]->buffsize); return -(EFAULT); } } dmap->raw_buf = start_addr; dmap->raw_buf_phys = virt_to_bus (start_addr); for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) { mem_map_reserve (i); } return 0;}voidsound_free_dmap (int dev, struct dma_buffparms *dmap){ int sz, size, i; unsigned long start_addr, end_addr; if (dmap->raw_buf == NULL) return; if (dmap->mapping_flags & DMA_MAP_MAPPED) return; /* Don't free mmapped buffer. Will use it next time */ for (sz = 0, size = PAGE_SIZE; size < audio_devs[dev]->buffsize; sz++, size <<= 1); start_addr = (unsigned long) dmap->raw_buf; end_addr = start_addr + audio_devs[dev]->buffsize; for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++) { mem_map_unreserve (i); } free_pages ((unsigned long) dmap->raw_buf, sz); dmap->raw_buf = NULL;}intsound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc * info){ printk ("Entered sound_map_buffer()\n"); printk ("Exited sound_map_buffer()\n"); return -(EINVAL);}#endifvoidconf_printf (char *name, struct address_info *hw_config){ if (!trace_init) return; printk ("<%s> at 0x%03x", name, hw_config->io_base); if (hw_config->irq) printk (" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq); if (hw_config->dma != -1 || hw_config->dma2 != -1) { printk (" dma %d", hw_config->dma); if (hw_config->dma2 != -1) printk (",%d", hw_config->dma2); } printk ("\n");}voidconf_printf2 (char *name, int base, int irq, int dma, int dma2){ if (!trace_init) return; printk ("<%s> at 0x%03x", name, base); if (irq) printk (" irq %d", (irq > 0) ? irq : -irq); if (dma != -1 || dma2 != -1) { printk (" dma %d", dma); if (dma2 != -1) printk (",%d", dma2); } printk ("\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -