diff options
Diffstat (limited to 'kernel/OS/VxWorks')
-rw-r--r-- | kernel/OS/VxWorks/.config | 1 | ||||
-rw-r--r-- | kernel/OS/VxWorks/linux/ioctl.h | 5 | ||||
-rw-r--r-- | kernel/OS/VxWorks/module.inc | 127 | ||||
-rw-r--r-- | kernel/OS/VxWorks/os_vxworks.c | 1133 | ||||
-rw-r--r-- | kernel/OS/VxWorks/os_vxworks.h | 297 |
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 |