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