kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / dev / sound / isa / i386 / gus / gus_midi.c
1 /*
2  * sound/gus2_midi.c
3  * 
4  * The low level driver for the GUS Midi Interface.
5  * 
6  * Copyright by Hannu Savolainen 1993
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met: 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer. 2.
12  * Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  * 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  * 
28  * $DragonFly: src/sys/dev/sound/isa/i386/gus/Attic/gus_midi.c,v 1.2 2003/08/07 21:17:12 dillon Exp $
29  */
30
31 #include <i386/isa/sound/sound_config.h>
32
33 #if defined(CONFIG_GUS) && defined(CONFIG_MIDI)
34 #include "gus_hw.h"
35
36 static int      midi_busy = 0, input_opened = 0;
37 static int      my_dev;
38 static int      output_used = 0;
39 static volatile unsigned char gus_midi_control;
40
41 static void     (*midi_input_intr) (int dev, unsigned char data);
42
43 static unsigned char tmp_queue[256];
44 static volatile int qlen;
45 static volatile unsigned char qhead, qtail;
46 extern int      gus_base, gus_irq, gus_dma;
47 extern sound_os_info *gus_osp;
48
49 #define GUS_MIDI_STATUS()       inb( u_MidiStatus)
50
51 static int
52 gus_midi_open(int dev, int mode,
53               void (*input) (int dev, unsigned char data),
54               void (*output) (int dev)
55 )
56 {
57
58         if (midi_busy) {
59                 printf("GUS: Midi busy\n");
60                 return -(EBUSY);
61         }
62         outb(u_MidiControl, MIDI_RESET);
63         gus_delay();
64
65         gus_midi_control = 0;
66         input_opened = 0;
67
68         if (mode == OPEN_READ || mode == OPEN_READWRITE) {
69                 gus_midi_control |= MIDI_ENABLE_RCV;
70                 input_opened = 1;
71         }
72         if (mode == OPEN_WRITE || mode == OPEN_READWRITE) {
73                 gus_midi_control |= MIDI_ENABLE_XMIT;
74         }
75         outb(u_MidiControl, gus_midi_control);  /* Enable */
76
77         midi_busy = 1;
78         qlen = qhead = qtail = output_used = 0;
79         midi_input_intr = input;
80
81         return 0;
82 }
83
84 static int
85 dump_to_midi(unsigned char midi_byte)
86 {
87         unsigned long   flags;
88         int             ok = 0;
89
90         output_used = 1;
91
92         flags = splhigh();
93
94         if (GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY) {
95                 ok = 1;
96                 outb(u_MidiData, midi_byte);
97         } else {
98                 /*
99                  * Enable Midi xmit interrupts (again)
100                  */
101                 gus_midi_control |= MIDI_ENABLE_XMIT;
102                 outb(u_MidiControl, gus_midi_control);
103         }
104
105         splx(flags);
106         return ok;
107 }
108
109 static void
110 gus_midi_close(int dev)
111 {
112         /*
113          * Reset FIFO pointers, disable intrs
114          */
115
116         outb(u_MidiControl, MIDI_RESET);
117         midi_busy = 0;
118 }
119
120 static int
121 gus_midi_out(int dev, unsigned char midi_byte)
122 {
123
124         unsigned long   flags;
125
126         /*
127          * Drain the local queue first
128          */
129
130         flags = splhigh();
131
132         while (qlen && dump_to_midi(tmp_queue[qhead])) {
133                 qlen--;
134                 qhead++;
135         }
136
137         splx(flags);
138
139         /*
140          * Output the byte if the local queue is empty.
141          */
142
143         if (!qlen)
144                 if (dump_to_midi(midi_byte))
145                         return 1;       /* OK */
146
147         /*
148          * Put to the local queue
149          */
150
151         if (qlen >= 256)
152                 return 0;       /* Local queue full */
153
154         flags = splhigh();
155
156         tmp_queue[qtail] = midi_byte;
157         qlen++;
158         qtail++;
159
160         splx(flags);
161
162         return 1;
163 }
164
165 static int
166 gus_midi_start_read(int dev)
167 {
168         return 0;
169 }
170
171 static int
172 gus_midi_end_read(int dev)
173 {
174         return 0;
175 }
176
177 static int
178 gus_midi_ioctl(int dev, unsigned cmd, ioctl_arg arg)
179 {
180         return -(EINVAL);
181 }
182
183 static void
184 gus_midi_kick(int dev)
185 {
186 }
187
188 static int
189 gus_midi_buffer_status(int dev)
190 {
191         unsigned long   flags;
192
193         if (!output_used)
194                 return 0;
195
196         flags = splhigh();
197
198         if (qlen && dump_to_midi(tmp_queue[qhead])) {
199                 qlen--;
200                 qhead++;
201         }
202         splx(flags);
203
204         return (qlen > 0) | !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY);
205 }
206
207 #define MIDI_SYNTH_NAME "Gravis Ultrasound Midi"
208 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
209 #include <i386/isa/sound/midi_synth.h>
210
211 static struct midi_operations gus_midi_operations =
212 {
213         {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
214         &std_midi_synth,
215         {0},
216         gus_midi_open,
217         gus_midi_close,
218         gus_midi_ioctl,
219         gus_midi_out,
220         gus_midi_start_read,
221         gus_midi_end_read,
222         gus_midi_kick,
223         NULL,                   /* command */
224         gus_midi_buffer_status,
225         NULL
226 };
227
228 void
229 gus_midi_init()
230 {
231         if (num_midis >= MAX_MIDI_DEV) {
232                 printf("Sound: Too many midi devices detected\n");
233                 return;
234         }
235         outb(u_MidiControl, MIDI_RESET);
236
237         std_midi_synth.midi_dev = my_dev = num_midis;
238         midi_devs[num_midis++] = &gus_midi_operations;
239         return;
240 }
241
242 void
243 gus_midi_interrupt(int dummy)
244 {
245         unsigned char   stat, data;
246         unsigned long   flags;
247
248         flags = splhigh();
249
250         stat = GUS_MIDI_STATUS();
251
252         if (stat & MIDI_RCV_FULL) {
253                 data = inb(u_MidiData);
254                 if (input_opened)
255                         midi_input_intr(my_dev, data);
256         }
257         if (stat & MIDI_XMIT_EMPTY) {
258                 while (qlen && dump_to_midi(tmp_queue[qhead])) {
259                         qlen--;
260                         qhead++;
261                 }
262
263                 if (!qlen) {
264                         /*
265                          * Disable Midi output interrupts, since no data in
266                          * the buffer
267                          */
268                         gus_midi_control &= ~MIDI_ENABLE_XMIT;
269                         outb(u_MidiControl, gus_midi_control);
270                 }
271         }
272         splx(flags);
273 }
274
275 #endif