Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 256 lines 5.0 kB view raw
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 <linux/spinlock.h> 20#include "sound_config.h" 21 22#include "gus.h" 23#include "gus_hw.h" 24 25static int midi_busy, input_opened; 26static int my_dev; 27static int output_used; 28static volatile unsigned char gus_midi_control; 29static void (*midi_input_intr) (int dev, unsigned char data); 30 31static unsigned char tmp_queue[256]; 32extern int gus_pnp_flag; 33static volatile int qlen; 34static volatile unsigned char qhead, qtail; 35extern int gus_base, gus_irq, gus_dma; 36extern int *gus_osp; 37extern spinlock_t gus_lock; 38 39static int GUS_MIDI_STATUS(void) 40{ 41 return inb(u_MidiStatus); 42} 43 44static int gus_midi_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev)) 45{ 46 if (midi_busy) 47 { 48/* printk("GUS: Midi busy\n");*/ 49 return -EBUSY; 50 } 51 outb((MIDI_RESET), u_MidiControl); 52 gus_delay(); 53 54 gus_midi_control = 0; 55 input_opened = 0; 56 57 if (mode == OPEN_READ || mode == OPEN_READWRITE) 58 if (!gus_pnp_flag) 59 { 60 gus_midi_control |= MIDI_ENABLE_RCV; 61 input_opened = 1; 62 } 63 outb((gus_midi_control), u_MidiControl); /* Enable */ 64 65 midi_busy = 1; 66 qlen = qhead = qtail = output_used = 0; 67 midi_input_intr = input; 68 69 return 0; 70} 71 72static int dump_to_midi(unsigned char midi_byte) 73{ 74 unsigned long flags; 75 int ok = 0; 76 77 output_used = 1; 78 79 spin_lock_irqsave(&gus_lock, flags); 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 spin_unlock_irqrestore(&gus_lock,flags); 96 return ok; 97} 98 99static 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 109static 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 spin_lock_irqsave(&gus_lock, flags); 117 118 while (qlen && dump_to_midi(tmp_queue[qhead])) 119 { 120 qlen--; 121 qhead++; 122 } 123 spin_unlock_irqrestore(&gus_lock,flags); 124 125 /* 126 * Output the byte if the local queue is empty. 127 */ 128 129 if (!qlen) 130 if (dump_to_midi(midi_byte)) 131 return 1; /* 132 * OK 133 */ 134 135 /* 136 * Put to the local queue 137 */ 138 139 if (qlen >= 256) 140 return 0; /* 141 * Local queue full 142 */ 143 spin_lock_irqsave(&gus_lock, flags); 144 145 tmp_queue[qtail] = midi_byte; 146 qlen++; 147 qtail++; 148 149 spin_unlock_irqrestore(&gus_lock,flags); 150 return 1; 151} 152 153static int gus_midi_start_read(int dev) 154{ 155 return 0; 156} 157 158static int gus_midi_end_read(int dev) 159{ 160 return 0; 161} 162 163static void gus_midi_kick(int dev) 164{ 165} 166 167static int gus_midi_buffer_status(int dev) 168{ 169 unsigned long flags; 170 171 if (!output_used) 172 return 0; 173 174 spin_lock_irqsave(&gus_lock, flags); 175 176 if (qlen && dump_to_midi(tmp_queue[qhead])) 177 { 178 qlen--; 179 qhead++; 180 } 181 spin_unlock_irqrestore(&gus_lock,flags); 182 return (qlen > 0) || !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY); 183} 184 185#define MIDI_SYNTH_NAME "Gravis Ultrasound Midi" 186#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT 187#include "midi_synth.h" 188 189static struct midi_operations gus_midi_operations = 190{ 191 .owner = THIS_MODULE, 192 .info = {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS}, 193 .converter = &std_midi_synth, 194 .in_info = {0}, 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, 202}; 203 204void __init gus_midi_init(struct address_info *hw_config) 205{ 206 int dev = sound_alloc_mididev(); 207 208 if (dev == -1) 209 { 210 printk(KERN_INFO "gus_midi: Too many midi devices detected\n"); 211 return; 212 } 213 outb((MIDI_RESET), u_MidiControl); 214 215 std_midi_synth.midi_dev = my_dev = dev; 216 hw_config->slots[2] = dev; 217 midi_devs[dev] = &gus_midi_operations; 218 sequencer_init(); 219 return; 220} 221 222void gus_midi_interrupt(int dummy) 223{ 224 volatile unsigned char stat, data; 225 int timeout = 10; 226 227 spin_lock(&gus_lock); 228 229 while (timeout-- > 0 && (stat = GUS_MIDI_STATUS()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY)) 230 { 231 if (stat & MIDI_RCV_FULL) 232 { 233 data = inb(u_MidiData); 234 if (input_opened) 235 midi_input_intr(my_dev, data); 236 } 237 if (stat & MIDI_XMIT_EMPTY) 238 { 239 while (qlen && dump_to_midi(tmp_queue[qhead])) 240 { 241 qlen--; 242 qhead++; 243 } 244 if (!qlen) 245 { 246 /* 247 * Disable Midi output interrupts, since no data in the buffer 248 */ 249 gus_midi_control &= ~MIDI_ENABLE_XMIT; 250 outb((gus_midi_control), u_MidiControl); 251 outb((gus_midi_control), u_MidiControl); 252 } 253 } 254 } 255 spin_unlock(&gus_lock); 256}