~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/sound/gus_midi.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * sound/gus2_midi.c
  3  *
  4  * The low level driver for the GUS Midi Interface.
  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  * 11-10-2000   Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
 15  *              Added __init to gus_midi_init()
 16  */
 17 
 18 #include "linux/init.h"
 19 #include "sound_config.h"
 20 
 21 #include "gus.h"
 22 #include "gus_hw.h"
 23 
 24 static int      midi_busy = 0, input_opened = 0;
 25 static int      my_dev;
 26 static int      output_used = 0;
 27 static volatile unsigned char gus_midi_control;
 28 
 29 static void     (*midi_input_intr) (int dev, unsigned char data);
 30 
 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;
 36 extern int     *gus_osp;
 37 
 38 static int GUS_MIDI_STATUS(void)
 39 {
 40         return inb(u_MidiStatus);
 41 }
 42 
 43 static int gus_midi_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev))
 44 {
 45         if (midi_busy)
 46         {
 47 /*              printk("GUS: Midi busy\n");*/
 48                 return -EBUSY;
 49         }
 50         outb((MIDI_RESET), u_MidiControl);
 51         gus_delay();
 52 
 53         gus_midi_control = 0;
 54         input_opened = 0;
 55 
 56         if (mode == OPEN_READ || mode == OPEN_READWRITE)
 57                 if (!gus_pnp_flag)
 58                 {
 59                         gus_midi_control |= MIDI_ENABLE_RCV;
 60                         input_opened = 1;
 61                 }
 62         outb((gus_midi_control), u_MidiControl);        /* Enable */
 63 
 64         midi_busy = 1;
 65         qlen = qhead = qtail = output_used = 0;
 66         midi_input_intr = input;
 67 
 68         return 0;
 69 }
 70 
 71 static int dump_to_midi(unsigned char midi_byte)
 72 {
 73         unsigned long   flags;
 74         int             ok = 0;
 75 
 76         output_used = 1;
 77 
 78         save_flags(flags);
 79         cli();
 80 
 81         if (GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY)
 82         {
 83                 ok = 1;
 84                 outb((midi_byte), u_MidiData);
 85         }
 86         else
 87         {
 88                 /*
 89                  * Enable Midi xmit interrupts (again)
 90                  */
 91                 gus_midi_control |= MIDI_ENABLE_XMIT;
 92                 outb((gus_midi_control), u_MidiControl);
 93         }
 94 
 95         restore_flags(flags);
 96         return ok;
 97 }
 98 
 99 static void gus_midi_close(int dev)
100 {
101         /*
102          * Reset FIFO pointers, disable intrs
103          */
104 
105         outb((MIDI_RESET), u_MidiControl);
106         midi_busy = 0;
107 }
108 
109 static int gus_midi_out(int dev, unsigned char midi_byte)
110 {
111         unsigned long   flags;
112 
113         /*
114          * Drain the local queue first
115          */
116 
117         save_flags(flags);
118         cli();
119 
120         while (qlen && dump_to_midi(tmp_queue[qhead]))
121         {
122                 qlen--;
123                 qhead++;
124         }
125         restore_flags(flags);
126 
127         /*
128          *      Output the byte if the local queue is empty.
129          */
130 
131         if (!qlen)
132                 if (dump_to_midi(midi_byte))
133                         return 1;       /*
134                                          * OK
135                                          */
136 
137         /*
138          *      Put to the local queue
139          */
140 
141         if (qlen >= 256)
142                 return 0;       /*
143                                  * Local queue full
144                                  */
145         save_flags(flags);
146         cli();
147 
148         tmp_queue[qtail] = midi_byte;
149         qlen++;
150         qtail++;
151 
152         restore_flags(flags);
153         return 1;
154 }
155 
156 static int gus_midi_start_read(int dev)
157 {
158         return 0;
159 }
160 
161 static int gus_midi_end_read(int dev)
162 {
163         return 0;
164 }
165 
166 static void gus_midi_kick(int dev)
167 {
168 }
169 
170 static int gus_midi_buffer_status(int dev)
171 {
172         unsigned long   flags;
173 
174         if (!output_used)
175                 return 0;
176 
177         save_flags(flags);
178         cli();
179 
180         if (qlen && dump_to_midi(tmp_queue[qhead]))
181         {
182                 qlen--;
183                 qhead++;
184         }
185         restore_flags(flags);
186         return (qlen > 0) | !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY);
187 }
188 
189 #define MIDI_SYNTH_NAME "Gravis Ultrasound Midi"
190 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
191 #include "midi_synth.h"
192 
193 static struct midi_operations gus_midi_operations =
194 {
195         owner:          THIS_MODULE,
196         info:           {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
197         converter:      &std_midi_synth,
198         in_info:        {0},
199         open:           gus_midi_open,
200         close:          gus_midi_close,
201         outputc:        gus_midi_out,
202         start_read:     gus_midi_start_read,
203         end_read:       gus_midi_end_read,
204         kick:           gus_midi_kick,
205         buffer_status:  gus_midi_buffer_status,
206 };
207 
208 void __init gus_midi_init(struct address_info *hw_config)
209 {
210         int dev = sound_alloc_mididev();
211 
212         if (dev == -1)
213         {
214                 printk(KERN_INFO "gus_midi: Too many midi devices detected\n");
215                 return;
216         }
217         outb((MIDI_RESET), u_MidiControl);
218 
219         std_midi_synth.midi_dev = my_dev = dev;
220         hw_config->slots[2] = dev;
221         midi_devs[dev] = &gus_midi_operations;
222         sequencer_init();
223         return;
224 }
225 
226 void gus_midi_interrupt(int dummy)
227 {
228         volatile unsigned char stat, data;
229         unsigned long flags;
230         int timeout = 10;
231 
232         save_flags(flags);
233         cli();
234 
235         while (timeout-- > 0 && (stat = GUS_MIDI_STATUS()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY))
236         {
237                 if (stat & MIDI_RCV_FULL)
238                 {
239                         data = inb(u_MidiData);
240                         if (input_opened)
241                                 midi_input_intr(my_dev, data);
242                 }
243                 if (stat & MIDI_XMIT_EMPTY)
244                 {
245                         while (qlen && dump_to_midi(tmp_queue[qhead]))
246                         {
247                                 qlen--;
248                                 qhead++;
249                         }
250                         if (!qlen)
251                         {
252                               /*
253                                * Disable Midi output interrupts, since no data in the buffer
254                                */
255                               gus_midi_control &= ~MIDI_ENABLE_XMIT;
256                               outb((gus_midi_control), u_MidiControl);
257                               outb((gus_midi_control), u_MidiControl);
258                         }
259                 }
260         }
261         restore_flags(flags);
262 }
263 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.