4 * The low level driver for the GUS Midi Interface.
7 * Copyright (C) by Hannu Savolainen 1993-1997
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
14 * 11-10-2000 Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
15 * Added __init to gus_midi_init()
18 #include <linux/init.h>
19 #include <linux/spinlock.h>
20 #include "sound_config.h"
25 static int midi_busy
, input_opened
;
27 static int output_used
;
28 static volatile unsigned char gus_midi_control
;
29 static void (*midi_input_intr
) (int dev
, unsigned char data
);
31 static unsigned char tmp_queue
[256];
32 extern int gus_pnp_flag
;
33 static volatile int qlen
;
34 static volatile unsigned char qhead
, qtail
;
35 extern int gus_base
, gus_irq
, gus_dma
;
37 extern spinlock_t gus_lock
;
39 static int GUS_MIDI_STATUS(void)
41 return inb(u_MidiStatus
);
44 static int gus_midi_open(int dev
, int mode
, void (*input
) (int dev
, unsigned char data
), void (*output
) (int dev
))
48 /* printk("GUS: Midi busy\n");*/
51 outb((MIDI_RESET
), u_MidiControl
);
57 if (mode
== OPEN_READ
|| mode
== OPEN_READWRITE
)
60 gus_midi_control
|= MIDI_ENABLE_RCV
;
63 outb((gus_midi_control
), u_MidiControl
); /* Enable */
66 qlen
= qhead
= qtail
= output_used
= 0;
67 midi_input_intr
= input
;
72 static int dump_to_midi(unsigned char midi_byte
)
79 spin_lock_irqsave(&gus_lock
, flags
);
81 if (GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY
)
84 outb((midi_byte
), u_MidiData
);
89 * Enable Midi xmit interrupts (again)
91 gus_midi_control
|= MIDI_ENABLE_XMIT
;
92 outb((gus_midi_control
), u_MidiControl
);
95 spin_unlock_irqrestore(&gus_lock
,flags
);
99 static void gus_midi_close(int dev
)
102 * Reset FIFO pointers, disable intrs
105 outb((MIDI_RESET
), u_MidiControl
);
109 static int gus_midi_out(int dev
, unsigned char midi_byte
)
114 * Drain the local queue first
116 spin_lock_irqsave(&gus_lock
, flags
);
118 while (qlen
&& dump_to_midi(tmp_queue
[qhead
]))
123 spin_unlock_irqrestore(&gus_lock
,flags
);
126 * Output the byte if the local queue is empty.
130 if (dump_to_midi(midi_byte
))
136 * Put to the local queue
143 spin_lock_irqsave(&gus_lock
, flags
);
145 tmp_queue
[qtail
] = midi_byte
;
149 spin_unlock_irqrestore(&gus_lock
,flags
);
153 static int gus_midi_start_read(int dev
)
158 static int gus_midi_end_read(int dev
)
163 static void gus_midi_kick(int dev
)
167 static int gus_midi_buffer_status(int dev
)
174 spin_lock_irqsave(&gus_lock
, flags
);
176 if (qlen
&& dump_to_midi(tmp_queue
[qhead
]))
181 spin_unlock_irqrestore(&gus_lock
,flags
);
182 return (qlen
> 0) || !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY
);
185 #define MIDI_SYNTH_NAME "Gravis Ultrasound Midi"
186 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
187 #include "midi_synth.h"
189 static struct midi_operations gus_midi_operations
=
191 .owner
= THIS_MODULE
,
192 .info
= {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS
},
193 .converter
= &std_midi_synth
,
195 .open
= gus_midi_open
,
196 .close
= gus_midi_close
,
197 .outputc
= gus_midi_out
,
198 .start_read
= gus_midi_start_read
,
199 .end_read
= gus_midi_end_read
,
200 .kick
= gus_midi_kick
,
201 .buffer_status
= gus_midi_buffer_status
,
204 void __init
gus_midi_init(struct address_info
*hw_config
)
206 int dev
= sound_alloc_mididev();
210 printk(KERN_INFO
"gus_midi: Too many midi devices detected\n");
213 outb((MIDI_RESET
), u_MidiControl
);
215 std_midi_synth
.midi_dev
= my_dev
= dev
;
216 hw_config
->slots
[2] = dev
;
217 midi_devs
[dev
] = &gus_midi_operations
;
222 void gus_midi_interrupt(int dummy
)
224 volatile unsigned char stat
, data
;
227 spin_lock(&gus_lock
);
229 while (timeout
-- > 0 && (stat
= GUS_MIDI_STATUS()) & (MIDI_RCV_FULL
| MIDI_XMIT_EMPTY
))
231 if (stat
& MIDI_RCV_FULL
)
233 data
= inb(u_MidiData
);
235 midi_input_intr(my_dev
, data
);
237 if (stat
& MIDI_XMIT_EMPTY
)
239 while (qlen
&& dump_to_midi(tmp_queue
[qhead
]))
247 * Disable Midi output interrupts, since no data in the buffer
249 gus_midi_control
&= ~MIDI_ENABLE_XMIT
;
250 outb((gus_midi_control
), u_MidiControl
);
251 outb((gus_midi_control
), u_MidiControl
);
255 spin_unlock(&gus_lock
);