gus_midi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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