diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/oss/mpu401.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'sound/oss/mpu401.c')
-rw-r--r-- | sound/oss/mpu401.c | 1826 |
1 files changed, 1826 insertions, 0 deletions
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c new file mode 100644 index 000000000000..b66f53fa8db0 --- /dev/null +++ b/sound/oss/mpu401.c | |||
@@ -0,0 +1,1826 @@ | |||
1 | /* | ||
2 | * sound/mpu401.c | ||
3 | * | ||
4 | * The low level driver for Roland MPU-401 compatible Midi cards. | ||
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 | * | ||
14 | * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) | ||
15 | * Alan Cox modularisation, use normal request_irq, use dev_id | ||
16 | * Bartlomiej Zolnierkiewicz removed some __init to allow using many drivers | ||
17 | * Chris Rankin Update the module-usage counter for the coprocessor | ||
18 | * Zwane Mwaikambo Changed attach/unload resource freeing | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #define USE_SEQ_MACROS | ||
26 | #define USE_SIMPLE_MACROS | ||
27 | |||
28 | #include "sound_config.h" | ||
29 | |||
30 | #include "coproc.h" | ||
31 | #include "mpu401.h" | ||
32 | |||
33 | static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; | ||
34 | |||
35 | struct mpu_config | ||
36 | { | ||
37 | int base; /* | ||
38 | * I/O base | ||
39 | */ | ||
40 | int irq; | ||
41 | int opened; /* | ||
42 | * Open mode | ||
43 | */ | ||
44 | int devno; | ||
45 | int synthno; | ||
46 | int uart_mode; | ||
47 | int initialized; | ||
48 | int mode; | ||
49 | #define MODE_MIDI 1 | ||
50 | #define MODE_SYNTH 2 | ||
51 | unsigned char version, revision; | ||
52 | unsigned int capabilities; | ||
53 | #define MPU_CAP_INTLG 0x10000000 | ||
54 | #define MPU_CAP_SYNC 0x00000010 | ||
55 | #define MPU_CAP_FSK 0x00000020 | ||
56 | #define MPU_CAP_CLS 0x00000040 | ||
57 | #define MPU_CAP_SMPTE 0x00000080 | ||
58 | #define MPU_CAP_2PORT 0x00000001 | ||
59 | int timer_flag; | ||
60 | |||
61 | #define MBUF_MAX 10 | ||
62 | #define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \ | ||
63 | {printk( "MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;} | ||
64 | int m_busy; | ||
65 | unsigned char m_buf[MBUF_MAX]; | ||
66 | int m_ptr; | ||
67 | int m_state; | ||
68 | int m_left; | ||
69 | unsigned char last_status; | ||
70 | void (*inputintr) (int dev, unsigned char data); | ||
71 | int shared_irq; | ||
72 | int *osp; | ||
73 | spinlock_t lock; | ||
74 | }; | ||
75 | |||
76 | #define DATAPORT(base) (base) | ||
77 | #define COMDPORT(base) (base+1) | ||
78 | #define STATPORT(base) (base+1) | ||
79 | |||
80 | |||
81 | static void mpu401_close(int dev); | ||
82 | |||
83 | static inline int mpu401_status(struct mpu_config *devc) | ||
84 | { | ||
85 | return inb(STATPORT(devc->base)); | ||
86 | } | ||
87 | |||
88 | #define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) | ||
89 | #define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) | ||
90 | |||
91 | static inline void write_command(struct mpu_config *devc, unsigned char cmd) | ||
92 | { | ||
93 | outb(cmd, COMDPORT(devc->base)); | ||
94 | } | ||
95 | |||
96 | static inline int read_data(struct mpu_config *devc) | ||
97 | { | ||
98 | return inb(DATAPORT(devc->base)); | ||
99 | } | ||
100 | |||
101 | static inline void write_data(struct mpu_config *devc, unsigned char byte) | ||
102 | { | ||
103 | outb(byte, DATAPORT(devc->base)); | ||
104 | } | ||
105 | |||
106 | #define OUTPUT_READY 0x40 | ||
107 | #define INPUT_AVAIL 0x80 | ||
108 | #define MPU_ACK 0xFE | ||
109 | #define MPU_RESET 0xFF | ||
110 | #define UART_MODE_ON 0x3F | ||
111 | |||
112 | static struct mpu_config dev_conf[MAX_MIDI_DEV]; | ||
113 | |||
114 | static int n_mpu_devs; | ||
115 | |||
116 | static int reset_mpu401(struct mpu_config *devc); | ||
117 | static void set_uart_mode(int dev, struct mpu_config *devc, int arg); | ||
118 | |||
119 | static int mpu_timer_init(int midi_dev); | ||
120 | static void mpu_timer_interrupt(void); | ||
121 | static void timer_ext_event(struct mpu_config *devc, int event, int parm); | ||
122 | |||
123 | static struct synth_info mpu_synth_info_proto = { | ||
124 | "MPU-401 MIDI interface", | ||
125 | 0, | ||
126 | SYNTH_TYPE_MIDI, | ||
127 | MIDI_TYPE_MPU401, | ||
128 | 0, 128, | ||
129 | 0, 128, | ||
130 | SYNTH_CAP_INPUT | ||
131 | }; | ||
132 | |||
133 | static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; | ||
134 | |||
135 | /* | ||
136 | * States for the input scanner | ||
137 | */ | ||
138 | |||
139 | #define ST_INIT 0 /* Ready for timing byte or msg */ | ||
140 | #define ST_TIMED 1 /* Leading timing byte rcvd */ | ||
141 | #define ST_DATABYTE 2 /* Waiting for (nr_left) data bytes */ | ||
142 | |||
143 | #define ST_SYSMSG 100 /* System message (sysx etc). */ | ||
144 | #define ST_SYSEX 101 /* System exclusive msg */ | ||
145 | #define ST_MTC 102 /* Midi Time Code (MTC) qframe msg */ | ||
146 | #define ST_SONGSEL 103 /* Song select */ | ||
147 | #define ST_SONGPOS 104 /* Song position pointer */ | ||
148 | |||
149 | static unsigned char len_tab[] = /* # of data bytes following a status | ||
150 | */ | ||
151 | { | ||
152 | 2, /* 8x */ | ||
153 | 2, /* 9x */ | ||
154 | 2, /* Ax */ | ||
155 | 2, /* Bx */ | ||
156 | 1, /* Cx */ | ||
157 | 1, /* Dx */ | ||
158 | 2, /* Ex */ | ||
159 | 0 /* Fx */ | ||
160 | }; | ||
161 | |||
162 | #define STORE(cmd) \ | ||
163 | { \ | ||
164 | int len; \ | ||
165 | unsigned char obuf[8]; \ | ||
166 | cmd; \ | ||
167 | seq_input_event(obuf, len); \ | ||
168 | } | ||
169 | |||
170 | #define _seqbuf obuf | ||
171 | #define _seqbufptr 0 | ||
172 | #define _SEQ_ADVBUF(x) len=x | ||
173 | |||
174 | static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) | ||
175 | { | ||
176 | |||
177 | switch (devc->m_state) | ||
178 | { | ||
179 | case ST_INIT: | ||
180 | switch (midic) | ||
181 | { | ||
182 | case 0xf8: | ||
183 | /* Timer overflow */ | ||
184 | break; | ||
185 | |||
186 | case 0xfc: | ||
187 | printk("<all end>"); | ||
188 | break; | ||
189 | |||
190 | case 0xfd: | ||
191 | if (devc->timer_flag) | ||
192 | mpu_timer_interrupt(); | ||
193 | break; | ||
194 | |||
195 | case 0xfe: | ||
196 | return MPU_ACK; | ||
197 | |||
198 | case 0xf0: | ||
199 | case 0xf1: | ||
200 | case 0xf2: | ||
201 | case 0xf3: | ||
202 | case 0xf4: | ||
203 | case 0xf5: | ||
204 | case 0xf6: | ||
205 | case 0xf7: | ||
206 | printk("<Trk data rq #%d>", midic & 0x0f); | ||
207 | break; | ||
208 | |||
209 | case 0xf9: | ||
210 | printk("<conductor rq>"); | ||
211 | break; | ||
212 | |||
213 | case 0xff: | ||
214 | devc->m_state = ST_SYSMSG; | ||
215 | break; | ||
216 | |||
217 | default: | ||
218 | if (midic <= 0xef) | ||
219 | { | ||
220 | /* printk( "mpu time: %d ", midic); */ | ||
221 | devc->m_state = ST_TIMED; | ||
222 | } | ||
223 | else | ||
224 | printk("<MPU: Unknown event %02x> ", midic); | ||
225 | } | ||
226 | break; | ||
227 | |||
228 | case ST_TIMED: | ||
229 | { | ||
230 | int msg = ((int) (midic & 0xf0) >> 4); | ||
231 | |||
232 | devc->m_state = ST_DATABYTE; | ||
233 | |||
234 | if (msg < 8) /* Data byte */ | ||
235 | { | ||
236 | /* printk( "midi msg (running status) "); */ | ||
237 | msg = ((int) (devc->last_status & 0xf0) >> 4); | ||
238 | msg -= 8; | ||
239 | devc->m_left = len_tab[msg] - 1; | ||
240 | |||
241 | devc->m_ptr = 2; | ||
242 | devc->m_buf[0] = devc->last_status; | ||
243 | devc->m_buf[1] = midic; | ||
244 | |||
245 | if (devc->m_left <= 0) | ||
246 | { | ||
247 | devc->m_state = ST_INIT; | ||
248 | do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); | ||
249 | devc->m_ptr = 0; | ||
250 | } | ||
251 | } | ||
252 | else if (msg == 0xf) /* MPU MARK */ | ||
253 | { | ||
254 | devc->m_state = ST_INIT; | ||
255 | |||
256 | switch (midic) | ||
257 | { | ||
258 | case 0xf8: | ||
259 | /* printk( "NOP "); */ | ||
260 | break; | ||
261 | |||
262 | case 0xf9: | ||
263 | /* printk( "meas end "); */ | ||
264 | break; | ||
265 | |||
266 | case 0xfc: | ||
267 | /* printk( "data end "); */ | ||
268 | break; | ||
269 | |||
270 | default: | ||
271 | printk("Unknown MPU mark %02x\n", midic); | ||
272 | } | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | devc->last_status = midic; | ||
277 | /* printk( "midi msg "); */ | ||
278 | msg -= 8; | ||
279 | devc->m_left = len_tab[msg]; | ||
280 | |||
281 | devc->m_ptr = 1; | ||
282 | devc->m_buf[0] = midic; | ||
283 | |||
284 | if (devc->m_left <= 0) | ||
285 | { | ||
286 | devc->m_state = ST_INIT; | ||
287 | do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); | ||
288 | devc->m_ptr = 0; | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | break; | ||
293 | |||
294 | case ST_SYSMSG: | ||
295 | switch (midic) | ||
296 | { | ||
297 | case 0xf0: | ||
298 | printk("<SYX>"); | ||
299 | devc->m_state = ST_SYSEX; | ||
300 | break; | ||
301 | |||
302 | case 0xf1: | ||
303 | devc->m_state = ST_MTC; | ||
304 | break; | ||
305 | |||
306 | case 0xf2: | ||
307 | devc->m_state = ST_SONGPOS; | ||
308 | devc->m_ptr = 0; | ||
309 | break; | ||
310 | |||
311 | case 0xf3: | ||
312 | devc->m_state = ST_SONGSEL; | ||
313 | break; | ||
314 | |||
315 | case 0xf6: | ||
316 | /* printk( "tune_request\n"); */ | ||
317 | devc->m_state = ST_INIT; | ||
318 | |||
319 | /* | ||
320 | * Real time messages | ||
321 | */ | ||
322 | case 0xf8: | ||
323 | /* midi clock */ | ||
324 | devc->m_state = ST_INIT; | ||
325 | timer_ext_event(devc, TMR_CLOCK, 0); | ||
326 | break; | ||
327 | |||
328 | case 0xfA: | ||
329 | devc->m_state = ST_INIT; | ||
330 | timer_ext_event(devc, TMR_START, 0); | ||
331 | break; | ||
332 | |||
333 | case 0xFB: | ||
334 | devc->m_state = ST_INIT; | ||
335 | timer_ext_event(devc, TMR_CONTINUE, 0); | ||
336 | break; | ||
337 | |||
338 | case 0xFC: | ||
339 | devc->m_state = ST_INIT; | ||
340 | timer_ext_event(devc, TMR_STOP, 0); | ||
341 | break; | ||
342 | |||
343 | case 0xFE: | ||
344 | /* active sensing */ | ||
345 | devc->m_state = ST_INIT; | ||
346 | break; | ||
347 | |||
348 | case 0xff: | ||
349 | /* printk( "midi hard reset"); */ | ||
350 | devc->m_state = ST_INIT; | ||
351 | break; | ||
352 | |||
353 | default: | ||
354 | printk("unknown MIDI sysmsg %0x\n", midic); | ||
355 | devc->m_state = ST_INIT; | ||
356 | } | ||
357 | break; | ||
358 | |||
359 | case ST_MTC: | ||
360 | devc->m_state = ST_INIT; | ||
361 | printk("MTC frame %x02\n", midic); | ||
362 | break; | ||
363 | |||
364 | case ST_SYSEX: | ||
365 | if (midic == 0xf7) | ||
366 | { | ||
367 | printk("<EOX>"); | ||
368 | devc->m_state = ST_INIT; | ||
369 | } | ||
370 | else | ||
371 | printk("%02x ", midic); | ||
372 | break; | ||
373 | |||
374 | case ST_SONGPOS: | ||
375 | BUFTEST(devc); | ||
376 | devc->m_buf[devc->m_ptr++] = midic; | ||
377 | if (devc->m_ptr == 2) | ||
378 | { | ||
379 | devc->m_state = ST_INIT; | ||
380 | devc->m_ptr = 0; | ||
381 | timer_ext_event(devc, TMR_SPP, | ||
382 | ((devc->m_buf[1] & 0x7f) << 7) | | ||
383 | (devc->m_buf[0] & 0x7f)); | ||
384 | } | ||
385 | break; | ||
386 | |||
387 | case ST_DATABYTE: | ||
388 | BUFTEST(devc); | ||
389 | devc->m_buf[devc->m_ptr++] = midic; | ||
390 | if ((--devc->m_left) <= 0) | ||
391 | { | ||
392 | devc->m_state = ST_INIT; | ||
393 | do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); | ||
394 | devc->m_ptr = 0; | ||
395 | } | ||
396 | break; | ||
397 | |||
398 | default: | ||
399 | printk("Bad state %d ", devc->m_state); | ||
400 | devc->m_state = ST_INIT; | ||
401 | } | ||
402 | return 1; | ||
403 | } | ||
404 | |||
405 | static void mpu401_input_loop(struct mpu_config *devc) | ||
406 | { | ||
407 | unsigned long flags; | ||
408 | int busy; | ||
409 | int n; | ||
410 | |||
411 | spin_lock_irqsave(&devc->lock,flags); | ||
412 | busy = devc->m_busy; | ||
413 | devc->m_busy = 1; | ||
414 | spin_unlock_irqrestore(&devc->lock,flags); | ||
415 | |||
416 | if (busy) /* Already inside the scanner */ | ||
417 | return; | ||
418 | |||
419 | n = 50; | ||
420 | |||
421 | while (input_avail(devc) && n-- > 0) | ||
422 | { | ||
423 | unsigned char c = read_data(devc); | ||
424 | |||
425 | if (devc->mode == MODE_SYNTH) | ||
426 | { | ||
427 | mpu_input_scanner(devc, c); | ||
428 | } | ||
429 | else if (devc->opened & OPEN_READ && devc->inputintr != NULL) | ||
430 | devc->inputintr(devc->devno, c); | ||
431 | } | ||
432 | devc->m_busy = 0; | ||
433 | } | ||
434 | |||
435 | int intchk_mpu401(void *dev_id) | ||
436 | { | ||
437 | struct mpu_config *devc; | ||
438 | int dev = (int) dev_id; | ||
439 | |||
440 | devc = &dev_conf[dev]; | ||
441 | return input_avail(devc); | ||
442 | } | ||
443 | |||
444 | irqreturn_t mpuintr(int irq, void *dev_id, struct pt_regs *dummy) | ||
445 | { | ||
446 | struct mpu_config *devc; | ||
447 | int dev = (int) dev_id; | ||
448 | int handled = 0; | ||
449 | |||
450 | devc = &dev_conf[dev]; | ||
451 | |||
452 | if (input_avail(devc)) | ||
453 | { | ||
454 | handled = 1; | ||
455 | if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) | ||
456 | mpu401_input_loop(devc); | ||
457 | else | ||
458 | { | ||
459 | /* Dummy read (just to acknowledge the interrupt) */ | ||
460 | read_data(devc); | ||
461 | } | ||
462 | } | ||
463 | return IRQ_RETVAL(handled); | ||
464 | } | ||
465 | |||
466 | static int mpu401_open(int dev, int mode, | ||
467 | void (*input) (int dev, unsigned char data), | ||
468 | void (*output) (int dev) | ||
469 | ) | ||
470 | { | ||
471 | int err; | ||
472 | struct mpu_config *devc; | ||
473 | struct coproc_operations *coprocessor; | ||
474 | |||
475 | if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) | ||
476 | return -ENXIO; | ||
477 | |||
478 | devc = &dev_conf[dev]; | ||
479 | |||
480 | if (devc->opened) | ||
481 | return -EBUSY; | ||
482 | /* | ||
483 | * Verify that the device is really running. | ||
484 | * Some devices (such as Ensoniq SoundScape don't | ||
485 | * work before the on board processor (OBP) is initialized | ||
486 | * by downloading its microcode. | ||
487 | */ | ||
488 | |||
489 | if (!devc->initialized) | ||
490 | { | ||
491 | if (mpu401_status(devc) == 0xff) /* Bus float */ | ||
492 | { | ||
493 | printk(KERN_ERR "mpu401: Device not initialized properly\n"); | ||
494 | return -EIO; | ||
495 | } | ||
496 | reset_mpu401(devc); | ||
497 | } | ||
498 | |||
499 | if ( (coprocessor = midi_devs[dev]->coproc) != NULL ) | ||
500 | { | ||
501 | if (!try_module_get(coprocessor->owner)) { | ||
502 | mpu401_close(dev); | ||
503 | return -ENODEV; | ||
504 | } | ||
505 | |||
506 | if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0) | ||
507 | { | ||
508 | printk(KERN_WARNING "MPU-401: Can't access coprocessor device\n"); | ||
509 | mpu401_close(dev); | ||
510 | return err; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | set_uart_mode(dev, devc, 1); | ||
515 | devc->mode = MODE_MIDI; | ||
516 | devc->synthno = 0; | ||
517 | |||
518 | mpu401_input_loop(devc); | ||
519 | |||
520 | devc->inputintr = input; | ||
521 | devc->opened = mode; | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static void mpu401_close(int dev) | ||
527 | { | ||
528 | struct mpu_config *devc; | ||
529 | struct coproc_operations *coprocessor; | ||
530 | |||
531 | devc = &dev_conf[dev]; | ||
532 | if (devc->uart_mode) | ||
533 | reset_mpu401(devc); /* | ||
534 | * This disables the UART mode | ||
535 | */ | ||
536 | devc->mode = 0; | ||
537 | devc->inputintr = NULL; | ||
538 | |||
539 | coprocessor = midi_devs[dev]->coproc; | ||
540 | if (coprocessor) { | ||
541 | coprocessor->close(coprocessor->devc, COPR_MIDI); | ||
542 | module_put(coprocessor->owner); | ||
543 | } | ||
544 | devc->opened = 0; | ||
545 | } | ||
546 | |||
547 | static int mpu401_out(int dev, unsigned char midi_byte) | ||
548 | { | ||
549 | int timeout; | ||
550 | unsigned long flags; | ||
551 | |||
552 | struct mpu_config *devc; | ||
553 | |||
554 | devc = &dev_conf[dev]; | ||
555 | |||
556 | /* | ||
557 | * Sometimes it takes about 30000 loops before the output becomes ready | ||
558 | * (After reset). Normally it takes just about 10 loops. | ||
559 | */ | ||
560 | |||
561 | for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); | ||
562 | |||
563 | spin_lock_irqsave(&devc->lock,flags); | ||
564 | if (!output_ready(devc)) | ||
565 | { | ||
566 | printk(KERN_WARNING "mpu401: Send data timeout\n"); | ||
567 | spin_unlock_irqrestore(&devc->lock,flags); | ||
568 | return 0; | ||
569 | } | ||
570 | write_data(devc, midi_byte); | ||
571 | spin_unlock_irqrestore(&devc->lock,flags); | ||
572 | return 1; | ||
573 | } | ||
574 | |||
575 | static int mpu401_command(int dev, mpu_command_rec * cmd) | ||
576 | { | ||
577 | int i, timeout, ok; | ||
578 | int ret = 0; | ||
579 | unsigned long flags; | ||
580 | struct mpu_config *devc; | ||
581 | |||
582 | devc = &dev_conf[dev]; | ||
583 | |||
584 | if (devc->uart_mode) /* | ||
585 | * Not possible in UART mode | ||
586 | */ | ||
587 | { | ||
588 | printk(KERN_WARNING "mpu401: commands not possible in the UART mode\n"); | ||
589 | return -EINVAL; | ||
590 | } | ||
591 | /* | ||
592 | * Test for input since pending input seems to block the output. | ||
593 | */ | ||
594 | if (input_avail(devc)) | ||
595 | mpu401_input_loop(devc); | ||
596 | |||
597 | /* | ||
598 | * Sometimes it takes about 50000 loops before the output becomes ready | ||
599 | * (After reset). Normally it takes just about 10 loops. | ||
600 | */ | ||
601 | |||
602 | timeout = 50000; | ||
603 | retry: | ||
604 | if (timeout-- <= 0) | ||
605 | { | ||
606 | printk(KERN_WARNING "mpu401: Command (0x%x) timeout\n", (int) cmd->cmd); | ||
607 | return -EIO; | ||
608 | } | ||
609 | spin_lock_irqsave(&devc->lock,flags); | ||
610 | |||
611 | if (!output_ready(devc)) | ||
612 | { | ||
613 | spin_unlock_irqrestore(&devc->lock,flags); | ||
614 | goto retry; | ||
615 | } | ||
616 | write_command(devc, cmd->cmd); | ||
617 | |||
618 | ok = 0; | ||
619 | for (timeout = 50000; timeout > 0 && !ok; timeout--) | ||
620 | { | ||
621 | if (input_avail(devc)) | ||
622 | { | ||
623 | if (devc->opened && devc->mode == MODE_SYNTH) | ||
624 | { | ||
625 | if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) | ||
626 | ok = 1; | ||
627 | } | ||
628 | else | ||
629 | { | ||
630 | /* Device is not currently open. Use simpler method */ | ||
631 | if (read_data(devc) == MPU_ACK) | ||
632 | ok = 1; | ||
633 | } | ||
634 | } | ||
635 | } | ||
636 | if (!ok) | ||
637 | { | ||
638 | spin_unlock_irqrestore(&devc->lock,flags); | ||
639 | return -EIO; | ||
640 | } | ||
641 | if (cmd->nr_args) | ||
642 | { | ||
643 | for (i = 0; i < cmd->nr_args; i++) | ||
644 | { | ||
645 | for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); | ||
646 | |||
647 | if (!mpu401_out(dev, cmd->data[i])) | ||
648 | { | ||
649 | spin_unlock_irqrestore(&devc->lock,flags); | ||
650 | printk(KERN_WARNING "mpu401: Command (0x%x), parm send failed.\n", (int) cmd->cmd); | ||
651 | return -EIO; | ||
652 | } | ||
653 | } | ||
654 | } | ||
655 | ret = 0; | ||
656 | cmd->data[0] = 0; | ||
657 | |||
658 | if (cmd->nr_returns) | ||
659 | { | ||
660 | for (i = 0; i < cmd->nr_returns; i++) | ||
661 | { | ||
662 | ok = 0; | ||
663 | for (timeout = 5000; timeout > 0 && !ok; timeout--) | ||
664 | if (input_avail(devc)) | ||
665 | { | ||
666 | cmd->data[i] = read_data(devc); | ||
667 | ok = 1; | ||
668 | } | ||
669 | if (!ok) | ||
670 | { | ||
671 | spin_unlock_irqrestore(&devc->lock,flags); | ||
672 | return -EIO; | ||
673 | } | ||
674 | } | ||
675 | } | ||
676 | spin_unlock_irqrestore(&devc->lock,flags); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | static int mpu_cmd(int dev, int cmd, int data) | ||
681 | { | ||
682 | int ret; | ||
683 | |||
684 | static mpu_command_rec rec; | ||
685 | |||
686 | rec.cmd = cmd & 0xff; | ||
687 | rec.nr_args = ((cmd & 0xf0) == 0xE0); | ||
688 | rec.nr_returns = ((cmd & 0xf0) == 0xA0); | ||
689 | rec.data[0] = data & 0xff; | ||
690 | |||
691 | if ((ret = mpu401_command(dev, &rec)) < 0) | ||
692 | return ret; | ||
693 | return (unsigned char) rec.data[0]; | ||
694 | } | ||
695 | |||
696 | static int mpu401_prefix_cmd(int dev, unsigned char status) | ||
697 | { | ||
698 | struct mpu_config *devc = &dev_conf[dev]; | ||
699 | |||
700 | if (devc->uart_mode) | ||
701 | return 1; | ||
702 | |||
703 | if (status < 0xf0) | ||
704 | { | ||
705 | if (mpu_cmd(dev, 0xD0, 0) < 0) | ||
706 | return 0; | ||
707 | return 1; | ||
708 | } | ||
709 | switch (status) | ||
710 | { | ||
711 | case 0xF0: | ||
712 | if (mpu_cmd(dev, 0xDF, 0) < 0) | ||
713 | return 0; | ||
714 | return 1; | ||
715 | |||
716 | default: | ||
717 | return 0; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | static int mpu401_start_read(int dev) | ||
722 | { | ||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static int mpu401_end_read(int dev) | ||
727 | { | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static int mpu401_ioctl(int dev, unsigned cmd, void __user *arg) | ||
732 | { | ||
733 | struct mpu_config *devc; | ||
734 | mpu_command_rec rec; | ||
735 | int val, ret; | ||
736 | |||
737 | devc = &dev_conf[dev]; | ||
738 | switch (cmd) | ||
739 | { | ||
740 | case SNDCTL_MIDI_MPUMODE: | ||
741 | if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ | ||
742 | printk(KERN_WARNING "mpu401: Intelligent mode not supported by the HW\n"); | ||
743 | return -EINVAL; | ||
744 | } | ||
745 | if (get_user(val, (int __user *)arg)) | ||
746 | return -EFAULT; | ||
747 | set_uart_mode(dev, devc, !val); | ||
748 | return 0; | ||
749 | |||
750 | case SNDCTL_MIDI_MPUCMD: | ||
751 | if (copy_from_user(&rec, arg, sizeof(rec))) | ||
752 | return -EFAULT; | ||
753 | if ((ret = mpu401_command(dev, &rec)) < 0) | ||
754 | return ret; | ||
755 | if (copy_to_user(arg, &rec, sizeof(rec))) | ||
756 | return -EFAULT; | ||
757 | return 0; | ||
758 | |||
759 | default: | ||
760 | return -EINVAL; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | static void mpu401_kick(int dev) | ||
765 | { | ||
766 | } | ||
767 | |||
768 | static int mpu401_buffer_status(int dev) | ||
769 | { | ||
770 | return 0; /* | ||
771 | * No data in buffers | ||
772 | */ | ||
773 | } | ||
774 | |||
775 | static int mpu_synth_ioctl(int dev, unsigned int cmd, void __user *arg) | ||
776 | { | ||
777 | int midi_dev; | ||
778 | struct mpu_config *devc; | ||
779 | |||
780 | midi_dev = synth_devs[dev]->midi_dev; | ||
781 | |||
782 | if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) | ||
783 | return -ENXIO; | ||
784 | |||
785 | devc = &dev_conf[midi_dev]; | ||
786 | |||
787 | switch (cmd) | ||
788 | { | ||
789 | |||
790 | case SNDCTL_SYNTH_INFO: | ||
791 | if (copy_to_user(arg, &mpu_synth_info[midi_dev], | ||
792 | sizeof(struct synth_info))) | ||
793 | return -EFAULT; | ||
794 | return 0; | ||
795 | |||
796 | case SNDCTL_SYNTH_MEMAVL: | ||
797 | return 0x7fffffff; | ||
798 | |||
799 | default: | ||
800 | return -EINVAL; | ||
801 | } | ||
802 | } | ||
803 | |||
804 | static int mpu_synth_open(int dev, int mode) | ||
805 | { | ||
806 | int midi_dev, err; | ||
807 | struct mpu_config *devc; | ||
808 | struct coproc_operations *coprocessor; | ||
809 | |||
810 | midi_dev = synth_devs[dev]->midi_dev; | ||
811 | |||
812 | if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) | ||
813 | return -ENXIO; | ||
814 | |||
815 | devc = &dev_conf[midi_dev]; | ||
816 | |||
817 | /* | ||
818 | * Verify that the device is really running. | ||
819 | * Some devices (such as Ensoniq SoundScape don't | ||
820 | * work before the on board processor (OBP) is initialized | ||
821 | * by downloading its microcode. | ||
822 | */ | ||
823 | |||
824 | if (!devc->initialized) | ||
825 | { | ||
826 | if (mpu401_status(devc) == 0xff) /* Bus float */ | ||
827 | { | ||
828 | printk(KERN_ERR "mpu401: Device not initialized properly\n"); | ||
829 | return -EIO; | ||
830 | } | ||
831 | reset_mpu401(devc); | ||
832 | } | ||
833 | if (devc->opened) | ||
834 | return -EBUSY; | ||
835 | devc->mode = MODE_SYNTH; | ||
836 | devc->synthno = dev; | ||
837 | |||
838 | devc->inputintr = NULL; | ||
839 | |||
840 | coprocessor = midi_devs[midi_dev]->coproc; | ||
841 | if (coprocessor) { | ||
842 | if (!try_module_get(coprocessor->owner)) | ||
843 | return -ENODEV; | ||
844 | |||
845 | if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0) | ||
846 | { | ||
847 | printk(KERN_WARNING "mpu401: Can't access coprocessor device\n"); | ||
848 | return err; | ||
849 | } | ||
850 | } | ||
851 | devc->opened = mode; | ||
852 | reset_mpu401(devc); | ||
853 | |||
854 | if (mode & OPEN_READ) | ||
855 | { | ||
856 | mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ | ||
857 | mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ | ||
858 | mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ | ||
859 | } | ||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static void mpu_synth_close(int dev) | ||
864 | { | ||
865 | int midi_dev; | ||
866 | struct mpu_config *devc; | ||
867 | struct coproc_operations *coprocessor; | ||
868 | |||
869 | midi_dev = synth_devs[dev]->midi_dev; | ||
870 | |||
871 | devc = &dev_conf[midi_dev]; | ||
872 | mpu_cmd(midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */ | ||
873 | mpu_cmd(midi_dev, 0x8a, 0); /* Disable data in stopped mode */ | ||
874 | |||
875 | devc->inputintr = NULL; | ||
876 | |||
877 | coprocessor = midi_devs[midi_dev]->coproc; | ||
878 | if (coprocessor) { | ||
879 | coprocessor->close(coprocessor->devc, COPR_MIDI); | ||
880 | module_put(coprocessor->owner); | ||
881 | } | ||
882 | devc->opened = 0; | ||
883 | devc->mode = 0; | ||
884 | } | ||
885 | |||
886 | #define MIDI_SYNTH_NAME "MPU-401 UART Midi" | ||
887 | #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT | ||
888 | #include "midi_synth.h" | ||
889 | |||
890 | static struct synth_operations mpu401_synth_proto = | ||
891 | { | ||
892 | .owner = THIS_MODULE, | ||
893 | .id = "MPU401", | ||
894 | .info = NULL, | ||
895 | .midi_dev = 0, | ||
896 | .synth_type = SYNTH_TYPE_MIDI, | ||
897 | .synth_subtype = 0, | ||
898 | .open = mpu_synth_open, | ||
899 | .close = mpu_synth_close, | ||
900 | .ioctl = mpu_synth_ioctl, | ||
901 | .kill_note = midi_synth_kill_note, | ||
902 | .start_note = midi_synth_start_note, | ||
903 | .set_instr = midi_synth_set_instr, | ||
904 | .reset = midi_synth_reset, | ||
905 | .hw_control = midi_synth_hw_control, | ||
906 | .load_patch = midi_synth_load_patch, | ||
907 | .aftertouch = midi_synth_aftertouch, | ||
908 | .controller = midi_synth_controller, | ||
909 | .panning = midi_synth_panning, | ||
910 | .bender = midi_synth_bender, | ||
911 | .setup_voice = midi_synth_setup_voice, | ||
912 | .send_sysex = midi_synth_send_sysex | ||
913 | }; | ||
914 | |||
915 | static struct synth_operations *mpu401_synth_operations[MAX_MIDI_DEV]; | ||
916 | |||
917 | static struct midi_operations mpu401_midi_proto = | ||
918 | { | ||
919 | .owner = THIS_MODULE, | ||
920 | .info = {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401}, | ||
921 | .in_info = {0}, | ||
922 | .open = mpu401_open, | ||
923 | .close = mpu401_close, | ||
924 | .ioctl = mpu401_ioctl, | ||
925 | .outputc = mpu401_out, | ||
926 | .start_read = mpu401_start_read, | ||
927 | .end_read = mpu401_end_read, | ||
928 | .kick = mpu401_kick, | ||
929 | .buffer_status = mpu401_buffer_status, | ||
930 | .prefix_cmd = mpu401_prefix_cmd | ||
931 | }; | ||
932 | |||
933 | static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; | ||
934 | |||
935 | static void mpu401_chk_version(int n, struct mpu_config *devc) | ||
936 | { | ||
937 | int tmp; | ||
938 | unsigned long flags; | ||
939 | |||
940 | devc->version = devc->revision = 0; | ||
941 | |||
942 | spin_lock_irqsave(&devc->lock,flags); | ||
943 | if ((tmp = mpu_cmd(n, 0xAC, 0)) < 0) | ||
944 | { | ||
945 | spin_unlock_irqrestore(&devc->lock,flags); | ||
946 | return; | ||
947 | } | ||
948 | if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ | ||
949 | { | ||
950 | spin_unlock_irqrestore(&devc->lock,flags); | ||
951 | return; | ||
952 | } | ||
953 | devc->version = tmp; | ||
954 | |||
955 | if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) | ||
956 | { | ||
957 | devc->version = 0; | ||
958 | spin_unlock_irqrestore(&devc->lock,flags); | ||
959 | return; | ||
960 | } | ||
961 | devc->revision = tmp; | ||
962 | spin_unlock_irqrestore(&devc->lock,flags); | ||
963 | } | ||
964 | |||
965 | int attach_mpu401(struct address_info *hw_config, struct module *owner) | ||
966 | { | ||
967 | unsigned long flags; | ||
968 | char revision_char; | ||
969 | |||
970 | int m, ret; | ||
971 | struct mpu_config *devc; | ||
972 | |||
973 | hw_config->slots[1] = -1; | ||
974 | m = sound_alloc_mididev(); | ||
975 | if (m == -1) | ||
976 | { | ||
977 | printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); | ||
978 | ret = -ENOMEM; | ||
979 | goto out_err; | ||
980 | } | ||
981 | devc = &dev_conf[m]; | ||
982 | devc->base = hw_config->io_base; | ||
983 | devc->osp = hw_config->osp; | ||
984 | devc->irq = hw_config->irq; | ||
985 | devc->opened = 0; | ||
986 | devc->uart_mode = 0; | ||
987 | devc->initialized = 0; | ||
988 | devc->version = 0; | ||
989 | devc->revision = 0; | ||
990 | devc->capabilities = 0; | ||
991 | devc->timer_flag = 0; | ||
992 | devc->m_busy = 0; | ||
993 | devc->m_state = ST_INIT; | ||
994 | devc->shared_irq = hw_config->always_detect; | ||
995 | devc->irq = hw_config->irq; | ||
996 | spin_lock_init(&devc->lock); | ||
997 | |||
998 | if (devc->irq < 0) | ||
999 | { | ||
1000 | devc->irq *= -1; | ||
1001 | devc->shared_irq = 1; | ||
1002 | } | ||
1003 | |||
1004 | if (!hw_config->always_detect) | ||
1005 | { | ||
1006 | /* Verify the hardware again */ | ||
1007 | if (!reset_mpu401(devc)) | ||
1008 | { | ||
1009 | printk(KERN_WARNING "mpu401: Device didn't respond\n"); | ||
1010 | ret = -ENODEV; | ||
1011 | goto out_mididev; | ||
1012 | } | ||
1013 | if (!devc->shared_irq) | ||
1014 | { | ||
1015 | if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0) | ||
1016 | { | ||
1017 | printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); | ||
1018 | ret = -ENOMEM; | ||
1019 | goto out_mididev; | ||
1020 | } | ||
1021 | } | ||
1022 | spin_lock_irqsave(&devc->lock,flags); | ||
1023 | mpu401_chk_version(m, devc); | ||
1024 | if (devc->version == 0) | ||
1025 | mpu401_chk_version(m, devc); | ||
1026 | spin_unlock_irqrestore(&devc->lock,flags); | ||
1027 | } | ||
1028 | |||
1029 | if (devc->version != 0) | ||
1030 | if (mpu_cmd(m, 0xC5, 0) >= 0) /* Set timebase OK */ | ||
1031 | if (mpu_cmd(m, 0xE0, 120) >= 0) /* Set tempo OK */ | ||
1032 | devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ | ||
1033 | |||
1034 | |||
1035 | mpu401_synth_operations[m] = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL); | ||
1036 | |||
1037 | if (mpu401_synth_operations[m] == NULL) | ||
1038 | { | ||
1039 | printk(KERN_ERR "mpu401: Can't allocate memory\n"); | ||
1040 | ret = -ENOMEM; | ||
1041 | goto out_irq; | ||
1042 | } | ||
1043 | if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ | ||
1044 | { | ||
1045 | memcpy((char *) mpu401_synth_operations[m], | ||
1046 | (char *) &std_midi_synth, | ||
1047 | sizeof(struct synth_operations)); | ||
1048 | } | ||
1049 | else | ||
1050 | { | ||
1051 | memcpy((char *) mpu401_synth_operations[m], | ||
1052 | (char *) &mpu401_synth_proto, | ||
1053 | sizeof(struct synth_operations)); | ||
1054 | } | ||
1055 | if (owner) | ||
1056 | mpu401_synth_operations[m]->owner = owner; | ||
1057 | |||
1058 | memcpy((char *) &mpu401_midi_operations[m], | ||
1059 | (char *) &mpu401_midi_proto, | ||
1060 | sizeof(struct midi_operations)); | ||
1061 | |||
1062 | mpu401_midi_operations[m].converter = mpu401_synth_operations[m]; | ||
1063 | |||
1064 | memcpy((char *) &mpu_synth_info[m], | ||
1065 | (char *) &mpu_synth_info_proto, | ||
1066 | sizeof(struct synth_info)); | ||
1067 | |||
1068 | n_mpu_devs++; | ||
1069 | |||
1070 | if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */ | ||
1071 | { | ||
1072 | int ports = (devc->revision & 0x08) ? 32 : 16; | ||
1073 | |||
1074 | devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | | ||
1075 | MPU_CAP_CLS | MPU_CAP_2PORT; | ||
1076 | |||
1077 | revision_char = (devc->revision == 0x7f) ? 'M' : ' '; | ||
1078 | sprintf(mpu_synth_info[m].name, "MQX-%d%c MIDI Interface #%d", | ||
1079 | ports, | ||
1080 | revision_char, | ||
1081 | n_mpu_devs); | ||
1082 | } | ||
1083 | else | ||
1084 | { | ||
1085 | revision_char = devc->revision ? devc->revision + '@' : ' '; | ||
1086 | if ((int) devc->revision > ('Z' - '@')) | ||
1087 | revision_char = '+'; | ||
1088 | |||
1089 | devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; | ||
1090 | |||
1091 | if (hw_config->name) | ||
1092 | sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); | ||
1093 | else | ||
1094 | sprintf(mpu_synth_info[m].name, | ||
1095 | "MPU-401 %d.%d%c Midi interface #%d", | ||
1096 | (int) (devc->version & 0xf0) >> 4, | ||
1097 | devc->version & 0x0f, | ||
1098 | revision_char, | ||
1099 | n_mpu_devs); | ||
1100 | } | ||
1101 | |||
1102 | strcpy(mpu401_midi_operations[m].info.name, | ||
1103 | mpu_synth_info[m].name); | ||
1104 | |||
1105 | conf_printf(mpu_synth_info[m].name, hw_config); | ||
1106 | |||
1107 | mpu401_synth_operations[m]->midi_dev = devc->devno = m; | ||
1108 | mpu401_synth_operations[devc->devno]->info = &mpu_synth_info[devc->devno]; | ||
1109 | |||
1110 | if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */ | ||
1111 | hw_config->slots[2] = mpu_timer_init(m); | ||
1112 | |||
1113 | midi_devs[m] = &mpu401_midi_operations[devc->devno]; | ||
1114 | |||
1115 | if (owner) | ||
1116 | midi_devs[m]->owner = owner; | ||
1117 | |||
1118 | hw_config->slots[1] = m; | ||
1119 | sequencer_init(); | ||
1120 | |||
1121 | return 0; | ||
1122 | |||
1123 | out_irq: | ||
1124 | free_irq(devc->irq, (void *)m); | ||
1125 | out_mididev: | ||
1126 | sound_unload_mididev(m); | ||
1127 | out_err: | ||
1128 | release_region(hw_config->io_base, 2); | ||
1129 | return ret; | ||
1130 | } | ||
1131 | |||
1132 | static int reset_mpu401(struct mpu_config *devc) | ||
1133 | { | ||
1134 | unsigned long flags; | ||
1135 | int ok, timeout, n; | ||
1136 | int timeout_limit; | ||
1137 | |||
1138 | /* | ||
1139 | * Send the RESET command. Try again if no success at the first time. | ||
1140 | * (If the device is in the UART mode, it will not ack the reset cmd). | ||
1141 | */ | ||
1142 | |||
1143 | ok = 0; | ||
1144 | |||
1145 | timeout_limit = devc->initialized ? 30000 : 100000; | ||
1146 | devc->initialized = 1; | ||
1147 | |||
1148 | for (n = 0; n < 2 && !ok; n++) | ||
1149 | { | ||
1150 | for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) | ||
1151 | ok = output_ready(devc); | ||
1152 | |||
1153 | write_command(devc, MPU_RESET); /* | ||
1154 | * Send MPU-401 RESET Command | ||
1155 | */ | ||
1156 | |||
1157 | /* | ||
1158 | * Wait at least 25 msec. This method is not accurate so let's make the | ||
1159 | * loop bit longer. Cannot sleep since this is called during boot. | ||
1160 | */ | ||
1161 | |||
1162 | for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) | ||
1163 | { | ||
1164 | spin_lock_irqsave(&devc->lock,flags); | ||
1165 | if (input_avail(devc)) | ||
1166 | if (read_data(devc) == MPU_ACK) | ||
1167 | ok = 1; | ||
1168 | spin_unlock_irqrestore(&devc->lock,flags); | ||
1169 | } | ||
1170 | |||
1171 | } | ||
1172 | |||
1173 | devc->m_state = ST_INIT; | ||
1174 | devc->m_ptr = 0; | ||
1175 | devc->m_left = 0; | ||
1176 | devc->last_status = 0; | ||
1177 | devc->uart_mode = 0; | ||
1178 | |||
1179 | return ok; | ||
1180 | } | ||
1181 | |||
1182 | static void set_uart_mode(int dev, struct mpu_config *devc, int arg) | ||
1183 | { | ||
1184 | if (!arg && (devc->capabilities & MPU_CAP_INTLG)) | ||
1185 | return; | ||
1186 | if ((devc->uart_mode == 0) == (arg == 0)) | ||
1187 | return; /* Already set */ | ||
1188 | reset_mpu401(devc); /* This exits the uart mode */ | ||
1189 | |||
1190 | if (arg) | ||
1191 | { | ||
1192 | if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) | ||
1193 | { | ||
1194 | printk(KERN_ERR "mpu401: Can't enter UART mode\n"); | ||
1195 | devc->uart_mode = 0; | ||
1196 | return; | ||
1197 | } | ||
1198 | } | ||
1199 | devc->uart_mode = arg; | ||
1200 | |||
1201 | } | ||
1202 | |||
1203 | int probe_mpu401(struct address_info *hw_config, struct resource *ports) | ||
1204 | { | ||
1205 | int ok = 0; | ||
1206 | struct mpu_config tmp_devc; | ||
1207 | |||
1208 | tmp_devc.base = hw_config->io_base; | ||
1209 | tmp_devc.irq = hw_config->irq; | ||
1210 | tmp_devc.initialized = 0; | ||
1211 | tmp_devc.opened = 0; | ||
1212 | tmp_devc.osp = hw_config->osp; | ||
1213 | |||
1214 | if (hw_config->always_detect) | ||
1215 | return 1; | ||
1216 | |||
1217 | if (inb(hw_config->io_base + 1) == 0xff) | ||
1218 | { | ||
1219 | DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); | ||
1220 | return 0; /* Just bus float? */ | ||
1221 | } | ||
1222 | ok = reset_mpu401(&tmp_devc); | ||
1223 | |||
1224 | if (!ok) | ||
1225 | { | ||
1226 | DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); | ||
1227 | } | ||
1228 | return ok; | ||
1229 | } | ||
1230 | |||
1231 | void unload_mpu401(struct address_info *hw_config) | ||
1232 | { | ||
1233 | void *p; | ||
1234 | int n=hw_config->slots[1]; | ||
1235 | |||
1236 | if (n != -1) { | ||
1237 | release_region(hw_config->io_base, 2); | ||
1238 | if (hw_config->always_detect == 0 && hw_config->irq > 0) | ||
1239 | free_irq(hw_config->irq, (void *)n); | ||
1240 | p=mpu401_synth_operations[n]; | ||
1241 | sound_unload_mididev(n); | ||
1242 | sound_unload_timerdev(hw_config->slots[2]); | ||
1243 | if(p) | ||
1244 | kfree(p); | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1248 | /***************************************************** | ||
1249 | * Timer stuff | ||
1250 | ****************************************************/ | ||
1251 | |||
1252 | static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0; | ||
1253 | static volatile int curr_tempo, curr_timebase, hw_timebase; | ||
1254 | static int max_timebase = 8; /* 8*24=192 ppqn */ | ||
1255 | static volatile unsigned long next_event_time; | ||
1256 | static volatile unsigned long curr_ticks, curr_clocks; | ||
1257 | static unsigned long prev_event_time; | ||
1258 | static int metronome_mode; | ||
1259 | |||
1260 | static unsigned long clocks2ticks(unsigned long clocks) | ||
1261 | { | ||
1262 | /* | ||
1263 | * The MPU-401 supports just a limited set of possible timebase values. | ||
1264 | * Since the applications require more choices, the driver has to | ||
1265 | * program the HW to do its best and to convert between the HW and | ||
1266 | * actual timebases. | ||
1267 | */ | ||
1268 | return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase; | ||
1269 | } | ||
1270 | |||
1271 | static void set_timebase(int midi_dev, int val) | ||
1272 | { | ||
1273 | int hw_val; | ||
1274 | |||
1275 | if (val < 48) | ||
1276 | val = 48; | ||
1277 | if (val > 1000) | ||
1278 | val = 1000; | ||
1279 | |||
1280 | hw_val = val; | ||
1281 | hw_val = (hw_val + 12) / 24; | ||
1282 | if (hw_val > max_timebase) | ||
1283 | hw_val = max_timebase; | ||
1284 | |||
1285 | if (mpu_cmd(midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) | ||
1286 | { | ||
1287 | printk(KERN_WARNING "mpu401: Can't set HW timebase to %d\n", hw_val * 24); | ||
1288 | return; | ||
1289 | } | ||
1290 | hw_timebase = hw_val * 24; | ||
1291 | curr_timebase = val; | ||
1292 | |||
1293 | } | ||
1294 | |||
1295 | static void tmr_reset(struct mpu_config *devc) | ||
1296 | { | ||
1297 | unsigned long flags; | ||
1298 | |||
1299 | spin_lock_irqsave(&devc->lock,flags); | ||
1300 | next_event_time = (unsigned long) -1; | ||
1301 | prev_event_time = 0; | ||
1302 | curr_ticks = curr_clocks = 0; | ||
1303 | spin_unlock_irqrestore(&devc->lock,flags); | ||
1304 | } | ||
1305 | |||
1306 | static void set_timer_mode(int midi_dev) | ||
1307 | { | ||
1308 | if (timer_mode & TMR_MODE_CLS) | ||
1309 | mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ | ||
1310 | else if (timer_mode & TMR_MODE_SMPTE) | ||
1311 | mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ | ||
1312 | |||
1313 | if (timer_mode & TMR_INTERNAL) | ||
1314 | { | ||
1315 | mpu_cmd(midi_dev, 0x80, 0); /* Use MIDI sync */ | ||
1316 | } | ||
1317 | else | ||
1318 | { | ||
1319 | if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) | ||
1320 | { | ||
1321 | mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */ | ||
1322 | mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ | ||
1323 | } | ||
1324 | else if (timer_mode & TMR_MODE_FSK) | ||
1325 | mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */ | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | static void stop_metronome(int midi_dev) | ||
1330 | { | ||
1331 | mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ | ||
1332 | } | ||
1333 | |||
1334 | static void setup_metronome(int midi_dev) | ||
1335 | { | ||
1336 | int numerator, denominator; | ||
1337 | int clks_per_click, num_32nds_per_beat; | ||
1338 | int beats_per_measure; | ||
1339 | |||
1340 | numerator = ((unsigned) metronome_mode >> 24) & 0xff; | ||
1341 | denominator = ((unsigned) metronome_mode >> 16) & 0xff; | ||
1342 | clks_per_click = ((unsigned) metronome_mode >> 8) & 0xff; | ||
1343 | num_32nds_per_beat = (unsigned) metronome_mode & 0xff; | ||
1344 | beats_per_measure = (numerator * 4) >> denominator; | ||
1345 | |||
1346 | if (!metronome_mode) | ||
1347 | mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ | ||
1348 | else | ||
1349 | { | ||
1350 | mpu_cmd(midi_dev, 0xE4, clks_per_click); | ||
1351 | mpu_cmd(midi_dev, 0xE6, beats_per_measure); | ||
1352 | mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without accents */ | ||
1353 | } | ||
1354 | } | ||
1355 | |||
1356 | static int mpu_start_timer(int midi_dev) | ||
1357 | { | ||
1358 | struct mpu_config *devc= &dev_conf[midi_dev]; | ||
1359 | |||
1360 | tmr_reset(devc); | ||
1361 | set_timer_mode(midi_dev); | ||
1362 | |||
1363 | if (tmr_running) | ||
1364 | return TIMER_NOT_ARMED; /* Already running */ | ||
1365 | |||
1366 | if (timer_mode & TMR_INTERNAL) | ||
1367 | { | ||
1368 | mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */ | ||
1369 | tmr_running = 1; | ||
1370 | return TIMER_NOT_ARMED; | ||
1371 | } | ||
1372 | else | ||
1373 | { | ||
1374 | mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */ | ||
1375 | mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */ | ||
1376 | mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */ | ||
1377 | mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ | ||
1378 | } | ||
1379 | return TIMER_ARMED; | ||
1380 | } | ||
1381 | |||
1382 | static int mpu_timer_open(int dev, int mode) | ||
1383 | { | ||
1384 | int midi_dev = sound_timer_devs[dev]->devlink; | ||
1385 | struct mpu_config *devc= &dev_conf[midi_dev]; | ||
1386 | |||
1387 | if (timer_open) | ||
1388 | return -EBUSY; | ||
1389 | |||
1390 | tmr_reset(devc); | ||
1391 | curr_tempo = 50; | ||
1392 | mpu_cmd(midi_dev, 0xE0, 50); | ||
1393 | curr_timebase = hw_timebase = 120; | ||
1394 | set_timebase(midi_dev, 120); | ||
1395 | timer_open = 1; | ||
1396 | metronome_mode = 0; | ||
1397 | set_timer_mode(midi_dev); | ||
1398 | |||
1399 | mpu_cmd(midi_dev, 0xe7, 0x04); /* Send all clocks to host */ | ||
1400 | mpu_cmd(midi_dev, 0x95, 0); /* Enable clock to host */ | ||
1401 | |||
1402 | return 0; | ||
1403 | } | ||
1404 | |||
1405 | static void mpu_timer_close(int dev) | ||
1406 | { | ||
1407 | int midi_dev = sound_timer_devs[dev]->devlink; | ||
1408 | |||
1409 | timer_open = tmr_running = 0; | ||
1410 | mpu_cmd(midi_dev, 0x15, 0); /* Stop all */ | ||
1411 | mpu_cmd(midi_dev, 0x94, 0); /* Disable clock to host */ | ||
1412 | mpu_cmd(midi_dev, 0x8c, 0); /* Disable measure end messages to host */ | ||
1413 | stop_metronome(midi_dev); | ||
1414 | } | ||
1415 | |||
1416 | static int mpu_timer_event(int dev, unsigned char *event) | ||
1417 | { | ||
1418 | unsigned char command = event[1]; | ||
1419 | unsigned long parm = *(unsigned int *) &event[4]; | ||
1420 | int midi_dev = sound_timer_devs[dev]->devlink; | ||
1421 | |||
1422 | switch (command) | ||
1423 | { | ||
1424 | case TMR_WAIT_REL: | ||
1425 | parm += prev_event_time; | ||
1426 | case TMR_WAIT_ABS: | ||
1427 | if (parm > 0) | ||
1428 | { | ||
1429 | long time; | ||
1430 | |||
1431 | if (parm <= curr_ticks) /* It's the time */ | ||
1432 | return TIMER_NOT_ARMED; | ||
1433 | time = parm; | ||
1434 | next_event_time = prev_event_time = time; | ||
1435 | |||
1436 | return TIMER_ARMED; | ||
1437 | } | ||
1438 | break; | ||
1439 | |||
1440 | case TMR_START: | ||
1441 | if (tmr_running) | ||
1442 | break; | ||
1443 | return mpu_start_timer(midi_dev); | ||
1444 | |||
1445 | case TMR_STOP: | ||
1446 | mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ | ||
1447 | stop_metronome(midi_dev); | ||
1448 | tmr_running = 0; | ||
1449 | break; | ||
1450 | |||
1451 | case TMR_CONTINUE: | ||
1452 | if (tmr_running) | ||
1453 | break; | ||
1454 | mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ | ||
1455 | setup_metronome(midi_dev); | ||
1456 | tmr_running = 1; | ||
1457 | break; | ||
1458 | |||
1459 | case TMR_TEMPO: | ||
1460 | if (parm) | ||
1461 | { | ||
1462 | if (parm < 8) | ||
1463 | parm = 8; | ||
1464 | if (parm > 250) | ||
1465 | parm = 250; | ||
1466 | if (mpu_cmd(midi_dev, 0xE0, parm) < 0) | ||
1467 | printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) parm); | ||
1468 | curr_tempo = parm; | ||
1469 | } | ||
1470 | break; | ||
1471 | |||
1472 | case TMR_ECHO: | ||
1473 | seq_copy_to_input(event, 8); | ||
1474 | break; | ||
1475 | |||
1476 | case TMR_TIMESIG: | ||
1477 | if (metronome_mode) /* Metronome enabled */ | ||
1478 | { | ||
1479 | metronome_mode = parm; | ||
1480 | setup_metronome(midi_dev); | ||
1481 | } | ||
1482 | break; | ||
1483 | |||
1484 | default:; | ||
1485 | } | ||
1486 | return TIMER_NOT_ARMED; | ||
1487 | } | ||
1488 | |||
1489 | static unsigned long mpu_timer_get_time(int dev) | ||
1490 | { | ||
1491 | if (!timer_open) | ||
1492 | return 0; | ||
1493 | |||
1494 | return curr_ticks; | ||
1495 | } | ||
1496 | |||
1497 | static int mpu_timer_ioctl(int dev, unsigned int command, void __user *arg) | ||
1498 | { | ||
1499 | int midi_dev = sound_timer_devs[dev]->devlink; | ||
1500 | int __user *p = (int __user *)arg; | ||
1501 | |||
1502 | switch (command) | ||
1503 | { | ||
1504 | case SNDCTL_TMR_SOURCE: | ||
1505 | { | ||
1506 | int parm; | ||
1507 | |||
1508 | if (get_user(parm, p)) | ||
1509 | return -EFAULT; | ||
1510 | parm &= timer_caps; | ||
1511 | |||
1512 | if (parm != 0) | ||
1513 | { | ||
1514 | timer_mode = parm; | ||
1515 | |||
1516 | if (timer_mode & TMR_MODE_CLS) | ||
1517 | mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ | ||
1518 | else if (timer_mode & TMR_MODE_SMPTE) | ||
1519 | mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ | ||
1520 | } | ||
1521 | if (put_user(timer_mode, p)) | ||
1522 | return -EFAULT; | ||
1523 | return timer_mode; | ||
1524 | } | ||
1525 | break; | ||
1526 | |||
1527 | case SNDCTL_TMR_START: | ||
1528 | mpu_start_timer(midi_dev); | ||
1529 | return 0; | ||
1530 | |||
1531 | case SNDCTL_TMR_STOP: | ||
1532 | tmr_running = 0; | ||
1533 | mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ | ||
1534 | stop_metronome(midi_dev); | ||
1535 | return 0; | ||
1536 | |||
1537 | case SNDCTL_TMR_CONTINUE: | ||
1538 | if (tmr_running) | ||
1539 | return 0; | ||
1540 | tmr_running = 1; | ||
1541 | mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ | ||
1542 | return 0; | ||
1543 | |||
1544 | case SNDCTL_TMR_TIMEBASE: | ||
1545 | { | ||
1546 | int val; | ||
1547 | if (get_user(val, p)) | ||
1548 | return -EFAULT; | ||
1549 | if (val) | ||
1550 | set_timebase(midi_dev, val); | ||
1551 | if (put_user(curr_timebase, p)) | ||
1552 | return -EFAULT; | ||
1553 | return curr_timebase; | ||
1554 | } | ||
1555 | break; | ||
1556 | |||
1557 | case SNDCTL_TMR_TEMPO: | ||
1558 | { | ||
1559 | int val; | ||
1560 | int ret; | ||
1561 | |||
1562 | if (get_user(val, p)) | ||
1563 | return -EFAULT; | ||
1564 | |||
1565 | if (val) | ||
1566 | { | ||
1567 | if (val < 8) | ||
1568 | val = 8; | ||
1569 | if (val > 250) | ||
1570 | val = 250; | ||
1571 | if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) | ||
1572 | { | ||
1573 | printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) val); | ||
1574 | return ret; | ||
1575 | } | ||
1576 | curr_tempo = val; | ||
1577 | } | ||
1578 | if (put_user(curr_tempo, p)) | ||
1579 | return -EFAULT; | ||
1580 | return curr_tempo; | ||
1581 | } | ||
1582 | break; | ||
1583 | |||
1584 | case SNDCTL_SEQ_CTRLRATE: | ||
1585 | { | ||
1586 | int val; | ||
1587 | if (get_user(val, p)) | ||
1588 | return -EFAULT; | ||
1589 | |||
1590 | if (val != 0) /* Can't change */ | ||
1591 | return -EINVAL; | ||
1592 | val = ((curr_tempo * curr_timebase) + 30)/60; | ||
1593 | if (put_user(val, p)) | ||
1594 | return -EFAULT; | ||
1595 | return val; | ||
1596 | } | ||
1597 | break; | ||
1598 | |||
1599 | case SNDCTL_SEQ_GETTIME: | ||
1600 | if (put_user(curr_ticks, p)) | ||
1601 | return -EFAULT; | ||
1602 | return curr_ticks; | ||
1603 | |||
1604 | case SNDCTL_TMR_METRONOME: | ||
1605 | if (get_user(metronome_mode, p)) | ||
1606 | return -EFAULT; | ||
1607 | setup_metronome(midi_dev); | ||
1608 | return 0; | ||
1609 | |||
1610 | default:; | ||
1611 | } | ||
1612 | return -EINVAL; | ||
1613 | } | ||
1614 | |||
1615 | static void mpu_timer_arm(int dev, long time) | ||
1616 | { | ||
1617 | if (time < 0) | ||
1618 | time = curr_ticks + 1; | ||
1619 | else if (time <= curr_ticks) /* It's the time */ | ||
1620 | return; | ||
1621 | next_event_time = prev_event_time = time; | ||
1622 | return; | ||
1623 | } | ||
1624 | |||
1625 | static struct sound_timer_operations mpu_timer = | ||
1626 | { | ||
1627 | .owner = THIS_MODULE, | ||
1628 | .info = {"MPU-401 Timer", 0}, | ||
1629 | .priority = 10, /* Priority */ | ||
1630 | .devlink = 0, /* Local device link */ | ||
1631 | .open = mpu_timer_open, | ||
1632 | .close = mpu_timer_close, | ||
1633 | .event = mpu_timer_event, | ||
1634 | .get_time = mpu_timer_get_time, | ||
1635 | .ioctl = mpu_timer_ioctl, | ||
1636 | .arm_timer = mpu_timer_arm | ||
1637 | }; | ||
1638 | |||
1639 | static void mpu_timer_interrupt(void) | ||
1640 | { | ||
1641 | if (!timer_open) | ||
1642 | return; | ||
1643 | |||
1644 | if (!tmr_running) | ||
1645 | return; | ||
1646 | |||
1647 | curr_clocks++; | ||
1648 | curr_ticks = clocks2ticks(curr_clocks); | ||
1649 | |||
1650 | if (curr_ticks >= next_event_time) | ||
1651 | { | ||
1652 | next_event_time = (unsigned long) -1; | ||
1653 | sequencer_timer(0); | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | static void timer_ext_event(struct mpu_config *devc, int event, int parm) | ||
1658 | { | ||
1659 | int midi_dev = devc->devno; | ||
1660 | |||
1661 | if (!devc->timer_flag) | ||
1662 | return; | ||
1663 | |||
1664 | switch (event) | ||
1665 | { | ||
1666 | case TMR_CLOCK: | ||
1667 | printk("<MIDI clk>"); | ||
1668 | break; | ||
1669 | |||
1670 | case TMR_START: | ||
1671 | printk("Ext MIDI start\n"); | ||
1672 | if (!tmr_running) | ||
1673 | { | ||
1674 | if (timer_mode & TMR_EXTERNAL) | ||
1675 | { | ||
1676 | tmr_running = 1; | ||
1677 | setup_metronome(midi_dev); | ||
1678 | next_event_time = 0; | ||
1679 | STORE(SEQ_START_TIMER()); | ||
1680 | } | ||
1681 | } | ||
1682 | break; | ||
1683 | |||
1684 | case TMR_STOP: | ||
1685 | printk("Ext MIDI stop\n"); | ||
1686 | if (timer_mode & TMR_EXTERNAL) | ||
1687 | { | ||
1688 | tmr_running = 0; | ||
1689 | stop_metronome(midi_dev); | ||
1690 | STORE(SEQ_STOP_TIMER()); | ||
1691 | } | ||
1692 | break; | ||
1693 | |||
1694 | case TMR_CONTINUE: | ||
1695 | printk("Ext MIDI continue\n"); | ||
1696 | if (timer_mode & TMR_EXTERNAL) | ||
1697 | { | ||
1698 | tmr_running = 1; | ||
1699 | setup_metronome(midi_dev); | ||
1700 | STORE(SEQ_CONTINUE_TIMER()); | ||
1701 | } | ||
1702 | break; | ||
1703 | |||
1704 | case TMR_SPP: | ||
1705 | printk("Songpos: %d\n", parm); | ||
1706 | if (timer_mode & TMR_EXTERNAL) | ||
1707 | { | ||
1708 | STORE(SEQ_SONGPOS(parm)); | ||
1709 | } | ||
1710 | break; | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | static int mpu_timer_init(int midi_dev) | ||
1715 | { | ||
1716 | struct mpu_config *devc; | ||
1717 | int n; | ||
1718 | |||
1719 | devc = &dev_conf[midi_dev]; | ||
1720 | |||
1721 | if (timer_initialized) | ||
1722 | return -1; /* There is already a similar timer */ | ||
1723 | |||
1724 | timer_initialized = 1; | ||
1725 | |||
1726 | mpu_timer.devlink = midi_dev; | ||
1727 | dev_conf[midi_dev].timer_flag = 1; | ||
1728 | |||
1729 | n = sound_alloc_timerdev(); | ||
1730 | if (n == -1) | ||
1731 | n = 0; | ||
1732 | sound_timer_devs[n] = &mpu_timer; | ||
1733 | |||
1734 | if (devc->version < 0x20) /* Original MPU-401 */ | ||
1735 | timer_caps = TMR_INTERNAL | TMR_EXTERNAL | TMR_MODE_FSK | TMR_MODE_MIDI; | ||
1736 | else | ||
1737 | { | ||
1738 | /* | ||
1739 | * The version number 2.0 is used (at least) by the | ||
1740 | * MusicQuest cards and the Roland Super-MPU. | ||
1741 | * | ||
1742 | * MusicQuest has given a special meaning to the bits of the | ||
1743 | * revision number. The Super-MPU returns 0. | ||
1744 | */ | ||
1745 | |||
1746 | if (devc->revision) | ||
1747 | timer_caps |= TMR_EXTERNAL | TMR_MODE_MIDI; | ||
1748 | |||
1749 | if (devc->revision & 0x02) | ||
1750 | timer_caps |= TMR_MODE_CLS; | ||
1751 | |||
1752 | |||
1753 | if (devc->revision & 0x40) | ||
1754 | max_timebase = 10; /* Has the 216 and 240 ppqn modes */ | ||
1755 | } | ||
1756 | |||
1757 | timer_mode = (TMR_INTERNAL | TMR_MODE_MIDI) & timer_caps; | ||
1758 | return n; | ||
1759 | |||
1760 | } | ||
1761 | |||
1762 | EXPORT_SYMBOL(probe_mpu401); | ||
1763 | EXPORT_SYMBOL(attach_mpu401); | ||
1764 | EXPORT_SYMBOL(unload_mpu401); | ||
1765 | EXPORT_SYMBOL(intchk_mpu401); | ||
1766 | EXPORT_SYMBOL(mpuintr); | ||
1767 | |||
1768 | static struct address_info cfg; | ||
1769 | |||
1770 | static int io = -1; | ||
1771 | static int irq = -1; | ||
1772 | |||
1773 | module_param(irq, int, 0); | ||
1774 | module_param(io, int, 0); | ||
1775 | |||
1776 | static int __init init_mpu401(void) | ||
1777 | { | ||
1778 | int ret; | ||
1779 | /* Can be loaded either for module use or to provide functions | ||
1780 | to others */ | ||
1781 | if (io != -1 && irq != -1) { | ||
1782 | struct resource *ports; | ||
1783 | cfg.irq = irq; | ||
1784 | cfg.io_base = io; | ||
1785 | ports = request_region(io, 2, "mpu401"); | ||
1786 | if (!ports) | ||
1787 | return -EBUSY; | ||
1788 | if (probe_mpu401(&cfg, ports) == 0) { | ||
1789 | release_region(io, 2); | ||
1790 | return -ENODEV; | ||
1791 | } | ||
1792 | if ((ret = attach_mpu401(&cfg, THIS_MODULE))) | ||
1793 | return ret; | ||
1794 | } | ||
1795 | |||
1796 | return 0; | ||
1797 | } | ||
1798 | |||
1799 | static void __exit cleanup_mpu401(void) | ||
1800 | { | ||
1801 | if (io != -1 && irq != -1) { | ||
1802 | /* Check for use by, for example, sscape driver */ | ||
1803 | unload_mpu401(&cfg); | ||
1804 | } | ||
1805 | } | ||
1806 | |||
1807 | module_init(init_mpu401); | ||
1808 | module_exit(cleanup_mpu401); | ||
1809 | |||
1810 | #ifndef MODULE | ||
1811 | static int __init setup_mpu401(char *str) | ||
1812 | { | ||
1813 | /* io, irq */ | ||
1814 | int ints[3]; | ||
1815 | |||
1816 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
1817 | |||
1818 | io = ints[1]; | ||
1819 | irq = ints[2]; | ||
1820 | |||
1821 | return 1; | ||
1822 | } | ||
1823 | |||
1824 | __setup("mpu401=", setup_mpu401); | ||
1825 | #endif | ||
1826 | MODULE_LICENSE("GPL"); | ||