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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * sound/sb_dsp.c
  3.  *
  4.  * The low level driver for the Sound Blaster DS chips.
  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. #include <linux/spinlock.h>
  14. #include "sound_config.h"
  15. #include "sb.h"
  16. #undef SB_TEST_IRQ
  17. /*
  18.  * The DSP channel can be used either for input or output. Variable
  19.  * 'sb_irq_mode' will be set when the program calls read or write first time
  20.  * after open. Current version doesn't support mode changes without closing
  21.  * and reopening the device. Support for this feature may be implemented in a
  22.  * future version of this driver.
  23.  */
  24. static int sb_midi_open(int dev, int mode,
  25.      void            (*input) (int dev, unsigned char data),
  26.      void            (*output) (int dev)
  27. )
  28. {
  29. sb_devc *devc = midi_devs[dev]->devc;
  30. unsigned long flags;
  31. if (devc == NULL)
  32. return -ENXIO;
  33. spin_lock_irqsave(&devc->lock, flags);
  34. if (devc->opened)
  35. {
  36. spin_unlock_irqrestore(&devc->lock, flags);
  37. return -EBUSY;
  38. }
  39. devc->opened = 1;
  40. spin_unlock_irqrestore(&devc->lock, flags);
  41. devc->irq_mode = IMODE_MIDI;
  42. devc->midi_broken = 0;
  43. sb_dsp_reset(devc);
  44. if (!sb_dsp_command(devc, 0x35)) /* Start MIDI UART mode */
  45. {
  46.   devc->opened = 0;
  47.   return -EIO;
  48. }
  49. devc->intr_active = 1;
  50. if (mode & OPEN_READ)
  51. {
  52. devc->input_opened = 1;
  53. devc->midi_input_intr = input;
  54. }
  55. return 0;
  56. }
  57. static void sb_midi_close(int dev)
  58. {
  59. sb_devc *devc = midi_devs[dev]->devc;
  60. unsigned long flags;
  61. if (devc == NULL)
  62. return;
  63. spin_lock_irqsave(&devc->lock, flags);
  64. sb_dsp_reset(devc);
  65. devc->intr_active = 0;
  66. devc->input_opened = 0;
  67. devc->opened = 0;
  68. spin_unlock_irqrestore(&devc->lock, flags);
  69. }
  70. static int sb_midi_out(int dev, unsigned char midi_byte)
  71. {
  72. sb_devc *devc = midi_devs[dev]->devc;
  73. if (devc == NULL)
  74. return 1;
  75. if (devc->midi_broken)
  76. return 1;
  77. if (!sb_dsp_command(devc, midi_byte))
  78. {
  79. devc->midi_broken = 1;
  80. return 1;
  81. }
  82. return 1;
  83. }
  84. static int sb_midi_start_read(int dev)
  85. {
  86. return 0;
  87. }
  88. static int sb_midi_end_read(int dev)
  89. {
  90. sb_devc *devc = midi_devs[dev]->devc;
  91. if (devc == NULL)
  92. return -ENXIO;
  93. sb_dsp_reset(devc);
  94. devc->intr_active = 0;
  95. return 0;
  96. }
  97. static int sb_midi_ioctl(int dev, unsigned cmd, caddr_t arg)
  98. {
  99.         return -EINVAL;
  100. }
  101. void sb_midi_interrupt(sb_devc * devc)
  102. {
  103. unsigned long   flags;
  104. unsigned char   data;
  105. if (devc == NULL)
  106. return;
  107. spin_lock_irqsave(&devc->lock, flags);
  108. data = inb(DSP_READ);
  109. if (devc->input_opened)
  110. devc->midi_input_intr(devc->my_mididev, data);
  111. spin_unlock_irqrestore(&devc->lock, flags);
  112. }
  113. #define MIDI_SYNTH_NAME "Sound Blaster Midi"
  114. #define MIDI_SYNTH_CAPS 0
  115. #include "midi_synth.h"
  116. static struct midi_operations sb_midi_operations =
  117. {
  118. owner: THIS_MODULE,
  119. info: {"Sound Blaster", 0, 0, SNDCARD_SB},
  120. converter: &std_midi_synth,
  121. in_info: {0},
  122. open: sb_midi_open,
  123. close: sb_midi_close,
  124. ioctl: sb_midi_ioctl,
  125. outputc: sb_midi_out,
  126. start_read: sb_midi_start_read,
  127. end_read: sb_midi_end_read,
  128. };
  129. void sb_dsp_midi_init(sb_devc * devc, struct module *owner)
  130. {
  131. int dev;
  132. if (devc->model < 2) /* No MIDI support for SB 1.x */
  133. return;
  134. dev = sound_alloc_mididev();
  135. if (dev == -1)
  136. {
  137. printk(KERN_ERR "sb_midi: too many MIDI devices detectedn");
  138. return;
  139. }
  140. std_midi_synth.midi_dev = devc->my_mididev = dev;
  141. midi_devs[dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
  142. if (midi_devs[dev] == NULL)
  143. {
  144. printk(KERN_WARNING "Sound Blaster:  failed to allocate MIDI memory.n");
  145. sound_unload_mididev(dev);
  146.   return;
  147. }
  148. memcpy((char *) midi_devs[dev], (char *) &sb_midi_operations,
  149.        sizeof(struct midi_operations));
  150. if (owner)
  151. midi_devs[dev]->owner = owner;
  152. midi_devs[dev]->devc = devc;
  153. midi_devs[dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
  154. if (midi_devs[dev]->converter == NULL)
  155. {
  156.   printk(KERN_WARNING "Sound Blaster:  failed to allocate MIDI memory.n");
  157.   kfree(midi_devs[dev]);
  158.   sound_unload_mididev(dev);
  159.   return;
  160. }
  161. memcpy((char *) midi_devs[dev]->converter, (char *) &std_midi_synth,
  162.        sizeof(struct synth_operations));
  163. midi_devs[dev]->converter->id = "SBMIDI";
  164. sequencer_init();
  165. }