aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/conf/NOTES24
-rw-r--r--sys/conf/files11
-rw-r--r--sys/dev/sound/isa/emu8000.c1980
-rw-r--r--sys/dev/sound/isa/gusmidi.c537
-rw-r--r--sys/dev/sound/isa/mpu.c805
-rw-r--r--sys/dev/sound/isa/opl.c1885
-rw-r--r--sys/dev/sound/isa/uartsio.c527
-rw-r--r--sys/dev/sound/midi/midi.c1054
-rw-r--r--sys/dev/sound/midi/midi.h334
-rw-r--r--sys/dev/sound/midi/midibuf.c403
-rw-r--r--sys/dev/sound/midi/midibuf.h65
-rw-r--r--sys/dev/sound/midi/midisynth.c532
-rw-r--r--sys/dev/sound/midi/midisynth.h110
-rw-r--r--sys/dev/sound/midi/miditypes.h34
-rw-r--r--sys/dev/sound/midi/sequencer.c2603
-rw-r--r--sys/dev/sound/midi/sequencer.h272
-rw-r--r--sys/dev/sound/midi/timer.c564
-rw-r--r--sys/dev/sound/midi/timer.h80
-rw-r--r--sys/dev/sound/pci/csamidi.c586
19 files changed, 0 insertions, 12406 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index df2eef6804b6..3213eeee2035 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1801,30 +1801,6 @@ hint.pcm.0.irq="10"
hint.pcm.0.drq="1"
hint.pcm.0.flags="0x0"
-#
-# midi: MIDI interfaces and synthesizers
-#
-
-device midi
-
-# For non-pnp sound cards with no bridge drivers:
-hint.midi.0.at="isa"
-hint.midi.0.irq="5"
-hint.midi.0.flags="0x0"
-
-# For serial ports (this example configures port 2):
-# TODO: implement generic tty-midi interface so that we can use
-# other uarts.
-hint.midi.0.at="isa"
-hint.midi.0.port="0x2F8"
-hint.midi.0.irq="3"
-
-#
-# seq: MIDI sequencer
-#
-
-device seq
-
# The bridge drivers for sound cards. These can be separately configured
# for providing services to the likes of new-midi.
# When used with 'device pcm' they also provide pcm sound services.
diff --git a/sys/conf/files b/sys/conf/files
index 0d48a92d164e..a6bc61519182 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -663,33 +663,22 @@ dev/sn/if_sn_pccard.c optional sn card
dev/sn/if_sn_pccard.c optional sn pccard
dev/snp/snp.c optional snp
dev/sound/isa/ad1816.c optional pcm isa
-dev/sound/isa/emu8000.c optional midi isa
dev/sound/isa/es1888.c optional pcm isa
dev/sound/isa/ess.c optional pcm isa
dev/sound/isa/gusc.c optional gusc isa
dev/sound/isa/gusc.c optional pcm isa
-dev/sound/isa/gusmidi.c optional midi isa
-dev/sound/isa/mpu.c optional midi isa
dev/sound/isa/mss.c optional pcm isa
-dev/sound/isa/opl.c optional midi isa
dev/sound/isa/sb16.c optional pcm isa
dev/sound/isa/sb8.c optional pcm isa
dev/sound/isa/sbc.c optional pcm isa
dev/sound/isa/sbc.c optional sbc isa
dev/sound/isa/sndbuf_dma.c optional pcm isa
-dev/sound/isa/uartsio.c optional midi isa
-dev/sound/midi/midi.c optional midi
-dev/sound/midi/midibuf.c optional midi
-dev/sound/midi/midisynth.c optional midi
-dev/sound/midi/sequencer.c optional seq midi
-dev/sound/midi/timer.c optional seq midi
dev/sound/pci/als4000.c optional pcm pci
#dev/sound/pci/au88x0.c optional pcm pci
dev/sound/pci/cmi.c optional pcm pci
dev/sound/pci/cs4281.c optional pcm pci
dev/sound/pci/csa.c optional csa pci
dev/sound/pci/csa.c optional pcm pci
-dev/sound/pci/csamidi.c optional midi csa
dev/sound/pci/csapcm.c optional pcm pci
dev/sound/pci/ds1.c optional pcm pci
dev/sound/pci/emu10k1.c optional pcm pci dependency "emu10k1-alsa%diked.h"
diff --git a/sys/dev/sound/isa/emu8000.c b/sys/dev/sound/isa/emu8000.c
deleted file mode 100644
index 2442e2bc08e7..000000000000
--- a/sys/dev/sound/isa/emu8000.c
+++ /dev/null
@@ -1,1980 +0,0 @@
-/*
- * Low level EMU8000 chip driver for FreeBSD. This handles io against
- * /dev/midi, the midi {in, out}put event queues and the event/message
- * operation to the EMU8000 chip.
- *
- * (C) 1999 Seigo Tanimura
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-
-#include <isa/isavar.h>
-
-static devclass_t midi_devclass;
-
-#ifndef DDB
-#undef DDB
-#define DDB(x)
-#endif /* DDB */
-
-/* These are the specs of EMU8000. */
-#define EMU8K_MAXVOICE 32
-#define EMU8K_MAXINFO 256
-
-#define EMU8K_IDX_DATA0 0
-#define EMU8K_IDX_DATA1 1
-#define EMU8K_IDX_DATA2 1
-#define EMU8K_IDX_DATA3 2
-#define EMU8K_IDX_PTR 2
-
-#define EMU8K_PORT_DATA0 0
-#define EMU8K_PORT_DATA1 0
-#define EMU8K_PORT_DATA2 2
-#define EMU8K_PORT_DATA3 0
-#define EMU8K_PORT_PTR 2
-
-#define EMU8K_DRAM_RAM 0x200000
-#define EMU8K_DRAM_MAX 0xffffe0
-
-/* And some convinient macros. */
-#define EMU8K_DMA_LEFT 0x00
-#define EMU8K_DMA_RIGHT 0x01
-#define EMU8K_DMA_LR 0x01
-#define EMU8K_DMA_READ 0x00
-#define EMU8K_DMA_WRITE 0x02
-#define EMU8K_DMA_RW 0x02
-#define EMU8K_DMA_MASK 0x03
-
-/* The followings are the init array for EMU8000, originally in ADIP. */
-
-/* Set 1 */
-static u_short init1_1[32] =
-{
- 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330,
- 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730,
- 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30,
- 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30,
-};
-
-static u_short init1_2[32] =
-{
- 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330,
- 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730,
- 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30,
- 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30,
-};
-
-static u_short init1_3[32] =
-{
- 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330,
- 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730,
- 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30,
- 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30,
-};
-
-static u_short init1_4[32] =
-{
- 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330,
- 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730,
- 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30,
- 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30,
-};
-
-/* Set 2 */
-
-static u_short init2_1[32] =
-{
- 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
- 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
- 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
- 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
-};
-
-static u_short init2_2[32] =
-{
- 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
- 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
- 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
- 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
-};
-
-static u_short init2_3[32] =
-{
- 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
- 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
- 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
- 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
-};
-
-static u_short init2_4[32] =
-{
- 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
- 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
- 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
- 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
-};
-
-/* Set 3 */
-
-static u_short init3_1[32] =
-{
- 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
- 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
- 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
- 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
-};
-
-static u_short init3_2[32] =
-{
- 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
- 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
- 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
- 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
-};
-
-static u_short init3_3[32] =
-{
- 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
- 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
- 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
- 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
-};
-
-static u_short init3_4[32] =
-{
- 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
- 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
- 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
- 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
-};
-
-/* Set 4 */
-
-static u_short init4_1[32] =
-{
- 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
- 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
- 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
- 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
-};
-
-static u_short init4_2[32] =
-{
- 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
- 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
- 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
- 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
-};
-
-static u_short init4_3[32] =
-{
- 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
- 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
- 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
- 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
-};
-
-static u_short init4_4[32] =
-{
- 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
- 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
- 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
- 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
-};
-
-/* The followings are the register, the channel and the port for the EMU8000 registers. */
-struct _emu_register {
- int reg; /* Register */
- int index; /* Index */
- int port; /* Port */
- int chn; /* Channel */
- int size; /* Size, 0 == word, 1 == double word */
-};
-
-#define EMU8K_CHN_ANY (-1)
-
-static struct _emu_register emu_regs[] =
-{
- /* Reg, Index, Port, Channel, Size */
- { 0, EMU8K_IDX_DATA0, EMU8K_PORT_DATA0, EMU8K_CHN_ANY, 1}, /* CPF */
- { 1, EMU8K_IDX_DATA0, EMU8K_PORT_DATA0, EMU8K_CHN_ANY, 1}, /* PTRX */
- { 2, EMU8K_IDX_DATA0, EMU8K_PORT_DATA0, EMU8K_CHN_ANY, 1}, /* CVCF */
- { 3, EMU8K_IDX_DATA0, EMU8K_PORT_DATA0, EMU8K_CHN_ANY, 1}, /* VTFT */
- { 6, EMU8K_IDX_DATA0, EMU8K_PORT_DATA0, EMU8K_CHN_ANY, 1}, /* PSST */
- { 7, EMU8K_IDX_DATA0, EMU8K_PORT_DATA0, EMU8K_CHN_ANY, 1}, /* CSL */
- { 0, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 1}, /* CCCA */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 9, 1}, /* HWCF4 */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 10, 1}, /* HWCF5 */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 13, 1}, /* HWCF6 */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 20, 1}, /* SMALR */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 21, 1}, /* SMARR */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 22, 1}, /* SMALW */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 23, 1}, /* SMARW */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 26, 0}, /* SMLD */
- { 1, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, 26, 0}, /* SMRD */
- { 1, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, 27, 0}, /* WC */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 29, 0}, /* HWCF1 */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 30, 0}, /* HWCF2 */
- { 1, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, 31, 0}, /* HWCF3 */
- { 2, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 0}, /* INIT1 */
- { 2, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, EMU8K_CHN_ANY, 0}, /* INIT2 */
- { 3, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 0}, /* INIT3 */
- { 3, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, EMU8K_CHN_ANY, 0}, /* INIT4 */
- { 4, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 0}, /* ENVVOL */
- { 5, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 0}, /* DCYSUSV */
- { 6, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 0}, /* ENVVAL */
- { 7, EMU8K_IDX_DATA1, EMU8K_PORT_DATA1, EMU8K_CHN_ANY, 0}, /* DCYSUS */
- { 4, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, EMU8K_CHN_ANY, 0}, /* ATKHLDV */
- { 5, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, EMU8K_CHN_ANY, 0}, /* LFO1VAL */
- { 6, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, EMU8K_CHN_ANY, 0}, /* ATKHLD */
- { 7, EMU8K_IDX_DATA2, EMU8K_PORT_DATA2, EMU8K_CHN_ANY, 0}, /* LFO2VAL */
- { 0, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, EMU8K_CHN_ANY, 0}, /* IP */
- { 1, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, EMU8K_CHN_ANY, 0}, /* IFATN */
- { 2, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, EMU8K_CHN_ANY, 0}, /* PEFE */
- { 3, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, EMU8K_CHN_ANY, 0}, /* FMMOD */
- { 4, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, EMU8K_CHN_ANY, 0}, /* TREMFRQ */
- { 5, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, EMU8K_CHN_ANY, 0}, /* FM2FRQ2 */
- { 7, EMU8K_IDX_DATA3, EMU8K_PORT_DATA3, 0, 0}, /* PROBE */
-};
-
-/* These are the EMU8000 register names. */
-enum {
- EMU8K_CPF = 0,
- EMU8K_PTRX,
- EMU8K_CVCF,
- EMU8K_VTFT,
- EMU8K_PSST,
- EMU8K_CSL,
- EMU8K_CCCA,
- EMU8K_HWCF4,
- EMU8K_HWCF5,
- EMU8K_HWCF6,
- EMU8K_SMALR,
- EMU8K_SMARR,
- EMU8K_SMALW,
- EMU8K_SMARW,
- EMU8K_SMLD,
- EMU8K_SMRD,
- EMU8K_WC,
- EMU8K_HWCF1,
- EMU8K_HWCF2,
- EMU8K_HWCF3,
- EMU8K_INIT1,
- EMU8K_INIT2,
- EMU8K_INIT3,
- EMU8K_INIT4,
- EMU8K_ENVVOL,
- EMU8K_DCYSUSV,
- EMU8K_ENVVAL,
- EMU8K_DCYSUS,
- EMU8K_ATKHLDV,
- EMU8K_LFO1VAL,
- EMU8K_ATKHLD,
- EMU8K_LFO2VAL,
- EMU8K_IP,
- EMU8K_IFATN,
- EMU8K_PEFE,
- EMU8K_FMMOD,
- EMU8K_TREMFRQ,
- EMU8K_FM2FRQ2,
- EMU8K_PROBE,
- EMU8K_REGLAST, /* keep this! */
-};
-#define EMU8K_REGNUM (EMU8K_REGLAST)
-
-/* These are the synthesizer and the midi device information. */
-static struct synth_info emu_synthinfo = {
- "EMU8000 Wavetable Synth",
- 0,
- SYNTH_TYPE_SAMPLE,
- SAMPLE_TYPE_AWE32,
- 0,
- EMU8K_MAXVOICE,
- 0,
- EMU8K_MAXINFO,
- 0,
-};
-
-static struct midi_info emu_midiinfo = {
- "EMU8000 Wavetable Synth",
- 0,
- 0,
- 0,
-};
-
-#if notyet
-/*
- * These functions goes into emusynthdev_op_desc.
- */
-static mdsy_killnote_t emu_killnote;
-static mdsy_setinstr_t emu_setinstr;
-static mdsy_startnote_t emu_startnote;
-static mdsy_reset_t emu_reset;
-static mdsy_hwcontrol_t emu_hwcontrol;
-static mdsy_loadpatch_t emu_loadpatch;
-static mdsy_panning_t emu_panning;
-static mdsy_aftertouch_t emu_aftertouch;
-static mdsy_controller_t emu_controller;
-static mdsy_patchmgr_t emu_patchmgr;
-static mdsy_bender_t emu_bender;
-static mdsy_allocvoice_t emu_allocvoice;
-static mdsy_setupvoice_t emu_setupvoice;
-static mdsy_sendsysex_t emu_sendsysex;
-static mdsy_prefixcmd_t emu_prefixcmd;
-static mdsy_volumemethod_t emu_volumemethod;
-
-/*
- * This is the synthdev_info for an EMU8000 chip.
- */
-static synthdev_info emusynth_op_desc = {
- emu_killnote,
- emu_setinstr,
- emu_startnote,
- emu_reset,
- emu_hwcontrol,
- emu_loadpatch,
- emu_panning,
- emu_aftertouch,
- emu_controller,
- emu_patchmgr,
- emu_bender,
- emu_allocvoice,
- emu_setupvoice,
- emu_sendsysex,
- emu_prefixcmd,
- emu_volumemethod,
-};
-#endif /* notyet */
-
-/*
- * These functions goes into emu_op_desc to get called
- * from sound.c.
- */
-
-static int emu_probe(device_t dev);
-static int emu_attach(device_t dev);
-static int emupnp_attach(device_t dev) __unused;
-
-static d_open_t emu_open;
-static d_close_t emu_close;
-static d_ioctl_t emu_ioctl;
-static midi_callback_t emu_callback;
-
-/* These go to mididev_info. */
-static mdsy_readraw_t emu_readraw;
-static mdsy_writeraw_t emu_writeraw;
-
-/* Here is the parameter structure per a device. */
-struct emu_softc {
- device_t dev; /* device information */
- mididev_info *devinfo; /* midi device information */
-
- struct mtx mtx; /* Mutex to protect a device */
-
- struct resource *io[3]; /* Base of io port */
- int io_rid[3]; /* Io resource ID */
-
- u_int dramsize; /* DRAM size */
- struct synth_info synthinfo; /* Synthesizer information */
-
- int fflags; /* File flags */
-};
-
-typedef struct emu_softc *sc_p;
-
-/* These functions are local. */
-static u_int emu_dramsize(sc_p scp);
-static void emu_allocdmachn(sc_p scp, int chn, int mode);
-static void emu_dmaaddress(sc_p scp, int mode, u_int addr);
-static void emu_waitstream(sc_p scp, int mode);
-static void emu_readblkstream(sc_p scp, int mode, u_short *data, size_t len);
-static void emu_writeblkstream(sc_p scp, int mode, u_short *data, size_t len);
-static void emu_readstream(sc_p scp, int mode, u_short *data);
-static void emu_writestream(sc_p scp, int mode, u_short data);
-static void emu_releasedmachn(sc_p scp, int chn, int mode);
-static void emu_delay(sc_p scp, short n);
-static void emu_readcpf(sc_p scp, int chn, u_int *cp, u_int *f) __unused;
-static void emu_writecpf(sc_p scp, int chn, u_int cp, u_int f);
-static void emu_readptrx(sc_p scp, int chn, u_int *pt, u_int *rs, u_int *auxd) __unused;
-static void emu_writeptrx(sc_p scp, int chn, u_int pt, u_int rs, u_int auxd);
-static void emu_readcvcf(sc_p scp, int chn, u_int *cv, u_int *cf) __unused;
-static void emu_writecvcf(sc_p scp, int chn, u_int cv, u_int cf);
-static void emu_readvtft(sc_p scp, int chn, u_int *vt, u_int *ft) __unused;
-static void emu_writevtft(sc_p scp, int chn, u_int vt, u_int ft);
-static void emu_readpsst(sc_p scp, int chn, u_int *pan, u_int *st) __unused;
-static void emu_writepsst(sc_p scp, int chn, u_int pan, u_int st);
-static void emu_readcsl(sc_p scp, int chn, u_int *cs, u_int *lp) __unused;
-static void emu_writecsl(sc_p scp, int chn, u_int cs, u_int lp);
-static void emu_readccca(sc_p scp, int chn, u_int *q, u_int *dma, u_int *wr, u_int *right, u_int *ca) __unused;
-static void emu_writeccca(sc_p scp, int chn, u_int q, u_int dma, u_int wr, u_int right, u_int ca);
-static void emu_readhwcf4(sc_p scp, u_int *val) __unused;
-static void emu_writehwcf4(sc_p scp, u_int val);
-static void emu_readhwcf5(sc_p scp, u_int *val) __unused;
-static void emu_writehwcf5(sc_p scp, u_int val);
-static void emu_readhwcf6(sc_p scp, u_int *val) __unused;
-static void emu_writehwcf6(sc_p scp, u_int val);
-static void emu_readsmalr(sc_p scp, u_int *mt, u_int *smalr);
-static void emu_writesmalr(sc_p scp, u_int mt, u_int smalr);
-static void emu_readsmarr(sc_p scp, u_int *mt, u_int *smarr);
-static void emu_writesmarr(sc_p scp, u_int mt, u_int smarr);
-static void emu_readsmalw(sc_p scp, u_int *full, u_int *smalw);
-static void emu_writesmalw(sc_p scp, u_int full, u_int smalw);
-static void emu_readsmarw(sc_p scp, u_int *full, u_int *smarw);
-static void emu_writesmarw(sc_p scp, u_int full, u_int smarw);
-static void emu_readsmld(sc_p scp, u_short *smld);
-static void emu_writesmld(sc_p scp, u_short smld);
-static void emu_readsmrd(sc_p scp, u_short *smrd);
-static void emu_writesmrd(sc_p scp, u_short smrd);
-static void emu_readwc(sc_p scp, u_int *wc);
-static void emu_writewc(sc_p scp, u_int wc) __unused;
-static void emu_readhwcf1(sc_p scp, u_int *val);
-static void emu_writehwcf1(sc_p scp, u_int val);
-static void emu_readhwcf2(sc_p scp, u_int *val);
-static void emu_writehwcf2(sc_p scp, u_int val);
-static void emu_readhwcf3(sc_p scp, u_int *val) __unused;
-static void emu_writehwcf3(sc_p scp, u_int val);
-static void emu_readinit1(sc_p scp, int chn, u_int *val) __unused;
-static void emu_writeinit1(sc_p scp, int chn, u_int val);
-static void emu_readinit2(sc_p scp, int chn, u_int *val) __unused;
-static void emu_writeinit2(sc_p scp, int chn, u_int val);
-static void emu_readinit3(sc_p scp, int chn, u_int *val) __unused;
-static void emu_writeinit3(sc_p scp, int chn, u_int val);
-static void emu_readinit4(sc_p scp, int chn, u_int *val) __unused;
-static void emu_writeinit4(sc_p scp, int chn, u_int val);
-static void emu_readenvvol(sc_p scp, int chn, u_int *envvol) __unused;
-static void emu_writeenvvol(sc_p scp, int chn, u_int envvol);
-static void emu_readdcysusv(sc_p scp, int chn, u_int *ph1v, u_int *susv, u_int *off, u_int *dcyv) __unused;
-static void emu_writedcysusv(sc_p scp, int chn, u_int ph1v, u_int susv, u_int off, u_int dcyv);
-static void emu_readenvval(sc_p scp, int chn, u_int *envval) __unused;
-static void emu_writeenvval(sc_p scp, int chn, u_int envval);
-static void emu_readdcysus(sc_p scp, int chn, u_int *ph1, u_int *sus, u_int *dcy) __unused;
-static void emu_writedcysus(sc_p scp, int chn, u_int ph1, u_int sus, u_int dcy);
-static void emu_readatkhldv(sc_p scp, int chn, u_int *atkhldv) __unused;
-static void emu_writeatkhldv(sc_p scp, int chn, u_int atkhldv);
-static void emu_readlfo1val(sc_p scp, int chn, u_int *lfo1val) __unused;
-static void emu_writelfo1val(sc_p scp, int chn, u_int lfo1val);
-static void emu_readatkhld(sc_p scp, int chn, u_int *atkhld) __unused;
-static void emu_writeatkhld(sc_p scp, int chn, u_int atkhld);
-static void emu_readlfo2val(sc_p scp, int chn, u_int *lfo2val) __unused;
-static void emu_writelfo2val(sc_p scp, int chn, u_int lfo2val);
-static void emu_readip(sc_p scp, int chn, u_int *ip) __unused;
-static void emu_writeip(sc_p scp, int chn, u_int ip);
-static void emu_readifatn(sc_p scp, int chn, u_int *ifc, u_int *atn) __unused;
-static void emu_writeifatn(sc_p scp, int chn, u_int ifc, u_int atn);
-static void emu_readpefe(sc_p scp, int chn, u_int *pe, u_int *fe) __unused;
-static void emu_writepefe(sc_p scp, int chn, u_int pe, u_int fe);
-static void emu_readfmmod(sc_p scp, int chn, u_int *fm, u_int *mod) __unused;
-static void emu_writefmmod(sc_p scp, int chn, u_int fm, u_int mod);
-static void emu_readtremfrq(sc_p scp, int chn, u_int *trem, u_int *frq) __unused;
-static void emu_writetremfrq(sc_p scp, int chn, u_int trem, u_int frq);
-static void emu_readfm2frq2(sc_p scp, int chn, u_int *fm2, u_int *frq2) __unused;
-static void emu_writefm2frq2(sc_p scp, int chn, u_int fm2, u_int frq2);
-static void emu_readprobe(sc_p scp, u_int *val);
-static void emu_writeprobe(sc_p scp, u_int val) __unused;
-static void emu_command(sc_p scp, int reg, int chn, u_long val);
-static u_long emu_status(sc_p scp, int reg, int chn);
-static int emu_allocres(sc_p scp, device_t dev);
-static void emu_releaseres(sc_p scp, device_t dev);
-
-/* PnP IDs */
-static struct isa_pnp_id emu_ids[] = {
- {0x21008c0e, "CTL0021 WaveTable Synthesizer"}, /* CTL0021 */
- {0x22008c0e, "CTL0022 WaveTable Synthesizer"}, /* CTL0022 */
-};
-
-/*
- * This is the device descriptor for the midi device.
- */
-mididev_info emu_op_desc = {
- "EMU8000 Wavetable Synth",
-
- SNDCARD_AWE32,
-
- emu_open,
- emu_close,
- emu_ioctl,
- emu_callback,
-
- MIDI_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-/*
- * Here are the main functions to interact to the user process.
- */
-
-static int
-emu_probe(device_t dev)
-{
- sc_p scp;
- int unit;
- u_int probe, hwcf1, hwcf2;
-
- /* Check isapnp ids */
- if (isa_get_logicalid(dev) != 0)
- return (ISA_PNP_PROBE(device_get_parent(dev), dev, emu_ids));
- /* XXX non-pnp emu? */
-
- unit = device_get_unit(dev);
- scp = device_get_softc(dev);
-
- device_set_desc(dev, "EMU8000 Wavetable Synth");
- bzero(scp, sizeof(*scp));
-
- MIDI_DEBUG(printf("emu%d: probing.\n", unit));
-
- if (emu_allocres(scp, dev)) {
- emu_releaseres(scp, dev);
- return (ENXIO);
- }
-
- emu_readprobe(scp, &probe);
- emu_readhwcf1(scp, &hwcf1);
- emu_readhwcf2(scp, &hwcf2);
- if ((probe & 0x000f) != 0x000c
- || (hwcf1 & 0x007e) != 0x0058
- || (hwcf2 & 0x0003) != 0x0003) {
- emu_releaseres(scp, dev);
- return (ENXIO);
- }
-
- MIDI_DEBUG(printf("emu%d: probed.\n", unit));
-
- return (0);
-}
-
-extern synthdev_info midisynth_op_desc;
-
-static int
-emu_attach(device_t dev)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit, i;
-
- unit = device_get_unit(dev);
- scp = device_get_softc(dev);
-
- MIDI_DEBUG(printf("emu%d: attaching.\n", unit));
-
- if (emu_allocres(scp, dev)) {
- emu_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* EMU8000 needs some initialization processes. */
-
- /* 1. Write HWCF{1,2}. */
- emu_writehwcf1(scp, 0x0059);
- emu_writehwcf2(scp, 0x0020);
-
- /* Disable the audio. */
- emu_writehwcf3(scp, 0);
-
- /* 2. Initialize the channels. */
-
- /* 2a. Write DCYSUSV. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writedcysusv(scp, i, 0, 0, 1, 0);
-
- /* 2b. Clear the envelope and sound engine registers. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++) {
- emu_writeenvvol(scp, i, 0);
- emu_writeenvval(scp, i, 0);
- emu_writedcysus(scp, i, 0, 0, 0);
- emu_writeatkhldv(scp, i, 0);
- emu_writelfo1val(scp, i, 0);
- emu_writeatkhld(scp, i, 0);
- emu_writelfo2val(scp, i, 0);
- emu_writeip(scp, i, 0);
- emu_writeifatn(scp, i, 0, 0);
- emu_writepefe(scp, i, 0, 0);
- emu_writefmmod(scp, i, 0, 0);
- emu_writetremfrq(scp, i, 0, 0);
- emu_writefm2frq2(scp, i, 0, 0);
- emu_writeptrx(scp, i, 0, 0, 0);
- emu_writevtft(scp, i, 0, 0);
- emu_writepsst(scp, i, 0, 0);
- emu_writecsl(scp, i, 0, 0);
- emu_writeccca(scp, i, 0, 0, 0, 0, 0);
- }
-
- /* 2c. Clear the current registers. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++) {
- emu_writecpf(scp, i, 0, 0);
- emu_writecvcf(scp, i, 0, 0);
- }
-
- /* 3. Initialize the sound memory DMA registers. */
- emu_writesmalr(scp, 0, 0);
- emu_writesmarr(scp, 0, 0);
- emu_writesmalw(scp, 0, 0);
- emu_writesmarw(scp, 0, 0);
-
- /* 4. Fill the array. */
-
- /* 4a. Set 1. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit1(scp, i, init1_1[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit2(scp, i, init1_2[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit3(scp, i, init1_3[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit4(scp, i, init1_4[i]);
-
- /* 4b. Have a rest. */
- emu_delay(scp, 1024); /* 1024 samples. */
-
- /* 4c. Set 2. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit1(scp, i, init2_1[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit2(scp, i, init2_2[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit3(scp, i, init2_3[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit4(scp, i, init2_4[i]);
-
- /* 4d. Set 3. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit1(scp, i, init3_1[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit2(scp, i, init3_2[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit3(scp, i, init3_3[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit4(scp, i, init3_4[i]);
-
- /* 4e. Write to HWCF{4,5,6}. */
- emu_writehwcf4(scp, 0);
- emu_writehwcf5(scp, 0x00000083);
- emu_writehwcf6(scp, 0x00008000);
-
- /* 4f. Set 4. */
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit1(scp, i, init4_1[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit2(scp, i, init4_2[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit3(scp, i, init4_3[i]);
- for (i = 0 ; i < EMU8K_MAXVOICE ; i++)
- emu_writeinit4(scp, i, init4_4[i]);
-
- /* 5. Determine the size of DRAM. */
- scp->dev = dev;
- scp->dramsize = emu_dramsize(scp);
- printf("emu%d: DRAM size = %dKB\n", unit, scp->dramsize / 1024);
-
- /* We have inited the EMU8000. Now work on FM. */
-
- /* Write parameters for the left channel. */
- emu_writedcysusv(scp, 30, 0, 0, 1, 0);
- emu_writepsst(scp, 30, 0x80, 0xffffe0); /* full left */
- emu_writecsl(scp, 30, 0, 0xfffff8); /* chorus */
- emu_writeptrx(scp, 30, 0, 0, 0); /* reverb */
- emu_writecpf(scp, 30, 0, 0);
- emu_writeccca(scp, 30, 0, 0, 0, 0, 0xffffe3);
-
- /* Then the right channel. */
- emu_writedcysusv(scp, 31, 0, 0, 1, 0);
- emu_writepsst(scp, 31, 0x80, 0xfffff0); /* full right */
- emu_writecsl(scp, 31, 0, 0xfffff8); /* chorus */
- emu_writeptrx(scp, 31, 0, 0, 0xff); /* reverb */
- emu_writecpf(scp, 31, 0, 0);
- emu_writeccca(scp, 31, 0, 0, 0, 0, 0xfffff3);
-
- /* Skew volume and cutoff. */
- emu_writevtft(scp, 30, 0x8000, 0xffff);
- emu_writevtft(scp, 31, 0x8000, 0xffff);
-
- /* Ready to sound. */
- emu_writehwcf3(scp, 0x0004);
-
- /* Fill the softc for this unit. */
- bcopy(&emu_synthinfo, &scp->synthinfo, sizeof(emu_synthinfo));
- mtx_init(&scp->mtx, "emumid", NULL, MTX_DEF);
- scp->devinfo = devinfo = create_mididev_info_unit(MDT_SYNTH, &emu_op_desc, &midisynth_op_desc);
-
- /* Fill the midi info. */
- devinfo->synth.readraw = emu_readraw;
- devinfo->synth.writeraw = emu_writeraw;
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x, 0x%x, 0x%x",
- (u_int)rman_get_start(scp->io[0]), (u_int)rman_get_start(scp->io[1]), (u_int)rman_get_start(scp->io[2]));
-
- midiinit(devinfo, dev);
-
- MIDI_DEBUG(printf("emu%d: attached.\n", unit));
-
- return (0);
-}
-
-static int
-emupnp_attach(device_t dev)
-{
- return (emu_attach(dev));
-}
-
-static int
-emu_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- return (0);
-}
-
-static int
-emu_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- return (0);
-}
-
-static int
-emu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("emu_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("emu_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- switch (cmd) {
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- if (synthinfo->device != unit)
- return (ENXIO);
- bcopy(&scp->synthinfo, synthinfo, sizeof(scp->synthinfo));
- synthinfo->device = unit;
- return (0);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- if (midiinfo->device != unit)
- return (ENXIO);
- bcopy(&emu_midiinfo, midiinfo, sizeof(emu_midiinfo));
- strcpy(midiinfo->name, scp->synthinfo.name);
- midiinfo->device = unit;
- return (0);
- break;
- case SNDCTL_SYNTH_MEMAVL:
- *(int *)arg = 0x7fffffff;
- return (0);
- break;
- default:
- return (ENOSYS);
- }
- /* NOTREACHED */
- return (EINVAL);
-}
-
-static int
-emu_callback(void *d, int reason)
-{
- mididev_info *devinfo;
-
- devinfo = (mididev_info *)d;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- return (0);
-}
-
-static int
-emu_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
-{
- sc_p scp;
- int unit;
-
- if (md == NULL)
- return (ENXIO);
- if (lenr == NULL)
- return (EINVAL);
-
- unit = md->unit;
- scp = md->softc;
- if ((md->fflags & FREAD) == 0) {
- MIDI_DEBUG(printf("emu_readraw: unit %d is not for reading.\n", unit));
- return (EIO);
- }
-
- /* NOP. */
- *lenr = 0;
-
- return (0);
-}
-
-static int
-emu_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
-{
- sc_p scp;
- int unit;
-
- if (md == NULL)
- return (ENXIO);
- if (lenw == NULL)
- return (EINVAL);
-
- unit = md->unit;
- scp = md->softc;
- if ((md->fflags & FWRITE) == 0) {
- MIDI_DEBUG(printf("emu_writeraw: unit %d is not for writing.\n", unit));
- return (EIO);
- }
-
- /* NOP. */
- *lenw = 0;
-
- return (0);
-}
-
-/*
- * The functions below here are the synthesizer interfaces.
- */
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-/* Determine the size of DRAM. */
-static u_int
-emu_dramsize(sc_p scp)
-{
- u_int dramsize;
- static u_short magiccode[] = {0x386d, 0xbd2a, 0x73df, 0xf2d8};
- static u_short magiccode2[] = {0x5ef3, 0x2b90, 0xa4c8, 0x6a13};
- u_short buf[sizeof(magiccode) / sizeof(*magiccode)];
-
- /*
- * Write the magic code to the bottom of DRAM.
- * Writing to a wrapped address clobbers the code.
- */
- emu_allocdmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE);
- emu_dmaaddress(scp, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE, EMU8K_DRAM_RAM);
- emu_writeblkstream(scp, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE, magiccode, sizeof(magiccode) / sizeof(*magiccode));
- emu_releasedmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE);
-
- for (dramsize = 0 ; dramsize + EMU8K_DRAM_RAM < EMU8K_DRAM_MAX ; ) {
-
- /* Read the magic code. */
- emu_allocdmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_READ);
- emu_dmaaddress(scp, EMU8K_DMA_LEFT | EMU8K_DMA_READ, EMU8K_DRAM_RAM);
- emu_readblkstream(scp, EMU8K_DMA_LEFT | EMU8K_DMA_READ, buf, sizeof(buf) / sizeof(*buf));
- emu_releasedmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_READ);
-
- /* Compare the code. */
- if (bcmp(magiccode, buf, sizeof(magiccode)))
- break;
-
- /* Increase the DRAM size. */
- dramsize += 0x8000;
-
- /* Try writing a different magic code to dramsize. */
- emu_allocdmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE);
- emu_dmaaddress(scp, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE, dramsize + EMU8K_DRAM_RAM);
- emu_writeblkstream(scp, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE, magiccode2, sizeof(magiccode2) / sizeof(*magiccode2));
- emu_releasedmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_WRITE);
-
- /* Then read the magic code. */
- emu_allocdmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_READ);
- emu_dmaaddress(scp, EMU8K_DMA_LEFT | EMU8K_DMA_READ, dramsize + EMU8K_DRAM_RAM);
- emu_readblkstream(scp, EMU8K_DMA_LEFT | EMU8K_DMA_READ, buf, sizeof(buf) / sizeof(*buf));
- emu_releasedmachn(scp, 31, EMU8K_DMA_LEFT | EMU8K_DMA_READ);
-
- /* Compare the code. */
- if (bcmp(magiccode2, buf, sizeof(magiccode2)))
- break;
- }
- if (dramsize + EMU8K_DRAM_RAM > EMU8K_DRAM_MAX)
- dramsize = EMU8K_DRAM_MAX - EMU8K_DRAM_RAM;
-
- return dramsize * 2; /* dramsize is in words. */
-}
-
-/* Allocates a channel to a DMA stream. */
-static void
-emu_allocdmachn(sc_p scp, int chn, int mode)
-{
- /* Turn off the sound, prepare for a DMA stream. */
- emu_writedcysusv(scp, chn, 0, 0, 1, 0);
- emu_writevtft(scp, chn, 0, 0);
- emu_writecvcf(scp, chn, 0, 0);
- emu_writeptrx(scp, chn, 0x4000, 0, 0);
- emu_writecpf(scp, chn, 0x4000, 0);
- emu_writepsst(scp, chn, 0, 0);
- emu_writecsl(scp, chn, 0, 0);
-
- /* Enter DMA mode. */
- emu_writeccca(scp, chn, 0, 1,
- ((mode & EMU8K_DMA_WRITE) > 0) ? 1 : 0,
- ((mode & EMU8K_DMA_RIGHT) > 0) ? 1 : 0,
- 0);
-}
-
-/* Programs the initial address to a DMA. */
-static void
-emu_dmaaddress(sc_p scp, int mode, u_int addr)
-{
- /* Wait until the stream comes ready. */
- emu_waitstream(scp, mode);
-
- switch(mode & EMU8K_DMA_MASK)
- {
- case EMU8K_DMA_LEFT | EMU8K_DMA_READ:
- emu_writesmalr(scp, 0, addr);
- emu_readsmld(scp, NULL); /* Read the stale data. */
- break;
- case EMU8K_DMA_RIGHT | EMU8K_DMA_READ:
- emu_writesmarr(scp, 0, addr);
- emu_readsmrd(scp, NULL); /* Read the stale data. */
- break;
- case EMU8K_DMA_LEFT | EMU8K_DMA_WRITE:
- emu_writesmalw(scp, 0, addr);
- break;
- case EMU8K_DMA_RIGHT | EMU8K_DMA_WRITE:
- emu_writesmarw(scp, 0, addr);
- break;
- }
-}
-
-/* Waits until a stream gets ready. */
-static void
-emu_waitstream(sc_p scp, int mode)
-{
- int i;
- u_int busy;
-
- for (i = 0 ; i < 100000 ; i++) {
- switch(mode & EMU8K_DMA_MASK)
- {
- case EMU8K_DMA_LEFT | EMU8K_DMA_READ:
- emu_readsmalr(scp, &busy, NULL);
- break;
- case EMU8K_DMA_RIGHT | EMU8K_DMA_READ:
- emu_readsmarr(scp, &busy, NULL);
- break;
- case EMU8K_DMA_LEFT | EMU8K_DMA_WRITE:
- emu_readsmalw(scp, &busy, NULL);
- break;
- case EMU8K_DMA_RIGHT | EMU8K_DMA_WRITE:
- emu_readsmarw(scp, &busy, NULL);
- break;
- }
- if (!busy)
- break;
- emu_delay(scp, 1);
- }
- if (busy)
- printf("emu%d: stream data still busy, timed out.\n", device_get_unit(scp->dev));
-}
-
-/* Reads a word block from a stream. */
-static void
-emu_readblkstream(sc_p scp, int mode, u_short *data, size_t len)
-{
- while((len--) > 0)
- emu_readstream(scp, mode, data++);
-}
-
-/* Writes a word block stream to a stream. */
-static void
-emu_writeblkstream(sc_p scp, int mode, u_short *data, size_t len)
-{
- while((len--) > 0)
- emu_writestream(scp, mode, *(data++));
-}
-
-/* Reads a word from a stream. */
-static void
-emu_readstream(sc_p scp, int mode, u_short *data)
-{
- if ((mode & EMU8K_DMA_RW) != EMU8K_DMA_READ)
- return;
-
- switch(mode & EMU8K_DMA_MASK)
- {
- case EMU8K_DMA_LEFT | EMU8K_DMA_READ:
- emu_readsmld(scp, data);
- break;
- case EMU8K_DMA_RIGHT | EMU8K_DMA_READ:
- emu_readsmrd(scp, data);
- break;
- }
-}
-
-/* Writes a word to a stream. */
-static void
-emu_writestream(sc_p scp, int mode, u_short data)
-{
- if ((mode & EMU8K_DMA_RW) != EMU8K_DMA_WRITE)
- return;
-
- switch(mode & EMU8K_DMA_MASK)
- {
- case EMU8K_DMA_LEFT | EMU8K_DMA_WRITE:
- emu_writesmld(scp, data);
- break;
- case EMU8K_DMA_RIGHT | EMU8K_DMA_WRITE:
- emu_writesmrd(scp, data);
- break;
- }
-}
-
-/* Releases a channel from a DMA stream. */
-static void
-emu_releasedmachn(sc_p scp, int chn, int mode)
-{
- /* Wait until the stream comes ready. */
- emu_waitstream(scp, mode);
-
- /* Leave DMA mode. */
- emu_writeccca(scp, chn, 0, 0, 0, 0, 0);
-}
-
-/*
- * Waits cycles.
- * Idea-stolen-from: sys/i386/isa/clock.c:DELAY()
- */
-static void
-emu_delay(sc_p scp, short n)
-{
- int wc_prev, wc, wc_left, wc_delta;
-
- emu_readwc(scp, &wc_prev);
- wc_left = n;
-
- while (wc_left > 0) {
- emu_readwc(scp, &wc);
- wc_delta = wc - wc_prev; /* The counter increases. */
- wc_prev = wc;
- if (wc_delta < 0)
- wc_delta += 0xffff;
- wc_left -= wc_delta;
- }
-}
-
-/* The followings provide abstract access to the registers. */
-#define DECBIT(sts, shift, len) (((sts) >> (shift))) & (0xffffffff >> (32 - len))
-#define GENBIT(val, shift, len) (((val) & (0xffffffff >> (32 - len))) << (shift))
-
-/* CPF: Current Pitch and Fractional Address */
-static void
-emu_readcpf(sc_p scp, int chn, u_int *cp, u_int *f)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_CPF, chn);
- if (cp != NULL)
- *cp = DECBIT(sts, 16, 16);
- if (f != NULL)
- *f = DECBIT(sts, 0, 16);
-}
-
-static void
-emu_writecpf(sc_p scp, int chn, u_int cp, u_int f)
-{
- emu_command(scp, EMU8K_CPF, chn,
- GENBIT(cp, 16, 16)
- | GENBIT(f, 0, 16));
-}
-
-/* PTRX: Pitch Target, Rvb Send and Aux Byte */
-static void
-emu_readptrx(sc_p scp, int chn, u_int *pt, u_int *rs, u_int *auxd)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_PTRX, chn);
- if (pt != NULL)
- *pt = DECBIT(sts, 16, 16);
- if (rs != NULL)
- *rs = DECBIT(sts, 8, 8);
- if (auxd != NULL)
- *auxd = DECBIT(sts, 0, 8);
-}
-
-static void
-emu_writeptrx(sc_p scp, int chn, u_int pt, u_int rs, u_int auxd)
-{
- emu_command(scp, EMU8K_PTRX, chn,
- GENBIT(pt, 16, 16)
- | GENBIT(rs, 8, 8)
- | GENBIT(auxd, 0, 8));
-}
-
-/* CVCF: Current Volume and Filter Cutoff */
-static void
-emu_readcvcf(sc_p scp, int chn, u_int *cv, u_int *cf)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_CVCF, chn);
- if (cv != NULL)
- *cv = DECBIT(sts, 16, 16);
- if (cf != NULL)
- *cf = DECBIT(sts, 0, 16);
-}
-
-static void
-emu_writecvcf(sc_p scp, int chn, u_int cv, u_int cf)
-{
- emu_command(scp, EMU8K_CVCF, chn,
- GENBIT(cv, 16, 16)
- | GENBIT(cf, 0, 16));
-}
-
-/* VTFT: Volume and Filter Cutoff Targets */
-static void
-emu_readvtft(sc_p scp, int chn, u_int *vt, u_int *ft)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_VTFT, chn);
- if (vt != NULL)
- *vt = DECBIT(sts, 16, 16);
- if (ft != NULL)
- *ft = DECBIT(sts, 0, 16);
-}
-
-static void
-emu_writevtft(sc_p scp, int chn, u_int vt, u_int ft)
-{
- emu_command(scp, EMU8K_VTFT, chn,
- GENBIT(vt, 16, 16)
- | GENBIT(ft, 0, 16));
-}
-
-/* PSST: Pan Send and Loop Start Address */
-static void
-emu_readpsst(sc_p scp, int chn, u_int *pan, u_int *st)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_PSST, chn);
- if (pan != NULL)
- *pan = DECBIT(sts, 24, 8);
- if (st != NULL)
- *st = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writepsst(sc_p scp, int chn, u_int pan, u_int st)
-{
- emu_command(scp, EMU8K_PSST, chn,
- GENBIT(pan, 24, 8)
- | GENBIT(st, 0, 24));
-}
-
-/* CSL: Chorus Send and Loop End Address */
-static void
-emu_readcsl(sc_p scp, int chn, u_int *cs, u_int *lp)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_CSL, chn);
- if (cs != NULL)
- *cs = DECBIT(sts, 24, 8);
- if (lp != NULL)
- *lp = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writecsl(sc_p scp, int chn, u_int cs, u_int lp)
-{
- emu_command(scp, EMU8K_CSL, chn,
- GENBIT(cs, 24, 8)
- | GENBIT(lp, 0, 24));
-}
-
-/* CCCA: Q, Control Bits and Current Address */
-static void
-emu_readccca(sc_p scp, int chn, u_int *q, u_int *dma, u_int *wr, u_int *right, u_int *ca)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_CCCA, chn);
- if (q != NULL)
- *q = DECBIT(sts, 28, 4);
- if (dma != NULL)
- *dma = DECBIT(sts, 26, 1);
- if (wr != NULL)
- *wr = DECBIT(sts, 25, 1);
- if (right != NULL)
- *right = DECBIT(sts, 24, 1);
- if (ca != NULL)
- *ca = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writeccca(sc_p scp, int chn, u_int q, u_int dma, u_int wr, u_int right, u_int ca)
-{
- emu_command(scp, EMU8K_CCCA, chn,
- GENBIT(q, 28, 4)
- | GENBIT(dma, 26, 1)
- | GENBIT(wr, 25, 1)
- | GENBIT(right, 24, 1)
- | GENBIT(ca, 0, 24));
-}
-
-/* HWCF4: Configuration Double Word 4 */
-static void
-emu_readhwcf4(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_HWCF4, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writehwcf4(sc_p scp, u_int val)
-{
- if (val != 0)
- printf("emu%d: writing value 0x%x to HWCF4.\n", device_get_unit(scp->dev), val);
- emu_command(scp, EMU8K_HWCF4, 0, val);
-}
-
-/* HWCF5: Configuration Double Word 5 */
-static void
-emu_readhwcf5(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_HWCF5, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writehwcf5(sc_p scp, u_int val)
-{
- if (val != 0x00000083)
- printf("emu%d: writing value 0x%x to HWCF5.\n", device_get_unit(scp->dev), val);
- emu_command(scp, EMU8K_HWCF5, 0, val);
-}
-
-/* HWCF6: Configuration Double Word 6 */
-static void
-emu_readhwcf6(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_HWCF6, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writehwcf6(sc_p scp, u_int val)
-{
- if (val != 0x00008000)
- printf("emu%d: writing value 0x%x to HWCF6.\n", device_get_unit(scp->dev), val);
- emu_command(scp, EMU8K_HWCF6, 0, val);
-}
-
-/* SMALR: Sound Memory Address for Left SM Reads */
-static void
-emu_readsmalr(sc_p scp, u_int *mt, u_int *smalr)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_SMALR, 0);
- if (mt != NULL)
- *mt = DECBIT(sts, 31, 1);
- if (smalr != NULL)
- *smalr = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writesmalr(sc_p scp, u_int mt, u_int smalr)
-{
- emu_command(scp, EMU8K_SMALR, 0,
- GENBIT(mt, 31, 1)
- | GENBIT(smalr, 0, 24));
-}
-
-/* SMARR: Sound Memory Address for Right SM Reads */
-static void
-emu_readsmarr(sc_p scp, u_int *mt, u_int *smarr)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_SMARR, 0);
- if (mt != NULL)
- *mt = DECBIT(sts, 31, 1);
- if (smarr != NULL)
- *smarr = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writesmarr(sc_p scp, u_int mt, u_int smarr)
-{
- emu_command(scp, EMU8K_SMARR, 0,
- GENBIT(mt, 31, 1)
- | GENBIT(smarr, 0, 24));
-}
-
-/* SMALW: Sound Memory Address for Left SM Writes */
-static void
-emu_readsmalw(sc_p scp, u_int *full, u_int *smalw)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_SMALW, 0);
- if (full != NULL)
- *full = DECBIT(sts, 31, 1);
- if (smalw != NULL)
- *smalw = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writesmalw(sc_p scp, u_int full, u_int smalw)
-{
- emu_command(scp, EMU8K_SMALW, 0,
- GENBIT(full, 31, 1)
- | GENBIT(smalw, 0, 24));
-}
-
-/* SMARW: Sound Memory Address for Right SM Writes */
-static void
-emu_readsmarw(sc_p scp, u_int *full, u_int *smarw)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_SMARW, 0);
- if (full != NULL)
- *full = DECBIT(sts, 31, 1);
- if (smarw != NULL)
- *smarw = DECBIT(sts, 0, 24);
-}
-
-static void
-emu_writesmarw(sc_p scp, u_int full, u_int smarw)
-{
- emu_command(scp, EMU8K_SMARW, 0,
- GENBIT(full, 31, 1)
- | GENBIT(smarw, 0, 24));
-}
-
-/* SMLD: Sound Memory Left Data */
-static void
-emu_readsmld(sc_p scp, u_short *smld)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_SMLD, 0);
- if (smld != NULL)
- *smld = sts;
-}
-
-static void
-emu_writesmld(sc_p scp, u_short smld)
-{
- emu_command(scp, EMU8K_SMLD, 0, smld);
-}
-
-/* SMRD: Sound Memory Right Data */
-static void
-emu_readsmrd(sc_p scp, u_short *smrd)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_SMRD, 0);
- if (smrd != NULL)
- *smrd = sts;
-}
-
-static void
-emu_writesmrd(sc_p scp, u_short smrd)
-{
- emu_command(scp, EMU8K_SMRD, 0, smrd);
-}
-
-/* WC: Sample COunter */
-static void
-emu_readwc(sc_p scp, u_int *wc)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_WC, 0);
- if (wc != NULL)
- *wc = sts;
-}
-
-static void
-emu_writewc(sc_p scp, u_int wc)
-{
- emu_command(scp, EMU8K_WC, 0, wc);
-}
-
-/* HWCF1: Configuration Double Word 1 */
-static void
-emu_readhwcf1(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_HWCF1, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writehwcf1(sc_p scp, u_int val)
-{
- if (val != 0x0059)
- printf("emu%d: writing value 0x%x to HWCF1.\n", device_get_unit(scp->dev), val);
- emu_command(scp, EMU8K_HWCF1, 0, val);
-}
-
-/* HWCF2: Configuration Double Word 2 */
-static void
-emu_readhwcf2(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_HWCF2, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writehwcf2(sc_p scp, u_int val)
-{
- if (val != 0x0020)
- printf("emu%d: writing value 0x%x to HWCF2.\n", device_get_unit(scp->dev), val);
- emu_command(scp, EMU8K_HWCF2, 0, val);
-}
-
-/* HWCF3: Configuration Double Word 3 */
-static void
-emu_readhwcf3(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_HWCF3, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writehwcf3(sc_p scp, u_int val)
-{
- if (val != 0x0004 && val != 0)
- printf("emu%d: writing value 0x%x to HWCF3.\n", device_get_unit(scp->dev), val);
- emu_command(scp, EMU8K_HWCF3, 0, val);
-}
-
-/* INIT1: Initialization Array 1 */
-static void
-emu_readinit1(sc_p scp, int chn, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_INIT1, chn);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writeinit1(sc_p scp, int chn, u_int val)
-{
- emu_command(scp, EMU8K_INIT1, chn, val);
-}
-
-/* INIT2: Initialization Array 2 */
-static void
-emu_readinit2(sc_p scp, int chn, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_INIT2, chn);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writeinit2(sc_p scp, int chn, u_int val)
-{
- emu_command(scp, EMU8K_INIT2, chn, val);
-}
-
-/* INIT3: Initialization Array 3 */
-static void
-emu_readinit3(sc_p scp, int chn, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_INIT3, chn);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writeinit3(sc_p scp, int chn, u_int val)
-{
- emu_command(scp, EMU8K_INIT3, chn, val);
-}
-
-/* INIT4: Initialization Array 4 */
-static void
-emu_readinit4(sc_p scp, int chn, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_INIT4, chn);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writeinit4(sc_p scp, int chn, u_int val)
-{
- emu_command(scp, EMU8K_INIT4, chn, val);
-}
-
-/* ENVVOL: Volume Envelope Decay */
-static void
-emu_readenvvol(sc_p scp, int chn, u_int *envvol)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_ENVVOL, chn);
- if (envvol != NULL)
- *envvol = sts;
-}
-
-static void
-emu_writeenvvol(sc_p scp, int chn, u_int envvol)
-{
- emu_command(scp, EMU8K_ENVVOL, chn, envvol);
-}
-
-/* DCYSUSV: Volume Envelope Sustain and Decay */
-static void
-emu_readdcysusv(sc_p scp, int chn, u_int *ph1v, u_int *susv, u_int *off, u_int *dcyv)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_DCYSUSV, chn);
- if (ph1v != NULL)
- *ph1v = DECBIT(sts, 15, 1);
- if (susv != NULL)
- *susv = DECBIT(sts, 8, 7);
- if (off != NULL)
- *off = DECBIT(sts, 7, 1);
- if (dcyv != NULL)
- *dcyv = DECBIT(sts, 0, 7);
-}
-
-static void
-emu_writedcysusv(sc_p scp, int chn, u_int ph1v, u_int susv, u_int off, u_int dcyv)
-{
- emu_command(scp, EMU8K_DCYSUSV, chn,
- GENBIT(ph1v, 15, 1)
- | GENBIT(susv, 8, 7)
- | GENBIT(off, 7, 1)
- | GENBIT(dcyv, 0, 7));
-}
-
-/* ENVVAL: Modulation Envelope Decay */
-static void
-emu_readenvval(sc_p scp, int chn, u_int *envval)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_ENVVAL, chn);
- if (envval != NULL)
- *envval = sts;
-}
-
-static void
-emu_writeenvval(sc_p scp, int chn, u_int envval)
-{
- emu_command(scp, EMU8K_ENVVAL, chn, envval);
-}
-
-/* DCYSUS: Modulation Envelope Sustain and Decay */
-static void
-emu_readdcysus(sc_p scp, int chn, u_int *ph1, u_int *sus, u_int *dcy)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_DCYSUS, chn);
- if (ph1 != NULL)
- *ph1 = DECBIT(sts, 15, 1);
- if (sus != NULL)
- *sus = DECBIT(sts, 8, 7);
- if (dcy != NULL)
- *dcy = DECBIT(sts, 0, 7);
-}
-
-static void
-emu_writedcysus(sc_p scp, int chn, u_int ph1, u_int sus, u_int dcy)
-{
- emu_command(scp, EMU8K_DCYSUS, chn,
- GENBIT(ph1, 15, 1)
- | GENBIT(sus, 8, 7)
- | GENBIT(dcy, 0, 7));
-}
-
-/* ATKHLDV: Volume Envelope Hold and Attack */
-static void
-emu_readatkhldv(sc_p scp, int chn, u_int *atkhldv)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_ATKHLDV, chn);
- if (atkhldv != NULL)
- *atkhldv = sts;
-}
-
-static void
-emu_writeatkhldv(sc_p scp, int chn, u_int atkhldv)
-{
- emu_command(scp, EMU8K_ATKHLDV, chn, atkhldv);
-}
-
-/* LFO1VAL: LFO #1 Delay */
-static void
-emu_readlfo1val(sc_p scp, int chn, u_int *lfo1val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_LFO1VAL, chn);
- if (lfo1val != NULL)
- *lfo1val = sts;
-}
-
-static void
-emu_writelfo1val(sc_p scp, int chn, u_int lfo1val)
-{
- emu_command(scp, EMU8K_LFO1VAL, chn, lfo1val);
-}
-
-/* ATKHLD: Modulation Envelope Hold and Attack */
-static void
-emu_readatkhld(sc_p scp, int chn, u_int *atkhld)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_ATKHLD, chn);
- if (atkhld != NULL)
- *atkhld = sts;
-}
-
-static void
-emu_writeatkhld(sc_p scp, int chn, u_int atkhld)
-{
- emu_command(scp, EMU8K_ATKHLD, chn, atkhld);
-}
-
-/* LFO2VAL: LFO #2 Delay */
-static void
-emu_readlfo2val(sc_p scp, int chn, u_int *lfo2val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_LFO2VAL, chn);
- if (lfo2val != NULL)
- *lfo2val = sts;
-}
-
-static void
-emu_writelfo2val(sc_p scp, int chn, u_int lfo2val)
-{
- emu_command(scp, EMU8K_LFO2VAL, chn, lfo2val);
-}
-
-/* IP: Initial Pitch */
-static void
-emu_readip(sc_p scp, int chn, u_int *ip)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_IP, chn);
- if (ip != NULL)
- *ip = sts;
-}
-
-static void
-emu_writeip(sc_p scp, int chn, u_int ip)
-{
- emu_command(scp, EMU8K_IP, chn, ip);
-}
-
-/* IFATN: Initial Filter Cutoff and Attenuation */
-static void
-emu_readifatn(sc_p scp, int chn, u_int *ifc, u_int *atn)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_IFATN, chn);
- if (ifc != NULL)
- *ifc = DECBIT(sts, 8, 8);
- if (atn != NULL)
- *atn = DECBIT(sts, 0, 8);
-}
-
-static void
-emu_writeifatn(sc_p scp, int chn, u_int ifc, u_int atn)
-{
- emu_command(scp, EMU8K_IFATN, chn,
- GENBIT(ifc, 8, 8)
- | GENBIT(atn, 0, 8));
-}
-
-/* PEFE: Pitch and Filter Envelope Heights */
-static void
-emu_readpefe(sc_p scp, int chn, u_int *pe, u_int *fe)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_PEFE, chn);
- if (pe != NULL)
- *pe = DECBIT(sts, 8, 8);
- if (fe != NULL)
- *fe = DECBIT(sts, 0, 8);
-}
-
-static void
-emu_writepefe(sc_p scp, int chn, u_int pe, u_int fe)
-{
- emu_command(scp, EMU8K_PEFE, chn,
- GENBIT(pe, 8, 8)
- | GENBIT(fe, 0, 8));
-}
-
-/* FMMOD: Vibrato and Filter Modulation from LFO #1 */
-static void
-emu_readfmmod(sc_p scp, int chn, u_int *fm, u_int *mod)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_FMMOD, chn);
- if (fm != NULL)
- *fm = DECBIT(sts, 8, 8);
- if (mod != NULL)
- *mod = DECBIT(sts, 0, 8);
-}
-
-static void
-emu_writefmmod(sc_p scp, int chn, u_int fm, u_int mod)
-{
- emu_command(scp, EMU8K_FMMOD, chn,
- GENBIT(fm, 8, 8)
- | GENBIT(mod, 0, 8));
-}
-
-/* TREMFRQ: LFO #1 Tremolo Amount and Frequency */
-static void
-emu_readtremfrq(sc_p scp, int chn, u_int *trem, u_int *frq)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_TREMFRQ, chn);
- if (trem != NULL)
- *trem = DECBIT(sts, 8, 8);
- if (frq != NULL)
- *frq = DECBIT(sts, 0, 8);
-}
-
-static void
-emu_writetremfrq(sc_p scp, int chn, u_int trem, u_int frq)
-{
- emu_command(scp, EMU8K_TREMFRQ, chn,
- GENBIT(trem, 8, 8)
- | GENBIT(frq, 0, 8));
-}
-
-/* FM2FRQ2: LFO #2 Vibrato Amount and Frequency */
-static void
-emu_readfm2frq2(sc_p scp, int chn, u_int *fm2, u_int *frq2)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_FM2FRQ2, chn);
- if (fm2 != NULL)
- *fm2 = DECBIT(sts, 8, 8);
- if (frq2 != NULL)
- *frq2 = DECBIT(sts, 0, 8);
-}
-
-static void
-emu_writefm2frq2(sc_p scp, int chn, u_int fm2, u_int frq2)
-{
- emu_command(scp, EMU8K_FM2FRQ2, chn,
- GENBIT(fm2, 8, 8)
- | GENBIT(frq2, 0, 8));
-}
-
-/* PROBE: Probe Register */
-static void
-emu_readprobe(sc_p scp, u_int *val)
-{
- u_long sts;
-
- sts = emu_status(scp, EMU8K_PROBE, 0);
- if (val != NULL)
- *val = sts;
-}
-
-static void
-emu_writeprobe(sc_p scp, u_int val)
-{
- emu_command(scp, EMU8K_PROBE, 0, val);
-}
-
-/* Writes to a register. */
-static void
-emu_command(sc_p scp, int reg, int chn, u_long val)
-{
- if (chn < 0 || chn >= EMU8K_MAXVOICE || reg < 0 || reg >= EMU8K_REGNUM)
- return;
-
- /* Override the channel if necessary. */
- if (emu_regs[reg].chn != EMU8K_CHN_ANY)
- chn = emu_regs[reg].chn;
-
- /* Select the register first. */
- bus_space_write_2(rman_get_bustag(scp->io[EMU8K_IDX_PTR]), rman_get_bushandle(scp->io[EMU8K_IDX_PTR]), EMU8K_PORT_PTR, (chn & 0x1f) | ((emu_regs[reg].reg & 0x07) << 5));
-
- /* Then we write the data. */
- bus_space_write_2(rman_get_bustag(scp->io[emu_regs[reg].index]), rman_get_bushandle(scp->io[emu_regs[reg].index]), emu_regs[reg].port, val & 0xffff);
- if (emu_regs[reg].size)
- /* double word */
- bus_space_write_2(rman_get_bustag(scp->io[emu_regs[reg].index]), rman_get_bushandle(scp->io[emu_regs[reg].index]), emu_regs[reg].port + 2, (val >> 16) & 0xffff);
-}
-
-/* Reads from a register. */
-static u_long
-emu_status(sc_p scp, int reg, int chn)
-{
- u_long status;
-
- if (chn < 0 || chn >= EMU8K_MAXVOICE || reg < 0 || reg >= EMU8K_REGNUM)
- return (0xffffffff);
-
- /* Override the channel if necessary. */
- if (emu_regs[reg].chn != EMU8K_CHN_ANY)
- chn = emu_regs[reg].chn;
-
- /* Select the register first. */
- bus_space_write_2(rman_get_bustag(scp->io[EMU8K_IDX_PTR]), rman_get_bushandle(scp->io[EMU8K_IDX_PTR]), EMU8K_PORT_PTR, (chn & 0x1f) | ((emu_regs[reg].reg & 0x07) << 5));
-
- /* Then we read the data. */
- status = bus_space_read_2(rman_get_bustag(scp->io[emu_regs[reg].index]), rman_get_bushandle(scp->io[emu_regs[reg].index]), emu_regs[reg].port) & 0xffff;
- if (emu_regs[reg].size)
- /* double word */
- status |= (bus_space_read_2(rman_get_bustag(scp->io[emu_regs[reg].index]), rman_get_bushandle(scp->io[emu_regs[reg].index]), emu_regs[reg].port + 2) & 0xffff) << 16;
-
- return (status);
-}
-
-/* Allocates resources. */
-static int
-emu_allocres(sc_p scp, device_t dev)
-{
- int i;
-
- /*
- * Attempt to allocate the EMU8000's three I/O port ranges.
- */
- for (i = 0; i < 3; i++)
- {
- if (scp->io[i] == NULL)
- {
- scp->io_rid[i] = i;
- scp->io[i] = bus_alloc_resource(dev, SYS_RES_IOPORT,
- &(scp->io_rid[i]),
- 0, ~0, 4, RF_ACTIVE);
- }
- }
-
- /*
- * Fail if any of the I/O ranges failed (I.e. weren't identified and
- * configured by PNP, which can happen if the ID of the card isn't
- * known by the PNP quirk-handling logic)
- */
- if (scp->io[0] == NULL || scp->io[1] == NULL || scp->io[2] == NULL)
- {
- printf("emu%d: Resource alloc failed, pnp_quirks "
- "may need { 0x%08x, 0x%08x }\n",
- device_get_unit(dev),
- isa_get_vendorid(dev),
- isa_get_logicalid(dev));
-
- return 1;
- }
-
- return 0;
-}
-
-/* Releases resources. */
-static void
-emu_releaseres(sc_p scp, device_t dev)
-{
- if (scp->io[0] != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]);
- scp->io[0] = NULL;
- }
- if (scp->io[1] != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid[1], scp->io[1]);
- scp->io[1] = NULL;
- }
- if (scp->io[2] != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid[2], scp->io[2]);
- scp->io[2] = NULL;
- }
-}
-
-static device_method_t emu_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , emu_probe ),
- DEVMETHOD(device_attach, emu_attach),
-
- { 0, 0 },
-};
-
-static driver_t emu_driver = {
- "midi",
- emu_methods,
- sizeof(struct emu_softc),
-};
-
-DRIVER_MODULE(emu, isa, emu_driver, midi_devclass, 0, 0);
diff --git a/sys/dev/sound/isa/gusmidi.c b/sys/dev/sound/isa/gusmidi.c
deleted file mode 100644
index 16a2d18c86e3..000000000000
--- a/sys/dev/sound/isa/gusmidi.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * GUS midi interface driver.
- * Based on the newmidi MPU401 driver.
- *
- * Copyright (c) 1999 Ville-Pertti Keinonen
- * Copyright by Hannu Savolainen 1993
- *
- * 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.
- *
- * Modified: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
- * initialization routine.
- *
- * Ported to the new Audio Driver by Luigi Rizzo:
- * (C) 1999 Seigo Tanimura <tanimura@r.dl.itc.u-tokyo.ac.jp>
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-
-#include <dev/sound/chip.h>
-#include <machine/cpufunc.h>
-
-static devclass_t midi_devclass;
-
-extern synthdev_info midisynth_op_desc;
-
-/* These are the synthesizer and the midi interface information. */
-static struct synth_info gusmidi_synthinfo = {
- "GUS MIDI",
- 0,
- SYNTH_TYPE_MIDI,
- 0,
- 0,
- 128,
- 128,
- 128,
- SYNTH_CAP_INPUT,
-};
-
-static struct midi_info gusmidi_midiinfo = {
- "GUS MIDI",
- 0,
- 0,
- 0,
-};
-
-#define MIDICTL_MASTER_RESET 0x03
-#define MIDICTL_TX_IRQ_EN 0x20
-#define MIDICTL_RX_IRQ_EN 0x80
-
-#define MIDIST_RXFULL 0x01
-#define MIDIST_TXDONE 0x02
-#define MIDIST_ERR_FR 0x10
-#define MIDIST_ERR_OVR 0x20
-#define MIDIST_INTR_PEND 0x80
-
-#define PORT_CTL 0
-#define PORT_ST 0
-#define PORT_TX 1
-#define PORT_RX 1
-
-/*
- * These functions goes into gusmidi_op_desc to get called
- * from sound.c.
- */
-
-static int gusmidi_probe(device_t dev);
-static int gusmidi_attach(device_t dev);
-
-static d_open_t gusmidi_open;
-static d_ioctl_t gusmidi_ioctl;
-driver_intr_t gusmidi_intr;
-static midi_callback_t gusmidi_callback;
-
-/* Here is the parameter structure per a device. */
-struct gusmidi_softc {
- device_t dev; /* device information */
- mididev_info *devinfo; /* midi device information */
-
- struct mtx mtx; /* Mutex to protect the device. */
-
- struct resource *io; /* Base of io port */
- int io_rid; /* Io resource ID */
- struct resource *irq; /* Irq */
- int irq_rid; /* Irq resource ID */
- void *ih; /* Interrupt cookie */
-
- int ctl; /* Control bits. */
-};
-
-typedef struct gusmidi_softc *sc_p;
-
-/* These functions are local. */
-static int gusmidi_init(device_t dev);
-static int gusmidi_allocres(sc_p scp, device_t dev);
-static void gusmidi_releaseres(sc_p scp, device_t dev);
-static void gusmidi_startplay(sc_p scp);
-static void gusmidi_xmit(sc_p scp);
-static u_int gusmidi_readport(sc_p scp, int off);
-static void gusmidi_writeport(sc_p scp, int off, u_int8_t value);
-
-/*
- * This is the device descriptor for the midi device.
- */
-static mididev_info gusmidi_op_desc = {
- "GUS midi",
-
- SNDCARD_GUS,
-
- gusmidi_open,
- NULL,
- gusmidi_ioctl,
-
- gusmidi_callback,
-
- MIDI_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-static int
-gusmidi_probe(device_t dev)
-{
- char *s;
- sc_p scp;
- struct sndcard_func *func;
-
- /* The parent device has already been probed. */
-
- func = device_get_ivars(dev);
- if (func == NULL || func->func != SCF_MIDI)
- return (ENXIO);
-
- s = "GUS Midi Interface";
-
- scp = device_get_softc(dev);
- bzero(scp, sizeof(*scp));
- scp->io_rid = 1;
- scp->irq_rid = 0;
-#if notdef
- ret = mpu_probe2(dev);
- if (ret != 0)
- return (ret);
-#endif /* notdef */
- device_set_desc(dev, s);
- return (0);
-}
-
-static int
-gusmidi_attach(device_t dev)
-{
- sc_p scp;
-
- scp = device_get_softc(dev);
-
- /* Allocate the resources, switch to uart mode. */
- if (gusmidi_allocres(scp, dev)) {
- gusmidi_releaseres(scp, dev);
- return (ENXIO);
- }
-
- gusmidi_init(dev);
-
- return (0);
-}
-
-static int
-gusmidi_init(device_t dev)
-{
- sc_p scp;
- mididev_info *devinfo;
-
- scp = device_get_softc(dev);
-
- /* Fill the softc. */
- scp->dev = dev;
- mtx_init(&scp->mtx, "gusmid", NULL, MTX_DEF);
- scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &gusmidi_op_desc, &midisynth_op_desc);
-
- /* Fill the midi info. */
- if (scp->irq != NULL)
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x irq %d",
- (u_int)rman_get_start(scp->io), (int)rman_get_start(scp->irq));
- else
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x",
- (u_int)rman_get_start(scp->io));
-
- midiinit(devinfo, dev);
-
- bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, gusmidi_intr, scp,
- &scp->ih);
-
- return (0);
-}
-
-static int
-gusmidi_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
-
- unit = MIDIUNIT(i_dev);
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("gusmidi_open: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- mtx_lock(&scp->mtx);
-
- gusmidi_writeport(scp, PORT_CTL, MIDICTL_MASTER_RESET);
- DELAY(100);
-
- gusmidi_writeport(scp, PORT_CTL, scp->ctl);
-
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-static int
-gusmidi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("gusmidi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("gusmidi_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- switch (cmd) {
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- if (synthinfo->device != unit)
- return (ENXIO);
- bcopy(&gusmidi_synthinfo, synthinfo, sizeof(gusmidi_synthinfo));
- synthinfo->device = unit;
- return (0);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- if (midiinfo->device != unit)
- return (ENXIO);
- bcopy(&gusmidi_midiinfo, midiinfo, sizeof(gusmidi_midiinfo));
- midiinfo->device = unit;
- return (0);
- break;
- default:
- return (ENOSYS);
- }
- /* NOTREACHED */
- return (EINVAL);
-}
-
-void
-gusmidi_intr(void *arg)
-{
- sc_p scp;
- u_char c;
- mididev_info *devinfo;
- int stat, did_something, leni;
-
- scp = (sc_p)arg;
- devinfo = scp->devinfo;
-
- /* XXX No framing/overrun checks... */
- mtx_lock(&devinfo->flagqueue_mtx);
- mtx_lock(&scp->mtx);
-
- do {
- stat = gusmidi_readport(scp, PORT_ST);
- did_something = 0;
- if (stat & MIDIST_RXFULL) {
- c = gusmidi_readport(scp, PORT_RX);
- mtx_unlock(&scp->mtx);
- if ((devinfo->flags & MIDI_F_PASSTHRU) &&
- (!(devinfo->flags & MIDI_F_BUSY) ||
- !(devinfo->fflags & FWRITE))) {
- midibuf_input_intr(&devinfo->midi_dbuf_passthru,
- &c, sizeof c, &leni);
- devinfo->callback(devinfo,
- MIDI_CB_START | MIDI_CB_WR);
- }
- if ((devinfo->flags & MIDI_F_READING) && c != 0xfe) {
- midibuf_input_intr(&devinfo->midi_dbuf_in,
- &c, sizeof c, &leni);
- }
- did_something = 1;
- } else
- mtx_unlock(&scp->mtx);
- if (stat & MIDIST_TXDONE) {
- if (devinfo->flags & MIDI_F_WRITING) {
- gusmidi_xmit(scp);
- did_something = 1;
- mtx_lock(&scp->mtx);
- } else if (scp->ctl & MIDICTL_TX_IRQ_EN) {
- /* This shouldn't happen. */
- mtx_lock(&scp->mtx);
- scp->ctl &= ~MIDICTL_TX_IRQ_EN;
- gusmidi_writeport(scp, PORT_CTL, scp->ctl);
- }
- } else
- mtx_lock(&scp->mtx);
- } while (did_something != 0);
-
- mtx_unlock(&scp->mtx);
- mtx_unlock(&devinfo->flagqueue_mtx);
-
- /* Invoke the upper layer. */
- midi_intr(devinfo);
-}
-
-static int
-gusmidi_callback(void *di, int reason)
-{
- int unit;
- sc_p scp;
- mididev_info *d;
-
- d = (mididev_info *)di;
-
- mtx_assert(&d->flagqueue_mtx, MA_OWNED);
-
- if (d == NULL) {
- MIDI_DEBUG(printf("gusmidi_callback: device not configured.\n"));
- return (ENXIO);
- }
-
- unit = d->unit;
- scp = d->softc;
-
- switch (reason & MIDI_CB_REASON_MASK) {
- case MIDI_CB_START:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0) {
- /* Begin recording. */
- d->flags |= MIDI_F_READING;
- mtx_lock(&scp->mtx);
- scp->ctl |= MIDICTL_RX_IRQ_EN;
- gusmidi_writeport(scp, PORT_CTL, scp->ctl);
- mtx_unlock(&scp->mtx);
- }
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0)
- /* Start playing. */
- gusmidi_startplay(scp);
- break;
- case MIDI_CB_STOP:
- case MIDI_CB_ABORT:
- mtx_lock(&scp->mtx);
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0) {
- /* Stop recording. */
- d->flags &= ~MIDI_F_READING;
- scp->ctl &= ~MIDICTL_RX_IRQ_EN;
- }
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0) {
- /* Stop Playing. */
- d->flags &= ~MIDI_F_WRITING;
- scp->ctl &= ~MIDICTL_TX_IRQ_EN;
- }
- gusmidi_writeport(scp, PORT_CTL, scp->ctl);
- mtx_unlock(&scp->mtx);
- break;
- }
-
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-/*
- * Starts to play the data in the output queue.
- */
-static void
-gusmidi_startplay(sc_p scp)
-{
- mididev_info *devinfo;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* Can we play now? */
- if (devinfo->midi_dbuf_out.rl == 0)
- return;
-
- devinfo->flags |= MIDI_F_WRITING;
- mtx_lock(&scp->mtx);
- scp->ctl |= MIDICTL_TX_IRQ_EN;
- mtx_unlock(&scp->mtx);
-}
-
-static void
-gusmidi_xmit(sc_p scp)
-{
- register mididev_info *devinfo;
- register midi_dbuf *dbuf;
- u_char c;
- int leno;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* See which source to use. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0))
- dbuf = &devinfo->midi_dbuf_out;
- else
- dbuf = &devinfo->midi_dbuf_passthru;
-
- /* Transmit the data in the queue. */
- while (devinfo->flags & MIDI_F_WRITING) {
- /* Do we have the data to transmit? */
- if (dbuf->rl == 0) {
- /* Stop playing. */
- devinfo->flags &= ~MIDI_F_WRITING;
- mtx_lock(&scp->mtx);
- scp->ctl &= ~MIDICTL_TX_IRQ_EN;
- gusmidi_writeport(scp, PORT_CTL, scp->ctl);
- mtx_unlock(&scp->mtx);
- break;
- } else {
- mtx_lock(&scp->mtx);
- if (gusmidi_readport(scp, PORT_ST) & MIDIST_TXDONE) {
- /* Send the data. */
- midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
- gusmidi_writeport(scp, PORT_TX, c);
- /* We are playing now. */
- } else {
- mtx_unlock(&scp->mtx);
- break;
- }
- mtx_unlock(&scp->mtx);
- }
- }
-}
-
-/* Reads from a port. */
-static u_int
-gusmidi_readport(sc_p scp, int off)
-{
- return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off) & 0xff;
-}
-
-/* Writes to a port. */
-static void
-gusmidi_writeport(sc_p scp, int off, u_int8_t value)
-{
- bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off, value);
-}
-
-/* Allocates resources. */
-static int
-gusmidi_allocres(sc_p scp, device_t dev)
-{
- if (scp->io == NULL) {
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT,
- &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
- if (scp->io == NULL)
- return (1);
- }
-#if notdef
- if (scp->irq == NULL && !(device_get_flags(dev) & MPU_DF_NO_IRQ)) {
-#else
- if (scp->irq == NULL) {
-#endif /* notdef */
- scp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &scp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
- if (scp->irq == NULL)
- return (1);
- }
-
- return (0);
-}
-
-/* Releases resources. */
-static void
-gusmidi_releaseres(sc_p scp, device_t dev)
-{
- if (scp->irq != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
- scp->irq = NULL;
- }
- if (scp->io != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, scp->io);
- scp->io = NULL;
- }
-}
-
-static device_method_t gusmidi_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , gusmidi_probe ),
- DEVMETHOD(device_attach, gusmidi_attach),
-
- { 0, 0 },
-};
-
-driver_t gusmidi_driver = {
- "midi",
- gusmidi_methods,
- sizeof(struct gusmidi_softc),
-};
-
-DRIVER_MODULE(gusmidi, gusc, gusmidi_driver, midi_devclass, 0, 0);
diff --git a/sys/dev/sound/isa/mpu.c b/sys/dev/sound/isa/mpu.c
deleted file mode 100644
index 3f259a76ecc2..000000000000
--- a/sys/dev/sound/isa/mpu.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * The low level driver for Roland MPU-401 compatible Midi interfaces.
- *
- * Copyright by Hannu Savolainen 1993
- *
- * 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.
- *
- * Modified: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
- * initialization routine.
- *
- * Ported to the new Audio Driver by Luigi Rizzo:
- * (C) 1999 Seigo Tanimura
- *
- * This is the MPU401 midi interface driver for FreeBSD, based on the Luigi Sound Driver.
- * This handles io against /dev/midi, the midi {in, out}put event queues
- * and the event/message transmittion to/from an MPU401 interface.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-#include <dev/sound/chip.h>
-#include <machine/cpufunc.h>
-
-#include <isa/isavar.h>
-#include <dev/ic/ns16550.h>
-
-static devclass_t midi_devclass;
-
-#ifndef DDB
-#undef DDB
-#define DDB(x)
-#endif /* DDB */
-
-#define MPU_DATAPORT 0
-#define MPU_CMDPORT 1
-#define MPU_STATPORT 1
-
-#define MPU_RESET 0xff
-#define MPU_UART 0x3f
-#define MPU_ACK 0xfe
-
-#define MPU_STATMASK 0xc0
-#define MPU_OUTPUTBUSY 0x40
-#define MPU_INPUTBUSY 0x80
-
-#define MPU_TRYDATA 50
-#define MPU_DELAY 25000
-
-/* Device flag. */
-#define MPU_DF_NO_IRQ 1
-
-extern synthdev_info midisynth_op_desc;
-
-/* PnP IDs */
-static struct isa_pnp_id mpu_ids[] = {
- {0x01200001, "@H@2001 Midi Interface"}, /* @H@2001 */
- {0x01100001, "@H@1001 Midi Interface"}, /* @H@1001 */
-#if notdef
- /* TODO: write bridge driver for these devices */
- {0x0000630e, "CSC0000 Midi Interface"}, /* CSC0000 */
- {0x2100a865, "YMH0021 Midi Interface"}, /* YMH0021 */
- {0x80719304, "ADS7180 Midi Interface"}, /* ADS7180 */
- {0x0300561e, "GRV0003 Midi Interface"}, /* GRV0003 */
-#endif
-};
-
-/* These are the synthesizer and the midi interface information. */
-static struct synth_info mpu_synthinfo = {
- "MPU401 MIDI",
- 0,
- SYNTH_TYPE_MIDI,
- 0,
- 0,
- 128,
- 128,
- 128,
- SYNTH_CAP_INPUT,
-};
-
-static struct midi_info mpu_midiinfo = {
- "MPU401 MIDI",
- 0,
- 0,
- 0,
-};
-
-/*
- * These functions goes into mpu_op_desc to get called
- * from sound.c.
- */
-
-static int mpu_probe(device_t dev);
-static int mpu_probe1(device_t dev);
-static int mpu_probe2(device_t dev);
-static int mpu_attach(device_t dev);
-static int mpusbc_probe(device_t dev);
-static int mpusbc_attach(device_t dev);
-
-static d_ioctl_t mpu_ioctl;
-static driver_intr_t mpu_intr;
-static midi_callback_t mpu_callback;
-
-/* Here is the parameter structure per a device. */
-struct mpu_softc {
- device_t dev; /* device information */
- mididev_info *devinfo; /* midi device information */
-
- struct mtx mtx; /* Mutex to protect the device. */
-
- struct resource *io; /* Base of io port */
- int io_rid; /* Io resource ID */
- u_long irq_val; /* Irq value */
- struct resource *irq; /* Irq */
- int irq_rid; /* Irq resource ID */
- void *ih; /* Interrupt cookie */
-
- int fflags; /* File flags */
-};
-
-typedef struct mpu_softc *sc_p;
-
-/* These functions are local. */
-static void mpu_startplay(sc_p scp);
-static void mpu_xmit(sc_p scp);
-static int mpu_resetmode(sc_p scp);
-static int mpu_uartmode(sc_p scp);
-static int mpu_waitack(sc_p scp);
-static int mpu_status(sc_p scp);
-static int mpu_command(sc_p scp, u_int8_t value);
-static int mpu_readdata(sc_p scp, u_int8_t *value);
-static int mpu_writedata(sc_p scp, u_int8_t value);
-static u_int mpu_readport(sc_p scp, int off);
-static void mpu_writeport(sc_p scp, int off, u_int8_t value);
-static int mpu_allocres(sc_p scp, device_t dev);
-static void mpu_releaseres(sc_p scp, device_t dev);
-
-/*
- * This is the device descriptor for the midi device.
- */
-static mididev_info mpu_op_desc = {
- "MPU401 midi",
-
- SNDCARD_MPU401,
-
- NULL,
- NULL,
- mpu_ioctl,
-
- mpu_callback,
-
- MIDI_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-/*
- * Here are the main functions to interact to the user process.
- */
-
-static int
-mpu_probe(device_t dev)
-{
- sc_p scp;
- int ret;
-
- /* Check isapnp ids */
- if (isa_get_logicalid(dev) != 0)
- return (ISA_PNP_PROBE(device_get_parent(dev), dev, mpu_ids));
-
- scp = device_get_softc(dev);
-
- device_set_desc(dev, mpu_op_desc.name);
- bzero(scp, sizeof(*scp));
-
- scp->io_rid = 0;
- ret = mpu_probe1(dev);
- if (ret != 0)
- return (ret);
- ret = mpu_probe2(dev);
- if (ret != 0)
- return (ret);
-
- return (0);
-}
-
-/*
- * Make sure this is an MPU401, not an 16550 uart.
- * Called only for non-pnp devices.
- */
-static int
-mpu_probe1(device_t dev)
-{
- sc_p scp;
- int iir;
- struct resource *io;
-
- scp = device_get_softc(dev);
-
- /*
- * If an MPU401 is ready to both input and output,
- * the status register value is zero, which may
- * confuse an 16550 uart to probe as an MPU401.
- * We read the IIR (base + 2), which is not used
- * by an MPU401.
- */
- io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 3, RF_ACTIVE);
- iir = bus_space_read_1(rman_get_bustag(io), rman_get_bushandle(io), com_iir) & 0xff;
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, io);
- if ((iir & ~(IIR_IMASK | IIR_FIFO_MASK)) == 0)
- /* Likely to be an 16550. */
- return (ENXIO);
-
- return (0);
-}
-
-/* Look up the irq. */
-static int
-mpu_probe2(device_t dev)
-{
- sc_p scp;
- int unit, i;
- intrmask_t irqp0, irqp1;
-
- scp = device_get_softc(dev);
- unit = device_get_unit(dev);
-
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
- if (scp->io == NULL)
- return (ENXIO);
-
- MIDI_DEBUG(printf("mpu%d: probing.\n", unit));
-
- /* Reset the interface. */
- if (mpu_resetmode(scp) != 0 || mpu_waitack(scp) != 0) {
- printf("mpu%d: reset failed.\n", unit);
- mpu_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /*
- * At this point, we are likely to have an interface.
- *
- * Switching the interface to uart mode gives us an interrupt.
- * We can make use of it to determine the irq.
- * Idea-stolen-from: sys/isa/sio.c:sioprobe()
- */
-
- critical_enter();
-
- /*
- * See the initial irq. We have to do this now,
- * otherwise a midi module/instrument might send
- * an active sensing, to mess up the irq.
- */
- irqp0 = isa_irq_pending();
- irqp1 = 0;
-
- /* Switch to uart mode. */
- if (mpu_uartmode(scp) != 0) {
- critical_exit();
- printf("mpu%d: mode switching failed.\n", unit);
- mpu_releaseres(scp, dev);
- return (ENXIO);
- }
-
- if (device_get_flags(dev) & MPU_DF_NO_IRQ) {
- irqp0 = irqp1 = 0;
- goto no_irq;
- }
-
- /* See which irq we have now. */
- for (i = 0 ; i < MPU_TRYDATA ; i++) {
- DELAY(MPU_DELAY);
- irqp1 = isa_irq_pending();
- if (irqp1 != irqp0)
- break;
- }
- if (irqp1 == irqp0) {
- critical_exit();
- printf("mpu%d: switching the mode gave no interrupt.\n", unit);
- mpu_releaseres(scp, dev);
- return (ENXIO);
- }
-
-no_irq:
- /* Wait to see an ACK. */
- if (mpu_waitack(scp) != 0) {
- critical_exit();
- printf("mpu%d: not acked.\n", unit);
- mpu_releaseres(scp, dev);
- return (ENXIO);
- }
-
- critical_exit();
-
- if (device_get_flags(dev) & MPU_DF_NO_IRQ)
- scp->irq_val = 0;
- else
- /* We have found the irq. */
- scp->irq_val = ffs(~irqp0 & irqp1) - 1;
-
- MIDI_DEBUG(printf("mpu%d: probed.\n", unit));
-
- return (0);
-}
-
-static int
-mpusbc_probe(device_t dev)
-{
- char *s;
- sc_p scp;
- struct sndcard_func *func;
-
- /* The parent device has already been probed. */
-
- func = device_get_ivars(dev);
- if (func == NULL || func->func != SCF_MIDI)
- return (ENXIO);
-
- s = "SB Midi Interface";
-
- scp = device_get_softc(dev);
- bzero(scp, sizeof(*scp));
- scp->io_rid = 1;
- scp->irq_rid = 0;
- device_set_desc(dev, s);
- return (0);
-}
-
-static int
-mpu_attach(device_t dev)
-{
- sc_p scp;
- mididev_info *devinfo;
-
- scp = device_get_softc(dev);
-
- MIDI_DEBUG(printf("mpu: attaching.\n"));
-
- mtx_init(&scp->mtx, "mpumid", NULL, MTX_DEF);
-
- /* Allocate the resources, switch to uart mode. */
- if (mpu_allocres(scp, dev) || mpu_uartmode(scp)) {
- mpu_releaseres(scp, dev);
- mtx_destroy(&scp->mtx);
- return (ENXIO);
- }
-
- /* mpu_probe() has put the interface to uart mode. */
-
- /* Fill the softc. */
- scp->dev = dev;
- scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &mpu_op_desc, &midisynth_op_desc);
-
- /* Fill the midi info. */
- if (scp->irq != NULL)
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x irq %d",
- (u_int)rman_get_start(scp->io), (int)rman_get_start(scp->irq));
- else
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x",
- (u_int)rman_get_start(scp->io));
-
- midiinit(devinfo, dev);
-
- /* Now we can handle the interrupts. */
- if (scp->irq != NULL)
- bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, mpu_intr, scp,
- &scp->ih);
-
- MIDI_DEBUG(printf("mpu: attached.\n"));
-
- return (0);
-}
-
-static int
-mpusbc_attach(device_t dev)
-{
- sc_p scp;
- int unit;
-
- scp = device_get_softc(dev);
- unit = device_get_unit(dev);
-
- mpu_attach(dev);
-
- return (0);
-}
-
-static int
-mpu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("mpu_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("mpu_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- switch (cmd) {
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- if (synthinfo->device != unit)
- return (ENXIO);
- bcopy(&mpu_synthinfo, synthinfo, sizeof(mpu_synthinfo));
- synthinfo->device = unit;
- return (0);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- if (midiinfo->device != unit)
- return (ENXIO);
- bcopy(&mpu_midiinfo, midiinfo, sizeof(mpu_midiinfo));
- midiinfo->device = unit;
- return (0);
- break;
- default:
- return (ENOSYS);
- }
- /* NOTREACHED */
- return (EINVAL);
-}
-
-static void
-mpu_intr(void *arg)
-{
- sc_p scp;
- u_char c;
- mididev_info *devinfo;
- int leni;
-
- scp = (sc_p)arg;
- devinfo = scp->devinfo;
-
- mtx_lock(&devinfo->flagqueue_mtx);
- mtx_lock(&scp->mtx);
-
- /* Read the received data. */
- while ((mpu_status(scp) & MPU_INPUTBUSY) == 0) {
- /* Receive the data. */
- mpu_readdata(scp, &c);
- mtx_unlock(&scp->mtx);
- /* Queue into the passthru buffer and start transmitting if we can. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
- midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni);
- devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR);
- }
- /* Queue if we are reading. Discard an active sensing. */
- if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) {
- midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni);
- }
- mtx_lock(&scp->mtx);
- }
- mtx_unlock(&scp->mtx);
- mtx_unlock(&devinfo->flagqueue_mtx);
-
- /* Invoke the upper layer. */
- midi_intr(devinfo);
-}
-
-static int
-mpu_callback(void *di, int reason)
-{
- int unit;
- sc_p scp;
- mididev_info *d;
-
- d = (mididev_info *)di;
-
- mtx_assert(&d->flagqueue_mtx, MA_OWNED);
-
- if (d == NULL) {
- MIDI_DEBUG(printf("mpu_callback: device not configured.\n"));
- return (ENXIO);
- }
-
- unit = d->unit;
- scp = d->softc;
-
- switch (reason & MIDI_CB_REASON_MASK) {
- case MIDI_CB_START:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0)
- /* Begin recording. */
- d->flags |= MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0)
- /* Start playing. */
- mpu_startplay(scp);
- break;
- case MIDI_CB_STOP:
- case MIDI_CB_ABORT:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0)
- /* Stop recording. */
- d->flags &= ~MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0)
- /* Stop Playing. */
- d->flags &= ~MIDI_F_WRITING;
- break;
- }
-
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-/*
- * Starts to play the data in the output queue.
- */
-static void
-mpu_startplay(sc_p scp)
-{
- mididev_info *devinfo;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* Can we play now? */
- if (devinfo->midi_dbuf_out.rl == 0)
- return;
-
- devinfo->flags |= MIDI_F_WRITING;
- mpu_xmit(scp);
-}
-
-static void
-mpu_xmit(sc_p scp)
-{
- register mididev_info *devinfo;
- register midi_dbuf *dbuf;
- u_char c;
- int leno;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* See which source to use. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0))
- dbuf = &devinfo->midi_dbuf_out;
- else
- dbuf = &devinfo->midi_dbuf_passthru;
-
- /* Transmit the data in the queue. */
- while ((devinfo->flags & MIDI_F_WRITING) != 0) {
- if (dbuf->rl == 0)
- break;
- else {
- mtx_lock(&scp->mtx);
- /* XXX Wait until we can write the data. */
- if ((mpu_status(scp) & MPU_OUTPUTBUSY) == 0) {
- /* Send the data. */
- midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
- mpu_writedata(scp, c);
- /* We are playing now. */
- devinfo->flags |= MIDI_F_WRITING;
- }
- mtx_unlock(&scp->mtx);
- }
- }
- /* Stop playing. */
- devinfo->flags &= ~MIDI_F_WRITING;
-}
-
-
-/*
- * Reset mpu.
- * The caller must lock scp->mtx before calling this function if needed.
- */
-static int
-mpu_resetmode(sc_p scp)
-{
- int i, resp;
-
- /* Reset the mpu. */
- resp = 0;
- for (i = 0 ; i < MPU_TRYDATA ; i++) {
- resp = mpu_command(scp, MPU_RESET);
- if (resp == 0)
- break;
- }
- if (resp != 0)
- return (1);
-
- DELAY(MPU_DELAY);
- return (0);
-}
-
-/*
- * Switch to uart mode.
- * The caller must lock scp->mtx before calling this function if needed.
- */
-static int
-mpu_uartmode(sc_p scp)
-{
- int i, resp;
-
- /* Switch to uart mode. */
- resp = 0;
- for (i = 0 ; i < MPU_TRYDATA ; i++) {
- resp = mpu_command(scp, MPU_UART);
- if (resp == 0)
- break;
- }
- if (resp != 0)
- return (1);
-
- DELAY(MPU_DELAY);
- return (0);
-}
-
-/*
- * Wait to see an ACK.
- * The caller must lock scp->mtx before calling this function if needed.
- */
-static int
-mpu_waitack(sc_p scp)
-{
- int i;
- u_int8_t resp;
-
- resp = 0;
- for (i = 0 ; i < MPU_TRYDATA ; i++) {
- if (mpu_readdata(scp, &resp) == 0)
- break;
- }
- if (resp != MPU_ACK)
- return (1);
-
- DELAY(MPU_DELAY);
- return (0);
-}
-
-/* Reads the status. */
-static int
-mpu_status(sc_p scp)
-{
- return mpu_readport(scp, MPU_STATPORT);
-}
-
-/* Writes a command. */
-static int
-mpu_command(sc_p scp, u_int8_t value)
-{
- u_int status;
-
- /* Is the interface ready to write? */
- status = mpu_status(scp);
- if ((status & MPU_OUTPUTBUSY) != 0)
- /* The interface is busy. */
- return (EAGAIN);
-
- mpu_writeport(scp, MPU_CMDPORT, value);
-
- return (0);
-}
-
-/* Reads a byte of data. */
-static int
-mpu_readdata(sc_p scp, u_int8_t *value)
-{
- u_int status;
-
- if (value == NULL)
- return (EINVAL);
-
- /* Is the interface ready to write? */
- status = mpu_status(scp);
- if ((status & MPU_INPUTBUSY) != 0)
- /* The interface is busy. */
- return (EAGAIN);
-
- *value = (u_int8_t)(mpu_readport(scp, MPU_DATAPORT) & 0xff);
-
- return (0);
-}
-
-/* Writes a byte of data. */
-static int
-mpu_writedata(sc_p scp, u_int8_t value)
-{
- u_int status;
-
- /* Is the interface ready to write? */
- status = mpu_status(scp);
- if ((status & MPU_OUTPUTBUSY) != 0)
- /* The interface is busy. */
- return (EAGAIN);
-
- mpu_writeport(scp, MPU_DATAPORT, value);
-
- return (0);
-}
-
-/* Reads from a port. */
-static u_int
-mpu_readport(sc_p scp, int off)
-{
- return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off) & 0xff;
-}
-
-/* Writes to a port. */
-static void
-mpu_writeport(sc_p scp, int off, u_int8_t value)
-{
- bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off, value);
-}
-
-/* Allocates resources. */
-static int
-mpu_allocres(sc_p scp, device_t dev)
-{
- if (scp->io == NULL) {
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
- if (scp->io == NULL)
- return (1);
- }
- if (scp->irq == NULL && !(device_get_flags(dev) & MPU_DF_NO_IRQ)) {
- if (scp->irq_val == 0)
- scp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &scp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
- else
- scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &scp->irq_rid, scp->irq_val, scp->irq_val, 1, RF_ACTIVE | RF_SHAREABLE);
- if (scp->irq == NULL)
- return (1);
- }
-
- return (0);
-}
-
-/* Releases resources. */
-static void
-mpu_releaseres(sc_p scp, device_t dev)
-{
- if (scp->irq != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
- scp->irq = NULL;
- }
- if (scp->io != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, scp->io);
- scp->io = NULL;
- }
-}
-
-static device_method_t mpu_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , mpu_probe ),
- DEVMETHOD(device_attach, mpu_attach),
-
- { 0, 0 },
-};
-
-static driver_t mpu_driver = {
- "midi",
- mpu_methods,
- sizeof(struct mpu_softc),
-};
-
-DRIVER_MODULE(mpu, isa, mpu_driver, midi_devclass, 0, 0);
-
-static device_method_t mpusbc_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , mpusbc_probe ),
- DEVMETHOD(device_attach, mpusbc_attach),
-
- { 0, 0 },
-};
-
-static driver_t mpusbc_driver = {
- "midi",
- mpusbc_methods,
- sizeof(struct mpu_softc),
-};
-
-DRIVER_MODULE(mpusbc, sbc, mpusbc_driver, midi_devclass, 0, 0);
diff --git a/sys/dev/sound/isa/opl.c b/sys/dev/sound/isa/opl.c
deleted file mode 100644
index 21eb4530cc9d..000000000000
--- a/sys/dev/sound/isa/opl.c
+++ /dev/null
@@ -1,1885 +0,0 @@
-/*
- * A low level driver for Yamaha YM3812 and OPL-3 -chips
- *
- * Copyright by Hannu Savolainen 1993
- *
- * 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.
- *
- */
-
-/*
- * Major improvements to the FM handling 30AUG92 by Rob Hooft,
- */
-/*
- * hooft@chem.ruu.nl
- */
-/*
- *
- * Ported to the new Audio Driver by Luigi Rizzo:
- * (C) 1999 Seigo Tanimura
- *
- * This is the OPL2/3/4 chip driver for FreeBSD, based on the Luigi Sound Driver.
- * This handles io against /dev/midi, the midi {in, out}put event queues
- * and the event/message operation to the OPL chip.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-#include <dev/sound/chip.h>
-
-#include <isa/isavar.h>
-
-static devclass_t midi_devclass;
-
-#ifndef DDB
-#undef DDB
-#define DDB(x)
-#endif /* DDB */
-
-/*
- * The OPL-3 mode is switched on by writing 0x01, to the offset 5
- * of the right side.
- *
- * Another special register at the right side is at offset 4. It contains
- * a bit mask defining which voices are used as 4 OP voices.
- *
- * The percussive mode is implemented in the left side only.
- *
- * With the above exeptions the both sides can be operated independently.
- *
- * A 4 OP voice can be created by setting the corresponding
- * bit at offset 4 of the right side.
- *
- * For example setting the rightmost bit (0x01) changes the
- * first voice on the right side to the 4 OP mode. The fourth
- * voice is made inaccessible.
- *
- * If a voice is set to the 2 OP mode, it works like 2 OP modes
- * of the original YM3812 (AdLib). In addition the voice can
- * be connected the left, right or both stereo channels. It can
- * even be left unconnected. This works with 4 OP voices also.
- *
- * The stereo connection bits are located in the FEEDBACK_CONNECTION
- * register of the voice (0xC0-0xC8). In 4 OP voices these bits are
- * in the second half of the voice.
- */
-
-/*
- * Register numbers for the global registers
- */
-
-#define TEST_REGISTER 0x01
-#define ENABLE_WAVE_SELECT 0x20
-
-#define TIMER1_REGISTER 0x02
-#define TIMER2_REGISTER 0x03
-#define TIMER_CONTROL_REGISTER 0x04 /* Left side */
-#define IRQ_RESET 0x80
-#define TIMER1_MASK 0x40
-#define TIMER2_MASK 0x20
-#define TIMER1_START 0x01
-#define TIMER2_START 0x02
-
-#define CONNECTION_SELECT_REGISTER 0x04 /* Right side */
-#define RIGHT_4OP_0 0x01
-#define RIGHT_4OP_1 0x02
-#define RIGHT_4OP_2 0x04
-#define LEFT_4OP_0 0x08
-#define LEFT_4OP_1 0x10
-#define LEFT_4OP_2 0x20
-
-#define OPL3_MODE_REGISTER 0x05 /* Right side */
-#define OPL3_ENABLE 0x01
-#define OPL4_ENABLE 0x02
-
-#define KBD_SPLIT_REGISTER 0x08 /* Left side */
-#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */
-#define KEYBOARD_SPLIT 0x40
-
-#define PERCUSSION_REGISTER 0xbd /* Left side only */
-#define TREMOLO_DEPTH 0x80
-#define VIBRATO_DEPTH 0x40
-#define PERCUSSION_ENABLE 0x20
-#define BASSDRUM_ON 0x10
-#define SNAREDRUM_ON 0x08
-#define TOMTOM_ON 0x04
-#define CYMBAL_ON 0x02
-#define HIHAT_ON 0x01
-
-/*
- * Offsets to the register banks for operators. To get the
- * register number just add the operator offset to the bank offset
- *
- * AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
- */
-#define AM_VIB 0x20
-#define TREMOLO_ON 0x80
-#define VIBRATO_ON 0x40
-#define SUSTAIN_ON 0x20
-#define KSR 0x10 /* Key scaling rate */
-#define MULTIPLE_MASK 0x0f /* Frequency multiplier */
-
-/*
- * KSL/Total level (0x40 to 0x55)
- */
-#define KSL_LEVEL 0x40
-#define KSL_MASK 0xc0 /* Envelope scaling bits */
-#define TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */
-
-/*
- * Attack / Decay rate (0x60 to 0x75)
- */
-#define ATTACK_DECAY 0x60
-#define ATTACK_MASK 0xf0
-#define DECAY_MASK 0x0f
-
-/*
- * Sustain level / Release rate (0x80 to 0x95)
- */
-#define SUSTAIN_RELEASE 0x80
-#define SUSTAIN_MASK 0xf0
-#define RELEASE_MASK 0x0f
-
-/*
- * Wave select (0xE0 to 0xF5)
- */
-#define WAVE_SELECT 0xe0
-
-/*
- * Offsets to the register banks for voices. Just add to the
- * voice number to get the register number.
- *
- * F-Number low bits (0xA0 to 0xA8).
- */
-#define FNUM_LOW 0xa0
-
-/*
- * F-number high bits / Key on / Block (octave) (0xB0 to 0xB8)
- */
-#define KEYON_BLOCK 0xb0
-#define KEYON_BIT 0x20
-#define BLOCKNUM_MASK 0x1c
-#define FNUM_HIGH_MASK 0x03
-
-/*
- * Feedback / Connection (0xc0 to 0xc8)
- *
- * These registers have two new bits when the OPL-3 mode
- * is selected. These bits controls connecting the voice
- * to the stereo channels. For 4 OP voices this bit is
- * defined in the second half of the voice (add 3 to the
- * register offset).
- *
- * For 4 OP voices the connection bit is used in the
- * both halfs (gives 4 ways to connect the operators).
- */
-#define FEEDBACK_CONNECTION 0xc0
-#define FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */
-#define CONNECTION_BIT 0x01
-/*
- * In the 4 OP mode there is four possible configurations how the
- * operators can be connected together (in 2 OP modes there is just
- * AM or FM). The 4 OP connection mode is defined by the rightmost
- * bit of the FEEDBACK_CONNECTION (0xC0-0xC8) on the both halfs.
- *
- * First half Second half Mode
- *
- * +---+
- * v |
- * 0 0 >+-1-+--2--3--4-->
- *
- *
- *
- * +---+
- * | |
- * 0 1 >+-1-+--2-+
- * |->
- * >--3----4-+
- *
- * +---+
- * | |
- * 1 0 >+-1-+-----+
- * |->
- * >--2--3--4-+
- *
- * +---+
- * | |
- * 1 1 >+-1-+--+
- * |
- * >--2--3-+->
- * |
- * >--4----+
- */
-#define STEREO_BITS 0x30 /* OPL-3 only */
-#define VOICE_TO_LEFT 0x10
-#define VOICE_TO_RIGHT 0x20
-
-/*
- * Definition table for the physical voices
- */
-
-struct physical_voice_info {
- unsigned char voice_num;
- unsigned char voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
- int ch; /* channel (left=USE_LEFT, right=USE_RIGHT) */
- unsigned char op[4]; /* Operator offsets */
-};
-
-/*
- * There is 18 possible 2 OP voices
- * (9 in the left and 9 in the right).
- * The first OP is the modulator and 2nd is the carrier.
- *
- * The first three voices in the both sides may be connected
- * with another voice to a 4 OP voice. For example voice 0
- * can be connected with voice 3. The operators of voice 3 are
- * used as operators 3 and 4 of the new 4 OP voice.
- * In this case the 2 OP voice number 0 is the 'first half' and
- * voice 3 is the second.
- */
-
-#define USE_LEFT 0
-#define USE_RIGHT 1
-
-static struct physical_voice_info pv_map[18] =
-{
-/* No Mode Side OP1 OP2 OP3 OP4 */
-/* --------------------------------------------------- */
- { 0, 2, USE_LEFT, {0x00, 0x03, 0x08, 0x0b}},
- { 1, 2, USE_LEFT, {0x01, 0x04, 0x09, 0x0c}},
- { 2, 2, USE_LEFT, {0x02, 0x05, 0x0a, 0x0d}},
-
- { 3, 2, USE_LEFT, {0x08, 0x0b, 0x00, 0x00}},
- { 4, 2, USE_LEFT, {0x09, 0x0c, 0x00, 0x00}},
- { 5, 2, USE_LEFT, {0x0a, 0x0d, 0x00, 0x00}},
-
- { 6, 2, USE_LEFT, {0x10, 0x13, 0x00, 0x00}}, /* Used by percussive voices */
- { 7, 2, USE_LEFT, {0x11, 0x14, 0x00, 0x00}}, /* if the percussive mode */
- { 8, 2, USE_LEFT, {0x12, 0x15, 0x00, 0x00}}, /* is selected */
-
- { 0, 2, USE_RIGHT, {0x00, 0x03, 0x08, 0x0b}},
- { 1, 2, USE_RIGHT, {0x01, 0x04, 0x09, 0x0c}},
- { 2, 2, USE_RIGHT, {0x02, 0x05, 0x0a, 0x0d}},
-
- { 3, 2, USE_RIGHT, {0x08, 0x0b, 0x00, 0x00}},
- { 4, 2, USE_RIGHT, {0x09, 0x0c, 0x00, 0x00}},
- { 5, 2, USE_RIGHT, {0x0a, 0x0d, 0x00, 0x00}},
-
- { 6, 2, USE_RIGHT, {0x10, 0x13, 0x00, 0x00}},
- { 7, 2, USE_RIGHT, {0x11, 0x14, 0x00, 0x00}},
- { 8, 2, USE_RIGHT, {0x12, 0x15, 0x00, 0x00}}
-};
-
-/* These are the tuning parameters. */
-static unsigned short semitone_tuning[24] =
-{
-/* 0 */ 10000, 10595, 11225, 11892, 12599, 13348, 14142, 14983,
-/* 8 */ 15874, 16818, 17818, 18877, 20000, 21189, 22449, 23784,
-/* 16 */ 25198, 26697, 28284, 29966, 31748, 33636, 35636, 37755
-};
-
-static unsigned short cent_tuning[100] =
-{
-/* 0 */ 10000, 10006, 10012, 10017, 10023, 10029, 10035, 10041,
-/* 8 */ 10046, 10052, 10058, 10064, 10070, 10075, 10081, 10087,
-/* 16 */ 10093, 10099, 10105, 10110, 10116, 10122, 10128, 10134,
-/* 24 */ 10140, 10145, 10151, 10157, 10163, 10169, 10175, 10181,
-/* 32 */ 10187, 10192, 10198, 10204, 10210, 10216, 10222, 10228,
-/* 40 */ 10234, 10240, 10246, 10251, 10257, 10263, 10269, 10275,
-/* 48 */ 10281, 10287, 10293, 10299, 10305, 10311, 10317, 10323,
-/* 56 */ 10329, 10335, 10341, 10347, 10353, 10359, 10365, 10371,
-/* 64 */ 10377, 10383, 10389, 10395, 10401, 10407, 10413, 10419,
-/* 72 */ 10425, 10431, 10437, 10443, 10449, 10455, 10461, 10467,
-/* 80 */ 10473, 10479, 10485, 10491, 10497, 10503, 10509, 10515,
-/* 88 */ 10521, 10528, 10534, 10540, 10546, 10552, 10558, 10564,
-/* 96 */ 10570, 10576, 10582, 10589
-};
-
-/*
- * The next table looks magical, but it certainly is not. Its values have
- * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception
- * for i=0. This log-table converts a linear volume-scaling (0..127) to a
- * logarithmic scaling as present in the FM-synthesizer chips. so : Volume
- * 64 = 0 db = relative volume 0 and: Volume 32 = -6 db = relative
- * volume -8 it was implemented as a table because it is only 128 bytes and
- * it saves a lot of log() calculations. (RH)
- */
-static char opl_volumetable[128] =
-{
- -64, -48, -40, -35, -32, -29, -27, -26,
- -24, -23, -21, -20, -19, -18, -18, -17,
- -16, -15, -15, -14, -13, -13, -12, -12,
- -11, -11, -10, -10, -10, -9, -9, -8,
- -8, -8, -7, -7, -7, -6, -6, -6,
- -5, -5, -5, -5, -4, -4, -4, -4,
- -3, -3, -3, -3, -2, -2, -2, -2,
- -2, -1, -1, -1, -1, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 4,
- 4, 4, 4, 4, 4, 4, 4, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 8, 8, 8, 8, 8};
-
-#define MAX_VOICE 18
-#define OFFS_4OP 11
-#define SBFM_MAXINSTR 256
-
-/* These are the OPL Models. */
-#define MODEL_NONE 0
-#define MODEL_OPL2 2
-#define MODEL_OPL3 3
-#define MODEL_OPL4 4
-
-/* These are the OPL Voice modes. */
-#define VOICE_NONE 0
-#define VOICE_2OP 2
-#define VOICE_4OP 4
-
-/* PnP IDs */
-static struct isa_pnp_id opl_ids[] = {
- {0x01200001, "@H@2001 FM Synthesizer"}, /* @H@2001 */
- {0x01100001, "@H@1001 FM Synthesizer"}, /* @H@1001 */
-#if notdef
- /* TODO: write bridge drivers for these devices. */
- {0x0000630e, "CSC0000 FM Synthesizer"}, /* CSC0000 */
- {0x68187316, "ESS1868 FM Synthesizer"}, /* ESS1868 */
- {0x79187316, "ESS1879 FM Synthesizer"}, /* ESS1879 */
- {0x2100a865, "YMH0021 FM Synthesizer"}, /* YMH0021 */
- {0x80719304, "ADS7180 FM Synthesizer"}, /* ADS7180 */
- {0x0300561e, "GRV0003 FM Synthesizer"}, /* GRV0003 */
-#endif /* notdef */
-};
-
-/* These are the default io bases. */
-static int opl_defaultiobase[] = {
- 0x388,
- 0x380,
-};
-
-/* These are the per-voice information. */
-struct voice_info {
- u_char keyon_byte;
- long bender;
- long bender_range;
- u_long orig_freq;
- u_long current_freq;
- int volume;
- int mode;
-};
-
-/* These are the synthesizer and the midi device information. */
-static struct synth_info opl_synthinfo = {
- "OPL FM Synthesizer",
- 0,
- SYNTH_TYPE_FM,
- FM_TYPE_ADLIB,
- 0,
- 9,
- 0,
- SBFM_MAXINSTR,
- 0,
-};
-
-static struct midi_info opl_midiinfo = {
- "OPL FM Synthesizer",
- 0,
- 0,
- 0,
-};
-
-/*
- * These functions goes into oplsynthdev_op_desc.
- */
-static mdsy_killnote_t opl_killnote;
-static mdsy_setinstr_t opl_setinstr;
-static mdsy_startnote_t opl_startnote;
-static mdsy_reset_t opl_reset;
-static mdsy_hwcontrol_t opl_hwcontrol;
-static mdsy_loadpatch_t opl_loadpatch;
-static mdsy_panning_t opl_panning;
-static mdsy_aftertouch_t opl_aftertouch;
-static mdsy_controller_t opl_controller;
-static mdsy_patchmgr_t opl_patchmgr;
-static mdsy_bender_t opl_bender;
-static mdsy_allocvoice_t opl_allocvoice;
-static mdsy_setupvoice_t opl_setupvoice;
-static mdsy_sendsysex_t opl_sendsysex;
-static mdsy_prefixcmd_t opl_prefixcmd;
-static mdsy_volumemethod_t opl_volumemethod;
-
-/*
- * This is the synthdev_info for an OPL3 chip.
- */
-static synthdev_info oplsynth_op_desc = {
- opl_killnote,
- opl_setinstr,
- opl_startnote,
- opl_reset,
- opl_hwcontrol,
- opl_loadpatch,
- opl_panning,
- opl_aftertouch,
- opl_controller,
- opl_patchmgr,
- opl_bender,
- opl_allocvoice,
- opl_setupvoice,
- opl_sendsysex,
- opl_prefixcmd,
- opl_volumemethod,
-};
-
-/* Here is the parameter structure per a device. */
-struct opl_softc {
- device_t dev; /* device information */
- mididev_info *devinfo; /* midi device information */
-
- struct mtx mtx; /* Mutex to protect the device. */
-
- struct resource *io; /* Base of io port */
- int io_rid; /* Io resource ID */
-
- int model; /* OPL model */
- struct synth_info synthinfo; /* Synthesizer information */
-
- struct sbi_instrument i_map[SBFM_MAXINSTR]; /* Instrument map */
- struct sbi_instrument *act_i[SBFM_MAXINSTR]; /* Active instruments */
- struct physical_voice_info pv_map[MAX_VOICE]; /* Physical voice map */
- int cmask; /* Connection mask */
- int lv_map[MAX_VOICE]; /* Level map */
- struct voice_info voc[MAX_VOICE]; /* Voice information */
-};
-
-typedef struct opl_softc *sc_p;
-
-/*
- * These functions goes into opl_op_desc to get called
- * from sound.c.
- */
-
-static int opl_probe(device_t dev);
-static int opl_probe1(sc_p scp);
-static int opl_attach(device_t dev);
-static int oplsbc_probe(device_t dev);
-static int oplsbc_attach(device_t dev);
-
-static d_open_t opl_open;
-static d_close_t opl_close;
-static d_ioctl_t opl_ioctl;
-static midi_callback_t opl_callback;
-
-/* These go to snddev_info. */
-static mdsy_readraw_t opl_readraw;
-static mdsy_writeraw_t opl_writeraw;
-
-/* These functions are local. */
-static void opl_command(sc_p scp, int ch, int addr, u_int val);
-static int opl_status(sc_p scp);
-static void opl_enter4opmode(sc_p scp);
-static void opl_storeinstr(sc_p scp, int instr_no, struct sbi_instrument *instr);
-static void opl_calcvol(u_char *regbyte, int volume, int main_vol);
-static void opl_setvoicevolume(sc_p scp, int voice, int volume, int main_vol);
-static void opl_freqtofnum(int freq, int *block, int *fnum);
-static int opl_bendpitch(sc_p scp, int voice, int val);
-static int opl_notetofreq(int note_num);
-static u_long opl_computefinetune(u_long base_freq, int bend, int range);
-static int opl_allocres(sc_p scp, device_t dev);
-static void opl_releaseres(sc_p scp, device_t dev);
-
-/*
- * This is the device descriptor for the midi device.
- */
-static mididev_info opl_op_desc = {
- "OPL FM Synthesizer",
-
- SNDCARD_OPL,
-
- opl_open,
- opl_close,
- opl_ioctl,
-
- opl_callback,
-
- MIDI_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-/*
- * Here are the main functions to interact to the user process.
- */
-
-static int
-opl_probe(device_t dev)
-{
- sc_p scp;
- int unit, i;
-
- /* Check isapnp ids */
- if (isa_get_logicalid(dev) != 0)
- return (ISA_PNP_PROBE(device_get_parent(dev), dev, opl_ids));
-
- scp = device_get_softc(dev);
- unit = device_get_unit(dev);
-
- device_set_desc(dev, opl_op_desc.name);
- bzero(scp, sizeof(*scp));
-
- MIDI_DEBUG(printf("opl%d: probing.\n", unit));
-
- scp->io_rid = 0;
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 4, RF_ACTIVE);
- if (opl_allocres(scp, dev)) {
- /* We try the defaults in opl_defaultiobase. */
- MIDI_DEBUG(printf("opl%d: port is omitted, trying the defaults.\n", unit));
- for (i = 0 ; i < sizeof(opl_defaultiobase) / sizeof(*opl_defaultiobase) ; i++) {
- scp->io_rid = 0;
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, opl_defaultiobase[i], opl_defaultiobase[i] + 1, 4, RF_ACTIVE);
- if (scp->io != NULL) {
- if (opl_probe1(scp))
- opl_releaseres(scp, dev);
- else
- break;
- }
- }
- if (scp->io == NULL)
- return (ENXIO);
- } else if(opl_probe1(scp)) {
- opl_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* We now have some kind of OPL. */
-
- MIDI_DEBUG(printf("opl%d: probed.\n", unit));
-
- return (0);
-}
-
-/* We do probe in this function. */
-static int
-opl_probe1(sc_p scp)
-{
- u_char stat1, stat2;
-
- /* Reset the timers and the interrupt. */
- opl_command(scp, USE_LEFT, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
- opl_command(scp, USE_LEFT, TIMER_CONTROL_REGISTER, IRQ_RESET);
-
- /* Read the status. */
- stat1 = opl_status(scp);
- if ((stat1 & 0xe0) != 0)
- return (1);
-
- /* Try firing the timer1. */
- opl_command(scp, USE_LEFT, TIMER1_REGISTER, 0xff); /* Set the timer value. */
- opl_command(scp, USE_LEFT, TIMER_CONTROL_REGISTER, TIMER1_START | TIMER2_MASK); /* Start the timer. */
- DELAY(150); /* Wait for the timer. */
-
- /* Read the status. */
- stat2 = opl_status(scp);
-
- /* Reset the timers and the interrupt. */
- opl_command(scp, USE_LEFT, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
- opl_command(scp, USE_LEFT, TIMER_CONTROL_REGISTER, IRQ_RESET);
-
- if ((stat2 & 0xe0) != 0xc0)
- return (1);
-
- return (0);
-}
-
-static int
-oplsbc_probe(device_t dev)
-{
- char *s;
- sc_p scp;
- struct sndcard_func *func;
-
- /* The parent device has already been probed. */
-
- func = device_get_ivars(dev);
- if (func == NULL || func->func != SCF_SYNTH)
- return (ENXIO);
-
- s = "SB OPL FM Synthesizer";
-
- scp = device_get_softc(dev);
- bzero(scp, sizeof(*scp));
- scp->io_rid = 2;
- device_set_desc(dev, s);
- return (0);
-}
-
-static int
-opl_attach(device_t dev)
-{
- sc_p scp;
- mididev_info *devinfo;
- int i, opl4_io, opl4_id;
- struct resource *opl4;
- u_char signature, tmp;
-
- scp = device_get_softc(dev);
-
- MIDI_DEBUG(printf("opl: attaching.\n"));
-
- /* Fill the softc for this unit. */
- scp->dev = dev;
-
- /* Allocate other resources. */
- if (opl_allocres(scp, dev)) {
- opl_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* Detect the OPL type. */
- signature = opl_status(scp);
- if (signature == 0x06)
- scp->model = MODEL_OPL2;
- else {
- /* OPL3 or later, might be OPL4. */
-
- /* Enable OPL3 and OPL4. */
- opl_command(scp, USE_RIGHT, OPL3_MODE_REGISTER, 0);
- opl_command(scp, USE_RIGHT, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE);
-
- tmp = opl_status(scp);
- if (tmp != 0x02)
- scp->model = MODEL_OPL3;
-#if notdef
- else {
-#endif /* notdef */
- /* Alloc OPL4 ID register. */
- opl4_id = 2;
- opl4_io = rman_get_start(scp->io) - 8;
- opl4 = bus_alloc_resource(dev, SYS_RES_IOPORT, &opl4_id, opl4_io, opl4_io + 1, 2, RF_ACTIVE);
- if (opl4 != NULL) {
- /* Select OPL4 ID register. */
- bus_space_write_1(rman_get_bustag(opl4), rman_get_bushandle(opl4), 0, 0x02);
- DELAY(10);
- tmp = bus_space_read_1(rman_get_bustag(opl4), rman_get_bushandle(opl4), 1);
- DELAY(10);
-
- if (tmp != 0x20)
- scp->model = MODEL_OPL3;
- else {
- scp->model = MODEL_OPL4;
-
- /* Select back OPL4 FM mixer control. */
- bus_space_write_1(rman_get_bustag(opl4), rman_get_bushandle(opl4), 0, 0xf8);
- DELAY(10);
- bus_space_write_1(rman_get_bustag(opl4), rman_get_bushandle(opl4), 1, 0x1b);
- DELAY(10);
- }
- bus_release_resource(dev, SYS_RES_IOPORT, opl4_id, opl4);
- }
-#if notdef
- }
-#endif /* notdef */
- opl_command(scp, USE_RIGHT, OPL3_MODE_REGISTER, 0);
- }
-
- /* Kill any previous notes. */
- for (i = 0 ; i < 9 ; i++)
- opl_command(scp, USE_RIGHT, KEYON_BLOCK + i, 0);
-
- /* Select melodic mode. */
- opl_command(scp, USE_LEFT, TEST_REGISTER, ENABLE_WAVE_SELECT);
- opl_command(scp, USE_LEFT, PERCUSSION_REGISTER, 0);
-
- for (i = 0 ; i < SBFM_MAXINSTR ; i++)
- scp->i_map[i].channel = -1;
-
- /* Fill the softc. */
- bcopy(&opl_synthinfo, &scp->synthinfo, sizeof(opl_synthinfo));
- snprintf(scp->synthinfo.name, 64, "Yamaha OPL%d FM", scp->model);
- mtx_init(&scp->mtx, "oplmid", NULL, MTX_DEF);
- bcopy(pv_map, scp->pv_map, sizeof(pv_map));
- if (scp->model < MODEL_OPL3) { /* OPL2. */
- scp->synthinfo.nr_voices = 9;
- scp->synthinfo.nr_drums = 0;
- for (i = 0 ; i < MAX_VOICE ; i++)
- scp->pv_map[i].ch = USE_LEFT;
- } else { /* OPL3 or later. */
- scp->synthinfo.capabilities |= SYNTH_CAP_OPL3;
- scp->synthinfo.nr_voices = 18;
- scp->synthinfo.nr_drums = 0;
-#if notdef
- for (i = 0 ; i < MAX_VOICE ; i++) {
- if (scp->pv_map[i].ch == USE_LEFT)
- scp->pv_map[i].ch = USE_LEFT;
- else
- scp->pv_map[i].ch = USE_RIGHT;
- }
-#endif /* notdef */
- opl_command(scp, USE_RIGHT, OPL3_MODE_REGISTER, OPL3_ENABLE);
- opl_command(scp, USE_RIGHT, CONNECTION_SELECT_REGISTER, 0);
- }
-
- scp->devinfo = devinfo = create_mididev_info_unit(MDT_SYNTH, &opl_op_desc, &oplsynth_op_desc);
-
- /* Fill the midi info. */
- devinfo->synth.readraw = opl_readraw;
- devinfo->synth.writeraw = opl_writeraw;
- devinfo->synth.alloc.max_voice = scp->synthinfo.nr_voices;
- strcpy(devinfo->name, scp->synthinfo.name);
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x", (u_int)rman_get_start(scp->io));
-
- midiinit(devinfo, dev);
-
- MIDI_DEBUG(printf("opl: attached.\n"));
- MIDI_DEBUG(printf("opl: the chip is OPL%d.\n", scp->model));
-
- return (0);
-}
-
-static int
-oplsbc_attach(device_t dev)
-{
- return (opl_attach(dev));
-}
-
-static int
-opl_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit, i;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("opl%d: opening.\n", unit));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("opl_open: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- mtx_lock(&devinfo->synth.vc_mtx);
- if (scp->model < MODEL_OPL3)
- devinfo->synth.alloc.max_voice = 9;
- else
- devinfo->synth.alloc.max_voice = 18;
- devinfo->synth.alloc.timestamp = 0;
- for (i = 0 ; i < MAX_VOICE ; i++) {
- devinfo->synth.alloc.map[i] = 0;
- devinfo->synth.alloc.alloc_times[i] = 0;
- }
- mtx_unlock(&devinfo->synth.vc_mtx);
- scp->cmask = 0; /* We are in 2 OP mode initially. */
- if (scp->model >= MODEL_OPL3) {
- mtx_lock(&scp->mtx);
- opl_command(scp, USE_RIGHT, CONNECTION_SELECT_REGISTER, scp->cmask);
- mtx_unlock(&scp->mtx);
- }
-
- MIDI_DEBUG(printf("opl%d: opened.\n", unit));
-
- return (0);
-}
-
-static int
-opl_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("opl%d: closing.\n", unit));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("opl_close: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- mtx_lock(&devinfo->synth.vc_mtx);
- if (scp->model < MODEL_OPL3)
- devinfo->synth.alloc.max_voice = 9;
- else
- devinfo->synth.alloc.max_voice = 18;
- mtx_unlock(&devinfo->synth.vc_mtx);
-
- /* Stop the OPL. */
- opl_reset(scp->devinfo);
-
- MIDI_DEBUG(printf("opl%d: closed.\n", unit));
-
- return (0);
-}
-
-static int
-opl_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
- struct sbi_instrument *ins;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("opl_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("opl_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- switch (cmd) {
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- if (synthinfo->device != unit)
- return (ENXIO);
- bcopy(&scp->synthinfo, synthinfo, sizeof(scp->synthinfo));
- synthinfo->device = unit;
- synthinfo->nr_voices = devinfo->synth.alloc.max_voice;
- if (synthinfo->nr_voices == 12)
- synthinfo->nr_voices = 6;
- return (0);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- if (midiinfo->device != unit)
- return (ENXIO);
- bcopy(&opl_midiinfo, midiinfo, sizeof(opl_midiinfo));
- strcpy(midiinfo->name, scp->synthinfo.name);
- midiinfo->device = unit;
- return (0);
- break;
- case SNDCTL_FM_LOAD_INSTR:
- ins = (struct sbi_instrument *)arg;
- if (ins->channel < 0 || ins->channel >= SBFM_MAXINSTR) {
- printf("opl_ioctl: Instrument number %d is not valid.\n", ins->channel);
- return (EINVAL);
- }
-#if notyet
- pmgr_inform(scp, PM_E_PATCH_LOADED, inc->channel, 0, 0, 0);
-#endif /* notyet */
- opl_storeinstr(scp, ins->channel, ins);
- return (0);
- break;
- case SNDCTL_SYNTH_MEMAVL:
- *(int *)arg = 0x7fffffff;
- return (0);
- break;
- case SNDCTL_FM_4OP_ENABLE:
- if (scp->model >= MODEL_OPL3)
- opl_enter4opmode(scp);
- return (0);
- break;
- default:
- return (ENOSYS);
- }
- /* NOTREACHED */
- return (EINVAL);
-}
-
-static int
-opl_callback(void *d, int reason)
-{
- int unit;
- sc_p scp;
- mididev_info *devinfo;
-
- devinfo = (mididev_info *)d;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("opl_callback: device not configured.\n"));
- return (ENXIO);
- }
-
- unit = devinfo->unit;
- scp = devinfo->softc;
-
- MIDI_DEBUG(printf("opl%d: callback, reason 0x%x.\n", unit, reason));
-
- switch (reason & MIDI_CB_REASON_MASK) {
- case MIDI_CB_START:
- if ((reason & MIDI_CB_RD) != 0 && (devinfo->flags & MIDI_F_READING) == 0)
- /* Begin recording. */
- devinfo->flags |= MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (devinfo->flags & MIDI_F_WRITING) == 0)
- /* Start playing. */
- devinfo->flags |= MIDI_F_WRITING;
- break;
- case MIDI_CB_STOP:
- case MIDI_CB_ABORT:
- if ((reason & MIDI_CB_RD) != 0 && (devinfo->flags & MIDI_F_READING) != 0)
- /* Stop recording. */
- devinfo->flags &= ~MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (devinfo->flags & MIDI_F_WRITING) != 0)
- /* Stop Playing. */
- devinfo->flags &= ~MIDI_F_WRITING;
- break;
- }
-
- return (0);
-}
-
-static int
-opl_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
-{
- sc_p scp;
- int unit;
-
- if (md == NULL)
- return (ENXIO);
- if (lenr == NULL)
- return (EINVAL);
-
- unit = md->unit;
- scp = md->softc;
- if ((md->fflags & FREAD) == 0) {
- MIDI_DEBUG(printf("opl_readraw: unit %d is not for reading.\n", unit));
- return (EIO);
- }
-
- /* NOP. */
- *lenr = 0;
-
- return (0);
-}
-
-static int
-opl_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
-{
- sc_p scp;
- int unit;
-
- if (md == NULL)
- return (ENXIO);
- if (lenw == NULL)
- return (EINVAL);
-
- unit = md->unit;
- scp = md->softc;
- if ((md->fflags & FWRITE) == 0) {
- MIDI_DEBUG(printf("opl_writeraw: unit %d is not for writing.\n", unit));
- return (EIO);
- }
-
- /* NOP. */
- *lenw = 0;
-
- return (0);
-}
-
-/* The functions below here are the synthesizer interfaces. */
-
-static int
-opl_killnote(mididev_info *md, int voice, int note, int vel)
-{
- int unit;
- sc_p scp;
- struct physical_voice_info *map;
-
- scp = md->softc;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: killing a note, voice %d, note %d, vel %d.\n", unit, voice, note, vel));
-
- if (voice < 0 || voice >= md->synth.alloc.max_voice)
- return (0);
-
- mtx_lock(&md->synth.vc_mtx);
-
- md->synth.alloc.map[voice] = 0;
- mtx_lock(&scp->mtx);
- map = &scp->pv_map[scp->lv_map[voice]];
-
- if (map->voice_mode != VOICE_NONE) {
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num, scp->voc[voice].keyon_byte & ~0x20);
-
- scp->voc[voice].keyon_byte = 0;
- scp->voc[voice].bender = 0;
- scp->voc[voice].volume = 64;
- scp->voc[voice].bender_range = 200;
- scp->voc[voice].orig_freq = 0;
- scp->voc[voice].current_freq = 0;
- scp->voc[voice].mode = 0;
- }
-
- mtx_unlock(&scp->mtx);
- mtx_unlock(&md->synth.vc_mtx);
-
- return (0);
-}
-
-static int
-opl_setinstr(mididev_info *md, int voice, int instr_no)
-{
- int unit;
- sc_p scp;
-
- scp = md->softc;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: setting an instrument, voice %d, instr_no %d.\n", unit, voice, instr_no));
-
-
- if (voice < 0 || voice >= md->synth.alloc.max_voice || instr_no < 0 || instr_no >= SBFM_MAXINSTR)
- return (0);
-
- mtx_lock(&scp->mtx);
- scp->act_i[voice] = &scp->i_map[instr_no];
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-static int
-opl_startnote(mididev_info *md, int voice, int note, int volume)
-{
- u_char fpc;
- int unit, block, fnum, freq, voice_mode, voice_shift;
- struct sbi_instrument *instr;
- struct physical_voice_info *map;
- sc_p scp;
-
- scp = md->softc;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: starting a note, voice %d, note %d, volume %d.\n", unit, voice, note, volume));
-
- if (voice < 0 || voice >= md->synth.alloc.max_voice)
- return (0);
-
- mtx_lock(&scp->mtx);
- map = &scp->pv_map[scp->lv_map[voice]];
- if (map->voice_mode == VOICE_NONE) {
- mtx_unlock(&scp->mtx);
- return (0);
- }
-
- if (note == 255) {
- /* Change the volume. */
- opl_setvoicevolume(scp, voice, volume, scp->voc[voice].volume);
- mtx_unlock(&scp->mtx);
- return (0);
- }
-
- /* Kill the previous note. */
- opl_command(scp, map->ch, KSL_LEVEL + map->op[1], 0xff); /* Carrier volume */
- opl_command(scp, map->ch, KSL_LEVEL + map->op[0], 0xff); /* Modulator volume */
- if (map->voice_mode == VOICE_4OP) {
- opl_command(scp, map->ch, KSL_LEVEL + map->op[3], 0xff); /* Carrier volume */
- opl_command(scp, map->ch, KSL_LEVEL + map->op[2], 0xff); /* Modulator volume */
- }
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num, 0); /* Note off. */
-
- instr = scp->act_i[voice];
- if (instr == NULL)
- instr = &scp->i_map[0];
- if (instr->channel < 0) {
- mtx_unlock(&scp->mtx);
- printf("opl_startnote: the instrument for voice %d is undefined.\n", voice);
- return (0);
- }
- if (map->voice_mode == VOICE_2OP && instr->key == OPL3_PATCH) {
- mtx_unlock(&scp->mtx);
- printf("opl_startnote: the voice mode %d mismatches the key 0x%x.\n", map->voice_mode, instr->key);
- return (0);
- }
-
- voice_mode = map->voice_mode;
- if (voice_mode == VOICE_4OP) {
- if (map->ch == USE_LEFT)
- voice_shift = 0;
- else
- voice_shift = 3;
- voice_shift += map->voice_num;
- if (instr->key != OPL3_PATCH) {
- voice_mode = VOICE_2OP;
- scp->cmask &= ~(1 << voice_shift);
- } else
- scp->cmask |= 1 << voice_shift;
-
- opl_command(scp, USE_RIGHT, CONNECTION_SELECT_REGISTER, scp->cmask);
- }
-
- /* Set the sound characteristics, attack, decay, sustain, release, wave select, feedback, connection. */
- opl_command(scp, map->ch, AM_VIB + map->op[0], instr->operators[0]); /* Sound characteristics. */
- opl_command(scp, map->ch, AM_VIB + map->op[1], instr->operators[1]);
- opl_command(scp, map->ch, ATTACK_DECAY + map->op[0], instr->operators[4]); /* Attack and decay. */
- opl_command(scp, map->ch, ATTACK_DECAY + map->op[1], instr->operators[5]);
- opl_command(scp, map->ch, SUSTAIN_RELEASE + map->op[0], instr->operators[6]); /* Sustain and release. */
- opl_command(scp, map->ch, SUSTAIN_RELEASE + map->op[1], instr->operators[7]);
- opl_command(scp, map->ch, WAVE_SELECT + map->op[0], instr->operators[8]); /* Wave select. */
- opl_command(scp, map->ch, WAVE_SELECT + map->op[1], instr->operators[9]);
- fpc = instr->operators[10];
- if ((fpc & 0x30) == 0)
- fpc |= 0x30; /* So that at least one channel is enabled. */
- opl_command(scp, map->ch, FEEDBACK_CONNECTION + map->voice_num, fpc); /* Feedback and connection. */
-
- if (voice_mode == VOICE_4OP) {
- /* Do not forget the operators 3 and 4. */
- opl_command(scp, map->ch, AM_VIB + map->op[2], instr->operators[OFFS_4OP + 0]); /* Sound characteristics. */
- opl_command(scp, map->ch, AM_VIB + map->op[3], instr->operators[OFFS_4OP + 1]);
- opl_command(scp, map->ch, ATTACK_DECAY + map->op[2], instr->operators[OFFS_4OP + 4]); /* Attack and decay. */
- opl_command(scp, map->ch, ATTACK_DECAY + map->op[3], instr->operators[OFFS_4OP + 5]);
- opl_command(scp, map->ch, SUSTAIN_RELEASE + map->op[2], instr->operators[OFFS_4OP + 6]); /* Sustain and release. */
- opl_command(scp, map->ch, SUSTAIN_RELEASE + map->op[3], instr->operators[OFFS_4OP + 7]);
- opl_command(scp, map->ch, WAVE_SELECT + map->op[2], instr->operators[OFFS_4OP + 8]); /* Wave select. */
- opl_command(scp, map->ch, WAVE_SELECT + map->op[3], instr->operators[OFFS_4OP + 9]);
- fpc = instr->operators[OFFS_4OP + 10];
- if ((fpc & 0x30) == 0)
- fpc |= 0x30; /* So that at least one channel is enabled. */
- opl_command(scp, map->ch, FEEDBACK_CONNECTION + map->voice_num + 3, fpc); /* Feedback and connection. */
- }
- scp->voc[voice].mode = voice_mode;
-
- opl_setvoicevolume(scp, voice, volume, scp->voc[voice].volume);
-
- /* Calcurate the frequency. */
- scp->voc[voice].orig_freq = opl_notetofreq(note) / 1000;
- /* Tune for the pitch bend. */
- freq = scp->voc[voice].current_freq = opl_computefinetune(scp->voc[voice].orig_freq, scp->voc[voice].bender, scp->voc[voice].bender_range);
- opl_freqtofnum(freq, &block, &fnum);
-
- /* Now we can play the note. */
- opl_command(scp, map->ch, FNUM_LOW + map->voice_num, fnum & 0xff);
- scp->voc[voice].keyon_byte = 0x20 | ((block & 0x07) << 2) | ((fnum >> 8) & 0x03);
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num, scp->voc[voice].keyon_byte);
- if (voice_mode == VOICE_4OP)
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num + 3, scp->voc[voice].keyon_byte);
-
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-static int
-opl_reset(mididev_info *md)
-{
- int unit, i;
- sc_p scp;
- struct physical_voice_info *map;
-
- scp = md->softc;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: resetting.\n", unit));
-
- mtx_lock(&md->synth.vc_mtx);
- mtx_lock(&scp->mtx);
-
- for (i = 0 ; i < MAX_VOICE ; i++)
- scp->lv_map[i] = i;
-
- for (i = 0 ; i < md->synth.alloc.max_voice ; i++) {
- opl_command(scp, scp->pv_map[scp->lv_map[i]].ch, KSL_LEVEL + scp->pv_map[scp->lv_map[i]].op[0], 0xff);
- opl_command(scp, scp->pv_map[scp->lv_map[i]].ch, KSL_LEVEL + scp->pv_map[scp->lv_map[i]].op[1], 0xff);
- if (scp->pv_map[scp->lv_map[i]].voice_mode == VOICE_4OP) {
- opl_command(scp, scp->pv_map[scp->lv_map[i]].ch, KSL_LEVEL + scp->pv_map[scp->lv_map[i]].op[2], 0xff);
- opl_command(scp, scp->pv_map[scp->lv_map[i]].ch, KSL_LEVEL + scp->pv_map[scp->lv_map[i]].op[3], 0xff);
- }
- /*
- * opl_killnote(md, i, 0, 64) inline-expanded to avoid
- * unlocking and relocking mutex unnecessarily.
- */
- md->synth.alloc.map[i] = 0;
- map = &scp->pv_map[scp->lv_map[i]];
-
- if (map->voice_mode != VOICE_NONE) {
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num, scp->voc[i].keyon_byte & ~0x20);
-
- scp->voc[i].keyon_byte = 0;
- scp->voc[i].bender = 0;
- scp->voc[i].volume = 64;
- scp->voc[i].bender_range = 200;
- scp->voc[i].orig_freq = 0;
- scp->voc[i].current_freq = 0;
- scp->voc[i].mode = 0;
- }
- }
-
- if (scp->model >= MODEL_OPL3) {
- md->synth.alloc.max_voice = 18;
- for (i = 0 ; i < MAX_VOICE ; i++)
- scp->pv_map[i].voice_mode = VOICE_2OP;
- }
-
- mtx_unlock(&md->synth.vc_mtx);
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-static int
-opl_hwcontrol(mididev_info *md, u_char *event)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-opl_loadpatch(mididev_info *md, int format, struct uio *buf, int offs, int count, int pmgr_flag)
-{
- int unit;
- struct sbi_instrument ins;
- sc_p scp;
-
- scp = md->softc;
- unit = md->unit;
-
- if (count < sizeof(ins)) {
- printf("opl_loadpatch: The patch record is too short.\n");
- return (EINVAL);
- }
- if (uiomove(&((char *)&ins)[offs], sizeof(ins) - offs, buf) != 0)
- printf("opl_loadpatch: User memory mangled?\n");
- if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) {
- printf("opl_loadpatch: Instrument number %d is not valid.\n", ins.channel);
- return (EINVAL);
- }
- ins.key = format;
-
- opl_storeinstr(scp, ins.channel, &ins);
- return (0);
-}
-
-static int
-opl_panning(mididev_info *md, int chn, int pan)
-{
- /* NOP. */
- return (0);
-}
-
-#define SET_VIBRATO(cell) do { \
- int tmp; \
- tmp = instr->operators[(cell-1)+(((cell-1)/2)*OFFS_4OP)]; \
- if (press > 110) \
- tmp |= 0x40; /* Vibrato on */ \
- opl_command(scp, map->ch, AM_VIB + map->op[cell-1], tmp);} while(0);
-
-static int
-opl_aftertouch(mididev_info *md, int voice, int press)
-{
- int unit, connection;
- struct sbi_instrument *instr;
- struct physical_voice_info *map;
- sc_p scp;
-
- scp = md->softc;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: setting the aftertouch, voice %d, press %d.\n", unit, voice, press));
-
- if (voice < 0 || voice >= md->synth.alloc.max_voice)
- return (0);
-
- mtx_lock(&scp->mtx);
-
- map = &scp->pv_map[scp->lv_map[voice]];
- if (map->voice_mode == VOICE_NONE) {
- mtx_unlock(&scp->mtx);
- return (0);
- }
-
- /* Adjust the vibrato. */
- instr = scp->act_i[voice];
- if (instr == NULL)
- instr = &scp->i_map[0];
-
- if (scp->voc[voice].mode == VOICE_4OP) {
- connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
- switch (connection) {
- case 0:
- SET_VIBRATO(4);
- break;
- case 1:
- SET_VIBRATO(2);
- SET_VIBRATO(4);
- break;
- case 2:
- SET_VIBRATO(1);
- SET_VIBRATO(4);
- break;
- case 3:
- SET_VIBRATO(1);
- SET_VIBRATO(3);
- SET_VIBRATO(4);
- break;
- }
- } else {
- SET_VIBRATO(1);
- if ((instr->operators[10] & 0x01))
- SET_VIBRATO(2);
- }
-
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-static int
-opl_bendpitch(sc_p scp, int voice, int value)
-{
- int unit, block, fnum, freq;
- struct physical_voice_info *map;
- mididev_info *md;
-
- md = scp->devinfo;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: setting the pitch bend, voice %d, value %d.\n", unit, voice, value));
-
- mtx_lock(&scp->mtx);
-
- map = &scp->pv_map[scp->lv_map[voice]];
- if (map->voice_mode == 0) {
- mtx_unlock(&scp->mtx);
- return (0);
- }
- scp->voc[voice].bender = value;
- if (value == 0 || (scp->voc[voice].keyon_byte & 0x20) == 0) {
- mtx_unlock(&scp->mtx);
- return (0);
- }
-
- freq = opl_computefinetune(scp->voc[voice].orig_freq, scp->voc[voice].bender, scp->voc[voice].bender_range);
- scp->voc[voice].current_freq = freq;
-
- opl_freqtofnum(freq, &block, &fnum);
-
- opl_command(scp, map->ch, FNUM_LOW + map->voice_num, fnum & 0xff);
- scp->voc[voice].keyon_byte = 0x20 | ((block & 0x07) << 2) | ((fnum >> 8) & 0x03);
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num, scp->voc[voice].keyon_byte);
- if (map->voice_mode == VOICE_4OP)
- opl_command(scp, map->ch, KEYON_BLOCK + map->voice_num + 3, scp->voc[voice].keyon_byte);
-
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-static int
-opl_controller(mididev_info *md, int voice, int ctrlnum, int val)
-{
- int unit;
- sc_p scp;
-
- scp = md->softc;
- unit = md->unit;
-
- MIDI_DEBUG(printf("opl%d: setting the controller, voice %d, ctrlnum %d, val %d.\n", unit, voice, ctrlnum, val));
-
- if (voice < 0 || voice >= md->synth.alloc.max_voice)
- return (0);
-
- switch (ctrlnum) {
- case CTRL_PITCH_BENDER:
- opl_bendpitch(scp, voice, val);
- break;
- case CTRL_PITCH_BENDER_RANGE:
- mtx_lock(&scp->mtx);
- scp->voc[voice].bender_range = val;
- mtx_unlock(&scp->mtx);
- break;
- case CTRL_MAIN_VOLUME:
- mtx_lock(&scp->mtx);
- scp->voc[voice].volume = val / 128;
- mtx_unlock(&scp->mtx);
- break;
- }
-
- return (0);
-}
-
-static int
-opl_patchmgr(mididev_info *md, struct patmgr_info *rec)
-{
- return (EINVAL);
-}
-
-static int
-opl_bender(mididev_info *md, int voice, int val)
-{
- sc_p scp;
-
- scp = md->softc;
-
- if (voice < 0 || voice >= md->synth.alloc.max_voice)
- return (0);
-
- return opl_bendpitch(scp, voice, val - 8192);
-}
-
-static int
-opl_allocvoice(mididev_info *md, int chn, int note, struct voice_alloc_info *alloc)
-{
- int i, p, best, first, avail, best_time, is4op, instr_no;
- struct sbi_instrument *instr;
- sc_p scp;
-
- scp = md->softc;
-
- MIDI_DEBUG(printf("opl%d: allocating a voice, chn %d, note %d.\n", md->unit, chn, note));
-
- best_time = 0x7fffffff;
-
- mtx_lock(&md->synth.vc_mtx);
-
- if (chn < 0 || chn >= 15)
- instr_no = 0;
- else
- instr_no = md->synth.chn_info[chn].pgm_num;
-
- mtx_lock(&scp->mtx);
-
- instr = &scp->i_map[instr_no];
- if (instr->channel < 0 || md->synth.alloc.max_voice != 12)
- is4op = 0;
- else if (md->synth.alloc.max_voice == 12) {
- if (instr->key == OPL3_PATCH)
- is4op = 1;
- else
- is4op = 0;
- } else
- is4op = 0;
-
- if (is4op) {
- first = p = 0;
- avail = 6;
- } else {
- if (md->synth.alloc.max_voice == 12)
- first = p = 6;
- else
- first = p = 0;
- avail = md->synth.alloc.max_voice;
- }
-
- /* Look up a free voice. */
- best = first;
-
- for (i = 0 ; i < avail ; i++) {
- if (alloc->map[p] == 0)
- return (p);
- }
- if (alloc->alloc_times[p] < best_time) {
- best_time = alloc->alloc_times[p];
- best = p;
- }
- p = (p + 1) % avail;
-
- if (best < 0)
- best = 0;
- else if (best > md->synth.alloc.max_voice)
- best -= md->synth.alloc.max_voice;
-
- mtx_unlock(&scp->mtx);
- mtx_unlock(&md->synth.vc_mtx);
-
- return best;
-}
-
-static int
-opl_setupvoice(mididev_info *md, int voice, int chn)
-{
- struct channel_info *info;
- sc_p scp;
-
- scp = md->softc;
-
- MIDI_DEBUG(printf("opl%d: setting up a voice, voice %d, chn %d.\n", md->unit, voice, chn));
-
- mtx_lock(&md->synth.vc_mtx);
-
- info = &md->synth.chn_info[chn];
-
- opl_setinstr(md, voice, info->pgm_num);
- mtx_lock(&scp->mtx);
- scp->voc[voice].bender = info->bender_value;
- scp->voc[voice].volume = info->controllers[CTL_MAIN_VOLUME];
- mtx_unlock(&scp->mtx);
-
- mtx_lock(&md->synth.vc_mtx);
-
- return (0);
-}
-
-static int
-opl_sendsysex(mididev_info *md, u_char *sysex, int len)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-opl_prefixcmd(mididev_info *md, int status)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-opl_volumemethod(mididev_info *md, int mode)
-{
- /* NOP. */
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-/* Writes a command to the OPL chip. */
-static void
-opl_command(sc_p scp, int ch, int addr, u_int val)
-{
- int model;
-
- MIDI_DEBUG(printf("opl%d: sending a command, addr 0x%x, val 0x%x.\n", scp->devinfo->unit, addr, val));
-
- model = scp->model;
-
- /* Write the addr first. */
- bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), ch * 2, (u_char)(addr & 0xff));
- if (model < MODEL_OPL3)
- DELAY(10);
- else {
- bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), ch * 2);
- bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), ch * 2);
- }
-
- /* Next write the value. */
- bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), ch * 2 + 1, (u_char)(val & 0xff));
- if (model < MODEL_OPL3)
- DELAY(30);
- else {
- bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), ch * 2);
- bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), ch * 2);
- }
-}
-
-/* Reads the status of the OPL chip. */
-static int
-opl_status(sc_p scp)
-{
- MIDI_DEBUG(printf("opl%d: reading the status.\n", scp->devinfo->unit));
-
- return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), 0);
-}
-
-static void
-opl_enter4opmode(sc_p scp)
-{
- int i;
- mididev_info *devinfo;
- static int v4op[MAX_VOICE] = {
- 0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17,
- };
-
- devinfo = scp->devinfo;
-
- MIDI_DEBUG(printf("opl%d: entering 4 OP mode.\n", devinfo->unit));
-
- /* Connect all possible 4 OP voice operators. */
- mtx_lock(&devinfo->synth.vc_mtx);
- mtx_lock(&scp->mtx);
- scp->cmask = 0x3f;
- opl_command(scp, USE_RIGHT, CONNECTION_SELECT_REGISTER, scp->cmask);
-
- for (i = 0 ; i < 3 ; i++)
- scp->pv_map[i].voice_mode = VOICE_4OP;
- for (i = 3 ; i < 6 ; i++)
- scp->pv_map[i].voice_mode = VOICE_NONE;
- for (i = 9 ; i < 12 ; i++)
- scp->pv_map[i].voice_mode = VOICE_4OP;
- for (i = 12 ; i < 15 ; i++)
- scp->pv_map[i].voice_mode = VOICE_NONE;
-
- for (i = 0 ; i < 12 ; i++)
- scp->lv_map[i] = v4op[i];
- mtx_unlock(&scp->mtx);
- devinfo->synth.alloc.max_voice = 12;
- mtx_unlock(&devinfo->synth.vc_mtx);
-}
-
-static void
-opl_storeinstr(sc_p scp, int instr_no, struct sbi_instrument *instr)
-{
- if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || scp->model < MODEL_OPL3))
- printf("opl_storeinstr: The patch format field 0x%x is not valid.\n", instr->key);
-
- bcopy(instr, &scp->i_map[instr_no], sizeof(*instr));
-}
-
-static void
-opl_calcvol(u_char *regbyte, int volume, int main_vol)
-{
- int level;
-
- level = (~*regbyte & 0x3f);
-
- if (main_vol > 127)
- main_vol = 127;
-
- volume = (volume * main_vol) / 127;
-
- if (level > 0)
- level += opl_volumetable[volume];
-
- RANGE(level, 0, 0x3f);
-
- *regbyte = (*regbyte & 0xc0) | (~level & 0x3f);
-}
-
-static void
-opl_setvoicevolume(sc_p scp, int voice, int volume, int main_vol)
-{
- u_char vol1, vol2, vol3, vol4;
- int connection;
- struct sbi_instrument *instr;
- struct physical_voice_info *map;
- mididev_info *devinfo;
-
- devinfo = scp->devinfo;
-
- if (voice < 0 || voice >= devinfo->synth.alloc.max_voice)
- return;
-
- map = &scp->pv_map[scp->lv_map[voice]];
- instr = scp->act_i[voice];
- if (instr == NULL)
- instr = &scp->i_map[0];
-
- if (instr->channel < 0)
- return;
- if (scp->voc[voice].mode == VOICE_NONE)
- return;
- if (scp->voc[voice].mode == VOICE_2OP) { /* 2 OP mode. */
- vol1 = instr->operators[2];
- vol2 = instr->operators[3];
- if ((instr->operators[10] & 0x01))
- opl_calcvol(&vol1, volume, main_vol);
- opl_calcvol(&vol2, volume, main_vol);
- opl_command(scp, map->ch, KSL_LEVEL + map->op[0], vol1);
- opl_command(scp, map->ch, KSL_LEVEL + map->op[1], vol2);
- } else { /* 4 OP mode. */
- vol1 = instr->operators[2];
- vol2 = instr->operators[3];
- vol3 = instr->operators[OFFS_4OP + 2];
- vol4 = instr->operators[OFFS_4OP + 3];
- connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01);
- switch(connection) {
- case 0:
- opl_calcvol(&vol4, volume, main_vol);
- break;
- case 1:
- opl_calcvol(&vol2, volume, main_vol);
- opl_calcvol(&vol4, volume, main_vol);
- break;
- case 2:
- opl_calcvol(&vol1, volume, main_vol);
- opl_calcvol(&vol4, volume, main_vol);
- break;
- case 3:
- opl_calcvol(&vol1, volume, main_vol);
- opl_calcvol(&vol3, volume, main_vol);
- opl_calcvol(&vol4, volume, main_vol);
- break;
- }
- opl_command(scp, map->ch, KSL_LEVEL + map->op[0], vol1);
- opl_command(scp, map->ch, KSL_LEVEL + map->op[1], vol2);
- opl_command(scp, map->ch, KSL_LEVEL + map->op[2], vol3);
- opl_command(scp, map->ch, KSL_LEVEL + map->op[3], vol4);
- }
-}
-
-static void
-opl_freqtofnum(int freq, int *block, int *fnum)
-{
- int f, octave;
-
- f = freq;
- octave = 5;
-
- if (f == 0)
- octave = 0;
- else if (f < 261) {
- while (f < 261) {
- octave--;
- f <<= 1;
- }
- } else if (f > 493) {
- while (f > 493) {
- octave++;
- f >>= 1;
- }
- }
- if (octave > 7)
- octave = 7;
-
- *fnum = freq * (1 << (20 - octave)) / 49716;
- *block = octave;
-}
-
-static int notes[] =
-{
- 261632,
- 277189,
- 293671,
- 311132,
- 329632,
- 349232,
- 369998,
- 391998,
- 415306,
- 440000,
- 466162,
- 493880
-};
-
-#define BASE_OCTAVE 5
-
-static int
-opl_notetofreq(int note_num)
-{
- int note, octave, note_freq;
-
- octave = note_num / 12;
- note = note_num % 12;
-
- note_freq = notes[note];
-
- if (octave < BASE_OCTAVE)
- note_freq >>= (BASE_OCTAVE - octave);
- else if (octave > BASE_OCTAVE)
- note_freq <<= (octave - BASE_OCTAVE);
-
- return (note_freq);
-}
-
-static u_long
-opl_computefinetune(u_long base_freq, int bend, int range)
-{
- u_long amount;
- int negative, semitones, cents, multiplier;
-
- if (bend == 0 || range == 0 || base_freq == 0)
- return (base_freq);
-
- multiplier = 1;
-
- if (range > 8192)
- range = 8192;
-
- bend = bend * range / 8192;
- if (bend == 0)
- return (base_freq);
-
- if (bend < 0) {
- negative = 1;
- bend = -bend;
- }
- else
- negative = 0;
- if (bend > range)
- bend = range;
-
- while (bend > 2399) {
- multiplier *= 4;
- bend -= 2400;
- }
-
- semitones = bend / 100;
- cents = bend % 100;
-
- amount = (u_long)(semitone_tuning[semitones] * multiplier * cent_tuning[cents]) / 10000;
-
- if (negative)
- return (base_freq * 10000) / amount;
- else
- return (base_freq * amount) / 10000;
-}
-
-/* Allocates resources other than IO ports. */
-static int
-opl_allocres(sc_p scp, device_t dev)
-{
- if (scp->io == NULL) {
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 4, RF_ACTIVE);
- if (scp->io == NULL)
- return (1);
- }
-
- return (0);
-}
-
-/* Releases resources. */
-static void
-opl_releaseres(sc_p scp, device_t dev)
-{
- if (scp->io != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, scp->io);
- scp->io = NULL;
- }
-}
-
-static device_method_t opl_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , opl_probe ),
- DEVMETHOD(device_attach, opl_attach),
-
- { 0, 0 },
-};
-
-static driver_t opl_driver = {
- "midi",
- opl_methods,
- sizeof(struct opl_softc),
-};
-
-DRIVER_MODULE(opl, isa, opl_driver, midi_devclass, 0, 0);
-
-static device_method_t oplsbc_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , oplsbc_probe ),
- DEVMETHOD(device_attach, oplsbc_attach),
-
- { 0, 0 },
-};
-
-static driver_t oplsbc_driver = {
- "midi",
- oplsbc_methods,
- sizeof(struct opl_softc),
-};
-
-DRIVER_MODULE(oplsbc, sbc, oplsbc_driver, midi_devclass, 0, 0);
diff --git a/sys/dev/sound/isa/uartsio.c b/sys/dev/sound/isa/uartsio.c
deleted file mode 100644
index 384e1837cda1..000000000000
--- a/sys/dev/sound/isa/uartsio.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright by George Hansper 1996
- *
- * Tue Jan 23 22:32:10 EST 1996 ghansper@daemon.apana.org.au
- * added 16450/16550 support for standard serial-port UARTs
- *
- * 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.
- *
- *
- * Wed Apl 1 02:25:30 JST 1998 zinnia@jan.ne.jp
- * ported to FreeBSD 2.2.5R-RELEASE
- *
- * Fri Apl 1 21:16:20 JST 1999 zinnia@jan.ne.jp
- * ported to FreeBSD 3.1-STABLE
- *
- *
- * Ported to the new Audio Driver by Luigi Rizzo:
- * (C) 1999 Seigo Tanimura
- *
- * This is the 16550 midi uart driver for FreeBSD, based on the Luigi Sound Driver.
- * This handles io against /dev/midi, the midi {in, out}put event queues
- * and the event/message transmittion to/from a serial port interface.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/ic/ns16550.h>
-#include <dev/sound/midi/midi.h>
-
-/* XXX What about a PCI uart? */
-#include <isa/isavar.h>
-
-static devclass_t midi_devclass;
-
-#ifndef DDB
-#undef DDB
-#define DDB(x)
-#endif /* DDB */
-
-#define TX_FIFO_SIZE 16
-
-extern synthdev_info midisynth_op_desc;
-
-/* These are the synthesizer and the midi interface information. */
-static struct synth_info uartsio_synthinfo = {
- "uart16550A MIDI",
- 0,
- SYNTH_TYPE_MIDI,
- 0,
- 0,
- 128,
- 128,
- 128,
- SYNTH_CAP_INPUT,
-};
-
-static struct midi_info uartsio_midiinfo = {
- "uart16550A MIDI",
- 0,
- 0,
- 0,
-};
-
-/*
- * These functions goes into uartsio_op_desc to get called
- * from sound.c.
- */
-
-static int uartsio_probe(device_t dev);
-static int uartsio_attach(device_t dev);
-
-static d_ioctl_t uartsio_ioctl;
-static driver_intr_t uartsio_intr;
-static midi_callback_t uartsio_callback;
-
-/* Here is the parameter structure per a device. */
-struct uartsio_softc {
- device_t dev; /* device information */
- mididev_info *devinfo; /* midi device information */
-
- struct mtx mtx; /* Mutex to protect the device. */
-
- struct resource *io; /* Base of io port */
- int io_rid; /* Io resource ID */
- struct resource *irq; /* Irq */
- int irq_rid; /* Irq resource ID */
- void *ih; /* Interrupt cookie */
-
- int fflags; /* File flags */
-
- int has_fifo; /* TX/RX fifo in the uart */
- int tx_size; /* Size of TX on a transmission */
-
-};
-
-typedef struct uartsio_softc *sc_p;
-
-/* These functions are local. */
-static void uartsio_startplay(sc_p scp);
-static int uartsio_xmit(sc_p scp);
-static int uartsio_readport(sc_p scp, int off);
-static void uartsio_writeport(sc_p scp, int off, u_int8_t value);
-static int uartsio_allocres(sc_p scp, device_t dev);
-static void uartsio_releaseres(sc_p scp, device_t dev);
-
-/*
- * This is the device descriptor for the midi device.
- */
-static mididev_info uartsio_op_desc = {
- "16550 uart midi",
-
- SNDCARD_UART16550,
-
- NULL,
- NULL,
- uartsio_ioctl,
-
- uartsio_callback,
-
- MIDI_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-/*
- * Here are the main functions to interact to the user process.
- * These are called from snd* functions in sys/i386/isa/snd/sound.c.
- */
-
-static int
-uartsio_probe(device_t dev)
-{
- sc_p scp;
- int unit;
- u_char c;
-
- if (isa_get_logicalid(dev) != 0)
- /* This is NOT a PnP device! */
- return (ENXIO);
-
- scp = device_get_softc(dev);
- unit = device_get_unit(dev);
-
- device_set_desc(dev, uartsio_op_desc.name);
- bzero(scp, sizeof(*scp));
-
- scp->io_rid = 0;
- scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 8, RF_ACTIVE);
- if (scp->io == NULL)
- return (ENXIO);
-
- MIDI_DEBUG(printf("uartsio%d: probing.\n", unit));
-
-/* Read the IER. The upper four bits should all be zero. */
- c = uartsio_readport(scp, com_ier);
- if ((c & 0xf0) != 0) {
- uartsio_releaseres(scp, dev);
- return (ENXIO);
- }
-
-/* Read the MSR. The upper three bits should all be zero. */
- c = uartsio_readport(scp, com_mcr);
- if ((c & 0xe0) != 0) {
- uartsio_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* XXX Do we need a loopback test? */
-
- MIDI_DEBUG(printf("uartsio%d: probed.\n", unit));
-
- return (0);
-}
-
-static int
-uartsio_attach(device_t dev)
-{
- sc_p scp;
- mididev_info *devinfo;
-
- scp = device_get_softc(dev);
-
- MIDI_DEBUG(printf("uartsio: attaching.\n"));
-
- /* Allocate resources. */
- if (uartsio_allocres(scp, dev)) {
- uartsio_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* See the size of the tx fifo. */
- uartsio_writeport(scp, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_RX_HIGH);
- if ((uartsio_readport(scp, com_iir) & IIR_FIFO_MASK) == FIFO_RX_HIGH) {
- scp->has_fifo = 1;
- scp->tx_size = TX_FIFO_SIZE;
- MIDI_DEBUG(printf("uartsio: uart is 16550A, tx size is %d bytes.\n", scp->tx_size));
- } else {
- scp->has_fifo = 0;
- scp->tx_size = 1;
- MIDI_DEBUG(printf("uartsio: uart is not 16550A.\n"));
- }
-
- /* Configure the uart. */
- uartsio_writeport(scp, com_cfcr, CFCR_DLAB); /* Latch the divisor. */
- uartsio_writeport(scp, com_dlbl, 0x03);
- uartsio_writeport(scp, com_dlbh, 0x00); /* We want a bitrate of 38.4kbps. */
- uartsio_writeport(scp, com_cfcr, CFCR_8BITS); /* We want 8bits, 1 stop bit, no parity. */
- uartsio_writeport(scp, com_mcr, MCR_IENABLE | MCR_RTS | MCR_DTR); /* Enable interrupt, set RTS and DTR. */
- uartsio_writeport(scp, com_ier, IER_ERXRDY | IER_ETXRDY | IER_EMSC | IER_ERLS); /* Give us an interrupt on RXRDY, TXRDY, MSC and RLS. */
- if (scp->has_fifo)
- uartsio_writeport(scp, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_RX_LOW); /* We use the fifo. */
- else
- uartsio_writeport(scp, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST | FIFO_RX_LOW); /* We do not use the fifo. */
-
- /* Clear the gabage. */
- uartsio_readport(scp, com_lsr);
- uartsio_readport(scp, com_lsr);
- uartsio_readport(scp, com_iir);
- uartsio_readport(scp, com_data);
-
- /* Fill the softc. */
- scp->dev = dev;
- mtx_init(&scp->mtx, "siomid", NULL, MTX_DEF);
- scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &uartsio_op_desc, &midisynth_op_desc);
-
- /* Fill the midi info. */
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x irq %d",
- (u_int)rman_get_start(scp->io), (int)rman_get_start(scp->irq));
-
- midiinit(devinfo, dev);
-
- /* Now we can handle the interrupts. */
- bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, uartsio_intr, scp, &scp->ih);
-
- MIDI_DEBUG(printf("uartsio: attached.\n"));
-
- return (0);
-}
-
-static int
-uartsio_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("uartsio_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("uartsio_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- switch (cmd) {
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- if (synthinfo->device != unit)
- return (ENXIO);
- bcopy(&uartsio_synthinfo, synthinfo, sizeof(uartsio_synthinfo));
- synthinfo->device = unit;
- return (0);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- if (midiinfo->device != unit)
- return (ENXIO);
- bcopy(&uartsio_midiinfo, midiinfo, sizeof(uartsio_midiinfo));
- midiinfo->device = unit;
- return (0);
- break;
- default:
- return (ENOSYS);
- }
- /* NOTREACHED */
- return (EINVAL);
-}
-
-static void
-uartsio_intr(void *arg)
-{
- sc_p scp;
- mididev_info *devinfo;
-
- scp = (sc_p)arg;
- devinfo = scp->devinfo;
-
- mtx_lock(&devinfo->flagqueue_mtx);
- uartsio_xmit(scp);
- mtx_unlock(&devinfo->flagqueue_mtx);
-
- /* Invoke the upper layer. */
- midi_intr(devinfo);
-}
-
-static int
-uartsio_callback(void *di, int reason)
-{
- int unit;
- sc_p scp;
- mididev_info *d;
-
- d = (mididev_info *)di;
-
- mtx_assert(&d->flagqueue_mtx, MA_OWNED);
-
- if (d == NULL) {
- MIDI_DEBUG(printf("uartsio_callback: device not configured.\n"));
- return (ENXIO);
- }
-
- unit = d->unit;
- scp = d->softc;
-
- switch (reason & MIDI_CB_REASON_MASK) {
- case MIDI_CB_START:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0)
- /* Begin recording. */
- d->flags |= MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0)
- uartsio_startplay(scp);
- break;
- case MIDI_CB_STOP:
- case MIDI_CB_ABORT:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0)
- /* Stop recording. */
- d->flags &= ~MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0)
- /* Stop Playing. */
- d->flags &= ~MIDI_F_WRITING;
- break;
- }
-
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-/*
- * Starts to play the data in the output queue.
- */
-static void
-uartsio_startplay(sc_p scp)
-{
- mididev_info *devinfo;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* Can we play now? */
- if (devinfo->midi_dbuf_out.rl == 0)
- return;
-
- devinfo->flags |= MIDI_F_WRITING;
- uartsio_xmit(scp);
-}
-
-static int
-uartsio_xmit(sc_p scp)
-{
- mididev_info *devinfo;
- midi_dbuf *dbuf;
- int lsr, msr, iir, i, txsize, leni, leno;
- u_char c[TX_FIFO_SIZE];
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- mtx_lock(&scp->mtx);
- for (;;) {
- /* Read the received data. */
- while (((lsr = uartsio_readport(scp, com_lsr)) & LSR_RCV_MASK) != 0) {
- /* Is this a data or an error/break? */
- if ((lsr & LSR_RXRDY) == 0)
- printf("uartsio_xmit: receive error or break in unit %d.\n", devinfo->unit);
- else {
- /* Receive the data. */
- c[0] = uartsio_readport(scp, com_data);
- mtx_unlock(&scp->mtx);
- /* Queue into the passthru buffer and start transmitting if we can. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
- midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c[0], sizeof(c[0]), &leni);
- devinfo->flags |= MIDI_F_WRITING;
- }
- /* Queue if we are reading. Discard an active sensing. */
- if ((devinfo->flags & MIDI_F_READING) != 0 && c[0] != 0xfe)
- midibuf_input_intr(&devinfo->midi_dbuf_in, &c[0], sizeof(c[0]), &leni);
- mtx_lock(&scp->mtx);
- }
- }
- mtx_unlock(&scp->mtx);
-
- /* See which source to use. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0))
- dbuf = &devinfo->midi_dbuf_out;
- else
- dbuf = &devinfo->midi_dbuf_passthru;
-
- /* Transmit the data in the queue. */
- if ((devinfo->flags & MIDI_F_WRITING) != 0) {
- /* Do we have the data to transmit? */
- if (dbuf->rl == 0) {
- /* Stop playing. */
- devinfo->flags &= ~MIDI_F_WRITING;
- } else {
- mtx_lock(&scp->mtx);
- /* Read LSR and MSR. */
- lsr = uartsio_readport(scp, com_lsr);
- msr = uartsio_readport(scp, com_msr);
- /* Is the device ready?. */
- if ((lsr & LSR_TXRDY) != 0 && (msr & MSR_CTS) != 0) {
- /* send the data. */
- txsize = scp->tx_size;
- if (dbuf->rl < txsize)
- txsize = dbuf->rl;
- midibuf_output_intr(dbuf, c, txsize, &leno);
- for (i = 0 ; i < txsize ; i++)
- uartsio_writeport(scp, com_data, c[i]);
- /* We are playing now. */
- devinfo->flags |= MIDI_F_WRITING;
- } else {
- /* Do we have the data to transmit? */
- if (dbuf->rl > 0)
- /* Wait for the next interrupt. */
- devinfo->flags |= MIDI_F_WRITING;
- }
- mtx_unlock(&scp->mtx);
- }
- }
- mtx_lock(&scp->mtx);
- if (((iir = uartsio_readport(scp, com_iir)) & IIR_IMASK) == IIR_NOPEND)
- break;
- }
- mtx_unlock(&scp->mtx);
-
- return (0);
-}
-
-/* Reads from a port. */
-static int
-uartsio_readport(sc_p scp, int off)
-{
- return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off);
-}
-
-/* Writes to a port. */
-static void
-uartsio_writeport(sc_p scp, int off, u_int8_t value)
-{
- bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off, value);
-}
-
-/* Allocates resources other than IO ports. */
-static int
-uartsio_allocres(sc_p scp, device_t dev)
-{
- if (scp->irq == NULL) {
- scp->irq_rid = 0;
- scp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &scp->irq_rid, RF_ACTIVE);
- }
- if (scp->irq == NULL)
- return (1);
-
- return (0);
-}
-
-/* Releases resources. */
-static void
-uartsio_releaseres(sc_p scp, device_t dev)
-{
- if (scp->irq != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
- scp->irq = NULL;
- }
- if (scp->io != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, scp->io);
- scp->io = NULL;
- }
-}
-
-static device_method_t uartsio_methods[] = {
-/* Device interface */
- DEVMETHOD(device_probe , uartsio_probe ),
- DEVMETHOD(device_attach, uartsio_attach),
-
- { 0, 0 },
-};
-
-static driver_t uartsio_driver = {
- "midi",
- uartsio_methods,
- sizeof(struct uartsio_softc),
-};
-
-DRIVER_MODULE(uartsio, isa, uartsio_driver, midi_devclass, 0, 0);
diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c
deleted file mode 100644
index a9d018496bd7..000000000000
--- a/sys/dev/sound/midi/midi.c
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- * Main midi driver for FreeBSD. This file provides the main
- * entry points for probe/attach and all i/o demultiplexing, including
- * default routines for generic devices.
- *
- * (C) 1999 Seigo Tanimura
- *
- * 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.
- *
- *
- * For each card type a template "mididev_info" structure contains
- * all the relevant parameters, both for configuration and runtime.
- *
- * In this file we build tables of pointers to the descriptors for
- * the various supported cards. The generic probe routine scans
- * the table(s) looking for a matching entry, then invokes the
- * board-specific probe routine. If successful, a pointer to the
- * correct mididev_info is stored in mididev_last_probed, for subsequent
- * use in the attach routine. The generic attach routine copies
- * the template to a permanent descriptor (midi_info and
- * friends), initializes all generic parameters, and calls the
- * board-specific attach routine.
- *
- * On device calls, the generic routines do the checks on unit and
- * device parameters, then call the board-specific routines if
- * available, or try to perform the task using the default code.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-
-static devclass_t midi_devclass;
-
-static d_open_t midiopen;
-static d_close_t midiclose;
-static d_ioctl_t midiioctl;
-static d_read_t midiread;
-static d_write_t midiwrite;
-static d_poll_t midipoll;
-
-/* These functions are local. */
-static d_open_t midistat_open;
-static d_close_t midistat_close;
-static d_read_t midistat_read;
-static int midi_initstatus(char *buf, int size);
-static int midi_readstatus(char *buf, int *ptr, struct uio *uio);
-
-#define CDEV_MAJOR MIDI_CDEV_MAJOR
-static struct cdevsw midi_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_open = midiopen,
- .d_close = midiclose,
- .d_read = midiread,
- .d_write = midiwrite,
- .d_ioctl = midiioctl,
- .d_poll = midipoll,
- .d_name = "midi",
- .d_maj = CDEV_MAJOR,
-};
-
-/*
- * descriptors for active devices. also used as the public softc
- * of a device.
- */
-static TAILQ_HEAD(,_mididev_info) midi_info;
-static int nmidi, nsynth;
-/* Mutex to protect midi_info, nmidi and nsynth. */
-static struct mtx midiinfo_mtx;
-static int midiinfo_mtx_init;
-
-/* These make the buffer for /dev/midistat */
-static int midistatbusy;
-static char midistatbuf[4096];
-static int midistatptr;
-
-SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver");
-
-int midi_debug;
-SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
-
-midi_cmdtab cmdtab_midiioctl[] = {
- {SNDCTL_MIDI_PRETIME, "SNDCTL_MIDI_PRETIME"},
- {SNDCTL_MIDI_MPUMODE, "SNDCTL_MIDI_MPUMODE"},
- {SNDCTL_MIDI_MPUCMD, "SNDCTL_MIDI_MPUCMD"},
- {SNDCTL_SYNTH_INFO, "SNDCTL_SYNTH_INFO"},
- {SNDCTL_MIDI_INFO, "SNDCTL_MIDI_INFO"},
- {SNDCTL_SYNTH_MEMAVL, "SNDCTL_SYNTH_MEMAVL"},
- {SNDCTL_FM_LOAD_INSTR, "SNDCTL_FM_LOAD_INSTR"},
- {SNDCTL_FM_4OP_ENABLE, "SNDCTL_FM_4OP_ENABLE"},
- {MIOSPASSTHRU, "MIOSPASSTHRU"},
- {MIOGPASSTHRU, "MIOGPASSTHRU"},
- {AIONWRITE, "AIONWRITE"},
- {AIOGSIZE, "AIOGSIZE"},
- {AIOSSIZE, "AIOSSIZE"},
- {AIOGFMT, "AIOGFMT"},
- {AIOSFMT, "AIOSFMT"},
- {AIOGMIX, "AIOGMIX"},
- {AIOSMIX, "AIOSMIX"},
- {AIOSTOP, "AIOSTOP"},
- {AIOSYNC, "AIOSYNC"},
- {AIOGCAP, "AIOGCAP"},
- {-1, NULL},
-};
-
-/*
- * This is the generic init routine.
- * Must be called after device-specific init.
- */
-int
-midiinit(mididev_info *d, device_t dev)
-{
- int unit;
-
- /*
- * initialize standard parameters for the device. This can be
- * overridden by device-specific configurations but better do
- * here the generic things.
- */
-
- MIDI_DEBUG(printf("midiinit: unit %d.\n", d->unit));
-
- unit = d->unit;
- d->softc = device_get_softc(dev);
- d->dev = dev;
- d->magic = MAGIC(d->unit); /* debugging... */
- d->flags = 0;
- d->fflags = 0;
- d->midi_dbuf_in.unit_size = 1;
- d->midi_dbuf_out.unit_size = 1;
- d->midi_dbuf_passthru.unit_size = 1;
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (midi_devclass == NULL) {
- midi_devclass = device_get_devclass(dev);
- make_dev(&midi_cdevsw, MIDIMKMINOR(0, MIDI_DEV_STATUS),
- UID_ROOT, GID_WHEEL, 0444, "midistat");
- }
- make_dev(&midi_cdevsw, MIDIMKMINOR(unit, MIDI_DEV_MIDIN),
- UID_ROOT, GID_WHEEL, 0666, "midi%d", unit);
-
- return 0 ;
-}
-
-/*
- * a small utility function which, given a device number, returns
- * a pointer to the associated mididev_info struct, and sets the unit
- * number.
- */
-mididev_info *
-get_mididev_info(dev_t i_dev, int *unit)
-{
- int u;
-
- if (MIDIDEV(i_dev) != MIDI_DEV_MIDIN)
- return NULL;
- u = MIDIUNIT(i_dev);
- if (unit)
- *unit = u;
-
- return get_mididev_info_unit(u);
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct.
- */
-mididev_info *
-get_mididev_info_unit(int unit)
-{
- mididev_info *md;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- mtx_lock(&midiinfo_mtx);
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->unit == unit)
- break;
- }
- mtx_unlock(&midiinfo_mtx);
-
- return md;
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct with MDT_MIDI.
- */
-mididev_info *
-get_mididev_midi_unit(int unit)
-{
- mididev_info *md;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- mtx_lock(&midiinfo_mtx);
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->midiunit == unit)
- break;
- }
- mtx_unlock(&midiinfo_mtx);
-
- return md;
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct with MDT_SYNTH.
- */
-mididev_info *
-get_mididev_synth_unit(int unit)
-{
- mididev_info *md;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- mtx_lock(&midiinfo_mtx);
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->synthunit == unit)
- break;
- }
- mtx_unlock(&midiinfo_mtx);
-
- return md;
-}
-
-/* Create a new midi device info structure. */
-/* TODO: lock md, then exit. */
-mididev_info *
-create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf)
-{
- int unit;
- mididev_info *md, *mdnew;
-
- /* XXX */
- if (!midiinfo_mtx_init) {
- midiinfo_mtx_init = 1;
- mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
- TAILQ_INIT(&midi_info);
- }
-
- /* As malloc(9) might block, allocate mididev_info now. */
- mdnew = malloc(sizeof(mididev_info), M_DEVBUF, M_WAITOK | M_ZERO);
- if (mdnew == NULL)
- return NULL;
- bcopy(mdinf, mdnew, sizeof(mididev_info));
- bcopy(syninf, &mdnew->synth, sizeof(synthdev_info));
- midibuf_init(&mdnew->midi_dbuf_in);
- midibuf_init(&mdnew->midi_dbuf_out);
- midibuf_init(&mdnew->midi_dbuf_passthru);
- mtx_init(&mdnew->flagqueue_mtx, "midflq", NULL, MTX_DEF);
- mtx_init(&mdnew->synth.vc_mtx, "synsvc", NULL, MTX_DEF);
- mtx_init(&mdnew->synth.status_mtx, "synsst", NULL, MTX_DEF);
-
- mtx_lock(&midiinfo_mtx);
-
- switch (type) {
- case MDT_MIDI:
- mdnew->midiunit = nmidi;
- mdnew->synthunit = nmidi;
- nmidi++;
- break;
- case MDT_SYNTH:
- mdnew->midiunit = -1;
- mdnew->synthunit = nsynth;
- nsynth++;
- break;
- default:
- mtx_unlock(&midiinfo_mtx);
- midibuf_destroy(&mdnew->midi_dbuf_in);
- midibuf_destroy(&mdnew->midi_dbuf_out);
- midibuf_destroy(&mdnew->midi_dbuf_passthru);
- mtx_destroy(&mdnew->flagqueue_mtx);
- mtx_destroy(&mdnew->synth.vc_mtx);
- mtx_destroy(&mdnew->synth.status_mtx);
- free(mdnew, M_DEVBUF);
- panic("unsupported device type");
- return NULL;
- }
- mdnew->mdtype = type;
-
- for (unit = 0 ; ; unit++) {
- TAILQ_FOREACH(md, &midi_info, md_link) {
- if (md->unit == unit)
- break;
- }
- if (md == NULL)
- break;
- }
-
- mdnew->unit = unit;
- mtx_lock(&mdnew->flagqueue_mtx);
- TAILQ_INSERT_TAIL(&midi_info, mdnew, md_link);
-
- mtx_unlock(&midiinfo_mtx);
-
- return mdnew;
-}
-
-/* Return the number of configured devices. */
-int
-mididev_info_number(void)
-{
- return nmidi + nsynth;
-}
-
-/* Return the number of configured midi devices. */
-int
-mididev_midi_number(void)
-{
- return nmidi;
-}
-
-/* Return the number of configured synth devices. */
-int
-mididev_synth_number(void)
-{
- return nsynth;
-}
-
-/*
- * here are the switches for the main functions. The switches do
- * all necessary checks on the device number to make sure
- * that the device is configured. They also provide some default
- * functionalities so that device-specific drivers have to deal
- * only with special cases.
- */
-
-static int
-midiopen(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_open(i_dev, flags, mode, td);
- break;
- case MIDI_DEV_STATUS:
- ret = midistat_open(i_dev, flags, mode, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiclose(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_close(i_dev, flags, mode, td);
- break;
- case MIDI_DEV_STATUS:
- ret = midistat_close(i_dev, flags, mode, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiread(dev_t i_dev, struct uio * buf, int flag)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_read(i_dev, buf, flag);
- break;
- case MIDI_DEV_STATUS:
- ret = midistat_read(i_dev, buf, flag);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiwrite(dev_t i_dev, struct uio * buf, int flag)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_write(i_dev, buf, flag);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midiioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_ioctl(i_dev, cmd, arg, mode, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-static int
-midipoll(dev_t i_dev, int events, struct thread *td)
-{
- int ret;
-
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_MIDIN:
- ret = midi_poll(i_dev, events, td);
- break;
- default:
- ret = ENXIO;
- break;
- }
-
- return (ret);
-}
-
-/*
- * Followings are the generic methods in midi drivers.
- */
-
-int
-midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int dev, unit, ret;
- mididev_info *d;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_open: unit %d, flags 0x%x.\n", unit, flags));
-
- if (d == NULL)
- return (ENXIO);
-
- /* Mark this device busy. */
- mtx_lock(&d->flagqueue_mtx);
- device_busy(d->dev);
- if ((d->flags & MIDI_F_BUSY) != 0) {
- mtx_unlock(&d->flagqueue_mtx);
- printf("midi_open: unit %d is busy.\n", unit);
- return (EBUSY);
- }
- d->fflags = flags;
- d->flags |= MIDI_F_BUSY;
- d->flags &= ~(MIDI_F_READING | MIDI_F_WRITING);
- if ((d->fflags & O_NONBLOCK) != 0)
- d->flags |= MIDI_F_NBIO;
-
- /* Init the queue. */
- if ((flags & FREAD) != 0)
- midibuf_clear(&d->midi_dbuf_in);
- if ((flags & FWRITE) != 0) {
- midibuf_clear(&d->midi_dbuf_out);
- midibuf_clear(&d->midi_dbuf_passthru);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (d->open == NULL)
- ret = 0;
- else
- ret = d->open(i_dev, flags, mode, td);
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Begin recording if nonblocking. */
- if ((d->flags & (MIDI_F_READING | MIDI_F_NBIO)) == MIDI_F_NBIO && (d->fflags & FREAD) != 0)
- d->callback(d, MIDI_CB_START | MIDI_CB_RD);
-
- mtx_unlock(&d->flagqueue_mtx);
-
- MIDI_DEBUG(printf("midi_open: opened.\n"));
-
- return (ret);
-}
-
-int
-midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int dev, unit, ret;
- mididev_info *d;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_close: unit %d.\n", unit));
-
- if (d == NULL)
- return (ENXIO);
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Stop recording and playing. */
- if ((d->flags & MIDI_F_READING) != 0)
- d->callback(d, MIDI_CB_ABORT | MIDI_CB_RD);
- if ((d->flags & MIDI_F_WRITING) != 0)
- d->callback(d, MIDI_CB_ABORT | MIDI_CB_WR);
-
- /* Clear the queues. */
- if ((d->fflags & FREAD) != 0)
- midibuf_clear(&d->midi_dbuf_in);
- if ((d->fflags & FWRITE) != 0) {
- midibuf_clear(&d->midi_dbuf_out);
- midibuf_clear(&d->midi_dbuf_passthru);
- }
-
- /* Stop playing and unmark this device busy. */
- d->flags &= ~MIDI_F_BUSY;
- d->fflags = 0;
-
- device_unbusy(d->dev);
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (d->close == NULL)
- ret = 0;
- else
- ret = d->close(i_dev, flags, mode, td);
-
- MIDI_DEBUG(printf("midi_close: closed.\n"));
-
- return (ret);
-}
-
-int
-midi_read(dev_t i_dev, struct uio * buf, int flag)
-{
- int dev, unit, len, lenr, ret;
- mididev_info *d ;
- u_char *uiobuf;
-
- dev = minor(i_dev);
-
- d = get_mididev_info(i_dev, &unit);
- MIDI_DEBUG(printf("midi_read: unit %d, resid %d.\n", unit, buf->uio_resid));
-
- if (d == NULL)
- return (ENXIO);
-
- ret = 0;
-
- len = buf->uio_resid;
- lenr = 0;
-
- uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
- if (uiobuf == NULL)
- return (ENOMEM);
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Begin recording. */
- d->callback(d, MIDI_CB_START | MIDI_CB_RD);
-
- /* Have we got the data to read? */
- if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_in.rl == 0)
- ret = EAGAIN;
- else {
- if ((d->flags & MIDI_F_NBIO) != 0 && len > d->midi_dbuf_in.rl)
- len = d->midi_dbuf_in.rl;
- ret = midibuf_seqread(&d->midi_dbuf_in, uiobuf, len, &lenr,
- d->callback, d, MIDI_CB_START | MIDI_CB_RD,
- &d->flagqueue_mtx);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- if (lenr > 0)
- ret = uiomove(uiobuf, lenr, buf);
-
- free(uiobuf, M_DEVBUF);
-
- MIDI_DEBUG(printf("midi_read: ret %d, resid %d.\n", ret, buf->uio_resid));
-
- return (ret);
-}
-
-int
-midi_write(dev_t i_dev, struct uio * buf, int flag)
-{
- int dev, unit, len, len2, lenw, ret;
- mididev_info *d;
- u_char *uiobuf;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_write: unit %d.\n", unit));
-
- if (d == NULL)
- return (ENXIO);
-
- ret = 0;
-
- len = buf->uio_resid;
- lenw = 0;
-
- uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
- if (uiobuf == NULL)
- return (ENOMEM);
-
- ret = uiomove(uiobuf, len, buf);
- if (ret != 0) {
- free(uiobuf, M_DEVBUF);
- return (ret);
- }
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Have we got the data to write? */
- if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_out.fl == 0) {
- /* Begin playing. */
- d->callback(d, MIDI_CB_START | MIDI_CB_WR);
- ret = EAGAIN;
- } else {
- len2 = len;
- if ((d->flags & MIDI_F_NBIO) != 0 && len2 > d->midi_dbuf_out.fl)
- len2 = d->midi_dbuf_out.fl;
- ret = midibuf_seqwrite(&d->midi_dbuf_out, uiobuf, len2, &lenw,
- d->callback, d, MIDI_CB_START | MIDI_CB_WR,
- &d->flagqueue_mtx);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- free(uiobuf, M_DEVBUF);
- buf->uio_resid = len - lenw;
-
- return (ret);
-}
-
-/*
- * generic midi ioctl. Functions of the default driver can be
- * overridden by the device-specific ioctl call.
- * If a device-specific call returns ENOSYS (Function not implemented),
- * the default driver is called. Otherwise, the returned value
- * is passed up.
- *
- * The default handler, for many parameters, sets the value in the
- * descriptor, sets MIDI_F_INIT, and calls the callback function with
- * reason INIT. If successful, the callback returns 1 and the caller
- * can update the parameter.
- */
-
-int
-midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- int ret = ENOSYS, dev, unit;
- mididev_info *d;
- struct snd_size *sndsize;
- snd_sync_parm *sp;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- if (d == NULL)
- return (ENXIO);
-
- if (d->ioctl)
- ret = d->ioctl(i_dev, cmd, arg, mode, td);
- if (ret != ENOSYS)
- return ret;
-
- /*
- * pass control to the default ioctl handler. Set ret to 0 now.
- */
- ret = 0;
-
- MIDI_DEBUG(printf("midi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- /*
- * all routines are called with int. blocked. Make sure that
- * ints are re-enabled when calling slow or blocking functions!
- */
- switch(cmd) {
-
- /*
- * we start with the new ioctl interface.
- */
- case AIONWRITE: /* how many bytes can write ? */
- mtx_lock(&d->flagqueue_mtx);
- *(int *)arg = d->midi_dbuf_out.fl;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: fl %d.\n", *(int *)arg));
- break;
-
- case AIOSSIZE: /* set the current blocksize */
- sndsize = (struct snd_size *)arg;
- MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
- mtx_lock(&d->flagqueue_mtx);
- if (sndsize->play_size <= d->midi_dbuf_out.unit_size && sndsize->rec_size <= d->midi_dbuf_in.unit_size) {
- d->midi_dbuf_out.blocksize = d->midi_dbuf_out.unit_size;
- d->midi_dbuf_in.blocksize = d->midi_dbuf_in.unit_size;
- sndsize->play_size = d->midi_dbuf_out.blocksize;
- sndsize->rec_size = d->midi_dbuf_in.blocksize;
- d->flags &= ~MIDI_F_HAS_SIZE;
- mtx_unlock(&d->flagqueue_mtx);
- }
- else {
- if (sndsize->play_size > d->midi_dbuf_out.bufsize / 4)
- sndsize->play_size = d->midi_dbuf_out.bufsize / 4;
- if (sndsize->rec_size > d->midi_dbuf_in.bufsize / 4)
- sndsize->rec_size = d->midi_dbuf_in.bufsize / 4;
- /* Round up the size to the multiple of EV_SZ. */
- d->midi_dbuf_out.blocksize =
- ((sndsize->play_size + d->midi_dbuf_out.unit_size - 1)
- / d->midi_dbuf_out.unit_size) * d->midi_dbuf_out.unit_size;
- d->midi_dbuf_in.blocksize =
- ((sndsize->rec_size + d->midi_dbuf_in.unit_size - 1)
- / d->midi_dbuf_in.unit_size) * d->midi_dbuf_in.unit_size;
- sndsize->play_size = d->midi_dbuf_out.blocksize;
- sndsize->rec_size = d->midi_dbuf_in.blocksize;
- d->flags |= MIDI_F_HAS_SIZE;
- mtx_unlock(&d->flagqueue_mtx);
- }
-
- ret = 0;
- break;
-
- case AIOGSIZE: /* get the current blocksize */
- sndsize = (struct snd_size *)arg;
- mtx_lock(&d->flagqueue_mtx);
- sndsize->play_size = d->midi_dbuf_out.blocksize;
- sndsize->rec_size = d->midi_dbuf_in.blocksize;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
-
- ret = 0;
- break;
-
- case AIOSTOP:
- mtx_lock(&d->flagqueue_mtx);
- if (*(int *)arg == AIOSYNC_PLAY) /* play */
- *(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
- else if (*(int *)arg == AIOSYNC_CAPTURE)
- *(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_RD);
- else {
- MIDI_DEBUG(printf("midi_ioctl: bad channel 0x%x.\n", *(int *)arg));
- *(int *)arg = 0 ;
- }
- mtx_unlock(&d->flagqueue_mtx);
- break ;
-
- case AIOSYNC:
- sp = (snd_sync_parm *)arg;
- MIDI_DEBUG(printf("midi_ioctl: unimplemented, chan 0x%03lx pos %lu.\n",
- sp->chan,
- sp->pos));
- break;
- /*
- * here follow the standard ioctls (filio.h etc.)
- */
- case FIONREAD: /* get # bytes to read */
- mtx_lock(&d->flagqueue_mtx);
- *(int *)arg = d->midi_dbuf_in.rl;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: rl %d.\n", *(int *)arg));
- break;
-
- case FIOASYNC: /*set/clear async i/o */
- MIDI_DEBUG(printf("FIOASYNC\n"));
- break;
-
- case FIONBIO: /* set/clear non-blocking i/o */
- mtx_lock(&d->flagqueue_mtx);
- if (*(int *)arg == 0)
- d->flags &= ~MIDI_F_NBIO ;
- else
- d->flags |= MIDI_F_NBIO ;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: arg %d.\n", *(int *)arg));
- break ;
-
- case MIOSPASSTHRU: /* set/clear passthru */
- mtx_lock(&d->flagqueue_mtx);
- if (*(int *)arg == 0)
- d->flags &= ~MIDI_F_PASSTHRU ;
- else
- d->flags |= MIDI_F_PASSTHRU ;
-
- /* Init the queue. */
- midibuf_clear(&d->midi_dbuf_passthru);
-
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
-
- /* FALLTHROUGH */
- case MIOGPASSTHRU: /* get passthru */
- mtx_lock(&d->flagqueue_mtx);
- if ((d->flags & MIDI_F_PASSTHRU) != 0)
- *(int *)arg = 1;
- else
- *(int *)arg = 0;
- mtx_unlock(&d->flagqueue_mtx);
- MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
- break;
-
- default:
- MIDI_DEBUG(printf("midi_ioctl: default ioctl midi%d subdev %d fn 0x%08lx fail\n",
- unit, dev & 0xf, cmd));
- ret = EINVAL;
- break ;
- }
- return ret ;
-}
-
-int
-midi_poll(dev_t i_dev, int events, struct thread *td)
-{
- int unit, dev, ret, lim;
- mididev_info *d;
-
- dev = minor(i_dev);
- d = get_mididev_info(i_dev, &unit);
-
- MIDI_DEBUG(printf("midi_poll: unit %d.\n", unit));
-
- if (d == NULL)
- return (ENXIO);
-
- ret = 0;
-
- mtx_lock(&d->flagqueue_mtx);
-
- /* Look up the apropriate queue and select it. */
- if ((events & (POLLOUT | POLLWRNORM)) != 0) {
- /* Start playing. */
- d->callback(d, MIDI_CB_START | MIDI_CB_WR);
-
- /* Find out the boundary. */
- if ((d->flags & MIDI_F_HAS_SIZE) != 0)
- lim = d->midi_dbuf_out.blocksize;
- else
- lim = d->midi_dbuf_out.unit_size;
- if (d->midi_dbuf_out.fl < lim)
- /* No enough space, record select. */
- selrecord(td, &d->midi_dbuf_out.sel);
- else
- /* We can write now. */
- ret |= events & (POLLOUT | POLLWRNORM);
- }
- if ((events & (POLLIN | POLLRDNORM)) != 0) {
- /* Start recording. */
- d->callback(d, MIDI_CB_START | MIDI_CB_RD);
-
- /* Find out the boundary. */
- if ((d->flags & MIDI_F_HAS_SIZE) != 0)
- lim = d->midi_dbuf_in.blocksize;
- else
- lim = d->midi_dbuf_in.unit_size;
- if (d->midi_dbuf_in.rl < lim)
- /* No data ready, record select. */
- selrecord(td, &d->midi_dbuf_in.sel);
- else
- /* We can write now. */
- ret |= events & (POLLIN | POLLRDNORM);
- }
-
- mtx_unlock(&d->flagqueue_mtx);
-
- return (ret);
-}
-
-void
-midi_intr(mididev_info *d)
-{
- if (d->intr != NULL)
- d->intr(d->intrarg, d);
-}
-
-/* Flush the output queue. */
-#define MIDI_SYNC_TIMEOUT 1
-int
-midi_sync(mididev_info *d)
-{
- int i, rl;
-
- mtx_assert(&d->flagqueue_mtx, MA_OWNED);
-
- MIDI_DEBUG(printf("midi_sync: unit %d.\n", d->unit));
-
- while (d->midi_dbuf_out.rl > 0) {
- if ((d->flags & MIDI_F_WRITING) == 0)
- d->callback(d, MIDI_CB_START | MIDI_CB_WR);
- rl = d->midi_dbuf_out.rl;
- i = cv_timedwait_sig(&d->midi_dbuf_out.cv_out,
- &d->flagqueue_mtx,
- (d->midi_dbuf_out.bufsize * 10 * hz / 38400)
- + MIDI_SYNC_TIMEOUT * hz);
- if (i == EINTR || i == ERESTART) {
- if (i == EINTR)
- d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
- return (i);
- }
- if (i == EWOULDBLOCK && rl == d->midi_dbuf_out.rl) {
- /* A queue seems to be stuck up. Give up and clear the queue. */
- d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
- midibuf_clear(&d->midi_dbuf_out);
- return (0);
- }
- }
-
- return 0;
-}
-
-/*
- * These handle the status message of the midi drivers.
- */
-
-int
-midistat_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- if (midistatbusy)
- return (EBUSY);
-
- bzero(midistatbuf, sizeof(midistatbuf));
- midistatptr = 0;
- if (midi_initstatus(midistatbuf, sizeof(midistatbuf) - 1))
- return (ENOMEM);
-
- midistatbusy = 1;
-
- return (0);
-}
-
-int
-midistat_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- midistatbusy = 0;
-
- return (0);
-}
-
-int
-midistat_read(dev_t i_dev, struct uio * buf, int flag)
-{
- return midi_readstatus(midistatbuf, &midistatptr, buf);
-}
-
-/*
- * finally, some "libraries"
- */
-
-/* Inits the buffer for /dev/midistat. */
-static int
-midi_initstatus(char *buf, int size)
-{
- int i, p;
- device_t dev;
- mididev_info *md;
-
- p = 0;
- p += snprintf(buf, size, "FreeBSD Midi Driver (newmidi) %s %s\nInstalled devices:\n", __DATE__, __TIME__);
- for (i = 0 ; i < mididev_info_number() ; i++) {
- md = get_mididev_info_unit(i);
- if (!MIDICONFED(md))
- continue;
- dev = devclass_get_device(midi_devclass, i);
- if (p < size)
- p += snprintf(&buf[p], size - p, "midi%d: <%s> %s\n", i, device_get_desc(dev), md->midistat);
- else
- return (1);
- }
-
- return (0);
-}
-
-/* Reads the status message. */
-static int
-midi_readstatus(char *buf, int *ptr, struct uio *uio)
-{
- int len;
-
- len = min(uio->uio_resid, strlen(&buf[*ptr]));
- if (len > 0) {
- uiomove(&buf[*ptr], len, uio);
- *ptr += len;
- }
-
- return (0);
-}
-
-char
-*midi_cmdname(int cmd, midi_cmdtab *tab)
-{
- while (tab->name != NULL) {
- if (cmd == tab->cmd)
- return (tab->name);
- tab++;
- }
-
- return ("unknown");
-}
diff --git a/sys/dev/sound/midi/midi.h b/sys/dev/sound/midi/midi.h
deleted file mode 100644
index 634d457f5c53..000000000000
--- a/sys/dev/sound/midi/midi.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Include file for midi driver.
- *
- * Copyright by Seigo Tanimura 1999.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * first, include kernel header files.
- */
-
-#ifndef _MIDI_H_
-#define _MIDI_H_
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ioccom.h>
-
-#include <sys/filio.h>
-#include <sys/lock.h>
-#include <sys/sockio.h>
-#include <sys/fcntl.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-
-#include <sys/kernel.h> /* for DATA_SET */
-
-#include <sys/module.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/syslog.h>
-#include <sys/errno.h>
-#include <sys/malloc.h>
-#include <sys/bus.h>
-#include <machine/resource.h>
-#include <machine/bus_memio.h>
-#include <machine/bus_pio.h>
-#include <machine/bus.h>
-#include <machine/clock.h> /* for DELAY */
-#include <sys/limits.h>
-#include <sys/soundcard.h>
-#include <sys/rman.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <sys/mutex.h>
-#include <sys/condvar.h>
-
-#include <dev/sound/midi/miditypes.h>
-#include <dev/sound/midi/midibuf.h>
-#include <dev/sound/midi/midisynth.h>
-
-#define MIDI_CDEV_MAJOR 30
-
-/*#define MIDI_OUTOFGIANT*/
-
-/*
- * The order of mutex lock (from the first to the last)
- *
- * 1. sequencer flags, queues, timer and device list
- * 2. midi synth voice and channel
- * 3. midi synth status
- * 4. generic midi flags and queues
- * 5. midi device
- */
-
-/*
- * descriptor of midi operations ...
- *
- */
-
-struct _mididev_info {
-
- /*
- * the first part of the descriptor is filled up from a
- * template.
- */
- char name[64];
-
- int type;
-
- d_open_t *open;
- d_close_t *close;
- d_ioctl_t *ioctl;
- midi_callback_t *callback;
-
- /*
- * combinations of the following flags are used as second argument in
- * the callback from the dma module to the device-specific routines.
- */
-
-#define MIDI_CB_RD 0x100 /* read callback */
-#define MIDI_CB_WR 0x200 /* write callback */
-#define MIDI_CB_REASON_MASK 0xff
-#define MIDI_CB_START 0x01 /* start dma op */
-#define MIDI_CB_STOP 0x03 /* stop dma op */
-#define MIDI_CB_ABORT 0x04 /* abort dma op */
-#define MIDI_CB_INIT 0x05 /* init board parameters */
-
- /*
- * callback extensions
- */
-#define MIDI_CB_DMADONE 0x10
-#define MIDI_CB_DMAUPDATE 0x11
-#define MIDI_CB_DMASTOP 0x12
-
- /* init can only be called with int enabled and
- * no pending DMA activity.
- */
-
- /*
- * whereas from here, parameters are set at runtime.
- * resources are stored in the softc of the device,
- * not in the common structure.
- */
-
- int unit; /* unit number of the device */
- int midiunit; /* unit number for midi devices */
- int synthunit; /* unit number for synth devices */
- int mdtype; /* MDT_MIDI or MDT_SYNTH */
- void *softc; /* softc for the device */
- device_t dev; /* device_t for the device */
-
- int bd_id; /* used to hold board-id info, eg. sb version,
- * mss codec type, etc. etc.
- */
-
- struct mtx flagqueue_mtx; /* Mutex to protect flags and queues */
-
- /* Queues */
- midi_dbuf midi_dbuf_in; /* midi input event/message queue */
- midi_dbuf midi_dbuf_out; /* midi output event/message queue */
- midi_dbuf midi_dbuf_passthru; /* midi passthru event/message queue */
-
- /*
- * these parameters describe the operation of the board.
- * Generic things like busy flag, speed, etc are here.
- */
-
- /* Flags */
- volatile u_long flags; /* 32 bits, used for various purposes. */
- int fflags; /* file flag */
-
- /*
- * we have separate flags for read and write, although in some
- * cases this is probably not necessary (e.g. because we cannot
- * know how many processes are using the device, we cannot
- * distinguish if open, close, abort are for a write or for a
- * read).
- */
-
- /*
- * the following flag is used by open-close routines
- * to mark the status of the device.
- */
-#define MIDI_F_BUSY 0x0001 /* has been opened */
- /*
- * the next two are used to allow only one pending operation of
- * each type.
- */
-#define MIDI_F_READING 0x0004 /* have a pending read */
-#define MIDI_F_WRITING 0x0008 /* have a pending write */
-
- /*
- * flag used to mark a pending close.
- */
-#define MIDI_F_CLOSING 0x0040 /* a pending close */
-
- /*
- * if user has not set block size, then make it adaptive
- * (0.25s, or the perhaps last read/write ?)
- */
-#define MIDI_F_HAS_SIZE 0x0080 /* user set block size */
- /*
- * assorted flags related to operating mode.
- */
-#define MIDI_F_STEREO 0x0100 /* doing stereo */
-#define MIDI_F_NBIO 0x0200 /* do non-blocking i/o */
-#define MIDI_F_PASSTHRU 0x0400 /* pass received data to output port */
-
- /*
- * these flags mark a pending abort on a r/w operation.
- */
-#define MIDI_F_ABORTING 0x1000 /* a pending abort */
-
- /*
- * this is used to mark that board initialization is needed, e.g.
- * because of a change in sampling rate, format, etc. -- It will
- * be done at the next convenient time.
- */
-#define MIDI_F_INIT 0x4000 /* changed parameters. need init */
-
- int play_blocksize, rec_blocksize; /* blocksize for io and dma ops */
-
-#define mwsel midi_dbuf_out.sel
-#define mrsel midi_dbuf_in.sel
- u_long nterrupts; /* counter of interrupts */
- u_long magic;
-#define MAGIC(unit) ( 0xa4d10de0 + unit )
- void *device_data ; /* just in case it is needed...*/
-
- midi_intr_t *intr; /* interrupt handler of the upper layer (ie sequencer) */
- void *intrarg; /* argument to interrupt handler */
-
- /* The following is the interface from a midi sequencer to a midi device. */
- synthdev_info synth;
-
- /* This is the status message to display via /dev/midistat */
- char midistat[128];
-
- /* The tailq entry of the next midi device. */
- TAILQ_ENTRY(_mididev_info) md_link;
-
- /* The tailq entry of the next midi device opened by a sequencer. */
- TAILQ_ENTRY(_mididev_info) md_linkseq;
-} ;
-
-/*
- * then ioctls and other stuff
- */
-
-#define NMIDI_MAX 16 /* Number of supported devices */
-
-/*
- * many variables should be reduced to a range. Here define a macro
- */
-
-#define RANGE(var, low, high) (var) = \
-((var)<(low)?(low) : (var)>(high)?(high) : (var))
-
-/*
- * convert dev_t to unit and dev
- */
-#define MIDIMINOR(x) (minor(x))
-#define MIDIUNIT(x) ((MIDIMINOR(x) & 0x000000f0) >> 4)
-#define MIDIDEV(x) (MIDIMINOR(x) & 0x0000000f)
-#define MIDIMKMINOR(u, d) (((u) & 0x0f) << 4 | ((d) & 0x0f))
-#define MIDIMKDEV(m, u, d) (udev2dev(makeudev((m), MIDIMKMINOR((u), (d)))))
-
-/*
- * see if the device is configured
- */
-#define MIDICONFED(x) ((x)->ioctl != NULL)
-
-/*
- * finally, all default parameters
- */
-#define MIDI_BUFFSIZE (1024) /* XXX */
-
-#ifdef _KERNEL
-
-/* This is the generic midi drvier initializer. */
- int midiinit(mididev_info *d, device_t dev);
-
-/* This provides an access to the mididev_info. */
- mididev_info *get_mididev_info(dev_t i_dev, int *unit);
- mididev_info *get_mididev_info_unit(int unit);
- mididev_info *get_mididev_midi_unit(int unit);
- mididev_info *get_mididev_synth_unit(int unit);
- mididev_info *create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf);
- int mididev_info_number(void);
- int mididev_midi_number(void);
- int mididev_synth_number(void);
-#define MDT_MIDI (0)
-#define MDT_SYNTH (1)
-
-/* These are the generic methods for a midi driver. */
- d_open_t midi_open;
- d_close_t midi_close;
- d_ioctl_t midi_ioctl;
- d_read_t midi_read;
- d_write_t midi_write;
- d_poll_t midi_poll;
-
-/* Common interrupt handler */
-void midi_intr(mididev_info *);
-
-/* Sync output */
-int midi_sync(mididev_info *);
-
-struct _midi_cmdtab {
- int cmd;
- char * name;
-};
-typedef struct _midi_cmdtab midi_cmdtab;
-
-char *midi_cmdname(int cmd, midi_cmdtab *tab);
-
-SYSCTL_DECL(_hw_midi);
-
-extern int midi_debug;
-#define MIDI_DEBUG(x) \
- do { \
- if (midi_debug) { \
- (x); \
- } \
- } while(0)
-
-extern midi_cmdtab cmdtab_midiioctl[];
-
-#endif /* _KERNEL */
-
-/*
- * Minor numbers for the midi driver.
- */
-
-#define MIDI_DEV_MIDIN 2 /* Raw midi access */
-#define MIDI_DEV_STATUS 15 /* /dev/midistat */
-
-#endif /* _MIDI_H_ */
diff --git a/sys/dev/sound/midi/midibuf.c b/sys/dev/sound/midi/midibuf.c
deleted file mode 100644
index f4444059ac8f..000000000000
--- a/sys/dev/sound/midi/midibuf.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright (C) 1999 Seigo Tanimura
- * All rights reserved.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * This file implements a midi event/message queue. A midi
- * event/message queue holds midi events and messages to
- * transmit to or received from a midi interface.
- */
-
-#include <dev/sound/midi/midi.h>
-
-/* Some macros to handle the queue. */
-#define DATA_AVAIL(dbuf) ((dbuf)->rl)
-#define SPACE_AVAIL(dbuf) ((dbuf)->fl)
-
-static void queuerawdata(midi_dbuf *dbuf, char *data, int len);
-static void dequeuerawdata(midi_dbuf *dbuf, char *data, int len);
-static void copyrawdata(midi_dbuf *dbuf, int offset, char *data, int len);
-static void deleterawdata(midi_dbuf *dbuf, int len);
-
-/*
- * Here are the functions to interact to the midi device drivers.
- * These are called from midi device driver functions under sys/i386/isa/snd.
- */
-
-int
-midibuf_init(midi_dbuf *dbuf)
-{
- if (dbuf->buf == NULL) {
- dbuf->buf = malloc(MIDI_BUFFSIZE, M_DEVBUF, M_WAITOK | M_ZERO);
- cv_init(&dbuf->cv_in, "midi queue in");
- cv_init(&dbuf->cv_out, "midi queue out");
- }
-
- return (midibuf_clear(dbuf));
-}
-
-int
-midibuf_destroy(midi_dbuf *dbuf)
-{
- if (dbuf->buf != NULL) {
- free(dbuf->buf, M_DEVBUF);
- cv_destroy(&dbuf->cv_in);
- cv_destroy(&dbuf->cv_out);
- }
-
- return (0);
-}
-
-int
-midibuf_clear(midi_dbuf *dbuf)
-{
- bzero(dbuf->buf, MIDI_BUFFSIZE);
- dbuf->bufsize = MIDI_BUFFSIZE;
- dbuf->rp = dbuf->fp = 0;
- dbuf->dl = 0;
- dbuf->rl = 0;
- dbuf->fl = dbuf->bufsize;
- dbuf->int_count = 0;
- dbuf->chan = 0;
- /*dbuf->unit_size = 1;*/ /* The drivers are responsible. */
- bzero(&dbuf->sel, sizeof(dbuf->sel));
- dbuf->total = 0;
- dbuf->prev_total = 0;
- dbuf->blocksize = dbuf->bufsize / 4;
-
- return (0);
-}
-
-/* The sequencer calls this function to queue data. */
-int
-midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, int *lenw, midi_callback_t *cb, void *d, int reason, struct mtx *m)
-{
- int i, lwrt;
-
- if (m != NULL)
- mtx_assert(m, MA_OWNED);
-
- if (lenw == NULL)
- return (EINVAL);
- *lenw = 0;
-
- /* Is this a real queue? */
- if (dbuf == (midi_dbuf *)NULL)
- return (EINVAL);
-
- /* Write down every single byte. */
- while (len > 0) {
- /* Find out the number of bytes to write. */
- lwrt = SPACE_AVAIL(dbuf);
- if (lwrt > len)
- lwrt = len;
- if (lwrt > 0) {
- /* We can write some now. Queue the data. */
- queuerawdata(dbuf, data, lwrt);
-
- *lenw += lwrt;
- len -= lwrt;
- data += lwrt;
- }
-
- if (cb != NULL)
- (*cb)(d, reason);
-
- /* Have we got still more data to write? */
- if (len > 0) {
- /* Sleep until we have enough space. */
- i = cv_wait_sig(&dbuf->cv_out, m);
- if (i == EINTR || i == ERESTART)
- return (i);
- }
- }
-
- return (0);
-}
-
-int
-midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len, int *leno)
-{
- if (leno == NULL)
- return (EINVAL);
- *leno = 0;
-
- /* Is this a real queue? */
- if (dbuf == (midi_dbuf *)NULL)
- return (EINVAL);
-
- /* Have we got any data in the queue? */
- *leno = DATA_AVAIL(dbuf);
- if (*leno == 0)
- return (EAGAIN);
-
- /* Dequeue the data. */
- if (*leno > len)
- *leno = len;
- dequeuerawdata(dbuf, data, *leno);
-
- return (0);
-}
-
-int
-midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len, int *leni)
-{
- if (leni == NULL)
- return (EINVAL);
- *leni = 0;
-
- /* Is this a real queue? */
- if (dbuf == (midi_dbuf *)NULL)
- return (EINVAL);
-
- /* Have we got any data to write? */
- if (len == 0)
- return (0);
- /* Can we write now? */
- if (SPACE_AVAIL(dbuf) < len)
- return (EAGAIN);
-
- /* We can write some now. Queue the data. */
- queuerawdata(dbuf, data, len);
- *leni = len;
-
- return (0);
-}
-
-/* The sequencer calls this function to dequeue data. */
-int
-midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m)
-{
- int i, lrd;
-
- if (m != NULL)
- mtx_assert(m, MA_OWNED);
-
- if (lenr == NULL)
- return (EINVAL);
- *lenr = 0;
-
- /* Is this a real queue? */
- if (dbuf == (midi_dbuf *)NULL)
- return (EINVAL);
-
- /* Write down every single byte. */
- while (len > 0) {
- if (cb != NULL)
- (*cb)(d, reason);
-
- /* Have we got data to read? */
- if ((lrd = DATA_AVAIL(dbuf)) == 0) {
- /* Sleep until we have data ready to read. */
- i = cv_wait_sig(&dbuf->cv_in, m);
- if (i == EINTR || i == ERESTART)
- return (i);
- /* Find out the number of bytes to read. */
- lrd = DATA_AVAIL(dbuf);
- }
-
- if (lrd > len)
- lrd = len;
- if (lrd > 0) {
- /* We can read some data now. Dequeue the data. */
- dequeuerawdata(dbuf, data, lrd);
-
- *lenr += lrd;
- len -= lrd;
- data += lrd;
- }
- }
-
- return (0);
-}
-
-/* The sequencer calls this function to copy data without dequeueing. */
-int
-midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, int *lenc, midi_callback_t *cb, void *d, int reason, struct mtx *m)
-{
- int i, lrd;
-
- if (m != NULL)
- mtx_assert(m, MA_OWNED);
-
- if (lenc == NULL)
- return (EINVAL);
- *lenc = 0;
-
- /* Is this a real queue? */
- if (dbuf == (midi_dbuf *)NULL)
- return (EINVAL);
-
- /* Write down every single byte. */
- while (len > 0) {
- if (cb != NULL)
- (*cb)(d, reason);
-
- /* Have we got data to read? */
- if ((lrd = DATA_AVAIL(dbuf)) == 0) {
- /* Sleep until we have data ready to read. */
- i = cv_wait_sig(&dbuf->cv_in, m);
- if (i == EINTR || i == ERESTART)
- return (i);
- /* Find out the number of bytes to read. */
- lrd = DATA_AVAIL(dbuf);
- }
-
- if (lrd > len)
- lrd = len;
- if (lrd > 0) {
- /* We can read some data now. Copy the data. */
- copyrawdata(dbuf, *lenc, data, lrd);
-
- *lenc += lrd;
- len -= lrd;
- data += lrd;
- }
- }
-
- return (0);
-}
-
-/*
- * The sequencer calls this function to delete the data
- * that the sequencer has already read.
- */
-int
-midibuf_seqdelete(midi_dbuf *dbuf, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m)
-{
- int i, lrd;
-
- if (m != NULL)
- mtx_assert(m, MA_OWNED);
-
- if (lenr == NULL)
- return (EINVAL);
- *lenr = 0;
-
- /* Is this a real queue? */
- if (dbuf == (midi_dbuf *)NULL)
- return (EINVAL);
-
- /* Write down every single byte. */
- while (len > 0) {
- if (cb != NULL)
- (*cb)(d, reason);
-
- /* Have we got data to read? */
- if ((lrd = DATA_AVAIL(dbuf)) == 0) {
- /* Sleep until we have data ready to read. */
- i = cv_wait_sig(&dbuf->cv_in, m);
- if (i == EINTR || i == ERESTART)
- return (i);
- /* Find out the number of bytes to read. */
- lrd = DATA_AVAIL(dbuf);
- }
-
- if (lrd > len)
- lrd = len;
- if (lrd > 0) {
- /* We can read some data now. Delete the data. */
- deleterawdata(dbuf, lrd);
-
- *lenr += lrd;
- len -= lrd;
- }
- }
-
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-static void
-queuerawdata(midi_dbuf *dbuf, char *data, int len)
-{
- /* dbuf->fp might wrap around dbuf->bufsize. */
- if (dbuf->bufsize - dbuf->fp < len) {
- /* The new data wraps, copy them twice. */
- bcopy(data, dbuf->buf + dbuf->fp, dbuf->bufsize - dbuf->fp);
- bcopy(data + dbuf->bufsize - dbuf->fp, dbuf->buf, len - (dbuf->bufsize - dbuf->fp));
- } else
- /* The new data do not wrap, once is enough. */
- bcopy(data, dbuf->buf + dbuf->fp, len);
-
- /* Adjust the pointer and the length counters. */
- dbuf->fp = (dbuf->fp + len) % dbuf->bufsize;
- dbuf->fl -= len;
- dbuf->rl += len;
-
- /* Wake up the processes sleeping on input data. */
- cv_broadcast(&dbuf->cv_in);
- if (SEL_WAITING(&dbuf->sel) && dbuf->rl >= dbuf->blocksize)
- selwakeuppri(&dbuf->sel, PRIBIO);
-}
-
-static void
-dequeuerawdata(midi_dbuf *dbuf, char *data, int len)
-{
- /* Copy the data. */
- copyrawdata(dbuf, 0, data, len);
-
- /* Delete the data. */
- deleterawdata(dbuf, len);
-}
-
-static void
-copyrawdata(midi_dbuf *dbuf, int offset, char *data, int len)
-{
- int rp;
-
- rp = (dbuf->rp + offset) % dbuf->bufsize;
-
- /* dbuf->rp might wrap around dbuf->bufsize. */
- if (dbuf->bufsize - rp < len) {
- /* The data to be read wraps, copy them twice. */
- bcopy(dbuf->buf + rp, data, dbuf->bufsize - rp);
- bcopy(dbuf->buf, data + dbuf->bufsize - rp, len - (dbuf->bufsize - rp));
- } else
- /* The new data do not wrap, once is enough. */
- bcopy(dbuf->buf + rp, data, len);
-}
-
-static void
-deleterawdata(midi_dbuf *dbuf, int len)
-{
- /* Adjust the pointer and the length counters. */
- dbuf->rp = (dbuf->rp + len) % dbuf->bufsize;
- dbuf->rl -= len;
- dbuf->fl += len;
-
- /* Wake up the processes sleeping on queueing. */
- cv_broadcast(&dbuf->cv_out);
- if (SEL_WAITING(&dbuf->sel) && dbuf->fl >= dbuf->blocksize)
- selwakeuppri(&dbuf->sel, PRIBIO);
-}
diff --git a/sys/dev/sound/midi/midibuf.h b/sys/dev/sound/midi/midibuf.h
deleted file mode 100644
index a25c1cc24bdf..000000000000
--- a/sys/dev/sound/midi/midibuf.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Include file for midi buffer.
- *
- * Copyright by Seigo Tanimura 1999.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * descriptor of a midi buffer. See midibuf.c for documentation.
- * (rp,rl) and (fp,fl) identify the READY and FREE regions of the
- * buffer. dl contains the length used for dma transfer, dl>0 also
- * means that the channel is busy and there is a DMA transfer in progress.
- */
-
-typedef struct _midi_dbuf {
- char *buf;
- int bufsize ;
- volatile int rp, fp; /* pointers to the ready and free area */
- volatile int dl; /* transfer size */
- volatile int rl, fl; /* length of ready and free areas. */
- int int_count;
- int chan; /* dma channel */
- int unit_size ; /* unit size */
- struct selinfo sel;
- u_long total; /* total bytes processed */
- u_long prev_total; /* copy of the above when GETxPTR called */
- struct cv cv_in, cv_out; /* condvars */
- int blocksize; /* block size */
-} midi_dbuf ;
-
-/*
- * These are the midi buffer methods, used in midi interface devices.
- */
-int midibuf_init(midi_dbuf *dbuf);
-int midibuf_destroy(midi_dbuf *dbuf);
-int midibuf_clear(midi_dbuf *dbuf);
-int midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, int *lenw, midi_callback_t *cb, void *d, int reason, struct mtx *m);
-int midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len, int *leno);
-int midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len, int *leni);
-int midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m);
-int midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, int *lenc, midi_callback_t *cb, void *d, int reason, struct mtx *m);
-int midibuf_seqdelete(midi_dbuf *dbuf, int len, int *lend, midi_callback_t *cb, void *d, int reason, struct mtx *m);
diff --git a/sys/dev/sound/midi/midisynth.c b/sys/dev/sound/midi/midisynth.c
deleted file mode 100644
index d3708332e58b..000000000000
--- a/sys/dev/sound/midi/midisynth.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright by Hannu Savolainen 1993
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * This is the interface for a sequencer to interact a midi driver.
- * This interface translates the sequencer operations to the corresponding
- * midi messages, and vice versa.
- */
-
-#include <dev/sound/midi/midi.h>
-
-#define TYPEDRANGE(type, x, lower, upper) \
-{ \
- type tl, tu; \
- tl = (lower); \
- tu = (upper); \
- if (x < tl) { \
- x = tl; \
- } else if(x > tu) { \
- x = tu; \
- } \
-}
-
-/*
- * These functions goes into midisynthdev_op_desc.
- */
-static mdsy_killnote_t synth_killnote;
-static mdsy_setinstr_t synth_setinstr;
-static mdsy_startnote_t synth_startnote;
-static mdsy_reset_t synth_reset;
-static mdsy_hwcontrol_t synth_hwcontrol;
-static mdsy_loadpatch_t synth_loadpatch;
-static mdsy_panning_t synth_panning;
-static mdsy_aftertouch_t synth_aftertouch;
-static mdsy_controller_t synth_controller;
-static mdsy_patchmgr_t synth_patchmgr;
-static mdsy_bender_t synth_bender;
-static mdsy_allocvoice_t synth_allocvoice;
-static mdsy_setupvoice_t synth_setupvoice;
-static mdsy_sendsysex_t synth_sendsysex;
-static mdsy_prefixcmd_t synth_prefixcmd;
-static mdsy_volumemethod_t synth_volumemethod;
-static mdsy_readraw_t synth_readraw;
-static mdsy_writeraw_t synth_writeraw;
-
-/*
- * This is the synthdev_info for a midi interface device.
- * You may have to replace a few of functions for an internal
- * synthesizer.
- */
-synthdev_info midisynth_op_desc = {
- synth_killnote,
- synth_setinstr,
- synth_startnote,
- synth_reset,
- synth_hwcontrol,
- synth_loadpatch,
- synth_panning,
- synth_aftertouch,
- synth_controller,
- synth_patchmgr,
- synth_bender,
- synth_allocvoice,
- synth_setupvoice,
- synth_sendsysex,
- synth_prefixcmd,
- synth_volumemethod,
- synth_readraw,
- synth_writeraw,
-};
-
-/* The following functions are local. */
-static int synth_leavesysex(mididev_info *md);
-
-/*
- * Here are the main functions to interact to the midi sequencer.
- * These are called from the sequencer functions in sequencer.c.
- */
-
-static int
-synth_killnote(mididev_info *md, int chn, int note, int vel)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c[3];
-
- unit = md->unit;
- sd = &md->synth;
-
- if (note < 0 || note > 127 || chn < 0 || chn > 15)
- return (EINVAL);
- TYPEDRANGE(int, vel, 0, 127);
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- if (vel == 64) {
- c[0] = 0x90 | (chn & 0x0f); /* Note on. */
- c[1] = (u_char)note;
- c[2] = 0;
- } else {
- c[0] = 0x80 | (chn & 0x0f); /* Note off. */
- c[1] = (u_char)note;
- c[2] = (u_char)vel;
- }
-
- if (synth_prefixcmd(md, c[0]))
- return (0);
-
- return (md->synth.writeraw(md, c, 3, &lenw, 1));
-}
-
-static int
-synth_setinstr(mididev_info *md, int chn, int instr)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c[2];
-
- unit = md->unit;
- sd = &md->synth;
-
- if (instr < 0 || instr > 127 || chn < 0 || chn > 15)
- return (EINVAL);
-
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */
- c[1] = (u_char)instr;
-
- return (md->synth.writeraw(md, c, 3, &lenw, 1));
-}
-
-static int
-synth_startnote(mididev_info *md, int chn, int note, int vel)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c[3];
-
- unit = md->unit;
- sd = &md->synth;
-
- if (note < 0 || note > 127 || chn < 0 || chn > 15)
- return (EINVAL);
- TYPEDRANGE(int, vel, 0, 127);
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- c[0] = 0x90 | (chn & 0x0f); /* Note on. */
- c[1] = (u_char)note;
- c[2] = (u_char)vel;
- if (synth_prefixcmd(md, c[0]))
- return (0);
-
- return (md->synth.writeraw(md, c, 3, &lenw, 1));
-}
-
-static int
-synth_reset(mididev_info *md)
-{
- synth_leavesysex(md);
- return (0);
-}
-
-static int
-synth_hwcontrol(mididev_info *md, u_char *event)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-synth_loadpatch(mididev_info *md, int format, struct uio *buf, int offs, int count, int pmgr_flag)
-{
- struct sysex_info sysex;
- synthdev_info *sd;
- int unit, i, eox_seen, first_byte, left, src_offs, hdr_size, lenw;
- u_char c[count];
-
- unit = md->unit;
- sd = &md->synth;
-
- eox_seen = 0;
- first_byte = 1;
- hdr_size = offsetof(struct sysex_info, data);
-
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- if (synth_prefixcmd(md, 0xf0))
- return (0);
- if (format != SYSEX_PATCH) {
- printf("synth_loadpatch: patch format 0x%x is invalid.\n", format);
- return (EINVAL);
- }
- if (count < hdr_size) {
- printf("synth_loadpatch: patch header is too short.\n");
- return (EINVAL);
- }
- count -= hdr_size;
-
- /* Copy the patch data. */
- if (uiomove((caddr_t)&((char *)&sysex)[offs], hdr_size - offs, buf))
- printf("synth_loadpatch: memory mangled?\n");
-
- if (count < sysex.len) {
- sysex.len = (long)count;
- printf("synth_loadpatch: sysex record of %d bytes is too long, adjusted to %d bytes.\n", (int)sysex.len, count);
- }
- left = sysex.len;
- src_offs = 0;
-
- for (i = 0 ; i < left ; i++) {
- uiomove((caddr_t)&c[i], 1, buf);
- eox_seen = i > 0 && (c[i] & 0x80) != 0;
- if (eox_seen && c[i] != 0xf7)
- c[i] = 0xf7;
- if (i == 0 && c[i] != 0x80) {
- printf("synth_loadpatch: sysex does not begin with the status.\n");
- return (EINVAL);
- }
- if (!first_byte && (c[i] & 0x80) != 0) {
- md->synth.writeraw(md, c, i + 1, &lenw, 0);
- return (0);
- }
- first_byte = 0;
- }
-
- if (!eox_seen) {
- c[0] = 0xf7;
- md->synth.writeraw(md, c, 1, &lenw, 0);
- }
-
- return (0);
-}
-
-static int
-synth_panning(mididev_info *md, int chn, int pan)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-synth_aftertouch(mididev_info *md, int chn, int press)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c[2];
-
- unit = md->unit;
- sd = &md->synth;
-
- if (press < 0 || press > 127 || chn < 0 || chn > 15)
- return (EINVAL);
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- c[0] = 0xd0 | (chn & 0x0f); /* Channel Pressure. */
- c[1] = (u_char)press;
- if (synth_prefixcmd(md, c[0]))
- return (0);
-
- return (md->synth.writeraw(md, c, 2, &lenw, 1));
-}
-
-static int
-synth_controller(mididev_info *md, int chn, int ctrlnum, int val)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c[3];
-
- unit = md->unit;
- sd = &md->synth;
-
- if (ctrlnum < 1 || ctrlnum > 127 || chn < 0 || chn > 15)
- return (EINVAL);
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */
- c[1] = (u_char)ctrlnum;
- if (synth_prefixcmd(md, c[0]))
- return (0);
-
- return (md->synth.writeraw(md, c, 3, &lenw, 1));
-}
-
-static int
-synth_patchmgr(mididev_info *md, struct patmgr_info *rec)
-{
- return (EINVAL);
-}
-
-static int
-synth_bender(mididev_info *md, int chn, int val)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c[3];
-
- unit = md->unit;
- sd = &md->synth;
-
- if (val < 0 || val > 16383 || chn < 0 || chn > 15)
- return (EINVAL);
- if (synth_leavesysex(md) == EAGAIN)
- return (EAGAIN);
-
- c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */
- c[1] = (u_char)val & 0x7f;
- c[2] = (u_char)(val >> 7) & 0x7f;
- if (synth_prefixcmd(md, c[0]))
- return (0);
-
- return (md->synth.writeraw(md, c, 3, &lenw, 1));
-}
-
-static int
-synth_allocvoice(mididev_info *md, int chn, int note, struct voice_alloc_info *alloc)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-synth_setupvoice(mididev_info *md, int voice, int chn)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-synth_sendsysex(mididev_info *md, u_char *sysex, int len)
-{
- int unit, i, lenw;
- synthdev_info *sd;
- u_char c[len];
-
- unit = md->unit;
- sd = &md->synth;
-
- mtx_lock(&sd->status_mtx);
- for (i = 0 ; i < len ; i++) {
- switch (sysex[i]) {
- case 0xf0:
- /* Sysex begins. */
- if (synth_prefixcmd(md, 0xf0)) {
- mtx_unlock(&sd->status_mtx);
- return (0);
- }
- sd->sysex_state = 1;
- break;
- case 0xf7:
- /* Sysex ends. */
- if (!sd->sysex_state) {
- mtx_unlock(&sd->status_mtx);
- return (0);
- }
- sd->sysex_state = 0;
- break;
- default:
- if (!sd->sysex_state) {
- mtx_unlock(&sd->status_mtx);
- return (0);
- }
- if ((sysex[i] & 0x80) != 0) {
- /* A status in a sysex? */
- sysex[i] = 0xf7;
- sd->sysex_state = 0;
- }
- break;
- }
- c[i] = sysex[i];
- if (!sd->sysex_state)
- break;
- }
- mtx_unlock(&sd->status_mtx);
-
- return (md->synth.writeraw(md, c, i, &lenw, 1));
-}
-
-static int
-synth_prefixcmd(mididev_info *md, int status)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-synth_volumemethod(mididev_info *md, int mode)
-{
- /* NOP. */
- return (0);
-}
-
-static int
-synth_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
-{
- int unit, ret;
-
- if (md == NULL)
- return (ENXIO);
- if (lenr == NULL)
- return (EINVAL);
-
- *lenr = 0;
- unit = md->unit;
-
- if ((md->fflags & FREAD) == 0) {
- MIDI_DEBUG(printf("synth_readraw: unit %d is not for reading.\n", unit));
- return (EIO);
- }
-
- mtx_lock(&md->flagqueue_mtx);
-
- /* Begin recording. */
- if ((md->flags & MIDI_F_READING) == 0)
- md->callback(md, MIDI_CB_START | MIDI_CB_RD);
-
- if (nonblock) {
- /* Have we got enough data to read? */
- if (md->midi_dbuf_in.rl < len) {
- mtx_unlock(&md->flagqueue_mtx);
- return (EAGAIN);
- }
- }
-
- ret = midibuf_seqread(&md->midi_dbuf_in, buf, len, lenr,
- md->callback, md, MIDI_CB_START | MIDI_CB_RD,
- &md->flagqueue_mtx);
-
- mtx_unlock(&md->flagqueue_mtx);
-
- return (ret);
-}
-
-static int
-synth_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
-{
- int unit, ret;
-
- if (md == NULL)
- return (ENXIO);
- if (lenw == NULL)
- return (EINVAL);
-
- *lenw = 0;
- unit = md->unit;
-
- if ((md->fflags & FWRITE) == 0) {
- MIDI_DEBUG(printf("synth_writeraw: unit %d is not for writing.\n", unit));
- return (EIO);
- }
-
- /* For nonblocking, have we got enough space to write? */
- mtx_lock(&md->flagqueue_mtx);
- if (nonblock && md->midi_dbuf_out.fl < len) {
- /* Begin playing. */
- md->callback(md, MIDI_CB_START | MIDI_CB_WR);
- mtx_unlock(&md->flagqueue_mtx);
- return (EAGAIN);
- }
-
- ret = midibuf_seqwrite(&md->midi_dbuf_out, buf, len, lenw,
- md->callback, md, MIDI_CB_START | MIDI_CB_WR,
- &md->flagqueue_mtx);
-
- if (ret == 0)
- /* Begin playing. */
- md->callback(md, MIDI_CB_START | MIDI_CB_WR);
-
- mtx_unlock(&md->flagqueue_mtx);
-
- return (ret);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-static int
-synth_leavesysex(mididev_info *md)
-{
- int unit, lenw;
- synthdev_info *sd;
- u_char c;
-
- unit = md->unit;
- sd = &md->synth;
-
- mtx_lock(&sd->status_mtx);
- if (!sd->sysex_state) {
- mtx_unlock(&sd->status_mtx);
- return (0);
- }
-
- sd->sysex_state = 0;
- mtx_unlock(&sd->status_mtx);
- c = 0xf7;
-
- return (md->synth.writeraw(md, &c, sizeof(c), &lenw, 1));
-}
diff --git a/sys/dev/sound/midi/midisynth.h b/sys/dev/sound/midi/midisynth.h
deleted file mode 100644
index 356be897cb66..000000000000
--- a/sys/dev/sound/midi/midisynth.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * include file for midi synthesizer interface.
- *
- * Copyright by Seigo Tanimura 1999.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-#define SYNTH_MAX_VOICES 32
-
-/* This is the voice allocation state for a synthesizer. */
-struct voice_alloc_info {
- int max_voice;
- int used_voices;
- int ptr; /* For device specific use */
- u_short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */
- int timestamp;
- int alloc_times[SYNTH_MAX_VOICES];
-};
-
-/* This is the channel information for a synthesizer. */
-struct channel_info {
- int pgm_num;
- int bender_value;
- u_char controllers[128];
-};
-
-/* These are the function types for a midi synthesizer interface. */
-typedef int (mdsy_killnote_t)(mididev_info *md, int chn, int note, int vel);
-typedef int (mdsy_setinstr_t)(mididev_info *md, int chn, int instr);
-typedef int (mdsy_startnote_t)(mididev_info *md, int chn, int note, int vel);
-typedef int (mdsy_reset_t)(mididev_info *md);
-typedef int (mdsy_hwcontrol_t)(mididev_info *md, u_char *event);
-typedef int (mdsy_loadpatch_t)(mididev_info *md, int format, struct uio *buf, int offs, int count, int pmgr_flag);
-typedef int (mdsy_panning_t)(mididev_info *md, int chn, int pan);
-typedef int (mdsy_aftertouch_t)(mididev_info *md, int chn, int press);
-typedef int (mdsy_controller_t)(mididev_info *md, int chn, int ctrlnum, int val);
-typedef int (mdsy_patchmgr_t)(mididev_info *md, struct patmgr_info *rec);
-typedef int (mdsy_bender_t)(mididev_info *md, int chn, int val);
-typedef int (mdsy_allocvoice_t)(mididev_info *md, int chn, int note, struct voice_alloc_info *alloc);
-typedef int (mdsy_setupvoice_t)(mididev_info *md, int voice, int chn);
-typedef int (mdsy_sendsysex_t)(mididev_info *md, u_char *sysex, int len);
-typedef int (mdsy_prefixcmd_t)(mididev_info *md, int status);
-typedef int (mdsy_volumemethod_t)(mididev_info *md, int mode);
-typedef int (mdsy_readraw_t)(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock);
-typedef int (mdsy_writeraw_t)(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock);
-
-/*
- * The order of mutex lock (from the first to the last)
- *
- * 1. sequencer flags, queues, timer and devlice list
- * 2. midi synth voice and channel
- * 3. midi synth status
- * 4. generic midi flags and queues
- * 5. midi device
- */
-
-/* This is a midi synthesizer interface and state. */
-struct _synthdev_info {
- mdsy_killnote_t *killnote;
- mdsy_setinstr_t *setinstr;
- mdsy_startnote_t *startnote;
- mdsy_reset_t *reset;
- mdsy_hwcontrol_t *hwcontrol;
- mdsy_loadpatch_t *loadpatch;
- mdsy_panning_t *panning;
- mdsy_aftertouch_t *aftertouch;
- mdsy_controller_t *controller;
- mdsy_patchmgr_t *patchmgr;
- mdsy_bender_t *bender;
- mdsy_allocvoice_t *allocvoice;
- mdsy_setupvoice_t *setupvoice;
- mdsy_sendsysex_t *sendsysex;
- mdsy_prefixcmd_t *prefixcmd;
- mdsy_volumemethod_t *volumemethod;
- mdsy_readraw_t *readraw;
- mdsy_writeraw_t *writeraw;
-
- /* Voice and channel */
- struct mtx vc_mtx; /* Mutex to protect voice and channel. */
- struct voice_alloc_info alloc; /* Voice allocation. */
- struct channel_info chn_info[16]; /* Channel information. */
-
- /* Status */
- struct mtx status_mtx; /* Mutex to protect status. */
- int sysex_state; /* State of sysex transmission. */
-};
-typedef struct _synthdev_info synthdev_info;
diff --git a/sys/dev/sound/midi/miditypes.h b/sys/dev/sound/midi/miditypes.h
deleted file mode 100644
index 065734252d03..000000000000
--- a/sys/dev/sound/midi/miditypes.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Include file for type definitions in midi driver.
- *
- * Copyright by Seigo Tanimura 1999.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-typedef struct _mididev_info mididev_info;
-
-typedef int (midi_callback_t)(void *d, int reason);
-typedef void (midi_intr_t)(void *p, mididev_info *md);
diff --git a/sys/dev/sound/midi/sequencer.c b/sys/dev/sound/midi/sequencer.c
deleted file mode 100644
index bea493616d40..000000000000
--- a/sys/dev/sound/midi/sequencer.c
+++ /dev/null
@@ -1,2603 +0,0 @@
-/*
- * The sequencer personality manager.
- *
- * Copyright by Hannu Savolainen 1993
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * This is the newmidi sequencer driver. This driver handles io against
- * /dev/sequencer, midi input and output event queues and event transmittion
- * to and from a midi device or synthesizer.
- */
-
-#include <dev/sound/midi/midi.h>
-#include <dev/sound/midi/sequencer.h>
-
-#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
- synthesizer and MIDI output) */
-#define SND_DEV_MIDIN 2 /* Raw midi access */
-#define SND_DEV_MUSIC 8 /* /dev/music, level 2 interface */
-
-#define MIDIDEV_MODE 0x2000
-
-/* Length of a sequencer event. */
-#define EV_SZ 8
-#define IEV_SZ 8
-
-/* Lookup modes */
-#define LOOKUP_EXIST (0)
-#define LOOKUP_OPEN (1)
-#define LOOKUP_CLOSE (2)
-
-/*
- * These functions goes into seq_op_desc to get called
- * from sound.c.
- */
-
-static midi_intr_t seq_intr;
-static midi_callback_t seq_callback;
-
-/* These are the entries to the sequencer driver. */
-static d_open_t seq_open;
-static d_close_t seq_close;
-static d_ioctl_t seq_ioctl;
-static d_read_t seq_read;
-static d_write_t seq_write;
-static d_poll_t seq_poll;
-
-/*
- * This is the device descriptor for the midi sequencer.
- */
-seqdev_info seq_op_desc = {
- "midi sequencer",
-
- 0,
-
- seq_open,
- seq_close,
- seq_read,
- seq_write,
- seq_ioctl,
- seq_poll,
-
- seq_callback,
-
- SEQ_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-
-/* Here is the parameter structure per a device. */
-struct seq_softc {
- seqdev_info *devinfo; /* sequencer device information */
-
- /* Flags (protected by flag_mtx of mididev_info) */
- int fflags; /* Access mode */
- int queueout_pending; /* Pending for the output queue */
- int seq_mode; /* Sequencer mode */
-
- /* Timer counters */
- u_long seq_time; /* The beggining time of this sequence */
- u_long prev_event_time; /* The time of the previous event output */
- u_long prev_input_time; /* The time of the previous event input */
- u_long prev_wakeup_time; /* The time of the previous wakeup */
- struct callout timeout_ch; /* Timer callout handler */
- long timer_current; /* Current timer value */
- int timer_running; /* State of timer */
- int pending_timer; /* Timer change operation */
- int pre_event_timeout; /* Time to wait event input */
-
- /* Devices */
- TAILQ_HEAD(,_mididev_info) midi_open; /* Midi devices opened by this sequencer. */
- timerdev_info *timer; /* A timer device for /dev/music */
-
- /*
- * XXX not sure to which category these belong.
- * (and some might be no-op)
- */
- int output_threshould; /* Sequence output threshould */
- snd_sync_parm sync_parm; /* AIOSYNC parameter set */
- struct thread *sync_thread; /* AIOSYNCing thread */
-};
-
-typedef struct seq_softc *sc_p;
-
-static d_open_t seqopen;
-static d_close_t seqclose;
-static d_ioctl_t seqioctl;
-static d_read_t seqread;
-static d_write_t seqwrite;
-static d_poll_t seqpoll;
-
-#define CDEV_MAJOR SEQ_CDEV_MAJOR
-static struct cdevsw seq_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_open = seqopen,
- .d_close = seqclose,
- .d_read = seqread,
- .d_write = seqwrite,
- .d_ioctl = seqioctl,
- .d_poll = seqpoll,
- .d_name = "midi", /* XXX */
- .d_maj = CDEV_MAJOR,
-};
-
-
-static TAILQ_HEAD(,_seqdev_info) seq_info;
-/* Mutex to protect seq_info and nseq. */
-static struct mtx seqinfo_mtx;
-/* total number of sequencers */
-static u_long nseq;
-static dev_t seq_alias = NODEV;
-static dev_t music_alias = NODEV;
-
-SYSCTL_NODE(_hw_midi, OID_AUTO, seq, CTLFLAG_RD, 0, "Midi sequencer");
-
-int seq_debug;
-SYSCTL_INT(_hw_midi_seq, OID_AUTO, debug, CTLFLAG_RW, &seq_debug, 0, "");
-
-static midi_cmdtab cmdtab_seqevent[] = {
- {SEQ_NOTEOFF, "SEQ_NOTEOFF"},
- {SEQ_NOTEON, "SEQ_NOTEON"},
- {SEQ_WAIT, "SEQ_WAIT"},
- {SEQ_PGMCHANGE, "SEQ_PGMCHANGE"},
- {SEQ_SYNCTIMER, "SEQ_SYNCTIMER"},
- {SEQ_MIDIPUTC, "SEQ_MIDIPUTC"},
- {SEQ_DRUMON, "SEQ_DRUMON"},
- {SEQ_DRUMOFF, "SEQ_DRUMOFF"},
- {SEQ_ECHO, "SEQ_ECHO"},
- {SEQ_AFTERTOUCH, "SEQ_AFTERTOUCH"},
- {SEQ_CONTROLLER, "SEQ_CONTROLLER"},
- {SEQ_BALANCE, "SEQ_BALANCE"},
- {SEQ_VOLMODE, "SEQ_VOLMODE"},
- {SEQ_FULLSIZE, "SEQ_FULLSIZE"},
- {SEQ_PRIVATE, "SEQ_PRIVATE"},
- {SEQ_EXTENDED, "SEQ_EXTENDED"},
- {EV_SEQ_LOCAL, "EV_SEQ_LOCAL"},
- {EV_TIMING, "EV_TIMING"},
- {EV_CHN_COMMON, "EV_CHN_COMMON"},
- {EV_CHN_VOICE, "EV_CHN_VOICE"},
- {EV_SYSEX, "EV_SYSEX"},
- {-1, NULL},
-};
-
-midi_cmdtab cmdtab_seqioctl[] = {
- {SNDCTL_SEQ_RESET, "SNDCTL_SEQ_RESET"},
- {SNDCTL_SEQ_SYNC, "SNDCTL_SEQ_SYNC"},
- {SNDCTL_SYNTH_INFO, "SNDCTL_SYNTH_INFO"},
- {SNDCTL_SEQ_CTRLRATE, "SNDCTL_SEQ_CTRLRATE"},
- {SNDCTL_SEQ_GETOUTCOUNT, "SNDCTL_SEQ_GETOUTCOUNT"},
- {SNDCTL_SEQ_GETINCOUNT, "SNDCTL_SEQ_GETINCOUNT"},
- {SNDCTL_SEQ_PERCMODE, "SNDCTL_SEQ_PERCMODE"},
- {SNDCTL_FM_LOAD_INSTR, "SNDCTL_FM_LOAD_INSTR"},
- {SNDCTL_SEQ_TESTMIDI, "SNDCTL_SEQ_TESTMIDI"},
- {SNDCTL_SEQ_RESETSAMPLES, "SNDCTL_SEQ_RESETSAMPLES"},
- {SNDCTL_SEQ_NRSYNTHS, "SNDCTL_SEQ_NRSYNTHS"},
- {SNDCTL_SEQ_NRMIDIS, "SNDCTL_SEQ_NRMIDIS"},
- {SNDCTL_MIDI_INFO, "SNDCTL_MIDI_INFO"},
- {SNDCTL_SEQ_THRESHOLD, "SNDCTL_SEQ_THRESHOLD"},
- {SNDCTL_SYNTH_MEMAVL, "SNDCTL_SYNTH_MEMAVL"},
- {SNDCTL_FM_4OP_ENABLE, "SNDCTL_FM_4OP_ENABLE"},
- {SNDCTL_PMGR_ACCESS, "SNDCTL_PMGR_ACCESS"},
- {SNDCTL_SEQ_PANIC, "SNDCTL_SEQ_PANIC"},
- {SNDCTL_SEQ_OUTOFBAND, "SNDCTL_SEQ_OUTOFBAND"},
- {SNDCTL_TMR_TIMEBASE, "SNDCTL_TMR_TIMEBASE"},
- {SNDCTL_TMR_START, "SNDCTL_TMR_START"},
- {SNDCTL_TMR_STOP, "SNDCTL_TMR_STOP"},
- {SNDCTL_TMR_CONTINUE, "SNDCTL_TMR_CONTINUE"},
- {SNDCTL_TMR_TEMPO, "SNDCTL_TMR_TEMPO"},
- {SNDCTL_TMR_SOURCE, "SNDCTL_TMR_SOURCE"},
- {SNDCTL_TMR_METRONOME, "SNDCTL_TMR_METRONOME"},
- {SNDCTL_TMR_SELECT, "SNDCTL_TMR_SELECT"},
- {SNDCTL_MIDI_PRETIME, "SNDCTL_MIDI_PRETIME"},
- {AIONWRITE, "AIONWRITE"},
- {AIOGSIZE, "AIOGSIZE"},
- {AIOSSIZE, "AIOSSIZE"},
- {AIOGFMT, "AIOGFMT"},
- {AIOSFMT, "AIOSFMT"},
- {AIOGMIX, "AIOGMIX"},
- {AIOSMIX, "AIOSMIX"},
- {AIOSTOP, "AIOSTOP"},
- {AIOSYNC, "AIOSYNC"},
- {AIOGCAP, "AIOGCAP"},
- {-1, NULL},
-};
-
-midi_cmdtab cmdtab_timer[] = {
- {TMR_WAIT_REL, "TMR_WAIT_REL"},
- {TMR_WAIT_ABS, "TMR_WAIT_ABS"},
- {TMR_STOP, "TMR_STOP"},
- {TMR_START, "TMR_START"},
- {TMR_CONTINUE, "TMR_CONTINUE"},
- {TMR_TEMPO, "TMR_TEMPO"},
- {TMR_ECHO, "TMR_ECHO"},
- {TMR_CLOCK, "TMR_CLOCK"},
- {TMR_SPP, "TMR_SPP"},
- {TMR_TIMESIG, "TMR_TIMESIG"},
- {-1, NULL},
-};
-
-static midi_cmdtab cmdtab_seqcv[] = {
- {MIDI_NOTEOFF, "MIDI_NOTEOFF"},
- {MIDI_NOTEON, "MIDI_NOTEON"},
- {MIDI_KEY_PRESSURE, "MIDI_KEY_PRESSURE"},
- {-1, NULL},
-};
-
-static midi_cmdtab cmdtab_seqccmn[] = {
- {MIDI_CTL_CHANGE, "MIDI_CTL_CHANGE"},
- {MIDI_PGM_CHANGE, "MIDI_PGM_CHANGE"},
- {MIDI_CHN_PRESSURE, "MIDI_CHN_PRESSURE"},
- {MIDI_PITCH_BEND, "MIDI_PITCH_BEND"},
- {MIDI_SYSTEM_PREFIX, "MIDI_SYSTEM_PREFIX"},
- {-1, NULL},
-};
-
-
-/* The followings are the local function. */
-static int seq_init(void);
-static int seq_initunit(int unit);
-static int seq_queue(sc_p scp, u_char *note);
-static void seq_startplay(sc_p scp);
-static int seq_playevent(sc_p scp, u_char *event);
-static u_long seq_gettime(void);
-static int seq_requesttimer(sc_p scp, int delay);
-static void seq_stoptimer(sc_p scp);
-static void seq_midiinput(sc_p scp, mididev_info *md);
-static int seq_extended(sc_p scp, u_char *event);
-static int seq_chnvoice(sc_p scp, u_char *event);
-static int seq_findvoice(mididev_info *md, int chn, int note) __unused;
-static int seq_allocvoice(sc_p scp, mididev_info *md, int chn, int note) __unused;
-static int seq_chncommon(sc_p scp, u_char *event);
-static int seq_timing(sc_p scp, u_char *event);
-static int seq_local(sc_p scp, u_char *event);
-static int seq_sysex(sc_p scp, u_char *event);
-static int seq_reset(sc_p scp);
-static int seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *p);
-static int seq_closemidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *p);
-static void seq_panic(sc_p scp);
-static int seq_sync(sc_p scp);
-
-static seqdev_info *get_seqdev_info(dev_t i_dev, int *unit);
-static seqdev_info *get_seqdev_info_unit(int unit);
-static seqdev_info *create_seqdev_info_unit(int unit, seqdev_info *seq);
-static int lookup_mididev(sc_p scp, int unit, int mode, mididev_info **mdp);
-static int lookup_mididev_midi(sc_p scp, int unit, int mode, mididev_info **mdp);
-static void seq_clone(void *arg, char *name, int namelen, dev_t *dev);
-
-/*
- * Here are the main functions to interact to the user process.
- * These are called from snd* functions in sys/i386/isa/snd/sound.c.
- */
-
-static int
-seq_init(void)
-{
- SEQ_DEBUG(printf("seq: initing.\n"));
-
- mtx_init(&seqinfo_mtx, "seqinf", NULL, MTX_DEF);
- TAILQ_INIT(&seq_info);
-
- seq_initunit(0);
- EVENTHANDLER_REGISTER(dev_clone, seq_clone, 0, 1000);
-
- SEQ_DEBUG(printf("seq: inited.\n"));
-
- return (0);
-}
-
-static int
-seq_initunit(int unit)
-{
- sc_p scp;
- seqdev_info *devinfo;
- dev_t seqdev, musicdev;
-
- /* Allocate the softc. */
- scp = malloc(sizeof(*scp), M_DEVBUF, M_WAITOK | M_ZERO);
- if (scp == (sc_p)NULL) {
- printf("seq_initunit: unit %d, softc allocation failed.\n", unit);
- return (1);
- }
-
- /* Fill the softc and the seq_info for this unit. */
- scp->seq_time = seq_gettime();
- scp->prev_event_time = 0;
- scp->prev_input_time = 0;
- scp->prev_wakeup_time = scp->seq_time;
-#if defined(MIDI_OUTOFGIANT)
- callout_init(&scp->timeout_ch, 1);
-#else
- callout_init(&scp->timeout_ch, 0);
-#endif /* MIDI_OUTOFGIANT */
- scp->timer_current = 0;
- scp->timer_running = 0;
- scp->queueout_pending = 0;
- TAILQ_INIT(&scp->midi_open);
- scp->pending_timer = -1;
-
- scp->devinfo = devinfo = create_seqdev_info_unit(unit, &seq_op_desc);
- devinfo->midi_dbuf_in.unit_size = devinfo->midi_dbuf_out.unit_size = EV_SZ;
- devinfo->softc = scp;
- devinfo->flags = 0;
- mtx_unlock(&devinfo->flagqueue_mtx);
-
- seqdev = make_dev(&seq_cdevsw, MIDIMKMINOR(unit, SND_DEV_SEQ),
- UID_ROOT, GID_WHEEL, 0666, "sequencer%d", unit);
- musicdev = make_dev(&seq_cdevsw, MIDIMKMINOR(unit, SND_DEV_MUSIC),
- UID_ROOT, GID_WHEEL, 0666, "music%d", unit);
-
- mtx_lock(&seqinfo_mtx);
- if (seq_alias != NODEV) {
- destroy_dev(seq_alias);
- seq_alias = NODEV;
- }
- seq_alias = make_dev_alias(seqdev, "sequencer");
- if (music_alias != NODEV) {
- destroy_dev(music_alias);
- music_alias = NODEV;
- }
- music_alias = make_dev_alias(musicdev, "music");
- mtx_unlock(&seqinfo_mtx);
-
- if (timerdev_install() != 0)
- printf("seq_initunit: timerdev_install failed.\n");
-
- return (0);
-}
-
-int
-seq_open(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int unit;
- sc_p scp;
- seqdev_info *sd;
-
- unit = MIDIUNIT(i_dev);
-
- SEQ_DEBUG(printf("seq_open: unit %d, flags 0x%x.\n", unit, flags));
-
- if (unit >= NSEQ_MAX) {
- SEQ_DEBUG(printf("seq_open: unit %d does not exist.\n", unit));
- return (ENXIO);
- }
-
- sd = get_seqdev_info(i_dev, &unit);
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_open: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = sd->softc;
-
- /* Mark this device busy. */
- mtx_lock(&sd->flagqueue_mtx);
- if ((sd->flags & SEQ_F_BUSY) != 0) {
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_open: unit %d is busy.\n", unit));
- return (EBUSY);
- }
- scp->fflags = flags;
- sd->flags |= SEQ_F_BUSY;
- sd->flags &= ~(SEQ_F_READING | SEQ_F_WRITING);
- if ((scp->fflags & O_NONBLOCK) != 0)
- sd->flags |= SEQ_F_NBIO;
- scp->seq_mode = MIDIDEV(i_dev);
-
- /* Init the queue. */
- midibuf_clear(&sd->midi_dbuf_in);
- midibuf_clear(&sd->midi_dbuf_out);
-
- /* Init timestamp. */
- scp->seq_time = seq_gettime();
- scp->prev_event_time = 0;
- scp->prev_input_time = 0;
- scp->prev_wakeup_time = scp->seq_time;
-
- if (scp->pending_timer != -1) {
- scp->timer = get_timerdev_info_unit(scp->pending_timer);
- scp->pending_timer = -1;
- }
- if (scp->timer == NULL)
- scp->timer = get_timerdev_info();
- if (scp->timer != NULL) {
- scp->timer->seq = scp;
- mtx_unlock(&scp->timer->mtx);
- } else if (scp->seq_mode == SND_DEV_MUSIC) {
- mtx_unlock(&sd->flagqueue_mtx);
- printf("seq_open: no timer available.\n");
- sd->flags &= ~SEQ_F_BUSY;
- return (ENXIO);
- }
-
- if (scp->seq_mode == SND_DEV_MUSIC)
- scp->timer->open(scp->timer, flags, mode, td);
-
- /* Begin recording if nonblocking. */
- if ((sd->flags & (SEQ_F_READING | SEQ_F_NBIO)) == SEQ_F_NBIO && (scp->fflags & FREAD) != 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_RD);
-
- mtx_unlock(&sd->flagqueue_mtx);
-
- SEQ_DEBUG(printf("seq_open: opened, mode %d.\n", scp->seq_mode == SND_DEV_MUSIC ? 2 : 1));
-
- return (0);
-}
-
-int
-seq_close(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- int unit;
- sc_p scp;
- seqdev_info *sd;
- mididev_info *md;
- timerdev_info *tmd;
-
- unit = MIDIUNIT(i_dev);
-
- SEQ_DEBUG(printf("seq_close: unit %d.\n", unit));
-
- if (unit >= NSEQ_MAX) {
- SEQ_DEBUG(printf("seq_close: unit %d does not exist.\n", unit));
- return (ENXIO);
- }
-
- sd = get_seqdev_info(i_dev, &unit);
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_close: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = sd->softc;
-
- mtx_lock(&sd->flagqueue_mtx);
-
- if (!(sd->flags & MIDI_F_NBIO))
- seq_sync(scp);
-
- /* Stop the timer. */
- seq_stoptimer(scp);
-
- /* Reset the sequencer. */
- seq_reset(scp);
- seq_sync(scp);
-
- /* Clean up the midi device. */
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq)
- lookup_mididev(scp, md->unit, LOOKUP_CLOSE, NULL);
-
- /* Stop playing and unmark this device busy. */
- sd->flags &= ~(SEQ_F_BUSY | SEQ_F_READING | SEQ_F_WRITING | SEQ_F_INSYNC);
-
- if (scp->seq_mode == SND_DEV_MUSIC)
- scp->timer->close(scp->timer, flags, mode, td);
-
- if (scp->timer != NULL) {
- tmd = scp->timer;
- mtx_lock(&tmd->mtx);
- scp->timer = NULL;
- tmd->seq = NULL;
- mtx_unlock(&tmd->mtx);
- }
-
- mtx_unlock(&sd->flagqueue_mtx);
-
- SEQ_DEBUG(printf("seq_close: closed.\n"));
-
- return (0);
-}
-
-int
-seq_read(dev_t i_dev, struct uio *buf, int flag)
-{
- int unit, ret, len, lenr;
- sc_p scp;
- seqdev_info *sd;
- u_char *uiobuf;
-
- unit = MIDIUNIT(i_dev);
-
- SEQ_DEBUG(printf("seq_read: unit %d, resid %d.\n", unit, buf->uio_resid));
-
- if (unit >= NSEQ_MAX) {
- SEQ_DEBUG(printf("seq_read: unit %d does not exist.\n", unit));
- return (ENXIO);
- }
-
- sd = get_seqdev_info(i_dev, &unit);
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_read: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = sd->softc;
- if ((scp->fflags & FREAD) == 0) {
- SEQ_DEBUG(printf("seq_read: unit %d is not for reading.\n", unit));
- return (EIO);
- }
-
- len = buf->uio_resid;
- lenr = 0;
-
- uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
- if (uiobuf == NULL)
- return (ENOMEM);
-
- mtx_lock(&sd->flagqueue_mtx);
-
- /* Begin recording. */
- if ((sd->flags & SEQ_F_READING) == 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_RD);
-
- /* Have we got the data to read? */
- if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_in.rl == 0)
- ret = EAGAIN;
- else {
- if ((sd->flags & SEQ_F_NBIO) != 0 && len > sd->midi_dbuf_in.rl)
- len = sd->midi_dbuf_in.rl;
- ret = midibuf_seqread(&sd->midi_dbuf_in, uiobuf, len, &lenr,
- sd->callback, sd, SEQ_CB_START | SEQ_CB_RD,
- &sd->flagqueue_mtx);
- }
-
- mtx_unlock(&sd->flagqueue_mtx);
-
- if (ret == 0 && lenr > 0)
- ret = uiomove(uiobuf, lenr, buf);
-
- free(uiobuf, M_DEVBUF);
-
- SEQ_DEBUG(printf("seq_read: ret %d, resid %d.\n", ret, buf->uio_resid));
-
- return (ret);
-}
-
-int
-seq_write(dev_t i_dev, struct uio *buf, int flag)
-{
- u_char event[EV_SZ], ev_code;
- int unit, count, countorg, midiunit, ev_size, p, ret;
- sc_p scp;
- seqdev_info *sd;
- mididev_info *md;
-
- unit = MIDIUNIT(i_dev);
-
- SEQ_DEBUG(printf("seq_write: unit %d, resid %d.\n", unit, buf->uio_resid));
-
- if (unit >= NSEQ_MAX) {
- SEQ_DEBUG(printf("seq_write: unit %d does not exist.\n", unit));
- return (ENXIO);
- }
-
- sd = get_seqdev_info(i_dev, &unit);
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_write: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = sd->softc;
- if ((scp->fflags & FWRITE) == 0) {
- SEQ_DEBUG(printf("seq_write: unit %d is not for writing.\n", unit));
- return (EIO);
- }
-
- p = 0;
- countorg = buf->uio_resid;
- count = countorg;
-
- /* Pick up an event. */
- while (count >= 4) {
- if (uiomove((caddr_t)event, 4, buf))
- printf("seq_write: user memory mangled?\n");
- ev_code = event[0];
- SEQ_DEBUG(printf("seq_write: unit %d, event %s.\n", unit, midi_cmdname(ev_code, cmdtab_seqevent)));
-
- /* Have a look at the event code. */
- if (ev_code == SEQ_FULLSIZE) {
-
- /* A long event, these are the patches/samples for a synthesizer. */
- midiunit = *(u_short *)&event[2];
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- return (ret);
-
- SEQ_DEBUG(printf("seq_write: loading a patch to the unit %d.\n", midiunit));
-
- ret = md->synth.loadpatch(md, *(short *)&event[0], buf, p + 4, count, 0);
- return (ret);
- }
-
- if (ev_code >= 128) {
-
- /* Some sort of an extended event. The size is eight bytes. */
- if (scp->seq_mode == SND_DEV_MUSIC && ev_code == SEQ_EXTENDED) {
- printf("seq_write: invalid level two event %x.\n", ev_code);
- return (EINVAL);
- }
- ev_size = 8;
-
- if (count < ev_size) {
- /* No more data. Start playing now. */
- mtx_lock(&sd->flagqueue_mtx);
- if ((sd->flags & SEQ_F_WRITING) == 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- mtx_unlock(&sd->flagqueue_mtx);
- buf->uio_resid += 4;
-
- return (0);
- }
- if (uiomove((caddr_t)&event[4], 4, buf))
- printf("seq_write: user memory mangled?\n");
- } else {
-
- /* Not an extended event. The size is four bytes. */
- if (scp->seq_mode == SND_DEV_MUSIC) {
- printf("seq_write: four byte event in level two mode.\n");
- return (EINVAL);
- }
- ev_size = 4;
- }
- if (ev_code == SEQ_MIDIPUTC) {
- /* An event passed to the midi device itself. */
- midiunit = event[2];
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev_midi(scp, midiunit, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- return (ret);
- }
-
- SEQ_DEBUG(printf("seq_write: queueing event %s.\n", midi_cmdname(event[0], cmdtab_seqevent)));
- /* Now we queue the event. */
- mtx_lock(&sd->flagqueue_mtx);
- switch (seq_queue(scp, event)) {
- case EAGAIN:
- /* The queue is full. Start playing now. */
- if ((sd->flags & SEQ_F_WRITING) == 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- mtx_unlock(&sd->flagqueue_mtx);
- buf->uio_resid = count;
- SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
- if (count < countorg)
- return (0);
- return (EAGAIN);
- case EINTR:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
- return (EINTR);
- case ERESTART:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
- return (ERESTART);
- }
- mtx_unlock(&sd->flagqueue_mtx);
- p += ev_size;
- count -= ev_size;
- }
-
- /* We have written every single data. Start playing now. */
- mtx_lock(&sd->flagqueue_mtx);
- if ((sd->flags & SEQ_F_WRITING) == 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- mtx_unlock(&sd->flagqueue_mtx);
-
- SEQ_DEBUG(printf("seq_write: resid %d.\n", buf->uio_resid));
-
- return (0);
-}
-
-int
-seq_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- int unit, midiunit, ret, tmp;
- sc_p scp;
- seqdev_info *sd;
- mididev_info *md;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
- struct patmgr_info *patinfo;
- struct seq_event_rec *event;
- struct snd_size *sndsize;
-
- unit = MIDIUNIT(i_dev);
-
- SEQ_DEBUG(printf("seq_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_seqioctl)));
-
- if (unit >= NSEQ_MAX) {
- SEQ_DEBUG(printf("seq_ioctl: unit %d does not exist.\n", unit));
- return (ENXIO);
- }
- sd = get_seqdev_info(i_dev, &unit);
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = sd->softc;
-
- ret = 0;
-
- switch (cmd) {
-
- /*
- * we start with the new ioctl interface.
- */
- case AIONWRITE: /* how many bytes can be written ? */
- mtx_lock(&sd->flagqueue_mtx);
- *(int *)arg = sd->midi_dbuf_out.fl;
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: fl %d.\n", *(int *)arg));
- break;
-
- case AIOSSIZE: /* set the current blocksize */
- sndsize = (struct snd_size *)arg;
- SEQ_DEBUG(printf("seq_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
- mtx_lock(&sd->flagqueue_mtx);
- if (sndsize->play_size <= sd->midi_dbuf_out.unit_size && sndsize->rec_size <= sd->midi_dbuf_in.unit_size) {
- sd->midi_dbuf_out.blocksize = sd->midi_dbuf_out.unit_size;
- sd->midi_dbuf_in.blocksize = sd->midi_dbuf_in.unit_size;
- sndsize->play_size = sd->midi_dbuf_out.blocksize;
- sndsize->rec_size = sd->midi_dbuf_in.blocksize;
- sd->flags &= ~MIDI_F_HAS_SIZE;
- mtx_unlock(&sd->flagqueue_mtx);
- }
- else {
- if (sndsize->play_size > sd->midi_dbuf_out.bufsize / 4)
- sndsize->play_size = sd->midi_dbuf_out.bufsize / 4;
- if (sndsize->rec_size > sd->midi_dbuf_in.bufsize / 4)
- sndsize->rec_size = sd->midi_dbuf_in.bufsize / 4;
- /* Round up the size to the multiple of EV_SZ. */
- sd->midi_dbuf_out.blocksize =
- ((sndsize->play_size + sd->midi_dbuf_out.unit_size - 1)
- / sd->midi_dbuf_out.unit_size) * sd->midi_dbuf_out.unit_size;
- sd->midi_dbuf_in.blocksize =
- ((sndsize->rec_size + sd->midi_dbuf_in.unit_size - 1)
- / sd->midi_dbuf_in.unit_size) * sd->midi_dbuf_in.unit_size;
- sndsize->play_size = sd->midi_dbuf_out.blocksize;
- sndsize->rec_size = sd->midi_dbuf_in.blocksize;
- sd->flags |= MIDI_F_HAS_SIZE;
- mtx_unlock(&sd->flagqueue_mtx);
- }
-
- ret = 0;
- break;
-
- case AIOGSIZE: /* get the current blocksize */
- sndsize = (struct snd_size *)arg;
- mtx_lock(&sd->flagqueue_mtx);
- sndsize->play_size = sd->midi_dbuf_out.blocksize;
- sndsize->rec_size = sd->midi_dbuf_in.blocksize;
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
-
- ret = 0;
- break;
-
- case AIOSTOP:
- if (*(int *)arg == AIOSYNC_PLAY) {
-
- /* Stop writing. */
- mtx_lock(&sd->flagqueue_mtx);
- sd->callback(sd, SEQ_CB_ABORT | SEQ_CB_WR);
- mtx_unlock(&sd->flagqueue_mtx);
-
- /* Pass the ioctl to the midi devices. */
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if ((md->flags & MIDI_F_WRITING) != 0)
- midi_ioctl(MIDIMKDEV(major(i_dev), md->unit, SND_DEV_MIDIN), cmd, (caddr_t)arg, mode, td);
- }
-
- mtx_lock(&sd->flagqueue_mtx);
- *(int *)arg = sd->midi_dbuf_out.rl;
- mtx_unlock(&sd->flagqueue_mtx);
- }
- else if (*(int *)arg == AIOSYNC_CAPTURE) {
-
- /* Stop reading. */
- mtx_lock(&sd->flagqueue_mtx);
- sd->callback(sd, SEQ_CB_ABORT | SEQ_CB_RD);
- mtx_unlock(&sd->flagqueue_mtx);
-
- /* Pass the ioctl to the midi devices. */
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if ((md->flags & MIDI_F_WRITING) != 0)
- midi_ioctl(MIDIMKDEV(major(i_dev), md->unit, SND_DEV_MIDIN), cmd, (caddr_t)arg, mode, td);
- }
-
- mtx_lock(&sd->flagqueue_mtx);
- *(int *)arg = sd->midi_dbuf_in.rl;
- mtx_unlock(&sd->flagqueue_mtx);
- }
-
- ret = 0;
- break;
-
- case AIOSYNC:
- mtx_lock(&sd->flagqueue_mtx);
- scp->sync_parm = *(snd_sync_parm *)arg;
- mtx_unlock(&sd->flagqueue_mtx);
-
- /* XXX Should select(2) against us watch the blocksize, or sync_parm? */
-
- ret = 0;
- break;
-
- case FIONBIO: /* set/clear non-blocking i/o */
- mtx_lock(&sd->flagqueue_mtx);
- if (*(int *)arg == 0)
- sd->flags &= ~SEQ_F_NBIO ;
- else
- sd->flags |= SEQ_F_NBIO ;
- mtx_unlock(&sd->flagqueue_mtx);
- MIDI_DEBUG(printf("seq_ioctl: arg %d.\n", *(int *)arg));
- break ;
-
- case SNDCTL_TMR_TIMEBASE:
- case SNDCTL_TMR_TEMPO:
- case SNDCTL_TMR_START:
- case SNDCTL_TMR_STOP:
- case SNDCTL_TMR_CONTINUE:
- case SNDCTL_TMR_METRONOME:
- case SNDCTL_TMR_SOURCE:
- mtx_lock(&sd->flagqueue_mtx);
- if (scp->seq_mode != SND_DEV_MUSIC) {
- ret = EINVAL;
- mtx_unlock(&sd->flagqueue_mtx);
- break;
- }
- mtx_unlock(&sd->flagqueue_mtx);
- /* XXX We should adopt am sx to protect scp->timer */
- ret = scp->timer->ioctl(scp->timer, cmd, arg, mode, td);
- break;
- case SNDCTL_TMR_SELECT:
- mtx_lock(&sd->flagqueue_mtx);
- if (scp->seq_mode != SND_DEV_MUSIC) {
- ret = EINVAL;
- mtx_unlock(&sd->flagqueue_mtx);
- break;
- }
- mtx_unlock(&sd->flagqueue_mtx);
- scp->pending_timer = *(int *)arg;
- mtx_lock(&sd->flagqueue_mtx);
- if (scp->pending_timer < 0) {
- scp->pending_timer = -1;
- ret = EINVAL;
- mtx_unlock(&sd->flagqueue_mtx);
- break;
- }
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: new timer %d.\n", *(int *)arg));
- ret = 0;
- break;
- case SNDCTL_SEQ_PANIC:
- mtx_lock(&sd->flagqueue_mtx);
- seq_panic(scp);
- mtx_unlock(&sd->flagqueue_mtx);
- ret = 0;
- break;
- case SNDCTL_SEQ_SYNC:
- if (mode == O_RDONLY) {
- ret = 0;
- break;
- }
- mtx_lock(&scp->devinfo->flagqueue_mtx);
- ret = seq_sync(scp);
- mtx_unlock(&scp->devinfo->flagqueue_mtx);
- break;
- case SNDCTL_SEQ_RESET:
- mtx_lock(&scp->devinfo->flagqueue_mtx);
- seq_reset(scp);
- mtx_unlock(&scp->devinfo->flagqueue_mtx);
- ret = 0;
- break;
- case SNDCTL_SEQ_TESTMIDI:
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev_midi(scp, *(int *)arg, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- break;
- case SNDCTL_SEQ_GETINCOUNT:
- if (mode == O_WRONLY)
- *(int *)arg = 0;
- else {
- mtx_lock(&sd->flagqueue_mtx);
- *(int *)arg = sd->midi_dbuf_in.rl;
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: incount %d.\n", *(int *)arg));
- }
- ret = 0;
- break;
- case SNDCTL_SEQ_GETOUTCOUNT:
- if (mode == O_RDONLY)
- *(int *)arg = 0;
- else {
- mtx_lock(&sd->flagqueue_mtx);
- *(int *)arg = sd->midi_dbuf_out.fl;
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: outcount %d.\n", *(int *)arg));
- }
- ret = 0;
- break;
- case SNDCTL_SEQ_CTRLRATE:
- mtx_lock(&sd->flagqueue_mtx);
- if (scp->seq_mode == SND_DEV_MUSIC) {
- mtx_unlock(&sd->flagqueue_mtx);
- ret = scp->timer->ioctl(scp->timer, cmd, arg, mode, td);
- break;
- }
- mtx_unlock(&sd->flagqueue_mtx);
- if (*(int *)arg != 0) {
- ret = EINVAL;
- break;
- }
- *(int *)arg = hz;
- SEQ_DEBUG(printf("seq_ioctl: ctrlrate %d.\n", *(int *)arg));
- ret = 0;
- break;
- case SNDCTL_SEQ_RESETSAMPLES:
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_SEQ_NRSYNTHS:
- mtx_lock(&sd->flagqueue_mtx);
- if (scp->seq_mode == SND_DEV_MUSIC)
- *(int *)arg = mididev_synth_number() + mididev_midi_number();
- else
- *(int *)arg = mididev_synth_number();
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: synths %d.\n", *(int *)arg));
- ret = 0;
- break;
- case SNDCTL_SEQ_NRMIDIS:
- mtx_lock(&sd->flagqueue_mtx);
- if (scp->seq_mode == SND_DEV_MUSIC)
- *(int *)arg = 0;
- else
- *(int *)arg = mididev_midi_number();
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: midis %d.\n", *(int *)arg));
- ret = 0;
- break;
- case SNDCTL_SYNTH_MEMAVL:
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_FM_4OP_ENABLE:
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, *(int *)arg, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), *(int *)arg, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- midiunit = synthinfo->device;
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_SEQ_OUTOFBAND:
- event = (struct seq_event_rec *)arg;
- mtx_lock(&sd->flagqueue_mtx);
- ret = seq_playevent(scp, event->arr);
- mtx_unlock(&sd->flagqueue_mtx);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- midiunit = midiinfo->device;
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev_midi(scp, midiunit, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_PMGR_IFACE:
- patinfo = (struct patmgr_info *)arg;
- midiunit = patinfo->device;
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_PMGR_ACCESS:
- patinfo = (struct patmgr_info *)arg;
- midiunit = patinfo->device;
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, midiunit, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), midiunit, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- case SNDCTL_SEQ_THRESHOLD:
- mtx_lock(&sd->flagqueue_mtx);
- RANGE(*(int *)arg, 1, sd->midi_dbuf_out.bufsize - 1);
- scp->output_threshould = *(int *)arg;
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: threshold %d.\n", *(int *)arg));
- ret = 0;
- break;
- case SNDCTL_MIDI_PRETIME:
- tmp = *(int *)arg;
- if (tmp < 0)
- tmp = 0;
- mtx_lock(&sd->flagqueue_mtx);
- scp->pre_event_timeout = (hz * tmp) / 10;
- *(int *)arg = scp->pre_event_timeout;
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_ioctl: pretime %d.\n", *(int *)arg));
- ret = 0;
- break;
- default:
- if ((scp->fflags & O_ACCMODE) == FREAD) {
- ret = EIO;
- break;
- }
- mtx_lock(&sd->flagqueue_mtx);
- ret = lookup_mididev(scp, 0, LOOKUP_OPEN, &md);
- mtx_unlock(&sd->flagqueue_mtx);
- if (ret != 0)
- break;
- ret = midi_ioctl(MIDIMKDEV(major(i_dev), 0, SND_DEV_MIDIN), cmd, arg, mode, td);
- break;
- }
-
- return (ret);
-}
-
-int
-seq_poll(dev_t i_dev, int events, struct thread *td)
-{
- int unit, ret, lim;
- sc_p scp;
- seqdev_info *sd;
-
- unit = MIDIUNIT(i_dev);
-
- SEQ_DEBUG(printf("seq_poll: unit %d.\n", unit));
-
- if (unit >= NSEQ_MAX) {
- SEQ_DEBUG(printf("seq_poll: unit %d does not exist.\n", unit));
- return (ENXIO);
- }
- sd = get_seqdev_info(i_dev, &unit);
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_poll: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = sd->softc;
-
- mtx_lock(&sd->flagqueue_mtx);
-
- ret = 0;
-
- /* Look up the apropriate queue and select it. */
- if ((events & (POLLOUT | POLLWRNORM)) != 0) {
- /* Start playing. */
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
-
- /* Find out the boundary. */
- if ((sd->flags & SEQ_F_HAS_SIZE) != 0)
- lim = sd->midi_dbuf_out.blocksize;
- else
- lim = sd->midi_dbuf_out.unit_size;
- if (sd->midi_dbuf_out.fl < lim)
- /* No enough space, record select. */
- selrecord(td, &sd->midi_dbuf_out.sel);
- else
- /* We can write now. */
- ret |= events & (POLLOUT | POLLWRNORM);
- }
- if ((events & (POLLIN | POLLRDNORM)) != 0) {
- /* Start recording. */
- sd->callback(sd, SEQ_CB_START | SEQ_CB_RD);
-
- /* Find out the boundary. */
- if ((sd->flags & SEQ_F_HAS_SIZE) != 0)
- lim = sd->midi_dbuf_in.blocksize;
- else
- lim = sd->midi_dbuf_in.unit_size;
- if (sd->midi_dbuf_in.rl < lim)
- /* No data ready, record select. */
- selrecord(td, &sd->midi_dbuf_in.sel);
- else
- /* We can write now. */
- ret |= events & (POLLIN | POLLRDNORM);
- }
-
- mtx_unlock(&sd->flagqueue_mtx);
-
- return (ret);
-}
-
-static void
-seq_intr(void *p, mididev_info *md)
-{
- sc_p scp;
- seqdev_info *sd;
-
- sd = (seqdev_info *)p;
- scp = sd->softc;
-
- mtx_lock(&sd->flagqueue_mtx);
-
- /* Restart playing if we have the data to output. */
- if (scp->queueout_pending)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- /* Check the midi device if we are reading. */
- if ((sd->flags & SEQ_F_READING) != 0)
- seq_midiinput(scp, md);
-
- mtx_unlock(&sd->flagqueue_mtx);
-}
-
-static int
-seq_callback(void *d, int reason)
-{
- int unit;
- sc_p scp;
- seqdev_info *sd;
-
- sd = (seqdev_info *)d;
-
- SEQ_DEBUG(printf("seq_callback: reason 0x%x.\n", reason));
-
- if (sd == NULL) {
- SEQ_DEBUG(printf("seq_callback: device not configured.\n"));
- return (ENXIO);
- }
- scp = sd->softc;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- switch (reason & SEQ_CB_REASON_MASK) {
- case SEQ_CB_START:
- if ((reason & SEQ_CB_RD) != 0 && (sd->flags & SEQ_F_READING) == 0)
- /* Begin recording. */
- sd->flags |= SEQ_F_READING;
- if ((reason & SEQ_CB_WR) != 0 && (sd->flags & SEQ_F_WRITING) == 0)
- /* Start playing. */
- seq_startplay(scp);
- break;
- case SEQ_CB_STOP:
- case SEQ_CB_ABORT:
- if ((reason & SEQ_CB_RD) != 0 && (sd->flags & SEQ_F_READING) != 0) {
- /* Stop recording. */
- sd->flags &= ~SEQ_F_READING;
- scp->seq_time = seq_gettime();
- scp->prev_input_time = 0;
- }
- if ((reason & SEQ_CB_WR) != 0 && (sd->flags & SEQ_F_WRITING) != 0) {
- /* Stop Playing. */
- sd->flags &= ~SEQ_F_WRITING;
- scp->queueout_pending = 0;
- scp->seq_time = seq_gettime();
- scp->prev_input_time = 0;
-
- /* Stop the timer. */
- seq_stoptimer(scp);
- }
- }
-
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-static int
-seq_queue(sc_p scp, u_char *note)
-{
- int unit, err, lenw;
- seqdev_info *sd;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- SEQ_DEBUG(printf("seq_queue: unit %d.\n", unit));
-
- if ((sd->flags & SEQ_F_INSYNC) != 0)
- cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
-
- if (sd->midi_dbuf_out.fl < EV_SZ) {
- /* We have no space. Start playing if not yet. */
- if ((sd->flags & SEQ_F_WRITING) == 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_out.fl < EV_SZ)
- /* We would block. */
- return (EAGAIN);
- }
-
- /* Write to the queue. */
- err = midibuf_seqwrite(&sd->midi_dbuf_out, note, EV_SZ, &lenw,
- sd->callback, sd, SEQ_CB_START | SEQ_CB_WR,
- &sd->flagqueue_mtx);
-
- if (err == 0) {
- /* Start playing if we have some data in the queue. */
- if (sd->midi_dbuf_out.rl >= EV_SZ && ((sd->flags & SEQ_F_WRITING) == 0))
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- }
-
- return (err);
-}
-
-static void
-seq_startplay(sc_p scp)
-{
- int unit, lenr;
- u_char event[EV_SZ];
- seqdev_info *sd;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- sd->flags |= SEQ_F_WRITING;
-
- /* Dequeue the events to play. */
- while (sd->midi_dbuf_out.rl >= EV_SZ) {
-
- midibuf_seqcopy(&sd->midi_dbuf_out, event, EV_SZ, &lenr,
- NULL, NULL, 0,
- &sd->flagqueue_mtx);
-
- switch (seq_playevent(scp, event)) {
- case TIMERARMED:
- midibuf_seqdelete(&sd->midi_dbuf_out, EV_SZ, &lenr,
- NULL, NULL, 0,
- &sd->flagqueue_mtx);
- return;
- case QUEUEFULL:
- /* We cannot play any further. */
- return;
- case MORE:
- midibuf_seqdelete(&sd->midi_dbuf_out, EV_SZ, &lenr,
- NULL, NULL, 0,
- &sd->flagqueue_mtx);
- break;
- }
- }
-
- /* Played every event in the queue. */
- sd->flags &= ~SEQ_F_WRITING;
-}
-
-static int
-seq_playevent(sc_p scp, u_char *event)
-{
- int unit, ret, lenw;
- long *delay;
- seqdev_info *sd;
- mididev_info *md;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- ret = lookup_mididev(scp, 0, LOOKUP_OPEN, &md);
- if (ret != 0)
- return (MORE);
-
- SEQ_DEBUG(printf("seq_playevent: unit %d, event %s.\n", sd->unit, midi_cmdname(event[0], cmdtab_seqevent)));
-
- switch(event[0]) {
- case SEQ_NOTEOFF:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_playevent: chn %d, note %d, vel %d.\n", event[1], event[2], event[3]));
- if (md->synth.killnote(md, event[1], 255, event[3]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- ret = QUEUEFULL;
- break;
- }
- mtx_lock(&sd->flagqueue_mtx);
- ret = MORE;
- break;
- case SEQ_NOTEON:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_playevent: chn %d, note %d, vel %d, aux %d.\n", event[1], event[2], event[3], event[4]));
- if ((event[4] < 128 || event[4] == 255) && md->synth.startnote(md, event[1], event[2], event[3]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- ret = QUEUEFULL;
- break;
- }
- mtx_lock(&sd->flagqueue_mtx);
- ret = MORE;
- break;
- case SEQ_WAIT:
-
- /* Extract the delay. */
- delay = (long *)event;
- *delay = (*delay >> 8) & 0xffffff;
- SEQ_DEBUG(printf("seq_playevent: delay %ld.\n", *delay));
- if (*delay > 0) {
- /* Arm the timer. */
- sd->flags |= SEQ_F_WRITING;
- if (seq_requesttimer(scp, *delay)) {
- ret = TIMERARMED;
- break;
- }
- }
- ret = MORE;
- break;
- case SEQ_PGMCHANGE:
- SEQ_DEBUG(printf("seq_playevent: chn %d, instr %d.\n", event[1], event[2]));
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.setinstr(md, event[1], event[2]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- ret = QUEUEFULL;
- break;
- }
- mtx_lock(&sd->flagqueue_mtx);
- ret = MORE;
- break;
- case SEQ_SYNCTIMER:
- /* Reset the timer. */
- scp->seq_time = seq_gettime();
- scp->prev_input_time = 0;
- scp->prev_event_time = 0;
- scp->prev_wakeup_time = scp->seq_time;
- ret = MORE;
- break;
- case SEQ_MIDIPUTC:
- SEQ_DEBUG(printf("seq_playevent: data 0x%02x, unit %d.\n", event[1], event[2]));
- /* Pass through to the midi device. */
- ret = lookup_mididev_midi(scp, event[2], LOOKUP_OPEN, &md);
- if (ret != 0) {
- ret = MORE;
- break;
- }
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.writeraw(md, &event[1], sizeof(event[1]), &lenw, 1) == EAGAIN)
- /* The queue was full. Try again later. */
- ret = QUEUEFULL;
- else
- ret = MORE;
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_ECHO:
- /* Echo this event back. */
- if (seq_copytoinput(scp, event, 4) == EAGAIN) {
- ret = QUEUEFULL;
- break;
- }
- ret = MORE;
- break;
- case SEQ_PRIVATE:
- ret = lookup_mididev(scp, event[1], LOOKUP_OPEN, &md);
- if (ret != 0) {
- ret = MORE;
- break;
- }
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.hwcontrol(md, event) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- ret = QUEUEFULL;
- break;
- }
- mtx_lock(&sd->flagqueue_mtx);
- ret = MORE;
- break;
- case SEQ_EXTENDED:
- ret = seq_extended(scp, event);
- break;
- case EV_CHN_VOICE:
- ret = seq_chnvoice(scp, event);
- break;
- case EV_CHN_COMMON:
- ret = seq_chncommon(scp, event);
- break;
- case EV_TIMING:
- ret = seq_timing(scp, event);
- break;
- case EV_SEQ_LOCAL:
- ret = seq_local(scp, event);
- break;
- case EV_SYSEX:
- ret = seq_sysex(scp, event);
- break;
- default:
- ret = MORE;
- break;
- }
-
- switch (ret) {
- case QUEUEFULL:
- SEQ_DEBUG(printf("seq_playevent: the queue is full.\n"));
- /* The queue was full. Try again on the interrupt by the midi device. */
- sd->flags |= SEQ_F_WRITING;
- scp->queueout_pending = 1;
- break;
- case TIMERARMED:
- SEQ_DEBUG(printf("seq_playevent: armed timer.\n"));
- sd->flags |= SEQ_F_WRITING;
- /* FALLTHRU */
- case MORE:
- scp->queueout_pending = 0;
- break;
- }
-
- return (ret);
-}
-
-static u_long
-seq_gettime(void)
-{
- struct timeval timecopy;
-
- getmicrotime(&timecopy);
- return timecopy.tv_usec / (1000000 / hz) + (u_long) timecopy.tv_sec * hz;
-}
-
-static int
-seq_requesttimer(sc_p scp, int delay)
-{
- u_long cur_time, rel_base;
-
- SEQ_DEBUG(printf("seq_requesttimer: unit %d, delay %d.\n", scp->devinfo->unit, delay));
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- cur_time = seq_gettime();
-
- scp->prev_event_time = delay;
- if (delay < 0)
- /* Request a new timer. */
- delay = -delay;
- else {
- rel_base = cur_time - scp->seq_time;
- if (delay <= rel_base) {
- seq_stoptimer(scp);
- return 0;
- }
- delay -= rel_base;
- }
-
-#if notdef
- /*
- * Compensate the delay of midi message transmission.
- * XXX Do we have to consider the accumulation of errors
- * less than 1/hz second?
- */
- delay -= (cur_time - scp->prev_wakeup_time);
- if (delay < 1) {
- printf("sequencer: prev = %lu, cur = %lu, delay = %d, skip sleeping.\n",
- scp->prev_wakeup_time, cur_time, delay);
- seq_stoptimer(scp);
- return 0;
- }
-#endif /* notdef */
-
- callout_reset(&scp->timeout_ch, delay, seq_timer, (void *)scp);
- scp->timer_running = 1;
-
- return 1;
-}
-
-static void
-seq_stoptimer(sc_p scp)
-{
- SEQ_DEBUG(printf("seq_stoptimer: unit %d.\n", scp->devinfo->unit));
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- if (scp->timer_running) {
- callout_stop(&scp->timeout_ch);
- scp->timer_running = 0;
- }
-}
-
-static void
-seq_midiinput(sc_p scp, mididev_info *md)
-{
- int unit, midiunit, lenr;
- u_long tstamp;
- u_char event[4];
- seqdev_info *sd;
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- /* Can this midi device interrupt for input? */
- midiunit = md->midiunit;
- if (lookup_mididev_midi(scp, midiunit, LOOKUP_EXIST, NULL) != 0)
- return;
-
- if ((md->flags & MIDI_F_READING) != 0 && md->intrarg == sd) {
- /* Read the input data. */
- mtx_unlock(&scp->devinfo->flagqueue_mtx);
- while (md->synth.readraw(md, &event[1], sizeof(event[1]), &lenr, 1) == 0) {
- mtx_lock(&scp->devinfo->flagqueue_mtx);
- tstamp = seq_gettime() - scp->seq_time;
- if (tstamp != scp->prev_input_time) {
- /* Insert a wait between events. */
- tstamp = (tstamp << 8) | SEQ_WAIT;
- seq_copytoinput(scp, (u_char *)&tstamp, 4);
- scp->prev_input_time = tstamp;
- }
- bzero(event, sizeof(event));
- event[0] = SEQ_MIDIPUTC;
- event[2] = midiunit;
- event[3] = 0;
- seq_copytoinput(scp, event, sizeof(event));
- mtx_unlock(&scp->devinfo->flagqueue_mtx);
- }
- mtx_lock(&scp->devinfo->flagqueue_mtx);
- }
-}
-
-int
-seq_copytoinput(void *arg, u_char *event, int len)
-{
- int ret, leni;
- sc_p scp;
- seqdev_info *sd;
-
- scp = arg;
- sd = scp->devinfo;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- if (len != 4 && len != 8)
- return (EINVAL);
- if (scp->seq_mode == SND_DEV_MUSIC && len != 8)
- return (EINVAL);
-
- ret = midibuf_input_intr(&sd->midi_dbuf_in, event, len, &leni);
- if (ret == EAGAIN)
- ret = 0;
-
- return (ret);
-}
-
-static int
-seq_extended(sc_p scp, u_char *event)
-{
- int unit;
- seqdev_info *sd;
- mididev_info *md;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- if (lookup_mididev(scp, event[2], LOOKUP_OPEN, &md) != 0)
- return (MORE);
-
- SEQ_DEBUG(printf("seq_extended: unit %d, event %s, midiunit %d.\n", unit, midi_cmdname(event[1], cmdtab_seqevent), event[2]));
-
- switch (event[1]) {
- case SEQ_NOTEOFF:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: chn %d, note %d, vel %d.\n", event[3], event[4], event[5]));
- if (md->synth.killnote(md, event[3], event[4], event[5]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_NOTEON:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: chn %d, note %d, vel %d.\n", event[3], event[4], event[5]));
- if ((event[4] < 128 || event[4] == 255) && md->synth.startnote(md, event[3], event[4], event[5]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_PGMCHANGE:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: chn %d, instr %d.\n", event[3], event[4]));
- if (md->synth.setinstr(md, event[3], event[4]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_AFTERTOUCH:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: chn %d, press %d.\n", event[3], event[4]));
- if (md->synth.aftertouch(md, event[3], event[4]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_BALANCE:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: chn %d, pan %d.\n", event[3], event[4]));
- if (md->synth.panning(md, event[3], (char)event[4]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_CONTROLLER:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: chn %d, ctrlnum %d, val %d.\n", event[3], event[4], *(short *)&event[5]));
- if (md->synth.controller(md, event[3], event[4], *(short *)&event[5]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case SEQ_VOLMODE:
- mtx_unlock(&sd->flagqueue_mtx);
- SEQ_DEBUG(printf("seq_extended: mode %d.\n", event[3]));
- if (md->synth.volumemethod != NULL && md->synth.volumemethod(md, event[3]) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- }
-
- return (MORE);
-}
-
-static int
-seq_chnvoice(sc_p scp, u_char *event)
-{
- int voice;
- seqdev_info *sd;
- mididev_info *md;
- u_char dev, cmd, chn, note, parm;
-
- voice = -1;
- dev = event[1];
- cmd = event[2];
- chn = event[3];
- note = event[4];
- parm = event[5];
-
- sd = scp->devinfo;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- if (lookup_mididev(scp, dev, LOOKUP_OPEN, &md) != 0)
- return (MORE);
-
- SEQ_DEBUG(printf("seq_chnvoice: unit %d, dev %d, cmd %s, chn %d, note %d, parm %d.\n",
- sd->unit,
- dev,
- midi_cmdname(cmd, cmdtab_seqcv),
- chn,
- note,
- parm));
-
- if (scp->seq_mode == SND_DEV_MUSIC && md->synth.allocvoice != NULL)
- voice = seq_allocvoice(scp, md, chn, note);
- switch (cmd) {
- case MIDI_NOTEON:
- if (note < 128 || note == 255) {
- if (voice == -1 && scp->seq_mode == SND_DEV_MUSIC && md->synth.allocvoice)
- /* This is an internal synthesizer. (FM, GUS, etc) */
- if ((voice = seq_allocvoice(scp, md, chn, note)) == EAGAIN)
- return (QUEUEFULL);
- if (voice == -1)
- voice = chn;
-
- if (scp->seq_mode == SND_DEV_MUSIC && chn == 9) {
- /* This channel is a percussion. The note number is the patch number. */
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.setinstr(md, voice, 128 + note) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
-
- note = 60; /* Middle C. */
- }
- if (scp->seq_mode == SND_DEV_MUSIC) {
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.setupvoice(md, voice, chn) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.startnote(md, voice, note, parm) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- break;
- case MIDI_NOTEOFF:
- if (voice == -1)
- voice = chn;
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.killnote(md, voice, note, parm) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- case MIDI_KEY_PRESSURE:
- if (voice == -1)
- voice = chn;
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.aftertouch(md, voice, parm) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- break;
- }
-
- return (MORE);
-}
-
-static int
-seq_findvoice(mididev_info *md, int chn, int note)
-{
- int i;
- u_short key;
-
- key = (chn << 8) | (note + 1);
-
- mtx_lock(&md->synth.vc_mtx);
- for (i = 0 ; i < md->synth.alloc.max_voice ; i++)
- if (md->synth.alloc.map[i] == key) {
- mtx_unlock(&md->synth.vc_mtx);
- return (i);
- }
- mtx_unlock(&md->synth.vc_mtx);
-
- return (-1);
-}
-
-static int
-seq_allocvoice(sc_p scp, mididev_info *md, int chn, int note)
-{
- int voice;
- u_short key;
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- key = (chn << 8) | (note + 1);
-
- mtx_unlock(&scp->devinfo->flagqueue_mtx);
- if ((voice = md->synth.allocvoice(md, chn, note, &md->synth.alloc)) == EAGAIN) {
- mtx_lock(&scp->devinfo->flagqueue_mtx);
- return (EAGAIN);
- }
- mtx_lock(&scp->devinfo->flagqueue_mtx);
-
- mtx_lock(&md->synth.vc_mtx);
- md->synth.alloc.map[voice] = key;
- md->synth.alloc.alloc_times[voice] = md->synth.alloc.timestamp++;
- mtx_unlock(&md->synth.vc_mtx);
-
- return (voice);
-}
-
-static int
-seq_chncommon(sc_p scp, u_char *event)
-{
- int unit, i, val, key;
- u_short w14;
- u_char dev, cmd, chn, p1;
- seqdev_info *sd;
- mididev_info *md;
-
- dev = event[1];
- cmd = event[2];
- chn = event[3];
- p1 = event[4];
- w14 = *(u_short *)&event[6];
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- if (lookup_mididev(scp, dev, LOOKUP_OPEN, &md) != 0)
- return (MORE);
-
- SEQ_DEBUG(printf("seq_chnvoice: unit %d, dev %d, cmd %s, chn %d, p1 %d, w14 %d.\n",
- sd->unit,
- dev,
- midi_cmdname(cmd, cmdtab_seqccmn),
- chn,
- p1,
- w14));
-
- switch (cmd) {
- case MIDI_PGM_CHANGE:
- if (scp->seq_mode == SND_DEV_MUSIC) {
- mtx_lock(&md->synth.vc_mtx);
- md->synth.chn_info[chn].pgm_num = p1;
- mtx_unlock(&md->synth.vc_mtx);
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->midiunit >= 0) {
- if (md->synth.setinstr(md, chn, p1) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- }
- mtx_lock(&sd->flagqueue_mtx);
- } else {
- /* For Mode 1. */
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.setinstr(md, chn, p1) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- break;
- case MIDI_CTL_CHANGE:
- /* mtx_lock(&md->giant); */
- if (scp->seq_mode == SND_DEV_MUSIC) {
- if (chn < 16 && p1 < 128) {
- mtx_lock(&md->synth.vc_mtx);
- md->synth.chn_info[chn].controllers[p1] = w14 & 0x7f;
- if (p1 < 32)
- /* We have set the MSB, clear the LSB. */
- md->synth.chn_info[chn].controllers[p1 + 32] = 0;
- if (md->midiunit >= 0) {
- val = w14 & 0x7f;
- if (p1 < 64) {
- /* Combine the MSB and the LSB. */
- val = ((md->synth.chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7)
- | (md->synth.chn_info[chn].controllers[p1 | 32] & 0x7f);
- p1 &= ~32;
- }
- /* Handle all of the notes playing on this channel. */
- key = ((int)chn << 8);
- for (i = 0 ; i < md->synth.alloc.max_voice ; i++)
- if ((md->synth.alloc.map[i] & 0xff00) == key) {
- mtx_unlock(&md->synth.vc_mtx);
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.controller(md, i, p1, val) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- mtx_lock(&md->synth.vc_mtx);
- }
- mtx_unlock(&md->synth.vc_mtx);
- } else {
- mtx_unlock(&md->synth.vc_mtx);
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.controller(md, chn, p1, w14) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- }
- } else {
- /* For Mode 1. */
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.controller(md, chn, p1, w14) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- break;
- case MIDI_PITCH_BEND:
- if (scp->seq_mode == SND_DEV_MUSIC) {
- mtx_lock(&md->synth.vc_mtx);
- md->synth.chn_info[chn].bender_value = w14;
- if (md->midiunit >= 0) {
- /* Handle all of the notes playing on this channel. */
- key = ((int)chn << 8);
- for (i = 0 ; i < md->synth.alloc.max_voice ; i++)
- if ((md->synth.alloc.map[i] & 0xff00) == key) {
- mtx_unlock(&md->synth.vc_mtx);
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.bender(md, i, w14) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- } else {
- mtx_unlock(&md->synth.vc_mtx);
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.bender(md, chn, w14) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- } else {
- /* For Mode 1. */
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.bender(md, chn, w14) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
- break;
- }
-
- return (MORE);
-}
-
-static int
-seq_timing(sc_p scp, u_char *event)
-{
- int unit, ret;
- long parm;
- seqdev_info *sd;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- parm = *(long *)&event[4];
-
- if (scp->seq_mode == SND_DEV_MUSIC) {
- ret = scp->timer->event(scp->timer, event);
- if (ret == TIMERARMED)
- sd->flags |= SEQ_F_WRITING;
- return (ret);
- }
-
- SEQ_DEBUG(printf("seq_timing: unit %d, cmd %s, parm %lu.\n",
- unit, midi_cmdname(event[1], cmdtab_timer), parm));
-
- ret = MORE;
- switch (event[1]) {
- case TMR_WAIT_REL:
- parm += scp->prev_event_time;
- /* FALLTHRU */
- case TMR_WAIT_ABS:
- if (parm > 0) {
- sd->flags |= SEQ_F_WRITING;
- if (seq_requesttimer(scp, parm))
- ret = TIMERARMED;
- }
- break;
- case TMR_START:
- scp->seq_time = seq_gettime();
- scp->prev_input_time = 0;
- scp->prev_event_time = 0;
- scp->prev_wakeup_time = scp->seq_time;
- break;
- case TMR_STOP:
- break;
- case TMR_CONTINUE:
- break;
- case TMR_TEMPO:
- break;
- case TMR_ECHO:
- if (scp->seq_mode == SND_DEV_MUSIC)
- seq_copytoinput(scp, event, 8);
- else {
- parm = (parm << 8 | SEQ_ECHO);
- seq_copytoinput(scp, (u_char *)&parm, 4);
- }
- break;
- }
-
- SEQ_DEBUG(printf("seq_timing: timer %s.\n",
- ret == TIMERARMED ? "armed" : "not armed"));
-
- return (ret);
-}
-
-static int
-seq_local(sc_p scp, u_char *event)
-{
- int unit;
- seqdev_info *sd;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- switch (event[1]) {
- case LOCL_STARTAUDIO:
-#if notyet
- DMAbuf_start_devices(*(u_int *)&event[4]);
-#endif /* notyet */
- break;
- }
-
- return (MORE);
-}
-
-static int
-seq_sysex(sc_p scp, u_char *event)
-{
- int unit, i, l;
- seqdev_info *sd;
- mididev_info *md;
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- if (lookup_mididev(scp, event[1], LOOKUP_OPEN, &md) != 0)
- return (MORE);
-
- l = 0;
- for (i = 0 ; i < 6 && event[i + 2] != 0xff ; i++)
- l = i + 1;
- if (l > 0) {
- mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.sendsysex(md, &event[2], l) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
- return (QUEUEFULL);
- }
- mtx_lock(&sd->flagqueue_mtx);
- }
-
- return (MORE);
-}
-
-void
-seq_timer(void *arg)
-{
- sc_p scp;
- seqdev_info *sd;
-
- scp = arg;
- sd = scp->devinfo;
-
- SEQ_DEBUG(printf("seq_timer: unit %d, timer fired.\n", sd->unit));
-
- /* Record the current timestamp. */
- mtx_lock(&sd->flagqueue_mtx);
-
- scp->timer_running = 0;
- scp->prev_wakeup_time = seq_gettime();
- seq_startplay(scp);
-
- mtx_unlock(&sd->flagqueue_mtx);
-}
-
-static int
-seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td)
-{
- int midiunit, err, insync, chn;
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- midiunit = md->unit;
-
- SEQ_DEBUG(printf("seq_openmidi: opening midi unit %d.\n", midiunit));
-
- err = midi_open(MIDIMKDEV(MIDI_CDEV_MAJOR, midiunit, SND_DEV_MIDIN), flags, mode, td);
- if (err != 0) {
- printf("seq_openmidi: failed to open midi device %d.\n", midiunit);
- return (err);
- }
- mtx_lock(&md->synth.status_mtx);
- mtx_lock(&md->flagqueue_mtx);
- md->intr = seq_intr;
- md->intrarg = scp->devinfo;
- mtx_unlock(&md->flagqueue_mtx);
- md->synth.sysex_state = 0;
- if (scp->seq_mode == SND_DEV_MUSIC) {
- for (chn = 0 ; chn < 16 ; chn++) {
- md->synth.chn_info[chn].pgm_num = 0;
- md->synth.reset(md);
- md->synth.chn_info[chn].bender_value = (1 << 7);
- }
- }
- mtx_unlock(&md->synth.status_mtx);
-
- insync = 0;
- if ((scp->devinfo->flags & SEQ_F_INSYNC) != 0) {
- insync = 1;
- cv_wait(&scp->devinfo->insync_cv, &scp->devinfo->flagqueue_mtx);
- }
-
- TAILQ_INSERT_TAIL(&scp->midi_open, md, md_linkseq);
-
- if (insync)
- cv_broadcast(&scp->devinfo->insync_cv);
-
- return (0);
-}
-
-static int
-seq_closemidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td)
-{
- int midiunit, insync;
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- if (md == NULL || !MIDICONFED(md)) {
- SEQ_DEBUG(printf("seq_closemidi: midi device does not exist.\n"));
- return (ENXIO);
- }
- midiunit = md->unit;
-
- SEQ_DEBUG(printf("seq_closemidi: closing midi unit %d.\n", midiunit));
-
- midi_close(MIDIMKDEV(MIDI_CDEV_MAJOR, midiunit, SND_DEV_MIDIN), flags, mode, td);
- mtx_lock(&md->flagqueue_mtx);
- md->intr = NULL;
- md->intrarg = NULL;
- mtx_unlock(&md->flagqueue_mtx);
-
- insync = 0;
- if ((scp->devinfo->flags & SEQ_F_INSYNC) != 0) {
- insync = 1;
- cv_wait(&scp->devinfo->insync_cv, &scp->devinfo->flagqueue_mtx);
- }
-
- TAILQ_REMOVE(&scp->midi_open, md, md_linkseq);
-
- if (insync)
- cv_broadcast(&scp->devinfo->insync_cv);
-
- return (0);
-}
-
-static void
-seq_panic(sc_p scp)
-{
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- seq_reset(scp);
-}
-
-static int
-seq_reset(sc_p scp)
-{
- int unit, chn, lenw, ret;
- seqdev_info *sd;
- mididev_info *md;
- u_char c[3];
-
- sd = scp->devinfo;
- unit = sd->unit;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- SEQ_DEBUG(printf("seq_reset: unit %d.\n", unit));
-
- if ((sd->flags & SEQ_F_INSYNC) != 0)
- cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
-
- /* Stop reading and writing. */
- sd->callback(sd, SEQ_CB_ABORT | SEQ_CB_RD | SEQ_CB_WR);
-
- /* Clear the queues. */
- midibuf_clear(&sd->midi_dbuf_in);
- midibuf_clear(&sd->midi_dbuf_out);
-
- /* Reset the synthesizers. */
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq)
- md->synth.reset(md);
-
- if (scp->seq_mode == SND_DEV_MUSIC) {
- for (chn = 0 ; chn < 16 ; chn++) {
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- mtx_unlock(&sd->flagqueue_mtx);
- ret = 0;
- if (md->synth.controller(md, chn, 123, 0) == EAGAIN /* All notes off. */
- || md->synth.controller(md, chn, 121, 0) == EAGAIN /* Reset all controllers. */
- || md->synth.bender(md, chn, 1 << 13) == EAGAIN) /* Reset pitch bend. */
- ret = EAGAIN;
- mtx_lock(&sd->flagqueue_mtx);
- return (ret);
- }
- }
- } else {
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- for (chn = 0 ; chn < 16 ; chn++) {
- mtx_unlock(&sd->flagqueue_mtx);
- c[0] = 0xb0 | (chn & 0x0f);
- c[1] = (u_char)0x78; /* All sound off */
- c[2] = (u_char)0;
- md->synth.writeraw(md, c, 3, &lenw, 0);
- c[1] = (u_char)0x7b; /* All note off */
- md->synth.writeraw(md, c, 3, &lenw, 0);
- c[1] = (u_char)0x79; /* Reset all controller */
- md->synth.writeraw(md, c, 3, &lenw, 0);
- mtx_lock(&sd->flagqueue_mtx);
- }
- }
- seq_sync(scp);
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq)
- lookup_mididev(scp, md->unit, LOOKUP_CLOSE, NULL);
- }
-
- return (0);
-}
-
-#define SEQ_SYNC_TIMEOUT 8
-static int
-seq_sync(sc_p scp)
-{
- int i, rl;
- seqdev_info *sd;
- mididev_info *md;
-
- sd = scp->devinfo;
-
- mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
-
- SEQ_DEBUG(printf("seq_sync: unit %d.\n", sd->unit));
- sd->flags |= SEQ_F_INSYNC;
-
- while (sd->midi_dbuf_out.rl >= EV_SZ) {
- if ((sd->flags & SEQ_F_WRITING) == 0)
- sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
- rl = sd->midi_dbuf_out.rl;
- i = cv_timedwait_sig(&sd->midi_dbuf_out.cv_out, &sd->flagqueue_mtx, SEQ_SYNC_TIMEOUT * hz);
- if (i == EINTR || i == ERESTART) {
- if (i == EINTR)
- sd->callback(sd, SEQ_CB_STOP | SEQ_CB_WR);
- sd->flags &= ~SEQ_F_INSYNC;
- return (i);
- }
- if (i == EWOULDBLOCK && rl == sd->midi_dbuf_out.rl && !scp->timer_running) {
- /* A queue seems to be stuck up. Give up and clear queues. */
- sd->callback(sd, SEQ_CB_STOP | SEQ_CB_WR);
- midibuf_clear(&sd->midi_dbuf_out);
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- mtx_lock(&md->flagqueue_mtx);
- md->callback(md, MIDI_CB_ABORT | MIDI_CB_WR);
- midibuf_clear(&md->midi_dbuf_out);
- mtx_unlock(&md->flagqueue_mtx);
- }
- break;
- }
- }
-
- /*
- * Since syncing a midi device might block, unlock sd->flagqueue_mtx.
- * Keep sd->midi_dbuf_out from writing by setting SEQ_F_INSYNC.
- * sd->insync_cv is signalled when sync is finished.
- */
- mtx_unlock(&sd->flagqueue_mtx);
-
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- mtx_lock(&md->flagqueue_mtx);
- midi_sync(md);
- mtx_unlock(&md->flagqueue_mtx);
- }
-
- mtx_lock(&sd->flagqueue_mtx);
- sd->flags &= ~SEQ_F_INSYNC;
- cv_broadcast(&sd->insync_cv);
-
- return (0);
-}
-
-/*
- * a small utility function which, given a device number, returns
- * a pointer to the associated seqdev_info struct, and sets the unit
- * number.
- */
-static seqdev_info *
-get_seqdev_info(dev_t i_dev, int *unit)
-{
- int u;
-
- if (MIDIDEV(i_dev) != SND_DEV_SEQ && MIDIDEV(i_dev) != SND_DEV_MUSIC)
- return NULL;
- u = MIDIUNIT(i_dev);
- if (unit)
- *unit = u ;
-
- return get_seqdev_info_unit(u);
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated mididev_info struct.
- */
-seqdev_info *
-get_seqdev_info_unit(int unit)
-{
- seqdev_info *sd;
-
- mtx_lock(&seqinfo_mtx);
- TAILQ_FOREACH(sd, &seq_info, sd_link) {
- if (sd->unit == unit)
- break;
- }
- mtx_unlock(&seqinfo_mtx);
-
- return sd;
-}
-
-/* Create a new sequencer device info structure. */
-seqdev_info *
-create_seqdev_info_unit(int unit, seqdev_info *seq)
-{
- seqdev_info *sd, *sdnew;
-
- /* As malloc(9) might block, allocate seqdev_info now. */
- sdnew = malloc(sizeof(seqdev_info), M_DEVBUF, M_WAITOK | M_ZERO);
- if (sdnew == NULL)
- return NULL;
- bcopy(seq, sdnew, sizeof(seqdev_info));
- sdnew->unit = unit;
- midibuf_init(&sdnew->midi_dbuf_in);
- midibuf_init(&sdnew->midi_dbuf_out);
- mtx_init(&sdnew->flagqueue_mtx, "seqflq", NULL, MTX_DEF);
- cv_init(&sdnew->insync_cv, "seqins");
-
- mtx_lock(&seqinfo_mtx);
-
- TAILQ_FOREACH(sd, &seq_info, sd_link) {
- if (sd->unit == unit) {
- mtx_unlock(&seqinfo_mtx);
- midibuf_destroy(&sdnew->midi_dbuf_in);
- midibuf_destroy(&sdnew->midi_dbuf_out);
- mtx_destroy(&sdnew->flagqueue_mtx);
- cv_destroy(&sdnew->insync_cv);
- free(sdnew, M_DEVBUF);
- return sd;
- }
- }
-
- mtx_lock(&sdnew->flagqueue_mtx);
- TAILQ_INSERT_TAIL(&seq_info, sdnew, sd_link);
- nseq++;
-
- mtx_unlock(&seqinfo_mtx);
-
- return sdnew;
-}
-
-/*
- * Look up a midi device by its unit number opened by this sequencer.
- * If the device is not opened and mode is LOOKUP_OPEN, open the device.
- */
-static int
-lookup_mididev(sc_p scp, int unit, int mode, mididev_info **mdp)
-{
- int ret;
- mididev_info *md;
-
- if (mdp == NULL)
- mdp = &md;
-
- *mdp = NULL;
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if (scp->seq_mode == SND_DEV_MUSIC ? md->unit == unit : md->synthunit == unit) {
- *mdp = md;
- if (mode == LOOKUP_CLOSE)
- return seq_closemidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
-
- return (md != NULL && MIDICONFED(md)) ? 0 : ENXIO;
- }
- }
-
- if (mode == LOOKUP_OPEN) {
- if (scp->seq_mode == SND_DEV_MUSIC)
- md = get_mididev_info_unit(unit);
- else
- md = get_mididev_synth_unit(unit);
- if (md != NULL) {
- *mdp = md;
- ret = seq_openmidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
- return ret;
- }
- }
-
- return ENXIO;
-}
-
-/*
- * Look up a midi device by its midi unit number opened by this sequencer.
- * If the device is not opened and mode is LOOKUP_OPEN, open the device.
- */
-static int
-lookup_mididev_midi(sc_p scp, int unit, int mode, mididev_info **mdp)
-{
- int ret;
- mididev_info *md;
-
- if (mdp == NULL)
- mdp = &md;
-
- *mdp = NULL;
-
- if (scp->seq_mode == SND_DEV_MUSIC)
- return (ENXIO);
-
- mtx_assert(&scp->devinfo->flagqueue_mtx, MA_OWNED);
-
- TAILQ_FOREACH(md, &scp->midi_open, md_linkseq) {
- if (md->midiunit == unit) {
- *mdp = md;
- if (mode == LOOKUP_CLOSE)
- return seq_closemidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
-
- return (md != NULL && MIDICONFED(md)) ? 0 : ENXIO;
- }
- }
-
- if (mode == LOOKUP_OPEN) {
- md = get_mididev_midi_unit(unit);
- if (md != NULL) {
- *mdp = md;
- ret = seq_openmidi(scp, md, scp->fflags, MIDIDEV_MODE, curthread);
- return ret;
- }
- }
-
- return ENXIO;
-}
-
-/* XXX These functions are actually redundant. */
-static int
-seqopen(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_SEQ:
- case MIDI_DEV_MUSIC:
- return seq_open(i_dev, flags, mode, td);
- }
-
- return (ENXIO);
-}
-
-static int
-seqclose(dev_t i_dev, int flags, int mode, struct thread *td)
-{
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_SEQ:
- case MIDI_DEV_MUSIC:
- return seq_close(i_dev, flags, mode, td);
- }
-
- return (ENXIO);
-}
-
-static int
-seqread(dev_t i_dev, struct uio * buf, int flag)
-{
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_SEQ:
- case MIDI_DEV_MUSIC:
- return seq_read(i_dev, buf, flag);
- }
-
- return (ENXIO);
-}
-
-static int
-seqwrite(dev_t i_dev, struct uio * buf, int flag)
-{
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_SEQ:
- case MIDI_DEV_MUSIC:
- return seq_write(i_dev, buf, flag);
- }
-
- return (ENXIO);
-}
-
-static int
-seqioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_SEQ:
- case MIDI_DEV_MUSIC:
- return seq_ioctl(i_dev, cmd, arg, mode, td);
- }
-
- return (ENXIO);
-}
-
-static int
-seqpoll(dev_t i_dev, int events, struct thread *td)
-{
- switch (MIDIDEV(i_dev)) {
- case MIDI_DEV_SEQ:
- case MIDI_DEV_MUSIC:
- return seq_poll(i_dev, events, td);
- }
-
- return (ENXIO);
-}
-
-static int
-seq_modevent(module_t mod, int type, void *data)
-{
- int retval;
-
- retval = 0;
-
- switch (type) {
- case MOD_LOAD:
- seq_init();
- break;
-
- case MOD_UNLOAD:
- printf("sequencer: unload not supported yet.\n");
- retval = EOPNOTSUPP;
- break;
-
- default:
- break;
- }
-
- return retval;
-}
-
-DEV_MODULE(seq, seq_modevent, NULL);
-
-static void
-seq_clone(arg, name, namelen, dev)
- void *arg;
- char *name;
- int namelen;
- dev_t *dev;
-{
- int u;
-
- if (*dev != NODEV)
- return;
- if (bcmp(name, "sequencer", 9) != 0)
- return;
- if (name[10] != '\0' && name[11] != '\0')
- return;
- u = name[9] - '0';
- if (name[10] != '\0') {
- u *= 10;
- u += name[10] - '0';
- }
- seq_initunit(u);
- *dev = MIDIMKDEV(SEQ_CDEV_MAJOR, u, MIDI_DEV_SEQ);
- return;
-}
diff --git a/sys/dev/sound/midi/sequencer.h b/sys/dev/sound/midi/sequencer.h
deleted file mode 100644
index c5db26420131..000000000000
--- a/sys/dev/sound/midi/sequencer.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Include file for midi sequencer driver.
- *
- * Copyright by Seigo Tanimura 1999.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-/*
- * first, include kernel header files.
- */
-
-#ifndef _SEQUENCER_H_
-#define _SEQUENCER_H_
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ioccom.h>
-
-#include <sys/filio.h>
-#include <sys/sockio.h>
-#include <sys/fcntl.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-
-#include <sys/kernel.h> /* for DATA_SET */
-
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/syslog.h>
-#include <sys/errno.h>
-#include <sys/malloc.h>
-#include <sys/condvar.h>
-#include <machine/clock.h> /* for DELAY */
-#include <sys/soundcard.h>
-
-#include <dev/sound/midi/timer.h>
-
-#define SEQ_CDEV_MAJOR MIDI_CDEV_MAJOR
-
-/*
- * the following assumes that FreeBSD 3.X uses poll(2) instead of select(2).
- * This change dates to late 1997.
- */
-#include <sys/poll.h>
-#define d_select_t d_poll_t
-
-/* Return value from seq_playevent and timer event handers. */
-enum {
- MORE,
- TIMERARMED,
- QUEUEFULL
-};
-
-typedef struct _seqdev_info seqdev_info;
-
-/*
- * The order of mutex lock (from the first to the last)
- *
- * 1. sequencer flags, queues, timer and device list
- * 2. midi synth voice and channel
- * 3. midi synth status
- * 4. generic midi flags and queues
- * 5. midi device
- */
-
-/*
- * descriptor of sequencer operations ...
- *
- */
-
-struct _seqdev_info {
-
- /*
- * the first part of the descriptor is filled up from a
- * template.
- */
- char name[64];
-
- int type ;
-
- d_open_t *open;
- d_close_t *close;
- d_read_t *read;
- d_write_t *write;
- d_ioctl_t *ioctl;
- d_poll_t *poll;
- midi_callback_t *callback;
-
- /*
- * combinations of the following flags are used as second argument in
- * the callback from the dma module to the device-specific routines.
- */
-
-#define SEQ_CB_RD 0x100 /* read callback */
-#define SEQ_CB_WR 0x200 /* write callback */
-#define SEQ_CB_REASON_MASK 0xff
-#define SEQ_CB_START 0x01 /* start dma op */
-#define SEQ_CB_STOP 0x03 /* stop dma op */
-#define SEQ_CB_ABORT 0x04 /* abort dma op */
-#define SEQ_CB_INIT 0x05 /* init board parameters */
-
- /*
- * callback extensions
- */
-#define SEQ_CB_DMADONE 0x10
-#define SEQ_CB_DMAUPDATE 0x11
-#define SEQ_CB_DMASTOP 0x12
-
- /* init can only be called with int enabled and
- * no pending DMA activity.
- */
-
- /*
- * whereas from here, parameters are set at runtime.
- * io_base == 0 means that the board is not configured.
- */
-
- int unit; /* unit number of the device */
- void *softc; /* softc for a device */
-
- int bd_id ; /* used to hold board-id info, eg. sb version,
- * mss codec type, etc. etc.
- */
-
- struct mtx flagqueue_mtx; /* Mutex to protect flags and queues */
- struct cv insync_cv; /* Conditional variable for sync */
-
- /* Queues */
- midi_dbuf midi_dbuf_in; /* midi input event/message queue */
- midi_dbuf midi_dbuf_out; /* midi output event/message queue */
-
-
- /*
- * these parameters describe the operation of the board.
- * Generic things like busy flag, speed, etc are here.
- */
-
- /* Flags */
- volatile u_long flags ; /* 32 bits, used for various purposes. */
-
- /*
- * we have separate flags for read and write, although in some
- * cases this is probably not necessary (e.g. because we cannot
- * know how many processes are using the device, we cannot
- * distinguish if open, close, abort are for a write or for a
- * read).
- */
-
- /*
- * the following flag is used by open-close routines
- * to mark the status of the device.
- */
-#define SEQ_F_BUSY 0x0001 /* has been opened */
- /*
- * the next two are used to allow only one pending operation of
- * each type.
- */
-#define SEQ_F_READING 0x0004 /* have a pending read */
-#define SEQ_F_WRITING 0x0008 /* have a pending write */
-
- /*
- * flag used to mark a pending close.
- */
-#define SEQ_F_CLOSING 0x0040 /* a pending close */
-
- /*
- * if user has not set block size, then make it adaptive
- * (0.25s, or the perhaps last read/write ?)
- */
-#define SEQ_F_HAS_SIZE 0x0080 /* user set block size */
- /*
- * assorted flags related to operating mode.
- */
-#define SEQ_F_STEREO 0x0100 /* doing stereo */
-#define SEQ_F_NBIO 0x0200 /* do non-blocking i/o */
-
- /*
- * these flags mark a pending abort on a r/w operation.
- */
-#define SEQ_F_ABORTING 0x1000 /* a pending abort */
-
- /*
- * this is used to mark that board initialization is needed, e.g.
- * because of a change in sampling rate, format, etc. -- It will
- * be done at the next convenient time.
- */
-#define SEQ_F_INIT 0x4000 /* changed parameters. need init */
-
-#define SEQ_F_INSYNC 0x8000 /* a pending sync */
-
- int play_blocksize, rec_blocksize; /* blocksize for io and dma ops */
-
-#define swsel midi_dbuf_out.sel
-#define srsel midi_dbuf_in.sel
- u_long interrupts; /* counter of interrupts */
- u_long magic;
-#define MAGIC(unit) ( 0xa4d10de0 + unit )
- void *device_data ; /* just in case it is needed...*/
-
- /* The tailq entry of the next sequencer device. */
- TAILQ_ENTRY(_seqdev_info) sd_link;
-};
-
-
-/*
- * then ioctls and other stuff
- */
-#define NSEQ_MAX 16 /* Number of supported devices */
-
-/*
- * many variables should be reduced to a range. Here define a macro
- */
-
-#define RANGE(var, low, high) (var) = \
-((var)<(low)?(low) : (var)>(high)?(high) : (var))
-
-/*
- * finally, all default parameters
- */
-#define SEQ_BUFFSIZE (1024) /* XXX */
-
-#define MIDI_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
- synthesizer and MIDI output) */
-#define MIDI_DEV_MUSIC 8 /* Sequencer output /dev/music (FM
- synthesizer and MIDI output) */
-
-#ifdef _KERNEL
-
-extern midi_cmdtab cmdtab_seqioctl[];
-extern midi_cmdtab cmdtab_timer[];
-
-void seq_timer(void *arg);
-int seq_copytoinput(void *arg, u_char *event, int len);
-
-SYSCTL_DECL(_hw_midi_seq);
-
-extern int seq_debug;
-#define SEQ_DEBUG(x) \
- do { \
- if (seq_debug) { \
- (x); \
- } \
- } while(0)
-
-#endif /* _KERNEL */
-
-
-#endif /* _SEQUENCER_H_ */
diff --git a/sys/dev/sound/midi/timer.c b/sys/dev/sound/midi/timer.c
deleted file mode 100644
index ba4bce0d5828..000000000000
--- a/sys/dev/sound/midi/timer.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * This is the timer engine of /dev/music for FreeBSD.
- *
- * (C) 2002 Seigo Tanimura
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-#include <dev/sound/midi/midi.h>
-#include <dev/sound/midi/sequencer.h>
-
-#define TMR2TICKS(scp, tmr_val) \
- ((((tmr_val) * (scp)->tempo * (scp)->timebase) + (30 * hz)) / (60 * hz))
-#define CURTICKS(scp) \
- ((scp)->ticks_offset + (scp)->ticks_cur - (scp)->ticks_base)
-
-struct systmr_timer_softc {
- int running;
-
- u_long ticks_offset;
- u_long ticks_base;
- u_long ticks_cur;
-
- int tempo;
- int timebase;
-
- u_long nexteventtime;
- u_long preveventtime;
-
- struct callout timer;
-};
-
-static timeout_t systmr_timer;
-static void systmr_reset(timerdev_info *tmd);
-static u_long systmr_time(void);
-
-static tmr_open_t systmr_open;
-static tmr_close_t systmr_close;
-static tmr_event_t systmr_event;
-static tmr_gettime_t systmr_gettime;
-static tmr_ioctl_t systmr_ioctl;
-static tmr_armtimer_t systmr_armtimer;
-
-static timerdev_info systmr_timerdev = {
- "System clock",
- 0,
- 0,
- systmr_open,
- systmr_close,
- systmr_event,
- systmr_gettime,
- systmr_ioctl,
- systmr_armtimer,
-};
-
-static TAILQ_HEAD(,_timerdev_info) timer_info;
-static struct mtx timerinfo_mtx;
-static int timerinfo_mtx_init;
-static int ntimer;
-
-
-/* Install a system timer. */
-int
-timerdev_install(void)
-{
- int ret;
- timerdev_info *tmd;
- struct systmr_timer_softc *scp;
-
- SEQ_DEBUG(printf("timerdev_install: install a new timer.\n"));
-
- ret = 0;
- tmd = NULL;
- scp = NULL;
-
- scp = malloc(sizeof(*scp), M_DEVBUF, M_WAITOK | M_ZERO);
- if (scp == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- tmd = create_timerdev_info_unit(&systmr_timerdev);
- if (tmd == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- tmd->softc = scp;
- callout_init(&scp->timer, 0);
-
- mtx_unlock(&tmd->mtx);
-
- SEQ_DEBUG(printf("timerdev_install: installed a new timer, unit %d.\n", tmd->unit));
-
- return (0);
-
-fail:
- if (scp != NULL)
- free(scp, M_DEVBUF);
- if (tmd != NULL) {
- TAILQ_REMOVE(&timer_info, tmd, tmd_link);
- free(tmd, M_DEVBUF);
- }
-
- SEQ_DEBUG(printf("timerdev_install: installation failed.\n"));
-
- return (ret);
-}
-
-/* Create a new timer device info structure. */
-timerdev_info *
-create_timerdev_info_unit(timerdev_info *tmdinf)
-{
- int unit;
- timerdev_info *tmd, *tmdnew;
-
- /* XXX */
- if (!timerinfo_mtx_init) {
- timerinfo_mtx_init = 1;
- mtx_init(&timerinfo_mtx, "tmrinf", NULL, MTX_DEF);
- TAILQ_INIT(&timer_info);
- }
-
- /* As malloc(9) might block, allocate timerdev_info now. */
- tmdnew = malloc(sizeof(timerdev_info), M_DEVBUF, M_WAITOK | M_ZERO);
- if (tmdnew == NULL)
- return NULL;
- bcopy(tmdinf, tmdnew, sizeof(timerdev_info));
- mtx_init(&tmdnew->mtx, "tmrmtx", NULL, MTX_DEF);
-
- mtx_lock(&timerinfo_mtx);
-
- ntimer++;
-
- for (unit = 0 ; ; unit++) {
- TAILQ_FOREACH(tmd, &timer_info, tmd_link) {
- if (tmd->unit == unit)
- break;
- }
- if (tmd == NULL)
- break;
- }
-
- tmdnew->unit = unit;
- mtx_lock(&tmdnew->mtx);
- tmd = TAILQ_FIRST(&timer_info);
- while (tmd != NULL) {
- if (tmd->prio < tmdnew->prio)
- break;
- tmd = TAILQ_NEXT(tmd, tmd_link);
- }
- if (tmd != NULL)
- TAILQ_INSERT_BEFORE(tmd, tmdnew, tmd_link);
- else
- TAILQ_INSERT_TAIL(&timer_info, tmdnew, tmd_link);
-
- mtx_unlock(&timerinfo_mtx);
-
- return (tmdnew);
-}
-
-/*
- * a small utility function which, given a unit number, returns
- * a pointer to the associated timerdev_info struct.
- */
-timerdev_info *
-get_timerdev_info_unit(int unit)
-{
- timerdev_info *tmd;
-
- /* XXX */
- if (!timerinfo_mtx_init) {
- timerinfo_mtx_init = 1;
- mtx_init(&timerinfo_mtx, "tmrinf", NULL, MTX_DEF);
- TAILQ_INIT(&timer_info);
- }
-
- mtx_lock(&timerinfo_mtx);
- TAILQ_FOREACH(tmd, &timer_info, tmd_link) {
- mtx_lock(&tmd->mtx);
- if (tmd->unit == unit && tmd->seq == NULL)
- break;
- mtx_unlock(&tmd->mtx);
- }
- mtx_unlock(&timerinfo_mtx);
-
- return tmd;
-}
-
-/*
- * a small utility function which returns a pointer
- * to the best preferred timerdev_info struct with
- * no sequencer.
- */
-timerdev_info *
-get_timerdev_info(void)
-{
- timerdev_info *tmd;
-
- /* XXX */
- if (!timerinfo_mtx_init) {
- timerinfo_mtx_init = 1;
- mtx_init(&timerinfo_mtx, "tmrinf", NULL, MTX_DEF);
- TAILQ_INIT(&timer_info);
- }
-
- mtx_lock(&timerinfo_mtx);
- TAILQ_FOREACH(tmd, &timer_info, tmd_link) {
- mtx_lock(&tmd->mtx);
- if (tmd->seq == NULL)
- break;
- mtx_unlock(&tmd->mtx);
- }
- mtx_unlock(&timerinfo_mtx);
-
- return tmd;
-}
-
-
-/* ARGSUSED */
-static void
-systmr_timer(void *d)
-{
- timerdev_info *tmd;
- struct systmr_timer_softc *scp;
- void *seq;
-
- tmd = (timerdev_info *)d;
- scp = (struct systmr_timer_softc *)tmd->softc;
- seq = NULL;
-
- mtx_lock(&tmd->mtx);
-
- if (tmd->opened) {
- callout_reset(&scp->timer, 1, systmr_timer, tmd);
-
- if (scp->running) {
- scp->ticks_cur = TMR2TICKS(scp, systmr_time());
-
- if (CURTICKS(scp) >= scp->nexteventtime) {
- SEQ_DEBUG(printf("systmr_timer: CURTICKS %lu, call the sequencer.\n", CURTICKS(scp)));
- scp->nexteventtime = ULONG_MAX;
- seq = tmd->seq;
- }
- }
- }
-
- mtx_unlock(&tmd->mtx);
-
- if (seq != NULL)
- seq_timer(seq);
-}
-
-static void
-systmr_reset(timerdev_info *tmd)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- mtx_assert(&tmd->mtx, MA_OWNED);
-
- SEQ_DEBUG(printf("systmr_reset: unit %d.\n", tmd->unit));
-
- scp->ticks_offset = 0;
- scp->ticks_base = scp->ticks_cur = TMR2TICKS(scp, systmr_time());
-
- scp->nexteventtime = ULONG_MAX;
- scp->preveventtime = 0;
-}
-
-static u_long
-systmr_time(void)
-{
- struct timeval timecopy;
-
- getmicrotime(&timecopy);
- return timecopy.tv_usec / (1000000 / hz) + (u_long) timecopy.tv_sec * hz;
-}
-
-
-/* ARGSUSED */
-static int
-systmr_open(timerdev_info *tmd, int oflags, int devtype, struct thread *td)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_open: unit %d.\n", tmd->unit));
-
- mtx_lock(&tmd->mtx);
-
- if (tmd->opened) {
- mtx_unlock(&tmd->mtx);
- return (EBUSY);
- }
-
- systmr_reset(tmd);
- scp->tempo = 60;
- scp->timebase = hz;
- tmd->opened = 1;
-
- callout_reset(&scp->timer, 1, systmr_timer, tmd);
-
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
-
-static int
-systmr_close(timerdev_info *tmd, int fflag, int devtype, struct thread *td)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_close: unit %d.\n", tmd->unit));
-
- mtx_lock(&tmd->mtx);
-
- tmd->opened = 0;
- scp->running = 0;
-
- callout_stop(&scp->timer);
-
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
-
-static int
-systmr_event(timerdev_info *tmd, u_char *ev)
-{
- struct systmr_timer_softc *scp;
- u_char cmd;
- u_long parm, t;
- int ret;
- void * seq;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
- cmd = ev[1];
- parm = *(int *)&ev[4];
- ret = MORE;
-
- SEQ_DEBUG(printf("systmr_event: unit %d, cmd %s, parm %lu.\n",
- tmd->unit, midi_cmdname(cmd, cmdtab_timer), parm));
-
- mtx_lock(&tmd->mtx);
-
- switch (cmd) {
- case TMR_WAIT_REL:
- parm += scp->preveventtime;
- /* FALLTHRU */
- case TMR_WAIT_ABS:
- if (parm > 0) {
- if (parm <= CURTICKS(scp))
- break;
- t = parm;
- scp->nexteventtime = scp->preveventtime = t;
- ret = TIMERARMED;
- break;
- }
- break;
-
- case TMR_START:
- systmr_reset(tmd);
- scp->running = 1;
- break;
-
- case TMR_STOP:
- scp->running = 0;
- break;
-
- case TMR_CONTINUE:
- scp->running = 1;
- break;
-
- case TMR_TEMPO:
- if (parm > 0) {
- RANGE(parm, 8, 360);
- scp->ticks_offset += scp->ticks_cur
- - scp->ticks_base;
- scp->ticks_base = scp->ticks_cur;
- scp->tempo = parm;
- }
- break;
-
- case TMR_ECHO:
- seq = tmd->seq;
- mtx_unlock(&tmd->mtx);
- seq_copytoinput(seq, ev, 8);
- mtx_lock(&tmd->mtx);
- break;
- }
-
- mtx_unlock(&tmd->mtx);
-
- SEQ_DEBUG(printf("systmr_event: timer %s.\n",
- ret == TIMERARMED ? "armed" : "not armed"));
-
- return (ret);
-}
-
-static int
-systmr_gettime(timerdev_info *tmd, u_long *t)
-{
- struct systmr_timer_softc *scp;
- int ret;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_gettime: unit %d.\n", tmd->unit));
-
- mtx_lock(&tmd->mtx);
-
- if (!tmd->opened || t == NULL) {
- ret = EINVAL;
- goto fail;
- }
-
- *t = CURTICKS(scp);
- SEQ_DEBUG(printf("systmr_gettime: ticks %lu.\n", *t));
-
-fail:
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
-
-static int
-systmr_ioctl(timerdev_info *tmd, u_long cmd, caddr_t data, int fflag, struct thread *td)
-{
- struct systmr_timer_softc *scp;
- int ret, val;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
- ret = 0;
-
- SEQ_DEBUG(printf("systmr_ioctl: unit %d, cmd %s.\n",
- tmd->unit, midi_cmdname(cmd, cmdtab_seqioctl)));
-
- switch (cmd) {
- case SNDCTL_TMR_SOURCE:
- *(int *)data = TMR_INTERNAL;
- break;
-
- case SNDCTL_TMR_START:
- mtx_lock(&tmd->mtx);
- systmr_reset(tmd);
- scp->running = 1;
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_TMR_STOP:
- mtx_lock(&tmd->mtx);
- scp->running = 0;
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_TMR_CONTINUE:
- mtx_lock(&tmd->mtx);
- scp->running = 1;
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_TMR_TIMEBASE:
- val = *(int *)data;
- mtx_lock(&tmd->mtx);
- if (val > 0) {
- RANGE(val, 1, 1000);
- scp->timebase = val;
- }
- *(int *)data = scp->timebase;
- mtx_unlock(&tmd->mtx);
- SEQ_DEBUG(printf("systmr_ioctl: timebase %d.\n", *(int *)data));
- break;
-
- case SNDCTL_TMR_TEMPO:
- val = *(int *)data;
- mtx_lock(&tmd->mtx);
- if (val > 0) {
- RANGE(val, 8, 360);
- scp->ticks_offset += scp->ticks_cur
- - scp->ticks_base;
- scp->ticks_base = scp->ticks_cur;
- scp->tempo = val;
- }
- *(int *)data = scp->tempo;
- SEQ_DEBUG(printf("systmr_ioctl: tempo %d.\n", *(int *)data));
- mtx_unlock(&tmd->mtx);
- break;
-
- case SNDCTL_SEQ_CTRLRATE:
- val = *(int *)data;
- if (val > 0)
- ret = EINVAL;
- else {
- mtx_lock(&tmd->mtx);
- *(int *)data = ((scp->tempo * scp->timebase) + 30) / 60;
- mtx_unlock(&tmd->mtx);
- SEQ_DEBUG(printf("systmr_ioctl: ctrlrate %d.\n", *(int *)data));
- }
- break;
-
- case SNDCTL_TMR_METRONOME:
- /* NOP. */
- break;
-
- case SNDCTL_TMR_SELECT:
- /* NOP. */
- break;
-
- default:
- ret = EINVAL;
- }
-
- return (ret);
-}
-
-static int
-systmr_armtimer(timerdev_info *tmd, u_long t)
-{
- struct systmr_timer_softc *scp;
-
- scp = (struct systmr_timer_softc *)tmd->softc;
-
- SEQ_DEBUG(printf("systmr_armtimer: unit %d, t %lu.\n", tmd->unit, t));
-
- mtx_lock(&tmd->mtx);
-
- if (t < 0)
- t = CURTICKS(scp) + 1;
- else if (t > CURTICKS(scp))
- scp->nexteventtime = scp->preveventtime = t;
-
- mtx_unlock(&tmd->mtx);
-
- return (0);
-}
diff --git a/sys/dev/sound/midi/timer.h b/sys/dev/sound/midi/timer.h
deleted file mode 100644
index a615ab64cdc9..000000000000
--- a/sys/dev/sound/midi/timer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Include file for a midi timer.
- *
- * Copyright by Seigo Tanimura 2002.
- *
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-#ifndef _TIMER_H_
-#define _TIMER_H_
-
-typedef struct _timerdev_info timerdev_info;
-
-typedef int (tmr_open_t)(timerdev_info *tmd, int oflags, int devtype, struct thread *td);
-typedef int (tmr_close_t)(timerdev_info *tmd, int fflag, int devtype, struct thread *td);
-typedef int (tmr_event_t)(timerdev_info *tmd, u_char *ev);
-typedef int (tmr_gettime_t)(timerdev_info *tmd, u_long *t);
-typedef int (tmr_ioctl_t)(timerdev_info *tmd, u_long cmd, caddr_t data, int fflag, struct thread *td);
-typedef int (tmr_armtimer_t)(timerdev_info *tmd, u_long t);
-
-struct _timerdev_info {
- /*
- * the first part of the descriptor is filled up from a
- * template.
- */
- char name[32];
-
- int caps;
- int prio;
-
- tmr_open_t *open;
- tmr_close_t *close;
- tmr_event_t *event;
- tmr_gettime_t *gettime;
- tmr_ioctl_t *ioctl;
- tmr_armtimer_t *armtimer;
-
-
- int unit;
- void *softc;
- void *seq;
-
- /* The tailq entry of the next timer device. */
- TAILQ_ENTRY(_timerdev_info) tmd_link;
-
- int opened;
-
- struct mtx mtx;
-};
-
-#ifdef _KERNEL
-int timerdev_install(void);
-timerdev_info *create_timerdev_info_unit(timerdev_info *tmdinf);
-timerdev_info *get_timerdev_info_unit(int unit);
-timerdev_info *get_timerdev_info(void);
-#endif /* _KERNEL */
-
-#endif /* _TIMER_H_ */
diff --git a/sys/dev/sound/pci/csamidi.c b/sys/dev/sound/pci/csamidi.c
deleted file mode 100644
index 4f91b5f3af65..000000000000
--- a/sys/dev/sound/pci/csamidi.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*-
- * Copyright (c) 1999 Seigo Tanimura
- * All rights reserved.
- *
- * 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.
- *
- * $FreeBSD$
- */
-
-#include <dev/sound/midi/midi.h>
-#include <dev/sound/chip.h>
-#include <dev/sound/pci/csareg.h>
-#include <machine/cpufunc.h>
-
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
-static devclass_t midi_devclass;
-
-#ifndef DDB
-#undef DDB
-#define DDB(x)
-#endif /* DDB */
-
-#define CSAMIDI_RESET 0xff
-#define CSAMIDI_UART 0x3f
-#define CSAMIDI_ACK 0xfe
-
-#define CSAMIDI_STATMASK 0xc0
-#define CSAMIDI_OUTPUTBUSY 0x40
-#define CSAMIDI_INPUTBUSY 0x80
-
-#define CSAMIDI_TRYDATA 50
-#define CSAMIDI_DELAY 25000
-
-extern synthdev_info midisynth_op_desc;
-
-/* These are the synthesizer and the midi interface information. */
-static struct synth_info csamidi_synthinfo = {
- "CS461x MIDI",
- 0,
- SYNTH_TYPE_MIDI,
- 0,
- 0,
- 128,
- 128,
- 128,
- SYNTH_CAP_INPUT,
-};
-
-static struct midi_info csamidi_midiinfo = {
- "CS461x MIDI",
- 0,
- 0,
- 0,
-};
-
-/*
- * These functions goes into csamidi_op_desc to get called
- * from sound.c.
- */
-
-static int csamidi_probe(device_t dev);
-static int csamidi_attach(device_t dev);
-
-static d_ioctl_t csamidi_ioctl;
-static driver_intr_t csamidi_intr;
-static midi_callback_t csamidi_callback;
-
-/* Here is the parameter structure per a device. */
-struct csamidi_softc {
- device_t dev; /* device information */
- mididev_info *devinfo; /* midi device information */
- struct csa_bridgeinfo *binfo; /* The state of the parent. */
-
- struct mtx mtx; /* Mutex to protect the device. */
-
- struct resource *io; /* Base of io map */
- int io_rid; /* Io map resource ID */
- struct resource *mem; /* Base of memory map */
- int mem_rid; /* Memory map resource ID */
- struct resource *irq; /* Irq */
- int irq_rid; /* Irq resource ID */
- void *ih; /* Interrupt cookie */
-
- int fflags; /* File flags */
-};
-
-typedef struct csamidi_softc *sc_p;
-
-/* These functions are local. */
-static void csamidi_startplay(sc_p scp);
-static void csamidi_xmit(sc_p scp);
-static int csamidi_reset(sc_p scp);
-static int csamidi_status(sc_p scp);
-static int csamidi_command(sc_p scp, u_int32_t value);
-static int csamidi_readdata(sc_p scp, u_int8_t *value);
-static int csamidi_writedata(sc_p scp, u_int32_t value);
-static u_int32_t csamidi_readio(sc_p scp, u_long offset);
-static void csamidi_writeio(sc_p scp, u_long offset, u_int32_t data);
-/* Not used in this file. */
-#if notdef
-static u_int32_t csamidi_readmem(sc_p scp, u_long offset);
-static void csamidi_writemem(sc_p scp, u_long offset, u_int32_t data);
-#endif /* notdef */
-static int csamidi_allocres(sc_p scp, device_t dev);
-static void csamidi_releaseres(sc_p scp, device_t dev);
-
-/*
- * This is the device descriptor for the midi device.
- */
-static mididev_info csamidi_op_desc = {
- "CS461x midi",
-
- SNDCARD_MPU401,
-
- NULL,
- NULL,
- csamidi_ioctl,
-
- csamidi_callback,
-
- MIDI_BUFFSIZE, /* Queue Length */
-
- 0, /* XXX This is not an *audio* device! */
-};
-
-/*
- * Here are the main functions to interact to the user process.
- */
-
-static int
-csamidi_probe(device_t dev)
-{
- char *s;
- sc_p scp;
- struct sndcard_func *func;
-
- /* The parent device has already been probed. */
-
- func = device_get_ivars(dev);
- if (func == NULL || func->func != SCF_MIDI)
- return (ENXIO);
-
- s = "CS461x Midi Interface";
-
- scp = device_get_softc(dev);
- bzero(scp, sizeof(*scp));
- scp->io_rid = PCIR_BAR(0);
- scp->mem_rid = PCIR_BAR(1);
- scp->irq_rid = 0;
-
- device_set_desc(dev, s);
- return (0);
-}
-
-static int
-csamidi_attach(device_t dev)
-{
- sc_p scp;
- mididev_info *devinfo;
- struct sndcard_func *func;
-
- scp = device_get_softc(dev);
- func = device_get_ivars(dev);
- scp->binfo = func->varinfo;
-
- /* Allocate the resources. */
- if (csamidi_allocres(scp, dev)) {
- csamidi_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* Fill the softc. */
- scp->dev = dev;
- mtx_init(&scp->mtx, "csamid", NULL, MTX_DEF);
- scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &csamidi_op_desc, &midisynth_op_desc);
-
- /* Fill the midi info. */
- snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at irq %d",
- (int)rman_get_start(scp->irq));
-
- midiinit(devinfo, dev);
-
- /* Enable interrupt. */
- if (bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, csamidi_intr, scp, &scp->ih)) {
- csamidi_releaseres(scp, dev);
- return (ENXIO);
- }
-
- /* Reset the interface. */
- csamidi_reset(scp);
-
- return (0);
-}
-
-static int
-csamidi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
-{
- sc_p scp;
- mididev_info *devinfo;
- int unit;
- struct synth_info *synthinfo;
- struct midi_info *midiinfo;
-
- unit = MIDIUNIT(i_dev);
-
- MIDI_DEBUG(printf("csamidi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
-
- devinfo = get_mididev_info(i_dev, &unit);
- if (devinfo == NULL) {
- MIDI_DEBUG(printf("csamidi_ioctl: unit %d is not configured.\n", unit));
- return (ENXIO);
- }
- scp = devinfo->softc;
-
- switch (cmd) {
- case SNDCTL_SYNTH_INFO:
- synthinfo = (struct synth_info *)arg;
- if (synthinfo->device != unit)
- return (ENXIO);
- bcopy(&csamidi_synthinfo, synthinfo, sizeof(csamidi_synthinfo));
- synthinfo->device = unit;
- return (0);
- break;
- case SNDCTL_MIDI_INFO:
- midiinfo = (struct midi_info *)arg;
- if (midiinfo->device != unit)
- return (ENXIO);
- bcopy(&csamidi_midiinfo, midiinfo, sizeof(csamidi_midiinfo));
- midiinfo->device = unit;
- return (0);
- break;
- default:
- return (ENOSYS);
- }
- /* NOTREACHED */
- return (EINVAL);
-}
-
-static void
-csamidi_intr(void *arg)
-{
- sc_p scp;
- u_char c;
- mididev_info *devinfo;
- int leni;
-
- scp = (sc_p)arg;
- devinfo = scp->devinfo;
-
- mtx_lock(&devinfo->flagqueue_mtx);
- mtx_lock(&scp->mtx);
-
- /* Read the received data. */
- while ((csamidi_status(scp) & MIDSR_RBE) == 0) {
- /* Receive the data. */
- csamidi_readdata(scp, &c);
- mtx_unlock(&scp->mtx);
-
- /* Queue into the passthru buffer and start transmitting if we can. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
- midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni);
- devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR);
- }
- /* Queue if we are reading. Discard an active sensing. */
- if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) {
- midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni);
- }
- mtx_lock(&scp->mtx);
- }
- mtx_unlock(&scp->mtx);
-
- /* Transmit out data. */
- if ((devinfo->flags & MIDI_F_WRITING) != 0 && (csamidi_status(scp) & MIDSR_TBF) == 0)
- csamidi_xmit(scp);
-
- mtx_unlock(&devinfo->flagqueue_mtx);
-
- /* Invoke the upper layer. */
- midi_intr(devinfo);
-}
-
-static int
-csamidi_callback(void *di, int reason)
-{
- int unit;
- sc_p scp;
- mididev_info *d;
-
- d = (mididev_info *)di;
-
- mtx_assert(&d->flagqueue_mtx, MA_OWNED);
-
- if (d == NULL) {
- MIDI_DEBUG(printf("csamidi_callback: device not configured.\n"));
- return (ENXIO);
- }
-
- unit = d->unit;
- scp = d->softc;
-
- switch (reason & MIDI_CB_REASON_MASK) {
- case MIDI_CB_START:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0)
- /* Begin recording. */
- d->flags |= MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0)
- /* Start playing. */
- csamidi_startplay(scp);
- break;
- case MIDI_CB_STOP:
- case MIDI_CB_ABORT:
- if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0)
- /* Stop recording. */
- d->flags &= ~MIDI_F_READING;
- if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0)
- /* Stop Playing. */
- d->flags &= ~MIDI_F_WRITING;
- break;
- }
-
- return (0);
-}
-
-/*
- * The functions below here are the libraries for the above ones.
- */
-
-/*
- * Starts to play the data in the output queue.
- */
-static void
-csamidi_startplay(sc_p scp)
-{
- mididev_info *devinfo;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* Can we play now? */
- if (devinfo->midi_dbuf_out.rl == 0)
- return;
-
- devinfo->flags |= MIDI_F_WRITING;
- csamidi_xmit(scp);
-}
-
-static void
-csamidi_xmit(sc_p scp)
-{
- register mididev_info *devinfo;
- register midi_dbuf *dbuf;
- u_char c;
- int leno;
-
- devinfo = scp->devinfo;
-
- mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
-
- /* See which source to use. */
- if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0))
- dbuf = &devinfo->midi_dbuf_out;
- else
- dbuf = &devinfo->midi_dbuf_passthru;
-
- /* Transmit the data in the queue. */
- while ((devinfo->flags & MIDI_F_WRITING) != 0) {
- /* Do we have the data to transmit? */
- if (dbuf->rl == 0) {
- /* Stop playing. */
- devinfo->flags &= ~MIDI_F_WRITING;
- break;
- } else {
- mtx_lock(&scp->mtx);
- if ((csamidi_status(scp) & MIDSR_TBF) != 0) {
- mtx_unlock(&scp->mtx);
- break;
- }
- /* Send the data. */
- midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
- csamidi_writedata(scp, c);
- /* We are playing now. */
- devinfo->flags |= MIDI_F_WRITING;
- mtx_unlock(&scp->mtx);
- }
- }
-}
-
-/* Reset midi. */
-static int
-csamidi_reset(sc_p scp)
-{
- int i, resp;
-
- mtx_lock(&scp->mtx);
-
- /* Reset the midi. */
- resp = 0;
- for (i = 0 ; i < CSAMIDI_TRYDATA ; i++) {
- resp = csamidi_command(scp, MIDCR_MRST);
- if (resp == 0)
- break;
- }
- if (resp != 0) {
- mtx_unlock(&scp->mtx);
- return (1);
- }
- for (i = 0 ; i < CSAMIDI_TRYDATA ; i++) {
- resp = csamidi_command(scp, MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE);
- if (resp == 0)
- break;
- }
- if (resp != 0)
- return (1);
-
- mtx_unlock(&scp->mtx);
-
- DELAY(CSAMIDI_DELAY);
-
- return (0);
-}
-
-/* Reads the status. */
-static int
-csamidi_status(sc_p scp)
-{
- return csamidi_readio(scp, BA0_MIDSR);
-}
-
-/* Writes a command. */
-static int
-csamidi_command(sc_p scp, u_int32_t value)
-{
- csamidi_writeio(scp, BA0_MIDCR, value);
-
- return (0);
-}
-
-/* Reads a byte of data. */
-static int
-csamidi_readdata(sc_p scp, u_int8_t *value)
-{
- u_int status;
-
- if (value == NULL)
- return (EINVAL);
-
- /* Is the interface ready to read? */
- status = csamidi_status(scp);
- if ((status & MIDSR_RBE) != 0)
- /* The interface is busy. */
- return (EAGAIN);
-
- *value = (u_int8_t)(csamidi_readio(scp, BA0_MIDRP) & 0xff);
-
- return (0);
-}
-
-/* Writes a byte of data. */
-static int
-csamidi_writedata(sc_p scp, u_int32_t value)
-{
- u_int status;
-
- /* Is the interface ready to write? */
- status = csamidi_status(scp);
- if ((status & MIDSR_TBF) != 0)
- /* The interface is busy. */
- return (EAGAIN);
-
- csamidi_writeio(scp, BA0_MIDWP, value & 0xff);
-
- return (0);
-}
-
-static u_int32_t
-csamidi_readio(sc_p scp, u_long offset)
-{
- if (offset < BA0_AC97_RESET)
- return bus_space_read_4(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), offset) & 0xffffffff;
- else
- return (0);
-}
-
-static void
-csamidi_writeio(sc_p scp, u_long offset, u_int32_t data)
-{
- if (offset < BA0_AC97_RESET)
- bus_space_write_4(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), offset, data);
-}
-
-/* Not used in this file. */
-#if notdef
-static u_int32_t
-csamidi_readmem(sc_p scp, u_long offset)
-{
- return bus_space_read_4(rman_get_bustag(scp->mem), rman_get_bushandle(scp->mem), offset) & 0xffffffff;
-}
-
-static void
-csamidi_writemem(sc_p scp, u_long offset, u_int32_t data)
-{
- bus_space_write_4(rman_get_bustag(scp->mem), rman_get_bushandle(scp->mem), offset, data);
-}
-#endif /* notdef */
-
-/* Allocates resources. */
-static int
-csamidi_allocres(sc_p scp, device_t dev)
-{
- if (scp->io == NULL) {
- scp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &scp->io_rid, RF_ACTIVE);
- if (scp->io == NULL)
- return (1);
- }
- if (scp->mem == NULL) {
- scp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &scp->mem_rid, RF_ACTIVE);
- if (scp->mem == NULL)
- return (1);
- }
- if (scp->irq == NULL) {
- scp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &scp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
- if (scp->irq == NULL)
- return (1);
- }
-
- return (0);
-}
-
-/* Releases resources. */
-static void
-csamidi_releaseres(sc_p scp, device_t dev)
-{
- if (scp->irq != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
- scp->irq = NULL;
- }
- if (scp->io != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, scp->io_rid, scp->io);
- scp->io = NULL;
- }
- if (scp->mem != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, scp->mem_rid, scp->mem);
- scp->mem = NULL;
- }
-}
-
-static device_method_t csamidi_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe , csamidi_probe ),
- DEVMETHOD(device_attach, csamidi_attach),
-
- { 0, 0 },
-};
-
-static driver_t csamidi_driver = {
- "midi",
- csamidi_methods,
- sizeof(struct csamidi_softc),
-};
-
-DRIVER_MODULE(csamidi, csa, csamidi_driver, midi_devclass, 0, 0);