/* * sound/maui.c * * The low level driver for Turtle Beach Maui and Tropez. * * Copyright by Hannu Savolainen 1995 * * 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. * */ #define USE_SEQ_MACROS #define USE_SIMPLE_MACROS #include #if defined(CONFIG_MAUI) static int maui_base = 0x330; static volatile int irq_ok = 0; static sound_os_info *maui_osp; #define HOST_DATA_PORT (maui_base + 2) #define HOST_STAT_PORT (maui_base + 3) #define HOST_CTRL_PORT (maui_base + 3) #define STAT_TX_INTR 0x40 #define STAT_TX_AVAIL 0x20 #define STAT_TX_IENA 0x10 #define STAT_RX_INTR 0x04 #define STAT_RX_AVAIL 0x02 #define STAT_RX_IENA 0x01 static int (*orig_load_patch) (int dev, int format, snd_rw_buf * addr, int offs, int count, int pmgr_flag) = NULL; static int maui_read(void) { int timeout; for (timeout = 0; timeout < 1000000; timeout++) if (inb(HOST_STAT_PORT) & STAT_RX_AVAIL) return inb(HOST_DATA_PORT); printf("Maui: Receive timeout\n"); return -1; } static int maui_write(u_char data) { int timeout; for (timeout = 0; timeout < 10000000; timeout++) { if (inb(HOST_STAT_PORT) & STAT_TX_AVAIL) { outb(HOST_DATA_PORT, data); return 1; } } printf("Maui: Write timeout\n"); return 0; } void mauiintr(int irq) { irq_ok = 1; } int maui_load_patch(int dev, int format, snd_rw_buf * addr, int offs, int count, int pmgr_flag) { struct sysex_info header; u_long left, src_offs; int hdr_size = (u_long) &header.data[0] - (u_long) &header; int i; if (format == SYSEX_PATCH) /* Handled by midi_synth.c */ return orig_load_patch(dev, format, addr, offs, count, pmgr_flag); if (format != MAUI_PATCH) { printf("Maui: Unknown patch format\n"); } if (count < hdr_size) { printf("Maui error: Patch header too short\n"); return -(EINVAL); } count -= hdr_size; /* * Copy the header from user space but ignore the first bytes which * have been transferred already. */ if (uiomove(&((char *) &header)[offs], hdr_size - offs, addr)) { printf("sb: Bad copyin()!\n"); }; if (count < header.len) { printf("Maui warning: Host command record too short (%d<%d)\n", count, (int) header.len); header.len = count; } left = header.len; src_offs = 0; for (i = 0; i < left; i++) { u_char data; uiomove((char *) &(data), 1, addr); if (i == 0 && !(data & 0x80)) return -(EINVAL); if (maui_write(data) == -1) return -(EIO); } if ((i = maui_read()) != 0x80) { if (i != -1) printf("Maui: Error status %02x\n", i); return -(EIO); } return 0; } int probe_maui(struct address_info * hw_config) { int i; int tmp1, tmp2; maui_base = hw_config->io_base; maui_osp = hw_config->osp; if (snd_set_irq_handler(hw_config->irq, mauiintr, maui_osp) < 0) return 0; if (!maui_write(0xCF)) {/* Report hardware version */ /* snd_release_irq(hw_config->irq); */ return 0; } if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) { /* snd_release_irq(hw_config->irq); */ return 0; } printf("WaveFront hardware version %d.%d\n", tmp1, tmp2); if (!maui_write(0x9F)) /* Report firmware version */ return 0; if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) return 0; printf("WaveFront firmware version %d.%d\n", tmp1, tmp2); if (!maui_write(0x85)) /* Report free DRAM */ return 0; tmp1 = 0; for (i = 0; i < 4; i++) { tmp1 |= maui_read() << (7 * i); } printf("Available DRAM %dk\n", tmp1 / 1024); for (i = 0; i < 1000; i++) if (probe_mpu401(hw_config)) break; return probe_mpu401(hw_config); } void attach_maui(struct address_info * hw_config) { int this_dev = num_midis; conf_printf("Maui", hw_config); hw_config->irq *= -1; attach_mpu401(hw_config); if (num_midis > this_dev) { /* The MPU401 driver installed itself */ struct synth_operations *synth; /* * Intercept patch loading calls so that they canbe handled * by the Maui driver. */ synth = midi_devs[this_dev]->converter; if (synth != NULL) { orig_load_patch = synth->load_patch; synth->load_patch = &maui_load_patch; } else printf("Maui: Can't install patch loader\n"); } return; } #endif