]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/isa/sound/sb_midi.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / sys / i386 / isa / sound / sb_midi.c
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 <i386/isa/sound/sound_config.h>
31
32 #if (NSND > 0) && defined(CONFIG_SB) && defined(CONFIG_MIDI)
33
34 #include <i386/isa/sound/sbcard.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 extern int      sb_dsp_ok;      /* Set to 1 atfer successful initialization */
46 extern int      sbc_base;
47
48 extern int      sb_midi_mode;
49 extern int      sb_midi_busy;   /* 1 if the process has output to MIDI */
50 extern int      sb_dsp_busy;
51 extern int      sb_dsp_highspeed;
52
53 extern volatile int sb_irq_mode;
54 extern int      sb_duplex_midi;
55 extern int      sb_intr_active;
56 static int      input_opened = 0;
57 static int      my_dev;
58
59 extern sound_os_info *sb_osp;
60
61 static void            (*midi_input_intr) (int dev, u_char data);
62
63 static int
64 sb_midi_open(int dev, int mode, void (*input) (int dev, u_char data),
65              void (*output) (int dev))
66 {
67     int             ret;
68
69     if (!sb_dsp_ok) {
70         printf("SB Error: MIDI hardware not installed\n");
71         return -(ENXIO);
72     }
73     if (sb_midi_busy)
74         return -(EBUSY);
75
76     if (mode != OPEN_WRITE && !sb_duplex_midi) {
77         if (num_midis == 1)
78             printf("SoundBlaster: Midi input not currently supported\n");
79         return -(EPERM);
80     }
81     sb_midi_mode = NORMAL_MIDI;
82     if (mode != OPEN_WRITE) {
83         if (sb_dsp_busy || sb_intr_active)
84             return -(EBUSY);
85         sb_midi_mode = UART_MIDI;
86     }
87     if (sb_dsp_highspeed) {
88         printf("SB Error: Midi output not possible during stereo or high speed audio\n");
89         return -(EBUSY);
90     }
91     if (sb_midi_mode == UART_MIDI) {
92         sb_irq_mode = IMODE_MIDI;
93
94         sb_reset_dsp();
95
96         if (!sb_dsp_command(0x35))
97             return -(EIO);      /* Enter the UART mode */
98         sb_intr_active = 1;
99
100         input_opened = 1;
101         midi_input_intr = input;
102     }
103     sb_midi_busy = 1;
104
105     return 0;
106 }
107
108 static void
109 sb_midi_close(int dev)
110 {
111     if (sb_midi_mode == UART_MIDI) {
112         sb_reset_dsp(); /* The only way to kill the UART mode */
113     }
114     sb_intr_active = 0;
115     sb_midi_busy = 0;
116     input_opened = 0;
117 }
118
119 static int
120 sb_midi_out(int dev, u_char midi_byte)
121 {
122     u_long   flags;
123
124     if (sb_midi_mode == NORMAL_MIDI) {
125         flags = splhigh();
126         if (sb_dsp_command(0x38))
127             sb_dsp_command(midi_byte);
128         else
129             printf("SB Error: Unable to send a MIDI byte\n");
130         splx(flags);
131     } else
132         sb_dsp_command(midi_byte);      /* UART write */
133
134     return 1;
135 }
136
137 static int
138 sb_midi_start_read(int dev)
139 {
140     if (sb_midi_mode != UART_MIDI) {
141         printf("SoundBlaster: MIDI input not implemented.\n");
142         return -(EPERM);
143     }
144     return 0;
145 }
146
147 static int
148 sb_midi_end_read(int dev)
149 {
150     if (sb_midi_mode == UART_MIDI) {
151         sb_reset_dsp();
152         sb_intr_active = 0;
153     }
154     return 0;
155 }
156
157 static int
158 sb_midi_ioctl(int dev, u_int cmd, ioctl_arg arg)
159 {
160     return -(EPERM);
161 }
162
163 void
164 sb_midi_interrupt(int dummy)
165 {
166     u_long   flags;
167     u_char   data;
168
169     flags = splhigh();
170
171     data = inb(DSP_READ);
172     if (input_opened)
173         midi_input_intr(my_dev, data);
174
175     splx(flags);
176 }
177
178 #define MIDI_SYNTH_NAME "SoundBlaster Midi"
179 #define MIDI_SYNTH_CAPS 0
180 #include <i386/isa/sound/midi_synth.h>
181
182 static struct midi_operations sb_midi_operations =
183 {
184         {"SoundBlaster", 0, 0, SNDCARD_SB},
185         &std_midi_synth,
186         {0},
187         sb_midi_open,
188         sb_midi_close,
189         sb_midi_ioctl,
190         sb_midi_out,
191         sb_midi_start_read,
192         sb_midi_end_read,
193         NULL,                   /* Kick */
194         NULL,                   /* command */
195         NULL,                   /* buffer_status */
196         NULL
197 };
198
199 void
200 sb_midi_init(int model)
201 {
202     if (num_midis >= MAX_MIDI_DEV) {
203         printf("Sound: Too many midi devices detected\n");
204         return;
205     }
206     std_midi_synth.midi_dev = num_midis;
207     my_dev = num_midis;
208     midi_devs[num_midis++] = &sb_midi_operations;
209 }
210
211 #endif