diff options
Diffstat (limited to 'sys/i386/isa/sound/uart6850.c')
-rw-r--r-- | sys/i386/isa/sound/uart6850.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/sys/i386/isa/sound/uart6850.c b/sys/i386/isa/sound/uart6850.c new file mode 100644 index 0000000..e978fc7 --- /dev/null +++ b/sys/i386/isa/sound/uart6850.c @@ -0,0 +1,296 @@ +/* + * sound/uart6850.c + * + * Copyright by Hannu Savolainen 1993 + * + * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: added 6850 support, used + * with COVOX SoundMaster II and custom cards. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <i386/isa/sound/sound_config.h> + +#if NSND > 0 + +#if 1 +/* #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) */ + +#define DATAPORT (uart6850_base) /* * * Midi6850 Data I/O Port on IBM */ +#define COMDPORT (uart6850_base+1) /* * * Midi6850 Command Port on IBM */ +#define STATPORT (uart6850_base+1) /* * * Midi6850 Status Port on IBM */ + +#define uart6850_status() inb( STATPORT) +#define input_avail() (uart6850_status()&INPUT_AVAIL) +#define output_ready() (uart6850_status()&OUTPUT_READY) +#define uart6850_cmd(cmd) outb( COMDPORT, cmd) +#define uart6850_read() inb( DATAPORT) +#define uart6850_write(byte) outb( DATAPORT, byte) + +#define OUTPUT_READY 0x02 /* * * Mask for Data Read Ready Bit */ +#define INPUT_AVAIL 0x01 /* * * Mask for Data Send Ready Bit */ + +#define UART_RESET 0x95 /* * * 6850 Total Reset Command */ +#define UART_MODE_ON 0x03 /* * * 6850 Send/Receive UART Mode */ + +static int uart6850_opened = 0; +static int uart6850_base = 0x330; +static int uart6850_irq; +static int uart6850_detected = 0; +static int my_dev; + +static int reset_uart6850(void); +static void (*midi_input_intr) (int dev, u_char data); +static void poll_uart6850(void *dummy); + + +static sound_os_info *uart6850_osp; + +static void +uart6850_input_loop(void) +{ + int count; + + count = 10; + + while (count) /* Not timed out */ + if (input_avail()) { + u_char c = uart6850_read(); + + count = 100; + + if (uart6850_opened & OPEN_READ) + midi_input_intr(my_dev, c); + } else + while (!input_avail() && count) + count--; +} + +void +m6850intr(int irq) +{ + if (input_avail()) + uart6850_input_loop(); +} + +/* + * It looks like there is no input interrupts in the UART mode. Let's try + * polling. + */ + +static void +poll_uart6850(void * dummy) +{ + u_long flags; + + if (!(uart6850_opened & OPEN_READ)) + return; /* Device has been closed */ + + flags = splhigh(); + + if (input_avail()) + uart6850_input_loop(); + + + timeout( poll_uart6850, 0, 1); /* Come back later */ + + splx(flags); +} + +static int +uart6850_open(int dev, int mode, + void (*input) (int dev, u_char data), + void (*output) (int dev) +) +{ + if (uart6850_opened) { + printf("Midi6850: Midi busy\n"); + return -(EBUSY); + } + uart6850_cmd(UART_RESET); + + uart6850_input_loop(); + + midi_input_intr = input; + uart6850_opened = mode; + poll_uart6850(0); /* Enable input polling */ + + return 0; +} + +static void +uart6850_close(int dev) +{ + uart6850_cmd(UART_MODE_ON); + + uart6850_opened = 0; +} + +static int +uart6850_out(int dev, u_char midi_byte) +{ + int timeout; + u_long flags; + + /* + * Test for input since pending input seems to block the output. + */ + + flags = splhigh(); + + if (input_avail()) + uart6850_input_loop(); + + splx(flags); + + /* + * Sometimes it takes about 13000 loops before the output becomes + * ready (After reset). Normally it takes just about 10 loops. + */ + + for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* Wait */ + + if (!output_ready()) { + printf("Midi6850: Timeout\n"); + return 0; + } + uart6850_write(midi_byte); + return 1; +} + +static int +uart6850_command(int dev, u_char *midi_byte) +{ + return 1; +} + +static int +uart6850_start_read(int dev) +{ + return 0; +} + +static int +uart6850_end_read(int dev) +{ + return 0; +} + +static int +uart6850_ioctl(int dev, u_int cmd, ioctl_arg arg) +{ + return -(EINVAL); +} + +static void +uart6850_kick(int dev) +{ +} + +static int +uart6850_buffer_status(int dev) +{ + return 0; /* No data in buffers */ +} + +#define MIDI_SYNTH_NAME "6850 UART Midi" +#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT +#include <i386/isa/sound/midi_synth.h> + +static struct midi_operations uart6850_operations = +{ + {"6850 UART", 0, 0, SNDCARD_UART6850}, + &std_midi_synth, + {0}, + uart6850_open, + uart6850_close, + uart6850_ioctl, + uart6850_out, + uart6850_start_read, + uart6850_end_read, + uart6850_kick, + uart6850_command, + uart6850_buffer_status +}; + + +void +attach_uart6850(struct address_info * hw_config) +{ + int ok, timeout; + u_long flags; + + if (num_midis >= MAX_MIDI_DEV) { + printf("Sound: Too many midi devices detected\n"); + return ; + } + uart6850_base = hw_config->io_base; + uart6850_osp = hw_config->osp; + uart6850_irq = hw_config->irq; + + if (!uart6850_detected) + return ; + + flags = splhigh(); + + for (timeout = 30000; timeout < 0 && !output_ready(); timeout--); /* Wait */ + uart6850_cmd(UART_MODE_ON); + + ok = 1; + + splx(flags); + + conf_printf("6850 Midi Interface", hw_config); + + std_midi_synth.midi_dev = my_dev = num_midis; + midi_devs[num_midis++] = &uart6850_operations; + return ; +} + +static int +reset_uart6850(void) +{ + uart6850_read(); + return 1; /* OK */ +} + + +int +probe_uart6850(struct address_info * hw_config) +{ + int ok = 0; + + uart6850_osp = hw_config->osp; + uart6850_base = hw_config->io_base; + uart6850_irq = hw_config->irq; + + if (snd_set_irq_handler(uart6850_irq, m6850intr, uart6850_osp) < 0) + return 0; + + ok = reset_uart6850(); + + uart6850_detected = ok; + return ok; +} + +#endif +#endif |