2
* oss_vxworks.c: Common entry points for OSS under VxWorks.
5
#include <oss_config.h>
7
#include <drv/pci/pciConfigLib.h>
12
typedef struct oss_device_handle
16
int valid; /* 1=valid, 0=undefined */
17
struct fileinfo finfo;
22
* Number of cards supported in the same system.
26
static oss_device_t *cards[MAX_CARDS];
27
int oss_num_cards = 0;
29
static int oss_driver_num = ERROR;
30
static int oss_expired = 0;
31
static oss_device_t *core_osdev = NULL;
36
oss_cmn_err (int level, const char *s, ...)
38
char tmp[1024], *a[6];
44
for (i = 0; i < strlen (s); i++)
48
for (i = 0; i < n && i < 6; i++)
49
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] ));
50
//a[i] = va_arg (ap, char *); // This was supposed to be used instead of above. Unfortunately va_arg() seems to be buggy
52
for (i = n; i < 6; i++)
57
sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
63
strcpy (tmp, "osscore: ");
64
sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5],
65
NULL, NULL, NULL, NULL);
74
oss_uiomove (void *addr, size_t nbytes, enum uio_rw rwflag, uio_t * uio)
77
* NOTE! Returns 0 upon success and EFAULT on failure (instead of -EFAULT
78
* (for Solaris/BSD compatibility)).
81
if (rwflag != uio->rw)
83
oss_cmn_err (CE_WARN, "uiomove: Bad direction\n");
87
if (uio->resid < nbytes)
89
oss_cmn_err (CE_WARN, "uiomove: Bad count %d (%d)\n", nbytes,
94
if (uio->kernel_space)
100
memcpy(uio->ptr, addr, nbytes);
104
memcpy(addr, uio->ptr, nbytes);
108
uio->resid -= nbytes;
115
oss_create_uio (uio_t * uio, char *buf, size_t count, uio_rw_t rw,
118
memset (uio, 0, sizeof (*uio));
122
oss_cmn_err (CE_CONT,
123
"oss_create_uio: Kernel space buffers not supported\n");
129
uio->kernel_space = is_kernel;
136
grow_array(oss_device_t *osdev, oss_cdev_t ***arr, int *size, int increment)
138
oss_cdev_t **old=*arr, **new = *arr;
139
int old_size = *size;
140
int new_size = *size;
142
new_size += increment;
144
if ((new=PMALLOC(osdev, new_size * sizeof (oss_cdev_t *)))==NULL)
147
memset(new, 0, new_size * sizeof(oss_cdev_t *));
149
memcpy(new, old, old_size * sizeof(oss_cdev_t *));
161
register_chrdev(oss_cdev_t *cdev, char *name)
163
if (iosDevAdd ((void *)cdev, name, oss_driver_num) == ERROR)
165
cmn_err (CE_WARN, "Failed to add device %s\n", name);
170
oss_install_chrdev (oss_device_t * osdev, char *name, int dev_class,
171
int instance, oss_cdev_drv_t * drv, int flags)
174
* oss_install_chrdev creates a character device (minor). However if
175
* name==NULL the device will not be exported (made visible to userland
180
oss_cdev_t *cdev = NULL;
182
if (dev_class != OSS_DEV_STATUS)
183
if (oss_expired && instance > 0)
186
if (oss_num_cdevs >= OSS_MAX_CDEVS)
188
if (!grow_array(osdev, &oss_cdevs, &oss_max_cdevs, 100))
190
cmn_err (CE_WARN, "Out of minor numbers.\n");
195
if ((cdev = PMALLOC (NULL, sizeof (*cdev))) == NULL)
197
cmn_err (CE_WARN, "Cannot allocate character device desc.\n");
201
num = oss_num_cdevs++;
203
memset (cdev, 0, sizeof (*cdev));
204
cdev->dev_class = dev_class;
205
cdev->instance = instance;
209
strncpy (cdev->name, name, sizeof (cdev->name));
211
strcpy (cdev->name, "NONE");
212
cdev->name[sizeof (cdev->name) - 1] = 0;
213
oss_cdevs[num] = cdev;
216
* Export the device only if name != NULL
220
strcpy (cdev->name, name);
221
register_chrdev (cdev, name);
226
oss_find_minor (int dev_class, int instance)
230
for (i = 0; i < oss_num_cdevs; i++)
232
if (oss_cdevs[i]->d != NULL && oss_cdevs[i]->dev_class == dev_class
233
&& oss_cdevs[i]->instance == instance)
241
cpy_file (int mode, struct fileinfo *fi)
244
fi->acc_flags = mode;
246
if ((fi->acc_flags & O_ACCMODE) == O_RDWR)
247
fi->mode = OPEN_READWRITE;
248
if ((fi->acc_flags & O_ACCMODE) == O_RDONLY)
249
fi->mode = OPEN_READ;
250
if ((fi->acc_flags & O_ACCMODE) == O_WRONLY)
251
fi->mode = OPEN_WRITE;
257
ossOpen (oss_cdev_t *cdev, char *reminder, int mode)
262
cpy_file (mode, &fi);
265
(CE_CONT, "ossOpen(%p): %s, class=%d, instance=%d\n", cdev,
266
cdev->name, cdev->dev_class, cdev->instance));
268
if (cdev->d->open == NULL)
276
cdev->d->open (cdev->instance, cdev->dev_class, &fi, 0, 0, &tmpdev);
286
if (tmpdev >= 0 && tmpdev < oss_num_cdevs)
288
cdev = oss_cdevs[tmpdev];
298
memcpy(&cdev->file, &fi, sizeof(struct fileinfo));
304
ossClose (oss_cdev_t *cdev)
306
if (cdev->d->close == NULL)
311
cdev->d->close (cdev->instance, &cdev->file);
317
ossRead (oss_cdev_t *cdev, char *buf, int count)
322
if (cdev->d->read == NULL)
328
if ((err = oss_create_uio (&uio, buf, count, UIO_READ, 0)) < 0)
334
len = cdev->d->read (cdev->instance, &cdev->file, &uio, count);
344
ossWrite (oss_cdev_t *cdev, char *buf, int count)
349
if (cdev->d->write == NULL)
355
if ((err = oss_create_uio (&uio, buf, count, UIO_WRITE, 0)) < 0)
361
len = cdev->d->write (cdev->instance, &cdev->file, &uio, count);
371
ossIoctl (oss_cdev_t *cdev, int cmd, int *arg)
375
if (cdev->d->ioctl == NULL)
381
if ((err = cdev->d->ioctl (cdev->instance, &cdev->file, cmd, (ioctl_arg) arg)) < 0)
390
osdev_create (dev_info_t * dip, int dev_type,
391
int instance, const char *nick, const char *handle)
395
osdev = PMALLOC (NULL, sizeof (*osdev));
398
cmn_err (CE_WARN, "osdev_create: Out of memory\n");
402
memset (osdev, 0, sizeof (*osdev));
404
sprintf (osdev->nick, "%s%d", nick, instance);
405
osdev->instance = instance;
407
osdev->available = 1;
408
osdev->first_mixer = -1;
410
strcpy (osdev->modname, nick);
415
if (oss_num_cards >= MAX_CARDS)
416
cmn_err (CE_WARN, "Too many OSS devices. At most %d permitted.\n",
420
osdev->cardnum = oss_num_cards;
421
cards[oss_num_cards++] = osdev;
424
* Create the device handle
432
unsigned int subvendor;
434
devpath = oss_pci_read_devpath (osdev->dip);
435
oss_pci_read_config_dword (osdev, 0x2c, &subvendor);
437
sprintf (osdev->handle, "PCI%08x-%s", subvendor, devpath);
439
strcpy(osdev->handle, "PCICARD");
445
// TODO: Get the vendor information
446
sprintf (osdev->handle, "USB-%s%d", handle, instance);
450
sprintf (osdev->handle, "%s%d", handle, instance);
457
osdev_clone (oss_device_t * orig_osdev, int new_instance)
461
osdev = PMALLOC (NULL, sizeof (*osdev));
464
cmn_err (CE_WARN, "osdev_create: Out of memory\n");
467
memcpy (osdev, orig_osdev, sizeof (*osdev));
468
osdev->dev_type = DRV_CLONE;
469
osdev->instance = new_instance;
470
sprintf (osdev->nick, "%s%d", orig_osdev->modname, new_instance);
471
sprintf (osdev->handle, "%s%d", orig_osdev->modname, new_instance);
477
osdev_delete (oss_device_t * osdev)
484
osdev->available = 0;
486
* Mark all minor nodes for this module as invalid.
488
for (i = 0; i < oss_num_cdevs; i++)
489
if (oss_cdevs[i]->osdev == osdev)
491
oss_cdevs[i]->d = NULL;
492
oss_cdevs[i]->osdev = NULL;
493
strcpy (oss_cdevs[i]->name, "Removed device");
498
oss_get_osid (oss_device_t * osdev)
504
oss_register_device (oss_device_t * osdev, const char *name)
508
cmn_err (CE_WARN, "oss_register_device: name==NULL\n");
509
osdev->name = "Undefined name";
513
if ((osdev->name = PMALLOC (NULL, strlen (name) + 1)) == NULL)
515
cmn_err (CE_WARN, "Cannot allocate memory for device name\n");
516
osdev->name = "Unknown device";
518
strcpy (osdev->name, name);
523
oss_unregister_device (oss_device_t * osdev)
526
* Notice! The driver calling this routine (the owner of the osdev parameter)
527
* has already uninitialized itself. Do not do any actions that may call this
528
* driver directly or indirectly.
531
// TODO: Move this to some common OSS module (also under Solaris)
535
oss_get_cardinfo (int cardnum, oss_card_info * ci)
538
* Print information about a 'card' in a format suitable for /dev/sndstat
541
if (cardnum < 0 || cardnum >= oss_num_cards)
544
if (cards[cardnum]->name != NULL)
545
strncpy (ci->longname, cards[cardnum]->name, 128);
546
ci->longname[127] = 0;
548
if (cards[cardnum]->nick != NULL)
549
strncpy (ci->shortname, cards[cardnum]->nick, 16);
550
ci->shortname[15] = 0;
552
if (cards[cardnum]->hw_info != NULL)
553
strncpy (ci->hw_info, cards[cardnum]->hw_info, sizeof (ci->hw_info));
554
ci->hw_info[sizeof (ci->hw_info) - 1] = 0;
555
ci->intr_count = cards[cardnum]->intrcount;
556
ci->ack_count = cards[cardnum]->ackcount;
564
oss_hz = sysClkRateGet();
566
if (oss_driver_num != ERROR)
568
cmn_err (CE_WARN, "OSS is already running\n");
572
#ifdef LICENSED_VERSION
573
if (!oss_license_handle_time (oss_get_time ()))
575
cmn_err (CE_WARN, "This version of Open Sound System has expired\n");
577
"Please download the latest version from www.opensound.com\n");
583
oss_driver_num = iosDrvInstall ((FUNCPTR) NULL, /* create */
584
(FUNCPTR) NULL, /* delete */
585
(FUNCPTR) ossOpen, (FUNCPTR) ossClose, (FUNCPTR) ossRead, (FUNCPTR) ossWrite, (FUNCPTR) ossIoctl /* ioctl */
587
if (oss_driver_num == ERROR)
589
cmn_err (CE_WARN, "Module osscore failed to install\n");
594
osdev_create (NULL, DRV_UNKNOWN, 0, "osscore", NULL)) == NULL)
596
oss_cmn_err (CE_WARN, "Failed to allocate OSDEV structure\n");
599
oss_register_device (core_osdev, "OSS core services");
601
oss_common_init (core_osdev);
603
return oss_driver_num;
615
if (oss_driver_num == ERROR)
618
for (i = 0; i < SND_NDEVS; i++)
619
if (oss_files[i].valid)
621
iosDevDelete (&oss_files[i].devHdr);
622
oss_files[i].valid = 0;
625
if (iosDrvRemove (oss_driver_num, FALSE) == ERROR)
627
cmn_err (CE_WARN, "Driver busy - cannot remove.\n");
632
oss_unload_drivers ();
634
oss_driver_num = ERROR; /* Mark it free */
639
#ifdef CONFIG_OSS_VMIX_FLOAT
643
#define FP_SAVE(envbuf) asm ("fnsave %0":"=m" (*envbuf));
644
#define FP_RESTORE(envbuf) asm ("frstor %0":"=m" (*envbuf));
646
/* SSE/SSE2 compatible macros */
647
#define FX_SAVE(envbuf) asm ("fxsave %0":"=m" (*envbuf));
648
#define FX_RESTORE(envbuf) asm ("fxrstor %0":"=m" (*envbuf));
650
static int old_arch = 0; /* No SSE/SSE2 instructions */
652
#if defined(__amd64__)
657
cpuid (int op, int *eax, int *ebx, int *ecx, int *edx)
659
__asm__ ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx):"0" (op), "c"
664
# define local_save_flags(x) asm volatile("pushfq ; popq %0":"=g" (x):)
665
# define local_restore_flags(x) asm volatile("pushq %0 ; popfq"::"g" (x):"memory", "cc")
667
# define local_save_flags(x) asm volatile("pushfl ; popl %0":"=g" (x):)
668
# define local_restore_flags(x) asm volatile("pushl %0 ; popfl"::"g" (x):"memory", "cc")
671
static inline unsigned long
676
asm ("movq %%cr0,%0":"=r" (cr0));
678
asm ("movl %%cr0,%0":"=r" (cr0));
684
write_cr0 (unsigned long val)
687
asm ("movq %0,%%cr0"::"r" (val));
689
asm ("movl %0,%%cr0"::"r" (val));
693
static inline unsigned long
698
asm ("movq %%cr4,%0":"=r" (cr4));
700
asm ("movl %%cr4,%0":"=r" (cr4));
706
write_cr4 (unsigned long val)
709
asm ("movq %0,%%cr4"::"r" (val));
711
asm ("movl %0,%%cr4"::"r" (val));
714
static inline unsigned long long
717
unsigned long long mxcsr;
718
asm volatile ("stmxcsr %0":"=m" (mxcsr));
723
write_mxcsr (unsigned long long val)
725
asm volatile ("ldmxcsr %0"::"m" (val));
731
int eax, ebx, ecx, edx;
732
#define FLAGS_ID (1<<21)
734
oss_native_word flags_reg;
736
local_save_flags (flags_reg);
737
flags_reg &= ~FLAGS_ID;
738
local_restore_flags (flags_reg);
740
local_save_flags (flags_reg);
741
if (flags_reg & FLAGS_ID)
744
flags_reg |= FLAGS_ID;
745
local_restore_flags (flags_reg);
747
local_save_flags (flags_reg);
748
if (!(flags_reg & FLAGS_ID))
751
//#define CPUID_FXSR (1<<24)
752
//#define CPUID_SSE (1<<25)
753
//#define CPUID_SSE2 (1<<26)
755
cpuid (1, &eax, &ebx, &ecx, &edx);
757
if (!(edx & CPUID_FXSR))
761
* Older machines require different FP handling than the latest ones. Use the SSE
762
* instruction set as an indicator.
764
if (!(edx & CPUID_SSE))
771
oss_fp_save (short *envbuf, unsigned int flags[])
773
flags[0] = read_cr0 ();
774
write_cr0 (flags[0] & ~0x0e); /* Clear CR0.TS/MP/EM */
782
flags[1] = read_cr4 ();
783
write_cr4 (flags[1] | 0x600); /* Set OSFXSR & OSXMMEXCEPT */
787
write_mxcsr (0x1f80);
789
flags[2] = read_cr0 ();
793
oss_fp_restore (short *envbuf, unsigned int flags[])
803
write_cr4 (flags[1]); /* Restore cr4 */
805
write_cr0 (flags[0]); /* Restore cr0 */
809
typedef struct tmout_desc
813
void (*func) (void *);
820
static volatile int next_id = 0;
821
#define MAX_TMOUTS 128
823
tmout_desc_t tmouts[MAX_TMOUTS] = { {0} };
825
int timeout_random = 0x12123400;
828
oss_timer_callback (int id)
837
if (ix < 0 || ix >= MAX_TMOUTS)
841
if (tmout->timestamp != id) /* Expired timer */
849
tmout->timestamp = 0;
856
oss_timeout (void (*func) (void *), void *arg,
857
unsigned long long ticks)
860
tmout_desc_t *tmout = NULL;
868
while (id == -1 && n < MAX_TMOUTS)
870
if (!tmouts[next_id].active)
872
tmouts[next_id].active = 1;
878
next_id = (next_id + 1) % MAX_TMOUTS;
881
if (id == -1) /* No timer slots available */
883
oss_cmn_err (CE_WARN, "Timeout table full\n");
889
tmout->timestamp = id | (timeout_random & ~0xff);
891
if ((tmout->id=wdCreate()) == NULL)
894
wdStart(tmout->id, ticks, (FUNCPTR)oss_timer_callback, (int)tmout->timestamp);
895
return id | (timeout_random & ~0xff);
899
oss_untimeout (timeout_id_t id)
905
if (ix < 0 || ix >= MAX_TMOUTS)
911
if (tmout->timestamp != id) /* Expired timer */
920
tmout->timestamp = 0;
924
oss_udelay(unsigned long ticks)
930
oss_contig_malloc (oss_device_t * osdev, int buffsize, oss_uint64_t memlimit,
931
oss_native_word * phaddr)
933
char *start_addr, *end_addr;
939
// TODO: See if there is a previously freed buffer available
941
start_addr = (char *) valloc (buffsize);
943
if (start_addr == NULL)
945
cmn_err (CE_NOTE, "Failed to allocate memory buffer of %d bytes\n",
951
/* make some checks */
952
end_addr = start_addr + buffsize - 1;
955
*phaddr = (oss_native_word)start_addr;
960
oss_contig_free (oss_device_t * osdev, void *p, int buffsize)
965
// TODO: Put the freed memory block to available list
966
cmn_err (CE_WARN, "Cannot free %d bytes of DMA buffer\n", buffsize);
970
__oss_alloc_dmabuf (int dev, dmap_p dmap, unsigned int alloc_flags,
971
oss_uint64_t maxaddr, int direction)
975
oss_native_word phaddr;
976
int size = 64 * 1024;
977
extern int dma_buffsize;
979
if (dma_buffsize > 16 && dma_buffsize <= 128)
980
size = dma_buffsize * 1024;
982
if (dmap->dmabuf != NULL)
983
return 0; /* Already done */
987
cmn_err (CE_WARN, "oss_alloc_dmabuf: dmap==NULL\n");
992
* Some applications and virtual drivers need shorter buffer.
994
if (dmap->flags & DMAP_SMALLBUF)
996
size = SMALL_DMABUF_SIZE;
998
else if (dmap->flags & DMAP_MEDIUMBUF)
1000
size = MEDIUM_DMABUF_SIZE;
1003
if ((alloc_flags & DMABUF_SIZE_16BITS) && size > 32 * 1024)
1006
dmap->dmabuf = NULL;
1007
dmap->buffsize = size;
1011
while (err < 0 && dmap->dmabuf == NULL && dmap->buffsize >= 4 * 1024)
1014
oss_contig_malloc (dmap->osdev, dmap->buffsize, maxaddr,
1017
if ((dmap->buffsize = (dmap->buffsize / 2)) < 8 * 1024)
1019
cmn_err (CE_CONT, "Dropping DMA buffer size to %d bytes.\n",
1025
dmap->dmabuf_phys = phaddr;
1034
oss_free_dmabuf (int dev, dmap_p dmap)
1036
void *buf = dmap->dmabuf;
1038
if (dmap->dmabuf == NULL)
1041
dmap->dmabuf = NULL;
1042
oss_contig_free (NULL, buf, dmap->buffsize);
1043
dmap->dmabuf_phys = 0;
1050
struct oss_wait_queue
1056
struct oss_wait_queue *
1057
oss_create_wait_queue (oss_device_t * osdev, const char *name)
1059
struct oss_wait_queue *wq;
1061
if ((wq = malloc (sizeof (*wq))) == NULL)
1063
oss_cmn_err (CE_WARN, "vmalloc(%d) failed (wq)\n", sizeof (*wq));
1066
wq->wq = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
1072
oss_reset_wait_queue (struct oss_wait_queue *wq)
1078
oss_remove_wait_queue (struct oss_wait_queue *wq)
1084
oss_sleep (struct oss_wait_queue *wq, oss_mutex_t * mutex, int ticks,
1085
oss_native_word * flags, unsigned int *status)
1097
ticks = WAIT_FOREVER;
1100
semTake(wq->wq, ticks);
1102
if (result == ERROR) /* Signal received */
1104
*status |= WK_SIGNAL;
1108
if (!(wq->flags & WK_WAKEUP)) /* Timeout */
1117
oss_register_poll (struct oss_wait_queue *wq, oss_mutex_t * mutex,
1118
oss_native_word * flags, oss_poll_event_t * ev)
1125
oss_wakeup (struct oss_wait_queue *wq, oss_mutex_t * mutex,
1126
oss_native_word * flags, short events)
1131
wq->flags |= WK_WAKEUP;