4 * Device file manager for /dev/midi#
6 * Copyright by Hannu Savolainen 1993
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.
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
30 #include <i386/isa/sound/sound_config.h>
33 #if defined(CONFIG_MIDI)
35 #include <sys/select.h>
38 * Don't make MAX_QUEUE_SIZE larger than 4000
41 #define MAX_QUEUE_SIZE 4000
43 MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait);
46 drain_midi_queue(int dev);
48 static int *midi_sleeper[MAX_MIDI_DEV] = {NULL};
49 static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] = { {0}};
50 static int *input_sleeper[MAX_MIDI_DEV] = {NULL};
51 static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] = { {0}};
55 u_char queue[MAX_QUEUE_SIZE];
59 int prech_timeout; /* Timeout before the first ch */
62 static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
63 static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
64 static struct midi_parms parms[MAX_MIDI_DEV];
66 static void midi_poll(void *dummy);
68 static volatile int open_devs = 0;
70 #define DATA_AVAIL(q) (q->len)
71 #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
73 #define QUEUE_BYTE(q, data) \
74 if (SPACE_AVAIL(q)) { \
77 q->queue[q->tail] = (data); \
78 q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
82 #define REMOVE_BYTE(q, data) \
83 if (DATA_AVAIL(q)) { \
86 data = q->queue[q->head]; \
87 q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
92 drain_midi_queue(int dev)
96 * Give the Midi driver time to drain its output queues
99 if (midi_devs[dev]->buffer_status != NULL)
100 while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) &&
101 midi_devs[dev]->buffer_status(dev)) {
104 midi_sleeper[dev] = &chn;
105 DO_SLEEP(chn, midi_sleep_flag[dev], hz / 10);
111 midi_input_intr(int dev, u_char data)
113 if (midi_in_buf[dev] == NULL)
116 if (data == 0xfe) /* Active sensing */
119 if (SPACE_AVAIL(midi_in_buf[dev])) {
120 QUEUE_BYTE(midi_in_buf[dev], data);
121 if ((input_sleep_flag[dev].mode & WK_SLEEP)) {
122 input_sleep_flag[dev].mode = WK_WAKEUP;
123 wakeup(input_sleeper[dev]);
129 midi_output_intr(int dev)
137 midi_poll(void *dummy)
144 for (dev = 0; dev < num_midis; dev++)
145 if (midi_out_buf[dev] != NULL) {
146 while (DATA_AVAIL(midi_out_buf[dev]) &&
147 midi_devs[dev]->putc(dev,
148 midi_out_buf[dev]->queue[midi_out_buf[dev]->head])) {
149 midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
150 midi_out_buf[dev]->len--;
153 if (DATA_AVAIL(midi_out_buf[dev]) < 100 &&
154 (midi_sleep_flag[dev].mode & WK_SLEEP)) {
155 midi_sleep_flag[dev].mode = WK_WAKEUP;
156 wakeup(midi_sleeper[dev]);
159 timeout( midi_poll, 0, 1);; /* Come back later */
165 MIDIbuf_open(int dev, struct fileinfo * file)
170 mode = file->mode & O_ACCMODE;
172 if (num_midis > MAX_MIDI_DEV) {
173 printf("Sound: FATAL ERROR: Too many midi interfaces\n");
174 num_midis = MAX_MIDI_DEV;
176 if (dev < 0 || dev >= num_midis) {
177 printf("Sound: Nonexistent MIDI interface %d\n", dev);
181 * Interrupts disabled. Be careful
184 if ((err = midi_devs[dev]->open(dev, mode,
185 midi_input_intr, midi_output_intr)) < 0) {
188 parms[dev].prech_timeout = 0;
190 midi_in_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK);
192 if (midi_in_buf[dev] == NULL) {
193 printf("midi: Can't allocate buffer\n");
194 midi_devs[dev]->close(dev);
197 midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
199 midi_out_buf[dev] = (struct midi_buf *) malloc(sizeof(struct midi_buf), M_TEMP, M_WAITOK);
201 if (midi_out_buf[dev] == NULL) {
202 printf("midi: Can't allocate buffer\n");
203 midi_devs[dev]->close(dev);
204 free(midi_in_buf[dev], M_TEMP);
205 midi_in_buf[dev] = NULL;
208 midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
212 midi_sleep_flag[dev].aborting = 0;
213 midi_sleep_flag[dev].mode = WK_NONE;
216 input_sleep_flag[dev].aborting = 0;
217 input_sleep_flag[dev].mode = WK_NONE;
220 if (open_devs < 2) { /* This was first open */
224 timeout( midi_poll, 0, 1);; /* Start polling */
230 MIDIbuf_release(int dev, struct fileinfo * file)
236 mode = file->mode & O_ACCMODE;
238 if (dev < 0 || dev >= num_midis)
244 * Wait until the queue is empty
247 if (mode != OPEN_READ) {
248 midi_devs[dev]->putc(dev, 0xfe); /* Active sensing to
249 * shut the devices */
251 while (!(PROCESS_ABORTING (midi_sleep_flag[dev])) &&
252 DATA_AVAIL(midi_out_buf[dev])) {
254 midi_sleeper[dev] = &chn;
255 DO_SLEEP(chn, midi_sleep_flag[dev], 0);
259 drain_midi_queue(dev); /* Ensure the output queues are empty */
263 midi_devs[dev]->close(dev);
265 free(midi_in_buf[dev], M_TEMP);
266 free(midi_out_buf[dev], M_TEMP);
267 midi_in_buf[dev] = NULL;
268 midi_out_buf[dev] = NULL;
275 MIDIbuf_write(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
291 n = SPACE_AVAIL(midi_out_buf[dev]);
293 if (n == 0) { /* No space just now. We have to sleep */
298 midi_sleeper[dev] = &chn;
299 DO_SLEEP(chn, midi_sleep_flag[dev], 0);
302 if (PROCESS_ABORTING(midi_sleep_flag[dev])) {
306 n = SPACE_AVAIL(midi_out_buf[dev]);
311 for (i = 0; i < n; i++) {
313 if (uiomove((char *) &tmp_data, 1, buf)) {
314 printf("sb: Bad copyin()!\n");
316 QUEUE_BYTE(midi_out_buf[dev], tmp_data);
328 MIDIbuf_read(int dev, struct fileinfo * file, snd_rw_buf * buf, int count)
338 if (!DATA_AVAIL(midi_in_buf[dev])) { /* No data yet, wait */
344 input_sleeper[dev] = &chn;
345 DO_SLEEP(chn, input_sleep_flag[dev],
346 parms[dev].prech_timeout);
349 if (PROCESS_ABORTING(input_sleep_flag[dev]))
350 c = -(EINTR); /* The user is getting restless */
352 if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) { /* Got some bytes */
353 n = DATA_AVAIL(midi_in_buf[dev]);
359 REMOVE_BYTE(midi_in_buf[dev], tmp_data);
361 if (uiomove((char *) &tmp_data, 1, buf)) {
362 printf("sb: Bad copyout()!\n");
373 MIDIbuf_ioctl(int dev, struct fileinfo * file, u_int cmd, ioctl_arg arg)
379 if (((cmd >> 8) & 0xff) == 'C') {
380 if (midi_devs[dev]->coproc) /* Coprocessor ioctl */
381 return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
383 printf("/dev/midi%d: No coprocessor for this device\n", dev);
389 case SNDCTL_MIDI_PRETIME:
390 val = (int) (*(int *) arg);
394 val = (hz * val) / 10;
395 parms[dev].prech_timeout = val;
396 return *(int *) arg = val;
400 return midi_devs[dev]->ioctl(dev, cmd, arg);
406 MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait)
412 if (events & (POLLIN | POLLRDNORM))
413 if (!DATA_AVAIL (midi_in_buf[dev]))
414 selrecord(wait, &selinfo[dev]);
416 revents |= events & (POLLIN | POLLRDNORM);
418 if (events & (POLLOUT | POLLWRNORM))
419 if (SPACE_AVAIL (midi_out_buf[dev]))
420 selrecord(wait, &selinfo[dev]);
422 revents |= events & (POLLOUT | POLLWRNORM);
427 #endif /* ALLOW_SELECT */