OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [sound/] [maui.c] - Blame information for rev 1765

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * sound/maui.c
3
 *
4
 * The low level driver for Turtle Beach Maui and Tropez.
5
 */
6
/*
7
 * Copyright (C) by Hannu Savolainen 1993-1996
8
 *
9
 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
11
 * for more info.
12
 */
13
#include <linux/config.h>
14
 
15
 
16
#define USE_SEQ_MACROS
17
#define USE_SIMPLE_MACROS
18
 
19
#include "sound_config.h"
20
 
21
#if defined(CONFIG_MAUI)
22
 
23
static int      maui_base = 0x330;
24
 
25
static volatile int irq_ok = 0;
26
static int     *maui_osp;
27
 
28
#define HOST_DATA_PORT  (maui_base + 2)
29
#define HOST_STAT_PORT  (maui_base + 3)
30
#define HOST_CTRL_PORT  (maui_base + 3)
31
 
32
#define STAT_TX_INTR    0x40
33
#define STAT_TX_AVAIL   0x20
34
#define STAT_TX_IENA    0x10
35
#define STAT_RX_INTR    0x04
36
#define STAT_RX_AVAIL   0x02
37
#define STAT_RX_IENA    0x01
38
 
39
static int      (*orig_load_patch) (int dev, int format, const char *addr,
40
                                 int offs, int count, int pmgr_flag) = NULL;
41
 
42
#ifdef HAVE_MAUI_BOOT
43
#include "maui_boot.h"
44
#else
45
static unsigned char *maui_os = NULL;
46
static int      maui_osLen = 0;
47
 
48
#endif
49
 
50
static wait_handle *maui_sleeper = NULL;
51
static volatile struct snd_wait maui_sleep_flag =
52
{0};
53
 
54
static int
55
maui_wait (int mask)
56
{
57
  int             i;
58
 
59
/*
60
 * Perform a short initial wait without sleeping
61
 */
62
 
63
  for (i = 0; i < 100; i++)
64
    {
65
      if (inb (HOST_STAT_PORT) & mask)
66
        {
67
          return 1;
68
        }
69
    }
70
 
71
/*
72
 * Wait up to 15 seconds with sleeping
73
 */
74
 
75
  for (i = 0; i < 150; i++)
76
    {
77
      if (inb (HOST_STAT_PORT) & mask)
78
        {
79
          return 1;
80
        }
81
 
82
 
83
      {
84
        unsigned long   tlimit;
85
 
86
        if (HZ / 10)
87
          current_set_timeout (tlimit = jiffies + (HZ / 10));
88
        else
89
          tlimit = (unsigned long) -1;
90
        maui_sleep_flag.flags = WK_SLEEP;
91
        module_interruptible_sleep_on (&maui_sleeper);
92
        if (!(maui_sleep_flag.flags & WK_WAKEUP))
93
          {
94
            if (jiffies >= tlimit)
95
              maui_sleep_flag.flags |= WK_TIMEOUT;
96
          }
97
        maui_sleep_flag.flags &= ~WK_SLEEP;
98
      };
99
      if (current_got_fatal_signal ())
100
        return 0;
101
    }
102
 
103
  return 0;
104
}
105
 
106
static int
107
maui_read (void)
108
{
109
  if (maui_wait (STAT_RX_AVAIL))
110
    return inb (HOST_DATA_PORT);
111
 
112
  return -1;
113
}
114
 
115
static int
116
maui_write (unsigned char data)
117
{
118
  if (maui_wait (STAT_TX_AVAIL))
119
    {
120
      outb (data, HOST_DATA_PORT);
121
      return 1;
122
    }
123
  printk ("Maui: Write timeout\n");
124
 
125
  return 0;
126
}
127
 
128
void
129
mauiintr (int irq, void *dev_id, struct pt_regs *dummy)
130
{
131
  irq_ok = 1;
132
}
133
 
134
static int
135
download_code (void)
136
{
137
  int             i, lines = 0;
138
  int             eol_seen = 0, done = 0;
139
  int             skip = 1;
140
 
141
  printk ("Code download (%d bytes): ", maui_osLen);
142
 
143
  for (i = 0; i < maui_osLen; i++)
144
    {
145
      if (maui_os[i] != '\r')
146
        if (!skip || (maui_os[i] == 'S' && (i == 0 || maui_os[i - 1] == '\n')))
147
          {
148
            skip = 0;
149
 
150
            if (maui_os[i] == '\n')
151
              eol_seen = skip = 1;
152
            else if (maui_os[i] == 'S')
153
              {
154
                if (maui_os[i + 1] == '8')
155
                  done = 1;
156
                if (!maui_write (0xF1))
157
                  goto failure;
158
                if (!maui_write ('S'))
159
                  goto failure;
160
              }
161
            else
162
              {
163
                if (!maui_write (maui_os[i]))
164
                  goto failure;
165
              }
166
 
167
            if (eol_seen)
168
              {
169
                int             c = 0;
170
 
171
                int             n;
172
 
173
                eol_seen = 0;
174
 
175
                for (n = 0; n < 2; n++)
176
                  if (maui_wait (STAT_RX_AVAIL))
177
                    {
178
                      c = inb (HOST_DATA_PORT);
179
                      break;
180
                    }
181
 
182
                if (c != 0x80)
183
                  {
184
                    printk ("Download not acknowledged\n");
185
                    return 0;
186
                  }
187
                else if (!(lines++ % 10))
188
                  printk (".");
189
 
190
                if (done)
191
                  {
192
                    printk ("\nDownload complete\n");
193
                    return 1;
194
                  }
195
              }
196
          }
197
    }
198
 
199
failure:
200
 
201
  printk ("\nDownload failed!!!\n");
202
  return 0;
203
}
204
 
205
static int
206
maui_init (int irq)
207
{
208
  int             i;
209
  unsigned char   bits;
210
 
211
  switch (irq)
212
    {
213
    case 9:
214
      bits = 0x00;
215
      break;
216
    case 5:
217
      bits = 0x08;
218
      break;
219
    case 12:
220
      bits = 0x10;
221
      break;
222
    case 15:
223
      bits = 0x18;
224
      break;
225
 
226
    default:
227
      printk ("Maui: Invalid IRQ %d\n", irq);
228
      return 0;
229
    }
230
 
231
  outb (0x00, HOST_CTRL_PORT);  /* Reset */
232
 
233
  outb (bits, HOST_DATA_PORT);  /* Set the IRQ bits */
234
  outb (bits | 0x80, HOST_DATA_PORT);   /* Set the IRQ bits again? */
235
 
236
  outb (0x80, HOST_CTRL_PORT);  /* Leave reset */
237
  outb (0x80, HOST_CTRL_PORT);  /* Leave reset */
238
 
239
  outb (0xD0, HOST_CTRL_PORT);  /* Cause interrupt */
240
 
241
  for (i = 0; i < 1000000 && !irq_ok; i++);
242
 
243
  if (!irq_ok)
244
    return 0;
245
 
246
  outb (0x80, HOST_CTRL_PORT);  /* Leave reset */
247
 
248
  printk ("Turtle Beach Maui initialization\n");
249
 
250
  if (!download_code ())
251
    return 0;
252
 
253
  outb (0xE0, HOST_CTRL_PORT);  /* Normal operation */
254
 
255
  /* Select mpu401 mode */
256
 
257
  maui_write (0xf0);
258
  maui_write (1);
259
  if (maui_read () != 0x80)
260
    {
261
      maui_write (0xf0);
262
      maui_write (1);
263
      if (maui_read () != 0x80)
264
        printk ("Maui didn't acknowledge set HW mode command\n");
265
    }
266
 
267
  printk ("Maui initialized OK\n");
268
  return 1;
269
}
270
 
271
static int
272
maui_short_wait (int mask)
273
{
274
  int             i;
275
 
276
  for (i = 0; i < 1000; i++)
277
    {
278
      if (inb (HOST_STAT_PORT) & mask)
279
        {
280
          return 1;
281
        }
282
    }
283
 
284
  return 0;
285
}
286
 
287
int
288
maui_load_patch (int dev, int format, const char *addr,
289
                 int offs, int count, int pmgr_flag)
290
{
291
 
292
  struct sysex_info header;
293
  unsigned long   left, src_offs;
294
  int             hdr_size = (unsigned long) &header.data[0] - (unsigned long) &header;
295
  int             i;
296
 
297
  if (format == SYSEX_PATCH)    /* Handled by midi_synth.c */
298
    return orig_load_patch (dev, format, addr, offs, count, pmgr_flag);
299
 
300
  if (format != MAUI_PATCH)
301
    {
302
      printk ("Maui: Unknown patch format\n");
303
    }
304
 
305
  if (count < hdr_size)
306
    {
307
      printk ("Maui error: Patch header too short\n");
308
      return -(EINVAL);
309
    }
310
 
311
  count -= hdr_size;
312
 
313
  /*
314
   * Copy the header from user space but ignore the first bytes which have
315
   * been transferred already.
316
   */
317
 
318
  memcpy_fromfs (&((char *) &header)[offs], &(addr)[offs], hdr_size - offs);
319
 
320
  if (count < header.len)
321
    {
322
      printk ("Maui warning: Host command record too short (%d<%d)\n",
323
              count, (int) header.len);
324
      header.len = count;
325
    }
326
 
327
  left = header.len;
328
  src_offs = 0;
329
 
330
  for (i = 0; i < left; i++)
331
    {
332
      unsigned char   data;
333
 
334
      data = get_fs_byte (&((addr)[hdr_size + i]));
335
      if (i == 0 && !(data & 0x80))
336
        return -(EINVAL);
337
 
338
      if (maui_write (data) == -1)
339
        return -(EIO);
340
    }
341
 
342
  if ((i = maui_read ()) != 0x80)
343
    {
344
      if (i != -1)
345
        printk ("Maui: Error status %02x\n", i);
346
 
347
      return -(EIO);
348
    }
349
 
350
  return 0;
351
}
352
 
353
int
354
probe_maui (struct address_info *hw_config)
355
{
356
  int             i;
357
  int             tmp1, tmp2, ret;
358
 
359
  if (check_region (hw_config->io_base, 8))
360
    return 0;
361
 
362
  maui_base = hw_config->io_base;
363
  maui_osp = hw_config->osp;
364
 
365
  if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0)
366
    return 0;
367
 
368
  maui_sleep_flag.flags = WK_NONE;
369
/*
370
 * Initialize the processor if necessary
371
 */
372
 
373
  if (maui_osLen > 0)
374
    {
375
      if (!(inb (HOST_STAT_PORT) & STAT_TX_AVAIL) ||
376
          !maui_write (0x9F) || /* Report firmware version */
377
          !maui_short_wait (STAT_RX_AVAIL) ||
378
          maui_read () == -1 || maui_read () == -1)
379
        if (!maui_init (hw_config->irq))
380
          {
381
            snd_release_irq (hw_config->irq);
382
            return 0;
383
          }
384
    }
385
 
386
  if (!maui_write (0xCF))       /* Report hardware version */
387
    {
388
      printk ("No WaveFront firmware detected (card uninitialized?)\n");
389
      snd_release_irq (hw_config->irq);
390
      return 0;
391
    }
392
 
393
  if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
394
    {
395
      printk ("No WaveFront firmware detected (card uninitialized?)\n");
396
      snd_release_irq (hw_config->irq);
397
      return 0;
398
    }
399
 
400
  if (tmp1 == 0xff || tmp2 == 0xff)
401
    {
402
      snd_release_irq (hw_config->irq);
403
      return 0;
404
    }
405
 
406
  if (trace_init)
407
    printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2);
408
 
409
  if (!maui_write (0x9F))       /* Report firmware version */
410
    return 0;
411
  if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
412
    return 0;
413
 
414
  if (trace_init)
415
    printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2);
416
 
417
  if (!maui_write (0x85))       /* Report free DRAM */
418
    return 0;
419
  tmp1 = 0;
420
  for (i = 0; i < 4; i++)
421
    {
422
      tmp1 |= maui_read () << (7 * i);
423
    }
424
  if (trace_init)
425
    printk ("Available DRAM %dk\n", tmp1 / 1024);
426
 
427
  for (i = 0; i < 1000; i++)
428
    if (probe_mpu401 (hw_config))
429
      break;
430
 
431
  ret = probe_mpu401 (hw_config);
432
 
433
  if (ret)
434
    request_region (hw_config->io_base + 2, 6, "Maui");
435
 
436
  return ret;
437
}
438
 
439
void
440
attach_maui (struct address_info *hw_config)
441
{
442
  int             this_dev = num_midis;
443
 
444
  conf_printf ("Maui", hw_config);
445
 
446
  hw_config->irq *= -1;
447
  hw_config->name = "Maui";
448
  attach_mpu401 (hw_config);
449
 
450
  if (num_midis > this_dev)     /* The MPU401 driver installed itself */
451
    {
452
      struct synth_operations *synth;
453
 
454
      /*
455
       * Intercept patch loading calls so that they can be handled
456
       * by the Maui driver.
457
       */
458
 
459
      synth = midi_devs[this_dev]->converter;
460
 
461
      if (synth != NULL)
462
        {
463
          orig_load_patch = synth->load_patch;
464
          synth->load_patch = &maui_load_patch;
465
        }
466
      else
467
        printk ("Maui: Can't install patch loader\n");
468
    }
469
}
470
 
471
void
472
unload_maui (struct address_info *hw_config)
473
{
474
  int             irq = hw_config->irq;
475
 
476
  release_region (hw_config->io_base + 2, 6);
477
 
478
  unload_mpu401 (hw_config);
479
 
480
  if (irq < 0)
481
    irq = -irq;
482
 
483
  if (irq > 0)
484
    snd_release_irq (irq);
485
}
486
 
487
 
488
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.