~ubuntu-branches/ubuntu/wily/oss4/wily

« back to all changes in this revision

Viewing changes to kernel/OS/VxWorks/os_vxworks.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis, Samuel Thibault, Romain Beauxis, Sebastien NOEL
  • Date: 2011-06-14 10:06:56 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110614100656-cx4oc7u426zn812z
Tags: 4.2-build2004-1
[ Samuel Thibault ]
* debian/control: Add liboss4-salsa2, liboss4-salsa-dev and
  liboss4-salsa-asound2 packages, equivalent to (and will replace) those from
  the oss-libsalsa package (Closes: #589127).
* debian/patches/liboss4-salsa.patch: New patch to rename libsalsa into
  liboss4-salsa to avoid conflicts in the archive for no good reason.
* debian/rules: Make in libOSSlib and libsalsa.
* debian/liboss4-salsa-dev.install, debian/liboss4-salsa2.install,
  debian/liboss4-salsa-asound2.links, debian/liboss4-salsa-dev.links:
  Install liboss4-salsa libraries like was done in the oss-libsalsa package.
* include-alsa: Add a copy of ALSA 1.0.5 headers: Cf ALSA_1.0.* symbols in
  libsalsa, this is the roughly supported version.
* debian/copyright: Update for new include-alsa files.
* alsa.pc: New file for compatibility with libasound-dev.
* debian/control:
  - Add Vcs-Browser and Vcs-Svn fields.
  - Use linux-any instead of the list of Linux archs (Closes: #604679).
  - Make dkms dependency linux-any only.
* debian/patches/hurd_iot.patch: New patch to fix soundcard.h usage in
  libsalsa on hurd-i386.
* debian/patches/libsalsa_fixes.patch: New patch to fix some printf usages
  and ioctl declaration in libsalsa.
* debian/patches/no_EBADE.patch: New patch to cope with hurd-i386 not having
  EBADE.
* debian/patches/CFLAGS.patch: New patch to make oss4 take debian/rules
  CFLAGS into account.
* debian/patches/snd_asoundlib_version.patch: New patch to add
  snd_asoundlib_version().
* debian/patches/generic_srccconf.patch: New patch to fix source
  configuration on unknown archs.

[ Romain Beauxis ]
* Fixed README.Debian to only mention dkms' modules.
* Switch to dpkg-source 3.0 (quilt) format
* Added DM-Upload-Allowed: yes

[ Sebastien NOEL ]
* New upstream release (Closes: #595298, #619272).
* Fix typo in initscript (Closes: #627149).
* debian/control: adjust linux-headers dependencies (Closes: #628879).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * oss_vxworks.c: Common entry points for OSS under VxWorks.
 
3
 */
 
4
 
 
5
#include <oss_config.h>
 
6
#include <oss_pci.h>
 
7
#include <drv/pci/pciConfigLib.h>
 
8
#include <memLib.h>
 
9
 
 
10
#if 0
 
11
// TODO: Obsolete
 
12
typedef struct oss_device_handle
 
13
{
 
14
  DEV_HDR devHdr;
 
15
  int minor;
 
16
  int valid;                    /* 1=valid, 0=undefined */
 
17
  struct fileinfo finfo;
 
18
}
 
19
oss_device_handle;
 
20
#endif
 
21
/*
 
22
 * Number of cards supported in the same system.
 
23
 */
 
24
#define MAX_CARDS 8
 
25
 
 
26
static oss_device_t *cards[MAX_CARDS];
 
27
int oss_num_cards = 0;
 
28
 
 
29
static int oss_driver_num = ERROR;
 
30
static int oss_expired = 0;
 
31
static oss_device_t *core_osdev = NULL;
 
32
 
 
33
int oss_hz = 100;
 
34
 
 
35
void
 
36
oss_cmn_err (int level, const char *s, ...)
 
37
{
 
38
  char tmp[1024], *a[6];
 
39
  va_list ap;
 
40
  int i, n = 0;
 
41
 
 
42
  va_start (ap, s);
 
43
 
 
44
  for (i = 0; i < strlen (s); i++)
 
45
    if (s[i] == '%')
 
46
      n++;
 
47
 
 
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
 
51
 
 
52
  for (i = n; i < 6; i++)
 
53
    a[i] = NULL;
 
54
 
 
55
  if (level == CE_CONT)
 
56
    {
 
57
      sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
 
58
               NULL, NULL, NULL);
 
59
      printf ("%s", tmp);
 
60
    }
 
61
  else
 
62
    {
 
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);
 
66
 
 
67
      printf ("%s", tmp);
 
68
    }
 
69
 
 
70
  va_end (ap);
 
71
}
 
72
 
 
73
int
 
74
oss_uiomove (void *addr, size_t nbytes, enum uio_rw rwflag, uio_t * uio)
 
75
{
 
76
/*
 
77
 * NOTE! Returns 0 upon success and EFAULT on failure (instead of -EFAULT
 
78
 * (for Solaris/BSD compatibility)).
 
79
 */
 
80
 
 
81
  if (rwflag != uio->rw)
 
82
    {
 
83
      oss_cmn_err (CE_WARN, "uiomove: Bad direction\n");
 
84
      return EFAULT;
 
85
    }
 
86
 
 
87
  if (uio->resid < nbytes)
 
88
    {
 
89
      oss_cmn_err (CE_WARN, "uiomove: Bad count %d (%d)\n", nbytes,
 
90
                   uio->resid);
 
91
      return EFAULT;
 
92
    }
 
93
 
 
94
  if (uio->kernel_space)
 
95
    return EFAULT;
 
96
 
 
97
  switch (rwflag)
 
98
    {
 
99
    case UIO_READ:
 
100
      memcpy(uio->ptr, addr, nbytes);
 
101
      break;
 
102
 
 
103
    case UIO_WRITE:
 
104
      memcpy(addr, uio->ptr, nbytes);
 
105
      break;
 
106
    }
 
107
 
 
108
  uio->resid -= nbytes;
 
109
  uio->ptr += nbytes;
 
110
 
 
111
  return 0;
 
112
}
 
113
 
 
114
int
 
115
oss_create_uio (uio_t * uio, char *buf, size_t count, uio_rw_t rw,
 
116
                int is_kernel)
 
117
{
 
118
  memset (uio, 0, sizeof (*uio));
 
119
 
 
120
  if (is_kernel)
 
121
    {
 
122
      oss_cmn_err (CE_CONT,
 
123
                   "oss_create_uio: Kernel space buffers not supported\n");
 
124
      return -EIO;
 
125
    }
 
126
 
 
127
  uio->ptr = buf;
 
128
  uio->resid = count;
 
129
  uio->kernel_space = is_kernel;
 
130
  uio->rw = rw;
 
131
 
 
132
  return 0;
 
133
}
 
134
 
 
135
static int
 
136
grow_array(oss_device_t *osdev, oss_cdev_t ***arr, int *size, int increment)
 
137
{
 
138
        oss_cdev_t **old=*arr, **new = *arr;
 
139
        int old_size = *size;
 
140
        int new_size = *size;
 
141
                
 
142
        new_size += increment;
 
143
 
 
144
        if ((new=PMALLOC(osdev, new_size * sizeof (oss_cdev_t *)))==NULL)
 
145
           return 0;
 
146
 
 
147
        memset(new, 0, new_size * sizeof(oss_cdev_t *));
 
148
        if (old != NULL)
 
149
           memcpy(new, old, old_size * sizeof(oss_cdev_t *));
 
150
 
 
151
        *size = new_size;
 
152
        *arr = new;
 
153
 
 
154
        if (old != NULL)
 
155
           PMFREE(osdev, old);
 
156
 
 
157
        return 1;
 
158
}
 
159
 
 
160
static void
 
161
register_chrdev(oss_cdev_t *cdev, char *name)
 
162
{
 
163
    if (iosDevAdd ((void *)cdev, name, oss_driver_num) == ERROR)
 
164
      {
 
165
        cmn_err (CE_WARN, "Failed to add device %s\n", name);
 
166
      }
 
167
}
 
168
 
 
169
void
 
170
oss_install_chrdev (oss_device_t * osdev, char *name, int dev_class,
 
171
                    int instance, oss_cdev_drv_t * drv, int flags)
 
172
{
 
173
/*
 
174
 * oss_install_chrdev creates a character device (minor). However if
 
175
 * name==NULL the device will not be exported (made visible to userland
 
176
 * clients).
 
177
 */
 
178
 
 
179
  int num;
 
180
  oss_cdev_t *cdev = NULL;
 
181
 
 
182
  if (dev_class != OSS_DEV_STATUS)
 
183
    if (oss_expired && instance > 0)
 
184
      return;
 
185
 
 
186
      if (oss_num_cdevs >= OSS_MAX_CDEVS)
 
187
        {
 
188
           if (!grow_array(osdev, &oss_cdevs, &oss_max_cdevs, 100))
 
189
           {
 
190
                cmn_err (CE_WARN, "Out of minor numbers.\n");
 
191
                return;
 
192
           }
 
193
        }
 
194
 
 
195
      if ((cdev = PMALLOC (NULL, sizeof (*cdev))) == NULL)
 
196
        {
 
197
          cmn_err (CE_WARN, "Cannot allocate character device desc.\n");
 
198
          return;
 
199
        }
 
200
 
 
201
      num = oss_num_cdevs++;
 
202
 
 
203
  memset (cdev, 0, sizeof (*cdev));
 
204
  cdev->dev_class = dev_class;
 
205
  cdev->instance = instance;
 
206
  cdev->d = drv;
 
207
  cdev->osdev = osdev;
 
208
  if (name != NULL)
 
209
    strncpy (cdev->name, name, sizeof (cdev->name));
 
210
  else
 
211
    strcpy (cdev->name, "NONE");
 
212
  cdev->name[sizeof (cdev->name) - 1] = 0;
 
213
  oss_cdevs[num] = cdev;
 
214
 
 
215
/*
 
216
 * Export the device only if name != NULL
 
217
 */
 
218
  if (name != NULL)
 
219
    {
 
220
      strcpy (cdev->name, name);
 
221
      register_chrdev (cdev, name);
 
222
    }
 
223
}
 
224
 
 
225
int
 
226
oss_find_minor (int dev_class, int instance)
 
227
{
 
228
  int i;
 
229
 
 
230
  for (i = 0; i < oss_num_cdevs; i++)
 
231
    {
 
232
      if (oss_cdevs[i]->d != NULL && oss_cdevs[i]->dev_class == dev_class
 
233
          && oss_cdevs[i]->instance == instance)
 
234
        return i;
 
235
    }
 
236
 
 
237
  return OSS_ENXIO;
 
238
}
 
239
 
 
240
static inline int
 
241
cpy_file (int mode, struct fileinfo *fi)
 
242
{
 
243
  fi->mode = 0;
 
244
  fi->acc_flags = mode;
 
245
 
 
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;
 
252
 
 
253
  return fi->mode;
 
254
}
 
255
 
 
256
static void *
 
257
ossOpen (oss_cdev_t *cdev, char *reminder, int mode)
 
258
{
 
259
  int tmpdev, retval;
 
260
  struct fileinfo fi;
 
261
 
 
262
  cpy_file (mode, &fi);
 
263
 
 
264
  DDB (cmn_err
 
265
       (CE_CONT, "ossOpen(%p): %s, class=%d, instance=%d\n", cdev,
 
266
        cdev->name, cdev->dev_class, cdev->instance));
 
267
 
 
268
  if (cdev->d->open == NULL)
 
269
    {
 
270
      errnoSet(ENODEV);
 
271
      return (void*)ERROR;
 
272
    }
 
273
 
 
274
  tmpdev = -1;
 
275
  retval =
 
276
    cdev->d->open (cdev->instance, cdev->dev_class, &fi, 0, 0, &tmpdev);
 
277
 
 
278
  if (retval < 0)
 
279
    {
 
280
      errnoSet(-retval);
 
281
      return (void*)ERROR;
 
282
    }
 
283
 
 
284
  if (tmpdev != -1)
 
285
  {
 
286
     if (tmpdev >= 0 && tmpdev < oss_num_cdevs)
 
287
        {
 
288
             cdev = oss_cdevs[tmpdev];
 
289
        }
 
290
     else
 
291
        {
 
292
                errnoSet(ENODEV);
 
293
                return (void*)ERROR;
 
294
        }
 
295
  }
 
296
 
 
297
  errnoSet (0);
 
298
  memcpy(&cdev->file, &fi, sizeof(struct fileinfo));
 
299
 
 
300
  return cdev;
 
301
}
 
302
 
 
303
static int
 
304
ossClose (oss_cdev_t *cdev)
 
305
{
 
306
  if (cdev->d->close == NULL)
 
307
    {
 
308
      return OK;
 
309
    }
 
310
 
 
311
  cdev->d->close (cdev->instance, &cdev->file);
 
312
 
 
313
  return OK;
 
314
}
 
315
 
 
316
static int
 
317
ossRead (oss_cdev_t *cdev, char *buf, int count)
 
318
{
 
319
  int err, len;
 
320
  uio_t uio;
 
321
 
 
322
  if (cdev->d->read == NULL)
 
323
    {
 
324
      errnoSet (ENXIO);
 
325
      return ERROR;
 
326
    }
 
327
 
 
328
  if ((err = oss_create_uio (&uio, buf, count, UIO_READ, 0)) < 0)
 
329
    {
 
330
      errnoSet (-err);
 
331
      return ERROR;
 
332
    }
 
333
 
 
334
  len = cdev->d->read (cdev->instance, &cdev->file, &uio, count);
 
335
 
 
336
  if (len >= 0)
 
337
     return len;
 
338
 
 
339
  errnoSet (-len);
 
340
  return ERROR;
 
341
}
 
342
 
 
343
static int
 
344
ossWrite (oss_cdev_t *cdev, char *buf, int count)
 
345
{
 
346
  int err, len;
 
347
  uio_t uio;
 
348
 
 
349
  if (cdev->d->write == NULL)
 
350
    {
 
351
      errnoSet (ENXIO);
 
352
      return ERROR;
 
353
    }
 
354
 
 
355
  if ((err = oss_create_uio (&uio, buf, count, UIO_WRITE, 0)) < 0)
 
356
    {
 
357
      errnoSet (-err);
 
358
      return ERROR;
 
359
    }
 
360
 
 
361
  len = cdev->d->write (cdev->instance, &cdev->file, &uio, count);
 
362
 
 
363
  if (len >= 0)
 
364
     return len;
 
365
 
 
366
  errnoSet (-len);
 
367
  return ERROR;
 
368
}
 
369
 
 
370
static int
 
371
ossIoctl (oss_cdev_t *cdev, int cmd, int *arg)
 
372
{
 
373
  int err;
 
374
 
 
375
  if (cdev->d->ioctl == NULL)
 
376
  {
 
377
      errnoSet (ENXIO);
 
378
      return ERROR;
 
379
  }
 
380
 
 
381
  if ((err = cdev->d->ioctl (cdev->instance, &cdev->file, cmd, (ioctl_arg) arg)) < 0)
 
382
    {
 
383
      errnoSet (-err);
 
384
      return ERROR;
 
385
    }
 
386
  return OK;
 
387
}
 
388
 
 
389
oss_device_t *
 
390
osdev_create (dev_info_t * dip, int dev_type,
 
391
              int instance, const char *nick, const char *handle)
 
392
{
 
393
  oss_device_t *osdev;
 
394
 
 
395
  osdev = PMALLOC (NULL, sizeof (*osdev));
 
396
  if (osdev == NULL)
 
397
    {
 
398
      cmn_err (CE_WARN, "osdev_create: Out of memory\n");
 
399
      return NULL;
 
400
    }
 
401
 
 
402
  memset (osdev, 0, sizeof (*osdev));
 
403
 
 
404
  sprintf (osdev->nick, "%s%d", nick, instance);
 
405
  osdev->instance = instance;
 
406
  osdev->dip = dip;
 
407
  osdev->available = 1;
 
408
  osdev->first_mixer = -1;
 
409
 
 
410
  strcpy (osdev->modname, nick);
 
411
 
 
412
  if (handle == NULL)
 
413
    handle = nick;
 
414
 
 
415
  if (oss_num_cards >= MAX_CARDS)
 
416
    cmn_err (CE_WARN, "Too many OSS devices. At most %d permitted.\n",
 
417
             MAX_CARDS);
 
418
  else
 
419
    {
 
420
      osdev->cardnum = oss_num_cards;
 
421
      cards[oss_num_cards++] = osdev;
 
422
    }
 
423
/*
 
424
 * Create the device handle
 
425
 */
 
426
  switch (dev_type)
 
427
    {
 
428
    case DRV_PCI:
 
429
      {
 
430
#if 0
 
431
        // TODO
 
432
        unsigned int subvendor;
 
433
        char *devpath;
 
434
        devpath = oss_pci_read_devpath (osdev->dip);
 
435
        oss_pci_read_config_dword (osdev, 0x2c, &subvendor);
 
436
 
 
437
        sprintf (osdev->handle, "PCI%08x-%s", subvendor, devpath);
 
438
#else
 
439
        strcpy(osdev->handle, "PCICARD");
 
440
#endif
 
441
      }
 
442
      break;
 
443
 
 
444
    case DRV_USB:
 
445
      // TODO: Get the vendor information
 
446
      sprintf (osdev->handle, "USB-%s%d", handle, instance);
 
447
      break;
 
448
 
 
449
    default:
 
450
      sprintf (osdev->handle, "%s%d", handle, instance);
 
451
    }
 
452
 
 
453
  return osdev;
 
454
}
 
455
 
 
456
oss_device_t *
 
457
osdev_clone (oss_device_t * orig_osdev, int new_instance)
 
458
{
 
459
  oss_device_t *osdev;
 
460
 
 
461
  osdev = PMALLOC (NULL, sizeof (*osdev));
 
462
  if (osdev == NULL)
 
463
    {
 
464
      cmn_err (CE_WARN, "osdev_create: Out of memory\n");
 
465
      return NULL;
 
466
    }
 
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);
 
472
 
 
473
  return osdev;
 
474
}
 
475
 
 
476
void
 
477
osdev_delete (oss_device_t * osdev)
 
478
{
 
479
  int i;
 
480
 
 
481
  if (osdev == NULL)
 
482
    return;
 
483
 
 
484
  osdev->available = 0;
 
485
/*
 
486
 * Mark all minor nodes for this module as invalid.
 
487
 */
 
488
  for (i = 0; i < oss_num_cdevs; i++)
 
489
    if (oss_cdevs[i]->osdev == osdev)
 
490
      {
 
491
        oss_cdevs[i]->d = NULL;
 
492
        oss_cdevs[i]->osdev = NULL;
 
493
        strcpy (oss_cdevs[i]->name, "Removed device");
 
494
      }
 
495
}
 
496
 
 
497
void *
 
498
oss_get_osid (oss_device_t * osdev)
 
499
{
 
500
  return NULL;                  // TODO
 
501
}
 
502
 
 
503
int
 
504
oss_register_device (oss_device_t * osdev, const char *name)
 
505
{
 
506
  if (name == NULL)
 
507
    {
 
508
      cmn_err (CE_WARN, "oss_register_device: name==NULL\n");
 
509
      osdev->name = "Undefined name";
 
510
      return 0;
 
511
    }
 
512
 
 
513
  if ((osdev->name = PMALLOC (NULL, strlen (name) + 1)) == NULL)
 
514
    {
 
515
      cmn_err (CE_WARN, "Cannot allocate memory for device name\n");
 
516
      osdev->name = "Unknown device";
 
517
    }
 
518
  strcpy (osdev->name, name);
 
519
  return 0;
 
520
}
 
521
 
 
522
void
 
523
oss_unregister_device (oss_device_t * osdev)
 
524
{
 
525
/*
 
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.
 
529
 */
 
530
 
 
531
// TODO: Move this to some common OSS module (also under Solaris)
 
532
}
 
533
 
 
534
int
 
535
oss_get_cardinfo (int cardnum, oss_card_info * ci)
 
536
{
 
537
/*
 
538
 * Print information about a 'card' in a format suitable for /dev/sndstat
 
539
 */
 
540
 
 
541
  if (cardnum < 0 || cardnum >= oss_num_cards)
 
542
    return OSS_ENXIO;
 
543
 
 
544
  if (cards[cardnum]->name != NULL)
 
545
    strncpy (ci->longname, cards[cardnum]->name, 128);
 
546
  ci->longname[127] = 0;
 
547
 
 
548
  if (cards[cardnum]->nick != NULL)
 
549
    strncpy (ci->shortname, cards[cardnum]->nick, 16);
 
550
  ci->shortname[15] = 0;
 
551
 
 
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;
 
557
 
 
558
  return 0;
 
559
}
 
560
 
 
561
int
 
562
ossDrv (void)
 
563
{
 
564
  oss_hz = sysClkRateGet();
 
565
 
 
566
  if (oss_driver_num != ERROR)
 
567
    {
 
568
      cmn_err (CE_WARN, "OSS is already running\n");
 
569
      return -1;
 
570
    }
 
571
 
 
572
#ifdef LICENSED_VERSION
 
573
  if (!oss_license_handle_time (oss_get_time ()))
 
574
    {
 
575
      cmn_err (CE_WARN, "This version of Open Sound System has expired\n");
 
576
      cmn_err (CE_CONT,
 
577
               "Please download the latest version from www.opensound.com\n");
 
578
      oss_expired = 1;
 
579
      return -1;
 
580
    }
 
581
#endif
 
582
 
 
583
  oss_driver_num = iosDrvInstall ((FUNCPTR) NULL,       /* create */
 
584
                                  (FUNCPTR) NULL,       /* delete */
 
585
                                  (FUNCPTR) ossOpen, (FUNCPTR) ossClose, (FUNCPTR) ossRead, (FUNCPTR) ossWrite, (FUNCPTR) ossIoctl      /* ioctl */
 
586
    );
 
587
  if (oss_driver_num == ERROR)
 
588
    {
 
589
      cmn_err (CE_WARN, "Module osscore failed to install\n");
 
590
      return -1;
 
591
    }
 
592
 
 
593
  if ((core_osdev =
 
594
       osdev_create (NULL, DRV_UNKNOWN, 0, "osscore", NULL)) == NULL)
 
595
    {
 
596
      oss_cmn_err (CE_WARN, "Failed to allocate OSDEV structure\n");
 
597
      return -1;
 
598
    }
 
599
  oss_register_device (core_osdev, "OSS core services");
 
600
 
 
601
  oss_common_init (core_osdev);
 
602
 
 
603
  return oss_driver_num;
 
604
}
 
605
 
 
606
int
 
607
ossDrvRemove (void)
 
608
{
 
609
#if 1
 
610
 
 
611
  return ERROR;
 
612
#else
 
613
  int i;
 
614
 
 
615
  if (oss_driver_num == ERROR)
 
616
    return 0;
 
617
 
 
618
  for (i = 0; i < SND_NDEVS; i++)
 
619
    if (oss_files[i].valid)
 
620
      {
 
621
        iosDevDelete (&oss_files[i].devHdr);
 
622
        oss_files[i].valid = 0;
 
623
      }
 
624
 
 
625
  if (iosDrvRemove (oss_driver_num, FALSE) == ERROR)
 
626
    {
 
627
      cmn_err (CE_WARN, "Driver busy - cannot remove.\n");
 
628
      return ERROR;
 
629
    }
 
630
 
 
631
  // TODO
 
632
  oss_unload_drivers ();
 
633
 
 
634
  oss_driver_num = ERROR;       /* Mark it free */
 
635
  return OK;
 
636
#endif
 
637
}
 
638
 
 
639
#ifdef CONFIG_OSS_VMIX_FLOAT
 
640
 
 
641
#undef FP_SAVE
 
642
#undef FP_RESTORE
 
643
#define FP_SAVE(envbuf)         asm ("fnsave %0":"=m" (*envbuf));
 
644
#define FP_RESTORE(envbuf)              asm ("frstor %0":"=m" (*envbuf));
 
645
 
 
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));
 
649
 
 
650
static int old_arch = 0;        /* No SSE/SSE2 instructions */
 
651
 
 
652
#if defined(__amd64__)
 
653
#define AMD64
 
654
#endif
 
655
 
 
656
static inline void
 
657
cpuid (int op, int *eax, int *ebx, int *ecx, int *edx)
 
658
{
 
659
__asm__ ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx):"0" (op), "c"
 
660
           (0));
 
661
}
 
662
 
 
663
#ifdef AMD64
 
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")
 
666
#else
 
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")
 
669
#endif
 
670
 
 
671
static inline unsigned long
 
672
read_cr0 (void)
 
673
{
 
674
  unsigned long cr0;
 
675
#ifdef AMD64
 
676
asm ("movq %%cr0,%0":"=r" (cr0));
 
677
#else
 
678
asm ("movl %%cr0,%0":"=r" (cr0));
 
679
#endif
 
680
  return cr0;
 
681
}
 
682
 
 
683
static inline void
 
684
write_cr0 (unsigned long val)
 
685
{
 
686
#ifdef AMD64
 
687
  asm ("movq %0,%%cr0"::"r" (val));
 
688
#else
 
689
  asm ("movl %0,%%cr0"::"r" (val));
 
690
#endif
 
691
}
 
692
 
 
693
static inline unsigned long
 
694
read_cr4 (void)
 
695
{
 
696
  unsigned long cr4;
 
697
#ifdef AMD64
 
698
asm ("movq %%cr4,%0":"=r" (cr4));
 
699
#else
 
700
asm ("movl %%cr4,%0":"=r" (cr4));
 
701
#endif
 
702
  return cr4;
 
703
}
 
704
 
 
705
static inline void
 
706
write_cr4 (unsigned long val)
 
707
{
 
708
#ifdef AMD64
 
709
  asm ("movq %0,%%cr4"::"r" (val));
 
710
#else
 
711
  asm ("movl %0,%%cr4"::"r" (val));
 
712
#endif
 
713
}
 
714
static inline unsigned long long
 
715
read_mxcsr (void)
 
716
{
 
717
  unsigned long long mxcsr;
 
718
  asm volatile ("stmxcsr %0":"=m" (mxcsr));
 
719
  return mxcsr;
 
720
}
 
721
 
 
722
static inline void
 
723
write_mxcsr (unsigned long long val)
 
724
{
 
725
  asm volatile ("ldmxcsr %0"::"m" (val));
 
726
}
 
727
 
 
728
int
 
729
oss_fp_check (void)
 
730
{
 
731
  int eax, ebx, ecx, edx;
 
732
#define FLAGS_ID (1<<21)
 
733
 
 
734
  oss_native_word flags_reg;
 
735
 
 
736
  local_save_flags (flags_reg);
 
737
  flags_reg &= ~FLAGS_ID;
 
738
  local_restore_flags (flags_reg);
 
739
 
 
740
  local_save_flags (flags_reg);
 
741
  if (flags_reg & FLAGS_ID)
 
742
    return 0;
 
743
 
 
744
  flags_reg |= FLAGS_ID;
 
745
  local_restore_flags (flags_reg);
 
746
 
 
747
  local_save_flags (flags_reg);
 
748
  if (!(flags_reg & FLAGS_ID))
 
749
    return 0;
 
750
 
 
751
//#define CPUID_FXSR    (1<<24)
 
752
//#define CPUID_SSE     (1<<25)
 
753
//#define CPUID_SSE2    (1<<26)
 
754
 
 
755
  cpuid (1, &eax, &ebx, &ecx, &edx);
 
756
 
 
757
  if (!(edx & CPUID_FXSR))
 
758
    return -1;
 
759
 
 
760
  /*
 
761
   * Older machines require different FP handling than the latest ones. Use the SSE
 
762
   * instruction set as an indicator.
 
763
   */
 
764
  if (!(edx & CPUID_SSE))
 
765
    old_arch = 1;
 
766
 
 
767
  return 1;
 
768
}
 
769
 
 
770
void
 
771
oss_fp_save (short *envbuf, unsigned int flags[])
 
772
{
 
773
  flags[0] = read_cr0 ();
 
774
  write_cr0 (flags[0] & ~0x0e); /* Clear CR0.TS/MP/EM */
 
775
 
 
776
  if (old_arch)
 
777
    {
 
778
      FP_SAVE (envbuf);
 
779
    }
 
780
  else
 
781
    {
 
782
      flags[1] = read_cr4 ();
 
783
      write_cr4 (flags[1] | 0x600);     /* Set OSFXSR & OSXMMEXCEPT */
 
784
      FX_SAVE (envbuf);
 
785
      asm ("fninit");
 
786
      asm ("fwait");
 
787
      write_mxcsr (0x1f80);
 
788
    }
 
789
  flags[2] = read_cr0 ();
 
790
}
 
791
 
 
792
void
 
793
oss_fp_restore (short *envbuf, unsigned int flags[])
 
794
{
 
795
  asm ("fwait");
 
796
  if (old_arch)
 
797
    {
 
798
      FP_RESTORE (envbuf);
 
799
    }
 
800
  else
 
801
    {
 
802
      FX_RESTORE (envbuf);
 
803
      write_cr4 (flags[1]);     /* Restore cr4 */
 
804
    }
 
805
  write_cr0 (flags[0]);         /* Restore cr0 */
 
806
}
 
807
#endif
 
808
 
 
809
typedef struct tmout_desc
 
810
{
 
811
  volatile int active;
 
812
  int timestamp;
 
813
  void (*func) (void *);
 
814
  void *arg;
 
815
 
 
816
  WDOG_ID id;
 
817
 
 
818
} tmout_desc_t;
 
819
 
 
820
static volatile int next_id = 0;
 
821
#define MAX_TMOUTS 128
 
822
 
 
823
tmout_desc_t tmouts[MAX_TMOUTS] = { {0} };
 
824
 
 
825
int timeout_random = 0x12123400;
 
826
 
 
827
void
 
828
oss_timer_callback (int id)
 
829
{
 
830
  tmout_desc_t *tmout;
 
831
  int ix;
 
832
  void *arg;
 
833
 
 
834
  timeout_random++;
 
835
 
 
836
  ix = id & 0xff;
 
837
  if (ix < 0 || ix >= MAX_TMOUTS)
 
838
    return;
 
839
  tmout = &tmouts[ix];
 
840
 
 
841
  if (tmout->timestamp != id)   /* Expired timer */
 
842
    return;
 
843
 
 
844
  if (!tmout->active)
 
845
    return;
 
846
 
 
847
  arg = tmout->arg;
 
848
  tmout->active = 0;
 
849
  tmout->timestamp = 0;
 
850
 
 
851
  tmout->func (arg);
 
852
  wdDelete(tmout->id);
 
853
}
 
854
 
 
855
timeout_id_t
 
856
oss_timeout (void (*func) (void *), void *arg,
 
857
                                 unsigned long long ticks)
 
858
{
 
859
 
 
860
  tmout_desc_t *tmout = NULL;
 
861
  int id, n;
 
862
 
 
863
  timeout_random++;
 
864
 
 
865
  n = 0;
 
866
  id = -1;
 
867
 
 
868
  while (id == -1 && n < MAX_TMOUTS)
 
869
    {
 
870
      if (!tmouts[next_id].active)
 
871
        {
 
872
          tmouts[next_id].active = 1;
 
873
          id = next_id++;
 
874
          tmout = &tmouts[id];
 
875
          break;
 
876
        }
 
877
 
 
878
      next_id = (next_id + 1) % MAX_TMOUTS;
 
879
    }
 
880
 
 
881
  if (id == -1)                 /* No timer slots available */
 
882
    {
 
883
      oss_cmn_err (CE_WARN, "Timeout table full\n");
 
884
      return 0;
 
885
    }
 
886
 
 
887
  tmout->func = func;
 
888
  tmout->arg = arg;
 
889
  tmout->timestamp = id | (timeout_random & ~0xff);
 
890
 
 
891
  if ((tmout->id=wdCreate()) == NULL)
 
892
     return 0;
 
893
 
 
894
  wdStart(tmout->id, ticks, (FUNCPTR)oss_timer_callback, (int)tmout->timestamp);
 
895
  return id | (timeout_random & ~0xff);
 
896
}
 
897
 
 
898
void
 
899
oss_untimeout (timeout_id_t id)
 
900
{
 
901
  tmout_desc_t *tmout;
 
902
  int ix;
 
903
 
 
904
  ix = id & 0xff;
 
905
  if (ix < 0 || ix >= MAX_TMOUTS)
 
906
    return;
 
907
 
 
908
  timeout_random++;
 
909
  tmout = &tmouts[ix];
 
910
 
 
911
  if (tmout->timestamp != id)   /* Expired timer */
 
912
    return;
 
913
  if (tmout->active)
 
914
     {
 
915
        wdCancel(tmout->id);
 
916
        wdDelete(tmout->id);
 
917
     }
 
918
 
 
919
  tmout->active = 0;
 
920
  tmout->timestamp = 0;
 
921
}
 
922
 
 
923
void
 
924
oss_udelay(unsigned long ticks)
 
925
{
 
926
        // TODO
 
927
}
 
928
 
 
929
void *
 
930
oss_contig_malloc (oss_device_t * osdev, int buffsize, oss_uint64_t memlimit,
 
931
                   oss_native_word * phaddr)
 
932
{
 
933
  char *start_addr, *end_addr;
 
934
 
 
935
  *phaddr = 0;
 
936
 
 
937
  start_addr = NULL;
 
938
 
 
939
  // TODO: See if there is a previously freed buffer available
 
940
 
 
941
  start_addr = (char *) valloc (buffsize);
 
942
 
 
943
  if (start_addr == NULL)
 
944
    {
 
945
      cmn_err (CE_NOTE, "Failed to allocate memory buffer of %d bytes\n",
 
946
               buffsize);
 
947
      return NULL;
 
948
    }
 
949
  else
 
950
    {
 
951
      /* make some checks */
 
952
      end_addr = start_addr + buffsize - 1;
 
953
    }
 
954
 
 
955
  *phaddr = (oss_native_word)start_addr;
 
956
  return start_addr;
 
957
}
 
958
 
 
959
void
 
960
oss_contig_free (oss_device_t * osdev, void *p, int buffsize)
 
961
{
 
962
  if (p == NULL)
 
963
    return;
 
964
 
 
965
  // TODO: Put the freed memory block to available list
 
966
  cmn_err (CE_WARN, "Cannot free %d bytes of DMA buffer\n", buffsize);
 
967
}
 
968
 
 
969
int
 
970
__oss_alloc_dmabuf (int dev, dmap_p dmap, unsigned int alloc_flags,
 
971
                    oss_uint64_t maxaddr, int direction)
 
972
{
 
973
  void *buf;
 
974
  int err;
 
975
  oss_native_word phaddr;
 
976
  int size = 64 * 1024;
 
977
  extern int dma_buffsize;
 
978
 
 
979
  if (dma_buffsize > 16 && dma_buffsize <= 128)
 
980
    size = dma_buffsize * 1024;
 
981
 
 
982
  if (dmap->dmabuf != NULL)
 
983
    return 0;                   /* Already done */
 
984
 
 
985
  if (dmap == NULL)
 
986
    {
 
987
      cmn_err (CE_WARN, "oss_alloc_dmabuf: dmap==NULL\n");
 
988
      return OSS_EIO;
 
989
    }
 
990
 
 
991
/*
 
992
 * Some applications and virtual drivers need shorter buffer.
 
993
 */
 
994
  if (dmap->flags & DMAP_SMALLBUF)
 
995
    {
 
996
      size = SMALL_DMABUF_SIZE;
 
997
    }
 
998
  else if (dmap->flags & DMAP_MEDIUMBUF)
 
999
    {
 
1000
      size = MEDIUM_DMABUF_SIZE;
 
1001
    }
 
1002
 
 
1003
  if ((alloc_flags & DMABUF_SIZE_16BITS) && size > 32 * 1024)
 
1004
    size = 32 * 1024;
 
1005
 
 
1006
  dmap->dmabuf = NULL;
 
1007
  dmap->buffsize = size;
 
1008
 
 
1009
  err = -1;
 
1010
 
 
1011
  while (err < 0 && dmap->dmabuf == NULL && dmap->buffsize >= 4 * 1024)
 
1012
    {
 
1013
      if ((buf =
 
1014
           oss_contig_malloc (dmap->osdev, dmap->buffsize, maxaddr,
 
1015
                              &phaddr)) == NULL)
 
1016
        {
 
1017
          if ((dmap->buffsize = (dmap->buffsize / 2)) < 8 * 1024)
 
1018
            return OSS_ENOMEM;
 
1019
          cmn_err (CE_CONT, "Dropping DMA buffer size to %d bytes.\n",
 
1020
                   dmap->buffsize);
 
1021
          continue;
 
1022
        }
 
1023
 
 
1024
      dmap->dmabuf = buf;
 
1025
      dmap->dmabuf_phys = phaddr;
 
1026
 
 
1027
      return 0;
 
1028
    }
 
1029
 
 
1030
  return OSS_ENOMEM;
 
1031
}
 
1032
 
 
1033
void
 
1034
oss_free_dmabuf (int dev, dmap_p dmap)
 
1035
{
 
1036
  void *buf = dmap->dmabuf;
 
1037
 
 
1038
  if (dmap->dmabuf == NULL)
 
1039
    return;
 
1040
 
 
1041
  dmap->dmabuf = NULL;
 
1042
  oss_contig_free (NULL, buf, dmap->buffsize);
 
1043
  dmap->dmabuf_phys = 0;
 
1044
}
 
1045
 
 
1046
/*
 
1047
 * Sleep/wakeup
 
1048
 */
 
1049
 
 
1050
struct oss_wait_queue
 
1051
{
 
1052
  volatile int flags;
 
1053
  SEM_ID wq;
 
1054
};
 
1055
 
 
1056
struct oss_wait_queue *
 
1057
oss_create_wait_queue (oss_device_t * osdev, const char *name)
 
1058
{
 
1059
  struct oss_wait_queue *wq;
 
1060
 
 
1061
  if ((wq = malloc (sizeof (*wq))) == NULL)
 
1062
    {
 
1063
      oss_cmn_err (CE_WARN, "vmalloc(%d) failed (wq)\n", sizeof (*wq));
 
1064
      return NULL;
 
1065
    }
 
1066
  wq->wq = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
 
1067
 
 
1068
  return wq;
 
1069
}
 
1070
 
 
1071
void
 
1072
oss_reset_wait_queue (struct oss_wait_queue *wq)
 
1073
{
 
1074
        // TODO: ?
 
1075
}
 
1076
 
 
1077
void
 
1078
oss_remove_wait_queue (struct oss_wait_queue *wq)
 
1079
{
 
1080
  free (wq);
 
1081
}
 
1082
 
 
1083
int
 
1084
oss_sleep (struct oss_wait_queue *wq, oss_mutex_t * mutex, int ticks,
 
1085
           oss_native_word * flags, unsigned int *status)
 
1086
{
 
1087
  int result;
 
1088
 
 
1089
  *status = 0;
 
1090
 
 
1091
  if (wq == NULL)
 
1092
    return 0;
 
1093
 
 
1094
  wq->flags = 0;
 
1095
 
 
1096
  if (ticks <= 0)
 
1097
     ticks = WAIT_FOREVER;
 
1098
 
 
1099
    result =
 
1100
            semTake(wq->wq, ticks);
 
1101
 
 
1102
  if (result == ERROR)          /* Signal received */
 
1103
    {
 
1104
      *status |= WK_SIGNAL;
 
1105
      return 1;
 
1106
    }
 
1107
 
 
1108
  if (!(wq->flags & WK_WAKEUP)) /* Timeout */
 
1109
    {
 
1110
      return 0;
 
1111
    }
 
1112
 
 
1113
  return 1;
 
1114
}
 
1115
 
 
1116
int
 
1117
oss_register_poll (struct oss_wait_queue *wq, oss_mutex_t * mutex,
 
1118
                   oss_native_word * flags, oss_poll_event_t * ev)
 
1119
{
 
1120
  // TODO: ?
 
1121
  return 0;
 
1122
}
 
1123
 
 
1124
void
 
1125
oss_wakeup (struct oss_wait_queue *wq, oss_mutex_t * mutex,
 
1126
            oss_native_word * flags, short events)
 
1127
{
 
1128
  if (wq == NULL)
 
1129
    return;
 
1130
 
 
1131
  wq->flags |= WK_WAKEUP;
 
1132
  semFlush(wq->wq);
 
1133
}