Open Sound System |
Do you have problems with sound/audio application development? Don't panic! Click here for help! |
This file will be shipped in source format and compiled in the target (customer) system. In this way minor changes between Linux versions can be fixed by the customer.
Copyright (C) 4Front Technologies 2005-2009. Released under GPL2 license.
//#include <linux/config.h> typedef int *ioctl_arg; #include <linux/init.h> #include <linux/module.h> #include <linux/delay.h> #include <stdarg.h> #include <linux/vmalloc.h> #include "timestamp.h" #include "local_config.h" #include "oss_exports.h" #include "wrap.h" #include "ossdip.h" #include <linux/version.h> #include <linux/fs.h> #include <linux/poll.h> #include <linux/time.h> #include <linux/proc_fs.h> #include <linux/spinlock.h> #include <linux/pci.h> #include <linux/irq.h> #include <linux/sched.h> #include <linux/interrupt.h> #undef strlen #undef strcpy #define strlen oss_strlen #define strcpy oss_strcpy typedef struct _smap_t dmap_t; #include "soundcard.h" #include "audio_core.h" #include "mixer_core.h" #include "ubuntu_version_hack.inc" MODULE_LICENSE ("GPL v2"); MODULE_DESCRIPTION ("Open Sound System core services"); MODULE_AUTHOR ("4Front Technologies (support@opensound.com)"); struct _oss_mutex_t { /* Caution! This definition must match cuckoo.h */ spinlock_t lock; int filler; /* Make sure this structure doesn't become zero length */ }; static oss_device_t *core_osdev = NULL;
Minor device list
#define MAX_MINOR 256 typedef struct { int major, minor; char name[32]; } oss_minor_t; static oss_minor_t minors[MAX_MINOR]; static int nminors = 0;
Sleep flags. Make sure these definitions match oss_config.h.
#define WK_NONE 0x00 #define WK_WAKEUP 0x01 #define WK_TIMEOUT 0x02 #define WK_SIGNAL 0x04 #define WK_SLEEP 0x08 #define WK_SELECT 0x10 time_t oss_get_time (void) { #if 1 return get_seconds (); #else return xtime.tv_sec; #endif } void *oss_memset (void *t, int val, size_t l); void * oss_kmem_alloc (size_t size) { void *ptr; if ((ptr = vmalloc (size)) == NULL) { oss_cmn_err (CE_WARN, "vmalloc(%d) failed\n", size); return NULL; } memset (ptr, 0, size); return ptr; } void oss_kmem_free (void *addr) { vfree (addr); } /* oss_pmalloc() moved to os_linux.c */ extern oss_native_word oss_virt_to_bus (void *addr) { return virt_to_bus (addr); } void * oss_memcpy (void *t_, const void *f_, size_t l) { unsigned char *t = t_; unsigned const char *f = f_; int i; for (i = 0; i < l; i++) *t++ = *f++; return t; } void * oss_memset (void *t, int val, size_t l) { char *c = t; while (l-- > 0) *c++ = val; return t; } int oss_strcmp (const char *s1, const char *s2) { while (*s1 && *s2) { if (*s1 != *s2) return *s1 - *s2; s1++; s2++; } return *s1 - *s2; } int oss_strncmp (const char *s1, const char *s2, size_t len) { while (*s1 && *s2 && len--) { if (*s1 != *s2) return *s1 - *s2; s1++; s2++; } return *s1 - *s2; } char * oss_strcpy (char *s1, const char *s2) { char *s = s1; while (*s2) *s1++ = *s2++; *s1 = '\0'; return s; } size_t oss_strlen (const char *s) { int i; for (i = 0; s[i]; i++); return i; } char * oss_strncpy (char *s1, const char *s2, size_t l) { char *s = s1; int n = 0; while (*s2) { if (n++ >= l) return s; *s1++ = *s2++; } *s1 = '\0'; return s; } int oss_hz = HZ; extern int max_intrate; extern int detect_trace; extern int src_quality; extern int flat_device_model; extern int vmix_disabled; extern int vmix_no_autoattach; extern int vmix_loopdevs; extern int ac97_amplifier; extern int ac97_recselect; extern int cooked_enable; extern int dma_buffsize; extern int excl_policy; extern int mixer_muted; module_param (oss_hz, int, S_IRUGO); module_param (max_intrate, int, S_IRUGO); module_param (detect_trace, int, S_IRUGO); module_param (src_quality, int, S_IRUGO); module_param (flat_device_model, int, S_IRUGO); module_param (vmix_disabled, int, S_IRUGO); module_param (vmix_no_autoattach, int, S_IRUGO); module_param (vmix_loopdevs, int, S_IRUGO); module_param (ac97_amplifier, int, S_IRUGO); module_param (ac97_recselect, int, S_IRUGO); module_param (cooked_enable, int, S_IRUGO); module_param (dma_buffsize, int, S_IRUGO); module_param (excl_policy, int, S_IRUGO); module_param (mixer_muted, int, S_IRUGO); static struct proc_dir_entry *oss_proc_root = NULL; static struct proc_dir_entry *oss_proc_devfiles = NULL; static ssize_t oss_read_devfiles (struct file *file, char __user * buf, size_t count, loff_t * ppos) { static char tmp[8192]; char *s; static int eof = 0; int i; if (eof) { eof = 0; return 0; } *tmp = 0; s = tmp; for (i = 0; i < nminors; i++) { if (strlen (tmp) > sizeof (tmp) - 20) { printk (KERN_ALERT "osscore: Procfs buffer too small\n"); return -ENOMEM; } s += sprintf (s, "%s %d %d\n", minors[i].name, minors[i].major, minors[i].minor); } if (copy_to_user (buf, (void *) tmp, strlen (tmp))) return -EFAULT; eof = 1; return strlen (tmp); } static struct file_operations oss_proc_operations = { .read = oss_read_devfiles, }; static void init_proc_fs (void) { if ((oss_proc_root = create_proc_entry ("opensound", 0700 | S_IFDIR, NULL)) == NULL) { oss_cmn_err (CE_CONT, "Cannot create /proc/opensound\n"); return; } if ((oss_proc_devfiles = create_proc_entry ("devfiles", 0600, oss_proc_root)) == NULL) { oss_cmn_err (CE_CONT, "Cannot create /proc/opensound/devfiles\n"); return; } oss_proc_devfiles->proc_fops = &oss_proc_operations; } static void uninit_proc_fs (void) { if (oss_proc_root) { if (oss_proc_devfiles) remove_proc_entry ("devfiles", oss_proc_root); remove_proc_entry ("opensound", NULL); } } static int osscore_init (void) { if ((core_osdev = osdev_create (NULL, DRV_UNKNOWN, 0, "osscore", NULL)) == NULL) { oss_cmn_err (CE_WARN, "Failed to allocate OSDEV structure\n"); return -ENOMEM; } osdev_set_owner (core_osdev, THIS_MODULE); init_proc_fs (); return oss_init_osscore (core_osdev); } static void osscore_exit (void) { uninit_proc_fs (); oss_uninit_osscore (core_osdev); } void oss_udelay (unsigned long d) { udelay (d); } oss_mutex_t oss_mutex_init (void) { oss_mutex_t mutex; if ((mutex = vmalloc (sizeof (*mutex))) == NULL) { oss_cmn_err (CE_WARN, "vmalloc(%d) failed (mutex)\n", sizeof (*mutex)); return NULL; } spin_lock_init (&(mutex->lock)); return mutex; } void oss_mutex_cleanup (oss_mutex_t mutex) { vfree (mutex); } void oss_spin_lock_irqsave (oss_mutex_t mutex, oss_native_word * flags) { unsigned long flag; if (mutex == NULL) return; spin_lock_irqsave (&mutex->lock, flag); *flags = flag; } void oss_spin_unlock_irqrestore (oss_mutex_t mutex, oss_native_word flags) { if (mutex == NULL) return; spin_unlock_irqrestore (&mutex->lock, flags); } void oss_spin_lock (oss_mutex_t mutex) { if (mutex == NULL) return; spin_lock (&mutex->lock); } void oss_spin_unlock (oss_mutex_t mutex) { if (mutex == NULL) return; spin_unlock (&mutex->lock); } void * oss_map_pci_mem (oss_device_t * osdev, int size, unsigned long offset) { #ifdef __arm__ return (void*)offset; #else return ioremap (offset, size); #endif } void oss_unmap_pci_mem (void *addr) { #ifndef __arm__ iounmap (addr); #endif } unsigned long long oss_get_jiffies (void) { return jiffies_64; } char * oss_get_procname (void) { return current->comm; } int oss_get_pid (void) { return current->pid; } int oss_get_uid (void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) return current->cred->uid; #else return current->uid; #endif } typedef struct tmout_desc { volatile int active; int timestamp; void (*func) (void *); void *arg; struct timer_list timer; } tmout_desc_t; static volatile int next_id = 0; #define MAX_TMOUTS 128 tmout_desc_t tmouts[MAX_TMOUTS] = { {0} }; int timeout_random = 0x12123400; void oss_timer_callback (unsigned long id) { tmout_desc_t *tmout; int ix; void *arg; timeout_random++; ix = id & 0xff; if (ix < 0 || ix >= MAX_TMOUTS) return; tmout = &tmouts[ix]; if (tmout->timestamp != id) /* Expired timer */ return; if (!tmout->active) return; arg = tmout->arg; tmout->active = 0; tmout->timestamp = 0; tmout->func (arg); } timeout_id_t oss_timeout (void (*func) (void *), void *arg, unsigned long long ticks) { tmout_desc_t *tmout = NULL; int id, n; timeout_random++; n = 0; id = -1; while (id == -1 && n < MAX_TMOUTS) { if (!tmouts[next_id].active) { tmouts[next_id].active = 1; id = next_id++; tmout = &tmouts[id]; break; } next_id = (next_id + 1) % MAX_TMOUTS; } if (id == -1) /* No timer slots available */ { oss_cmn_err (CE_WARN, "Timeout table full\n"); return 0; } tmout->func = func; tmout->arg = arg; tmout->timestamp = id | (timeout_random & ~0xff); init_timer (&tmout->timer); tmout->timer.expires = jiffies + ticks; tmout->timer.data = id | (timeout_random & ~0xff); tmout->timer.function = oss_timer_callback; add_timer (&tmout->timer); return id | (timeout_random & ~0xff); } void oss_untimeout (timeout_id_t id) { tmout_desc_t *tmout; int ix; ix = id & 0xff; if (ix < 0 || ix >= MAX_TMOUTS) return; timeout_random++; tmout = &tmouts[ix]; if (tmout->timestamp != id) /* Expired timer */ return; if (tmout->active) del_timer (&tmout->timer); tmout->active = 0; tmout->timestamp = 0; } int oss_uiomove (void *addr, size_t nbytes, enum uio_rw rwflag, uio_t * uio) {
NOTE! Returns 0 upon success and EFAULT on failure (instead of -EFAULT (for Solaris/BSD compatibilityi)).
int c; char *address = addr; if (rwflag != uio->rw) { oss_cmn_err (CE_WARN, "uiomove: Bad direction\n"); return EFAULT; } if (uio->resid < nbytes) { oss_cmn_err (CE_WARN, "uiomove: Bad count %d (%d)\n", nbytes, uio->resid); return EFAULT; } if (uio->kernel_space) return EFAULT; switch (rwflag) { case UIO_READ: c = nbytes; if (c > 10) c = 0; if ((c = copy_to_user (uio->ptr, address, nbytes) != 0)) { uio->resid -= nbytes; oss_cmn_err (CE_CONT, "copy_to_user(%d) failed (%d)\n", nbytes, c); return EFAULT; } break; case UIO_WRITE: if (copy_from_user (address, uio->ptr, nbytes) != 0) { oss_cmn_err (CE_CONT, "copy_from_user failed\n"); uio->resid -= nbytes; return EFAULT; } break; } uio->resid -= nbytes; uio->ptr += nbytes; return 0; } int oss_create_uio (uio_t * uio, char *buf, size_t count, uio_rw_t rw, int is_kernel) { memset (uio, 0, sizeof (*uio)); if (is_kernel) { oss_cmn_err (CE_CONT, "oss_create_uio: Kernel space buffers not supported\n"); return -EIO; } uio->ptr = buf; uio->resid = count; uio->kernel_space = is_kernel; uio->rw = rw; return 0; } void oss_cmn_err (int level, const char *s, ...) { char tmp[1024], *a[6]; va_list ap; int i, n = 0; va_start (ap, s); for (i = 0; i < strlen (s); i++) if (s[i] == '%') n++; for (i = 0; i < n && i < 6; i++) a[i] = va_arg (ap, char *); for (i = n; i < 6; i++) a[i] = NULL; if (level == CE_CONT) { sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL, NULL, NULL, NULL); printk ("%s", tmp); } else { strcpy (tmp, "osscore: "); sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5], NULL, NULL, NULL, NULL); if (level == CE_PANIC) panic (tmp); printk (KERN_ALERT "%s", tmp); } #if 0 /* This may cause a crash under SMP */ if (sound_started) store_msg (tmp); #endif va_end (ap); }
Sleep/wakeup
struct oss_wait_queue { volatile int flags; wait_queue_head_t wq; }; struct oss_wait_queue * oss_create_wait_queue (oss_device_t * osdev, const char *name) { struct oss_wait_queue *wq; if ((wq = vmalloc (sizeof (*wq))) == NULL) { oss_cmn_err (CE_WARN, "vmalloc(%d) failed (wq)\n", sizeof (*wq)); return NULL; } init_waitqueue_head (&wq->wq); return wq; } void oss_reset_wait_queue (struct oss_wait_queue *wq) { wq->flags = 0; } void oss_remove_wait_queue (struct oss_wait_queue *wq) { vfree (wq); } int oss_sleep (struct oss_wait_queue *wq, oss_mutex_t * mutex, int ticks, oss_native_word * flags, unsigned int *status) { int result = 0; *status = 0; if (wq == NULL) return 0; wq->flags = 0; oss_spin_unlock_irqrestore (*mutex, *flags); if (ticks <= 0) result = wait_event_interruptible (wq->wq, (wq->flags & WK_WAKEUP)); else result = wait_event_interruptible_timeout (wq->wq, (wq->flags & WK_WAKEUP), ticks); oss_spin_lock_irqsave (*mutex, flags); if (result < 0) /* Signal received */ { *status |= WK_SIGNAL; return 1; } if (!(wq->flags & WK_WAKEUP)) /* Timeout */ { return 0; } return 1; } int oss_register_poll (struct oss_wait_queue *wq, oss_mutex_t * mutex, oss_native_word * flags, oss_poll_event_t * ev) { oss_spin_unlock_irqrestore (*mutex, *flags); poll_wait ((struct file *) ev->file, &wq->wq, (struct poll_table_struct *) ev->wait); oss_spin_lock_irqsave (*mutex, flags); return 0; } void oss_wakeup (struct oss_wait_queue *wq, oss_mutex_t * mutex, oss_native_word * flags, short events) { if (wq == NULL) return; wq->flags |= WK_WAKEUP; oss_spin_unlock_irqrestore (*mutex, *flags); wake_up (&wq->wq); oss_spin_lock_irqsave (*mutex, flags); } void oss_reserve_pages (oss_native_word start_addr, oss_native_word end_addr) { struct page *page, *lastpage; lastpage = virt_to_page (end_addr); for (page = virt_to_page (start_addr); page <= lastpage; page++) set_bit (PG_reserved, &page->flags); } void oss_unreserve_pages (oss_native_word start_addr, oss_native_word end_addr) { struct page *page, *lastpage; lastpage = virt_to_page (end_addr); for (page = virt_to_page (start_addr); page <= lastpage; page++) clear_bit (PG_reserved, &page->flags); } void * oss_contig_malloc (oss_device_t * osdev, int buffsize, oss_uint64_t memlimit, oss_native_word * phaddr) { char *start_addr, *end_addr; int sz, size; int flags = 0; *phaddr = 0; #ifdef GFP_DMA32 if (memlimit < 0x0000000100000000LL) flags |= GFP_DMA32; #endif if (memlimit < 0x00000000ffffffffLL) flags |= GFP_DMA; start_addr = NULL; for (sz = 0, size = PAGE_SIZE; size < buffsize; sz++, size <<= 1); if (buffsize != (PAGE_SIZE * (1 << sz))) { #if 0 printk ("Contig_malloc: Invalid size %d != %ld\n", buffsize, PAGE_SIZE * (1 << sz)); #endif } start_addr = (char *) __get_free_pages (GFP_KERNEL | flags, sz); if (start_addr == NULL) { cmn_err (CE_NOTE, "Failed to allocate memory buffer of %d bytes\n", buffsize); return NULL; } else { /* make some checks */ end_addr = start_addr + buffsize - 1; oss_reserve_pages ((oss_native_word) start_addr, (oss_native_word) end_addr); } *phaddr = virt_to_bus (start_addr); return start_addr; } void oss_contig_free (oss_device_t * osdev, void *p, int buffsize) { int sz, size; caddr_t start_addr, end_addr; if (p == NULL) return; for (sz = 0, size = PAGE_SIZE; size < buffsize; sz++, size <<= 1); start_addr = p; end_addr = p + buffsize - 1; oss_unreserve_pages ((oss_native_word) start_addr, (oss_native_word) end_addr); free_pages ((unsigned long) p, sz); }
These typedefs must match definition of struct file_operations. (See notes in routine oss_register_chrdev).
typedef ssize_t (*read_t) (struct file *, char *, size_t, loff_t *); typedef ssize_t (*write_t) (struct file *, const char *, size_t, loff_t *); typedef unsigned int (*poll_t) (struct file *, poll_table *); typedef poll_table select_table; typedef int (*readdir_t) (struct inode *, struct file *, void *, filldir_t); typedef int (*ioctl_t) (struct inode *, struct file *, unsigned int, unsigned long); typedef long (*new_ioctl_t) (struct file *, unsigned int, unsigned long); typedef int (*mmap_t) (struct file *, struct vm_area_struct *); typedef int (*open_t) (struct inode *, struct file *); typedef int (*release_t) (struct inode *, struct file *); typedef int (*fasync_t) (int, struct file *, int); typedef int (*fsync_t) (struct inode *, struct file *); static loff_t oss_no_llseek (struct file *file, loff_t offset, int orig) { return -EINVAL; } static int oss_no_fsync (struct file *f, struct dentry *d, int datasync) { return -EINVAL; } static int oss_no_fasync (int x, struct file *f, int m) { return -EINVAL; }
Wrappers for installing and uninstalling character and block devices.
The oss_file_operation_handle structure differs from kernel's file_operations structure in parameters of the driver entry points. Kernel inode, file, wait_struct, vm_are_struct etc. typed arguments are replaced by wrapper handles.
static struct file_operations * alloc_fop (oss_device_t * osdev, struct oss_file_operation_handle *op) {
This routine performs initialization of kernel file_operations structure from oss_file_operation_handle structure. Each procedure pointer is copied to a temporary variable before doing the actual assignment. This prevents unnecessary warnings while it still enables compatibility warnings.
Any warning given by this routine may indicate that kernel fs call interface has changed significantly (added parameters to the routines). In this case definition routine in oss_file_operation_handle must be updated and WRAPPER_VERSION must be incremented.
struct file_operations *fop; poll_t tmp_poll = (poll_t) op->poll; read_t tmp_read = (read_t) op->read; write_t tmp_write = (write_t) op->write; /* readdir_t tmp_readdir = (readdir_t)op->readdir; */ ioctl_t tmp_ioctl = (ioctl_t) op->ioctl; mmap_t tmp_mmap = (mmap_t) op->mmap; open_t tmp_open = (open_t) op->open; release_t tmp_release = (release_t) op->release; new_ioctl_t tmp_unlocked_ioctl = (new_ioctl_t) op->unlocked_ioctl; new_ioctl_t tmp_compat_ioctl = (new_ioctl_t) op->compat_ioctl; fop = (struct file_operations *) oss_kmem_alloc (sizeof (struct file_operations)); memset ((char *) fop, 0, sizeof (struct file_operations));
Now the assignment
fop->llseek = oss_no_llseek; fop->read = tmp_read; fop->write = tmp_write; fop->readdir = NULL; /* tmp_readdir; */ fop->poll = tmp_poll; fop->ioctl = tmp_ioctl; fop->mmap = tmp_mmap; fop->open = tmp_open; fop->release = tmp_release; fop->fsync = oss_no_fsync; fop->fasync = oss_no_fasync; fop->lock = NULL; fop->flush = NULL; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) fop->owner = osdev_get_owner (osdev); #endif #ifdef HAVE_UNLOCKED_IOCTL fop->unlocked_ioctl = tmp_unlocked_ioctl; #endif #ifdef HAVE_COMPAT_IOCTL fop->compat_ioctl = tmp_compat_ioctl; #endif return fop; } int oss_register_chrdev (oss_device_t * osdev, unsigned int major, const char *name, struct oss_file_operation_handle *op) { int maj; maj = register_chrdev (major, name, alloc_fop (osdev, op)); return maj; } void oss_register_minor (int major, int minor, char *name) { if (nminors >= MAX_MINOR) { oss_cmn_err (CE_WARN, "Too many device files\n"); return; } minors[nminors].major = major; minors[nminors].minor = minor; strcpy (minors[nminors].name, name); nminors++; } int oss_unregister_chrdev (unsigned int major, const char *name) { unregister_chrdev (major, name); return 0; } int oss_inode_get_minor (oss_inode_handle_t * inode) { return MINOR (((struct inode *) inode)->i_rdev); } int oss_file_get_flags (oss_file_handle_t * file) { return ((struct file *) file)->f_flags; } void * oss_file_get_private (oss_file_handle_t * file) { return ((struct file *) file)->private_data; } void oss_file_set_private (oss_file_handle_t * file, void *v) { ((struct file *) file)->private_data = v; } int oss_vma_get_flags (oss_vm_area_handle_t * vma) { return ((struct vm_area_struct *) vma)->vm_flags; } int oss_do_mmap (oss_vm_area_handle_t * v, oss_native_word dmabuf_phys, int bytes_in_use) { struct vm_area_struct *vma = (struct vm_area_struct *) v; int res, size; if (vma->vm_pgoff != 0) { oss_cmn_err (CE_WARN, "mmap() offset must be 0.\n"); return -EINVAL; } size = vma->vm_end - vma->vm_start; if (size != bytes_in_use) { oss_cmn_err (CE_WARN, "mmap() size = %ld. Should be %d\n", size, bytes_in_use); return -EBUSY; } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) res = io_remap_page_range (vma, vma->vm_start, dmabuf_phys, size, vma->vm_page_prot); #else res = io_remap_pfn_range (vma, vma->vm_start, dmabuf_phys >> PAGE_SHIFT, size, vma->vm_page_prot); #endif if (res) { oss_cmn_err (CE_WARN, "io_remap_pfn_range returned %d\n", res); return -EAGAIN; } return 0; }
some of which are compiled with GCC, to produce an executable, this library does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License.
typedef unsigned int UQItype __attribute__ ((mode (QI))); typedef int SItype __attribute__ ((mode (SI))); typedef unsigned int USItype __attribute__ ((mode (SI))); typedef int DItype __attribute__ ((mode (DI))); typedef unsigned int UDItype __attribute__ ((mode (DI))); typedef int word_type __attribute__ ((mode (__word__)));
little/big ENDIAN.
#if defined(__i386__) || defined(__x86_64__) struct DIstruct { SItype low, high; }; #endif #ifndef __arm__
any arithmetic yet. Incoming DImode parameters are stored into the `ll' field, and the unpacked result is read from the struct `s'.
typedef union { struct DIstruct s; DItype ll; } DIunion; /* From gcc/longlong.h */ #ifndef SI_TYPE_SIZE #define SI_TYPE_SIZE 32 #endif #define __BITS4 (SI_TYPE_SIZE / 4) #define __ll_B (1L << (SI_TYPE_SIZE / 2)) #define __ll_lowpart(t) ((USItype) (t) % __ll_B) #define __ll_highpart(t) ((USItype) (t) / __ll_B) #if defined(__i386__) || defined(__x86_64__) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%1\n" \ "sbbl %3,%0" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "0" ((USItype) (ah)), \ "g" ((USItype) (bh)), \ "1" ((USItype) (al)), \ "g" ((USItype) (bl))) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mull %3" \ : "=a" ((USItype) (w0)), \ "=d" ((USItype) (w1)) \ : "%0" ((USItype) (u)), \ "rm" ((USItype) (v))) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divl %4" \ : "=a" ((USItype) (q)), \ "=d" ((USItype) (r)) \ : "0" ((USItype) (n0)), \ "1" ((USItype) (n1)), \ "rm" ((USItype) (d))) #define count_leading_zeros(count, x) \ do { \ USItype __cbtmp; \ __asm__ ("bsrl %1,%0" \ : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ (count) = __cbtmp ^ 31; \ } while (0) #endif /* __i386__ */ /* If this machine has no inline assembler, use C macros. */ /* Define this unconditionally, so it can be used for debugging. */ #define __udiv_qrnnd_c(q, r, n1, n0, d) \ do { \ USItype __d1, __d0, __q1, __q0; \ USItype __r1, __r0, __m; \ __d1 = __ll_highpart (d); \ __d0 = __ll_lowpart (d); \ \ __r1 = (n1) % __d1; \ __q1 = (n1) / __d1; \ __m = (USItype) __q1 * __d0; \ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ if (__r1 < __m) \ { \ __q1--, __r1 += (d); \ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ if (__r1 < __m) \ __q1--, __r1 += (d); \ } \ __r1 -= __m; \ \ __r0 = __r1 % __d1; \ __q0 = __r1 / __d1; \ __m = (USItype) __q0 * __d0; \ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ if (__r0 < __m) \ { \ __q0--, __r0 += (d); \ if (__r0 >= (d)) \ if (__r0 < __m) \ __q0--, __r0 += (d); \ } \ __r0 -= __m; \ \ (q) = (USItype) __q1 * __ll_B | __q0; \ (r) = __r0; \ } while (0) /* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ #if !defined (udiv_qrnnd) #define UDIV_NEEDS_NORMALIZATION 1 #define udiv_qrnnd __udiv_qrnnd_c #endif /* End of gcc/longlong.h */ static inline DItype __negdi2 (DItype u) { DIunion w; DIunion uu; uu.ll = u; w.s.low = -uu.s.low; w.s.high = -uu.s.high - ((USItype) w.s.low > 0); return w.ll; } static inline UDItype __udivmoddi4 (UDItype n, UDItype d, UDItype * rp) { DIunion ww; DIunion nn, dd; DIunion rr; USItype d0, d1, n0, n1, n2; USItype q0, q1; USItype b, bm; nn.ll = n; dd.ll = d; d0 = dd.s.low; d1 = dd.s.high; n0 = nn.s.low; n1 = nn.s.high; #ifndef UDIV_NEEDS_NORMALIZATION if (d1 == 0) { if (d0 > n1) { /* 0q = nn / 0D */ udiv_qrnnd (q0, n0, n1, n0, d0); q1 = 0; /* Remainder in n0. */ } else { /* qq = NN / 0d */ if (d0 == 0) d0 = 1 / d0; /* Divide intentionally by zero. */ udiv_qrnnd (q1, n1, 0, n1, d0); udiv_qrnnd (q0, n0, n1, n0, d0); /* Remainder in n0. */ } if (rp != 0) { rr.s.low = n0; rr.s.high = 0; *rp = rr.ll; } } #else /* UDIV_NEEDS_NORMALIZATION */ if (d1 == 0) { if (d0 > n1) { /* 0q = nn / 0D */ count_leading_zeros (bm, d0); if (bm != 0) {
denominator set.
d0 = d0 << bm; n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm)); n0 = n0 << bm; } udiv_qrnnd (q0, n0, n1, n0, d0); q1 = 0; /* Remainder in n0 >> bm. */ } else { /* qq = NN / 0d */ if (d0 == 0) d0 = 1 / d0; /* Divide intentionally by zero. */ count_leading_zeros (bm, d0); if (bm == 0) {
conclude (the most significant bit of n1 is set) /\ (the leading quotient digit q1 = 1).
This special case is necessary, not an optimization. (Shifts counts of SI_TYPE_SIZE are undefined.)
n1 -= d0; q1 = 1; } else { /* Normalize. */ b = SI_TYPE_SIZE - bm; d0 = d0 << bm; n2 = n1 >> b; n1 = (n1 << bm) | (n0 >> b); n0 = n0 << bm; udiv_qrnnd (q1, n1, n2, n1, d0); } /* n1 != d0... */ udiv_qrnnd (q0, n0, n1, n0, d0); /* Remainder in n0 >> bm. */ } if (rp != 0) { rr.s.low = n0 >> bm; rr.s.high = 0; *rp = rr.ll; } } #endif /* UDIV_NEEDS_NORMALIZATION */ else { if (d1 > n1) { /* 00 = nn / DD */ q0 = 0; q1 = 0; /* Remainder in n1n0. */ if (rp != 0) { rr.s.low = n0; rr.s.high = n1; *rp = rr.ll; } } else { /* 0q = NN / dd */ count_leading_zeros (bm, d1); if (bm == 0) {
conclude (the most significant bit of n1 is set) /\ (the quotient digit q0 = 0 or 1).
This special case is necessary, not an optimization.
n1 >= d1 (true due to program flow).
if (n1 > d1 || n0 >= d0) { q0 = 1; sub_ddmmss (n1, n0, n1, n0, d1, d0); } else q0 = 0; q1 = 0; if (rp != 0) { rr.s.low = n0; rr.s.high = n1; *rp = rr.ll; } } else { USItype m1, m0; /* Normalize. */ b = SI_TYPE_SIZE - bm; d1 = (d1 << bm) | (d0 >> b); d0 = d0 << bm; n2 = n1 >> b; n1 = (n1 << bm) | (n0 >> b); n0 = n0 << bm; udiv_qrnnd (q0, n1, n2, n1, d1); umul_ppmm (m1, m0, q0, d0); if (m1 > n1 || (m1 == n1 && m0 > n0)) { q0--; sub_ddmmss (m1, m0, m1, m0, d1, d0); } q1 = 0; /* Remainder in (n1n0 - m1m0) >> bm. */ if (rp != 0) { sub_ddmmss (n1, n0, n1, n0, m1, m0); rr.s.low = (n1 << b) | (n0 >> bm); rr.s.high = n1 >> bm; *rp = rr.ll; } } } } ww.s.low = q0; ww.s.high = q1; return ww.ll; } DItype __divdi3 (DItype u, DItype v) { word_type c = 0; DIunion uu, vv; DItype w; uu.ll = u; vv.ll = v; if (uu.s.high < 0) c = ~c, uu.ll = __negdi2 (uu.ll); if (vv.s.high < 0) c = ~c, vv.ll = __negdi2 (vv.ll); w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0); if (c) w = __negdi2 (w); return w; } DItype __moddi3 (DItype u, DItype v) { word_type c = 0; DIunion uu, vv; DItype w; uu.ll = u; vv.ll = v; if (uu.s.high < 0) c = ~c, uu.ll = __negdi2 (uu.ll); if (vv.s.high < 0) vv.ll = __negdi2 (vv.ll); (void) __udivmoddi4 (uu.ll, vv.ll, (UDItype *) & w); if (c) w = __negdi2 (w); return w; } UDItype __umoddi3 (UDItype u, UDItype v) { UDItype w; (void) __udivmoddi4 (u, v, (UDItype *) & w); return w; } UDItype __udivdi3 (UDItype n, UDItype d) { return __udivmoddi4 (n, d, (UDItype *) 0); } #endif #ifdef __arm__ void raise(void) { oss_cmn_err (CE_PANIC, "raise() got called\n"); } #endif dev_info_t * oss_create_pcidip (struct pci_dev * pcidev) { dev_info_t *dip; if ((dip = oss_pmalloc (sizeof (*dip))) == NULL) return NULL; memset (dip, 0, sizeof (*dip)); dip->pcidev = pcidev; return dip; } int osscore_pci_read_config_byte (dev_info_t * dip, unsigned int where, unsigned char *val) { return pci_read_config_byte (dip->pcidev, where, val); } int osscore_pci_read_config_irq (dev_info_t * dip, unsigned int where, unsigned char *val) { *val = dip->pcidev->irq; return 0; // PCIBIOS_SUCCESSFUL } int osscore_pci_read_config_word (dev_info_t * dip, unsigned int where, unsigned short *val) { if (dip == NULL) { oss_cmn_err (CE_CONT, "osscore_pci_read_config_word: dip==NULL\n"); return -1; } return pci_read_config_word (dip->pcidev, where, val); } int osscore_pci_read_config_dword (dev_info_t * dip, unsigned int where, unsigned int *val) { return pci_read_config_dword (dip->pcidev, where, val); } int osscore_pci_write_config_byte (dev_info_t * dip, unsigned int where, unsigned char val) { return pci_write_config_byte (dip->pcidev, where, val); } int osscore_pci_write_config_word (dev_info_t * dip, unsigned int where, unsigned short val) { return pci_write_config_word (dip->pcidev, where, val); } int osscore_pci_write_config_dword (dev_info_t * dip, unsigned int where, unsigned int val) { return pci_write_config_dword (dip->pcidev, where, val); } int osscore_pci_enable_msi (dev_info_t * dip) { pci_enable_msi (dip->pcidev); return (dip->pcidev->irq); } /* These definitions must match with oss_config.h */ typedef int (*oss_tophalf_handler_t) (struct _oss_device_t * osdev); typedef void (*oss_bottomhalf_handler_t) (struct _oss_device_t * osdev); typedef struct { int irq; oss_device_t *osdev; oss_tophalf_handler_t top; oss_bottomhalf_handler_t bottom; } osscore_intr_t; #define MAX_INTRS 32 static osscore_intr_t intrs[MAX_INTRS] = { {0} }; static int nintrs = 0; static irqreturn_t osscore_intr (int irq, void *arg) { int serviced; osscore_intr_t *intr = arg; if (intr->osdev == NULL || intr->top == NULL) /* Removed interrupt */ return 0; serviced = intr->top (intr->osdev); oss_inc_intrcount (intr->osdev, serviced); if (serviced) { if (intr->bottom != NULL) intr->bottom (intr->osdev); return IRQ_HANDLED; } return IRQ_NONE; } extern int oss_pci_read_config_irq (oss_device_t * osdev, unsigned long where, unsigned char *val); char * oss_pci_read_devpath (dev_info_t * dip) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) return dev_name(&dip->pcidev->dev); #else return dip->pcidev->dev.bus_id; #endif } int oss_register_interrupts (oss_device_t * osdev, int irqnum, oss_tophalf_handler_t top, oss_bottomhalf_handler_t bottom) { unsigned char pci_irq_line; osscore_intr_t *intr; char *name; int err; if (nintrs >= MAX_INTRS) { oss_cmn_err (CE_CONT, "oss_register_interrupts: Too many interrupt handlers\n"); return -ENOMEM; } intr = &intrs[nintrs]; if (oss_pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line) > 0) return -EIO; intr->irq = pci_irq_line; intr->osdev = osdev; intr->top = top; intr->bottom = bottom; name = osdev_get_nick (osdev); #ifndef IRQF_SHARED #define IRQF_SHARED SA_SHIRQ #endif if ((err = request_irq (pci_irq_line, osscore_intr, IRQF_SHARED, name, intr)) < 0) { oss_cmn_err (CE_CONT, "request_irq(%d) failed, err=%d\n", pci_irq_line, err); return err; } nintrs++; return 0; } void oss_unregister_interrupts (oss_device_t * osdev) { int i; for (i = 0; i < nintrs; i++) if (intrs[i].osdev == osdev) { free_irq (intrs[i].irq, &intrs[i]); intrs[i].osdev = NULL; intrs[i].top = NULL; intrs[i].bottom = NULL; } } int oss_copy_to_user (void *to, const void *from, unsigned long n) { return copy_to_user (to, from, n); } int oss_copy_from_user (void *to, const void *from, unsigned long n) { return copy_from_user (to, from, n); } static int refcount = 0; typedef struct { struct module *module; int active; } oss_module_t; #define OSS_MAX_MODULES 50 static oss_module_t oss_modules[OSS_MAX_MODULES]; static int num_oss_modules = 0; void oss_inc_refcounts (void) { int i; refcount++; for (i = 0; i < num_oss_modules; i++) if (oss_modules[i].active) { if (!try_module_get (oss_modules[i].module)) oss_cmn_err (CE_WARN, "try_module_get() failed\n"); } } void oss_dec_refcounts (void) { int i; refcount--; for (i = 0; i < num_oss_modules; i++) if (oss_modules[i].active) { module_put (oss_modules[i].module); } } void oss_register_module (struct module *mod) { int i, n = -1; for (i = 0; i < num_oss_modules; i++) if (!oss_modules[i].active) { n = i; break; } if (n == -1) { if (num_oss_modules >= OSS_MAX_MODULES) { printk (KERN_ALERT "Too many OSS modules\n"); return; } n = num_oss_modules++; } oss_modules[n].module = mod; oss_modules[n].active = 1; } void oss_unregister_module (struct module *mod) { int i; for (i = 0; i < num_oss_modules; i++) if (oss_modules[i].active && oss_modules[i].module == mod) { oss_modules[i].active = 0; oss_modules[i].module = NULL; return; } } module_init (osscore_init); module_exit (osscore_exit); #ifdef CONFIG_OSS_VMIX_FLOAT #define FP_SAVE(envbuf) asm ("fnsave %0":"=m" (*envbuf)); #define FP_RESTORE(envbuf) asm ("frstor %0":"=m" (*envbuf)); /* SSE/SSE2 compatible macros */ #define FX_SAVE(envbuf) asm ("fxsave %0":"=m" (*envbuf)); #define FX_RESTORE(envbuf) asm ("fxrstor %0":"=m" (*envbuf)); static int old_arch = 0; /* No SSE/SSE2 instructions */ #if 0 static inline unsigned long read_cr0 (void) { unsigned long cr0; asm volatile ("movq %%cr0,%0":"=r" (cr0)); return cr0; } static inline void write_cr0 (unsigned long val) { asm volatile ("movq %0,%%cr0"::"r" (val)); } static inline unsigned long read_cr4 (void) { unsigned long cr4; asm volatile ("movq %%cr4,%0":"=r" (cr4)); return cr4; } static inline void write_cr4 (unsigned long val) { asm volatile ("movq %0,%%cr4"::"r" (val)); } #endif static inline unsigned long long read_mxcsr (void) { unsigned long long mxcsr; asm volatile ("stmxcsr %0":"=m" (mxcsr)); return mxcsr; } static inline void write_mxcsr (unsigned long long val) { asm volatile ("ldmxcsr %0"::"m" (val)); } int oss_fp_check (void) { int eax, ebx, ecx, edx; #define FLAGS_ID (1<<21) oss_native_word flags_reg; local_save_flags (flags_reg); flags_reg &= ~FLAGS_ID; local_irq_restore (flags_reg); local_save_flags (flags_reg); if (flags_reg & FLAGS_ID) return 0; flags_reg |= FLAGS_ID; local_irq_restore (flags_reg); local_save_flags (flags_reg); if (!(flags_reg & FLAGS_ID)) return 0; #define CPUID_FXSR (1<<24) #define CPUID_SSE (1<<25) #define CPUID_SSE2 (1<<26) cpuid (1, &eax, &ebx, &ecx, &edx); if (!(edx & CPUID_FXSR)) return -1;
Older machines require different FP handling than the latest ones. Use the SSE instruction set as an indicator.
if (!(edx & CPUID_SSE)) old_arch = 1; return 1; } void oss_fp_save (short *envbuf, unsigned int flags[]) { flags[0] = read_cr0 (); write_cr0 (flags[0] & ~0x0e); /* Clear CR0.TS/MP/EM */ if (old_arch) { FP_SAVE (envbuf); } else { flags[1] = read_cr4 (); write_cr4 (flags[1] | 0x600); /* Set OSFXSR & OSXMMEXCEPT */ FX_SAVE (envbuf); asm ("fninit"); asm ("fwait"); write_mxcsr (0x1f80); } flags[2] = read_cr0 (); } void oss_fp_restore (short *envbuf, unsigned int flags[]) { asm ("fwait"); if (old_arch) { FP_RESTORE (envbuf); } else { FX_RESTORE (envbuf); write_cr4 (flags[1]); /* Restore cr4 */ } write_cr0 (flags[0]); /* Restore cr0 */ } #endif #if 0 void __stack_chk_fail (void) { panic ("__stack_chk_fail\n"); } #endif
Exported symbols
#define EXPORT_FUNC(name) extern void name(void);EXPORT_SYMBOL(name); #define EXPORT_DATA(name) extern int name;EXPORT_SYMBOL(name); /* EXPORT_SYMBOL (__stack_chk_fail); */ #ifdef CONFIG_OSS_VMIX_FLOAT EXPORT_SYMBOL (oss_fp_check); EXPORT_SYMBOL (oss_fp_save); EXPORT_SYMBOL (oss_fp_restore); #endif EXPORT_SYMBOL (oss_register_chrdev); EXPORT_SYMBOL (oss_unregister_chrdev); EXPORT_SYMBOL (oss_reserve_pages); EXPORT_SYMBOL (oss_unreserve_pages); EXPORT_FUNC (ac97_install); EXPORT_FUNC (ac97_install_full); EXPORT_FUNC (ac97_playrate); EXPORT_FUNC (ac97_recrate); EXPORT_FUNC (ac97_varrate); EXPORT_FUNC (ac97_override_control); EXPORT_FUNC (ac97_init_ext); EXPORT_FUNC (ac97_mixer_set); EXPORT_FUNC (ac97_spdif_setup); EXPORT_FUNC (ac97_spdifout_ctl); EXPORT_FUNC (ac97_remove_control); EXPORT_SYMBOL (ac97_amplifier); EXPORT_FUNC (ac97_disable_spdif); EXPORT_FUNC (ac97_enable_spdif); EXPORT_FUNC (ac97_mixext_ctl); EXPORT_FUNC (ac97_spdifin_ctl); EXPORT_FUNC (oss_pci_byteswap); EXPORT_SYMBOL (mixer_ext_truncate); EXPORT_SYMBOL (mixer_ext_rebuild_all); EXPORT_FUNC (remux_install); EXPORT_SYMBOL (oss_strlen); EXPORT_SYMBOL (oss_strcmp); EXPORT_FUNC (oss_install_mididev); EXPORT_DATA (detect_trace); EXPORT_SYMBOL (dmap_get_qhead); EXPORT_SYMBOL (dmap_get_qtail); EXPORT_FUNC (oss_alloc_dmabuf); EXPORT_SYMBOL (oss_contig_free); EXPORT_SYMBOL (oss_contig_malloc); EXPORT_FUNC (oss_disable_device); EXPORT_FUNC (oss_free_dmabuf); EXPORT_SYMBOL (oss_map_pci_mem); EXPORT_SYMBOL (oss_install_audiodev); EXPORT_SYMBOL (oss_install_audiodev_with_devname); EXPORT_FUNC (oss_audio_set_error); EXPORT_SYMBOL (load_mixer_volumes); EXPORT_SYMBOL (oss_unmap_pci_mem); EXPORT_SYMBOL (oss_memset); EXPORT_SYMBOL (oss_mutex_cleanup); EXPORT_SYMBOL (oss_mutex_init); EXPORT_SYMBOL (oss_register_device); EXPORT_SYMBOL (oss_register_interrupts); EXPORT_SYMBOL (oss_inc_intrcount); EXPORT_SYMBOL (oss_spin_lock); EXPORT_SYMBOL (oss_spin_lock_irqsave); EXPORT_SYMBOL (oss_spin_unlock); EXPORT_SYMBOL (oss_spin_unlock_irqrestore); EXPORT_SYMBOL (oss_udelay); EXPORT_FUNC (oss_unregister_device); EXPORT_SYMBOL (oss_unregister_interrupts); EXPORT_SYMBOL (oss_virt_to_bus); EXPORT_FUNC (oss_pci_read_config_byte); EXPORT_FUNC (oss_pci_read_config_word); EXPORT_FUNC (oss_pci_read_config_dword); EXPORT_FUNC (oss_pci_write_config_byte); EXPORT_FUNC (oss_pci_write_config_word); EXPORT_FUNC (oss_pci_write_config_dword); EXPORT_FUNC (oss_pci_enable_msi); EXPORT_SYMBOL (oss_pci_read_config_irq); EXPORT_SYMBOL (oss_pci_read_devpath); EXPORT_SYMBOL (oss_get_jiffies); EXPORT_SYMBOL (mixer_find_ext); EXPORT_SYMBOL (oss_install_mixer); EXPORT_SYMBOL (oss_strcpy); EXPORT_SYMBOL (oss_kmem_free); #ifndef __arm__ EXPORT_FUNC (uart401_init); EXPORT_FUNC (uart401_disable); EXPORT_FUNC (uart401_irq); #endif EXPORT_SYMBOL (mixer_ext_set_init_fn); EXPORT_SYMBOL (mixer_ext_set_vmix_init_fn); #ifdef CONFIG_OSS_VMIX EXPORT_FUNC (vmix_attach_audiodev); EXPORT_FUNC (vmix_detach_audiodev); EXPORT_FUNC (vmix_change_devnames); #endif EXPORT_SYMBOL (mixer_ext_set_strings); EXPORT_SYMBOL (mixer_ext_create_group); EXPORT_SYMBOL (mixer_ext_create_group_flags); EXPORT_SYMBOL (mixer_ext_create_control); EXPORT_SYMBOL (oss_strncpy); EXPORT_SYMBOL (oss_memcpy); EXPORT_SYMBOL (oss_kmem_alloc); EXPORT_DATA (oss_hz); EXPORT_FUNC (oss_spdif_open); EXPORT_FUNC (oss_spdif_ioctl); EXPORT_FUNC (oss_spdif_install); EXPORT_FUNC (oss_spdif_uninstall); EXPORT_FUNC (oss_spdif_close); EXPORT_FUNC (oss_spdif_mix_init); EXPORT_FUNC (oss_spdif_setrate); EXPORT_FUNC (create_new_card); EXPORT_FUNC (oss_audio_ioctl); EXPORT_FUNC (oss_audio_open_engine); EXPORT_FUNC (oss_audio_release); EXPORT_FUNC (oss_audio_set_rate); EXPORT_SYMBOL (oss_uiomove); EXPORT_SYMBOL (oss_get_pid); EXPORT_SYMBOL (oss_get_uid); EXPORT_SYMBOL (oss_get_procname); EXPORT_SYMBOL (mix_cvt); EXPORT_FUNC (oss_audio_set_format); EXPORT_FUNC (oss_audio_set_channels); EXPORT_FUNC (midiparser_create); EXPORT_FUNC (midiparser_input); EXPORT_FUNC (midiparser_unalloc); EXPORT_FUNC (mixer_ext_create_device); EXPORT_SYMBOL (mixer_ext_recrw); EXPORT_SYMBOL (mixer_ext_rw); EXPORT_SYMBOL (mixer_ext_set_enum); EXPORT_SYMBOL (mixer_ext_set_description); EXPORT_SYMBOL (osdev_create); EXPORT_FUNC (osdev_clone); EXPORT_SYMBOL (osdev_delete); EXPORT_FUNC (oss_audio_chpoll); EXPORT_FUNC (oss_audio_delayed_attach); EXPORT_FUNC (oss_audio_read); EXPORT_FUNC (oss_audio_write); EXPORT_SYMBOL (oss_create_wait_queue); EXPORT_SYMBOL (oss_remove_wait_queue); EXPORT_SYMBOL (oss_reset_wait_queue); EXPORT_SYMBOL (oss_sleep); EXPORT_SYMBOL (oss_strncmp); EXPORT_SYMBOL (oss_timeout); EXPORT_SYMBOL (oss_untimeout); EXPORT_SYMBOL (oss_wakeup); #if 0 EXPORT_FUNC (ossddk_ac97_install); EXPORT_FUNC (ossddk_ac97_is_varrate); EXPORT_FUNC (ossddk_ac97_remove); EXPORT_FUNC (ossddk_ac97_set_ext_init); EXPORT_FUNC (ossddk_ac97_set_playrate); EXPORT_FUNC (ossddk_ac97_set_recrate); EXPORT_FUNC (ossddk_adev_get_devc); EXPORT_FUNC (ossddk_adev_get_dmapin); EXPORT_FUNC (ossddk_adev_get_dmapout); EXPORT_FUNC (ossddk_adev_get_flags); EXPORT_FUNC (ossddk_adev_get_label); EXPORT_FUNC (ossddk_adev_get_portc); EXPORT_FUNC (ossddk_adev_get_portc_play); EXPORT_FUNC (ossddk_adev_get_portc_record); EXPORT_FUNC (ossddk_adev_get_songname); EXPORT_FUNC (ossddk_adev_set_buflimits); EXPORT_FUNC (ossddk_adev_set_caps); EXPORT_FUNC (ossddk_adev_set_channels); EXPORT_FUNC (ossddk_adev_set_devc); EXPORT_FUNC (ossddk_adev_set_enable_flag); EXPORT_FUNC (ossddk_adev_set_flags); EXPORT_FUNC (ossddk_adev_set_formats); EXPORT_FUNC (ossddk_adev_set_label); EXPORT_FUNC (ossddk_adev_set_magic); EXPORT_FUNC (ossddk_adev_set_mixer); EXPORT_FUNC (ossddk_adev_set_portc); EXPORT_FUNC (ossddk_adev_set_portc_play); EXPORT_FUNC (ossddk_adev_set_portc_record); EXPORT_FUNC (ossddk_adev_set_portnum); EXPORT_FUNC (ossddk_adev_set_rates); EXPORT_FUNC (ossddk_adev_set_ratesource); EXPORT_FUNC (ossddk_adev_set_songname); EXPORT_FUNC (ossddk_adev_set_unloaded_flag); EXPORT_FUNC (ossddk_audio_inputintr); EXPORT_FUNC (ossddk_audio_outputintr); EXPORT_FUNC (ossddk_disable_device); EXPORT_FUNC (ossddk_dmap_get_buffsize); EXPORT_FUNC (ossddk_dmap_get_buffused); EXPORT_FUNC (ossddk_dmap_get_dmabuf); EXPORT_FUNC (ossddk_dmap_get_fragsize); EXPORT_FUNC (ossddk_dmap_get_numfrags); EXPORT_FUNC (ossddk_dmap_get_phys); EXPORT_FUNC (ossddk_dmap_get_private); EXPORT_FUNC (ossddk_dmap_get_qhead); EXPORT_FUNC (ossddk_dmap_get_qtail); EXPORT_FUNC (ossddk_dmap_set_buffsize); EXPORT_FUNC (ossddk_dmap_set_callback); EXPORT_FUNC (ossddk_dmap_set_dmabuf); EXPORT_FUNC (ossddk_dmap_set_fragsize); EXPORT_FUNC (ossddk_dmap_set_numfrags); EXPORT_FUNC (ossddk_dmap_set_phys); EXPORT_FUNC (ossddk_dmap_set_playerror); EXPORT_FUNC (ossddk_dmap_set_private); EXPORT_FUNC (ossddk_dmap_set_recerror); EXPORT_FUNC (ossddk_install_audiodev); EXPORT_FUNC (ossddk_install_mixer); EXPORT_FUNC (ossddk_mixer_create_control); EXPORT_FUNC (ossddk_mixer_create_group); EXPORT_FUNC (ossddk_mixer_get_devc); EXPORT_FUNC (ossddk_mixer_set_strings); EXPORT_FUNC (ossddk_mixer_touch); EXPORT_FUNC (ossddk_mixer_truncate); EXPORT_FUNC (ossddk_osdev_get_devc); EXPORT_FUNC (ossddk_register_device); EXPORT_FUNC (ossddk_unregister_device); #endif EXPORT_SYMBOL (osdev_set_major); EXPORT_SYMBOL (osdev_set_owner); EXPORT_SYMBOL (osdev_get_owner); EXPORT_SYMBOL (oss_create_pcidip); EXPORT_SYMBOL (touch_mixer); EXPORT_SYMBOL (oss_mixer_ext); EXPORT_SYMBOL (oss_request_major); EXPORT_SYMBOL (audio_engines); EXPORT_DATA (midi_devs); EXPORT_SYMBOL (mixer_devs); EXPORT_SYMBOL (mixer_devs_p); EXPORT_DATA (num_audio_engines); EXPORT_DATA (num_mididevs); EXPORT_SYMBOL (num_mixers); EXPORT_DATA (oss_timing_mutex); EXPORT_DATA (oss_num_cards); EXPORT_FUNC (oss_do_timing); EXPORT_FUNC (oss_do_timing2); EXPORT_FUNC (oss_timing_enter); EXPORT_FUNC (oss_timing_leave); #ifndef __arm__ EXPORT_SYMBOL (__udivdi3); EXPORT_SYMBOL (__umoddi3); EXPORT_SYMBOL (__divdi3); #else EXPORT_SYMBOL (raise); #endif EXPORT_SYMBOL (oss_copy_from_user); EXPORT_SYMBOL (oss_copy_to_user); EXPORT_SYMBOL (osdev_set_irqparms); EXPORT_SYMBOL (osdev_get_irqparms); EXPORT_SYMBOL (osdev_get_nick); EXPORT_SYMBOL (osdev_get_instance); EXPORT_SYMBOL (oss_inc_refcounts); EXPORT_SYMBOL (oss_dec_refcounts); EXPORT_SYMBOL (oss_register_module); EXPORT_SYMBOL (oss_unregister_module); EXPORT_SYMBOL (oss_audio_reset); EXPORT_SYMBOL (oss_audio_start_syncgroup); EXPORT_SYMBOL (oss_encode_enum); EXPORT_SYMBOL (dmap_get_qlen); EXPORT_SYMBOL (num_audio_devfiles); EXPORT_SYMBOL (oss_audio_inc_byte_counter); EXPORT_SYMBOL (oss_audio_register_client); EXPORT_SYMBOL (audio_devfiles); EXPORT_FUNC (oss_get_cardinfo); EXPORT_SYMBOL (oss_pmalloc); EXPORT_SYMBOL (oss_add_audio_devlist); EXPORT_FUNC (oss_memblk_malloc); EXPORT_FUNC (oss_memblk_free); EXPORT_FUNC (oss_memblk_unalloc); EXPORT_DATA (oss_global_memblk); EXPORT_FUNC (oss_get_procinfo); EXPORT_DATA (mixer_muted); #ifdef CONFIG_OSS_MIDI EXPORT_FUNC (oss_midi_ioctl); EXPORT_FUNC (oss_midi_copy_timer); #endif