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

« back to all changes in this revision

Viewing changes to kernel/drv/oss_cs4281/oss_cs4281.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: Driver for Crystal PCI audio controller.
 
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_cs4281_cfg.h"
 
17
#include "midi_core.h"
 
18
#include "ac97.h"
 
19
#include "oss_pci.h"
 
20
#include "cs4281.h"
 
21
 
 
22
#define CRYSTAL_VENDOR_ID       0x1013
 
23
#define CRYSTAL_CS4281_ID       0x6005
 
24
 
 
25
#if 1
 
26
#define WRITEB(a,d) devc->bRegister0[a] = d
 
27
#define READB(a) devc->bRegister0[a]
 
28
#define WRITEW(a,d) devc->wRegister0[a>>1] = d
 
29
#define READW(a) devc->wRegister0[a>>1]
 
30
#define READL(a) (devc->dwRegister0[a>>2])
 
31
#define WRITEL(a, d) devc->dwRegister0[a>>2] = d
 
32
#else
 
33
#define WRITEB(a,d) PCI_WRITEB(devc->osdev, d, devc->bRegister0[a])
 
34
#define READB(a) PCI_READB(devc->osdev, devc->bRegister0[a])
 
35
#define WRITEW(a,d) PCI_WRITEW(devc->osdev, d, devc->wRegister0[a>>1])
 
36
#define READW(a) PCI_READW(devc->osdev, devc->wRegister0[a>>1])
 
37
#define READL(a) PCI_READL(devc->osdev, devc->dwRegister0[a>>2])
 
38
#define WRITEL(a, d) PCI_WRITEL(devc->osdev, d, devc->dwRegister0[a>>2])
 
39
#endif
 
40
 
 
41
#ifdef OSS_BIG_ENDIAN
 
42
static unsigned int
 
43
be_swap (unsigned int x)
 
44
{
 
45
  return ((x & 0x000000ff) << 24) |
 
46
    ((x & 0x0000ff00) << 8) |
 
47
    ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
 
48
}
 
49
 
 
50
#define LSWAP(x) be_swap(x)
 
51
#else
 
52
#define LSWAP(x)        x
 
53
#endif
 
54
 
 
55
#define MAX_PORTC 2
 
56
 
 
57
typedef struct cs4281_portc
 
58
{
 
59
  int speed, bits, channels;
 
60
  int open_mode;
 
61
  int trigger_bits;
 
62
  int audio_enabled;
 
63
  int audiodev;
 
64
}
 
65
cs4281_portc;
 
66
 
 
67
typedef struct cs4281_devc
 
68
{
 
69
  oss_device_t *osdev;
 
70
  char *chip_name;
 
71
  oss_native_word bar0addr, bar1addr;
 
72
  unsigned int *bar0virt, *bar1virt;
 
73
  volatile unsigned int *dwRegister0, *dwRegister1;
 
74
  volatile unsigned short *wRegister0, *wRegister1;
 
75
  volatile unsigned char *bRegister0, *bRegister1;
 
76
  int irq;
 
77
  volatile unsigned char intr_mask;
 
78
  oss_mutex_t mutex;
 
79
  oss_mutex_t low_mutex;
 
80
 
 
81
  /* MIDI */
 
82
  int midi_opened;
 
83
  int midi_dev;
 
84
  oss_midi_inputbyte_t midi_input_intr;
 
85
 
 
86
  /* Mixer parameters */
 
87
  ac97_devc ac97devc;
 
88
  int mixer_dev;
 
89
 
 
90
  /* Audio parameters */
 
91
  cs4281_portc portc[MAX_PORTC];
 
92
  int open_mode;
 
93
  int fm_attached, mpu_attached;
 
94
}
 
95
cs4281_devc;
 
96
 
 
97
 
 
98
 
 
99
static int
 
100
ac97_read (void *devc_, int reg)
 
101
{
 
102
  cs4281_devc *devc = devc_;
 
103
  int count;
 
104
  oss_native_word status, value;
 
105
  oss_native_word flags;
 
106
 
 
107
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
 
108
  /*
 
109
   * Make sure that there is not data sitting around from a previous
 
110
   * uncompleted access. ACSDA = Status Data Register = 47Ch
 
111
   */
 
112
  status = READL (BA0_ACSDA);
 
113
  /* Get the actual AC97 register from the offset */
 
114
  WRITEL (BA0_ACCAD, reg);
 
115
  WRITEL (BA0_ACCDA, 0);
 
116
  WRITEL (BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN);
 
117
 
 
118
  /* Wait for the read to occur. */
 
119
  for (count = 0; count < 500; count++)
 
120
    {
 
121
      /* First, we want to wait for a short time. */
 
122
      oss_udelay (10);
 
123
      /*
 
124
       * Now, check to see if the read has completed.
 
125
       * ACCTL = 460h, DCV should be reset by now and 460h = 17h
 
126
       */
 
127
      status = READL (BA0_ACCTL);
 
128
      if (!(status & ACCTL_DCV))
 
129
        {
 
130
          break;
 
131
        }
 
132
    }
 
133
 
 
134
  /* Make sure the read completed. */
 
135
  if (status & ACCTL_DCV)
 
136
    {
 
137
      cmn_err (CE_WARN, "AC97 Read Timedout\n");
 
138
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
 
139
      return (-1);
 
140
    }
 
141
 
 
142
  /* Wait for the valid status bit to go active. */
 
143
 
 
144
  for (count = 0; count < 500; count++)
 
145
    {
 
146
      /*
 
147
       * Read the AC97 status register.
 
148
       * ACSTS = Status Register = 464h
 
149
       */
 
150
      status = READL (BA0_ACSTS);
 
151
      /*
 
152
       * See if we have valid status.
 
153
       * VSTS - Valid Status
 
154
       */
 
155
      if (status & ACSTS_VSTS)
 
156
        break;
 
157
 
 
158
      /*
 
159
       * Wait for a short while.
 
160
       */
 
161
      oss_udelay (10);
 
162
    }
 
163
  /* Make sure we got valid status. */
 
164
  if (!(status & ACSTS_VSTS))
 
165
    {
 
166
      cmn_err (CE_WARN, "AC97 Read Timedout\n");
 
167
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
 
168
      return (-1);
 
169
    }
 
170
 
 
171
  /*
 
172
   * Read the data returned from the AC97 register.
 
173
   * ACSDA = Status Data Register = 474h
 
174
   */
 
175
  value = READL (BA0_ACSDA);
 
176
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
 
177
  return (value);
 
178
}
 
179
 
 
180
static int
 
181
ac97_write (void *devc_, int reg, int data)
 
182
{
 
183
  cs4281_devc *devc = devc_;
 
184
  int count;
 
185
  oss_native_word status, flags;
 
186
 
 
187
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
 
188
  WRITEL (BA0_ACCAD, reg);
 
189
  WRITEL (BA0_ACCDA, data);
 
190
  WRITEL (BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN);
 
191
  for (count = 0; count < 500; count++)
 
192
    {
 
193
      /* First, we want to wait for a short time. */
 
194
      oss_udelay (10);
 
195
      /* Now, check to see if the write has completed. */
 
196
      /* ACCTL = 460h, DCV should be reset by now and 460h = 07h */
 
197
      status = READL (BA0_ACCTL);
 
198
      if (!(status & ACCTL_DCV))
 
199
        break;
 
200
    }
 
201
 
 
202
  /* write didn't completed. */
 
203
  if (status & ACCTL_DCV)
 
204
    {
 
205
      cmn_err (CE_WARN, "AC97 Write timeout\n");
 
206
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
 
207
      return (-1);
 
208
    }
 
209
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
 
210
  return 0;
 
211
}
 
212
 
 
213
 
 
214
static int
 
215
cs4281intr (oss_device_t * osdev)
 
216
{
 
217
  cs4281_devc *devc = (cs4281_devc *) osdev->devc;
 
218
  cs4281_portc *portc;
 
219
  oss_native_word status, uart_stat;
 
220
  int i;
 
221
  int serviced = 0;
 
222
 
 
223
/* Read the Interrupt Status Register */
 
224
  status = READL (BA0_HISR);
 
225
 
 
226
/*
 
227
 * This is the MIDI read interrupt service. First check to see
 
228
 * if the MIDI interrupt flag is set in the HISR register. Next
 
229
 * read the MIDI status register. See if Receive Buffer Empty 
 
230
 * is empty (0=FIFO Not empty, 1=FIFO is empty
 
231
 */
 
232
  if ((devc->midi_opened & OPEN_READ) && (status & HISR_MIDI))
 
233
    {
 
234
      serviced = 1;
 
235
      uart_stat = READL (BA0_MIDSR);
 
236
/*
 
237
 * read one byte of MIDI data and hand it off the the sequencer module
 
238
 * to decode this. Keep checking to see if the data is available. Stop
 
239
 * when no more data is there in the FIFO.
 
240
 */
 
241
      while (!(uart_stat & MIDSR_RBE))
 
242
        {
 
243
          unsigned char d;
 
244
          d = READL (BA0_MIDRP);
 
245
 
 
246
          if (devc->midi_opened & OPEN_READ && devc->midi_input_intr)
 
247
            devc->midi_input_intr (devc->midi_dev, d);
 
248
          uart_stat = READL (BA0_MIDSR);
 
249
        }
 
250
    }
 
251
/* Audio interrupt handling */
 
252
  if (status & (HISR_INTENA | HISR_DMAI))
 
253
    for (i = 0; i < MAX_PORTC; i++)
 
254
      {
 
255
        portc = &devc->portc[i];
 
256
        if ((status & HISR_DMA0) && (portc->trigger_bits & PCM_ENABLE_OUTPUT))
 
257
          {
 
258
            dmap_t *dmapout = audio_engines[portc->audiodev]->dmap_out;
 
259
            unsigned int currdac;
 
260
            int n;
 
261
 
 
262
            serviced = 1;
 
263
            READL (BA0_HDSR0);  /* ack the DMA interrupt */
 
264
            currdac = READL (BA0_DCA0) - dmapout->dmabuf_phys;
 
265
            currdac /= dmapout->fragment_size;
 
266
            n = 0;
 
267
            while (dmap_get_qhead (dmapout) != currdac
 
268
                   && n++ < dmapout->nfrags)
 
269
              oss_audio_outputintr (portc->audiodev, 1);
 
270
          }
 
271
 
 
272
        if ((status & HISR_DMA1) && (portc->trigger_bits & PCM_ENABLE_INPUT))
 
273
          {
 
274
            dmap_t *dmapin = audio_engines[portc->audiodev]->dmap_in;
 
275
            unsigned int curradc;
 
276
            int n;
 
277
 
 
278
            serviced = 1;
 
279
            READL (BA0_HDSR1);  /* ack the DMA interrupt */
 
280
            curradc = READL (BA0_DCA1) - dmapin->dmabuf_phys;
 
281
            curradc /= dmapin->fragment_size;
 
282
            n = 0;
 
283
            while (dmap_get_qtail (dmapin) != curradc && n++ < dmapin->nfrags)
 
284
              oss_audio_inputintr (portc->audiodev, 0);
 
285
          }
 
286
        WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM);
 
287
      }
 
288
  return serviced;
 
289
}
 
290
 
 
291
static int
 
292
cs4281_audio_set_rate (int dev, int arg)
 
293
{
 
294
  cs4281_portc *portc = audio_engines[dev]->portc;
 
295
  if (arg == 0)
 
296
    return portc->speed;
 
297
  if (arg > 48000)
 
298
    arg = 48000;
 
299
  if (arg < 6023)
 
300
    arg = 6023;
 
301
  portc->speed = arg;
 
302
  return portc->speed;
 
303
}
 
304
 
 
305
static short
 
306
cs4281_audio_set_channels (int dev, short arg)
 
307
{
 
308
  cs4281_portc *portc = audio_engines[dev]->portc;
 
309
  if ((arg != 1) && (arg != 2))
 
310
    return portc->channels;
 
311
  portc->channels = arg;
 
312
  return portc->channels;
 
313
}
 
314
 
 
315
static unsigned int
 
316
cs4281_audio_set_format (int dev, unsigned int arg)
 
317
{
 
318
  cs4281_portc *portc = audio_engines[dev]->portc;
 
319
  if (arg == 0)
 
320
    return portc->bits;
 
321
  if (!(arg & (AFMT_U8 | AFMT_S16_LE)))
 
322
    return portc->bits;
 
323
  portc->bits = arg;
 
324
  return portc->bits;
 
325
}
 
326
 
 
327
/*ARGSUSED*/
 
328
static int
 
329
cs4281_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 
330
{
 
331
  return OSS_EINVAL;
 
332
}
 
333
 
 
334
static void cs4281_audio_trigger (int dev, int state);
 
335
static void
 
336
cs4281_audio_reset (int dev)
 
337
{
 
338
  cs4281_audio_trigger (dev, 0);
 
339
}
 
340
 
 
341
static void
 
342
cs4281_audio_reset_input (int dev)
 
343
{
 
344
  cs4281_portc *portc = audio_engines[dev]->portc;
 
345
  cs4281_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT);
 
346
}
 
347
 
 
348
static void
 
349
cs4281_audio_reset_output (int dev)
 
350
{
 
351
  cs4281_portc *portc = audio_engines[dev]->portc;
 
352
  cs4281_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT);
 
353
}
 
354
 
 
355
/*ARGSUSED*/
 
356
static int
 
357
cs4281_audio_open (int dev, int mode, int open_flags)
 
358
{
 
359
  cs4281_portc *portc = audio_engines[dev]->portc;
 
360
  cs4281_devc *devc = audio_engines[dev]->devc;
 
361
  oss_native_word flags;
 
362
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
363
  if (portc->open_mode)
 
364
    {
 
365
      MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
366
      return OSS_EBUSY;
 
367
    }
 
368
 
 
369
  if (devc->open_mode & mode)
 
370
    {
 
371
      MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
372
      return OSS_EBUSY;
 
373
    }
 
374
 
 
375
  devc->open_mode |= mode;
 
376
  portc->open_mode = mode;
 
377
  portc->audio_enabled &= ~mode;
 
378
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
379
  return 0;
 
380
}
 
381
 
 
382
static void
 
383
cs4281_audio_close (int dev, int mode)
 
384
{
 
385
  cs4281_portc *portc = audio_engines[dev]->portc;
 
386
  cs4281_devc *devc = audio_engines[dev]->devc;
 
387
  cs4281_audio_reset (dev);
 
388
  portc->open_mode = 0;
 
389
  devc->open_mode &= ~mode;
 
390
  portc->audio_enabled &= ~mode;
 
391
}
 
392
 
 
393
/*ARGSUSED*/
 
394
static void
 
395
cs4281_audio_output_block (int dev, oss_native_word buf, int count,
 
396
                           int fragsize, int intrflag)
 
397
{
 
398
  cs4281_portc *portc = audio_engines[dev]->portc;
 
399
 
 
400
  portc->audio_enabled |= PCM_ENABLE_OUTPUT;
 
401
  portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
 
402
}
 
403
 
 
404
/*ARGSUSED*/
 
405
static void
 
406
cs4281_audio_start_input (int dev, oss_native_word buf, int count,
 
407
                          int fragsize, int intrflag)
 
408
{
 
409
  cs4281_portc *portc = audio_engines[dev]->portc;
 
410
 
 
411
  portc->audio_enabled |= PCM_ENABLE_INPUT;
 
412
  portc->trigger_bits &= ~PCM_ENABLE_INPUT;
 
413
}
 
414
 
 
415
static void
 
416
cs4281_audio_trigger (int dev, int state)
 
417
{
 
418
  cs4281_devc *devc = audio_engines[dev]->devc;
 
419
  cs4281_portc *portc = audio_engines[dev]->portc;
 
420
  oss_native_word tmp1;
 
421
  oss_native_word flags;
 
422
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
423
  if (portc->open_mode & OPEN_WRITE)
 
424
    {
 
425
      if (state & PCM_ENABLE_OUTPUT)
 
426
        {
 
427
          if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
 
428
              !(portc->trigger_bits & PCM_ENABLE_OUTPUT))
 
429
            {
 
430
              /* Clear DMA0 channel Mask bit. Start Playing. */
 
431
              tmp1 = READL (BA0_DCR0) & ~DCRn_MSK;      /*enable DMA */
 
432
              WRITEL (BA0_DCR0, tmp1);  /* (154h) */
 
433
              WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM);  /*enable intr */
 
434
              portc->trigger_bits |= PCM_ENABLE_OUTPUT;
 
435
            }
 
436
        }
 
437
      else
 
438
        {
 
439
          if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
 
440
              (portc->trigger_bits & PCM_ENABLE_OUTPUT))
 
441
            {
 
442
              portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
 
443
              portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
 
444
              tmp1 = READL (BA0_DCR0) & ~DCRn_MSK;
 
445
              WRITEL (BA0_DCR0, tmp1 | DCRn_MSK);
 
446
            }
 
447
        }
 
448
    }
 
449
  if (portc->open_mode & OPEN_READ)
 
450
    {
 
451
      if (state & PCM_ENABLE_INPUT)
 
452
        {
 
453
          if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
 
454
              !(portc->trigger_bits & PCM_ENABLE_INPUT))
 
455
            {
 
456
              /* Clear DMA1 channel Mask bit. Start recording. */
 
457
              tmp1 = READL (BA0_DCR1) & ~DCRn_MSK;
 
458
              WRITEL (BA0_DCR1, tmp1);  /* (15ch) */
 
459
              WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM);  /*Set INTENA=1. */
 
460
              portc->trigger_bits |= PCM_ENABLE_INPUT;
 
461
            }
 
462
        }
 
463
      else
 
464
        {
 
465
          if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
 
466
              (portc->trigger_bits & PCM_ENABLE_INPUT))
 
467
            {
 
468
              portc->audio_enabled &= ~PCM_ENABLE_INPUT;
 
469
              portc->trigger_bits &= ~PCM_ENABLE_INPUT;
 
470
              tmp1 = READL (BA0_DCR1) & ~DCRn_MSK;
 
471
              WRITEL (BA0_DCR1, tmp1 | DCRn_MSK);
 
472
            }
 
473
        }
 
474
    }
 
475
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
476
}
 
477
 
 
478
static int
 
479
cs4281_rate (oss_native_word rate)
 
480
{
 
481
  int val = 0;
 
482
 
 
483
  switch (rate)
 
484
    {
 
485
    case 8000:
 
486
      val = 5;
 
487
      break;
 
488
    case 11025:
 
489
      val = 4;
 
490
      break;
 
491
    case 16000:
 
492
      val = 3;
 
493
      break;
 
494
    case 22050:
 
495
      val = 2;
 
496
      break;
 
497
    case 44100:
 
498
      val = 1;
 
499
      break;
 
500
    case 48000:
 
501
      val = 0;
 
502
      break;
 
503
    default:
 
504
      val = 1536000 / rate;
 
505
      break;
 
506
    }
 
507
  return val;
 
508
}
 
509
 
 
510
/*ARGSUSED*/
 
511
static int
 
512
cs4281_audio_prepare_for_input (int dev, int bsize, int bcount)
 
513
{
 
514
  cs4281_devc *devc = audio_engines[dev]->devc;
 
515
  cs4281_portc *portc = audio_engines[dev]->portc;
 
516
  dmap_t *dmap = audio_engines[dev]->dmap_in;
 
517
  int count = dmap->bytes_in_use;
 
518
  oss_native_word recordFormat;
 
519
  oss_native_word flags;
 
520
 
 
521
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
522
  /* set the record rate */
 
523
  WRITEL (BA0_ADCSR, cs4281_rate (portc->speed));       /* (748h) */
 
524
  /* Start with defaults for the record format */
 
525
  /* reg & modify them for the current case. */
 
526
  recordFormat = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE;
 
527
  if (portc->channels == 1)     /* If mono, */
 
528
    recordFormat |= DMRn_MONO;  /* Turn on mono bit. */
 
529
  if (portc->bits == 8)         /* If 8-bit, */
 
530
    recordFormat |= (DMRn_SIZE8 | DMRn_USIGN);  /* turn on 8bit/unsigned. */
 
531
  WRITEL (BA0_DMR1, recordFormat);
 
532
  /* set input gain to 0db */
 
533
  /* ac97_write(devc, BA0_AC97_RECORD_GAIN, 0x0808);  */
 
534
  if (portc->channels == 2)     /* If stereo, */
 
535
    count /= 2;                 /* halve DMA count(stereo); */
 
536
  if (portc->bits == 16)        /* If 16-bit, */
 
537
    count /= 2;
 
538
  /* Set the physical play buffer address DMA1 Base & Current. */
 
539
  WRITEL (BA0_DBA1, dmap->dmabuf_phys); /* (118h) */
 
540
  /* Set the sample count(-1) in DMA Base Count register 1. */
 
541
  WRITEL (BA0_DBC1, count - 1);
 
542
  portc->audio_enabled &= ~PCM_ENABLE_INPUT;
 
543
  portc->trigger_bits &= ~PCM_ENABLE_INPUT;
 
544
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
545
  return 0;
 
546
}
 
547
 
 
548
/*ARGSUSED*/
 
549
static int
 
550
cs4281_audio_prepare_for_output (int dev, int bsize, int bcount)
 
551
{
 
552
  cs4281_devc *devc = audio_engines[dev]->devc;
 
553
  cs4281_portc *portc = audio_engines[dev]->portc;
 
554
  dmap_t *dmap = audio_engines[dev]->dmap_out;
 
555
  int count = dmap->bytes_in_use;
 
556
  oss_native_word playFormat;
 
557
  oss_native_word flags;
 
558
 
 
559
  MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
 
560
  /* Set the sample rate converter */
 
561
  WRITEL (BA0_DACSR, cs4281_rate (portc->speed));
 
562
  playFormat = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ | (1 << 6);
 
563
  if (portc->channels == 1)     /* If stereo, */
 
564
    playFormat |= DMRn_MONO;    /* Turn on mono bit. */
 
565
  if (portc->bits == 8)         /* If 16-bit, */
 
566
    playFormat |= (DMRn_SIZE8 | DMRn_USIGN);    /* turn on 8-bit/unsigned. */
 
567
  WRITEL (BA0_DMR0, playFormat);        /* (150h) */
 
568
  if (portc->channels == 2)     /* If stereo, */
 
569
    count /= 2;                 /* halve DMA count(stereo); */
 
570
  if (portc->bits == 16)        /* If 16-bit, */
 
571
    count /= 2;
 
572
  /* Set the physical play buffer address DMA0 Base & Current. */
 
573
  WRITEL (BA0_DBA0, dmap->dmabuf_phys & ~0x3);  /* (118h) */
 
574
  /* Set the sample count(-1) in DMA Base Count register 0. */
 
575
  WRITEL (BA0_DBC0, count - 1);
 
576
  portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
 
577
  portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
 
578
  MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
579
  return 0;
 
580
}
 
581
 
 
582
static int
 
583
cs4281_get_buffer_pointer (int dev, dmap_t * dmap, int direction)
 
584
{
 
585
  cs4281_devc *devc = audio_engines[dev]->devc;
 
586
  unsigned int ptr = 0;
 
587
  oss_native_word flags;
 
588
 
 
589
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
 
590
 
 
591
  if (direction == PCM_ENABLE_OUTPUT)
 
592
    {
 
593
      ptr = READL (BA0_DCA0);
 
594
    }
 
595
  if (direction == PCM_ENABLE_INPUT)
 
596
    {
 
597
      ptr = READL (BA0_DCA1);
 
598
    }
 
599
  ptr -= dmap->dmabuf_phys;
 
600
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
 
601
  return ptr;
 
602
}
 
603
 
 
604
static audiodrv_t cs4281_audio_driver = {
 
605
  cs4281_audio_open,
 
606
  cs4281_audio_close,
 
607
  cs4281_audio_output_block,
 
608
  cs4281_audio_start_input,
 
609
  cs4281_audio_ioctl,
 
610
  cs4281_audio_prepare_for_input,
 
611
  cs4281_audio_prepare_for_output,
 
612
  cs4281_audio_reset,
 
613
  NULL,
 
614
  NULL,
 
615
  cs4281_audio_reset_input,
 
616
  cs4281_audio_reset_output,
 
617
  cs4281_audio_trigger,
 
618
  cs4281_audio_set_rate,
 
619
  cs4281_audio_set_format,
 
620
  cs4281_audio_set_channels,
 
621
  NULL,
 
622
  NULL,
 
623
  NULL,
 
624
  NULL,
 
625
  NULL,                         /* cs4281_alloc_buffer, */
 
626
  NULL,                         /* cs4281_free_buffer, */
 
627
  NULL,
 
628
  NULL,
 
629
  cs4281_get_buffer_pointer
 
630
};
 
631
 
 
632
/***********************MIDI PORT ROUTINES ****************/
 
633
/*ARGSUSED*/
 
634
static int
 
635
cs4281_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte,
 
636
                  oss_midi_inputbuf_t inputbuf,
 
637
                  oss_midi_outputintr_t outputintr)
 
638
{
 
639
  cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc;
 
640
  if (devc->midi_opened)
 
641
    {
 
642
      return OSS_EBUSY;
 
643
    }
 
644
 
 
645
  devc->midi_input_intr = inputbyte;
 
646
  devc->midi_opened = mode;
 
647
  /* first reset the MIDI port */
 
648
  WRITEL (BA0_MIDCR, 0x10);
 
649
  WRITEL (BA0_MIDCR, 0x00);
 
650
  /* Now check if we're in Read or Write mode */
 
651
  if (mode & OPEN_READ)
 
652
    {
 
653
      /* enable MIDI Input intr and receive enable */
 
654
      WRITEL (BA0_MIDCR, MIDCR_RXE | MIDCR_RIE);
 
655
    }
 
656
 
 
657
  if (mode & OPEN_WRITE)
 
658
    {
 
659
      /* enable MIDI transmit enable */
 
660
      WRITEL (BA0_MIDCR, MIDCR_TXE);
 
661
    }
 
662
  return 0;
 
663
}
 
664
 
 
665
/*ARGSUSED*/
 
666
static void
 
667
cs4281_midi_close (int dev, int mode)
 
668
{
 
669
  cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc;
 
670
/* Reset the device*/
 
671
  WRITEL (BA0_MIDCR, 0x10);
 
672
  WRITEL (BA0_MIDCR, 0x00);
 
673
  devc->midi_opened = 0;
 
674
}
 
675
 
 
676
static int
 
677
cs4281_midi_out (int dev, unsigned char midi_byte)
 
678
{
 
679
  cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc;
 
680
  unsigned char uart_stat = READL (BA0_MIDSR);
 
681
/* Check if Transmit buffer full flag is set - if so return */
 
682
  if ((uart_stat & MIDSR_TBF))
 
683
    return 0;
 
684
/* Now put the MIDI databyte in the write port */
 
685
  WRITEL (BA0_MIDWP, midi_byte);
 
686
  return 1;
 
687
}
 
688
 
 
689
/*ARGSUSED*/
 
690
static int
 
691
cs4281_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
 
692
{
 
693
  return OSS_EINVAL;
 
694
}
 
695
 
 
696
static midi_driver_t cs4281_midi_driver = {
 
697
  cs4281_midi_open,
 
698
  cs4281_midi_close,
 
699
  cs4281_midi_ioctl,
 
700
  cs4281_midi_out
 
701
};
 
702
 
 
703
static int
 
704
init_cs4281 (cs4281_devc * devc)
 
705
{
 
706
 
 
707
  int my_mixer, i;
 
708
  oss_native_word dwAC97SlotID, tmp1;
 
709
  int first_dev = 0;
 
710
/****************BEGIN HARDWARE INIT*****************/
 
711
  /* Setup CFLR */
 
712
  tmp1 = READL (BA0_CFLR);
 
713
  if (tmp1 != 0x01)
 
714
    {
 
715
      WRITEL (BA0_CFLR, 0x01);  /*set up AC97 mode */
 
716
      tmp1 = READL (BA0_CFLR);
 
717
      if (tmp1 != 0x01)
 
718
        {
 
719
          tmp1 = READL (BA0_CWPR);
 
720
          if (tmp1 != 0x4281)
 
721
            WRITEL (BA0_CWPR, 0x4281);
 
722
          tmp1 = READL (BA0_CWPR);
 
723
          if (tmp1 != 0x4281)
 
724
            {
 
725
              cmn_err (CE_WARN, "Resetting AC97 failed\n");
 
726
              return OSS_EIO;
 
727
            }
 
728
          WRITEL (BA0_CFLR, 0x1);
 
729
          tmp1 = READL (BA0_CFLR);
 
730
          if (tmp1 != 0x1)
 
731
            {
 
732
              cmn_err (CE_WARN, "Resetting AC97 still fails\n");
 
733
              return OSS_EIO;
 
734
            }
 
735
        }
 
736
    }
 
737
  /* Setup the FM and Joystick trap address for Legacy emulation */
 
738
  WRITEL (BA0_IOTCR, 0x1);
 
739
  WRITEL (BA0_IOTFM, 0xc0030388);
 
740
  WRITEL (BA0_IOTGP, 0xc0070200);
 
741
  /**************************************** */
 
742
  /*  Set up the Sound System Configuration */
 
743
  /**************************************** */
 
744
  /* Set the 'Configuration Write Protect' register */
 
745
  /* to 4281h.  Allows vendor-defined configuration */
 
746
  /* space between 0e4h and 0ffh to be written. */
 
747
  WRITEL (BA0_CWPR, 0x4281);    /* (3e0h) */
 
748
  if ((tmp1 = READL (BA0_SERC1)) != (SERC1_SO1EN | SERC1_SO1F_AC97))
 
749
    {
 
750
      cmn_err (CE_WARN, "SERC1: AC97 check failed\n");
 
751
      return OSS_EIO;
 
752
    }
 
753
  /* setup power management to full power */
 
754
  WRITEL (BA0_SSPM, 0x7E);
 
755
  /* First, blast the clock control register to zero so that the */
 
756
  /* PLL starts out in a known state, and blast the master serial */
 
757
  /* port control register to zero so that the serial ports also */
 
758
  /* start out in a known state. */
 
759
  WRITEL (BA0_CLKCR1, 0);       /* (400h) */
 
760
  WRITEL (BA0_SERMC, 0);        /* (420h) */
 
761
  /* (1) Drive the ARST# pin low for a minimum of 1uS (as defined in */
 
762
  /* the AC97 spec) and then drive it high.  This is done for non */
 
763
  /* AC97 modes since there might be logic external to the CS461x */
 
764
  /* that uses the ARST# line for a reset. */
 
765
  WRITEL (BA0_ACCTL, 0);
 
766
  oss_udelay (50);
 
767
  WRITEL (BA0_SPMC, 0);         /* (3ech) */
 
768
  oss_udelay (50);
 
769
  WRITEL (BA0_SPMC, SPMC_RSTN);
 
770
  oss_udelay (50000);
 
771
  WRITEL (BA0_SERMC, SERMC_PTC_AC97 | SERMC_MSPE | 0x10000);
 
772
  /* (3) Turn on the Sound System Clocks. */
 
773
  WRITEL (BA0_CLKCR1, CLKCR1_DLLP);     /* (400h) */
 
774
  /* Wait for the PLL to stabilize. */
 
775
  oss_udelay (50000);
 
776
  /* Turn on clocking of the core (CLKCR1(400h) = 0x00000030) */
 
777
  WRITEL (BA0_CLKCR1, CLKCR1_DLLP | CLKCR1_SWCE);
 
778
  /* (5) Wait for clock stabilization. */
 
779
  for (tmp1 = 0; tmp1 < 100; tmp1++)
 
780
    {
 
781
      if (READL (BA0_CLKCR1) & CLKCR1_DLLRDY)
 
782
        break;
 
783
      oss_udelay (50000);
 
784
    }
 
785
  if (!(READL (BA0_CLKCR1) & CLKCR1_DLLRDY))
 
786
    {
 
787
      cmn_err (CE_WARN, "DLLRDY Clock not ready\n");
 
788
      return OSS_EIO;
 
789
    }
 
790
  /* (6) Enable ASYNC generation. */
 
791
  WRITEL (BA0_ACCTL, ACCTL_ESYN);       /* (460h) */
 
792
  /* Now wait 'for a short while' to allow the  AC97 */
 
793
  /* part to start generating bit clock. (so we don't */
 
794
  /* Try to start the PLL without an input clock.) */
 
795
  /* (7) Wait for the codec ready signal from the AC97 codec. */
 
796
  for (tmp1 = 0; tmp1 < 100; tmp1++)
 
797
    {
 
798
      /* Delay a mil to let things settle out and */
 
799
      /* to prevent retrying the read too quickly. */
 
800
      if (READL (BA0_ACSTS) & ACSTS_CRDY)       /* If ready,  (464h) */
 
801
        break;                  /*   exit the 'for' loop. */
 
802
      oss_udelay (50000);
 
803
    }
 
804
  if (!(READL (BA0_ACSTS) & ACSTS_CRDY))        /* If never came ready, */
 
805
    {
 
806
      cmn_err (CE_WARN, "AC97 not ready\n");
 
807
      return OSS_EIO;           /*   exit initialization. */
 
808
    }
 
809
  /* (8) Assert the 'valid frame' signal so we can */
 
810
  /* begin sending commands to the AC97 codec. */
 
811
  WRITEL (BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN);  /* (460h) */
 
812
 
 
813
  /* (11) Wait until we've sampled input slots 3 & 4 as valid, meaning */
 
814
  /* that the codec is pumping ADC data across the AC link. */
 
815
  for (tmp1 = 0; tmp1 < 100; tmp1++)
 
816
    {
 
817
      /* Read the input slot valid register;  See */
 
818
      /* if input slots 3 and 4 are valid yet. */
 
819
      if ((READL (BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) ==    /* (474h) */
 
820
          (ACISV_ISV3 | ACISV_ISV4))
 
821
        break;                  /* Exit the 'for' if slots are valid. */
 
822
      oss_udelay (50000);
 
823
    }
 
824
  /* If we never got valid data, exit initialization. */
 
825
  if ((READL (BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) !=
 
826
      (ACISV_ISV3 | ACISV_ISV4))
 
827
    {
 
828
      cmn_err (CE_WARN, "AC97 Slot not valid\n");
 
829
      return OSS_EIO;           /* If no valid data, exit initialization. */
 
830
    }
 
831
  /* (12) Start digital data transfer of audio data to the codec. */
 
832
  WRITEL (BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);  /* (468h) */
 
833
 
 
834
  /* For playback, we map AC97 slot 3 and 4(Left */
 
835
  /* & Right PCM playback) to DMA Channel 0. */
 
836
  /* Set the fifo to be 31 bytes at offset zero. */
 
837
  dwAC97SlotID = 0x01001F00;    /* FCR0.RS[4:0]=1(=>slot4, right PCM playback). */
 
838
  /* FCR0.LS[4:0]=0(=>slot3, left PCM playback). */
 
839
  /* FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. */
 
840
  WRITEL (BA0_FCR0, dwAC97SlotID);      /* (180h) */
 
841
  WRITEL (BA0_FCR0, dwAC97SlotID | FCRn_FEN);   /* Turn on FIFO Enable. */
 
842
  /* For capture, we map AC97 slot 10 and 11(Left */
 
843
  /* and Right PCM Record) to DMA Channel 1. */
 
844
  /* Set the fifo to be 31 bytes at offset 32. */
 
845
  dwAC97SlotID = 0x0B0A1F20;    /* FCR1.RS[4:0]=11(=>slot11, right PCM record). */
 
846
  /* FCR1.LS[4:0]=10(=>slot10, left PCM record). */
 
847
  /* FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. */
 
848
  WRITEL (BA0_FCR1, dwAC97SlotID);      /* (184h) */
 
849
  WRITEL (BA0_FCR1, dwAC97SlotID | FCRn_FEN);   /* Turn on FIFO Enable. */
 
850
  /* Map the Playback SRC to the same AC97 slots(3 & 4-- */
 
851
  /* --Playback left & right)as DMA channel 0. */
 
852
  /* Map the record SRC to the same AC97 slots(10 & 11-- */
 
853
  /* -- Record left & right) as DMA channel 1. */
 
854
  dwAC97SlotID = 0x0b0a0100;    /*SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback). */
 
855
  /*SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). */
 
856
  /*SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) */
 
857
  /*SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). */
 
858
  WRITEL (BA0_SRCSA, dwAC97SlotID);     /* (75ch) */
 
859
  /* Set 'Half Terminal Count Interrupt Enable' and 'Terminal */
 
860
  /* Count Interrupt Enable' in DMA Control Registers 0 & 1. */
 
861
  /* Set 'MSK' flag to 1 to keep the DMA engines paused. */
 
862
  tmp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK);   /* (00030001h) */
 
863
  WRITEL (BA0_DCR0, tmp1);      /* (154h) */
 
864
  WRITEL (BA0_DCR1, tmp1);      /* (15ch) */
 
865
  /* Set 'Auto-Initialize Control' to 'enabled'; For playback, */
 
866
  /* set 'Transfer Type Control'(TR[1:0]) to 'read transfer', */
 
867
  /* for record, set Transfer Type Control to 'write transfer'. */
 
868
  /* All other bits set to zero;  Some will be changed @ transfer start. */
 
869
  tmp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); /* (20000018h) */
 
870
  WRITEL (BA0_DMR0, tmp1);      /* (150h) */
 
871
  tmp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);        /* (20000014h) */
 
872
  WRITEL (BA0_DMR1, tmp1);      /* (158h) */
 
873
  /* Enable DMA interrupts generally, and */
 
874
  /* DMA0 & DMA1 interrupts specifically. */
 
875
  tmp1 = READL (BA0_HIMR) & 0x7fbbfcff;
 
876
  WRITEL (BA0_HIMR, tmp1);
 
877
  /* set up some volume defaults */
 
878
  WRITEL (BA0_PPLVC, 0x0808);
 
879
  WRITEL (BA0_PPRVC, 0x0808);
 
880
  WRITEL (BA0_FMLVC, 0x0);
 
881
  WRITEL (BA0_FMRVC, 0x0);
 
882
/****** END OF HARDWARE INIT *****/
 
883
 
 
884
 
 
885
  my_mixer =
 
886
    ac97_install (&devc->ac97devc, "CS4281 AC97 Mixer", ac97_read, ac97_write,
 
887
                  devc, devc->osdev);
 
888
  if (my_mixer < 0)
 
889
    {
 
890
      return 0;
 
891
    }
 
892
 
 
893
  devc->mixer_dev = my_mixer;
 
894
 
 
895
  /* ac97_write(devc,  0x26, ac97_read(devc, 0x26) | 0x8000); */
 
896
  for (i = 0; i < MAX_PORTC; i++)
 
897
    {
 
898
      int adev;
 
899
      int caps = 0;
 
900
      cs4281_portc *portc = &devc->portc[i];
 
901
      char tmp_name[100];
 
902
      strcpy (tmp_name, devc->chip_name);
 
903
 
 
904
      if (i == 0)
 
905
        {
 
906
          caps = ADEV_AUTOMODE | ADEV_DUPLEX;
 
907
          strcpy (tmp_name, devc->chip_name);
 
908
        }
 
909
      else
 
910
        {
 
911
          caps = ADEV_AUTOMODE | ADEV_DUPLEX | ADEV_SHADOW;
 
912
          strcpy (tmp_name, devc->chip_name);
 
913
        }
 
914
 
 
915
      if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
 
916
                                        devc->osdev,
 
917
                                        devc->osdev,
 
918
                                        tmp_name,
 
919
                                        &cs4281_audio_driver,
 
920
                                        sizeof (audiodrv_t),
 
921
                                        caps,
 
922
                                        AFMT_S16_LE | AFMT_U8, devc, -1)) < 0)
 
923
        {
 
924
          adev = -1;
 
925
          return 0;
 
926
        }
 
927
      else
 
928
        {
 
929
          if (i == 0)
 
930
            first_dev = adev;
 
931
          audio_engines[adev]->portc = portc;
 
932
          audio_engines[adev]->rate_source = first_dev;
 
933
          audio_engines[adev]->mixer_dev = my_mixer;
 
934
          audio_engines[adev]->min_rate = 6023;
 
935
          audio_engines[adev]->max_rate = 48000;
 
936
          audio_engines[adev]->caps |= PCM_CAP_FREERATE;
 
937
          portc->open_mode = 0;
 
938
          portc->audiodev = adev;
 
939
          portc->audio_enabled = 0;
 
940
#ifdef CONFIG_OSS_VMIX
 
941
          if (i == 0)
 
942
             vmix_attach_audiodev(devc->osdev, adev, -1, 0);
 
943
#endif
 
944
        }
 
945
    }
 
946
 
 
947
  devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "CS4281", "CS4281 MIDI Port", &cs4281_midi_driver, sizeof (midi_driver_t),
 
948
                                        0, devc, devc->osdev);
 
949
  devc->midi_opened = 0;
 
950
  return 1;
 
951
}
 
952
 
 
953
int
 
954
oss_cs4281_attach (oss_device_t * osdev)
 
955
{
 
956
  unsigned char pci_irq_line, pci_revision, pci_irq_inta;
 
957
  unsigned short pci_command, vendor, device;
 
958
  unsigned int ioaddr;
 
959
  int err;
 
960
  cs4281_devc *devc;
 
961
 
 
962
  DDB (cmn_err (CE_WARN, "Entered CS4281 probe routine\n"));
 
963
 
 
964
  pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
 
965
  pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
 
966
 
 
967
  if (vendor != CRYSTAL_VENDOR_ID || device != CRYSTAL_CS4281_ID)
 
968
    return 0;
 
969
 
 
970
  if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
 
971
    {
 
972
      cmn_err (CE_WARN, "Out of memory\n");
 
973
      return 0;
 
974
    }
 
975
 
 
976
  devc->osdev = osdev;
 
977
  osdev->devc = devc;
 
978
 
 
979
  oss_pci_byteswap (osdev, 1);
 
980
 
 
981
  pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
 
982
  pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
 
983
  pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
 
984
  pci_read_config_byte (osdev, PCI_INTERRUPT_LINE + 1, &pci_irq_inta);
 
985
  pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &ioaddr);
 
986
  devc->bar0addr = ioaddr;
 
987
  pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_1, &ioaddr);
 
988
  devc->bar1addr = ioaddr;
 
989
 
 
990
  /* activate the device enable bus master/memory space */
 
991
  pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
 
992
  pci_write_config_word (osdev, PCI_COMMAND, pci_command);
 
993
 
 
994
  if ((devc->bar0addr == 0) || (devc->bar1addr == 0))
 
995
    {
 
996
      cmn_err (CE_WARN, "undefined MEMORY I/O address.\n");
 
997
      return 0;
 
998
    }
 
999
 
 
1000
  if (pci_irq_line == 0)
 
1001
    {
 
1002
      cmn_err (CE_WARN, "IRQ not assigned by BIOS.\n");
 
1003
      return 0;
 
1004
    }
 
1005
 
 
1006
 
 
1007
  /* Map the shared memory area */
 
1008
  devc->bar0virt =
 
1009
    (unsigned int *) MAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, 4 * 1024);
 
1010
  devc->bar1virt =
 
1011
    (unsigned int *) MAP_PCI_MEM (devc->osdev, 1, devc->bar1addr,
 
1012
                                  1024 * 1024);
 
1013
  devc->dwRegister0 = devc->bar0virt;
 
1014
  devc->wRegister0 = (unsigned short *) devc->bar0virt;
 
1015
  devc->bRegister0 = (unsigned char *) devc->bar0virt;
 
1016
  devc->dwRegister1 = devc->bar1virt;
 
1017
  devc->wRegister1 = (unsigned short *) devc->bar1virt;
 
1018
  devc->bRegister1 = (unsigned char *) devc->bar1virt;
 
1019
 
 
1020
  devc->chip_name = "CS4281";
 
1021
  devc->irq = pci_irq_line;
 
1022
  devc->open_mode = 0;
 
1023
 
 
1024
  MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
 
1025
  MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);
 
1026
 
 
1027
  oss_register_device (osdev, devc->chip_name);
 
1028
 
 
1029
  if ((err = oss_register_interrupts (devc->osdev, 0, cs4281intr, NULL)) < 0)
 
1030
    {
 
1031
      cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err);
 
1032
      return 0;
 
1033
    }
 
1034
  return init_cs4281 (devc);    /*Detected */
 
1035
}
 
1036
 
 
1037
 
 
1038
int
 
1039
oss_cs4281_detach (oss_device_t * osdev)
 
1040
{
 
1041
  cs4281_devc *devc = (cs4281_devc *) osdev->devc;
 
1042
 
 
1043
  if (oss_disable_device (osdev) < 0)
 
1044
    return 0;
 
1045
 
 
1046
  WRITEL (BA0_HICR, 0x02);      /*enable intena */
 
1047
 
 
1048
  oss_unregister_interrupts (devc->osdev);
 
1049
 
 
1050
  MUTEX_CLEANUP (devc->mutex);
 
1051
  MUTEX_CLEANUP (devc->low_mutex);
 
1052
 
 
1053
  UNMAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, devc->bar0virt, 4 * 1024);
 
1054
  UNMAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, devc->bar1virt, 1024 * 1024);
 
1055
 
 
1056
  devc->bar0addr = 0;
 
1057
  devc->bar1addr = 0;
 
1058
 
 
1059
  oss_unregister_device (devc->osdev);
 
1060
  return 1;
 
1061
}