summaryrefslogtreecommitdiff
path: root/kernel/OS/FreeBSD
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/OS/FreeBSD')
-rw-r--r--kernel/OS/FreeBSD/.config1
-rw-r--r--kernel/OS/FreeBSD/os_freebsd.c1107
-rw-r--r--kernel/OS/FreeBSD/os_freebsd.h263
-rw-r--r--kernel/OS/FreeBSD/wrapper/bsddefs.h150
4 files changed, 1521 insertions, 0 deletions
diff --git a/kernel/OS/FreeBSD/.config b/kernel/OS/FreeBSD/.config
new file mode 100644
index 0000000..816ac62
--- /dev/null
+++ b/kernel/OS/FreeBSD/.config
@@ -0,0 +1 @@
+mode=kernel
diff --git a/kernel/OS/FreeBSD/os_freebsd.c b/kernel/OS/FreeBSD/os_freebsd.c
new file mode 100644
index 0000000..58b11cc
--- /dev/null
+++ b/kernel/OS/FreeBSD/os_freebsd.c
@@ -0,0 +1,1107 @@
+/*
+ * Purpose: Operating system abstraction functions for FreeBSD
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include "oss_config.h"
+#include "midi_core.h"
+#include <oss_pci.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/sx.h>
+#include <sys/mman.h>
+#include <sys/lockmgr.h>
+#include <fs/devfs/devfs.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/filio.h>
+
+/* Function prototypes */
+static d_open_t oss_open;
+static d_close_t oss_close;
+static d_read_t oss_read;
+static d_write_t oss_write;
+static d_ioctl_t oss_ioctl;
+static d_poll_t oss_poll;
+static d_mmap_t oss_mmap;
+
+/* Character device entry points */
+
+static struct cdevsw oss_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = D_TRACKCLOSE,
+ .d_open = oss_open,
+ .d_close = oss_close,
+ .d_read = oss_read,
+ .d_write = oss_write,
+ .d_ioctl = oss_ioctl,
+ .d_poll = oss_poll,
+ .d_mmap = oss_mmap,
+ .d_name = "oss"
+};
+
+static int oss_major = 30;
+oss_device_t *core_osdev = NULL;
+static int open_devices = 0;
+static int refcount = 0;
+
+#define MAX_CARDS 32
+int oss_num_cards = 0;
+static oss_device_t *cards[MAX_CARDS];
+static int oss_expired = 0;
+
+
+int
+__oss_alloc_dmabuf (int dev, dmap_p dmap, unsigned int alloc_flags,
+ oss_uint64_t maxaddr, int direction)
+{
+ void *tmpbuf;
+ oss_native_word phaddr;
+ int size = 64 * 1024;
+ extern int dma_buffsize;
+
+ if (dma_buffsize > 16 && dma_buffsize <= 128)
+ size = dma_buffsize * 1024;
+
+ if (dmap->dmabuf != NULL)
+ return 0;
+
+ if (dmap == NULL)
+ {
+ cmn_err (CE_WARN, "oss_alloc_dmabuf: dmap==NULL\n");
+ return OSS_EIO;
+ }
+
+/*
+ * Some applications and virtual drivers need shorter buffer.
+ */
+ if (dmap->flags & DMAP_SMALLBUF)
+ {
+ size = SMALL_DMABUF_SIZE;
+ }
+ else if (dmap->flags & DMAP_MEDIUMBUF)
+ {
+ size = MEDIUM_DMABUF_SIZE;
+ }
+
+ if ((alloc_flags & DMABUF_SIZE_16BITS) && size > 32 * 1024)
+ size = 32 * 1024;
+
+ tmpbuf = CONTIG_MALLOC (dmap->osdev, size, maxaddr, &phaddr, NULL);
+ if (tmpbuf == NULL)
+ return OSS_ENOMEM;
+ dmap->dmabuf = tmpbuf;
+ dmap->buffsize = size;
+ dmap->dmabuf_phys = phaddr;
+
+ return 0;
+}
+
+void
+oss_free_dmabuf (int dev, dmap_p dmap)
+{
+ if (dmap->dmabuf == NULL)
+ return;
+
+ CONTIG_FREE (dmap->osdev, dmap->dmabuf, dmap->buffsize, NULL);
+ dmap->dmabuf = NULL;
+ dmap->buffsize = 0;
+ dmap->dmabuf_phys = 0;
+}
+
+oss_wait_queue_t *
+oss_create_wait_queue (oss_device_t * osdev, const char *name)
+{
+ oss_wait_queue_t *wq;
+
+ if ((wq = PMALLOC (NULL, sizeof (*wq))) == NULL)
+ return NULL;
+
+ MUTEX_INIT (osdev, wq->mutex, MH_TOP);
+
+ return wq;
+}
+
+void
+oss_reset_wait_queue (oss_wait_queue_t * wq)
+{
+ wq->flags = 0;
+}
+
+void
+oss_remove_wait_queue (oss_wait_queue_t * wq)
+{
+ MUTEX_CLEANUP (wq->mutex);
+}
+
+int
+oss_sleep (oss_wait_queue_t * wq, oss_mutex_t * mutex, int ticks,
+ oss_native_word * flags, unsigned int *status)
+{
+ int flag;
+ *status = 0;
+
+ if (wq == NULL)
+ return 0;
+
+ wq->flags = 0;
+#ifdef USE_SX_LOCK
+ flag = sx_sleep (wq, *mutex, PRIBIO | PCATCH, "oss", ticks);
+#else
+#if __FreeBSD_version >= 602000
+ flag = msleep_spin (wq, *mutex, "oss", ticks);
+#else
+ flag = msleep (wq, *mutex, PRIBIO | PCATCH, "oss", ticks);
+#endif
+#endif
+ if (flag == EWOULDBLOCK) /* Timeout */
+ {
+ return 0;
+ }
+
+ if (flag != 0)
+ {
+ *status |= WK_SIGNAL;
+ }
+
+ return 1;
+}
+
+int
+oss_register_poll (oss_wait_queue_t * wq, oss_mutex_t * mutex,
+ oss_native_word * flags, oss_poll_event_t * ev)
+{
+ MUTEX_EXIT_IRQRESTORE (*mutex, *flags);
+ selrecord (ev->p, &wq->poll_info);
+ MUTEX_ENTER_IRQDISABLE (*mutex, *flags);
+ return 0;
+}
+
+void
+oss_wakeup (oss_wait_queue_t * wq, oss_mutex_t * mutex,
+ oss_native_word * flags, short events)
+{
+ MUTEX_EXIT_IRQRESTORE (*mutex, *flags);
+ wakeup (wq);
+ selwakeup (&wq->poll_info);
+ MUTEX_ENTER_IRQDISABLE (*mutex, *flags);
+}
+
+void
+oss_register_module (char *name)
+{
+ refcount++;
+}
+
+void
+oss_unregister_module (char *name)
+{
+ refcount--;
+}
+
+void
+oss_reserve_device (oss_device_t * osdev)
+{
+ osdev->refcount++;
+}
+
+void
+oss_unreserve_device (oss_device_t * osdev, int decrement)
+{
+ osdev->refcount--;
+ if (osdev->refcount < 0)
+ osdev->refcount = 0;
+}
+
+int
+oss_register_device (oss_device_t * osdev, const char *name)
+{
+ if ((osdev->name = PMALLOC (NULL, strlen (name) + 1)) == NULL)
+ {
+ cmn_err (CE_WARN, "Cannot allocate memory for device name\n");
+ osdev->name = "Unknown device";
+ }
+ strcpy (osdev->name, name);
+ if (osdev->dip != NULL)
+ device_set_desc (osdev->dip, name);
+ return OSS_ENXIO;
+}
+
+void
+oss_unregister_device (oss_device_t * osdev)
+{
+ // NOP
+}
+
+int
+oss_find_minor (int dev_class, int instance)
+{
+ int i;
+
+ for (i = 0; i < oss_num_cdevs; i++)
+ if (oss_cdevs[i]->d != NULL && oss_cdevs[i]->dev_class == dev_class
+ && oss_cdevs[i]->instance == instance)
+ return i;
+
+ return OSS_EIO;
+}
+
+void *
+oss_find_minor_info (int dev_class, int instance)
+{
+ int i;
+
+ for (i = 0; i < oss_num_cdevs; i++)
+ {
+ if (oss_cdevs[i]->d != NULL && oss_cdevs[i]->dev_class == dev_class
+ && oss_cdevs[i]->instance == instance)
+ return oss_cdevs[i]->info;
+ }
+
+ return NULL;
+}
+
+int
+oss_disable_device (oss_device_t * osdev)
+{
+ int i;
+
+ if (osdev->refcount > 0)
+ return OSS_EBUSY;
+
+ if (open_devices > 0)
+ return OSS_EBUSY;
+
+ for (i = 0; i < num_mixers; i++)
+ if (mixer_devs[i]->osdev == osdev)
+ {
+ mixer_devs[i]->unloaded = 1;
+ }
+
+ for (i = 0; i < num_mididevs; i++)
+ {
+ if (midi_devs[i]->osdev == osdev)
+ {
+ midi_devs[i]->unloaded = 1;
+ }
+ }
+
+ for (i = 0; i < num_audio_engines; i++)
+ if (audio_engines[i]->osdev == osdev)
+ {
+ audio_uninit_device (i);
+ }
+ return 0;
+}
+
+int
+oss_get_cardinfo (int cardnum, oss_card_info * ci)
+{
+/*
+ * Print information about a 'card' in a format suitable for /dev/sndstat
+ */
+
+ if (cardnum < 0 || cardnum >= oss_num_cards)
+ return OSS_ENXIO;
+
+ if (cards[cardnum]->name != NULL)
+ strncpy (ci->longname, cards[cardnum]->name, 128);
+ ci->shortname[127] = 0;
+
+ if (cards[cardnum]->nick != NULL)
+ strncpy (ci->shortname, cards[cardnum]->nick, 16);
+ ci->shortname[15] = 0;
+
+ if (cards[cardnum]->hw_info != NULL)
+ strncpy (ci->hw_info, cards[cardnum]->hw_info, sizeof (ci->hw_info));
+ ci->hw_info[sizeof (ci->hw_info) - 1] = 0;
+ ci->intr_count = cards[cardnum]->intrcount;
+ ci->ack_count = cards[cardnum]->ackcount;
+
+ return 0;
+}
+
+static int
+grow_array(oss_device_t *osdev, oss_cdev_t ***arr, int *size, int element_size, int increment)
+{
+ oss_cdev_t **old=*arr, **new = *arr;
+ int old_size = *size;
+ int new_size = *size;
+
+ new_size += increment;
+
+ if ((new=PMALLOC(osdev, new_size * element_size))==NULL)
+ return 0;
+
+ memset(new, 0, new_size * element_size);
+ if (old != NULL)
+ memcpy(new, old, old_size * element_size);
+
+ *size = new_size;
+ *arr = new;
+
+ if (old != NULL)
+ PMFREE(osdev, old);
+
+ return 1;
+}
+
+void
+oss_install_chrdev (oss_device_t * osdev, char *name, int dev_class,
+ int instance, oss_cdev_drv_t * drv, int flags)
+{
+ struct cdev *bsd_cdev;
+ oss_cdev_t *cdev = NULL;
+ int i, num;
+
+ if (dev_class != OSS_DEV_STATUS)
+ if (oss_expired && instance > 0)
+ return;
+/*
+ * Find if this dev_class&instance already exists (after previous module
+ * detach).
+ */
+
+ for (num = 0; num < oss_num_cdevs; num++)
+ if (oss_cdevs[num]->d == NULL) /* Unloaded driver */
+ if (oss_cdevs[num]->dev_class == dev_class
+ && oss_cdevs[num]->instance == instance)
+ {
+ cdev = oss_cdevs[num];
+ break;
+ }
+
+ if (cdev == NULL)
+ {
+ if (oss_num_cdevs >= OSS_MAX_CDEVS)
+ {
+ if (!grow_array(osdev, &oss_cdevs, &oss_max_cdevs, sizeof(oss_cdev_t*), 100))
+ {
+ cmn_err (CE_WARN, "Cannot allocate new minor numbers.\n");
+ return;
+ }
+ }
+
+ if ((cdev = PMALLOC (NULL, sizeof (*cdev))) == NULL)
+ {
+ cmn_err (CE_WARN, "Cannot allocate character device desc.\n");
+ return;
+ }
+ num = oss_num_cdevs++;
+ }
+
+ memset (cdev, 0, sizeof (*cdev));
+ cdev->dev_class = dev_class;
+ cdev->instance = instance;
+ cdev->d = drv;
+ cdev->osdev = osdev;
+ if (name != NULL)
+ strncpy (cdev->name, name, sizeof (cdev->name) - 1);
+ else
+ strcpy (cdev->name, "NONE");
+ cdev->name[sizeof (cdev->name) - 1] = 0;
+ oss_cdevs[num] = cdev;
+
+ if (!(flags & CHDEV_VIRTUAL) && (name != NULL))
+ {
+ bsd_cdev =
+ make_dev (&oss_cdevsw, num, UID_ROOT, GID_WHEEL, 0666, name, 0);
+ cdev->info = bsd_cdev;
+ }
+}
+
+#define MAX_MEMBLOCKS 4096
+static void *memblocks[MAX_MEMBLOCKS];
+static int nmemblocks = 0;
+
+void *
+oss_pmalloc (size_t sz)
+{
+ void *tmp;
+
+ tmp = KERNEL_MALLOC (sz);
+
+ if (nmemblocks < MAX_MEMBLOCKS)
+ memblocks[nmemblocks++] = tmp;
+
+ return tmp;
+}
+
+int
+oss_uiomove (void *address, size_t nbytes, enum uio_rw rwflag, uio_t * uio_p)
+{
+ int err;
+
+#undef uiomove
+ err = uiomove (address, nbytes, uio_p);
+
+ return err;
+}
+
+#undef timeout
+#undef untimeout
+
+typedef struct tmout_desc
+{
+ volatile int active;
+ int timestamp;
+ void (*func) (void *);
+ void *arg;
+
+ struct callout_handle 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 (void *arg)
+{
+ int ix;
+ tmout_desc_t *tmout = arg;
+
+ timeout_random++;
+
+ 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 */
+ {
+ cmn_err (CE_CONT, "Timeout table full\n");
+ return 0;
+ }
+
+ tmout->func = func;
+ tmout->arg = arg;
+ tmout->timestamp = id | (timeout_random & ~0xff);
+
+ tmout->timer = timeout (oss_timer_callback, tmout, ticks);
+
+ 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)
+ untimeout (oss_timer_callback, tmout, tmout->timer);
+ tmout->active = 0;
+ tmout->timestamp = 0;
+}
+
+int
+oss_get_procinfo (int what)
+{
+ switch (what)
+ {
+ case OSS_GET_PROCINFO_UID:
+ return oss_get_uid();
+ }
+
+ return EINVAL;
+}
+
+unsigned long
+oss_get_time (void)
+{
+ struct timeval timecopy;
+
+ getmicrotime (&timecopy);
+ return timecopy.tv_usec / (1000000 / hz) + (u_long) timecopy.tv_sec * hz;
+}
+
+caddr_t
+oss_map_pci_mem (oss_device_t * osdev, int nr, int paddr, int psize)
+{
+ void *vaddr = 0;
+ u_int32_t poffs;
+
+ poffs = paddr - trunc_page (paddr);
+ vaddr = (caddr_t) pmap_mapdev (paddr - poffs, psize + poffs) + poffs;
+
+ return vaddr;
+}
+
+void
+oss_pci_byteswap (oss_device_t * osdev, int mode)
+{
+ // NOP
+}
+
+void
+oss_pcie_init (oss_device_t * osdev, int flags)
+{
+ /* TODO: Should we do something? */
+}
+
+static time_t
+oss_get_walltime (void)
+{
+ struct timeval timecopy;
+
+ getmicrotime (&timecopy);
+ return timecopy.tv_sec;
+}
+
+int
+soundcard_attach (void)
+{
+ oss_device_t *osdev;
+
+ if ((osdev = PMALLOC (NULL, sizeof (*osdev))) == NULL)
+ {
+ return ENOSPC;
+ }
+
+ memset (osdev, 0, sizeof (*osdev));
+ core_osdev = osdev;
+
+#ifdef LICENSED_VERSION
+ if (!oss_license_handle_time (oss_get_walltime ()))
+ {
+ cmn_err (CE_WARN, "This version of Open Sound System has expired\n");
+ cmn_err (CE_CONT,
+ "Please download the latest version from www.opensound.com\n");
+ oss_expired = 1;
+ }
+#endif
+
+ osdev->major = oss_major;
+ oss_register_device (osdev, "OSS core services");
+
+ oss_common_init (osdev);
+
+ return 0;
+}
+
+int
+soundcard_detach (void)
+{
+ int i;
+
+ if (refcount > 0 || open_devices > 0)
+ return EBUSY;
+
+ oss_unload_drivers ();
+
+ osdev_delete (core_osdev);
+
+ for (i = 0; i < nmemblocks; i++)
+ KERNEL_FREE (memblocks[i]);
+ nmemblocks = 0;
+
+ return 0;
+}
+
+static void
+init_fileinfo (struct fileinfo *fi, int flags)
+{
+ memset (fi, 0, sizeof (*fi));
+ if ((flags & FREAD) && (flags & FWRITE))
+ fi->mode = OPEN_READWRITE;
+ else if (flags & FREAD)
+ fi->mode = OPEN_READ;
+ else if (flags & FWRITE)
+ fi->mode = OPEN_WRITE;
+ fi->acc_flags = flags;
+ fi->pid = -1;
+ fi->dev = -1;
+ fi->cmd = NULL;
+}
+
+static int
+oss_read (struct cdev *bsd_dev, struct uio *buf, int flags)
+{
+ int retval;
+ int dev;
+ oss_cdev_t *cdev;
+#ifndef VDEV_SUPPORT
+ struct fileinfo _fi, * fi = &_fi;
+ dev = MINOR (bsd_dev);
+ init_fileinfo (fi, flags);
+#else
+ struct fileinfo * fi;
+ if (oss_file_get_private ((void **)&fi)) return ENXIO;
+ dev = fi->dev;
+#endif
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (cdev->d->read == NULL)
+ {
+ return ENODEV;
+ }
+
+ retval = cdev->d->read (cdev->instance, fi, buf, buf->uio_resid);
+ if (retval < 0)
+ return -retval;
+ return 0;
+
+}
+
+static int
+oss_write (struct cdev *bsd_dev, struct uio *buf, int flags)
+{
+ int retval;
+ int dev;
+ oss_cdev_t *cdev;
+#ifndef VDEV_SUPPORT
+ struct fileinfo _fi, * fi = &_fi;
+ dev = MINOR (bsd_dev);
+ init_fileinfo (fi, flags);
+#else
+ struct fileinfo * fi;
+ if (oss_file_get_private ((void **)&fi)) return ENXIO;
+ dev = fi->dev;
+#endif
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (cdev->d->write == NULL)
+ {
+ return ENODEV;
+ }
+
+ retval = cdev->d->write (cdev->instance, fi, buf, buf->uio_resid);
+ if (retval < 0)
+ return -retval;
+ return 0;
+}
+
+static int
+oss_open (struct cdev *bsd_dev, int flags, int mode, struct thread *p)
+{
+ int dev = MINOR (bsd_dev);
+ oss_cdev_t *cdev;
+ struct fileinfo fi;
+ int tmpdev, retval;
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (cdev->d->open == NULL)
+ {
+ return ENODEV;
+ }
+
+ init_fileinfo (&fi, flags);
+ fi.pid = p->td_proc->p_pid;
+ fi.cmd = p->td_proc->p_comm;
+ tmpdev = dev;
+
+ retval =
+ cdev->d->open (cdev->instance, cdev->dev_class, &fi, 0, 0, &tmpdev);
+
+ if (tmpdev != -1) fi.dev = tmpdev;
+ else fi.dev = dev;
+ if (retval < 0)
+ return -retval;
+
+#ifdef VDEV_SUPPORT
+ if (oss_file_set_private (p, (void *)&fi, sizeof (struct fileinfo)))
+ return ENXIO;
+#endif
+
+ open_devices++;
+ return 0;
+}
+
+static int
+oss_close (struct cdev *bsd_dev, int flags, int mode, struct thread *p)
+{
+ int dev;
+ oss_cdev_t *cdev;
+#ifndef VDEV_SUPPORT
+ struct fileinfo _fi, * fi = &_fi;
+ dev = MINOR (bsd_dev);
+ init_fileinfo (fi, flags);
+#else
+ struct fileinfo * fi;
+ if (oss_file_get_private ((void **)&fi)) return ENXIO;
+ dev = fi->dev;
+#endif
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (cdev->d->close == NULL)
+ {
+ return ENODEV;
+ }
+
+ cdev->d->close (cdev->instance, fi);
+ open_devices--;
+ return 0;
+}
+
+static int
+oss_ioctl (struct cdev *bsd_dev, u_long cmd, caddr_t arg, int mode,
+ struct thread *p)
+{
+ int retval;
+ int dev;
+ oss_cdev_t *cdev;
+#ifndef VDEV_SUPPORT
+ struct fileinfo _fi, * fi = &_fi;
+ dev = MINOR (bsd_dev);
+ init_fileinfo (fi, mode);
+#else
+ struct fileinfo * fi;
+ if (oss_file_get_private ((void **)&fi)) return ENXIO;
+ dev = fi->dev;
+#endif
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (cdev->d->ioctl == NULL)
+ {
+ return ENODEV;
+ }
+
+ switch (cmd)
+ {
+ /*
+ * FreeBSD uses these ioctls to (un)set nonblocking I/O for devices. e.g.
+ * in case of fcntl (fd, F_SETFL, O_RDONLY|O_NONBLOCK) it will fire
+ * both ioctls.
+ * We deal with them here, and not in oss_audio_core because struct file
+ * isn't available in oss_audio_ioctl and we want the flags to remain
+ * accurate. oss_audio_core checks for O_NONBLOCK, and will pick
+ * up the change next read/write.
+ */
+ case FIONBIO:
+ if (arg != NULL)
+ {
+ if (*arg) fi->acc_flags |= O_NONBLOCK;
+ else fi->acc_flags &= ~O_NONBLOCK;
+ }
+ case FIOASYNC:
+ return 0;
+ default: break;
+ }
+
+ retval = cdev->d->ioctl (cdev->instance, fi, cmd, (ioctl_arg) arg);
+ if (retval < 0)
+ return -retval;
+ return 0;
+}
+
+static int
+oss_poll (struct cdev *bsd_dev, int events, struct thread *p)
+{
+ int retval;
+ int dev;
+ oss_cdev_t *cdev;
+ oss_poll_event_t ev;
+ int err;
+#ifndef VDEV_SUPPORT
+ struct fileinfo _fi, * fi = &_fi;
+ dev = MINOR (bsd_dev);
+ init_fileinfo (fi, 0);
+#else
+ struct fileinfo * fi;
+ if (oss_file_get_private ((void **)&fi)) return ENXIO;
+ dev = fi->dev;
+#endif
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (cdev->d->chpoll == NULL)
+ {
+ return ENODEV;
+ }
+
+ ev.events = events;
+ ev.revents = 0;
+ ev.p = p;
+ ev.bsd_dev = bsd_dev;
+
+ err = cdev->d->chpoll (cdev->instance, fi, &ev);
+ if (err < 0)
+ {
+ return -err;
+ }
+ return ev.revents;
+}
+
+#if defined(D_VERSION_03) && (D_VERSION == D_VERSION_03)
+static int
+oss_mmap (struct cdev *bsd_dev, vm_ooffset_t offset, vm_paddr_t * paddr,
+ int nprot, vm_memattr_t *memattr)
+#else
+static int
+oss_mmap (struct cdev *bsd_dev, vm_offset_t offset, vm_paddr_t * paddr,
+ int nprot)
+#endif
+{
+ int retval;
+ int dev;
+ oss_cdev_t *cdev;
+ oss_poll_event_t ev;
+ dmap_p dmap = NULL;
+ int err;
+#ifndef VDEV_SUPPORT
+ dev = MINOR (bsd_dev);
+#else
+ struct fileinfo * fi;
+ if (oss_file_get_private ((void **)&fi)) return ENXIO;
+ dev = fi->dev;
+#endif
+
+ if (dev >= oss_num_cdevs)
+ return ENXIO;
+
+ if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
+ return ENXIO;
+
+ if (nprot & PROT_EXEC)
+ return EACCES;
+
+ if ((cdev->dev_class != OSS_DEV_DSP) &&
+ (cdev->dev_class != OSS_DEV_DSP_ENGINE)) /* Only mmapable devices */
+ {
+ cmn_err (CE_NOTE, "mmap() is only possible with DSP devices (%d)\n",
+ cdev->dev_class);
+ return EINVAL;
+ }
+
+ dev = cdev->instance;
+
+ if (dev < 0 || dev >= num_audio_engines)
+ return ENODEV;
+
+ if (nprot & PROT_WRITE)
+ dmap = audio_engines[dev]->dmap_out;
+ else
+ dmap = audio_engines[dev]->dmap_in;
+
+ if (dmap == NULL)
+ return EIO;
+
+ if (dmap->dmabuf_phys == 0)
+ return EIO;
+
+ if (dmap->flags & DMAP_COOKED)
+ {
+ cmn_err (CE_WARN,
+ "mmap() not possible with currently selected sample format.\n");
+ return EIO;
+ }
+
+ dmap->mapping_flags |= DMA_MAP_MAPPED;
+ *paddr = dmap->dmabuf_phys + offset;
+
+ return 0;
+}
+
+oss_device_t *
+osdev_create (dev_info_t * dip, int dev_type, int instance, const char *nick,
+ const char *handle)
+{
+ oss_device_t *osdev = NULL;
+ int i, err;
+ caddr_t addr;
+ off_t region_size;
+
+ if (handle == NULL)
+ handle = nick;
+
+ /*
+ * Don't accept any more drivers if expired
+ */
+ if (oss_expired && oss_num_cards > 0)
+ return NULL;
+
+ for (i = 0; i < oss_num_cards; i++)
+ {
+ if (cards[i]->dip == dip)
+ {
+ osdev = cards[i];
+ break;
+ }
+ }
+
+ if (osdev == NULL)
+ {
+ if (oss_num_cards >= MAX_CARDS)
+ {
+ cmn_err (CE_WARN, "Too many OSS devices. At most %d permitted.\n",
+ MAX_CARDS);
+ return NULL;
+ }
+
+ if ((osdev = PMALLOC (NULL, sizeof (*osdev))) == NULL)
+ {
+ cmn_err (CE_WARN, "osdev_create: Out of memory\n");
+ return NULL;
+ }
+
+ osdev->cardnum = oss_num_cards;
+ cards[oss_num_cards++] = osdev;
+ }
+
+ osdev->dip = dip;
+ osdev->osid = dip;
+ osdev->available = 1;
+ osdev->instance = instance;
+ osdev->dev_type = dev_type;
+ osdev->devc = NULL;
+ osdev->first_mixer = -1;
+ sprintf (osdev->nick, "%s%d", nick, instance);
+ strcpy (osdev->modname, nick);
+
+/*
+ * Create the device handle
+ */
+ switch (dev_type)
+ {
+ case DRV_PCI:
+ {
+ sprintf (osdev->handle, "OSS-PCI");
+ }
+ break;
+
+ default:
+ sprintf (osdev->handle, "%s%d", handle, instance);
+ }
+
+ return osdev;
+}
+
+oss_device_t *
+osdev_clone (oss_device_t * orig_osdev, int new_instance)
+{
+ oss_device_t *osdev;
+
+ osdev = PMALLOC (NULL, sizeof (*osdev));
+ if (osdev == NULL)
+ {
+ cmn_err (CE_WARN, "osdev_create: Out of memory\n");
+ return NULL;
+ }
+ memcpy (osdev, orig_osdev, sizeof (*osdev));
+ osdev->dev_type = DRV_CLONE;
+ osdev->instance = new_instance;
+ sprintf (osdev->nick, "%s%d", orig_osdev->modname, new_instance);
+ sprintf (osdev->handle, "%s%d", orig_osdev->modname, new_instance);
+
+ return osdev;
+}
+
+void
+osdev_delete (oss_device_t * osdev)
+{
+ int i;
+
+ if (osdev == NULL)
+ return;
+
+ osdev->available = 0;
+/*
+ * Mark all minor nodes for this module as invalid.
+ */
+ for (i = 0; i < oss_num_cdevs; i++)
+ if (oss_cdevs[i]->osdev == osdev)
+ {
+ if (oss_cdevs[i]->info != NULL)
+ destroy_dev (oss_cdevs[i]->info);
+ oss_cdevs[i]->d = NULL;
+ oss_cdevs[i]->info = NULL;
+ oss_cdevs[i]->osdev = NULL;
+ strcpy (oss_cdevs[i]->name, "Removed device");
+ }
+}
+
+void *
+oss_get_osid (oss_device_t * osdev)
+{
+ return osdev->osid;
+}
+
+void
+oss_inc_intrcount (oss_device_t * osdev, int claimed)
+{
+ osdev->intrcount++;
+
+ if (claimed)
+ osdev->ackcount++;
+}
diff --git a/kernel/OS/FreeBSD/os_freebsd.h b/kernel/OS/FreeBSD/os_freebsd.h
new file mode 100644
index 0000000..161a2e3
--- /dev/null
+++ b/kernel/OS/FreeBSD/os_freebsd.h
@@ -0,0 +1,263 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+/*
+ * Purpose: OS specific definitions for FreeBSD
+ *
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+#define OS_VERSION "6"
+#define __inline__ inline
+#define __inline inline
+#define EXTERN_C extern "C"
+
+/*
+ * Debugging and misc settings
+ */
+#undef MUTEX_CHECKS
+#undef MEMDEBUG
+
+#if (!defined(__i386__) && !defined(__x86_64__)) || defined(CONFIG_OSS_FIXDEPOINT)
+// Floating point is not supported or it's disabled
+#undef CONFIG_OSS_VMIX_FLOAT
+#endif
+
+/*
+ * Disable support for per-application features such as /dev/dsp device
+ * selection based on command name. Requires working GET_PROCESS_NAME
+ * macro implementation.
+ */
+#undef APPLIST_SUPPORT
+#define USE_DEVICE_SUBDIRS
+
+#include <stdarg.h>
+#include <sys/types.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#endif
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/fcntl.h>
+#include <sys/poll.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
+#include <machine/cpufunc.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <sys/selinfo.h>
+#include <oss_errno.h>
+
+#if __FreeBSD_version >= 800062
+#define MINOR(x) dev2unit(x)
+#else
+#define MINOR(x) minor(x)
+#endif
+
+#undef timeout
+#define timeout oss_timeout
+#undef untimeout
+#define untimeout oss_untimeout
+typedef int timeout_id_t;
+extern timeout_id_t oss_timeout (void (*func) (void *), void *arg,
+ unsigned long long ticks);
+extern void oss_untimeout (timeout_id_t id);
+
+#include "kernel/OS/FreeBSD/wrapper/bsddefs.h"
+
+#ifdef USE_SX_LOCK
+#include <sys/proc.h> /* XXX for curthread */
+#include <sys/sx.h>
+#else
+#include <sys/mutex.h>
+#endif
+
+
+#define uiomove oss_uiomove
+typedef struct uio uio_t;
+extern int oss_uiomove (void *address, size_t nbytes, enum uio_rw rwflag,
+ uio_t * uio_p);
+
+#undef HZ
+#define OSS_HZ hz
+
+/* The soundcard.h could be in a nonstandard place so include it here. */
+#include "soundcard.h"
+
+typedef struct udi_usb_devc udi_usb_devc;
+
+#define ALLOW_SELECT
+#define ALLOW_BUFFER_MAPPING
+
+/*
+ * Sleep/wakeup
+ */
+
+#ifdef _KERNEL
+struct oss_wait_queue
+{
+ oss_mutex_t mutex;
+ unsigned long flags;
+ struct selinfo poll_info;
+};
+#endif
+
+/* Busy wait routine */
+
+/* System wall timer access */
+extern unsigned long oss_get_time (void);
+#define GET_JIFFIES() oss_get_time()
+
+/*
+ * Mutexes
+ */
+
+#ifdef USE_SX_LOCK
+struct sx;
+#define MUTEX_INIT(osdev, mutex, hier) \
+do { \
+ mutex = malloc(sizeof(*mutex), M_DEVBUF, M_WAITOK | M_ZERO); \
+ sx_init(mutex, "oss"); \
+} while (0)
+#define MUTEX_CLEANUP(mutex) \
+do { \
+ sx_destroy(mutex); \
+ free(mutex, M_DEVBUF); \
+} while (0)
+#define MUTEX_ENTER_IRQDISABLE(mutex, flags) sx_xlock(mutex)
+#define MUTEX_ENTER(mutex, flags) sx_slock(mutex)
+#define MUTEX_EXIT_IRQRESTORE(mutex, flags) sx_xunlock(mutex)
+#define MUTEX_EXIT(mutex, flags) sx_sunlock(mutex)
+#else /* !USE_SX_LOCK */
+struct mtx;
+#define MUTEX_INIT(osdev, mutex, hier) \
+do { \
+ mutex = malloc(sizeof(*mutex), M_DEVBUF, M_WAITOK | M_ZERO); \
+ mtx_init(mutex, "oss", NULL, MTX_RECURSE | MTX_SPIN); \
+} while (0)
+#define MUTEX_CLEANUP(mutex) \
+do { \
+ mtx_destroy(mutex); \
+ free(mutex, M_DEVBUF); \
+} while (0)
+#define MUTEX_ENTER_IRQDISABLE(mutex, flags) mtx_lock_spin_flags(mutex, flags)
+#define MUTEX_ENTER(mutex, flags) mtx_lock_spin(mutex)
+#define MUTEX_EXIT_IRQRESTORE(mutex, flags) mtx_unlock_spin_flags(mutex, flags)
+#define MUTEX_EXIT(mutex, flags) mtx_unlock_spin(mutex)
+#endif /* USE_SX_LOCK */
+
+
+/*
+ * INB() and OUTB() should be obvious. NOTE! The order of
+ * paratemeters of OUTB() is different than on some other
+ * operating systems.
+ */
+
+/* I/O Mapped devices */
+#define INB(o, p) inb(p)
+#define INW(o, p) inw(p)
+#define INL(o, p) inl(p)
+
+#define OUTB(o, v, p) outb(p,v)
+#define OUTW(o, v, p) outw(p,v)
+#define OUTL(o, v, p) outl(p,v)
+
+/* Memory Mapped devices */
+#define PCI_READL(osp, p) readl(p)
+#define PCI_READW(osp, p) readw(p)
+#define PCI_READB(osp, p) readb(p)
+#define PCI_WRITEL(osp, addr, data) writel(addr, data)
+#define PCI_WRITEW(osp, addr, data) writew(addr, data)
+#define PCI_WRITEB(osp, addr, data) writeb(addr, data)
+
+typedef void *oss_dma_handle_t;
+
+/*
+ KERNEL_MALLOC() allocates requested number of memory and
+ KERNEL_FREE is used to free it.
+ These macros are never called from interrupt, in addition the
+ nbytes will never be more than 4096 bytes. Generally the driver
+ will allocate memory in blocks of 4k. If the kernel has just a
+ page level memory allocation, 4K can be safely used as the size
+ (the nbytes parameter can be ignored).
+*/
+#define KERNEL_MALLOC(nbytes) malloc(nbytes, M_DEVBUF, M_NOWAIT|M_ZERO)
+#define KERNEL_FREE(addr) {if (addr)free(addr, M_DEVBUF);addr=NULL;}
+
+#define CONTIG_MALLOC(osdev, sz, memlimit, phaddr, handle) oss_contig_malloc(sz, memlimit, phaddr)
+#define CONTIG_FREE(osdev, p, sz, handle) oss_contig_free(p, sz)
+
+/*
+ * Timer macros
+ *
+ * These macros are obsolete and should not be used in any new code.
+ * Use the timeout mechanism (see the timeout(9F) Solaris man page).
+ */
+#define DEFINE_TIMER(name, proc) static timeout_id_t name = 0
+#define REMOVE_TIMER(name, proc) {if (name != 0) untimeout(name);}
+#define INIT_TIMER(name,proc)
+typedef void (*timeout_func_t) (void *);
+#define ACTIVATE_TIMER(name, proc, time) \
+ name=timeout((timeout_func_t)proc, (void*)&name, time)
+#endif
+
+struct fileinfo
+{
+ int mode; /* Open mode */
+ int acc_flags;
+ int pid;
+ int dev;
+ char *cmd;
+};
+#define ISSET_FILE_FLAG(fileinfo, flag) (fileinfo->acc_flags & (flag) ? 1:0)
+
+#define OSS_OS "FreeBSD"
+#define OSS_OS_LONGNAME "FreeBSD " OS_VERSION
+
+typedef void (*softintr_func_t) (int);
+
+struct oss_softintr
+{
+ int id;
+ softintr_func_t func;
+ volatile int armed, running;
+};
+
+struct _oss_poll_event_t
+{
+ short events, revents;
+ struct thread *p;
+ struct cdev *bsd_dev;
+};
+typedef struct _oss_poll_event_t oss_poll_event_t;
+
+extern int detect_trace;
+#define DDB(x) if (detect_trace) x
+
+extern caddr_t oss_map_pci_mem (oss_device_t * osdev, int nr, int phaddr,
+ int size);
+#define MAP_PCI_IOADDR(osdev, nr, io) (oss_native_word)(io)
+#define MAP_PCI_MEM(osdev, ix, phaddr, size) oss_map_pci_mem(osdev, ix, phaddr, size)
+#define UNMAP_PCI_MEM(osdev, ix, ph, virt, size) {}
+#define UNMAP_PCI_IOADDR(osdev, ix) {}
+
+#define GET_PROCESS_PID(f) f->pid
+#define GET_PROCESS_NAME(f) f->cmd
+
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+
+/*
+ * PCI config space access (in os.c)
+ */
+extern char *oss_pci_read_devpath (dev_info_t * dip);
diff --git a/kernel/OS/FreeBSD/wrapper/bsddefs.h b/kernel/OS/FreeBSD/wrapper/bsddefs.h
new file mode 100644
index 0000000..c22965c
--- /dev/null
+++ b/kernel/OS/FreeBSD/wrapper/bsddefs.h
@@ -0,0 +1,150 @@
+/*
+ * Purpose: Definitions for routines and variables exported by osscore.c
+ *
+ * Do not make any modifications to these settings because OSS core modules
+ * have been compiled against them. Full rebuild of OSS will be required if
+ * this file is changed.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <sys/types.h>
+#if 0 /* __FreeBSD_version >= 700031 */
+/* Some crashes have been reported with SX on 7-STABLE/8-CURRENT:
+ * http://4front-tech.com/forum/viewtopic.php?t=2718
+ * http://4front-tech.com/forum/viewtopic.php?t=2563
+ */
+#define USE_SX_LOCK 1
+#endif
+#undef VDEV_SUPPORT
+#if __FreeBSD_version >= 700111
+#define VDEV_SUPPORT
+extern int oss_file_set_private (struct thread *p, void *v, size_t l);
+extern int oss_file_get_private (void **v);
+#endif
+extern int oss_get_uid (void);
+
+typedef struct device dev_info_t;
+typedef long long oss_int64_t; /* Signed 64 bit integer */
+typedef unsigned long long oss_uint64_t; /* Unsigned 64 bit integer */
+typedef unsigned long offset_t;
+
+/*
+ * Some integer types
+ */
+#if defined(__amd64__)
+typedef unsigned long long oss_native_word; /* Same as the address and status register size */
+#else
+typedef unsigned long oss_native_word; /* Same as the address and status register size */
+#endif
+
+struct _oss_device_t
+{
+ int cardnum;
+ int dev_type;
+ int instance;
+ int available;
+ dev_info_t *dip;
+ void *osid;
+ void *devc;
+ char *name;
+ char *hw_info;
+ int major;
+ char nick[16];
+ char modname[16];
+ char handle[32];
+ int num_audio_engines;
+ int num_audioplay, num_audiorec, num_audioduplex;
+ int num_mididevs;
+ int num_mixerdevs;
+ int num_loopdevs;
+ int first_mixer; /* This must be set to -1 by osdev_create() */
+
+ int intrcount;
+ int ackcount;
+ volatile int refcount; /* Nonzero means that the device is needed by some other (virtual) driver. */
+
+};
+
+extern void cmn_err (int level, char *format, ...);
+#define CE_CONT 0
+#define CE_NOTE 1
+#define CE_WARN 2
+#define CE_PANIC 3
+
+#ifdef USE_SX_LOCK
+typedef struct sx *oss_mutex_t;
+#else
+typedef struct mtx *oss_mutex_t;
+#endif
+
+typedef int ddi_iblock_cookie_t;
+
+extern void oss_udelay (unsigned long t);
+
+#ifdef _KERNEL
+#define memset oss_memset
+extern void *oss_memset (void *t, int val, int l);
+#endif
+
+extern oss_device_t *osdev_create (dev_info_t * dip, int dev_type,
+ int instance, const char *nick,
+ const char *handle);
+extern void osdev_delete (oss_device_t * osdev);
+
+extern char *oss_pci_read_devpath (dev_info_t * dip);
+extern int pci_read_config_byte (oss_device_t * osdev, offset_t where,
+ unsigned char *val);
+extern int pci_read_config_irq (oss_device_t * osdev, offset_t where,
+ unsigned char *val);
+extern int pci_read_config_word (oss_device_t * osdev, offset_t where,
+ unsigned short *val);
+extern int pci_read_config_dword (oss_device_t * osdev, offset_t where,
+ unsigned int *val);
+extern int pci_write_config_byte (oss_device_t * osdev, offset_t where,
+ unsigned char val);
+extern int pci_write_config_word (oss_device_t * osdev, offset_t where,
+ unsigned short val);
+extern int pci_write_config_dword (oss_device_t * osdev, offset_t where,
+ unsigned int val);
+#ifndef OSS_CONFIG_H
+/* 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);
+#endif
+
+extern int oss_register_interrupts (oss_device_t * osdev, int intrnum,
+ oss_tophalf_handler_t top,
+ oss_bottomhalf_handler_t bottom);
+extern void oss_unregister_interrupts (oss_device_t * osdev);
+
+extern void *oss_contig_malloc (unsigned long sz, unsigned long memlimit,
+ oss_native_word * phaddr);
+extern void oss_contig_free (void *p, unsigned long sz);
+
+extern void oss_register_module (char *name);
+extern void oss_unregister_module (char *name);
+extern void *oss_find_minor_info (int dev_class, int instance);
+extern int oss_find_minor (int dev_class, int instance);
+extern void oss_inc_intrcount (oss_device_t * osdev, int claimed);
+
+#define FP_SUPPORT
+
+#ifdef FP_SUPPORT
+typedef short fp_env_t[512];
+typedef unsigned int fp_flags_t[4];
+extern int oss_fp_check (void);
+extern void oss_fp_save (short *envbuf, fp_flags_t flags);
+extern void oss_fp_restore (short *envbuf, fp_flags_t flags);
+# define FP_SAVE(envbuf, flags) oss_fp_save(envbuf, flags)
+# define FP_RESTORE(envbuf, flags) oss_fp_restore(envbuf, flags)
+#endif