gus_midi.c 4.9 KB

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