summaryrefslogtreecommitdiff
path: root/kernel/OS/VxWorks
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/OS/VxWorks')
-rw-r--r--kernel/OS/VxWorks/.config1
-rw-r--r--kernel/OS/VxWorks/linux/ioctl.h5
-rw-r--r--kernel/OS/VxWorks/module.inc127
-rw-r--r--kernel/OS/VxWorks/os_vxworks.c1133
-rw-r--r--kernel/OS/VxWorks/os_vxworks.h297
5 files changed, 1563 insertions, 0 deletions
diff --git a/kernel/OS/VxWorks/.config b/kernel/OS/VxWorks/.config
new file mode 100644
index 0000000..816ac62
--- /dev/null
+++ b/kernel/OS/VxWorks/.config
@@ -0,0 +1 @@
+mode=kernel
diff --git a/kernel/OS/VxWorks/linux/ioctl.h b/kernel/OS/VxWorks/linux/ioctl.h
new file mode 100644
index 0000000..937d84c
--- /dev/null
+++ b/kernel/OS/VxWorks/linux/ioctl.h
@@ -0,0 +1,5 @@
+/*
+ * This file is currently required when cross compiling
+ * for VxWorks under Linux.
+ */
+#include <sys/ioctl.h>
diff --git a/kernel/OS/VxWorks/module.inc b/kernel/OS/VxWorks/module.inc
new file mode 100644
index 0000000..31f17f0
--- /dev/null
+++ b/kernel/OS/VxWorks/module.inc
@@ -0,0 +1,127 @@
+#if DRIVER_TYPE == DRV_PCI
+#include <drv/pci/pciConfigLib.h>
+#undef PCI_LATENCY_TIMER
+#include <oss_pci.h>
+
+int
+oss_pci_read_config_byte (oss_device_t * osdev, offset_t where,
+ unsigned char *val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ return pciConfigInByte (pd->bus, pd->dev, pd->func, where, val);
+}
+
+int
+oss_pci_read_config_irq (oss_device_t * osdev, offset_t where,
+ unsigned char *val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ return pciConfigInByte (pd->bus, pd->dev, pd->func, where, val);
+}
+
+int
+oss_pci_read_config_word (oss_device_t * osdev, offset_t where,
+ unsigned short *val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ if (osdev == NULL)
+ {
+ cmn_err (CE_CONT, "oss_pci_read_config_word: osdev==NULL\n");
+ return PCIBIOS_FAILED;
+ }
+
+ return pciConfigInWord (pd->bus, pd->dev, pd->func, where, val);
+}
+
+int
+oss_pci_read_config_dword (oss_device_t * osdev, offset_t where,
+ unsigned int *val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ return pciConfigInLong (pd->bus, pd->dev, pd->func, where, val);
+}
+
+int
+oss_pci_write_config_byte (oss_device_t * osdev, offset_t where,
+ unsigned char val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ return pciConfigOutByte (pd->bus, pd->dev, pd->func, where, val);
+}
+
+int
+oss_pci_write_config_word (oss_device_t * osdev, offset_t where,
+ unsigned short val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ return pciConfigOutWord (pd->bus, pd->dev, pd->func, where, val);
+}
+
+int
+oss_pci_write_config_dword (oss_device_t * osdev, offset_t where,
+ unsigned int val)
+{
+ oss_pci_device_t *pd = osdev->dip;
+
+ return pciConfigOutLong (pd->bus, pd->dev, pd->func, where, val);
+}
+#endif
+
+int
+DRIVER_NAME(void)
+{
+#if DRIVER_TYPE == DRV_PCI
+ int i;
+ int bus, dev, func;
+ unsigned int d, vendor_id, dev_id;
+ static int instance = 0;
+
+ if (id_table[0] == 0)
+ {
+ cmn_err (CE_WARN, DRIVER_NICK ": ID table is empty\n");
+ return OSS_EIO;
+ }
+
+ i=0;
+
+ while ((d=id_table[i]) != 0)
+ {
+ int index=0;
+ vendor_id = (d >> 16) & 0xffff;
+ dev_id = d & 0xffff;
+
+ while (pciFindDevice(vendor_id, dev_id, instance,&bus, &dev, &func) == OK)
+ {
+ oss_pci_device_t *pcidev = malloc(sizeof(*pcidev));
+ oss_device_t *osdev;
+
+
+ cmn_err(CE_CONT, "Found pci device %08x / %d : b=%d, d=%d, f=%d\n", d, index, bus, dev, func);
+
+ pcidev->bus = bus;
+ pcidev->dev = dev;
+ pcidev->func = func;
+
+ if ((osdev =
+ osdev_create ((dev_info_t*)pcidev, DRIVER_TYPE, instance++, DRIVER_NICK,
+ NULL)) == NULL)
+ {
+ return OSS_ENOMEM;
+ }
+
+ index++;
+ }
+
+ i++;
+ }
+
+#endif
+
+ return 0;
+}
diff --git a/kernel/OS/VxWorks/os_vxworks.c b/kernel/OS/VxWorks/os_vxworks.c
new file mode 100644
index 0000000..a679e6c
--- /dev/null
+++ b/kernel/OS/VxWorks/os_vxworks.c
@@ -0,0 +1,1133 @@
+/*
+ * oss_vxworks.c: Common entry points for OSS under VxWorks.
+ */
+
+#include <oss_config.h>
+#include <oss_pci.h>
+#include <drv/pci/pciConfigLib.h>
+#include <memLib.h>
+
+#if 0
+// TODO: Obsolete
+typedef struct oss_device_handle
+{
+ DEV_HDR devHdr;
+ int minor;
+ int valid; /* 1=valid, 0=undefined */
+ struct fileinfo finfo;
+}
+oss_device_handle;
+#endif
+/*
+ * Number of cards supported in the same system.
+ */
+#define MAX_CARDS 8
+
+static oss_device_t *cards[MAX_CARDS];
+int oss_num_cards = 0;
+
+static int oss_driver_num = ERROR;
+static int oss_expired = 0;
+static oss_device_t *core_osdev = NULL;
+
+int oss_hz = 100;
+
+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] = ( (sizeof(char *) == 32) ? ( *((char * **)(ap += ((sizeof(char * *)+sizeof(int)-1) & ~(sizeof(int)-1))))[-1] ) : ( ((char * *)(ap += ((sizeof(char *)+sizeof(int)-1) & ~(sizeof(int)-1))))[-1] ));
+ //a[i] = va_arg (ap, char *); // This was supposed to be used instead of above. Unfortunately va_arg() seems to be buggy
+
+ 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);
+ printf ("%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);
+
+ printf ("%s", tmp);
+ }
+
+ va_end (ap);
+}
+
+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 compatibility)).
+ */
+
+ 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:
+ memcpy(uio->ptr, addr, nbytes);
+ break;
+
+ case UIO_WRITE:
+ memcpy(addr, uio->ptr, nbytes);
+ 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;
+}
+
+static int
+grow_array(oss_device_t *osdev, oss_cdev_t ***arr, int *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 * sizeof (oss_cdev_t *)))==NULL)
+ return 0;
+
+ memset(new, 0, new_size * sizeof(oss_cdev_t *));
+ if (old != NULL)
+ memcpy(new, old, old_size * sizeof(oss_cdev_t *));
+
+ *size = new_size;
+ *arr = new;
+
+ if (old != NULL)
+ PMFREE(osdev, old);
+
+ return 1;
+}
+
+static void
+register_chrdev(oss_cdev_t *cdev, char *name)
+{
+ if (iosDevAdd ((void *)cdev, name, oss_driver_num) == ERROR)
+ {
+ cmn_err (CE_WARN, "Failed to add device %s\n", name);
+ }
+}
+
+void
+oss_install_chrdev (oss_device_t * osdev, char *name, int dev_class,
+ int instance, oss_cdev_drv_t * drv, int flags)
+{
+/*
+ * oss_install_chrdev creates a character device (minor). However if
+ * name==NULL the device will not be exported (made visible to userland
+ * clients).
+ */
+
+ int num;
+ oss_cdev_t *cdev = NULL;
+
+ if (dev_class != OSS_DEV_STATUS)
+ if (oss_expired && instance > 0)
+ return;
+
+ if (oss_num_cdevs >= OSS_MAX_CDEVS)
+ {
+ if (!grow_array(osdev, &oss_cdevs, &oss_max_cdevs, 100))
+ {
+ cmn_err (CE_WARN, "Out of 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));
+ else
+ strcpy (cdev->name, "NONE");
+ cdev->name[sizeof (cdev->name) - 1] = 0;
+ oss_cdevs[num] = cdev;
+
+/*
+ * Export the device only if name != NULL
+ */
+ if (name != NULL)
+ {
+ strcpy (cdev->name, name);
+ register_chrdev (cdev, name);
+ }
+}
+
+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_ENXIO;
+}
+
+static inline int
+cpy_file (int mode, struct fileinfo *fi)
+{
+ fi->mode = 0;
+ fi->acc_flags = mode;
+
+ if ((fi->acc_flags & O_ACCMODE) == O_RDWR)
+ fi->mode = OPEN_READWRITE;
+ if ((fi->acc_flags & O_ACCMODE) == O_RDONLY)
+ fi->mode = OPEN_READ;
+ if ((fi->acc_flags & O_ACCMODE) == O_WRONLY)
+ fi->mode = OPEN_WRITE;
+
+ return fi->mode;
+}
+
+static void *
+ossOpen (oss_cdev_t *cdev, char *reminder, int mode)
+{
+ int tmpdev, retval;
+ struct fileinfo fi;
+
+ cpy_file (mode, &fi);
+
+ DDB (cmn_err
+ (CE_CONT, "ossOpen(%p): %s, class=%d, instance=%d\n", cdev,
+ cdev->name, cdev->dev_class, cdev->instance));
+
+ if (cdev->d->open == NULL)
+ {
+ errnoSet(ENODEV);
+ return (void*)ERROR;
+ }
+
+ tmpdev = -1;
+ retval =
+ cdev->d->open (cdev->instance, cdev->dev_class, &fi, 0, 0, &tmpdev);
+
+ if (retval < 0)
+ {
+ errnoSet(-retval);
+ return (void*)ERROR;
+ }
+
+ if (tmpdev != -1)
+ {
+ if (tmpdev >= 0 && tmpdev < oss_num_cdevs)
+ {
+ cdev = oss_cdevs[tmpdev];
+ }
+ else
+ {
+ errnoSet(ENODEV);
+ return (void*)ERROR;
+ }
+ }
+
+ errnoSet (0);
+ memcpy(&cdev->file, &fi, sizeof(struct fileinfo));
+
+ return cdev;
+}
+
+static int
+ossClose (oss_cdev_t *cdev)
+{
+ if (cdev->d->close == NULL)
+ {
+ return OK;
+ }
+
+ cdev->d->close (cdev->instance, &cdev->file);
+
+ return OK;
+}
+
+static int
+ossRead (oss_cdev_t *cdev, char *buf, int count)
+{
+ int err, len;
+ uio_t uio;
+
+ if (cdev->d->read == NULL)
+ {
+ errnoSet (ENXIO);
+ return ERROR;
+ }
+
+ if ((err = oss_create_uio (&uio, buf, count, UIO_READ, 0)) < 0)
+ {
+ errnoSet (-err);
+ return ERROR;
+ }
+
+ len = cdev->d->read (cdev->instance, &cdev->file, &uio, count);
+
+ if (len >= 0)
+ return len;
+
+ errnoSet (-len);
+ return ERROR;
+}
+
+static int
+ossWrite (oss_cdev_t *cdev, char *buf, int count)
+{
+ int err, len;
+ uio_t uio;
+
+ if (cdev->d->write == NULL)
+ {
+ errnoSet (ENXIO);
+ return ERROR;
+ }
+
+ if ((err = oss_create_uio (&uio, buf, count, UIO_WRITE, 0)) < 0)
+ {
+ errnoSet (-err);
+ return ERROR;
+ }
+
+ len = cdev->d->write (cdev->instance, &cdev->file, &uio, count);
+
+ if (len >= 0)
+ return len;
+
+ errnoSet (-len);
+ return ERROR;
+}
+
+static int
+ossIoctl (oss_cdev_t *cdev, int cmd, int *arg)
+{
+ int err;
+
+ if (cdev->d->ioctl == NULL)
+ {
+ errnoSet (ENXIO);
+ return ERROR;
+ }
+
+ if ((err = cdev->d->ioctl (cdev->instance, &cdev->file, cmd, (ioctl_arg) arg)) < 0)
+ {
+ errnoSet (-err);
+ return ERROR;
+ }
+ return OK;
+}
+
+oss_device_t *
+osdev_create (dev_info_t * dip, int dev_type,
+ int instance, const char *nick, const char *handle)
+{
+ oss_device_t *osdev;
+
+ osdev = PMALLOC (NULL, sizeof (*osdev));
+ if (osdev == NULL)
+ {
+ cmn_err (CE_WARN, "osdev_create: Out of memory\n");
+ return NULL;
+ }
+
+ memset (osdev, 0, sizeof (*osdev));
+
+ sprintf (osdev->nick, "%s%d", nick, instance);
+ osdev->instance = instance;
+ osdev->dip = dip;
+ osdev->available = 1;
+ osdev->first_mixer = -1;
+
+ strcpy (osdev->modname, nick);
+
+ if (handle == NULL)
+ handle = nick;
+
+ if (oss_num_cards >= MAX_CARDS)
+ cmn_err (CE_WARN, "Too many OSS devices. At most %d permitted.\n",
+ MAX_CARDS);
+ else
+ {
+ osdev->cardnum = oss_num_cards;
+ cards[oss_num_cards++] = osdev;
+ }
+/*
+ * Create the device handle
+ */
+ switch (dev_type)
+ {
+ case DRV_PCI:
+ {
+#if 0
+ // TODO
+ unsigned int subvendor;
+ char *devpath;
+ devpath = oss_pci_read_devpath (osdev->dip);
+ oss_pci_read_config_dword (osdev, 0x2c, &subvendor);
+
+ sprintf (osdev->handle, "PCI%08x-%s", subvendor, devpath);
+#else
+ strcpy(osdev->handle, "PCICARD");
+#endif
+ }
+ break;
+
+ case DRV_USB:
+ // TODO: Get the vendor information
+ sprintf (osdev->handle, "USB-%s%d", handle, instance);
+ 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)
+ {
+ oss_cdevs[i]->d = NULL;
+ oss_cdevs[i]->osdev = NULL;
+ strcpy (oss_cdevs[i]->name, "Removed device");
+ }
+}
+
+void *
+oss_get_osid (oss_device_t * osdev)
+{
+ return NULL; // TODO
+}
+
+int
+oss_register_device (oss_device_t * osdev, const char *name)
+{
+ if (name == NULL)
+ {
+ cmn_err (CE_WARN, "oss_register_device: name==NULL\n");
+ osdev->name = "Undefined name";
+ return 0;
+ }
+
+ 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);
+ return 0;
+}
+
+void
+oss_unregister_device (oss_device_t * osdev)
+{
+/*
+ * Notice! The driver calling this routine (the owner of the osdev parameter)
+ * has already uninitialized itself. Do not do any actions that may call this
+ * driver directly or indirectly.
+ */
+
+// TODO: Move this to some common OSS module (also under Solaris)
+}
+
+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->longname[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;
+}
+
+int
+ossDrv (void)
+{
+ oss_hz = sysClkRateGet();
+
+ if (oss_driver_num != ERROR)
+ {
+ cmn_err (CE_WARN, "OSS is already running\n");
+ return -1;
+ }
+
+#ifdef LICENSED_VERSION
+ if (!oss_license_handle_time (oss_get_time ()))
+ {
+ 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;
+ return -1;
+ }
+#endif
+
+ oss_driver_num = iosDrvInstall ((FUNCPTR) NULL, /* create */
+ (FUNCPTR) NULL, /* delete */
+ (FUNCPTR) ossOpen, (FUNCPTR) ossClose, (FUNCPTR) ossRead, (FUNCPTR) ossWrite, (FUNCPTR) ossIoctl /* ioctl */
+ );
+ if (oss_driver_num == ERROR)
+ {
+ cmn_err (CE_WARN, "Module osscore failed to install\n");
+ return -1;
+ }
+
+ if ((core_osdev =
+ osdev_create (NULL, DRV_UNKNOWN, 0, "osscore", NULL)) == NULL)
+ {
+ oss_cmn_err (CE_WARN, "Failed to allocate OSDEV structure\n");
+ return -1;
+ }
+ oss_register_device (core_osdev, "OSS core services");
+
+ oss_common_init (core_osdev);
+
+ return oss_driver_num;
+}
+
+int
+ossDrvRemove (void)
+{
+#if 1
+
+ return ERROR;
+#else
+ int i;
+
+ if (oss_driver_num == ERROR)
+ return 0;
+
+ for (i = 0; i < SND_NDEVS; i++)
+ if (oss_files[i].valid)
+ {
+ iosDevDelete (&oss_files[i].devHdr);
+ oss_files[i].valid = 0;
+ }
+
+ if (iosDrvRemove (oss_driver_num, FALSE) == ERROR)
+ {
+ cmn_err (CE_WARN, "Driver busy - cannot remove.\n");
+ return ERROR;
+ }
+
+ // TODO
+ oss_unload_drivers ();
+
+ oss_driver_num = ERROR; /* Mark it free */
+ return OK;
+#endif
+}
+
+#ifdef CONFIG_OSS_VMIX_FLOAT
+
+#undef FP_SAVE
+#undef FP_RESTORE
+#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 defined(__amd64__)
+#define AMD64
+#endif
+
+static inline void
+cpuid (int op, int *eax, int *ebx, int *ecx, int *edx)
+{
+__asm__ ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx):"0" (op), "c"
+ (0));
+}
+
+#ifdef AMD64
+# define local_save_flags(x) asm volatile("pushfq ; popq %0":"=g" (x):)
+# define local_restore_flags(x) asm volatile("pushq %0 ; popfq"::"g" (x):"memory", "cc")
+#else
+# define local_save_flags(x) asm volatile("pushfl ; popl %0":"=g" (x):)
+# define local_restore_flags(x) asm volatile("pushl %0 ; popfl"::"g" (x):"memory", "cc")
+#endif
+
+static inline unsigned long
+read_cr0 (void)
+{
+ unsigned long cr0;
+#ifdef AMD64
+asm ("movq %%cr0,%0":"=r" (cr0));
+#else
+asm ("movl %%cr0,%0":"=r" (cr0));
+#endif
+ return cr0;
+}
+
+static inline void
+write_cr0 (unsigned long val)
+{
+#ifdef AMD64
+ asm ("movq %0,%%cr0"::"r" (val));
+#else
+ asm ("movl %0,%%cr0"::"r" (val));
+#endif
+}
+
+static inline unsigned long
+read_cr4 (void)
+{
+ unsigned long cr4;
+#ifdef AMD64
+asm ("movq %%cr4,%0":"=r" (cr4));
+#else
+asm ("movl %%cr4,%0":"=r" (cr4));
+#endif
+ return cr4;
+}
+
+static inline void
+write_cr4 (unsigned long val)
+{
+#ifdef AMD64
+ asm ("movq %0,%%cr4"::"r" (val));
+#else
+ asm ("movl %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_restore_flags (flags_reg);
+
+ local_save_flags (flags_reg);
+ if (flags_reg & FLAGS_ID)
+ return 0;
+
+ flags_reg |= FLAGS_ID;
+ local_restore_flags (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
+
+typedef struct tmout_desc
+{
+ volatile int active;
+ int timestamp;
+ void (*func) (void *);
+ void *arg;
+
+ WDOG_ID id;
+
+} 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 (int 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);
+ wdDelete(tmout->id);
+}
+
+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);
+
+ if ((tmout->id=wdCreate()) == NULL)
+ return 0;
+
+ wdStart(tmout->id, ticks, (FUNCPTR)oss_timer_callback, (int)tmout->timestamp);
+ 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)
+ {
+ wdCancel(tmout->id);
+ wdDelete(tmout->id);
+ }
+
+ tmout->active = 0;
+ tmout->timestamp = 0;
+}
+
+void
+oss_udelay(unsigned long ticks)
+{
+ // TODO
+}
+
+void *
+oss_contig_malloc (oss_device_t * osdev, int buffsize, oss_uint64_t memlimit,
+ oss_native_word * phaddr)
+{
+ char *start_addr, *end_addr;
+
+ *phaddr = 0;
+
+ start_addr = NULL;
+
+ // TODO: See if there is a previously freed buffer available
+
+ start_addr = (char *) valloc (buffsize);
+
+ 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;
+ }
+
+ *phaddr = (oss_native_word)start_addr;
+ return start_addr;
+}
+
+void
+oss_contig_free (oss_device_t * osdev, void *p, int buffsize)
+{
+ if (p == NULL)
+ return;
+
+ // TODO: Put the freed memory block to available list
+ cmn_err (CE_WARN, "Cannot free %d bytes of DMA buffer\n", buffsize);
+}
+
+int
+__oss_alloc_dmabuf (int dev, dmap_p dmap, unsigned int alloc_flags,
+ oss_uint64_t maxaddr, int direction)
+{
+ void *buf;
+ int err;
+ 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; /* Already done */
+
+ 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;
+
+ dmap->dmabuf = NULL;
+ dmap->buffsize = size;
+
+ err = -1;
+
+ while (err < 0 && dmap->dmabuf == NULL && dmap->buffsize >= 4 * 1024)
+ {
+ if ((buf =
+ oss_contig_malloc (dmap->osdev, dmap->buffsize, maxaddr,
+ &phaddr)) == NULL)
+ {
+ if ((dmap->buffsize = (dmap->buffsize / 2)) < 8 * 1024)
+ return OSS_ENOMEM;
+ cmn_err (CE_CONT, "Dropping DMA buffer size to %d bytes.\n",
+ dmap->buffsize);
+ continue;
+ }
+
+ dmap->dmabuf = buf;
+ dmap->dmabuf_phys = phaddr;
+
+ return 0;
+ }
+
+ return OSS_ENOMEM;
+}
+
+void
+oss_free_dmabuf (int dev, dmap_p dmap)
+{
+ void *buf = dmap->dmabuf;
+
+ if (dmap->dmabuf == NULL)
+ return;
+
+ dmap->dmabuf = NULL;
+ oss_contig_free (NULL, buf, dmap->buffsize);
+ dmap->dmabuf_phys = 0;
+}
+
+/*
+ * Sleep/wakeup
+ */
+
+struct oss_wait_queue
+{
+ volatile int flags;
+ SEM_ID wq;
+};
+
+struct oss_wait_queue *
+oss_create_wait_queue (oss_device_t * osdev, const char *name)
+{
+ struct oss_wait_queue *wq;
+
+ if ((wq = malloc (sizeof (*wq))) == NULL)
+ {
+ oss_cmn_err (CE_WARN, "vmalloc(%d) failed (wq)\n", sizeof (*wq));
+ return NULL;
+ }
+ wq->wq = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
+
+ return wq;
+}
+
+void
+oss_reset_wait_queue (struct oss_wait_queue *wq)
+{
+ // TODO: ?
+}
+
+void
+oss_remove_wait_queue (struct oss_wait_queue *wq)
+{
+ free (wq);
+}
+
+int
+oss_sleep (struct oss_wait_queue *wq, oss_mutex_t * mutex, int ticks,
+ oss_native_word * flags, unsigned int *status)
+{
+ int result;
+
+ *status = 0;
+
+ if (wq == NULL)
+ return 0;
+
+ wq->flags = 0;
+
+ if (ticks <= 0)
+ ticks = WAIT_FOREVER;
+
+ result =
+ semTake(wq->wq, ticks);
+
+ if (result == ERROR) /* 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)
+{
+ // TODO: ?
+ 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;
+ semFlush(wq->wq);
+}
diff --git a/kernel/OS/VxWorks/os_vxworks.h b/kernel/OS/VxWorks/os_vxworks.h
new file mode 100644
index 0000000..275aa34
--- /dev/null
+++ b/kernel/OS/VxWorks/os_vxworks.h
@@ -0,0 +1,297 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+/*
+ * Purpose: OS specific definitions for VxWorks
+ *
+ */
+/*
+ *
+ * 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 "5.5"
+
+#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
+
+#define VDEV_SUPPORT
+#undef USE_DEVICE_SUBDIRS
+
+#define __inline__ inline
+#define __inline inline
+#define EXTERN_C extern "C"
+
+/*
+ * 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
+
+#undef ALLOW_BUFFER_MAPPING
+
+/*
+ * Some integer types
+ */
+#if defined(amd64) || defined(sparc)
+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
+
+typedef long long oss_int64_t; /* Signed 64 bit integer */
+typedef unsigned long long oss_uint64_t; /* Unsigned 64 bit integer */
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include "vxWorks.h"
+#include "iv.h"
+#include "ioLib.h"
+#include "fioLib.h"
+#include "iosLib.h"
+#include "wdLib.h"
+#include "intLib.h"
+#include "tickLib.h"
+#include "errnoLib.h"
+#include "sysLib.h"
+#include "objLib.h"
+#include "vmLib.h"
+#include "semLib.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <oss_errno.h>
+/*
+ * Mutexes
+ */
+typedef int oss_mutex_t;
+#define MUTEX_INIT(osdev, mutex, hier)
+#define MUTEX_CLEANUP(mutex)
+#define MUTEX_ENTER_IRQDISABLE(mutex, flags) {flags=0;mutex=0;}
+#define MUTEX_ENTER(mutex, flags) {flags=0;mutex=0;}
+#define MUTEX_EXIT_IRQRESTORE(mutex, flags) (flags)++
+#define MUTEX_EXIT(mutex, flags) (flags)++
+
+/*
+ * Fileinfo structure
+ */
+struct fileinfo
+{
+ int mode; /* Open mode */
+ int acc_flags;
+};
+#define ISSET_FILE_FLAG(fileinfo, flag) (fileinfo->acc_flags & (flag) ? 1:0)
+
+/*
+ * Misc types
+ */
+typedef int oss_dma_handle_t;
+typedef int oss_poll_event_t;
+typedef int offset_t;
+
+/*
+ * uio_/uiomove()
+ */
+typedef enum uio_rw uio_rw_t;
+typedef struct oss_uio
+{
+ char *ptr;
+ int resid;
+ int kernel_space; /* Set if this uio points to a kernel space buffer */
+ uio_rw_t rw;
+} uio_t;
+extern int oss_uiomove (void *address, size_t nbytes, enum uio_rw rwflag,
+ uio_t * uio_p);
+extern int oss_create_uio (uio_t * uiop, char *buf, size_t count, uio_rw_t rw,
+ int is_kernel);
+#define uiomove oss_uiomove
+
+/*
+ * Error handling
+ */
+#define cmn_err oss_cmn_err
+extern int detect_trace;
+#define DDB(x) if (detect_trace) x
+extern void oss_cmn_err (int level, const char *format, ...);
+#define CE_CONT 0
+#define CE_NOTE 1
+#define CE_WARN 2
+#define CE_PANIC 3
+
+/* Busy wait routine */
+extern void oss_udelay(unsigned long ticks);
+/* System wall timer access */
+#define GET_JIFFIES() tickGet()
+extern inline unsigned int
+__inb (unsigned short port)
+{
+ unsigned int _v;
+ __asm__ __volatile__ ("in" "b" " %" "w" "1,%" "b" "0":"=a" (_v):"d" (port),
+ "0" (0));
+ return _v;
+}
+extern inline unsigned int
+__inw (unsigned short port)
+{
+ unsigned int _v;
+ __asm__ __volatile__ ("in" "w" " %" "w" "1,%" "w" "0":"=a" (_v):"d" (port),
+ "0" (0));
+ return _v;
+}
+extern inline unsigned int
+__inl (unsigned short port)
+{
+ unsigned int _v;
+ __asm__ __volatile__ ("in" "l" " %" "w" "1,%" "" "0":"=a" (_v):"d" (port));
+ return _v;
+}
+
+extern inline void
+__outb (unsigned char value, unsigned short port)
+{
+ __asm__ __volatile__ ("out" "b" " %" "b" "0,%" "w" "1"::"a" (value),
+ "d" (port));
+}
+extern inline void
+__outw (unsigned short value, unsigned short port)
+{
+ __asm__ __volatile__ ("out" "w" " %" "w" "0,%" "w" "1"::"a" (value),
+ "d" (port));
+}
+extern inline void
+__outl (unsigned int value, unsigned short port)
+{
+ __asm__ __volatile__ ("out" "l" " %" "0,%" "w" "1"::"a" (value),
+ "d" (port));
+}
+
+#define INB(osdev,a) __inb(a)
+#define INW(osdev,a) __inw(a)
+#define INL(osdev,a) __inl(a)
+
+#define OUTB(osdev, d, a) __outb(d, a)
+
+#define OUTW(osdev, d, a) __outw(d, a)
+#define OUTL(osdev, d, a) __outl(d, a)
+
+#define PCI_READL(osdev, p) (*(volatile unsigned int *) (p))
+#define PCI_WRITEL(osdev, addr, data) (*(volatile unsigned int *) (addr) = (data))
+#define PCI_READW(osdev, p) (*(volatile unsigned short *) (p))
+#define PCI_WRITEW(osdev, addr, data) (*(volatile unsigned short *) (addr) = (data))
+#define PCI_READB(osdev, p) (*(volatile unsigned char *) (p))
+#define PCI_WRITEB(osdev, addr, data) (*(volatile unsigned char *) (addr) = (data))
+
+#define MAP_PCI_IOADDR(osdev, nr, io) (oss_native_word)io
+#define MAP_PCI_MEM(osdev, ix, phaddr, size) (oss_native_word)phaddr
+#define UNMAP_PCI_MEM(osdev, ix, ph, virt, size) {}
+#define UNMAP_PCI_IOADDR(osdev, ix) {}
+/*
+ * Memory allocation and mapping
+ */
+extern void *oss_contig_malloc (oss_device_t * osdev, int sz,
+ oss_uint64_t memlimit,
+ oss_native_word * phaddr);
+extern void oss_contig_free (oss_device_t * osdev, void *p, int sz);
+extern void oss_reserve_pages (oss_native_word start_addr,
+ oss_native_word end_addr);
+extern void oss_unreserve_pages (oss_native_word start_addr,
+ oss_native_word end_addr);
+
+#define KERNEL_MALLOC(nbytes) malloc(nbytes)
+#define KERNEL_FREE(addr) free(addr)
+#define CONTIG_MALLOC(osdev, sz, memlimit, phaddr, handle) oss_contig_malloc(osdev, sz, memlimit, phaddr)
+#define CONTIG_FREE(osdev, p, sz, handle) oss_contig_free(osdev, p, sz)
+
+typedef void dev_info_t;
+
+struct _oss_device_t
+{
+ int cardnum;
+ int dev_type;
+ int available;
+ int instance;
+ dev_info_t *dip;
+ void *devc;
+ char *name;
+ char nick[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 major;
+ struct module *owner; /* Pointer to THISMODULE (needed by osscore.c) */
+ char modname[32];
+ char *hw_info;
+
+ volatile int refcount; /* Nonzero means that the device is needed by some other (virtual) driver. */
+
+/* Interrupts */
+
+ int iblock_cookie; /* Dummy field under Linux */
+ void *irqparms;
+ int intrcount, ackcount;
+};
+
+typedef struct
+{
+ int bus, dev, func;
+} oss_pci_device_t;
+
+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);
+#define timeout oss_timeout
+#define untimeout oss_untimeout
+
+extern int oss_hz;
+#define HZ oss_hz
+#define OSS_HZ HZ
+
+/*
+ * Dummy defines for poll()
+ */
+#define POLLIN 0
+#define POLLOUT 0
+#define POLLRDNORM 0
+#define POLLWRNORM 0
+
+/*
+ * Process info macros
+ */
+#define GET_PROCESS_PID(x) -1
+#define GET_PROCESS_UID(x) 0
+#define GET_PROCESS_NAME(x) NULL
+
+/*
+ * Floating point save/restore support for vmix
+ */
+#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);
+#undef FP_SAVE
+#undef FP_RESTORE
+# define FP_SAVE(envbuf, flags) oss_fp_save(envbuf, flags)
+# define FP_RESTORE(envbuf, flags) oss_fp_restore(envbuf, flags)
+#endif
+
+#endif