1 /* 2 * sound/sb_dsp.c 3 * 4 * The low level driver for the SoundBlaster DS chips. 5 * 6 * Copyright by Hannu Savolainen 1993 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 2. 12 * Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29
30 #include "sound_config.h"
31
32 #ifdefined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI)
33
34 #include "sb.h"
35 #undef SB_TEST_IRQ
36
37 /* 38 * The DSP channel can be used either for input or output. Variable 39 * 'sb_irq_mode' will be set when the program calls read or write first time 40 * after open. Current version doesn't support mode changes without closing 41 * and reopening the device. Support for this feature may be implemented in a 42 * future version of this driver. 43 */ 44
45 externintsb_dsp_ok; /* Set to 1 after successful initialization */ 46
47 externintsb_midi_mode;
48 externintsb_midi_busy; /* 1 if the process has output to MIDI */ 49 externintsb_dsp_busy;
50 externintsb_dsp_highspeed;
51
52 externvolatileintsb_irq_mode; /* IMODE_INPUT, IMODE_OUTPUT 53 * or IMODE_NONE */ 54 externintsb_dsp_model; /* 1=SB, 2=SB Pro */ 55 externintsb_duplex_midi;
56 externintsb_intr_active;
57
58 staticint 59 sb_midi_open (intdev, intmode,
/* */ 60 void (*input) (intdev, unsignedchardata),
61 void (*output) (intdev)
62 )
63 { 64 intret;
65
66 if (!sb_dsp_ok)
67 { 68 printk ("SB Error: MIDI hardware not installed\n");
69 returnRET_ERROR (ENXIO);
70 } 71
72 if (mode != OPEN_WRITE && !sb_duplex_midi)
73 { 74 if (num_midis == 1)
75 printk ("SoundBlaster: Midi input not currently supported\n");
76 returnRET_ERROR (EPERM);
77 } 78
79 sb_midi_mode = NORMAL_MIDI;
80 if (mode != OPEN_WRITE)
81 { 82 if (sb_dsp_busy || sb_intr_active)
83 returnRET_ERROR (EBUSY);
84 sb_midi_mode = UART_MIDI;
85 } 86
87 if (sb_dsp_highspeed)
88 { 89 printk ("SB Error: Midi output not possible during stereo or high speed audio\n");
90 returnRET_ERROR (EBUSY);
91 } 92
93 if (sb_midi_mode == UART_MIDI)
94 { 95 sb_irq_mode = IMODE_MIDI;
96
97 sb_reset_dsp ();
98
99 if (!sb_dsp_command (0x35))
100 returnRET_ERROR (EIO); /* Enter the UART mode */ 101 sb_intr_active = 1;
102
103 if ((ret = sb_get_irq ()) < 0)
104 { 105 sb_reset_dsp ();
106 return 0; /* IRQ not free */ 107 } 108 } 109
110 sb_midi_busy = 1;
111
112 return 0;
113 } 114
115 staticvoid 116 sb_midi_close (intdev)
/* */ 117 { 118 if (sb_midi_mode == UART_MIDI)
119 { 120 sb_reset_dsp (); /* The only way to kill the UART mode */ 121 sb_free_irq ();
122 } 123 sb_intr_active = 0;
124 sb_midi_busy = 0;
125 } 126
127 staticint 128 sb_midi_out (intdev, unsignedcharmidi_byte)
/* */ 129 { 130 unsignedlongflags;
131
132 sb_midi_busy = 1; /* Kill all notes after close */ 133
134 if (sb_midi_mode == NORMAL_MIDI)
135 { 136 DISABLE_INTR (flags);
137 if (sb_dsp_command (0x38))
138 sb_dsp_command (midi_byte);
139 else 140 printk ("SB Error: Unable to send a MIDI byte\n");
141 RESTORE_INTR (flags);
142 } 143 else 144 sb_dsp_command (midi_byte); /* UART write */ 145
146 return 1;
147 } 148
149 staticint 150 sb_midi_start_read (intdev)
/* */ 151 { 152 if (sb_midi_mode != UART_MIDI)
153 { 154 printk ("SoundBlaster: MIDI input not implemented.\n");
155 returnRET_ERROR (EPERM);
156 } 157 return 0;
158 } 159
160 staticint 161 sb_midi_end_read (intdev)
/* */ 162 { 163 if (sb_midi_mode == UART_MIDI)
164 { 165 sb_reset_dsp ();
166 sb_intr_active = 0;
167 } 168 return 0;
169 } 170
171 staticint 172 sb_midi_ioctl (intdev, unsignedcmd, unsignedarg)
/* */ 173 { 174 returnRET_ERROR (EPERM);
175 } 176
177 staticstructmidi_operationssb_midi_operations =
178 { 179 {"SoundBlaster", 0, 0, SNDCARD_SB},
180 sb_midi_open,
181 sb_midi_close,
182 sb_midi_ioctl,
183 sb_midi_out,
184 sb_midi_start_read,
185 sb_midi_end_read,
186 NULL, /* Kick */ 187 NULL, /* command */ 188 NULL/* buffer_status */ 189 };
190
191 void 192 sb_midi_init(intmodel)
/* */ 193 { 194 midi_devs[num_midis++] = &sb_midi_operations;
195 } 196
197 #endif