~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to kernel/OS/SCO_SV/os_sco.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: Operating system abstraction functions for SCO OpenServer/UnixWare
 
3
 */
 
4
/*
 
5
 *
 
6
 * This file is part of Open Sound System.
 
7
 *
 
8
 * Copyright (C) 4Front Technologies 1996-2008.
 
9
 *
 
10
 * This this source file is released under GPL v2 license (no other versions).
 
11
 * See the COPYING file included in the main directory of this source
 
12
 * distribution for the license terms and conditions.
 
13
 *
 
14
 */
 
15
 
 
16
#include "oss_config.h"
 
17
#include "midi_core.h"
 
18
#include <oss_pci.h>
 
19
#include <sys/exec.h>
 
20
#include <sys/user.h>
 
21
#include <errno.h>
 
22
 
 
23
/*
 
24
 * MAX_CARDS must be larger than life. The system will panic if there are
 
25
 * more sound devices (cards os sound chips) than MAX_CARDS.
 
26
 */
 
27
#define MAX_CARDS 32
 
28
 
 
29
static oss_device_t *cards[MAX_CARDS];
 
30
int oss_num_cards = 0;
 
31
static int oss_expired = 0;
 
32
 
 
33
volatile int oss_open_devices = 0;
 
34
 
 
35
static bcb_t *oss_bcb;
 
36
 
 
37
/*
 
38
 * Driver information structures, for drv_attach().
 
39
 */
 
40
static int oss_config (cfg_func_t func, void *idata, rm_key_t key);
 
41
 
 
42
static const drvops_t oss_ops = {
 
43
  oss_config,
 
44
  oss_open,
 
45
  oss_close,
 
46
  oss_devinfo,
 
47
  oss_biostart,
 
48
  oss_ioctl,
 
49
  NULL,                         /* drvctl */
 
50
  NULL                          /* mmap */
 
51
};
 
52
 
 
53
static const drvinfo_t oss_drvinfo = {
 
54
  &oss_ops,
 
55
  "osscore",
 
56
  D_MP,                         /* MP-safe */
 
57
  NULL,                         /* Not a STREAMS driver */
 
58
  10                            /* Must match $maxchan in Node file */
 
59
};
 
60
 
 
61
static physreq_t *physreq_isa = NULL;   /* 24 bits */
 
62
static physreq_t *physreq_28bit = NULL;
 
63
static physreq_t *physreq_30bit = NULL;
 
64
static physreq_t *physreq_31bit = NULL;
 
65
static physreq_t *physreq_32bit = NULL;
 
66
 
 
67
#ifdef MEMDEBUG
 
68
typedef struct
 
69
{
 
70
  void *addr;
 
71
  int size;
 
72
  char file[40];
 
73
  int line;
 
74
} mem_block_t;
 
75
 
 
76
#define MAX_MEMBLOCKS 1024
 
77
 
 
78
static mem_block_t memblocks[MAX_MEMBLOCKS];
 
79
static int num_memblocks = 0;
 
80
#endif
 
81
 
 
82
#ifdef MEMDEBUG
 
83
void *
 
84
oss_kmem_alloc (size_t size, int flags, char *file, int line)
 
85
#else
 
86
void *
 
87
oss_kmem_alloc (size_t size, int flags)
 
88
#endif
 
89
{
 
90
/*
 
91
 * This routine allocates a memory block and stores length of it in
 
92
 * the beginning. This length information can be used when later unallocating
 
93
 * the memory.
 
94
 */
 
95
 
 
96
  char *ptr;
 
97
  uint64_t *len;
 
98
 
 
99
  ptr = kmem_zalloc (size + sizeof (uint64_t), flags);
 
100
#ifdef MEMDEBUG
 
101
  cmn_err (CE_CONT, "kmalloc(%d, %s:%d)=%x\n", size, file, line, ptr);
 
102
#endif
 
103
 
 
104
  if (ptr == NULL)
 
105
    return NULL;
 
106
 
 
107
  len = (uint64_t *) ptr;
 
108
 
 
109
  ptr += sizeof (uint64_t);
 
110
  *len = size + sizeof (uint64_t);
 
111
 
 
112
#ifdef MEMDEBUG
 
113
#if 1
 
114
  {
 
115
    int i;
 
116
    for (i = 0; i < num_memblocks; i++)
 
117
      if (memblocks[i].addr == NULL)
 
118
        {
 
119
          memblocks[i].addr = ptr;
 
120
          memblocks[i].size = size;
 
121
          strncpy (memblocks[i].file, file, 39);
 
122
          memblocks[i].line = line;
 
123
          return ptr;
 
124
        }
 
125
  }
 
126
#endif
 
127
 
 
128
  if (num_memblocks < MAX_MEMBLOCKS)
 
129
    {
 
130
      memblocks[num_memblocks].addr = ptr;
 
131
      memblocks[num_memblocks].size = size;
 
132
      strncpy (memblocks[num_memblocks].file, file, 39);
 
133
      memblocks[num_memblocks].line = line;
 
134
      num_memblocks++;
 
135
    }
 
136
#endif
 
137
 
 
138
  return ptr;
 
139
}
 
140
 
 
141
void
 
142
#ifdef MEMDEBUG
 
143
oss_kmem_free (void *addr, char *file, int line)
 
144
#else
 
145
oss_kmem_free (void *addr)
 
146
#endif
 
147
{
 
148
  uint64_t *len;
 
149
  int i;
 
150
 
 
151
  char *ptr = addr;
 
152
 
 
153
  if (addr == NULL)
 
154
    return;
 
155
 
 
156
  ptr -= sizeof (uint64_t);
 
157
 
 
158
  len = (uint64_t *) ptr;
 
159
 
 
160
  kmem_free (ptr, *len);
 
161
#ifdef MEMDEBUG
 
162
  {
 
163
    int i;
 
164
 
 
165
    for (i = 0; i < num_memblocks; i++)
 
166
      if (addr == memblocks[i].addr)
 
167
        {
 
168
          memblocks[i].addr = NULL;
 
169
          return;
 
170
        }
 
171
  }
 
172
  cmn_err (CE_WARN, "Bad kfree(%x, %s:%d)\n", addr, file, line);
 
173
#endif
 
174
}
 
175
 
 
176
/*
 
177
 * Table for permanently allocated memory (to be freed by _fini)
 
178
 */
 
179
#define OSS_MAX_MEM     1024
 
180
void *oss_mem_blocks[OSS_MAX_MEM];
 
181
int oss_nblocks = 0;
 
182
 
 
183
void *
 
184
#ifdef MEMDEBUG
 
185
oss_pmalloc (size_t size, char *file, int line)
 
186
#else
 
187
oss_pmalloc (size_t size)
 
188
#endif
 
189
{
 
190
  void *mem_ptr;
 
191
#ifdef MEMDEBUG
 
192
  mem_ptr = (oss_mem_blocks[oss_nblocks] =
 
193
             oss_kmem_alloc (size, KM_SLEEP, file, line));
 
194
#else
 
195
  mem_ptr = (oss_mem_blocks[oss_nblocks] = KERNEL_MALLOC (size));
 
196
#endif
 
197
 
 
198
  if (oss_nblocks <= OSS_MAX_MEM)
 
199
    oss_nblocks++;
 
200
  else
 
201
    cmn_err (CE_NOTE, "Out of mem blocks\n");
 
202
  return mem_ptr;
 
203
}
 
204
 
 
205
int
 
206
__oss_alloc_dmabuf (int dev, dmap_p dmap, unsigned int alloc_flags,
 
207
                    oss_uint64_t maxaddr, int direction)
 
208
{
 
209
  void *p;
 
210
  oss_native_word phaddr;
 
211
  int size = 64 * 1024;
 
212
  extern int dma_buffsize;
 
213
 
 
214
  if (dma_buffsize > 16 && dma_buffsize <= 128)
 
215
    size = dma_buffsize * 1024;
 
216
 
 
217
  if (dmap->dmabuf != NULL)
 
218
    return 0;
 
219
 
 
220
/*
 
221
 * Some applications and virtual drivers need shorter buffer.
 
222
 */
 
223
  if (dmap->flags & DMAP_SMALLBUF)
 
224
    {
 
225
      size = SMALL_DMABUF_SIZE;
 
226
    }
 
227
  else if (dmap->flags & DMAP_MEDIUMBUF)
 
228
    {
 
229
      size = MEDIUM_DMABUF_SIZE;
 
230
    }
 
231
 
 
232
  if ((alloc_flags & DMABUF_SIZE_16BITS) && size > 32 * 1024)
 
233
    size = 32 * 1024;
 
234
 
 
235
  if ((p =
 
236
       oss_contig_malloc (audio_engines[dev]->osdev, size, maxaddr,
 
237
                          &phaddr)) == NULL)
 
238
    return OSS_ENOMEM;
 
239
 
 
240
  dmap->dmabuf = p;
 
241
  dmap->dmabuf_phys = phaddr;
 
242
  dmap->buffsize = size;
 
243
 
 
244
  return 0;
 
245
}
 
246
 
 
247
void
 
248
oss_free_dmabuf (int dev, dmap_p dmap)
 
249
{
 
250
  if (dmap->dmabuf == NULL)
 
251
    return;
 
252
 
 
253
  oss_contig_free (audio_engines[dev]->osdev, dmap->dmabuf, dmap->buffsize);
 
254
  dmap->dmabuf = NULL;
 
255
  dmap->dmabuf_phys = 0;
 
256
  dmap->buffsize = 0;
 
257
}
 
258
 
 
259
void *
 
260
oss_contig_malloc (oss_device_t * osdev, int size, oss_uint64_t memlimit,
 
261
                   oss_native_word * phaddr)
 
262
{
 
263
  void *p = NULL;
 
264
  physreq_t *preqp = physreq_32bit;
 
265
  paddr32_t pa;
 
266
 
 
267
  *phaddr = 0;
 
268
 
 
269
  switch (memlimit)
 
270
    {
 
271
    case MEMLIMIT_ISA:
 
272
      preqp = physreq_isa;
 
273
      break;
 
274
    case MEMLIMIT_28BITS:
 
275
      preqp = physreq_28bit;
 
276
      break;
 
277
    case MEMLIMIT_30BITS:
 
278
      preqp = physreq_30bit;
 
279
      break;
 
280
    case MEMLIMIT_31BITS:
 
281
      preqp = physreq_31bit;
 
282
      break;
 
283
    case MEMLIMIT_32BITS:
 
284
      preqp = physreq_32bit;
 
285
      break;
 
286
 
 
287
    default:
 
288
      cmn_err (CE_WARN, "osscore: Bad DMA memlimit for %s\n", osdev->nick);
 
289
    }
 
290
 
 
291
  if ((p = kmem_alloc_phys (size, preqp, &pa, 0)) == NULL)
 
292
    {
 
293
      cmn_err (CE_WARN, "osscore: kmem_alloc_phys() failed\n");
 
294
      return NULL;
 
295
    }
 
296
 
 
297
  *phaddr = pa;
 
298
  return p;
 
299
}
 
300
 
 
301
void
 
302
oss_contig_free (oss_device_t * osdev, void *p, int sz)
 
303
{
 
304
  if (p)
 
305
    kmem_free (p, sz);
 
306
}
 
307
 
 
308
/*
 
309
 * Wait queue support
 
310
 */
 
311
oss_wait_queue_t *
 
312
oss_create_wait_queue (oss_device_t * osdev, const char *name)
 
313
{
 
314
  oss_wait_queue_t *q;
 
315
 
 
316
  if ((q = KERNEL_MALLOC (sizeof (*q))) == NULL)
 
317
    {
 
318
      cmn_err (CE_WARN, "osscore: Cannot allocate memory for a wait queue\n");
 
319
      return NULL;
 
320
    }
 
321
 
 
322
  memset (q, 0, sizeof (*q));
 
323
 
 
324
  if ((q->sv = SV_ALLOC (KM_SLEEP)) == NULL)
 
325
    {
 
326
      cmn_err (CE_WARN,
 
327
               "osscore: Cannot allocate synchronization variable\n");
 
328
      return NULL;
 
329
    }
 
330
 
 
331
  return q;
 
332
}
 
333
 
 
334
void
 
335
oss_reset_wait_queue (oss_wait_queue_t * wq)
 
336
{
 
337
  // NOP
 
338
}
 
339
 
 
340
void
 
341
oss_remove_wait_queue (oss_wait_queue_t * wq)
 
342
{
 
343
  SV_DEALLOC (wq->sv);
 
344
  KERNEL_FREE (wq);
 
345
}
 
346
 
 
347
static void
 
348
sleep_timeout (caddr_t arg)
 
349
{
 
350
  oss_wait_queue_t *wq = (oss_wait_queue_t *) arg;
 
351
 
 
352
  SV_BROADCAST (wq->sv, 0);
 
353
}
 
354
 
 
355
int
 
356
oss_sleep (oss_wait_queue_t * wq, oss_mutex_t * mutex, int ticks,
 
357
           oss_native_word * flags, unsigned int *status)
 
358
{
 
359
  timeout_id_t tid;
 
360
 
 
361
  *status = 0;
 
362
  wq->flags = 0;
 
363
 
 
364
  if (wq == NULL)
 
365
    {
 
366
      cmn_err (CE_WARN, "osscore: Unallocated wait queue\n");
 
367
      *status |= WK_SIGNAL;
 
368
      return 1;
 
369
    }
 
370
  if (ticks > 0)
 
371
    tid = timeout (sleep_timeout, wq, ticks);
 
372
 
 
373
  /*
 
374
   * Note SV_WAIT_SIG() will release the mutex/lock so we must re-acquire
 
375
   * it before returning.
 
376
   */
 
377
#ifdef MUTEX_CHECKS
 
378
  // Pop mutex because it will be released by SV_WAIT_SIG() 
 
379
  pop_mutex (*mutex, __FILE__, __LINE__);
 
380
#endif
 
381
  if (!SV_WAIT_SIG (wq->sv, prihi, *mutex))     /* Signal */
 
382
    {
 
383
      *status |= WK_SIGNAL;
 
384
      wq->flags |= WK_WAKEUP;   /* Needed to prevent false timeout messages */
 
385
    }
 
386
 
 
387
  MUTEX_ENTER_IRQDISABLE (*mutex, *flags);
 
388
  if (ticks > 0 && (wq->flags & WK_WAKEUP))
 
389
    untimeout (tid);
 
390
 
 
391
  return (wq->flags & WK_WAKEUP);
 
392
}
 
393
 
 
394
int
 
395
oss_register_poll (oss_wait_queue_t * wq, oss_mutex_t * mutex,
 
396
                   oss_native_word * flags, oss_poll_event_t * ev)
 
397
{
 
398
  // NOP: DDI8 doesn't support chpoll
 
399
}
 
400
 
 
401
void
 
402
oss_wakeup (oss_wait_queue_t * wq, oss_mutex_t * mutex,
 
403
            oss_native_word * flags, short events)
 
404
{
 
405
  wq->flags |= WK_WAKEUP;
 
406
  SV_BROADCAST (wq->sv, 0);
 
407
}
 
408
 
 
409
void *
 
410
oss_get_osid (oss_device_t * osdev)
 
411
{
 
412
  return osdev->osid;
 
413
}
 
414
 
 
415
static int
 
416
grow_array(oss_device_t *osdev, oss_cdev_t ***arr, int *size, int element_size, int increment)
 
417
{
 
418
        oss_cdev_t **old=*arr, **new = *arr;
 
419
        int old_size = *size;
 
420
        int new_size = *size;
 
421
                
 
422
        new_size += increment;
 
423
 
 
424
        if ((new=PMALLOC(osdev, new_size * element_size))==NULL)
 
425
           return 0;
 
426
 
 
427
        memset(new, 0, new_size * element_size);
 
428
        if (old != NULL)
 
429
           memcpy(new, old, old_size * element_size);
 
430
 
 
431
        *size = new_size;
 
432
        *arr = new;
 
433
 
 
434
        if (old != NULL)
 
435
           PMFREE(osdev, old);
 
436
 
 
437
        return 1;
 
438
}
 
439
 
 
440
void
 
441
oss_install_chrdev (oss_device_t * osdev, char *name, int dev_class,
 
442
                    int instance, oss_cdev_drv_t * drv, int flags)
 
443
{
 
444
/*
 
445
 * oss_install_chrdev creates a character device (minor). However if
 
446
 * name==NULL the device will not be exported (made visible to userland
 
447
 * clients).
 
448
 */
 
449
 
 
450
  int i, num;
 
451
  oss_cdev_t *cdev = NULL;
 
452
 
 
453
  if (dev_class != OSS_DEV_STATUS)
 
454
    if (oss_expired && instance > 0)
 
455
      return;
 
456
/*
 
457
 * Find if this dev_class&instance already exists (after previous module
 
458
 * detach).
 
459
 */
 
460
 
 
461
  for (num = 0; num < oss_num_cdevs; num++)
 
462
    if (oss_cdevs[num]->d == NULL)      /* Unloaded driver */
 
463
      if (oss_cdevs[num]->dev_class == dev_class
 
464
          && oss_cdevs[num]->instance == instance)
 
465
        {
 
466
          cdev = oss_cdevs[num];
 
467
          break;
 
468
        }
 
469
 
 
470
  if (cdev == NULL)
 
471
    {
 
472
      if (oss_num_cdevs >= OSS_MAX_CDEVS)
 
473
        {
 
474
           if (!grow_array(osdev, &oss_cdevs, &oss_max_cdevs, sizeof(oss_cdev_t*), 100))
 
475
           {
 
476
                cmn_err (CE_WARN, "Cannot allocate new minor numbers.\n");
 
477
                return;
 
478
           }
 
479
        }
 
480
 
 
481
      if ((cdev = PMALLOC (NULL, sizeof (*cdev))) == NULL)
 
482
        {
 
483
          cmn_err (CE_WARN, "Cannot allocate character device desc.\n");
 
484
          return;
 
485
        }
 
486
      num = oss_num_cdevs++;
 
487
    }
 
488
 
 
489
  memset (cdev, 0, sizeof (*cdev));
 
490
  cdev->dev_class = dev_class;
 
491
  cdev->instance = instance;
 
492
  cdev->d = drv;
 
493
  cdev->osdev = osdev;
 
494
  if (name != NULL)
 
495
    strncpy (cdev->name, name, sizeof (cdev->name) - 1);
 
496
  else
 
497
    strcpy (cdev->name, "NONE");
 
498
  cdev->name[sizeof (cdev->name) - 1] = 0;
 
499
  oss_cdevs[num] = cdev;
 
500
}
 
501
 
 
502
int
 
503
oss_find_minor (int dev_class, int instance)
 
504
{
 
505
  int i;
 
506
 
 
507
  for (i = 0; i < oss_num_cdevs; i++)
 
508
    if (oss_cdevs[i]->d != NULL && oss_cdevs[i]->dev_class == dev_class
 
509
        && oss_cdevs[i]->instance == instance)
 
510
      return i;
 
511
 
 
512
  return OSS_EIO;
 
513
}
 
514
 
 
515
int
 
516
oss_get_cardinfo (int cardnum, oss_card_info * ci)
 
517
{
 
518
/*
 
519
 * Print information about a 'card' in a format suitable for /dev/sndstat
 
520
 */
 
521
 
 
522
  if (cardnum < 0 || cardnum >= oss_num_cards)
 
523
    return OSS_ENXIO;
 
524
 
 
525
  if (cards[cardnum]->name != NULL)
 
526
    strncpy (ci->longname, cards[cardnum]->name, 128);
 
527
  ci->shortname[127] = 0;
 
528
 
 
529
  if (cards[cardnum]->nick != NULL)
 
530
    strncpy (ci->shortname, cards[cardnum]->nick, 16);
 
531
  ci->shortname[15] = 0;
 
532
 
 
533
  if (cards[cardnum]->hw_info != NULL)
 
534
    strncpy (ci->hw_info, cards[cardnum]->hw_info, sizeof (ci->hw_info) - 1);
 
535
  ci->hw_info[sizeof (ci->hw_info) - 1] = 0;
 
536
 
 
537
  return 0;
 
538
}
 
539
 
 
540
void
 
541
oss_reserve_device (oss_device_t * osdev)
 
542
{
 
543
  osdev->refcount++;
 
544
}
 
545
 
 
546
void
 
547
oss_unreserve_device (oss_device_t * osdev, int decrement)
 
548
{
 
549
  osdev->refcount--;
 
550
  if (osdev->refcount < 0)
 
551
    osdev->refcount = 0;
 
552
}
 
553
 
 
554
/*
 
555
 *      Some standard C library routines
 
556
 */
 
557
void *
 
558
memset (void *t, int c, size_t l)
 
559
{
 
560
  int i;
 
561
 
 
562
  if (t == NULL)
 
563
    return NULL;
 
564
 
 
565
  for (i = 0; i < l; i++)
 
566
    ((char *) t)[i] = c;
 
567
 
 
568
  return t;
 
569
}
 
570
 
 
571
void *
 
572
memcpy (void *t, const void *s, size_t l)
 
573
{
 
574
  bcopy (s, t, l);
 
575
  return t;
 
576
}
 
577
 
 
578
oss_device_t *
 
579
osdev_create (dev_info_t * dip, int dev_type, int instance, const char *nick,
 
580
              const char *handle)
 
581
{
 
582
  oss_device_t *osdev = NULL;
 
583
  int i, err;
 
584
  caddr_t addr;
 
585
  dev_info_t ldip = 0;
 
586
 
 
587
  if (dip == NULL)
 
588
    dip = &ldip;
 
589
 
 
590
  if (handle == NULL)
 
591
    handle = nick;
 
592
 
 
593
  /*
 
594
   * Don't accept any more drivers if expired
 
595
   */
 
596
  if (oss_expired && oss_num_cards > 0)
 
597
    return NULL;
 
598
 
 
599
/*
 
600
 * Check if a driver/device was reinserted
 
601
 */
 
602
  if (dip != &ldip)             /* Not a virtual driver */
 
603
    for (i = 0; i < oss_num_cards; i++)
 
604
      {
 
605
        if (!cards[i]->available && cards[i]->key == *dip)
 
606
          {
 
607
            osdev = cards[i];
 
608
            break;
 
609
          }
 
610
      }
 
611
 
 
612
  if (osdev == NULL)
 
613
    {
 
614
      if (oss_num_cards >= MAX_CARDS)
 
615
        {
 
616
          cmn_err (CE_WARN, "Too many OSS devices. At most %d permitted.\n",
 
617
                   MAX_CARDS);
 
618
          return NULL;
 
619
        }
 
620
 
 
621
      if ((osdev = PMALLOC (NULL, sizeof (*osdev))) == NULL)
 
622
        {
 
623
          cmn_err (CE_WARN, "osdev_create: Out of memory\n");
 
624
          return NULL;
 
625
        }
 
626
 
 
627
      osdev->cardnum = oss_num_cards;
 
628
      cards[oss_num_cards++] = osdev;
 
629
    }
 
630
  osdev->key = *dip;
 
631
  osdev->osid = dip;
 
632
  osdev->available = 1;
 
633
  osdev->first_mixer = -1;
 
634
  osdev->instance = instance;
 
635
  osdev->dev_type = dev_type;
 
636
  osdev->devc = NULL;
 
637
  MUTEX_INIT (osdev, osdev->mutex, MH_GLOBAL);
 
638
  sprintf (osdev->nick, "%s%d", nick, instance);
 
639
  strcpy (osdev->modname, nick);
 
640
 
 
641
  switch (dev_type)
 
642
    {
 
643
    case DRV_PCI:
 
644
      //pci_config_setup (dip, &osdev->pci_config_handle);
 
645
      break;
 
646
 
 
647
    case DRV_VIRTUAL:
 
648
    case DRV_VMIX:
 
649
    case DRV_STREAMS:
 
650
      /* NOP */
 
651
      break;
 
652
 
 
653
    case DRV_USB:
 
654
      /* NOP */
 
655
      break;
 
656
 
 
657
    default:
 
658
      cmn_err (CE_WARN, "Bad device type\n");
 
659
      return NULL;
 
660
    }
 
661
 
 
662
/*
 
663
 * Create the device handle
 
664
 */
 
665
  switch (dev_type)
 
666
    {
 
667
    case DRV_PCI:
 
668
      {
 
669
        unsigned int subvendor = 0;
 
670
        pci_read_config_dword (osdev, 0x2c, &subvendor);
 
671
 
 
672
        sprintf (osdev->handle, "PCI%08x-%d", subvendor, instance);
 
673
      }
 
674
      break;
 
675
 
 
676
#if 0
 
677
    case DRV_USB:
 
678
      sprintf (osdev->handle, "USB-%s%d", handle, instance);
 
679
      break;
 
680
#endif
 
681
 
 
682
    default:
 
683
      sprintf (osdev->handle, "%s%d", handle, instance);
 
684
    }
 
685
 
 
686
  return osdev;
 
687
}
 
688
 
 
689
oss_device_t *
 
690
osdev_clone (oss_device_t * orig_osdev, int new_instance)
 
691
{
 
692
  oss_device_t *osdev;
 
693
 
 
694
  osdev = PMALLOC (NULL, sizeof (*osdev));
 
695
  if (osdev == NULL)
 
696
    {
 
697
      cmn_err (CE_WARN, "osdev_create: Out of memory\n");
 
698
      return NULL;
 
699
    }
 
700
  memcpy (osdev, orig_osdev, sizeof (*osdev));
 
701
  osdev->dev_type = DRV_CLONE;
 
702
  osdev->instance = new_instance;
 
703
  sprintf (osdev->nick, "%s%d", orig_osdev->modname, new_instance);
 
704
  sprintf (osdev->handle, "%s%d", orig_osdev->modname, new_instance);
 
705
 
 
706
  return osdev;
 
707
}
 
708
 
 
709
void
 
710
osdev_delete (oss_device_t * osdev)
 
711
{
 
712
  int i;
 
713
 
 
714
  if (osdev == NULL)
 
715
    return;
 
716
 
 
717
  if (!osdev->available)
 
718
    {
 
719
      cmn_err (CE_WARN, "device %s, osdev already deleted\n", osdev->nick);
 
720
      return;
 
721
    }
 
722
 
 
723
  osdev->available = 0;
 
724
 
 
725
  switch (osdev->dev_type)
 
726
    {
 
727
    case DRV_PCI:
 
728
      break;
 
729
    }
 
730
 
 
731
/*
 
732
 * Mark all minor nodes for this module as invalid.
 
733
 */
 
734
  for (i = 0; i < oss_num_cdevs; i++)
 
735
    if (oss_cdevs[i]->osdev == osdev)
 
736
      {
 
737
        oss_cdevs[i]->d = NULL;
 
738
        oss_cdevs[i]->osdev = NULL;
 
739
        strcpy (oss_cdevs[i]->name, "Removed device");
 
740
      }
 
741
  MUTEX_CLEANUP (osdev->mutex);
 
742
}
 
743
 
 
744
int
 
745
oss_register_device (oss_device_t * osdev, const char *name)
 
746
{
 
747
  if ((osdev->name = PMALLOC (NULL, strlen (name) + 1)) == NULL)
 
748
    {
 
749
      cmn_err (CE_WARN, "Cannot allocate memory for device name\n");
 
750
      osdev->name = "Unknown device";
 
751
    }
 
752
  strcpy (osdev->name, name);
 
753
  return 0;
 
754
}
 
755
 
 
756
int
 
757
oss_disable_device (oss_device_t * osdev)
 
758
{
 
759
  int i;
 
760
/*
 
761
 * This routine should check if the device is ready to be unloaded (no devices are in use).
 
762
 * If the device cannot be unloaded this routine must return OSS_EBUSY.
 
763
 *
 
764
 * If the device can be unloaded then disable any timers or other features that may cause the
 
765
 * device to be called. Also mark the audio/midi/mixer/etc devices of this device to be disabled.
 
766
 * However the interrupt handler should still stay enabled. The low level driver will call
 
767
 * oss_unregister_interrupts() after it has cleared the interrupt enable register.
 
768
 */
 
769
  if (osdev->refcount > 0)
 
770
    {
 
771
      return OSS_EBUSY;
 
772
    }
 
773
 
 
774
/*
 
775
 * Now mark all devices unavailable (for the time being)
 
776
 */
 
777
 
 
778
  for (i = 0; i < num_mixers; i++)
 
779
    if (mixer_devs[i]->osdev == osdev)
 
780
      {
 
781
        mixer_devs[i]->unloaded = 1;
 
782
      }
 
783
 
 
784
  for (i = 0; i < num_mididevs; i++)
 
785
    {
 
786
      if (midi_devs[i]->osdev == osdev)
 
787
        {
 
788
          midi_devs[i]->unloaded = 1;
 
789
        }
 
790
    }
 
791
 
 
792
  for (i = 0; i < num_audio_engines; i++)
 
793
    if (audio_engines[i]->osdev == osdev)
 
794
      {
 
795
        audio_uninit_device (i);
 
796
      }
 
797
 
 
798
  return 0;
 
799
}
 
800
 
 
801
void
 
802
oss_unregister_device (oss_device_t * osdev)
 
803
{
 
804
}
 
805
 
 
806
#ifdef MUTEX_CHECKS
 
807
static int oss_context = 0;     /* 0=user context, 1=interrupt context */
 
808
#endif
 
809
 
 
810
static int
 
811
ossintr (void *idata)
 
812
{
 
813
  oss_device_t *osdev = idata;
 
814
  oss_native_word flags;
 
815
#ifdef MUTEX_CHECKS
 
816
  int saved_context;
 
817
  saved_context = oss_context;
 
818
  if (oss_context == 1)
 
819
    cmn_err (CE_WARN, "Recursive interrupt\n");
 
820
  oss_context = 1;
 
821
#endif
 
822
 
 
823
  MUTEX_ENTER_IRQDISABLE (osdev->mutex, flags);
 
824
 
 
825
  if (!osdev->tophalf_handler (osdev))
 
826
    {
 
827
      MUTEX_EXIT_IRQRESTORE (osdev->mutex, flags);
 
828
#ifdef MUTEX_CHECKS
 
829
      oss_context = saved_context;
 
830
#endif
 
831
      return ISTAT_NONE;
 
832
    }
 
833
 
 
834
  if (osdev->bottomhalf_handler != NULL)
 
835
    osdev->bottomhalf_handler (osdev);
 
836
 
 
837
  MUTEX_EXIT_IRQRESTORE (osdev->mutex, flags);
 
838
#ifdef MUTEX_CHECKS
 
839
  oss_context = saved_context;
 
840
#endif
 
841
 
 
842
  return ISTAT_ASSERTED;
 
843
}
 
844
 
 
845
int
 
846
oss_register_interrupts (oss_device_t * osdev, int intrnum,
 
847
                         oss_tophalf_handler_t top,
 
848
                         oss_bottomhalf_handler_t bottom)
 
849
{
 
850
  int err;
 
851
 
 
852
  if (intrnum != 0)
 
853
    {
 
854
      cmn_err (CE_WARN, "Bad interrupt index (%d) for %s\n", intrnum,
 
855
               osdev->name);
 
856
      return OSS_EINVAL;
 
857
    }
 
858
 
 
859
  if (osdev == NULL)
 
860
    {
 
861
      cmn_err (CE_WARN, "oss_register_interrupts: Bad osdev\n");
 
862
      return OSS_EINVAL;
 
863
    }
 
864
 
 
865
  if (osdev->tophalf_handler != NULL || osdev->bottomhalf_handler != NULL)
 
866
    {
 
867
      cmn_err (CE_WARN, "Interrupts already registered for %s\n",
 
868
               osdev->name);
 
869
      return OSS_EINVAL;
 
870
    }
 
871
 
 
872
  if (top == NULL)
 
873
    {
 
874
      cmn_err (CE_WARN, "Bad interrupt handler for %s\n", osdev->name);
 
875
      return OSS_EINVAL;
 
876
    }
 
877
 
 
878
  osdev->tophalf_handler = top;
 
879
  osdev->bottomhalf_handler = bottom;
 
880
  if (cm_intr_attach
 
881
      (osdev->key, ossintr, osdev, osdev->drvinfo, &osdev->intr_cookie) == 0)
 
882
    {
 
883
      cmn_err (CE_WARN, "cm_intr_attach failed for %s\n", osdev->nick);
 
884
    }
 
885
 
 
886
  return 0;
 
887
}
 
888
 
 
889
void
 
890
oss_unregister_interrupts (oss_device_t * osdev)
 
891
{
 
892
  if (osdev->intr_cookie != NULL)
 
893
    cm_intr_detach (osdev->intr_cookie);
 
894
  osdev->intr_cookie = NULL;
 
895
}
 
896
 
 
897
static char *
 
898
ksprintn (ul, base, lenp)
 
899
     register u_long ul;
 
900
     register int base, *lenp;
 
901
{                               /* A long in base 8, plus NULL. */
 
902
  static char buf[sizeof (long) * NBBY / 3 + 2];
 
903
  register char *p;
 
904
 
 
905
  p = buf;
 
906
  do
 
907
    {
 
908
      *++p = "0123456789abcdef"[ul % base];
 
909
    }
 
910
  while (ul /= base);
 
911
  if (lenp)
 
912
    *lenp = p - buf;
 
913
  return (p);
 
914
}
 
915
 
 
916
int
 
917
oss_sprintf (char *buf, char *cfmt, ...)
 
918
{
 
919
  const char *fmt = cfmt;
 
920
  register char *p, *bp;
 
921
  register int ch, base;
 
922
  unsigned long ul;
 
923
  int lflag;
 
924
  int count = 10;
 
925
  va_list ap;
 
926
 
 
927
  va_start (ap, fmt);
 
928
  for (bp = buf;;)
 
929
    {
 
930
      while ((ch = *(unsigned char *) fmt++) != '%')
 
931
        if ((*bp++ = ch) == '\0')
 
932
          {
 
933
            va_end (ap);
 
934
            return ((bp - buf) - 1);
 
935
          }
 
936
 
 
937
      lflag = 0;
 
938
    reswitch:
 
939
      switch (ch = *(unsigned char *) fmt++)
 
940
        {
 
941
        case 'l':
 
942
          lflag = 1;
 
943
          goto reswitch;
 
944
 
 
945
        case '0':
 
946
        case '1':
 
947
        case '2':
 
948
        case '3':
 
949
        case '4':
 
950
        case '5':
 
951
        case '6':
 
952
        case '7':
 
953
        case '8':
 
954
        case '9':
 
955
          goto reswitch;
 
956
 
 
957
        case 'c':
 
958
          *bp++ = va_arg (ap, int);
 
959
          break;
 
960
 
 
961
        case 's':
 
962
          p = va_arg (ap, char *);
 
963
          while (*bp++ = *p++)
 
964
            ;
 
965
          --bp;
 
966
          break;
 
967
 
 
968
        case 'd':
 
969
          ul = lflag ? va_arg (ap, long) : va_arg (ap, int);
 
970
          if ((long) ul < 0)
 
971
            {
 
972
              *bp++ = '-';
 
973
              ul = -(long) ul;
 
974
            }
 
975
          base = 10;
 
976
          goto number;
 
977
          break;
 
978
 
 
979
        case 'o':
 
980
          ul = lflag ? va_arg (ap, unsigned long) : va_arg (ap, unsigned int);
 
981
          base = 8;
 
982
          goto number;
 
983
          break;
 
984
 
 
985
        case 'u':
 
986
          ul = lflag ? va_arg (ap, unsigned long) : va_arg (ap, unsigned int);
 
987
          base = 10;
 
988
          goto number;
 
989
          break;
 
990
 
 
991
        case 'x':
 
992
          ul = lflag ? va_arg (ap, unsigned long) : va_arg (ap, unsigned int);
 
993
          base = 16;
 
994
        number:
 
995
          for (p = (char *) ksprintn (ul, base, NULL); ch = *p--;)
 
996
            *bp++ = ch;
 
997
          break;
 
998
 
 
999
        default:
 
1000
          *bp++ = '%';
 
1001
          if (lflag)
 
1002
            *bp++ = 'l';
 
1003
          /* FALLTHROUGH */
 
1004
 
 
1005
        case '%':
 
1006
          *bp++ = ch;
 
1007
        }
 
1008
    }
 
1009
 
 
1010
  /* va_end(ap); */
 
1011
}
 
1012
 
 
1013
static physreq_t *
 
1014
build_physreq (int bits)
 
1015
{
 
1016
  physreq_t *pr;
 
1017
  long long tmp;
 
1018
 
 
1019
  if ((pr = physreq_alloc (KM_SLEEP)) == NULL)
 
1020
    return NULL;
 
1021
 
 
1022
  pr->phys_align = 4096;
 
1023
  pr->phys_boundary = 0;
 
1024
  pr->phys_dmasize = bits;
 
1025
  pr->phys_max_scgth = 0;
 
1026
  pr->phys_flags = PREQ_PHYSCONTIG;
 
1027
 
 
1028
  if (physreq_prep (pr, KM_SLEEP) != B_TRUE)
 
1029
    {
 
1030
      cmn_err (CE_WARN, "osscore: physreq_prep failed\n");
 
1031
    }
 
1032
 
 
1033
  return pr;
 
1034
}
 
1035
 
 
1036
/*
 
1037
 * Driver info device file
 
1038
 */
 
1039
static int drvinfo_busy = 0;
 
1040
static int drvinfo_len = 0, drvinfo_ptr = 0;
 
1041
static char *drvinfo_buf = NULL;
 
1042
#define DRVINFO_SIZE 4096
 
1043
 
 
1044
static int
 
1045
drvinfo_open (int dev, int dev_class, struct fileinfo *file,
 
1046
              int recursive, int open_flags, int *redirect)
 
1047
{
 
1048
  int i;
 
1049
 
 
1050
  if (drvinfo_busy)
 
1051
    return OSS_EBUSY;
 
1052
  drvinfo_busy = 1;
 
1053
 
 
1054
  if ((drvinfo_buf = KERNEL_MALLOC (DRVINFO_SIZE)) == NULL)
 
1055
    {
 
1056
      cmn_err (CE_WARN, "Cannot allocate drvinfo buffer\n");
 
1057
      return OSS_ENOMEM;
 
1058
    }
 
1059
 
 
1060
  drvinfo_len = 0;
 
1061
  drvinfo_ptr = 0;
 
1062
 
 
1063
  for (i = 1; i < oss_num_cdevs; i++)
 
1064
    if (oss_cdevs[i]->name[0] != 'N' || oss_cdevs[i]->name[1] != 'O' || oss_cdevs[i]->name[2] != 'N' || oss_cdevs[i]->name[3] != 'E')   /* Not a dummy placeholder device */
 
1065
      if (DRVINFO_SIZE - drvinfo_len > 32)
 
1066
        {
 
1067
          char *s = drvinfo_buf + drvinfo_len;
 
1068
 
 
1069
          drvinfo_len +=
 
1070
            oss_sprintf (s, "%s %s %d\n", oss_cdevs[i]->name,
 
1071
                         oss_cdevs[i]->osdev->nick, i);
 
1072
 
 
1073
        }
 
1074
 
 
1075
  return 0;
 
1076
}
 
1077
 
 
1078
static void
 
1079
drvinfo_close (int dev, struct fileinfo *file)
 
1080
{
 
1081
  KERNEL_FREE (drvinfo_buf);
 
1082
  drvinfo_buf = NULL;
 
1083
  drvinfo_len = 0;
 
1084
  drvinfo_ptr = 0;
 
1085
  drvinfo_busy = 0;
 
1086
}
 
1087
 
 
1088
static int
 
1089
drvinfo_read (int dev, struct fileinfo *file, uio_t * buf, int count)
 
1090
{
 
1091
  /*
 
1092
   * Return at most 'count' bytes from the drvinfo_buf.
 
1093
   */
 
1094
  int l, c;
 
1095
 
 
1096
  l = count;
 
1097
  c = drvinfo_len - drvinfo_ptr;
 
1098
 
 
1099
  if (l > c)
 
1100
    l = c;
 
1101
  if (l <= 0)
 
1102
    return 0;
 
1103
 
 
1104
  if (uiomove (&drvinfo_buf[drvinfo_ptr], l, UIO_READ, buf) != 0)
 
1105
    return OSS_EFAULT;
 
1106
  drvinfo_ptr += l;
 
1107
 
 
1108
  return l;
 
1109
}
 
1110
 
 
1111
static oss_cdev_drv_t drvinfo_cdev_drv = {
 
1112
  drvinfo_open,
 
1113
  drvinfo_close,
 
1114
  drvinfo_read
 
1115
};
 
1116
 
 
1117
static void
 
1118
install_drvinfo (oss_device_t * osdev)
 
1119
{
 
1120
  oss_install_chrdev (osdev, "ossinfo", OSS_DEV_MISC, 0, &drvinfo_cdev_drv,
 
1121
                      0);
 
1122
}
 
1123
 
 
1124
/*
 
1125
 * Driver entry point routines
 
1126
 */
 
1127
 
 
1128
int
 
1129
_load ()
 
1130
{
 
1131
  int err = 0;
 
1132
  oss_device_t *osdev;
 
1133
  time_t t;
 
1134
 
 
1135
  if ((err = drv_attach (&oss_drvinfo)) != 0)
 
1136
    {
 
1137
      cmn_err (CE_WARN, "drv_attach failed %d\n", err);
 
1138
      return err;
 
1139
    }
 
1140
 
 
1141
#ifdef LICENSED_VERSION
 
1142
  if (drv_getparm (TIME, &t) != 0)
 
1143
    {
 
1144
      cmn_err (CE_WARN, "drv_getparm(TIME) failed\n");
 
1145
      return EBUSY;
 
1146
    }
 
1147
 
 
1148
  if (!oss_license_handle_time (t))
 
1149
    {
 
1150
      cmn_err (CE_WARN, "This version of Open Sound System has expired\n");
 
1151
      cmn_err (CE_CONT,
 
1152
               "Please download the latest version from www.opensound.com\n");
 
1153
      oss_expired = 1;
 
1154
    }
 
1155
#endif
 
1156
 
 
1157
  if ((osdev = osdev_create (NULL, DRV_VIRTUAL, 0, "oss", NULL)) == NULL)
 
1158
    {
 
1159
      cmn_err (CE_WARN, "Creating osdev failed\n");
 
1160
      return ENOMEM;
 
1161
    }
 
1162
 
 
1163
/*
 
1164
 * Allocate physrec structures for various memory ranges. Remember to free them in the _load
 
1165
 * entry point.
 
1166
 */
 
1167
  physreq_isa = build_physreq (24);
 
1168
  physreq_28bit = build_physreq (28);
 
1169
  physreq_30bit = build_physreq (30);
 
1170
  physreq_31bit = build_physreq (31);
 
1171
  physreq_32bit = build_physreq (32);
 
1172
 
 
1173
/*
 
1174
 * Create the BCB structure
 
1175
 */
 
1176
  oss_bcb = bcb_alloc (KM_SLEEP);
 
1177
  oss_bcb->bcb_addrtypes = BA_UIO;
 
1178
  oss_bcb->bcb_flags = 0;
 
1179
  oss_bcb->bcb_max_xfer = 0;
 
1180
  oss_bcb->bcb_granularity = 1;
 
1181
  oss_bcb->bcb_physreqp = physreq_32bit;
 
1182
  bcb_prep (oss_bcb, KM_SLEEP);
 
1183
 
 
1184
  install_drvinfo (osdev);
 
1185
  oss_common_init (osdev);
 
1186
 
 
1187
  oss_register_device (osdev, "OSS core services");
 
1188
 
 
1189
  return 0;
 
1190
}
 
1191
 
 
1192
int
 
1193
_unload ()
 
1194
{
 
1195
  int i;
 
1196
  static int already_unloaded = 0;
 
1197
 
 
1198
  if (oss_open_devices > 0)
 
1199
    return EBUSY;
 
1200
  drv_detach (&oss_drvinfo);
 
1201
 
 
1202
  if (already_unloaded)
 
1203
    return 0;
 
1204
  already_unloaded = 1;
 
1205
 
 
1206
  oss_unload_drivers ();
 
1207
 
 
1208
  physreq_free (physreq_isa);
 
1209
  physreq_free (physreq_28bit);
 
1210
  physreq_free (physreq_30bit);
 
1211
  physreq_free (physreq_31bit);
 
1212
  physreq_free (physreq_32bit);
 
1213
 
 
1214
  bcb_free (oss_bcb);
 
1215
 
 
1216
  for (i = 0; i < oss_nblocks; i++)
 
1217
    KERNEL_FREE (oss_mem_blocks[i]);
 
1218
  oss_nblocks = 0;
 
1219
 
 
1220
  return 0;
 
1221
}
 
1222
 
 
1223
void
 
1224
oss_pci_byteswap (oss_device_t * osdev, int mode)
 
1225
{
 
1226
  // NOP
 
1227
}
 
1228
 
 
1229
void
 
1230
oss_pcie_init (oss_device_t * osdev, int flags)
 
1231
{
 
1232
        /* TODO: Should we do something? */
 
1233
}
 
1234
 
 
1235
int
 
1236
pci_read_config_byte (oss_device_t * osdev, offset_t where,
 
1237
                      unsigned char *val)
 
1238
{
 
1239
  *val = 0;
 
1240
  if (cm_read_devconfig (osdev->key, where, val, sizeof (*val)) ==
 
1241
      sizeof (*val))
 
1242
    return PCIBIOS_SUCCESSFUL;
 
1243
 
 
1244
  return PCIBIOS_FAILED;
 
1245
}
 
1246
 
 
1247
int
 
1248
pci_read_config_irq (oss_device_t * osdev, offset_t where, unsigned char *val)
 
1249
{
 
1250
  *val = 0;
 
1251
  if (cm_read_devconfig (osdev->key, where, val, sizeof (*val)) ==
 
1252
      sizeof (*val))
 
1253
    return PCIBIOS_SUCCESSFUL;
 
1254
 
 
1255
  return PCIBIOS_FAILED;
 
1256
}
 
1257
 
 
1258
 
 
1259
int
 
1260
pci_read_config_word (oss_device_t * osdev, offset_t where,
 
1261
                      unsigned short *val)
 
1262
{
 
1263
  *val = 0;
 
1264
#if 1
 
1265
  if (cm_read_devconfig (osdev->key, where, val, sizeof (*val)) ==
 
1266
      sizeof (*val))
 
1267
    return PCIBIOS_SUCCESSFUL;
 
1268
#else
 
1269
  switch (where)
 
1270
    {
 
1271
    case PCI_VENDOR_ID:
 
1272
      *val = osdev->vendor;
 
1273
      return PCIBIOS_SUCCESSFUL;
 
1274
      break;
 
1275
 
 
1276
    case PCI_DEVICE_ID:
 
1277
      *val = osdev->product;
 
1278
      return PCIBIOS_SUCCESSFUL;
 
1279
      break;
 
1280
 
 
1281
    }
 
1282
 
 
1283
#endif
 
1284
  return PCIBIOS_FAILED;
 
1285
}
 
1286
 
 
1287
int
 
1288
pci_read_config_dword (oss_device_t * osdev, offset_t where,
 
1289
                       unsigned int *val)
 
1290
{
 
1291
  *val = 0;
 
1292
  if (cm_read_devconfig (osdev->key, where, val, sizeof (*val)) ==
 
1293
      sizeof (*val))
 
1294
    return PCIBIOS_SUCCESSFUL;
 
1295
 
 
1296
  return PCIBIOS_FAILED;
 
1297
}
 
1298
 
 
1299
int
 
1300
pci_write_config_byte (oss_device_t * osdev, offset_t where,
 
1301
                       unsigned char val)
 
1302
{
 
1303
  if (cm_write_devconfig (osdev->key, where, &val, sizeof (val)) ==
 
1304
      sizeof (val))
 
1305
    return PCIBIOS_SUCCESSFUL;
 
1306
 
 
1307
  return PCIBIOS_FAILED;
 
1308
}
 
1309
 
 
1310
int
 
1311
pci_write_config_word (oss_device_t * osdev, offset_t where,
 
1312
                       unsigned short val)
 
1313
{
 
1314
  if (cm_write_devconfig (osdev->key, where, &val, sizeof (val)) ==
 
1315
      sizeof (val))
 
1316
    return PCIBIOS_SUCCESSFUL;
 
1317
 
 
1318
  return PCIBIOS_FAILED;
 
1319
}
 
1320
 
 
1321
int
 
1322
pci_write_config_dword (oss_device_t * osdev, offset_t where,
 
1323
                        unsigned int val)
 
1324
{
 
1325
  if (cm_write_devconfig (osdev->key, where, &val, sizeof (val)) ==
 
1326
      sizeof (val))
 
1327
    return PCIBIOS_SUCCESSFUL;
 
1328
 
 
1329
  return PCIBIOS_FAILED;
 
1330
}
 
1331
 
 
1332
/*
 
1333
 * Entry point routines
 
1334
 */
 
1335
static int
 
1336
oss_config (cfg_func_t func, void *idata, rm_key_t key)
 
1337
{
 
1338
  return EOPNOTSUPP;
 
1339
}
 
1340
 
 
1341
int
 
1342
oss_devinfo (void *idata, channel_t channel, di_parm_t parm, void *valp)
 
1343
{
 
1344
  switch (parm)
 
1345
    {
 
1346
    case DI_MEDIA:
 
1347
      break;
 
1348
 
 
1349
    case DI_SIZE:
 
1350
      break;
 
1351
 
 
1352
    case DI_RBCBP:
 
1353
      *(bcb_t **) valp = oss_bcb;
 
1354
      return 0;
 
1355
      break;
 
1356
 
 
1357
    case DI_WBCBP:
 
1358
      *(bcb_t **) valp = oss_bcb;
 
1359
      return 0;
 
1360
      break;
 
1361
 
 
1362
    case DI_PHYS_HINT:
 
1363
      break;
 
1364
 
 
1365
    }
 
1366
  return EOPNOTSUPP;
 
1367
}
 
1368
 
 
1369
void
 
1370
oss_biostart (void *idata, channel_t channel, buf_t * bp)
 
1371
{
 
1372
  int dev = channel;
 
1373
  oss_cdev_t *cdev;
 
1374
  int count = bp->b_un.b_uio->uio_resid;
 
1375
  int retval;
 
1376
 
 
1377
  if ((cdev = oss_cdevs[dev]) == NULL)
 
1378
    {
 
1379
      bioerror (bp, ENXIO);
 
1380
      biodone (bp);
 
1381
      return;
 
1382
    }
 
1383
 
 
1384
  cdev->file.acc_flags = 0;
 
1385
 
 
1386
  if (bp->b_flags & B_READ)
 
1387
    {
 
1388
      /* Read operation */
 
1389
      if (cdev->d->read == NULL)
 
1390
        {
 
1391
          bioerror (bp, ENXIO);
 
1392
          biodone (bp);
 
1393
          return;
 
1394
        }
 
1395
      retval =
 
1396
        cdev->d->read (cdev->instance, &cdev->file, bp->b_un.b_uio, count);
 
1397
      if (retval < 0)
 
1398
        bioerror (bp, -retval);
 
1399
      else if (retval < count)
 
1400
        bp->b_resid = count - retval;
 
1401
 
 
1402
      biodone (bp);
 
1403
      return;
 
1404
    }
 
1405
 
 
1406
  /* Write operation */
 
1407
  if (cdev->d->write == NULL)
 
1408
    {
 
1409
      bioerror (bp, ENXIO);
 
1410
      biodone (bp);
 
1411
      return;
 
1412
    }
 
1413
  retval =
 
1414
    cdev->d->write (cdev->instance, &cdev->file, bp->b_un.b_uio, count);
 
1415
  if (retval < 0)
 
1416
    bioerror (bp, -retval);
 
1417
  else if (retval < count)
 
1418
    bp->b_resid = count - retval;
 
1419
 
 
1420
  biodone (bp);
 
1421
}
 
1422
 
 
1423
int
 
1424
oss_open (void *idata, channel_t * channelp,
 
1425
          int open_flags, cred_t * crp, queue_t * q)
 
1426
{
 
1427
  oss_device_t *osdev;
 
1428
  int dev = *channelp, tmpdev;
 
1429
  oss_cdev_t *cdev;
 
1430
  int retval;
 
1431
 
 
1432
  osdev = idata;
 
1433
 
 
1434
  if (dev >= OSS_MAX_CDEVS)
 
1435
    return ENXIO;
 
1436
 
 
1437
  if (dev >= oss_num_cdevs)
 
1438
    {
 
1439
      return ENODEV;
 
1440
    }
 
1441
 
 
1442
  if ((cdev = oss_cdevs[dev]) == NULL || cdev->d == NULL)
 
1443
    return ENODEV;
 
1444
 
 
1445
  if (cdev->d->open == NULL)
 
1446
    {
 
1447
      return ENODEV;
 
1448
    }
 
1449
 
 
1450
  memset (&cdev->file, 0, sizeof (cdev->file));
 
1451
  cdev->file.mode = 0;
 
1452
  cdev->file.acc_flags = open_flags;
 
1453
 
 
1454
  if (open_flags & FREAD && open_flags & FWRITE)
 
1455
    cdev->file.mode = OPEN_READWRITE;
 
1456
  else if (open_flags & FREAD)
 
1457
    cdev->file.mode = OPEN_READ;
 
1458
  else if (open_flags & FWRITE)
 
1459
    cdev->file.mode = OPEN_WRITE;
 
1460
 
 
1461
  tmpdev = dev;
 
1462
  retval =
 
1463
    cdev->d->open (cdev->instance, cdev->dev_class, &cdev->file, 0, 0, &tmpdev);
 
1464
  *channelp = tmpdev;
 
1465
  dev = tmpdev;
 
1466
 
 
1467
  if (retval < 0)
 
1468
    {
 
1469
      return -retval;
 
1470
    }
 
1471
 
 
1472
  oss_open_devices++;
 
1473
  cdev->open_count++;
 
1474
 
 
1475
  return 0;
 
1476
}
 
1477
 
 
1478
int
 
1479
oss_close (void *idata, channel_t channel,
 
1480
           int oflags, cred_t * crp, queue_t * q)
 
1481
{
 
1482
  oss_cdev_t *cdev;
 
1483
  int dev;
 
1484
 
 
1485
  dev = channel;
 
1486
 
 
1487
  if (dev >= OSS_MAX_CDEVS)
 
1488
    return ENXIO;
 
1489
 
 
1490
  if ((cdev = oss_cdevs[dev]) == NULL)
 
1491
    return ENXIO;
 
1492
 
 
1493
  if (cdev->open_count == 0)    /* Not opened */
 
1494
    return 0;
 
1495
 
 
1496
  cdev->d->close (cdev->instance, &cdev->file);
 
1497
 
 
1498
  oss_open_devices--;
 
1499
  cdev->open_count--;
 
1500
  return 0;
 
1501
}
 
1502
 
 
1503
int
 
1504
oss_ioctl (void *idata, channel_t channel, int cmd, void *arg,
 
1505
           int oflags, cred_t * crp, int *rvalp)
 
1506
{
 
1507
  int dev = channel;
 
1508
  int retval;
 
1509
  int len = 0;
 
1510
  char localbuf[256];           /* All frequently used ioctl calls fit in 256 bytes */
 
1511
  char *buf = localbuf, *auxbuf = NULL;
 
1512
  oss_cdev_t *cdev;
 
1513
 
 
1514
  if ((cdev = oss_cdevs[dev]) == NULL || cdev->d->ioctl == NULL)
 
1515
    return *rvalp = ENXIO;
 
1516
 
 
1517
  if (oss_expired)
 
1518
    return *rvalp = ENODEV;
 
1519
 
 
1520
  if (cmd & (SIOC_OUT | SIOC_IN))
 
1521
    {
 
1522
 
 
1523
      len = __SIOC_SIZE (cmd);
 
1524
      if (len < 0)
 
1525
        len = 0;
 
1526
      if (len > sizeof (localbuf))
 
1527
        {
 
1528
          /*
 
1529
           * For the few largest ioctl calls we need to allocate an off-stack
 
1530
           * buffer because otherwise the kernel stack will overflow.
 
1531
           * This approach is slower but fortunately "sane" applications don't
 
1532
           * use these ioctl calls too frequently.
 
1533
           */
 
1534
          if ((auxbuf = KERNEL_MALLOC (len)) == NULL)
 
1535
            {
 
1536
              cmn_err (CE_WARN,
 
1537
                       "Failed to allocate an ioctl buffer of %d bytes\n",
 
1538
                       len);
 
1539
              return *rvalp = ENOMEM;
 
1540
            }
 
1541
          buf = auxbuf;
 
1542
        }
 
1543
 
 
1544
      if ((cmd & SIOC_IN) && len > 0)
 
1545
        {
 
1546
          if (copyin ((char *) arg, buf, len) == -1)
 
1547
            {
 
1548
              if (auxbuf != NULL)
 
1549
                KERNEL_FREE (auxbuf);
 
1550
              return *rvalp = EFAULT;
 
1551
            }
 
1552
        }
 
1553
 
 
1554
    }
 
1555
 
 
1556
  retval = cdev->d->ioctl (cdev->instance, &cdev->file, cmd, (ioctl_arg) buf);
 
1557
 
 
1558
  if ((cmd & SIOC_OUT) && len > 0)
 
1559
    {
 
1560
      if (copyout (buf, (char *) arg, len) == -1)
 
1561
        {
 
1562
          if (auxbuf != NULL)
 
1563
            KERNEL_FREE (auxbuf);
 
1564
          return *rvalp = EFAULT;
 
1565
        }
 
1566
    }
 
1567
 
 
1568
  *rvalp = (((retval) < 0) ? -(retval) : 0);
 
1569
 
 
1570
  if (auxbuf != NULL)
 
1571
    KERNEL_FREE (auxbuf);
 
1572
 
 
1573
  return *rvalp;
 
1574
}
 
1575
 
 
1576
#ifdef MUTEX_CHECKS
 
1577
 
 
1578
typedef struct
 
1579
{
 
1580
  int active;
 
1581
  void *mutex;
 
1582
  const char *filename;
 
1583
  int line;
 
1584
  int context;
 
1585
} mutex_debug_t;
 
1586
 
 
1587
static mutex_debug_t mutex_tab[1024];
 
1588
static int n_mutexes = 0;
 
1589
 
 
1590
void
 
1591
push_mutex (void *mutex, const char *file, int line)
 
1592
{
 
1593
  int i, n = -1;
 
1594
//cmn_err(CE_CONT, "Push mutex %08x, %s:%d, context=%d\n", mutex, file, line, oss_context);
 
1595
 
 
1596
  for (i = 0; n == -1 && i < n_mutexes; i++)
 
1597
    if (!mutex_tab[i].active)
 
1598
      n = i;
 
1599
    else
 
1600
      {
 
1601
        if (mutex_tab[i].mutex == mutex
 
1602
            && mutex_tab[i].context == oss_context)
 
1603
          {
 
1604
            cmn_err (CE_NOTE, "Mutex %08x already held\n", mutex);
 
1605
            cmn_err (CE_CONT, "  Locked by %s:%d\n", mutex_tab[i].filename,
 
1606
                     mutex_tab[i].line);
 
1607
            cmn_err (CE_CONT, "  Acquire by %s:%d\n", file, line);
 
1608
          }
 
1609
      }
 
1610
 
 
1611
  if (n == -1)
 
1612
    {
 
1613
      if (n_mutexes >= 1024)
 
1614
        {
 
1615
          cmn_err (CE_NOTE, "Mutex debug table full\n");
 
1616
          return;
 
1617
        }
 
1618
      n = n_mutexes++;
 
1619
    }
 
1620
 
 
1621
  mutex_tab[n].active = 1;
 
1622
  mutex_tab[n].mutex = mutex;
 
1623
  mutex_tab[n].filename = file;
 
1624
  mutex_tab[n].line = line;
 
1625
  mutex_tab[n].context = oss_context;
 
1626
}
 
1627
 
 
1628
void
 
1629
pop_mutex (void *mutex, const char *file, int line)
 
1630
{
 
1631
  int i;
 
1632
 
 
1633
//cmn_err(CE_CONT, "Pop mutex %08x, %s:%d, context=%d\n", mutex, file, line, oss_context);
 
1634
  for (i = 0; i < n_mutexes; i++)
 
1635
    if (mutex_tab[i].active && mutex_tab[i].mutex == mutex
 
1636
        && mutex_tab[i].context == oss_context)
 
1637
      {
 
1638
        mutex_tab[i].active = 0;
 
1639
        mutex_tab[i].filename = file;
 
1640
        mutex_tab[i].line = line;
 
1641
        return;
 
1642
      }
 
1643
 
 
1644
  cmn_err (CE_NOTE, "Mutex %08x not locked (%s:%d), context=%d\n",
 
1645
           mutex, file, line, oss_context);
 
1646
  for (i = 0; i < n_mutexes; i++)
 
1647
    if (mutex_tab[i].active == 0 && mutex_tab[i].mutex == mutex)
 
1648
      {
 
1649
        cmn_err (CE_CONT, "  Previous unlock at %s:%d, context=%d\n",
 
1650
                 mutex_tab[i].filename, mutex_tab[i].line,
 
1651
                 mutex_tab[i].context);
 
1652
      }
 
1653
}
 
1654
 
 
1655
void
 
1656
print_mutexes (void)
 
1657
{
 
1658
  int i, n = 0;
 
1659
 
 
1660
  for (i = 0; i < n_mutexes; i++)
 
1661
    if (mutex_tab[i].active)
 
1662
      n++;
 
1663
 
 
1664
  cmn_err (CE_CONT, "%d mutexes held\n", n);
 
1665
 
 
1666
  for (i = 0; i < n_mutexes; i++)
 
1667
    if (mutex_tab[i].active)
 
1668
      cmn_err (CE_CONT, "   %08x %s:%d\n", mutex_tab[i].mutex,
 
1669
               mutex_tab[i].filename, mutex_tab[i].line);
 
1670
}
 
1671
#endif
 
1672
 
 
1673
int
 
1674
oss_get_procinfo(int what)
 
1675
{
 
1676
        // TODO
 
1677
 
 
1678
        return OSS_EINVAL;
 
1679
}