Home | History | Annotate | Line # | Download | only in pci
emuxki.c revision 1.64
      1  1.64   msaitoh /*	$NetBSD: emuxki.c,v 1.64 2016/07/07 06:55:41 msaitoh Exp $	*/
      2   1.1  jdolecek 
      3   1.1  jdolecek /*-
      4  1.60  jmcneill  * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
      5   1.1  jdolecek  * All rights reserved.
      6   1.1  jdolecek  *
      7   1.1  jdolecek  * This code is derived from software contributed to The NetBSD Foundation
      8  1.60  jmcneill  * by Yannick Montulet, and by Andrew Doran.
      9   1.1  jdolecek  *
     10   1.1  jdolecek  * Redistribution and use in source and binary forms, with or without
     11   1.1  jdolecek  * modification, are permitted provided that the following conditions
     12   1.1  jdolecek  * are met:
     13   1.1  jdolecek  * 1. Redistributions of source code must retain the above copyright
     14   1.1  jdolecek  *    notice, this list of conditions and the following disclaimer.
     15   1.1  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  jdolecek  *    documentation and/or other materials provided with the distribution.
     18   1.1  jdolecek  *
     19   1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1  jdolecek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1  jdolecek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1  jdolecek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1  jdolecek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1  jdolecek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1  jdolecek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1  jdolecek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1  jdolecek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1  jdolecek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1  jdolecek  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1  jdolecek  */
     31   1.1  jdolecek 
     32   1.1  jdolecek /*
     33   1.1  jdolecek  * Driver for Creative Labs SBLive! series and probably PCI512.
     34  1.40      kent  *
     35   1.1  jdolecek  * Known bugs:
     36   1.1  jdolecek  * - inversed stereo at ac97 codec level
     37   1.1  jdolecek  *   (XXX jdolecek - don't see the problem? maybe because auvia(4) has
     38   1.1  jdolecek  *    it swapped too?)
     39  1.37   dsainty  * - bass disappear when you plug rear jack-in on Cambridge FPS2000 speakers
     40   1.1  jdolecek  *   (and presumably all speakers that support front and rear jack-in)
     41   1.1  jdolecek  *
     42   1.1  jdolecek  * TODO:
     43   1.1  jdolecek  * - Digital Outputs
     44   1.1  jdolecek  * - (midi/mpu),joystick support
     45   1.1  jdolecek  * - Multiple voices play (problem with /dev/audio architecture)
     46   1.1  jdolecek  * - Multiple sources recording (Pb with audio(4))
     47  1.37   dsainty  * - Independent modification of each channel's parameters (via mixer ?)
     48   1.1  jdolecek  * - DSP FX patches (to make fx like chipmunk)
     49   1.1  jdolecek  */
     50   1.4     lukem 
     51   1.4     lukem #include <sys/cdefs.h>
     52  1.64   msaitoh __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.64 2016/07/07 06:55:41 msaitoh Exp $");
     53   1.1  jdolecek 
     54   1.5     lukem #include <sys/param.h>
     55   1.1  jdolecek #include <sys/device.h>
     56   1.1  jdolecek #include <sys/errno.h>
     57   1.1  jdolecek #include <sys/systm.h>
     58   1.1  jdolecek #include <sys/audioio.h>
     59   1.1  jdolecek #include <sys/select.h>
     60  1.60  jmcneill #include <sys/mutex.h>
     61  1.60  jmcneill #include <sys/kmem.h>
     62  1.60  jmcneill #include <sys/malloc.h>
     63  1.60  jmcneill 
     64   1.1  jdolecek #include <dev/audio_if.h>
     65   1.1  jdolecek #include <dev/audiovar.h>
     66   1.1  jdolecek #include <dev/auconv.h>
     67   1.1  jdolecek #include <dev/mulaw.h>
     68  1.60  jmcneill 
     69   1.1  jdolecek #include <dev/ic/ac97reg.h>
     70   1.1  jdolecek #include <dev/ic/ac97var.h>
     71   1.1  jdolecek 
     72  1.60  jmcneill #include <dev/pci/pcireg.h>
     73  1.60  jmcneill #include <dev/pci/pcivar.h>
     74  1.60  jmcneill #include <dev/pci/pcidevs.h>
     75   1.1  jdolecek #include <dev/pci/emuxkireg.h>
     76   1.1  jdolecek #include <dev/pci/emuxkivar.h>
     77   1.1  jdolecek 
     78  1.26       wiz /* autoconf goo */
     79  1.56    cegger static int	emuxki_match(device_t, cfdata_t, void *);
     80  1.56    cegger static void	emuxki_attach(device_t, device_t, void *);
     81  1.56    cegger static int	emuxki_detach(device_t, int);
     82   1.1  jdolecek 
     83  1.26       wiz /* DMA mem mgmt */
     84   1.3  jdolecek static struct dmamem *dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
     85  1.60  jmcneill 		int);
     86  1.60  jmcneill static void	dmamem_free(struct dmamem *);
     87   1.1  jdolecek 
     88   1.1  jdolecek /* Emu10k1 init & shutdown */
     89  1.40      kent static int	emuxki_init(struct emuxki_softc *);
     90  1.40      kent static void	emuxki_shutdown(struct emuxki_softc *);
     91   1.1  jdolecek 
     92   1.1  jdolecek /* Emu10k1 mem mgmt */
     93  1.60  jmcneill static void	*emuxki_pmem_alloc(struct emuxki_softc *, size_t);
     94  1.60  jmcneill static void	*emuxki_rmem_alloc(struct emuxki_softc *, size_t);
     95   1.1  jdolecek 
     96   1.1  jdolecek /*
     97   1.1  jdolecek  * Emu10k1 channels funcs : There is no direct access to channels, everything
     98   1.1  jdolecek  * is done through voices I will at least provide channel based fx params
     99   1.1  jdolecek  * modification, later...
    100   1.1  jdolecek  */
    101   1.1  jdolecek 
    102   1.1  jdolecek /* Emu10k1 voice mgmt */
    103   1.3  jdolecek static struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *,
    104  1.40      kent 		uint8_t);
    105  1.40      kent static void	emuxki_voice_delete(struct emuxki_voice *);
    106  1.60  jmcneill static int	emuxki_voice_set_audioparms(struct emuxki_softc *,
    107  1.60  jmcneill 					    struct emuxki_voice *, uint8_t,
    108  1.60  jmcneill 					    uint8_t, uint32_t);
    109   1.1  jdolecek /* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
    110  1.40      kent static int	emuxki_voice_set_bufparms(struct emuxki_voice *,
    111  1.40      kent 		void *, uint32_t, uint16_t);
    112  1.40      kent static void	emuxki_voice_commit_parms(struct emuxki_voice *);
    113  1.40      kent static int	emuxki_voice_adc_rate(struct emuxki_voice *);
    114  1.40      kent static uint32_t	emuxki_voice_curaddr(struct emuxki_voice *);
    115  1.40      kent static void	emuxki_voice_start(struct emuxki_voice *,
    116  1.40      kent 		void (*) (void *), void *);
    117  1.40      kent static void	emuxki_voice_halt(struct emuxki_voice *);
    118   1.1  jdolecek 
    119   1.1  jdolecek /*
    120   1.1  jdolecek  * Emu10k1 stream mgmt : not done yet
    121   1.1  jdolecek  */
    122   1.1  jdolecek #if 0
    123   1.3  jdolecek static struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
    124  1.40      kent static void	emuxki_stream_delete(struct emuxki_stream *);
    125  1.40      kent static int	emuxki_stream_set_audio_params(struct emuxki_stream *,
    126  1.40      kent 		uint8_t, uint8_t, uint8_t, uint16_t);
    127  1.40      kent static void	emuxki_stream_start(struct emuxki_stream *);
    128  1.40      kent static void	emuxki_stream_halt(struct emuxki_stream *);
    129   1.1  jdolecek #endif
    130   1.1  jdolecek 
    131   1.1  jdolecek /* audio interface callbacks */
    132   1.1  jdolecek 
    133   1.3  jdolecek static int	emuxki_open(void *, int);
    134   1.3  jdolecek static void	emuxki_close(void *);
    135   1.1  jdolecek 
    136   1.3  jdolecek static int	emuxki_query_encoding(void *, struct audio_encoding *);
    137  1.39      kent static int	emuxki_set_params(void *, int, int, audio_params_t *,
    138  1.40      kent 		audio_params_t *, stream_filter_list_t *,
    139  1.40      kent 		stream_filter_list_t *);
    140   1.1  jdolecek 
    141  1.39      kent static int	emuxki_round_blocksize(void *, int, int, const audio_params_t *);
    142   1.3  jdolecek static size_t	emuxki_round_buffersize(void *, int, size_t);
    143   1.1  jdolecek 
    144   1.3  jdolecek static int	emuxki_trigger_output(void *, void *, void *, int,
    145  1.40      kent 		void (*)(void *), void *, const audio_params_t *);
    146   1.3  jdolecek static int	emuxki_trigger_input(void *, void *, void *, int,
    147  1.40      kent 		void (*) (void *), void *, const audio_params_t *);
    148   1.3  jdolecek static int	emuxki_halt_output(void *);
    149   1.3  jdolecek static int	emuxki_halt_input(void *);
    150   1.3  jdolecek 
    151   1.3  jdolecek static int	emuxki_getdev(void *, struct audio_device *);
    152   1.3  jdolecek static int	emuxki_set_port(void *, mixer_ctrl_t *);
    153   1.3  jdolecek static int	emuxki_get_port(void *, mixer_ctrl_t *);
    154   1.3  jdolecek static int	emuxki_query_devinfo(void *, mixer_devinfo_t *);
    155   1.1  jdolecek 
    156  1.60  jmcneill static void    *emuxki_allocm(void *, int, size_t);
    157  1.60  jmcneill static void	emuxki_freem(void *, void *, size_t);
    158   1.1  jdolecek 
    159   1.3  jdolecek static paddr_t	emuxki_mappage(void *, void *, off_t, int);
    160   1.3  jdolecek static int	emuxki_get_props(void *);
    161  1.60  jmcneill static void	emuxki_get_locks(void *, kmutex_t **, kmutex_t **);
    162   1.1  jdolecek 
    163   1.1  jdolecek /* Interrupt handler */
    164  1.40      kent static int	emuxki_intr(void *);
    165   1.1  jdolecek 
    166   1.1  jdolecek /* Emu10k1 AC97 interface callbacks */
    167  1.40      kent static int	emuxki_ac97_attach(void *, struct ac97_codec_if *);
    168  1.40      kent static int	emuxki_ac97_read(void *, uint8_t, uint16_t *);
    169  1.40      kent static int	emuxki_ac97_write(void *, uint8_t, uint16_t);
    170  1.40      kent static int	emuxki_ac97_reset(void *);
    171   1.6  jdolecek static enum ac97_host_flags emuxki_ac97_flags(void *);
    172   1.1  jdolecek 
    173   1.1  jdolecek /*
    174   1.1  jdolecek  * Autoconfig goo.
    175   1.1  jdolecek  */
    176  1.58   tsutsui CFATTACH_DECL_NEW(emuxki, sizeof(struct emuxki_softc),
    177  1.12   thorpej     emuxki_match, emuxki_attach, emuxki_detach, NULL);
    178   1.1  jdolecek 
    179  1.38      yamt static const struct audio_hw_if emuxki_hw_if = {
    180   1.1  jdolecek 	emuxki_open,
    181   1.1  jdolecek 	emuxki_close,
    182   1.1  jdolecek 	NULL,			/* drain */
    183   1.1  jdolecek 	emuxki_query_encoding,
    184   1.1  jdolecek 	emuxki_set_params,
    185  1.19    toshii 	emuxki_round_blocksize,
    186   1.1  jdolecek 	NULL,			/* commit settings */
    187   1.1  jdolecek 	NULL,			/* init_output */
    188   1.1  jdolecek 	NULL,			/* init_input */
    189   1.1  jdolecek 	NULL,			/* start_output */
    190   1.1  jdolecek 	NULL,			/* start_input */
    191   1.1  jdolecek 	emuxki_halt_output,
    192   1.1  jdolecek 	emuxki_halt_input,
    193   1.1  jdolecek 	NULL,			/* speaker_ctl */
    194   1.1  jdolecek 	emuxki_getdev,
    195   1.1  jdolecek 	NULL,			/* setfd */
    196   1.1  jdolecek 	emuxki_set_port,
    197   1.1  jdolecek 	emuxki_get_port,
    198   1.1  jdolecek 	emuxki_query_devinfo,
    199   1.1  jdolecek 	emuxki_allocm,
    200   1.1  jdolecek 	emuxki_freem,
    201   1.1  jdolecek 	emuxki_round_buffersize,
    202   1.1  jdolecek 	emuxki_mappage,
    203   1.1  jdolecek 	emuxki_get_props,
    204   1.1  jdolecek 	emuxki_trigger_output,
    205   1.1  jdolecek 	emuxki_trigger_input,
    206   1.1  jdolecek 	NULL,			/* dev_ioctl */
    207  1.60  jmcneill 	emuxki_get_locks,
    208   1.1  jdolecek };
    209   1.1  jdolecek 
    210  1.20      fvdl #if 0
    211  1.19    toshii static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
    212  1.19    toshii     { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
    213  1.20      fvdl #endif
    214  1.40      kent static const uint32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
    215  1.19    toshii     { EMU_MICBA, EMU_ADCBA, EMU_FXBA };
    216  1.40      kent static const uint32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
    217  1.19    toshii     { EMU_MICBS, EMU_ADCBS, EMU_FXBS };
    218  1.19    toshii static const int emuxki_recbuf_sz[] = {
    219  1.19    toshii 	0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
    220  1.19    toshii 	2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
    221  1.19    toshii 	12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
    222  1.19    toshii 	57344, 65536
    223  1.19    toshii };
    224  1.19    toshii 
    225  1.39      kent #define EMUXKI_NFORMATS	4
    226  1.39      kent static const struct audio_format emuxki_formats[EMUXKI_NFORMATS] = {
    227  1.39      kent 	{NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
    228  1.39      kent 	 2, AUFMT_STEREO, 0, {4000, 48000}},
    229  1.39      kent 	{NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
    230  1.39      kent 	 1, AUFMT_MONAURAL, 0, {4000, 48000}},
    231  1.39      kent 	{NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
    232  1.39      kent 	 2, AUFMT_STEREO, 0, {4000, 48000}},
    233  1.39      kent 	{NULL, AUMODE_PLAY, AUDIO_ENCODING_ULINEAR_LE, 8, 8,
    234  1.39      kent 	 1, AUFMT_MONAURAL, 0, {4000, 48000}},
    235  1.39      kent };
    236  1.39      kent 
    237   1.1  jdolecek /*
    238  1.26       wiz  * DMA memory mgmt
    239   1.1  jdolecek  */
    240   1.1  jdolecek 
    241   1.1  jdolecek static void
    242  1.60  jmcneill dmamem_delete(struct dmamem *mem)
    243   1.1  jdolecek {
    244  1.40      kent 
    245  1.60  jmcneill 	kmem_free(mem->segs, mem->nsegs * sizeof(*(mem->segs)));
    246  1.60  jmcneill 	kmem_free(mem, sizeof(*mem));
    247   1.1  jdolecek }
    248   1.1  jdolecek 
    249   1.1  jdolecek static struct dmamem *
    250  1.60  jmcneill dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align, int nsegs)
    251   1.1  jdolecek {
    252   1.1  jdolecek 	struct dmamem	*mem;
    253   1.1  jdolecek 
    254   1.1  jdolecek 	/* Allocate memory for structure */
    255  1.60  jmcneill 	if ((mem = kmem_alloc(sizeof(*mem), KM_SLEEP)) == NULL)
    256  1.40      kent 		return NULL;
    257   1.1  jdolecek 	mem->dmat = dmat;
    258   1.1  jdolecek 	mem->size = size;
    259   1.1  jdolecek 	mem->align = align;
    260   1.1  jdolecek 	mem->nsegs = nsegs;
    261   1.1  jdolecek 	mem->bound = 0;
    262   1.1  jdolecek 
    263  1.60  jmcneill 	mem->segs = kmem_alloc(mem->nsegs * sizeof(*(mem->segs)), KM_SLEEP);
    264   1.1  jdolecek 	if (mem->segs == NULL) {
    265  1.60  jmcneill 		kmem_free(mem, sizeof(*mem));
    266  1.40      kent 		return NULL;
    267   1.1  jdolecek 	}
    268   1.1  jdolecek 
    269   1.1  jdolecek 	if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
    270   1.1  jdolecek 			     mem->segs, mem->nsegs, &(mem->rsegs),
    271  1.60  jmcneill 			     BUS_DMA_WAITOK)) {
    272  1.60  jmcneill 		dmamem_delete(mem);
    273  1.40      kent 		return NULL;
    274   1.1  jdolecek 	}
    275   1.1  jdolecek 
    276   1.1  jdolecek 	if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
    277  1.60  jmcneill 			   &(mem->kaddr), BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
    278   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    279  1.60  jmcneill 		dmamem_delete(mem);
    280  1.40      kent 		return NULL;
    281   1.1  jdolecek 	}
    282   1.1  jdolecek 
    283   1.1  jdolecek 	if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
    284  1.60  jmcneill 			      mem->bound, BUS_DMA_WAITOK, &(mem->map))) {
    285   1.1  jdolecek 		bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
    286   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    287  1.60  jmcneill 		dmamem_delete(mem);
    288  1.40      kent 		return NULL;
    289   1.1  jdolecek 	}
    290   1.1  jdolecek 
    291  1.40      kent 	if (bus_dmamap_load(dmat, mem->map, mem->kaddr,
    292  1.60  jmcneill 			    mem->size, NULL, BUS_DMA_WAITOK)) {
    293   1.1  jdolecek 		bus_dmamap_destroy(dmat, mem->map);
    294   1.1  jdolecek 		bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
    295   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    296  1.60  jmcneill 		dmamem_delete(mem);
    297  1.40      kent 		return NULL;
    298   1.1  jdolecek 	}
    299   1.1  jdolecek 
    300  1.40      kent 	return mem;
    301   1.1  jdolecek }
    302   1.1  jdolecek 
    303   1.1  jdolecek static void
    304  1.60  jmcneill dmamem_free(struct dmamem *mem)
    305   1.1  jdolecek {
    306  1.40      kent 
    307   1.1  jdolecek 	bus_dmamap_unload(mem->dmat, mem->map);
    308   1.1  jdolecek 	bus_dmamap_destroy(mem->dmat, mem->map);
    309   1.1  jdolecek 	bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
    310   1.1  jdolecek 	bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
    311  1.60  jmcneill 	dmamem_delete(mem);
    312   1.1  jdolecek }
    313   1.1  jdolecek 
    314   1.1  jdolecek 
    315   1.1  jdolecek /*
    316   1.1  jdolecek  * Autoconf device callbacks : attach and detach
    317   1.1  jdolecek  */
    318   1.1  jdolecek 
    319   1.1  jdolecek static void
    320   1.1  jdolecek emuxki_pci_shutdown(struct emuxki_softc *sc)
    321   1.1  jdolecek {
    322  1.40      kent 
    323   1.1  jdolecek 	if (sc->sc_ih != NULL)
    324   1.1  jdolecek 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    325   1.1  jdolecek 	if (sc->sc_ios)
    326   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    327   1.1  jdolecek }
    328   1.1  jdolecek 
    329   1.1  jdolecek static int
    330   1.1  jdolecek emuxki_scinit(struct emuxki_softc *sc)
    331   1.1  jdolecek {
    332  1.40      kent 	int err;
    333   1.1  jdolecek 
    334   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    335   1.1  jdolecek 		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
    336   1.1  jdolecek 		EMU_HCFG_MUTEBUTTONENABLE);
    337   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
    338   1.1  jdolecek 		EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE);
    339   1.1  jdolecek 
    340   1.1  jdolecek 	if ((err = emuxki_init(sc)))
    341  1.40      kent 		return err;
    342   1.1  jdolecek 
    343  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY2) {
    344  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    345  1.35  christos 			EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF |
    346  1.35  christos 			EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE);
    347  1.35  christos 	} else if (sc->sc_type & EMUXKI_AUDIGY) {
    348  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    349  1.35  christos 			EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE);
    350  1.35  christos 	} else {
    351  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    352  1.42  jdolecek 			EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE |
    353  1.35  christos 			EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
    354  1.35  christos 	}
    355   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
    356   1.1  jdolecek 		bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
    357   1.1  jdolecek 		EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
    358   1.1  jdolecek 		EMU_INTE_MUTEENABLE);
    359  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY2) {
    360  1.35  christos 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG,
    361  1.35  christos 			EMU_A_IOCFG_GPOUT0 |
    362  1.35  christos 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG));
    363  1.35  christos 	}
    364   1.1  jdolecek 
    365   1.1  jdolecek 	/* No multiple voice support for now */
    366  1.54  gmcgarry 	sc->pvoice = sc->rvoice = NULL;
    367   1.1  jdolecek 
    368  1.40      kent 	return 0;
    369   1.1  jdolecek }
    370   1.1  jdolecek 
    371   1.1  jdolecek static int
    372   1.1  jdolecek emuxki_ac97_init(struct emuxki_softc *sc)
    373   1.1  jdolecek {
    374   1.1  jdolecek 	sc->hostif.arg = sc;
    375   1.1  jdolecek 	sc->hostif.attach = emuxki_ac97_attach;
    376   1.1  jdolecek 	sc->hostif.read = emuxki_ac97_read;
    377   1.1  jdolecek 	sc->hostif.write = emuxki_ac97_write;
    378   1.1  jdolecek 	sc->hostif.reset = emuxki_ac97_reset;
    379   1.6  jdolecek 	sc->hostif.flags = emuxki_ac97_flags;
    380  1.60  jmcneill 	return ac97_attach(&sc->hostif, sc->sc_dev, &sc->sc_lock);
    381   1.1  jdolecek }
    382   1.1  jdolecek 
    383   1.1  jdolecek static int
    384  1.56    cegger emuxki_match(device_t parent, cfdata_t match, void *aux)
    385   1.1  jdolecek {
    386  1.40      kent 	struct pci_attach_args *pa;
    387   1.1  jdolecek 
    388  1.40      kent 	pa = aux;
    389  1.35  christos 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CREATIVELABS)
    390  1.35  christos 		return 0;
    391  1.35  christos 
    392  1.35  christos 	switch (PCI_PRODUCT(pa->pa_id)) {
    393  1.35  christos 	case PCI_PRODUCT_CREATIVELABS_SBLIVE:
    394  1.35  christos 	case PCI_PRODUCT_CREATIVELABS_SBLIVE2:
    395  1.40      kent 	case PCI_PRODUCT_CREATIVELABS_AUDIGY:
    396  1.40      kent 		return 1;
    397  1.35  christos 	default:
    398  1.35  christos 		return 0;
    399  1.32    martti 	}
    400   1.1  jdolecek }
    401   1.1  jdolecek 
    402   1.1  jdolecek static void
    403  1.56    cegger emuxki_attach(device_t parent, device_t self, void *aux)
    404   1.1  jdolecek {
    405  1.40      kent 	struct emuxki_softc *sc;
    406  1.40      kent 	struct pci_attach_args *pa;
    407   1.1  jdolecek 	pci_intr_handle_t ih;
    408  1.40      kent 	const char *intrstr;
    409  1.63  christos 	char intrbuf[PCI_INTRSTR_LEN];
    410   1.1  jdolecek 
    411  1.57    cegger 	sc = device_private(self);
    412  1.58   tsutsui 	sc->sc_dev = self;
    413  1.40      kent 	pa = aux;
    414  1.15   thorpej 
    415  1.60  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    416  1.61       mrg 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
    417  1.61       mrg 	mutex_init(&sc->sc_index_lock, MUTEX_DEFAULT, IPL_AUDIO);
    418  1.61       mrg 	mutex_init(&sc->sc_ac97_index_lock, MUTEX_DEFAULT, IPL_AUDIO);
    419  1.60  jmcneill 
    420   1.1  jdolecek 	if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
    421   1.1  jdolecek 	    &(sc->sc_iot), &(sc->sc_ioh), &(sc->sc_iob),
    422   1.1  jdolecek 			   &(sc->sc_ios))) {
    423  1.15   thorpej 		aprint_error(": can't map iospace\n");
    424   1.1  jdolecek 		return;
    425   1.1  jdolecek 	}
    426  1.62  drochner 
    427  1.62  drochner 	pci_aprint_devinfo(pa, "Audio controller");
    428   1.1  jdolecek 
    429   1.1  jdolecek 	sc->sc_pc   = pa->pa_pc;
    430   1.1  jdolecek 	sc->sc_dmat = pa->pa_dmat;
    431   1.1  jdolecek 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
    432   1.1  jdolecek 		pci_conf_read(pa->pa_pc, pa->pa_tag,
    433   1.1  jdolecek 		(PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE));
    434   1.1  jdolecek 
    435   1.1  jdolecek 	if (pci_intr_map(pa, &ih)) {
    436  1.58   tsutsui 		aprint_error_dev(self, "couldn't map interrupt\n");
    437   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    438   1.1  jdolecek 		return;
    439   1.1  jdolecek 	}
    440   1.1  jdolecek 
    441  1.63  christos 	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
    442  1.61       mrg 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, emuxki_intr,
    443   1.1  jdolecek 		sc);
    444   1.1  jdolecek 	if (sc->sc_ih == NULL) {
    445  1.58   tsutsui 		aprint_error_dev(self, "couldn't establish interrupt");
    446   1.1  jdolecek 		if (intrstr != NULL)
    447  1.59     njoly 			aprint_error(" at %s", intrstr);
    448  1.59     njoly 		aprint_error("\n");
    449   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    450   1.1  jdolecek 		return;
    451   1.1  jdolecek 	}
    452  1.58   tsutsui 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
    453  1.35  christos 
    454  1.37   dsainty  /* XXX it's unknown whether APS is made from Audigy as well */
    455  1.40      kent 	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
    456  1.40      kent 		sc->sc_type = EMUXKI_AUDIGY;
    457  1.40      kent 		if (PCI_REVISION(pa->pa_class) == 0x04) {
    458  1.40      kent 			sc->sc_type |= EMUXKI_AUDIGY2;
    459  1.64   msaitoh 			strlcpy(sc->sc_audv.name, "Audigy2",
    460  1.64   msaitoh 			    sizeof sc->sc_audv.name);
    461  1.40      kent 		} else {
    462  1.64   msaitoh 			strlcpy(sc->sc_audv.name, "Audigy",
    463  1.64   msaitoh 			    sizeof sc->sc_audv.name);
    464  1.40      kent 		}
    465  1.40      kent 	} else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
    466  1.40      kent 	    PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
    467  1.40      kent 		sc->sc_type = EMUXKI_APS;
    468  1.40      kent 		strlcpy(sc->sc_audv.name, "E-mu APS", sizeof sc->sc_audv.name);
    469  1.40      kent 	} else {
    470  1.40      kent 		sc->sc_type = EMUXKI_SBLIVE;
    471  1.40      kent 		strlcpy(sc->sc_audv.name, "SB Live!", sizeof sc->sc_audv.name);
    472  1.40      kent 	}
    473  1.40      kent 	snprintf(sc->sc_audv.version, sizeof sc->sc_audv.version, "0x%02x",
    474  1.40      kent 		 PCI_REVISION(pa->pa_class));
    475  1.40      kent 	strlcpy(sc->sc_audv.config, "emuxki", sizeof sc->sc_audv.config);
    476   1.1  jdolecek 
    477   1.1  jdolecek 	if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
    478  1.19    toshii 	    (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
    479   1.1  jdolecek 		emuxki_pci_shutdown(sc);
    480  1.19    toshii 		return;
    481  1.19    toshii 	}
    482  1.19    toshii #if 0
    483  1.60  jmcneill 	mutex_enter(&sc->lock);
    484  1.19    toshii 	sc->rsourcectl.dev =
    485  1.19    toshii 	    sc->codecif->vtbl->get_portnum_by_name(sc->codec_if, AudioCrecord,
    486  1.19    toshii 						   AudioNsource, NULL);
    487  1.19    toshii 	sc->rsourcectl.cp = AUDIO_MIXER_ENUM;
    488  1.60  jmcneill 	mutex_exit(&sc->lock);
    489  1.19    toshii #endif
    490   1.1  jdolecek }
    491   1.1  jdolecek 
    492   1.1  jdolecek static int
    493  1.56    cegger emuxki_detach(device_t self, int flags)
    494   1.1  jdolecek {
    495  1.40      kent 	struct emuxki_softc *sc;
    496   1.1  jdolecek 
    497  1.57    cegger 	sc = device_private(self);
    498  1.40      kent 	if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
    499  1.40      kent 		config_detach(sc->sc_audev, 0);
    500   1.1  jdolecek 
    501   1.1  jdolecek 	/* All voices should be stopped now but add some code here if not */
    502   1.1  jdolecek 
    503   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    504   1.1  jdolecek 		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
    505   1.1  jdolecek 		EMU_HCFG_MUTEBUTTONENABLE);
    506   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, 0);
    507   1.1  jdolecek 
    508  1.60  jmcneill 	mutex_enter(&sc->sc_lock);
    509   1.1  jdolecek 	emuxki_shutdown(sc);
    510  1.60  jmcneill 	mutex_exit(&sc->sc_lock);
    511   1.1  jdolecek 
    512   1.1  jdolecek 	emuxki_pci_shutdown(sc);
    513   1.1  jdolecek 
    514  1.60  jmcneill 	mutex_destroy(&sc->sc_lock);
    515  1.60  jmcneill 	mutex_destroy(&sc->sc_intr_lock);
    516  1.60  jmcneill 	mutex_destroy(&sc->sc_index_lock);
    517  1.60  jmcneill 	mutex_destroy(&sc->sc_ac97_index_lock);
    518  1.60  jmcneill 
    519  1.40      kent 	return 0;
    520   1.1  jdolecek }
    521   1.1  jdolecek 
    522   1.1  jdolecek 
    523   1.1  jdolecek /* Misc stuff relative to emu10k1 */
    524   1.1  jdolecek 
    525  1.40      kent static uint32_t
    526  1.40      kent emuxki_rate_to_pitch(uint32_t rate)
    527   1.1  jdolecek {
    528  1.40      kent 	static const uint32_t logMagTable[128] = {
    529   1.1  jdolecek 		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3,
    530   1.1  jdolecek 		0x13aa2, 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a,
    531   1.1  jdolecek 		0x2655d, 0x28ed5, 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb,
    532   1.1  jdolecek 		0x381b6, 0x3a93d, 0x3d081, 0x3f782, 0x41e42, 0x444c1, 0x46b01,
    533   1.1  jdolecek 		0x49101, 0x4b6c4, 0x4dc49, 0x50191, 0x5269e, 0x54b6f, 0x57006,
    534   1.1  jdolecek 		0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 0x646ee, 0x66a00,
    535   1.1  jdolecek 		0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 0x759d4,
    536   1.1  jdolecek 		0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
    537   1.1  jdolecek 		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20,
    538   1.1  jdolecek 		0x93d26, 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec,
    539   1.1  jdolecek 		0xa11d8, 0xa2f9d, 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241,
    540   1.1  jdolecek 		0xadf26, 0xafbe7, 0xb1885, 0xb3500, 0xb5157, 0xb6d8c, 0xb899f,
    541   1.1  jdolecek 		0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 0xc1404, 0xc2f50, 0xc4a7b,
    542   1.1  jdolecek 		0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 0xceaec, 0xd053f,
    543   1.1  jdolecek 		0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 0xdba4a,
    544   1.1  jdolecek 		0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
    545   1.1  jdolecek 		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a,
    546   1.1  jdolecek 		0xf2c83, 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57,
    547   1.1  jdolecek 		0xfd1a7, 0xfe8df
    548   1.1  jdolecek 	};
    549  1.40      kent 	static const uint8_t logSlopeTable[128] = {
    550   1.1  jdolecek 		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
    551   1.1  jdolecek 		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
    552   1.1  jdolecek 		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
    553   1.1  jdolecek 		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
    554   1.1  jdolecek 		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
    555   1.1  jdolecek 		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
    556   1.1  jdolecek 		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
    557   1.1  jdolecek 		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
    558   1.1  jdolecek 		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
    559   1.1  jdolecek 		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
    560   1.1  jdolecek 		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
    561   1.1  jdolecek 		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
    562   1.1  jdolecek 		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
    563   1.1  jdolecek 		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
    564   1.1  jdolecek 		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
    565   1.1  jdolecek 		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
    566   1.1  jdolecek 	};
    567  1.40      kent 	int8_t i;
    568   1.1  jdolecek 
    569   1.1  jdolecek 	if (rate == 0)
    570   1.1  jdolecek 		return 0;	/* Bail out if no leading "1" */
    571   1.1  jdolecek 	rate *= 11185;		/* Scale 48000 to 0x20002380 */
    572   1.1  jdolecek 	for (i = 31; i > 0; i--) {
    573   1.1  jdolecek 		if (rate & 0x80000000) {	/* Detect leading "1" */
    574  1.40      kent 			return (((uint32_t) (i - 15) << 20) +
    575   1.1  jdolecek 				logMagTable[0x7f & (rate >> 24)] +
    576   1.1  jdolecek 				(0x7f & (rate >> 17)) *
    577   1.1  jdolecek 				logSlopeTable[0x7f & (rate >> 24)]);
    578   1.1  jdolecek 		}
    579   1.1  jdolecek 		rate <<= 1;
    580   1.1  jdolecek 	}
    581   1.1  jdolecek 
    582   1.1  jdolecek 	return 0;		/* Should never reach this point */
    583   1.1  jdolecek }
    584   1.1  jdolecek 
    585   1.1  jdolecek /* Emu10k1 Low level */
    586   1.1  jdolecek 
    587  1.40      kent static uint32_t
    588  1.40      kent emuxki_read(struct emuxki_softc *sc, uint16_t chano, uint32_t reg)
    589   1.1  jdolecek {
    590  1.40      kent 	uint32_t ptr, mask;
    591  1.40      kent 	uint8_t  size, offset;
    592   1.1  jdolecek 
    593  1.40      kent 	mask = 0xffffffff;
    594  1.40      kent 	offset = 0;
    595  1.35  christos 	ptr = ((((u_int32_t) reg) << 16) &
    596  1.35  christos 		(sc->sc_type & EMUXKI_AUDIGY ?
    597  1.35  christos 			EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
    598   1.1  jdolecek 		(chano & EMU_PTR_CHNO_MASK);
    599   1.1  jdolecek 	if (reg & 0xff000000) {
    600   1.1  jdolecek 		size = (reg >> 24) & 0x3f;
    601   1.1  jdolecek 		offset = (reg >> 16) & 0x1f;
    602   1.1  jdolecek 		mask = ((1 << size) - 1) << offset;
    603   1.1  jdolecek 	}
    604   1.1  jdolecek 
    605  1.60  jmcneill 	mutex_spin_enter(&sc->sc_index_lock);
    606   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
    607   1.1  jdolecek 	ptr = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_DATA) & mask)
    608   1.1  jdolecek 		>> offset;
    609  1.60  jmcneill 	mutex_spin_exit(&sc->sc_index_lock);
    610   1.1  jdolecek 
    611  1.40      kent 	return ptr;
    612   1.1  jdolecek }
    613   1.1  jdolecek 
    614   1.1  jdolecek static void
    615  1.40      kent emuxki_write(struct emuxki_softc *sc, uint16_t chano,
    616  1.40      kent 	      uint32_t reg, uint32_t data)
    617   1.1  jdolecek {
    618  1.40      kent 	uint32_t ptr, mask;
    619  1.40      kent 	uint8_t size, offset;
    620   1.1  jdolecek 
    621  1.35  christos 	ptr = ((((u_int32_t) reg) << 16) &
    622  1.35  christos 		(sc->sc_type & EMUXKI_AUDIGY ?
    623  1.35  christos 			EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
    624   1.1  jdolecek 		(chano & EMU_PTR_CHNO_MASK);
    625   1.1  jdolecek 	if (reg & 0xff000000) {
    626   1.1  jdolecek 		size = (reg >> 24) & 0x3f;
    627   1.1  jdolecek 		offset = (reg >> 16) & 0x1f;
    628   1.1  jdolecek 		mask = ((1 << size) - 1) << offset;
    629   1.1  jdolecek 		data = ((data << offset) & mask) |
    630   1.1  jdolecek 			(emuxki_read(sc, chano, reg & 0xffff) & ~mask);
    631   1.1  jdolecek 	}
    632   1.1  jdolecek 
    633  1.60  jmcneill 	mutex_spin_enter(&sc->sc_index_lock);
    634   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
    635   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_DATA, data);
    636  1.60  jmcneill 	mutex_spin_exit(&sc->sc_index_lock);
    637   1.1  jdolecek }
    638   1.1  jdolecek 
    639   1.1  jdolecek /* Microcode should this go in /sys/dev/microcode ? */
    640   1.1  jdolecek 
    641   1.1  jdolecek static void
    642  1.40      kent emuxki_write_micro(struct emuxki_softc *sc, uint32_t pc, uint32_t data)
    643   1.1  jdolecek {
    644  1.40      kent 
    645  1.35  christos 	emuxki_write(sc, 0,
    646  1.35  christos 		(sc->sc_type & EMUXKI_AUDIGY ?
    647  1.35  christos 			EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc,
    648  1.35  christos 		 data);
    649   1.1  jdolecek }
    650   1.1  jdolecek 
    651   1.1  jdolecek static void
    652  1.40      kent emuxki_dsp_addop(struct emuxki_softc *sc, uint16_t *pc, uint8_t op,
    653  1.40      kent 		  uint16_t r, uint16_t a, uint16_t x, uint16_t y)
    654   1.1  jdolecek {
    655  1.40      kent 
    656  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY) {
    657  1.35  christos 		emuxki_write_micro(sc, *pc << 1,
    658  1.35  christos 			((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) |
    659  1.35  christos 			(y & EMU_A_DSP_LOWORD_OPY_MASK));
    660  1.35  christos 		emuxki_write_micro(sc, (*pc << 1) + 1,
    661  1.35  christos 			((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) |
    662  1.35  christos 			((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) |
    663  1.35  christos 			(a & EMU_A_DSP_HIWORD_OPA_MASK));
    664  1.35  christos 	} else {
    665  1.35  christos 		emuxki_write_micro(sc, *pc << 1,
    666  1.35  christos 			((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
    667  1.35  christos 			(y & EMU_DSP_LOWORD_OPY_MASK));
    668  1.35  christos 		emuxki_write_micro(sc, (*pc << 1) + 1,
    669  1.35  christos 			((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
    670  1.35  christos 			((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
    671  1.35  christos 			(a & EMU_DSP_HIWORD_OPA_MASK));
    672  1.35  christos 	}
    673  1.40      kent 	(*pc)++;
    674   1.1  jdolecek }
    675   1.1  jdolecek 
    676   1.1  jdolecek /* init and shutdown */
    677   1.1  jdolecek 
    678   1.1  jdolecek static void
    679   1.1  jdolecek emuxki_initfx(struct emuxki_softc *sc)
    680   1.1  jdolecek {
    681  1.40      kent 	uint16_t pc;
    682   1.1  jdolecek 
    683   1.1  jdolecek 	/* Set all GPRs to 0 */
    684   1.1  jdolecek 	for (pc = 0; pc < 256; pc++)
    685   1.1  jdolecek 		emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
    686   1.1  jdolecek 	for (pc = 0; pc < 160; pc++) {
    687   1.1  jdolecek 		emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
    688   1.1  jdolecek 		emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
    689   1.1  jdolecek 	}
    690   1.1  jdolecek 	pc = 0;
    691   1.1  jdolecek 
    692  1.35  christos 	if (sc->sc_type & EMUXKI_AUDIGY) {
    693  1.35  christos 		/* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
    694  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    695  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
    696  1.35  christos 				  EMU_A_DSP_CST(0),
    697  1.35  christos 				  EMU_DSP_FX(0), EMU_A_DSP_CST(4));
    698  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    699  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
    700  1.35  christos 				  EMU_A_DSP_CST(0),
    701  1.35  christos 				  EMU_DSP_FX(1), EMU_A_DSP_CST(4));
    702  1.35  christos 
    703  1.35  christos 		/* Rear channel OUT (l/r) = FX[2/3] * 4 */
    704   1.1  jdolecek #if 0
    705  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    706  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR),
    707  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
    708  1.35  christos 				  EMU_DSP_FX(0), EMU_A_DSP_CST(4));
    709  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    710  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR),
    711  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
    712  1.35  christos 				  EMU_DSP_FX(1), EMU_A_DSP_CST(4));
    713  1.35  christos #endif
    714  1.35  christos 		/* ADC recording (l/r) = AC97 In (l/r) */
    715  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    716  1.35  christos 				  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC),
    717  1.35  christos 				  EMU_A_DSP_INL(EMU_DSP_IN_AC97),
    718  1.35  christos 				  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
    719  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    720  1.35  christos 				  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC),
    721  1.35  christos 				  EMU_A_DSP_INR(EMU_DSP_IN_AC97),
    722  1.35  christos 				  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
    723  1.35  christos 
    724  1.35  christos 		/* zero out the rest of the microcode */
    725  1.35  christos 		while (pc < 512)
    726  1.35  christos 			emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    727  1.35  christos 					  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0),
    728  1.35  christos 					  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
    729  1.35  christos 
    730  1.35  christos 		emuxki_write(sc, 0, EMU_A_DBG, 0);	/* Is it really necessary ? */
    731  1.35  christos 	} else {
    732  1.35  christos 		/* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
    733  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    734  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
    735  1.35  christos 				  EMU_DSP_CST(0),
    736  1.35  christos 				  EMU_DSP_FX(0), EMU_DSP_CST(4));
    737  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    738  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
    739  1.35  christos 				  EMU_DSP_CST(0),
    740  1.35  christos 				  EMU_DSP_FX(1), EMU_DSP_CST(4));
    741  1.35  christos 
    742  1.35  christos 		/* Rear channel OUT (l/r) = FX[2/3] * 4 */
    743  1.35  christos #if 0
    744  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    745  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR),
    746  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
    747  1.35  christos 				  EMU_DSP_FX(0), EMU_DSP_CST(4));
    748  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    749  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR),
    750  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
    751  1.35  christos 				  EMU_DSP_FX(1), EMU_DSP_CST(4));
    752  1.35  christos #endif
    753  1.35  christos 		/* ADC recording (l/r) = AC97 In (l/r) */
    754   1.1  jdolecek 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    755  1.35  christos 				  EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
    756  1.35  christos 				  EMU_DSP_INL(EMU_DSP_IN_AC97),
    757   1.1  jdolecek 				  EMU_DSP_CST(0), EMU_DSP_CST(0));
    758  1.35  christos 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    759  1.35  christos 				  EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
    760  1.35  christos 				  EMU_DSP_INR(EMU_DSP_IN_AC97),
    761  1.35  christos 				  EMU_DSP_CST(0), EMU_DSP_CST(0));
    762  1.35  christos 
    763  1.35  christos 		/* zero out the rest of the microcode */
    764  1.35  christos 		while (pc < 512)
    765  1.35  christos 			emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    766  1.35  christos 					  EMU_DSP_CST(0), EMU_DSP_CST(0),
    767  1.35  christos 					  EMU_DSP_CST(0), EMU_DSP_CST(0));
    768   1.1  jdolecek 
    769  1.35  christos 		emuxki_write(sc, 0, EMU_DBG, 0);	/* Is it really necessary ? */
    770  1.35  christos 	}
    771   1.1  jdolecek }
    772   1.1  jdolecek 
    773   1.1  jdolecek static int
    774   1.1  jdolecek emuxki_init(struct emuxki_softc *sc)
    775   1.1  jdolecek {
    776  1.40      kent 	uint16_t i;
    777  1.40      kent 	uint32_t spcs, *ptb;
    778  1.40      kent 	bus_addr_t silentpage;
    779   1.1  jdolecek 
    780   1.1  jdolecek 	/* disable any channel interrupt */
    781   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    782   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    783   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    784   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    785   1.1  jdolecek 
    786   1.1  jdolecek 	/* Set recording buffers sizes to zero */
    787   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    788   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    789   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    790   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    791   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    792   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    793   1.1  jdolecek 
    794  1.40      kent 	if(sc->sc_type & EMUXKI_AUDIGY) {
    795  1.40      kent 		emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS);
    796  1.40      kent 		emuxki_write(sc, 0, EMU_AC97SLOT, EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE);
    797  1.40      kent 	}
    798  1.35  christos 
    799   1.1  jdolecek 	/* Initialize all channels to stopped and no effects */
    800   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    801   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
    802   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IP, 0);
    803   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
    804   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
    805   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    806   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    807   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCR, 0);
    808   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PSST, 0);
    809   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DSL, 0x10);	/* Why 16 ? */
    810   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCCA, 0);
    811   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z1, 0);
    812   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z2, 0);
    813   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
    814   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
    815   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
    816   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
    817   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PEFE, 0);
    818   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
    819   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 24);
    820   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 24);
    821   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
    822   1.1  jdolecek 
    823   1.1  jdolecek 		/* these are last so OFF prevents writing */
    824   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0);
    825   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0);
    826   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0);
    827   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
    828   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0);
    829   1.1  jdolecek 	}
    830   1.1  jdolecek 
    831   1.1  jdolecek 	/* set digital outputs format */
    832   1.1  jdolecek 	spcs = (EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
    833   1.1  jdolecek 	      EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
    834   1.1  jdolecek 		EMU_SPCS_GENERATIONSTATUS | 0x00001200 /* Cat code. */ |
    835   1.1  jdolecek 		0x00000000 /* IEC-958 Mode */ | EMU_SPCS_EMPHASIS_NONE |
    836   1.1  jdolecek 		EMU_SPCS_COPYRIGHT);
    837   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS0, spcs);
    838   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS1, spcs);
    839   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS2, spcs);
    840   1.1  jdolecek 
    841  1.40      kent 	if(sc->sc_type & EMUXKI_AUDIGY2) {
    842  1.40      kent 		emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, EMU_A2_SPDIF_UNKNOWN);
    843  1.35  christos 
    844  1.40      kent 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCSEL);
    845  1.41     perry 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA,
    846  1.40      kent 			EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
    847  1.40      kent 
    848  1.40      kent 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCMULTI);
    849  1.40      kent 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA, EMU_A2_SRCMULTI_ENABLE_INPUT);
    850  1.40      kent 	}
    851  1.35  christos 
    852  1.35  christos 
    853   1.1  jdolecek 	/* Let's play with sound processor */
    854   1.1  jdolecek 	emuxki_initfx(sc);
    855   1.1  jdolecek 
    856   1.1  jdolecek 	/* Here is our Page Table */
    857   1.1  jdolecek 	if ((sc->ptb = dmamem_alloc(sc->sc_dmat,
    858   1.1  jdolecek 	    EMU_MAXPTE * sizeof(u_int32_t),
    859  1.60  jmcneill 	    EMU_DMA_ALIGN, EMU_DMAMEM_NSEG)) == NULL)
    860  1.40      kent 		return ENOMEM;
    861   1.1  jdolecek 
    862   1.1  jdolecek 	/* This is necessary unless you like Metallic noise... */
    863   1.1  jdolecek 	if ((sc->silentpage = dmamem_alloc(sc->sc_dmat, EMU_PTESIZE,
    864  1.60  jmcneill 	    EMU_DMA_ALIGN, EMU_DMAMEM_NSEG))==NULL){
    865  1.60  jmcneill 		dmamem_free(sc->ptb);
    866  1.40      kent 		return ENOMEM;
    867   1.1  jdolecek 	}
    868   1.1  jdolecek 
    869   1.1  jdolecek 	/* Zero out the silent page */
    870   1.1  jdolecek 	/* This might not be always true, it might be 128 for 8bit channels */
    871   1.1  jdolecek 	memset(KERNADDR(sc->silentpage), 0, DMASIZE(sc->silentpage));
    872   1.1  jdolecek 
    873   1.1  jdolecek 	/*
    874   1.1  jdolecek 	 * Set all the PTB Entries to the silent page We shift the physical
    875   1.1  jdolecek 	 * address by one and OR it with the page number. I don't know what
    876   1.1  jdolecek 	 * the ORed index is for, might be a very useful unused feature...
    877   1.1  jdolecek 	 */
    878   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
    879   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
    880   1.1  jdolecek 	for (i = 0; i < EMU_MAXPTE; i++)
    881  1.34   tsutsui 		ptb[i] = htole32(silentpage | i);
    882   1.1  jdolecek 
    883   1.1  jdolecek 	/* Write PTB address and set TCB to none */
    884   1.1  jdolecek 	emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
    885   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCBS, 0);	/* This means 16K TCB */
    886   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCB, 0);	/* No TCB use for now */
    887   1.1  jdolecek 
    888   1.1  jdolecek 	/*
    889   1.1  jdolecek 	 * Set channels MAPs to the silent page.
    890   1.1  jdolecek 	 * I don't know what MAPs are for.
    891   1.1  jdolecek 	 */
    892   1.1  jdolecek 	silentpage |= EMU_CHAN_MAP_PTI_MASK;
    893   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    894   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_MAPA, silentpage);
    895   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_MAPB, silentpage);
    896   1.1  jdolecek 		sc->channel[i] = NULL;
    897   1.1  jdolecek 	}
    898   1.1  jdolecek 
    899   1.1  jdolecek 	/* Init voices list */
    900   1.1  jdolecek 	LIST_INIT(&(sc->voices));
    901   1.1  jdolecek 
    902   1.1  jdolecek 	/* Timer is stopped */
    903   1.1  jdolecek 	sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
    904  1.40      kent 	return 0;
    905   1.1  jdolecek }
    906   1.1  jdolecek 
    907   1.1  jdolecek static void
    908   1.1  jdolecek emuxki_shutdown(struct emuxki_softc *sc)
    909   1.1  jdolecek {
    910  1.40      kent 	uint32_t i;
    911   1.1  jdolecek 
    912   1.1  jdolecek 	/* Disable any Channels interrupts */
    913   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    914   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    915   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    916   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    917   1.1  jdolecek 
    918   1.1  jdolecek 	/*
    919   1.1  jdolecek 	 * Should do some voice(stream) stopping stuff here, that's what will
    920   1.1  jdolecek 	 * stop and deallocate all channels.
    921   1.1  jdolecek 	 */
    922   1.1  jdolecek 
    923   1.1  jdolecek 	/* Stop all channels */
    924   1.1  jdolecek 	/* XXX This shouldn't be necessary, I'll remove once everything works */
    925   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++)
    926   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
    927   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    928   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0);
    929   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0);
    930   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    931   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    932   1.1  jdolecek 	}
    933   1.1  jdolecek 
    934   1.1  jdolecek 	/*
    935   1.1  jdolecek 	 * Deallocate Emu10k1 caches and recording buffers. Again it will be
    936   1.1  jdolecek 	 * removed because it will be done in voice shutdown.
    937   1.1  jdolecek 	 */
    938   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    939   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    940   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    941   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    942  1.40      kent 	if(sc->sc_type & EMUXKI_AUDIGY) {
    943  1.40      kent 		emuxki_write(sc, 0, EMU_A_FXWC1, 0);
    944  1.40      kent 		emuxki_write(sc, 0, EMU_A_FXWC2, 0);
    945  1.40      kent 	} else {
    946  1.40      kent 		emuxki_write(sc, 0, EMU_FXWC, 0);
    947  1.40      kent 	}
    948   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    949   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    950   1.1  jdolecek 
    951   1.1  jdolecek 	/*
    952   1.1  jdolecek 	 * XXX I don't know yet how I will handle tank cache buffer,
    953   1.1  jdolecek 	 * I don't even clearly  know what it is for.
    954   1.1  jdolecek 	 */
    955   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCB, 0);	/* 16K again */
    956   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCBS, 0);
    957   1.1  jdolecek 
    958   1.1  jdolecek 	emuxki_write(sc, 0, EMU_DBG, 0x8000);	/* necessary ? */
    959   1.1  jdolecek 
    960  1.60  jmcneill 	dmamem_free(sc->silentpage);
    961  1.60  jmcneill 	dmamem_free(sc->ptb);
    962   1.1  jdolecek }
    963   1.1  jdolecek 
    964  1.25       wiz /* Emu10k1 Memory management */
    965   1.1  jdolecek 
    966   1.1  jdolecek static struct emuxki_mem *
    967  1.60  jmcneill emuxki_mem_new(struct emuxki_softc *sc, int ptbidx, size_t size)
    968   1.1  jdolecek {
    969   1.1  jdolecek 	struct emuxki_mem *mem;
    970   1.1  jdolecek 
    971  1.60  jmcneill 	if ((mem = kmem_alloc(sizeof(*mem), KM_SLEEP)) == NULL)
    972  1.40      kent 		return NULL;
    973   1.1  jdolecek 
    974   1.1  jdolecek 	mem->ptbidx = ptbidx;
    975   1.1  jdolecek 	if ((mem->dmamem = dmamem_alloc(sc->sc_dmat, size, EMU_DMA_ALIGN,
    976  1.60  jmcneill 	    EMU_DMAMEM_NSEG)) == NULL) {
    977  1.60  jmcneill 		kmem_free(mem, sizeof(*mem));
    978  1.40      kent 		return NULL;
    979   1.1  jdolecek 	}
    980  1.40      kent 	return mem;
    981   1.1  jdolecek }
    982   1.1  jdolecek 
    983   1.1  jdolecek static void
    984  1.60  jmcneill emuxki_mem_delete(struct emuxki_mem *mem, size_t size)
    985   1.1  jdolecek {
    986  1.40      kent 
    987  1.60  jmcneill 	dmamem_free(mem->dmamem);
    988  1.60  jmcneill 	kmem_free(mem, sizeof(*mem));
    989   1.1  jdolecek }
    990   1.1  jdolecek 
    991   1.1  jdolecek static void *
    992  1.60  jmcneill emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size)
    993   1.1  jdolecek {
    994  1.60  jmcneill 	int i, j;
    995  1.40      kent 	size_t numblocks;
    996   1.1  jdolecek 	struct emuxki_mem *mem;
    997  1.40      kent 	uint32_t *ptb, silentpage;
    998   1.1  jdolecek 
    999   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
   1000   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
   1001   1.1  jdolecek 	numblocks = size / EMU_PTESIZE;
   1002   1.1  jdolecek 	if (size % EMU_PTESIZE)
   1003   1.1  jdolecek 		numblocks++;
   1004   1.1  jdolecek 
   1005  1.60  jmcneill 	for (i = 0; i < EMU_MAXPTE; i++) {
   1006  1.60  jmcneill 		mutex_spin_enter(&sc->sc_intr_lock);
   1007  1.34   tsutsui 		if ((le32toh(ptb[i]) & EMU_CHAN_MAP_PTE_MASK) == silentpage) {
   1008   1.1  jdolecek 			/* We look for a free PTE */
   1009   1.1  jdolecek 			for (j = 0; j < numblocks; j++)
   1010  1.34   tsutsui 				if ((le32toh(ptb[i + j])
   1011  1.34   tsutsui 				    & EMU_CHAN_MAP_PTE_MASK) != silentpage)
   1012   1.1  jdolecek 					break;
   1013   1.1  jdolecek 			if (j == numblocks) {
   1014  1.60  jmcneill 				mutex_spin_exit(&sc->sc_intr_lock);
   1015   1.1  jdolecek 				if ((mem = emuxki_mem_new(sc, i,
   1016  1.60  jmcneill 						size)) == NULL) {
   1017  1.40      kent 					return NULL;
   1018   1.1  jdolecek 				}
   1019  1.60  jmcneill 				mutex_spin_enter(&sc->sc_intr_lock);
   1020   1.1  jdolecek 				for (j = 0; j < numblocks; j++)
   1021   1.1  jdolecek 					ptb[i + j] =
   1022  1.34   tsutsui 					    htole32((((DMAADDR(mem->dmamem) +
   1023  1.34   tsutsui 					    j * EMU_PTESIZE)) << 1) | (i + j));
   1024   1.1  jdolecek 				LIST_INSERT_HEAD(&(sc->mem), mem, next);
   1025  1.60  jmcneill 				mutex_spin_exit(&sc->sc_intr_lock);
   1026   1.1  jdolecek 				return (KERNADDR(mem->dmamem));
   1027   1.1  jdolecek 			} else
   1028   1.1  jdolecek 				i += j;
   1029   1.1  jdolecek 		}
   1030  1.60  jmcneill 		mutex_spin_exit(&sc->sc_intr_lock);
   1031  1.60  jmcneill 	}
   1032  1.40      kent 	return NULL;
   1033   1.1  jdolecek }
   1034   1.1  jdolecek 
   1035   1.1  jdolecek static void *
   1036  1.60  jmcneill emuxki_rmem_alloc(struct emuxki_softc *sc, size_t size)
   1037   1.1  jdolecek {
   1038   1.1  jdolecek 	struct emuxki_mem *mem;
   1039   1.1  jdolecek 
   1040  1.60  jmcneill 	mem = emuxki_mem_new(sc, EMU_RMEM, size);
   1041   1.1  jdolecek 	if (mem == NULL)
   1042  1.40      kent 		return NULL;
   1043   1.1  jdolecek 
   1044  1.60  jmcneill 	mutex_spin_enter(&sc->sc_intr_lock);
   1045   1.1  jdolecek 	LIST_INSERT_HEAD(&(sc->mem), mem, next);
   1046  1.60  jmcneill 	mutex_spin_exit(&sc->sc_intr_lock);
   1047   1.1  jdolecek 
   1048  1.40      kent 	return KERNADDR(mem->dmamem);
   1049   1.1  jdolecek }
   1050   1.1  jdolecek 
   1051   1.1  jdolecek /*
   1052  1.25       wiz  * emuxki_channel_* : Channel management functions
   1053   1.1  jdolecek  * emuxki_chanparms_* : Channel parameters modification functions
   1054   1.1  jdolecek  */
   1055   1.1  jdolecek 
   1056   1.1  jdolecek /*
   1057   1.1  jdolecek  * is splaudio necessary here, can the same voice be manipulated by two
   1058   1.1  jdolecek  * different threads at a time ?
   1059   1.1  jdolecek  */
   1060   1.1  jdolecek static void
   1061   1.1  jdolecek emuxki_chanparms_set_defaults(struct emuxki_channel *chan)
   1062   1.1  jdolecek {
   1063  1.40      kent 
   1064   1.1  jdolecek 	chan->fxsend.a.level = chan->fxsend.b.level =
   1065  1.35  christos 	chan->fxsend.c.level = chan->fxsend.d.level =
   1066  1.35  christos 	/* for audigy */
   1067  1.35  christos 	chan->fxsend.e.level = chan->fxsend.f.level =
   1068  1.35  christos 	chan->fxsend.g.level = chan->fxsend.h.level =
   1069  1.35  christos 		chan->voice->sc->sc_type & EMUXKI_AUDIGY ?
   1070  1.35  christos 			0xc0 : 0xff;	/* not max */
   1071  1.35  christos 
   1072   1.1  jdolecek 	chan->fxsend.a.dest = 0x0;
   1073   1.1  jdolecek 	chan->fxsend.b.dest = 0x1;
   1074   1.1  jdolecek 	chan->fxsend.c.dest = 0x2;
   1075   1.1  jdolecek 	chan->fxsend.d.dest = 0x3;
   1076  1.35  christos 	/* for audigy */
   1077  1.35  christos 	chan->fxsend.e.dest = 0x4;
   1078  1.35  christos 	chan->fxsend.f.dest = 0x5;
   1079  1.35  christos 	chan->fxsend.g.dest = 0x6;
   1080  1.35  christos 	chan->fxsend.h.dest = 0x7;
   1081   1.1  jdolecek 
   1082  1.17       wiz 	chan->pitch.initial = 0x0000;	/* shouldn't it be 0xE000 ? */
   1083   1.1  jdolecek 	chan->pitch.current = 0x0000;	/* should it be 0x0400 */
   1084   1.1  jdolecek 	chan->pitch.target = 0x0000;	/* the unity pitch shift ? */
   1085   1.1  jdolecek 	chan->pitch.envelope_amount = 0x00;	/* none */
   1086   1.1  jdolecek 
   1087   1.1  jdolecek 	chan->initial_attenuation = 0x00;	/* no attenuation */
   1088   1.1  jdolecek 	chan->volume.current = 0x0000;	/* no volume */
   1089   1.1  jdolecek 	chan->volume.target = 0xffff;
   1090   1.1  jdolecek 	chan->volume.envelope.current_state = 0x8000;	/* 0 msec delay */
   1091   1.1  jdolecek 	chan->volume.envelope.hold_time = 0x7f;	/* 0 msec */
   1092   1.1  jdolecek 	chan->volume.envelope.attack_time = 0x7F;	/* 5.5msec */
   1093   1.1  jdolecek 	chan->volume.envelope.sustain_level = 0x7F;	/* full  */
   1094   1.1  jdolecek 	chan->volume.envelope.decay_time = 0x7F;	/* 22msec  */
   1095   1.1  jdolecek 
   1096   1.1  jdolecek 	chan->filter.initial_cutoff_frequency = 0xff;	/* no filter */
   1097   1.1  jdolecek 	chan->filter.current_cutoff_frequency = 0xffff;	/* no filtering */
   1098   1.1  jdolecek 	chan->filter.target_cutoff_frequency = 0xffff;	/* no filtering */
   1099   1.1  jdolecek 	chan->filter.lowpass_resonance_height = 0x0;
   1100   1.1  jdolecek 	chan->filter.interpolation_ROM = 0x1;	/* full band */
   1101   1.1  jdolecek 	chan->filter.envelope_amount = 0x7f;	/* none */
   1102   1.1  jdolecek 	chan->filter.LFO_modulation_depth = 0x00;	/* none */
   1103   1.1  jdolecek 
   1104   1.1  jdolecek 	chan->loop.start = 0x000000;
   1105   1.1  jdolecek 	chan->loop.end = 0x000010;	/* Why ? */
   1106   1.1  jdolecek 
   1107   1.1  jdolecek 	chan->modulation.envelope.current_state = 0x8000;
   1108   1.1  jdolecek 	chan->modulation.envelope.hold_time = 0x00;	/* 127 better ? */
   1109   1.1  jdolecek 	chan->modulation.envelope.attack_time = 0x00;	/* infinite */
   1110   1.1  jdolecek 	chan->modulation.envelope.sustain_level = 0x00;	/* off */
   1111   1.1  jdolecek 	chan->modulation.envelope.decay_time = 0x7f;	/* 22 msec */
   1112   1.1  jdolecek 	chan->modulation.LFO_state = 0x8000;
   1113   1.1  jdolecek 
   1114   1.1  jdolecek 	chan->vibrato_LFO.state = 0x8000;
   1115   1.1  jdolecek 	chan->vibrato_LFO.modulation_depth = 0x00;	/* none */
   1116   1.1  jdolecek 	chan->vibrato_LFO.vibrato_depth = 0x00;
   1117   1.1  jdolecek 	chan->vibrato_LFO.frequency = 0x00;	/* Why set to 24 when
   1118   1.1  jdolecek 						 * initialized ? */
   1119   1.1  jdolecek 
   1120   1.1  jdolecek 	chan->tremolo_depth = 0x00;
   1121   1.1  jdolecek }
   1122   1.1  jdolecek 
   1123   1.1  jdolecek /* only call it at splaudio */
   1124   1.1  jdolecek static struct emuxki_channel *
   1125   1.1  jdolecek emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num)
   1126   1.1  jdolecek {
   1127   1.1  jdolecek 	struct emuxki_channel *chan;
   1128   1.1  jdolecek 
   1129   1.1  jdolecek 	chan = malloc(sizeof(struct emuxki_channel), M_DEVBUF, M_WAITOK);
   1130   1.1  jdolecek 	if (chan == NULL)
   1131  1.40      kent 		return NULL;
   1132   1.1  jdolecek 
   1133   1.1  jdolecek 	chan->voice = voice;
   1134   1.1  jdolecek 	chan->num = num;
   1135   1.1  jdolecek 	emuxki_chanparms_set_defaults(chan);
   1136   1.1  jdolecek 	chan->voice->sc->channel[num] = chan;
   1137  1.40      kent 	return chan;
   1138   1.1  jdolecek }
   1139   1.1  jdolecek 
   1140   1.1  jdolecek /* only call it at splaudio */
   1141   1.1  jdolecek static void
   1142   1.1  jdolecek emuxki_channel_delete(struct emuxki_channel *chan)
   1143   1.1  jdolecek {
   1144  1.40      kent 
   1145   1.1  jdolecek 	chan->voice->sc->channel[chan->num] = NULL;
   1146   1.1  jdolecek 	free(chan, M_DEVBUF);
   1147   1.1  jdolecek }
   1148   1.1  jdolecek 
   1149   1.1  jdolecek static void
   1150   1.1  jdolecek emuxki_channel_set_fxsend(struct emuxki_channel *chan,
   1151  1.40      kent     struct emuxki_chanparms_fxsend *fxsend)
   1152   1.1  jdolecek {
   1153   1.1  jdolecek 	/* Could do a memcpy ...*/
   1154   1.1  jdolecek 	chan->fxsend.a.level = fxsend->a.level;
   1155   1.1  jdolecek 	chan->fxsend.b.level = fxsend->b.level;
   1156   1.1  jdolecek 	chan->fxsend.c.level = fxsend->c.level;
   1157   1.1  jdolecek 	chan->fxsend.d.level = fxsend->d.level;
   1158   1.1  jdolecek 	chan->fxsend.a.dest = fxsend->a.dest;
   1159   1.1  jdolecek 	chan->fxsend.b.dest = fxsend->b.dest;
   1160   1.1  jdolecek 	chan->fxsend.c.dest = fxsend->c.dest;
   1161   1.1  jdolecek 	chan->fxsend.d.dest = fxsend->d.dest;
   1162  1.35  christos 
   1163  1.35  christos 	/* for audigy */
   1164  1.35  christos 	chan->fxsend.e.level = fxsend->e.level;
   1165  1.35  christos 	chan->fxsend.f.level = fxsend->f.level;
   1166  1.35  christos 	chan->fxsend.g.level = fxsend->g.level;
   1167  1.35  christos 	chan->fxsend.h.level = fxsend->h.level;
   1168  1.35  christos 	chan->fxsend.e.dest = fxsend->e.dest;
   1169  1.35  christos 	chan->fxsend.f.dest = fxsend->f.dest;
   1170  1.35  christos 	chan->fxsend.g.dest = fxsend->g.dest;
   1171  1.35  christos 	chan->fxsend.h.dest = fxsend->h.dest;
   1172   1.1  jdolecek }
   1173   1.1  jdolecek 
   1174   1.1  jdolecek static void
   1175  1.40      kent emuxki_channel_set_srate(struct emuxki_channel *chan, uint32_t srate)
   1176   1.1  jdolecek {
   1177  1.40      kent 
   1178   1.1  jdolecek 	chan->pitch.target = (srate << 8) / 375;
   1179   1.1  jdolecek 	chan->pitch.target = (chan->pitch.target >> 1) +
   1180   1.1  jdolecek 		(chan->pitch.target & 1);
   1181   1.1  jdolecek 	chan->pitch.target &= 0xffff;
   1182   1.1  jdolecek 	chan->pitch.current = chan->pitch.target;
   1183  1.17       wiz 	chan->pitch.initial =
   1184   1.1  jdolecek 		(emuxki_rate_to_pitch(srate) >> 8) & EMU_CHAN_IP_MASK;
   1185   1.1  jdolecek }
   1186   1.1  jdolecek 
   1187   1.1  jdolecek /* voice params must be set before calling this */
   1188   1.1  jdolecek static void
   1189   1.1  jdolecek emuxki_channel_set_bufparms(struct emuxki_channel *chan,
   1190  1.40      kent     uint32_t start, uint32_t end)
   1191   1.1  jdolecek {
   1192  1.40      kent 
   1193   1.1  jdolecek 	chan->loop.start = start & EMU_CHAN_PSST_LOOPSTARTADDR_MASK;
   1194   1.1  jdolecek 	chan->loop.end = end & EMU_CHAN_DSL_LOOPENDADDR_MASK;
   1195   1.1  jdolecek }
   1196   1.1  jdolecek 
   1197   1.1  jdolecek static void
   1198  1.35  christos emuxki_channel_commit_fx(struct emuxki_channel *chan)
   1199  1.35  christos {
   1200  1.40      kent 	struct emuxki_softc *sc;
   1201  1.40      kent 	u_int8_t chano;
   1202  1.40      kent 
   1203  1.40      kent 	sc = chan->voice->sc;
   1204  1.40      kent 	chano = chan->num;
   1205  1.40      kent 	if(sc->sc_type & EMUXKI_AUDIGY) {
   1206  1.40      kent 		emuxki_write(sc, chano, EMU_A_CHAN_FXRT1,
   1207  1.40      kent 			      (chan->fxsend.d.dest << 24) |
   1208  1.40      kent 			      (chan->fxsend.c.dest << 16) |
   1209  1.40      kent 			      (chan->fxsend.b.dest << 8) |
   1210  1.40      kent 			      (chan->fxsend.a.dest));
   1211  1.40      kent 		emuxki_write(sc, chano, EMU_A_CHAN_FXRT2,
   1212  1.40      kent 			      (chan->fxsend.h.dest << 24) |
   1213  1.40      kent 			      (chan->fxsend.g.dest << 16) |
   1214  1.40      kent 			      (chan->fxsend.f.dest << 8) |
   1215  1.40      kent 			      (chan->fxsend.e.dest));
   1216  1.40      kent 		emuxki_write(sc, chano, EMU_A_CHAN_SENDAMOUNTS,
   1217  1.40      kent 			      (chan->fxsend.e.level << 24) |
   1218  1.40      kent 			      (chan->fxsend.f.level << 16) |
   1219  1.40      kent 			      (chan->fxsend.g.level << 8) |
   1220  1.40      kent 			      (chan->fxsend.h.level));
   1221  1.40      kent 	} else {
   1222  1.40      kent 		emuxki_write(sc, chano, EMU_CHAN_FXRT,
   1223  1.40      kent 			      (chan->fxsend.d.dest << 28) |
   1224  1.40      kent 			      (chan->fxsend.c.dest << 24) |
   1225  1.40      kent 			      (chan->fxsend.b.dest << 20) |
   1226  1.40      kent 			      (chan->fxsend.a.dest << 16));
   1227  1.40      kent 	}
   1228  1.40      kent 
   1229  1.40      kent 	emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX,
   1230  1.40      kent 		      (chan->fxsend.a.level << 8) | chan->fxsend.b.level);
   1231  1.40      kent 	emuxki_write(sc, chano, EMU_CHAN_DSL,
   1232  1.40      kent 		      (chan->fxsend.d.level << 24) | chan->loop.end);
   1233  1.40      kent 	emuxki_write(sc, chano, EMU_CHAN_PSST,
   1234  1.40      kent 		      (chan->fxsend.c.level << 24) | chan->loop.start);
   1235  1.35  christos }
   1236  1.35  christos 
   1237  1.35  christos static void
   1238   1.1  jdolecek emuxki_channel_commit_parms(struct emuxki_channel *chan)
   1239   1.1  jdolecek {
   1240  1.40      kent 	struct emuxki_voice *voice;
   1241  1.40      kent 	struct emuxki_softc *sc;
   1242  1.40      kent 	uint32_t start, mapval;
   1243  1.40      kent 	uint8_t chano;
   1244   1.1  jdolecek 
   1245  1.40      kent 	voice = chan->voice;
   1246  1.40      kent 	sc = voice->sc;
   1247  1.40      kent 	chano = chan->num;
   1248   1.1  jdolecek 	start = chan->loop.start +
   1249   1.1  jdolecek 		(voice->stereo ? 28 : 30) * (voice->b16 + 1);
   1250   1.1  jdolecek 	mapval = DMAADDR(sc->silentpage) << 1 | EMU_CHAN_MAP_PTI_MASK;
   1251   1.1  jdolecek 
   1252  1.60  jmcneill 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1253   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo);
   1254  1.35  christos 
   1255  1.35  christos 	emuxki_channel_commit_fx(chan);
   1256  1.35  christos 
   1257   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCCA,
   1258   1.1  jdolecek 		(chan->filter.lowpass_resonance_height << 28) |
   1259   1.1  jdolecek 		(chan->filter.interpolation_ROM << 25) |
   1260   1.1  jdolecek 		(voice->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT) | start);
   1261   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_Z1, 0);
   1262   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_Z2, 0);
   1263   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_MAPA, mapval);
   1264   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_MAPB, mapval);
   1265   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRFILTER,
   1266   1.1  jdolecek 		chan->filter.current_cutoff_frequency);
   1267   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_FILTERTARGET,
   1268   1.1  jdolecek 		chan->filter.target_cutoff_frequency);
   1269   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ATKHLDM,
   1270   1.1  jdolecek 		(chan->modulation.envelope.hold_time << 8) |
   1271   1.1  jdolecek 		chan->modulation.envelope.attack_time);
   1272   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DCYSUSM,
   1273   1.1  jdolecek 		(chan->modulation.envelope.sustain_level << 8) |
   1274   1.1  jdolecek 		chan->modulation.envelope.decay_time);
   1275   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_LFOVAL1,
   1276   1.1  jdolecek 		chan->modulation.LFO_state);
   1277   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_LFOVAL2,
   1278   1.1  jdolecek 		chan->vibrato_LFO.state);
   1279   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FMMOD,
   1280   1.1  jdolecek 		(chan->vibrato_LFO.modulation_depth << 8) |
   1281   1.1  jdolecek 		chan->filter.LFO_modulation_depth);
   1282   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_TREMFRQ,
   1283   1.1  jdolecek 		(chan->tremolo_depth << 8));
   1284   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FM2FRQ2,
   1285   1.1  jdolecek 		(chan->vibrato_LFO.vibrato_depth << 8) |
   1286   1.1  jdolecek 		chan->vibrato_LFO.frequency);
   1287   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ENVVAL,
   1288   1.1  jdolecek 		chan->modulation.envelope.current_state);
   1289   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ATKHLDV,
   1290   1.1  jdolecek 		(chan->volume.envelope.hold_time << 8) |
   1291   1.1  jdolecek 		chan->volume.envelope.attack_time);
   1292   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ENVVOL,
   1293   1.1  jdolecek 		chan->volume.envelope.current_state);
   1294   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PEFE,
   1295   1.1  jdolecek 		(chan->pitch.envelope_amount << 8) |
   1296   1.1  jdolecek 		chan->filter.envelope_amount);
   1297   1.1  jdolecek }
   1298   1.1  jdolecek 
   1299   1.1  jdolecek static void
   1300   1.1  jdolecek emuxki_channel_start(struct emuxki_channel *chan)
   1301   1.1  jdolecek {
   1302  1.40      kent 	struct emuxki_voice *voice;
   1303  1.40      kent 	struct emuxki_softc *sc;
   1304  1.40      kent 	u_int8_t cache_sample, cache_invalid_size, chano;
   1305  1.40      kent 	u_int32_t sample;
   1306   1.1  jdolecek 
   1307  1.40      kent 	voice = chan->voice;
   1308  1.40      kent 	sc = voice->sc;
   1309  1.40      kent 	chano = chan->num;
   1310   1.1  jdolecek 	cache_sample = voice->stereo ? 4 : 2;
   1311   1.1  jdolecek 	sample = voice->b16 ? 0x00000000 : 0x80808080;
   1312   1.1  jdolecek 	cache_invalid_size = (voice->stereo ? 28 : 30) * (voice->b16 + 1);
   1313   1.1  jdolecek 
   1314  1.60  jmcneill 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1315   1.1  jdolecek 	while (cache_sample--) {
   1316   1.1  jdolecek 		emuxki_write(sc, chano, EMU_CHAN_CD0 + cache_sample,
   1317   1.1  jdolecek 			sample);
   1318   1.1  jdolecek 	}
   1319   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
   1320   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_READADDRESS, 64);
   1321   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE,
   1322   1.1  jdolecek 		cache_invalid_size);
   1323   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IFATN,
   1324   1.1  jdolecek 		(chan->filter.target_cutoff_frequency << 8) |
   1325   1.1  jdolecek 		chan->initial_attenuation);
   1326   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET,
   1327   1.1  jdolecek 		chan->volume.target);
   1328   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL,
   1329   1.1  jdolecek 		chan->volume.current);
   1330   1.1  jdolecek 	emuxki_write(sc, 0,
   1331   1.1  jdolecek 		EMU_MKSUBREG(1, chano, EMU_SOLEL + (chano >> 5)),
   1332   1.1  jdolecek 		0);	/* Clear stop on loop */
   1333   1.1  jdolecek 	emuxki_write(sc, 0,
   1334   1.1  jdolecek 		EMU_MKSUBREG(1, chano, EMU_CLIEL + (chano >> 5)),
   1335   1.1  jdolecek 		0);	/* Clear loop interrupt */
   1336   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DCYSUSV,
   1337   1.1  jdolecek 		(chan->volume.envelope.sustain_level << 8) |
   1338   1.1  jdolecek 		chan->volume.envelope.decay_time);
   1339   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET,
   1340   1.1  jdolecek 		chan->pitch.target);
   1341   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH,
   1342   1.1  jdolecek 		chan->pitch.current);
   1343  1.17       wiz 	emuxki_write(sc, chano, EMU_CHAN_IP, chan->pitch.initial);
   1344   1.1  jdolecek }
   1345   1.1  jdolecek 
   1346   1.1  jdolecek static void
   1347   1.1  jdolecek emuxki_channel_stop(struct emuxki_channel *chan)
   1348   1.1  jdolecek {
   1349  1.40      kent 	struct emuxki_softc *sc;
   1350  1.40      kent 	u_int8_t chano;
   1351   1.1  jdolecek 
   1352  1.40      kent 	sc = chan->voice->sc;
   1353  1.40      kent 	chano = chan->num;
   1354  1.60  jmcneill 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1355   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET, 0);
   1356   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH, 0);
   1357   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IFATN_ATTENUATION, 0xff);
   1358   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET, 0);
   1359   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL, 0);
   1360   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IP, 0);
   1361   1.1  jdolecek }
   1362   1.1  jdolecek 
   1363   1.1  jdolecek /*
   1364  1.25       wiz  * Voices management
   1365  1.37   dsainty  * emuxki_voice_dataloc : use(play or rec) independent dataloc union helpers
   1366   1.1  jdolecek  * emuxki_voice_channel_* : play part of dataloc union helpers
   1367   1.1  jdolecek  * emuxki_voice_recsrc_* : rec part of dataloc union helpers
   1368   1.1  jdolecek  */
   1369   1.1  jdolecek 
   1370   1.1  jdolecek /* Allocate channels for voice in case of play voice */
   1371   1.1  jdolecek static int
   1372   1.1  jdolecek emuxki_voice_channel_create(struct emuxki_voice *voice)
   1373   1.1  jdolecek {
   1374  1.40      kent 	struct emuxki_channel **channel;
   1375  1.40      kent 	uint8_t i, stereo;
   1376   1.1  jdolecek 
   1377  1.40      kent 	channel = voice->sc->channel;
   1378  1.40      kent 	stereo = voice->stereo;
   1379  1.45  christos 	for (i = 0; i < EMU_NUMCHAN - stereo; i += stereo + 1) {
   1380   1.1  jdolecek 		if ((stereo && (channel[i + 1] != NULL)) ||
   1381   1.1  jdolecek 		    (channel[i] != NULL))	/* Looking for free channels */
   1382   1.1  jdolecek 			continue;
   1383  1.60  jmcneill 
   1384   1.1  jdolecek 		if (stereo) {
   1385   1.1  jdolecek 			voice->dataloc.chan[1] =
   1386   1.1  jdolecek 				emuxki_channel_new(voice, i + 1);
   1387  1.60  jmcneill 			if (voice->dataloc.chan[1] == NULL)
   1388  1.40      kent 				return ENOMEM;
   1389   1.1  jdolecek 		}
   1390   1.1  jdolecek 		voice->dataloc.chan[0] = emuxki_channel_new(voice, i);
   1391   1.1  jdolecek 		if (voice->dataloc.chan[0] == NULL) {
   1392   1.1  jdolecek 			if (stereo) {
   1393   1.1  jdolecek 				emuxki_channel_delete(voice->dataloc.chan[1]);
   1394   1.1  jdolecek 				voice->dataloc.chan[1] = NULL;
   1395   1.1  jdolecek 			}
   1396  1.40      kent 			return ENOMEM;
   1397   1.1  jdolecek 		}
   1398  1.40      kent 		return 0;
   1399   1.1  jdolecek 	}
   1400  1.40      kent 	return EAGAIN;
   1401   1.1  jdolecek }
   1402   1.1  jdolecek 
   1403   1.1  jdolecek /* When calling this function we assume no one can access the voice */
   1404   1.1  jdolecek static void
   1405   1.1  jdolecek emuxki_voice_channel_destroy(struct emuxki_voice *voice)
   1406   1.1  jdolecek {
   1407  1.40      kent 
   1408   1.1  jdolecek 	emuxki_channel_delete(voice->dataloc.chan[0]);
   1409   1.1  jdolecek 	voice->dataloc.chan[0] = NULL;
   1410   1.1  jdolecek 	if (voice->stereo)
   1411   1.1  jdolecek 		emuxki_channel_delete(voice->dataloc.chan[1]);
   1412   1.1  jdolecek 	voice->dataloc.chan[1] = NULL;
   1413   1.1  jdolecek }
   1414   1.1  jdolecek 
   1415   1.1  jdolecek /*
   1416   1.1  jdolecek  * Will come back when used in voice_dataloc_create
   1417   1.1  jdolecek  */
   1418   1.1  jdolecek static int
   1419   1.1  jdolecek emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
   1420   1.1  jdolecek {
   1421  1.40      kent 
   1422  1.46  christos 	if (source >= EMU_NUMRECSRCS) {
   1423  1.19    toshii #ifdef EMUXKI_DEBUG
   1424  1.37   dsainty 		printf("Tried to reserve invalid source: %d\n", source);
   1425  1.19    toshii #endif
   1426  1.40      kent 		return EINVAL;
   1427  1.19    toshii 	}
   1428  1.19    toshii 	if (voice->sc->recsrc[source] == voice)
   1429  1.40      kent 		return 0;			/* XXX */
   1430  1.19    toshii 	if (voice->sc->recsrc[source] != NULL)
   1431  1.40      kent 		return EBUSY;
   1432  1.19    toshii 	voice->sc->recsrc[source] = voice;
   1433  1.40      kent 	return 0;
   1434   1.1  jdolecek }
   1435  1.19    toshii 
   1436   1.1  jdolecek /* When calling this function we assume the voice is stopped */
   1437   1.1  jdolecek static void
   1438   1.1  jdolecek emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source)
   1439   1.1  jdolecek {
   1440  1.40      kent 
   1441   1.1  jdolecek 	sc->recsrc[source] = NULL;
   1442   1.1  jdolecek }
   1443   1.1  jdolecek 
   1444   1.1  jdolecek static int
   1445   1.1  jdolecek emuxki_voice_dataloc_create(struct emuxki_voice *voice)
   1446   1.1  jdolecek {
   1447  1.40      kent 	int error;
   1448   1.1  jdolecek 
   1449   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1450   1.1  jdolecek 		if ((error = emuxki_voice_channel_create(voice)))
   1451  1.40      kent 			return error;
   1452   1.1  jdolecek 	} else {
   1453  1.19    toshii 		if ((error =
   1454  1.19    toshii 		    emuxki_recsrc_reserve(voice, voice->dataloc.source)))
   1455  1.40      kent 			return error;
   1456   1.1  jdolecek 	}
   1457  1.40      kent 	return 0;
   1458   1.1  jdolecek }
   1459   1.1  jdolecek 
   1460   1.1  jdolecek static void
   1461   1.1  jdolecek emuxki_voice_dataloc_destroy(struct emuxki_voice *voice)
   1462   1.1  jdolecek {
   1463  1.40      kent 
   1464   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1465   1.1  jdolecek 		if (voice->dataloc.chan[0] != NULL)
   1466   1.1  jdolecek 			emuxki_voice_channel_destroy(voice);
   1467   1.1  jdolecek 	} else {
   1468   1.1  jdolecek 		if (voice->dataloc.source != EMU_RECSRC_NOTSET) {
   1469   1.1  jdolecek 			emuxki_voice_recsrc_release(voice->sc,
   1470   1.1  jdolecek 						     voice->dataloc.source);
   1471   1.1  jdolecek 			voice->dataloc.source = EMU_RECSRC_NOTSET;
   1472   1.1  jdolecek 		}
   1473   1.1  jdolecek 	}
   1474   1.1  jdolecek }
   1475   1.1  jdolecek 
   1476   1.1  jdolecek static struct emuxki_voice *
   1477  1.40      kent emuxki_voice_new(struct emuxki_softc *sc, uint8_t use)
   1478   1.1  jdolecek {
   1479   1.1  jdolecek 	struct emuxki_voice *voice;
   1480   1.1  jdolecek 
   1481  1.60  jmcneill 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1482  1.60  jmcneill 
   1483   1.7  jdolecek 	voice = sc->lvoice;
   1484   1.7  jdolecek 	sc->lvoice = NULL;
   1485   1.7  jdolecek 
   1486  1.24    toshii 	if (!voice) {
   1487  1.60  jmcneill 		mutex_exit(&sc->sc_intr_lock);
   1488  1.60  jmcneill 		voice = kmem_alloc(sizeof(*voice), KM_SLEEP);
   1489  1.60  jmcneill 		mutex_enter(&sc->sc_intr_lock);
   1490  1.60  jmcneill 		if (!voice)
   1491  1.40      kent 			return NULL;
   1492  1.60  jmcneill 	} else if (voice->use != use) {
   1493  1.60  jmcneill 		mutex_exit(&sc->sc_intr_lock);
   1494  1.24    toshii 		emuxki_voice_dataloc_destroy(voice);
   1495  1.60  jmcneill 		mutex_enter(&sc->sc_intr_lock);
   1496  1.60  jmcneill 	} else
   1497  1.24    toshii 		goto skip_initialize;
   1498  1.19    toshii 
   1499  1.19    toshii 	voice->sc = sc;
   1500  1.19    toshii 	voice->state = !EMU_VOICE_STATE_STARTED;
   1501  1.19    toshii 	voice->stereo = EMU_VOICE_STEREO_NOTSET;
   1502  1.19    toshii 	voice->b16 = 0;
   1503  1.19    toshii 	voice->sample_rate = 0;
   1504  1.19    toshii 	if (use & EMU_VOICE_USE_PLAY)
   1505  1.19    toshii 		voice->dataloc.chan[0] = voice->dataloc.chan[1] = NULL;
   1506  1.19    toshii 	else
   1507  1.19    toshii 		voice->dataloc.source = EMU_RECSRC_NOTSET;
   1508  1.19    toshii 	voice->buffer = NULL;
   1509  1.19    toshii 	voice->blksize = 0;
   1510  1.19    toshii 	voice->trigblk = 0;
   1511  1.19    toshii 	voice->blkmod = 0;
   1512  1.19    toshii 	voice->inth = NULL;
   1513  1.19    toshii 	voice->inthparam = NULL;
   1514   1.1  jdolecek 	voice->use = use;
   1515   1.1  jdolecek 
   1516  1.24    toshii skip_initialize:
   1517   1.1  jdolecek 	LIST_INSERT_HEAD((&sc->voices), voice, next);
   1518   1.1  jdolecek 
   1519  1.40      kent 	return voice;
   1520   1.1  jdolecek }
   1521   1.1  jdolecek 
   1522   1.1  jdolecek static void
   1523   1.1  jdolecek emuxki_voice_delete(struct emuxki_voice *voice)
   1524   1.1  jdolecek {
   1525  1.40      kent 	struct emuxki_softc *sc;
   1526   1.7  jdolecek 	struct emuxki_voice *lvoice;
   1527   1.1  jdolecek 
   1528  1.40      kent 	sc = voice->sc;
   1529   1.1  jdolecek 	if (voice->state & EMU_VOICE_STATE_STARTED)
   1530   1.1  jdolecek 		emuxki_voice_halt(voice);
   1531   1.1  jdolecek 
   1532   1.1  jdolecek 	LIST_REMOVE(voice, next);
   1533   1.7  jdolecek 	lvoice = sc->lvoice;
   1534   1.7  jdolecek 	sc->lvoice = voice;
   1535   1.1  jdolecek 
   1536   1.7  jdolecek 	if (lvoice) {
   1537  1.60  jmcneill 		mutex_exit(&sc->sc_lock);
   1538   1.7  jdolecek 		emuxki_voice_dataloc_destroy(lvoice);
   1539  1.60  jmcneill 		kmem_free(lvoice, sizeof(*lvoice));
   1540  1.60  jmcneill 		mutex_enter(&sc->sc_lock);
   1541   1.7  jdolecek 	}
   1542   1.1  jdolecek }
   1543   1.1  jdolecek 
   1544   1.1  jdolecek static int
   1545  1.60  jmcneill emuxki_voice_set_stereo(struct emuxki_softc *sc,
   1546  1.60  jmcneill     			struct emuxki_voice *voice, uint8_t stereo)
   1547   1.1  jdolecek {
   1548  1.40      kent 	int error;
   1549  1.40      kent 	emuxki_recsrc_t source;
   1550   1.1  jdolecek 	struct emuxki_chanparms_fxsend fxsend;
   1551   1.1  jdolecek 
   1552  1.40      kent 	source = 0;		/* XXX: gcc */
   1553  1.19    toshii 	if (! (voice->use & EMU_VOICE_USE_PLAY))
   1554  1.19    toshii 		source = voice->dataloc.source;
   1555  1.60  jmcneill 	mutex_exit(&sc->sc_lock);
   1556   1.1  jdolecek 	emuxki_voice_dataloc_destroy(voice);
   1557  1.19    toshii 	if (! (voice->use & EMU_VOICE_USE_PLAY))
   1558  1.19    toshii 		voice->dataloc.source = source;
   1559   1.1  jdolecek 	voice->stereo = stereo;
   1560  1.60  jmcneill 	error = emuxki_voice_dataloc_create(voice);
   1561  1.60  jmcneill 	mutex_enter(&sc->sc_lock);
   1562  1.60  jmcneill 	if (error)
   1563  1.40      kent 		return error;
   1564   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1565   1.1  jdolecek 		fxsend.a.dest = 0x0;
   1566   1.1  jdolecek 		fxsend.b.dest = 0x1;
   1567   1.1  jdolecek 		fxsend.c.dest = 0x2;
   1568   1.1  jdolecek 		fxsend.d.dest = 0x3;
   1569  1.35  christos 		/* for audigy */
   1570  1.35  christos 		fxsend.e.dest = 0x4;
   1571  1.35  christos 		fxsend.f.dest = 0x5;
   1572  1.35  christos 		fxsend.g.dest = 0x6;
   1573  1.35  christos 		fxsend.h.dest = 0x7;
   1574   1.1  jdolecek 		if (voice->stereo) {
   1575   1.7  jdolecek 			fxsend.a.level = fxsend.c.level = 0xc0;
   1576   1.1  jdolecek 			fxsend.b.level = fxsend.d.level = 0x00;
   1577  1.35  christos 			fxsend.e.level = fxsend.g.level = 0xc0;
   1578  1.35  christos 			fxsend.f.level = fxsend.h.level = 0x00;
   1579   1.1  jdolecek 			emuxki_channel_set_fxsend(voice->dataloc.chan[0],
   1580   1.1  jdolecek 						   &fxsend);
   1581   1.1  jdolecek 			fxsend.a.level = fxsend.c.level = 0x00;
   1582   1.7  jdolecek 			fxsend.b.level = fxsend.d.level = 0xc0;
   1583  1.35  christos 			fxsend.e.level = fxsend.g.level = 0x00;
   1584  1.35  christos 			fxsend.f.level = fxsend.h.level = 0xc0;
   1585   1.1  jdolecek 			emuxki_channel_set_fxsend(voice->dataloc.chan[1],
   1586   1.1  jdolecek 						   &fxsend);
   1587  1.40      kent 		} /* No else : default is good for mono */
   1588   1.1  jdolecek 	}
   1589  1.40      kent 	return 0;
   1590   1.1  jdolecek }
   1591   1.1  jdolecek 
   1592   1.1  jdolecek static int
   1593  1.40      kent emuxki_voice_set_srate(struct emuxki_voice *voice, uint32_t srate)
   1594   1.1  jdolecek {
   1595  1.40      kent 
   1596   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1597   1.1  jdolecek 		if ((srate < 4000) || (srate > 48000))
   1598  1.40      kent 			return EINVAL;
   1599   1.1  jdolecek 		voice->sample_rate = srate;
   1600   1.1  jdolecek 		emuxki_channel_set_srate(voice->dataloc.chan[0], srate);
   1601   1.1  jdolecek 		if (voice->stereo)
   1602   1.1  jdolecek 			emuxki_channel_set_srate(voice->dataloc.chan[1],
   1603   1.1  jdolecek 						  srate);
   1604   1.1  jdolecek 	} else {
   1605  1.35  christos 		if ((srate < 8000) || (srate > 48000))
   1606  1.40      kent 			return EINVAL;
   1607  1.19    toshii 		voice->sample_rate = srate;
   1608  1.35  christos 		if (emuxki_voice_adc_rate(voice) < 0) {
   1609  1.35  christos 			voice->sample_rate = 0;
   1610  1.40      kent 			return EINVAL;
   1611  1.35  christos 		}
   1612   1.1  jdolecek 	}
   1613  1.40      kent 	return 0;
   1614   1.1  jdolecek }
   1615   1.1  jdolecek 
   1616   1.1  jdolecek static int
   1617  1.60  jmcneill emuxki_voice_set_audioparms(struct emuxki_softc *sc,
   1618  1.60  jmcneill     struct emuxki_voice *voice, uint8_t stereo, uint8_t b16, uint32_t srate)
   1619   1.1  jdolecek {
   1620  1.40      kent 	int error;
   1621   1.1  jdolecek 
   1622   1.1  jdolecek 	if (voice->stereo == stereo && voice->b16 == b16 &&
   1623   1.1  jdolecek 	    voice->sample_rate == srate)
   1624  1.40      kent 		return 0;
   1625   1.1  jdolecek 
   1626   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1627  1.18   tsutsui 	printf("Setting %s voice params : %s, %u bits, %u Hz\n",
   1628   1.1  jdolecek 	       (voice->use & EMU_VOICE_USE_PLAY) ? "play" : "record",
   1629   1.1  jdolecek 	       stereo ? "stereo" : "mono", (b16 + 1) * 8, srate);
   1630   1.1  jdolecek #endif
   1631  1.40      kent 	error = 0;
   1632   1.1  jdolecek 	if (voice->stereo != stereo) {
   1633  1.60  jmcneill 		if ((error = emuxki_voice_set_stereo(sc, voice, stereo)))
   1634  1.40      kent 			return error;
   1635   1.1  jdolecek 	 }
   1636   1.1  jdolecek 	voice->b16 = b16;
   1637   1.1  jdolecek 	if (voice->sample_rate != srate)
   1638  1.23    toshii 		error = emuxki_voice_set_srate(voice, srate);
   1639  1.23    toshii 	return error;
   1640   1.1  jdolecek }
   1641   1.1  jdolecek 
   1642   1.1  jdolecek /* voice audio parms (see just before) must be set prior to this */
   1643   1.1  jdolecek static int
   1644   1.1  jdolecek emuxki_voice_set_bufparms(struct emuxki_voice *voice, void *ptr,
   1645  1.40      kent     uint32_t bufsize, uint16_t blksize)
   1646   1.1  jdolecek {
   1647   1.1  jdolecek 	struct emuxki_mem *mem;
   1648   1.1  jdolecek 	struct emuxki_channel **chan;
   1649  1.40      kent 	uint32_t start, end;
   1650  1.40      kent 	uint8_t sample_size;
   1651  1.19    toshii 	int idx;
   1652  1.40      kent 	int error;
   1653   1.1  jdolecek 
   1654  1.40      kent 	error = EFAULT;
   1655   1.1  jdolecek 	LIST_FOREACH(mem, &voice->sc->mem, next) {
   1656   1.1  jdolecek 		if (KERNADDR(mem->dmamem) != ptr)
   1657   1.1  jdolecek 			continue;
   1658   1.1  jdolecek 
   1659   1.1  jdolecek 		voice->buffer = mem;
   1660   1.1  jdolecek 		sample_size = (voice->b16 + 1) * (voice->stereo + 1);
   1661   1.1  jdolecek 		voice->trigblk = 0;	/* This shouldn't be needed */
   1662   1.1  jdolecek 		voice->blkmod = bufsize / blksize;
   1663  1.40      kent 		if (bufsize % blksize)	  /* This should not happen */
   1664   1.1  jdolecek 			voice->blkmod++;
   1665   1.1  jdolecek 		error = 0;
   1666   1.1  jdolecek 
   1667   1.1  jdolecek 		if (voice->use & EMU_VOICE_USE_PLAY) {
   1668  1.19    toshii 			voice->blksize = blksize / sample_size;
   1669   1.1  jdolecek 			chan = voice->dataloc.chan;
   1670   1.1  jdolecek 			start = mem->ptbidx << 12;
   1671   1.1  jdolecek 			end = start + bufsize / sample_size;
   1672   1.1  jdolecek 			emuxki_channel_set_bufparms(chan[0],
   1673   1.1  jdolecek 						     start, end);
   1674   1.1  jdolecek 			if (voice->stereo)
   1675   1.1  jdolecek 				emuxki_channel_set_bufparms(chan[1],
   1676   1.1  jdolecek 				     start, end);
   1677  1.40      kent 			voice->timerate = (uint32_t) 48000 *
   1678  1.40      kent 			    voice->blksize / voice->sample_rate;
   1679   1.1  jdolecek 			if (voice->timerate < 5)
   1680   1.1  jdolecek 				error = EINVAL;
   1681   1.1  jdolecek 		} else {
   1682  1.19    toshii 			voice->blksize = blksize;
   1683  1.19    toshii 			for(idx = sizeof(emuxki_recbuf_sz) /
   1684  1.19    toshii 			    sizeof(emuxki_recbuf_sz[0]); --idx >= 0;)
   1685  1.19    toshii 				if (emuxki_recbuf_sz[idx] == bufsize)
   1686  1.19    toshii 					break;
   1687  1.19    toshii 			if (idx < 0) {
   1688  1.19    toshii #ifdef EMUXKI_DEBUG
   1689  1.19    toshii 				printf("Invalid bufsize: %d\n", bufsize);
   1690  1.19    toshii #endif
   1691  1.40      kent 				return EINVAL;
   1692  1.19    toshii 			}
   1693  1.19    toshii 			emuxki_write(voice->sc, 0,
   1694  1.19    toshii 			    emuxki_recsrc_szreg[voice->dataloc.source], idx);
   1695  1.19    toshii 			emuxki_write(voice->sc, 0,
   1696  1.19    toshii 			    emuxki_recsrc_bufaddrreg[voice->dataloc.source],
   1697  1.19    toshii 			    DMAADDR(mem->dmamem));
   1698  1.19    toshii 
   1699  1.19    toshii 			/* Use timer to emulate DMA completion interrupt */
   1700  1.19    toshii 			voice->timerate = (u_int32_t) 48000 * blksize /
   1701  1.19    toshii 			    (voice->sample_rate * sample_size);
   1702  1.19    toshii 			if (voice->timerate < 5) {
   1703   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1704  1.19    toshii 				printf("Invalid timerate: %d, blksize %d\n",
   1705  1.19    toshii 				    voice->timerate, blksize);
   1706   1.1  jdolecek #endif
   1707  1.19    toshii 				error = EINVAL;
   1708  1.19    toshii 			}
   1709   1.1  jdolecek 		}
   1710   1.1  jdolecek 
   1711   1.1  jdolecek 		break;
   1712   1.1  jdolecek 	}
   1713   1.1  jdolecek 
   1714  1.40      kent 	return error;
   1715   1.1  jdolecek }
   1716   1.1  jdolecek 
   1717   1.1  jdolecek static void
   1718   1.1  jdolecek emuxki_voice_commit_parms(struct emuxki_voice *voice)
   1719   1.1  jdolecek {
   1720   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1721   1.1  jdolecek 		emuxki_channel_commit_parms(voice->dataloc.chan[0]);
   1722   1.1  jdolecek 		if (voice->stereo)
   1723   1.1  jdolecek 			emuxki_channel_commit_parms(voice->dataloc.chan[1]);
   1724   1.1  jdolecek 	}
   1725   1.1  jdolecek }
   1726   1.1  jdolecek 
   1727  1.40      kent static uint32_t
   1728   1.1  jdolecek emuxki_voice_curaddr(struct emuxki_voice *voice)
   1729   1.1  jdolecek {
   1730  1.40      kent 	int idxreg;
   1731  1.53  gmcgarry 	int rv;
   1732  1.19    toshii 
   1733  1.19    toshii 	/* XXX different semantics in these cases */
   1734  1.35  christos 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1735  1.19    toshii 		/* returns number of samples (an l/r pair counts 1) */
   1736  1.53  gmcgarry 		rv = emuxki_read(voice->sc,
   1737  1.40      kent 		    voice->dataloc.chan[0]->num, EMU_CHAN_CCCA_CURRADDR) -
   1738  1.40      kent 		    voice->dataloc.chan[0]->loop.start;
   1739  1.35  christos 	} else {
   1740  1.40      kent 		idxreg = 0;
   1741  1.19    toshii 		/* returns number of bytes */
   1742  1.35  christos 		switch (voice->dataloc.source) {
   1743  1.35  christos 			case EMU_RECSRC_MIC:
   1744  1.35  christos 				idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
   1745  1.35  christos 					EMU_A_MICIDX : EMU_MICIDX;
   1746  1.35  christos 				break;
   1747  1.35  christos 			case EMU_RECSRC_ADC:
   1748  1.35  christos 				idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
   1749  1.35  christos 					EMU_A_ADCIDX : EMU_ADCIDX;
   1750  1.35  christos 				break;
   1751  1.35  christos 			case EMU_RECSRC_FX:
   1752  1.35  christos 				idxreg = EMU_FXIDX;
   1753  1.35  christos 				break;
   1754  1.35  christos 			default:
   1755  1.35  christos #ifdef EMUXKI_DEBUG
   1756  1.35  christos 				printf("emu: bad recording source!\n");
   1757  1.35  christos #endif
   1758  1.35  christos 				break;
   1759  1.35  christos 		}
   1760  1.53  gmcgarry 		rv = emuxki_read(voice->sc, 0, EMU_RECIDX(idxreg)
   1761  1.35  christos 				& EMU_RECIDX_MASK);
   1762  1.35  christos 	}
   1763  1.53  gmcgarry 	return rv;
   1764   1.1  jdolecek }
   1765   1.1  jdolecek 
   1766   1.1  jdolecek static void
   1767   1.1  jdolecek emuxki_resched_timer(struct emuxki_softc *sc)
   1768   1.1  jdolecek {
   1769   1.1  jdolecek 	struct emuxki_voice *voice;
   1770  1.40      kent 	uint16_t timerate;
   1771  1.40      kent 	uint8_t active;
   1772   1.1  jdolecek 
   1773  1.40      kent 	timerate = 1024;
   1774  1.40      kent 	active = 0;
   1775  1.60  jmcneill 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1776   1.1  jdolecek 	LIST_FOREACH(voice, &sc->voices, next) {
   1777  1.19    toshii 		if ((voice->state & EMU_VOICE_STATE_STARTED) == 0)
   1778   1.1  jdolecek 			continue;
   1779   1.1  jdolecek 		active = 1;
   1780   1.1  jdolecek 		if (voice->timerate < timerate)
   1781   1.1  jdolecek 			timerate = voice->timerate;
   1782   1.1  jdolecek 	}
   1783   1.1  jdolecek 
   1784   1.1  jdolecek 	if (timerate & ~EMU_TIMER_RATE_MASK)
   1785   1.1  jdolecek 		timerate = 0;
   1786  1.14      tron 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_TIMER, timerate);
   1787   1.1  jdolecek 	if (!active && (sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
   1788   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
   1789   1.1  jdolecek 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) &
   1790   1.1  jdolecek 			~EMU_INTE_INTERTIMERENB);
   1791   1.1  jdolecek 		sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
   1792   1.1  jdolecek 	} else if (active && !(sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
   1793   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
   1794   1.1  jdolecek 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
   1795   1.1  jdolecek 			EMU_INTE_INTERTIMERENB);
   1796   1.1  jdolecek 		sc->timerstate |= EMU_TIMER_STATE_ENABLED;
   1797   1.1  jdolecek 	}
   1798   1.1  jdolecek }
   1799   1.1  jdolecek 
   1800  1.35  christos static int
   1801  1.35  christos emuxki_voice_adc_rate(struct emuxki_voice *voice)
   1802  1.35  christos {
   1803  1.40      kent 
   1804  1.35  christos 	switch(voice->sample_rate) {
   1805  1.35  christos 		case 48000:
   1806  1.35  christos 			return EMU_ADCCR_SAMPLERATE_48;
   1807  1.35  christos 			break;
   1808  1.35  christos 		case 44100:
   1809  1.35  christos 			return EMU_ADCCR_SAMPLERATE_44;
   1810  1.35  christos 			break;
   1811  1.35  christos 		case 32000:
   1812  1.35  christos 			return EMU_ADCCR_SAMPLERATE_32;
   1813  1.35  christos 			break;
   1814  1.35  christos 		case 24000:
   1815  1.35  christos 			return EMU_ADCCR_SAMPLERATE_24;
   1816  1.35  christos 			break;
   1817  1.35  christos 		case 22050:
   1818  1.35  christos 			return EMU_ADCCR_SAMPLERATE_22;
   1819  1.35  christos 			break;
   1820  1.35  christos 		case 16000:
   1821  1.35  christos 			return EMU_ADCCR_SAMPLERATE_16;
   1822  1.35  christos 			break;
   1823  1.35  christos 		case 12000:
   1824  1.35  christos 			if(voice->sc->sc_type & EMUXKI_AUDIGY)
   1825  1.35  christos 				return EMU_A_ADCCR_SAMPLERATE_12;
   1826  1.35  christos 			else {
   1827  1.35  christos #ifdef EMUXKI_DEBUG
   1828  1.35  christos 				printf("recording sample_rate not supported : %u\n", voice->sample_rate);
   1829  1.35  christos #endif
   1830  1.40      kent 				return -1;
   1831  1.35  christos 			}
   1832  1.35  christos 			break;
   1833  1.35  christos 		case 11000:
   1834  1.35  christos 			if(voice->sc->sc_type & EMUXKI_AUDIGY)
   1835  1.35  christos 				return EMU_A_ADCCR_SAMPLERATE_11;
   1836  1.35  christos 			else
   1837  1.35  christos 				return EMU_ADCCR_SAMPLERATE_11;
   1838  1.35  christos 			break;
   1839  1.35  christos 		case 8000:
   1840  1.35  christos 			if(voice->sc->sc_type & EMUXKI_AUDIGY)
   1841  1.35  christos 				return EMU_A_ADCCR_SAMPLERATE_8;
   1842  1.35  christos 			else
   1843  1.35  christos 				return EMU_ADCCR_SAMPLERATE_8;
   1844  1.35  christos 			break;
   1845  1.35  christos 		default:
   1846  1.35  christos #ifdef EMUXKI_DEBUG
   1847  1.35  christos 				printf("recording sample_rate not supported : %u\n", voice->sample_rate);
   1848  1.35  christos #endif
   1849  1.40      kent 				return -1;
   1850  1.35  christos 	}
   1851  1.40      kent 	return -1;		/* shouldn't get here */
   1852  1.35  christos }
   1853  1.35  christos 
   1854  1.35  christos 
   1855   1.1  jdolecek static void
   1856   1.1  jdolecek emuxki_voice_start(struct emuxki_voice *voice,
   1857  1.40      kent     void (*inth) (void *), void *inthparam)
   1858   1.1  jdolecek {
   1859  1.40      kent 	uint32_t val;
   1860  1.19    toshii 
   1861   1.1  jdolecek 	voice->inth = inth;
   1862   1.1  jdolecek 	voice->inthparam = inthparam;
   1863   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1864   1.1  jdolecek 		voice->trigblk = 1;
   1865   1.1  jdolecek 		emuxki_channel_start(voice->dataloc.chan[0]);
   1866   1.1  jdolecek 		if (voice->stereo)
   1867   1.1  jdolecek 			emuxki_channel_start(voice->dataloc.chan[1]);
   1868  1.19    toshii 	} else {
   1869  1.19    toshii 		voice->trigblk = 1;
   1870  1.35  christos 		switch (voice->dataloc.source) {
   1871  1.19    toshii 		case EMU_RECSRC_ADC:
   1872  1.19    toshii 			/* XXX need to program DSP to output L+R
   1873  1.19    toshii 			 * XXX in monaural case? */
   1874  1.35  christos 			if (voice->sc->sc_type & EMUXKI_AUDIGY) {
   1875  1.35  christos 				val = EMU_A_ADCCR_LCHANENABLE;
   1876  1.35  christos 				if (voice->stereo)
   1877  1.35  christos 					val |= EMU_A_ADCCR_RCHANENABLE;
   1878  1.35  christos 			} else {
   1879  1.35  christos 				val = EMU_ADCCR_LCHANENABLE;
   1880  1.35  christos 				if (voice->stereo)
   1881  1.35  christos 					val |= EMU_ADCCR_RCHANENABLE;
   1882  1.35  christos 			}
   1883  1.35  christos 			val |= emuxki_voice_adc_rate(voice);
   1884  1.35  christos 			emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
   1885  1.35  christos 			emuxki_write(voice->sc, 0, EMU_ADCCR, val);
   1886  1.19    toshii 			break;
   1887  1.19    toshii 		case EMU_RECSRC_MIC:
   1888  1.19    toshii 		case EMU_RECSRC_FX:
   1889  1.19    toshii 			printf("unimplemented\n");
   1890  1.19    toshii 			break;
   1891  1.35  christos 		case EMU_RECSRC_NOTSET:
   1892  1.35  christos 		default:
   1893  1.44  christos 			printf("Bad dataloc.source %d\n",
   1894  1.44  christos 			    voice->dataloc.source);
   1895  1.40      kent 			break;
   1896  1.19    toshii 		}
   1897  1.19    toshii #if 0
   1898  1.44  christos 		switch (voice->dataloc.source) {
   1899  1.44  christos 		case EMU_RECSRC_ADC:
   1900  1.44  christos 		case EMU_RECSRC_FX:
   1901  1.44  christos 		case EMU_RECSRC_MIC:
   1902  1.44  christos 			/* DMA completion interrupt is useless; use timer */
   1903  1.60  jmcneill 			KASSERT(mutex_owned(&sc->sc_intr_lock));
   1904  1.44  christos 			val = emu_rd(sc, INTE, 4);
   1905  1.44  christos 			val |= emuxki_recsrc_intrmasks[voice->dataloc.source];
   1906  1.44  christos 			emu_wr(sc, INTE, val, 4);
   1907  1.44  christos 			break;
   1908  1.44  christos 		default:
   1909  1.44  christos 			break;
   1910  1.44  christos 		}
   1911  1.19    toshii #endif
   1912   1.1  jdolecek 	}
   1913   1.1  jdolecek 	voice->state |= EMU_VOICE_STATE_STARTED;
   1914  1.19    toshii 	emuxki_resched_timer(voice->sc);
   1915   1.1  jdolecek }
   1916   1.1  jdolecek 
   1917   1.1  jdolecek static void
   1918   1.1  jdolecek emuxki_voice_halt(struct emuxki_voice *voice)
   1919   1.1  jdolecek {
   1920  1.40      kent 
   1921   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1922   1.1  jdolecek 		emuxki_channel_stop(voice->dataloc.chan[0]);
   1923   1.1  jdolecek 		if (voice->stereo)
   1924   1.1  jdolecek 			emuxki_channel_stop(voice->dataloc.chan[1]);
   1925  1.19    toshii 	} else {
   1926  1.19    toshii 		switch (voice->dataloc.source) {
   1927  1.19    toshii 		case EMU_RECSRC_ADC:
   1928  1.35  christos 			emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
   1929  1.19    toshii 			break;
   1930  1.19    toshii 		case EMU_RECSRC_FX:
   1931  1.19    toshii 		case EMU_RECSRC_MIC:
   1932  1.19    toshii 			printf("unimplemented\n");
   1933  1.19    toshii 			break;
   1934  1.44  christos 		default:
   1935  1.19    toshii 		case EMU_RECSRC_NOTSET:
   1936  1.44  christos 			printf("Bad dataloc.source %d\n",
   1937  1.44  christos 			    voice->dataloc.source);
   1938  1.44  christos 			break;
   1939  1.19    toshii 		}
   1940  1.44  christos 
   1941  1.44  christos 		switch (voice->dataloc.source) {
   1942  1.44  christos 		case EMU_RECSRC_ADC:
   1943  1.44  christos 		case EMU_RECSRC_FX:
   1944  1.44  christos 		case EMU_RECSRC_MIC:
   1945  1.44  christos 			/* This should reset buffer pointer */
   1946  1.44  christos 			emuxki_write(voice->sc, 0,
   1947  1.44  christos 			    emuxki_recsrc_szreg[voice->dataloc.source],
   1948  1.44  christos 			    EMU_RECBS_BUFSIZE_NONE);
   1949  1.19    toshii #if 0
   1950  1.60  jmcneill 			KASSERT(mutex_owned(&sc->sc_intr_lock));
   1951  1.44  christos 			val = emu_rd(sc, INTE, 4);
   1952  1.44  christos 			val &= ~emuxki_recsrc_intrmasks[voice->dataloc.source];
   1953  1.44  christos 			emu_wr(sc, INTE, val, 4);
   1954  1.19    toshii #endif
   1955  1.44  christos 			break;
   1956  1.44  christos 		default:
   1957  1.44  christos 			break;
   1958  1.44  christos 		}
   1959   1.1  jdolecek 	}
   1960   1.1  jdolecek 	voice->state &= ~EMU_VOICE_STATE_STARTED;
   1961  1.19    toshii 	emuxki_resched_timer(voice->sc);
   1962   1.1  jdolecek }
   1963   1.1  jdolecek 
   1964   1.1  jdolecek /*
   1965   1.1  jdolecek  * The interrupt handler
   1966   1.1  jdolecek  */
   1967   1.1  jdolecek static int
   1968   1.1  jdolecek emuxki_intr(void *arg)
   1969   1.1  jdolecek {
   1970  1.40      kent 	struct emuxki_softc *sc;
   1971   1.1  jdolecek 	struct emuxki_voice *voice;
   1972  1.40      kent 	uint32_t ipr, curblk;
   1973  1.40      kent 	int claim;
   1974   1.1  jdolecek 
   1975  1.40      kent 	sc = arg;
   1976  1.40      kent 	claim = 0;
   1977  1.60  jmcneill 
   1978  1.60  jmcneill 	mutex_spin_enter(&sc->sc_intr_lock);
   1979  1.60  jmcneill 
   1980   1.1  jdolecek 	while ((ipr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_IPR))) {
   1981   1.1  jdolecek 		if (ipr & EMU_IPR_INTERVALTIMER) {
   1982   1.1  jdolecek 			LIST_FOREACH(voice, &sc->voices, next) {
   1983  1.19    toshii 				if ((voice->state &
   1984   1.1  jdolecek 				      EMU_VOICE_STATE_STARTED) == 0)
   1985   1.1  jdolecek 					continue;
   1986   1.1  jdolecek 
   1987   1.1  jdolecek 				curblk = emuxki_voice_curaddr(voice) /
   1988   1.1  jdolecek 				       voice->blksize;
   1989  1.19    toshii #if 0
   1990   1.1  jdolecek 				if (curblk == voice->trigblk) {
   1991   1.1  jdolecek 					voice->inth(voice->inthparam);
   1992   1.1  jdolecek 					voice->trigblk++;
   1993   1.1  jdolecek 					voice->trigblk %= voice->blkmod;
   1994   1.1  jdolecek 				}
   1995  1.19    toshii #else
   1996  1.19    toshii 				while ((curblk >= voice->trigblk &&
   1997  1.19    toshii 				    curblk < (voice->trigblk + voice->blkmod / 2)) ||
   1998  1.19    toshii 				    ((int)voice->trigblk - (int)curblk) >
   1999  1.19    toshii 				    (voice->blkmod / 2 + 1)) {
   2000  1.19    toshii 					voice->inth(voice->inthparam);
   2001  1.19    toshii 					voice->trigblk++;
   2002  1.19    toshii 					voice->trigblk %= voice->blkmod;
   2003  1.19    toshii 				}
   2004  1.19    toshii #endif
   2005   1.1  jdolecek 			}
   2006   1.1  jdolecek 		}
   2007   1.1  jdolecek 
   2008   1.1  jdolecek 		/* Got interrupt */
   2009   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_IPR, ipr);
   2010  1.13  jdolecek 
   2011  1.13  jdolecek 		claim = 1;
   2012   1.1  jdolecek 	}
   2013   1.1  jdolecek 
   2014  1.60  jmcneill 	mutex_spin_exit(&sc->sc_intr_lock);
   2015  1.60  jmcneill 
   2016  1.40      kent 	return claim;
   2017   1.1  jdolecek }
   2018   1.1  jdolecek 
   2019   1.1  jdolecek 
   2020   1.1  jdolecek /*
   2021   1.1  jdolecek  * Audio Architecture callbacks
   2022   1.1  jdolecek  */
   2023   1.1  jdolecek 
   2024   1.1  jdolecek static int
   2025   1.1  jdolecek emuxki_open(void *addr, int flags)
   2026   1.1  jdolecek {
   2027  1.40      kent 	struct emuxki_softc *sc;
   2028   1.1  jdolecek 
   2029  1.40      kent 	sc = addr;
   2030   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2031  1.58   tsutsui 	printf("%s: emuxki_open called\n", device_xname(sc->sc_dev));
   2032   1.1  jdolecek #endif
   2033   1.1  jdolecek 
   2034   1.1  jdolecek 	/*
   2035   1.1  jdolecek 	 * Multiple voice support would be added as soon as I find a way to
   2036   1.1  jdolecek 	 * trick the audio arch into supporting multiple voices.
   2037   1.1  jdolecek 	 * Or I might integrate a modified audio arch supporting
   2038   1.1  jdolecek 	 * multiple voices.
   2039   1.1  jdolecek 	 */
   2040   1.1  jdolecek 
   2041   1.1  jdolecek 	/*
   2042   1.1  jdolecek 	 * I did this because i have problems identifying the selected
   2043   1.1  jdolecek 	 * recording source(s) which is necessary when setting recording
   2044  1.31       wiz 	 * params This will be addressed very soon
   2045   1.1  jdolecek 	 */
   2046  1.19    toshii 	if (flags & AUOPEN_READ) {
   2047  1.19    toshii 		sc->rvoice = emuxki_voice_new(sc, 0 /* EMU_VOICE_USE_RECORD */);
   2048  1.19    toshii 		if (sc->rvoice == NULL)
   2049  1.40      kent 			return EBUSY;
   2050  1.19    toshii 
   2051  1.19    toshii 		/* XXX Hardcode RECSRC_ADC for now */
   2052  1.19    toshii 		sc->rvoice->dataloc.source = EMU_RECSRC_ADC;
   2053  1.19    toshii 	}
   2054   1.1  jdolecek 
   2055   1.1  jdolecek 	if (flags & AUOPEN_WRITE) {
   2056   1.1  jdolecek 		sc->pvoice = emuxki_voice_new(sc, EMU_VOICE_USE_PLAY);
   2057   1.1  jdolecek 		if (sc->pvoice == NULL) {
   2058   1.8  jdolecek 			if (sc->rvoice) {
   2059   1.1  jdolecek 				emuxki_voice_delete(sc->rvoice);
   2060   1.8  jdolecek 				sc->rvoice = NULL;
   2061   1.8  jdolecek 			}
   2062  1.40      kent 			return EBUSY;
   2063   1.1  jdolecek 		}
   2064   1.1  jdolecek 	}
   2065   1.1  jdolecek 
   2066  1.40      kent 	return 0;
   2067   1.1  jdolecek }
   2068   1.1  jdolecek 
   2069   1.1  jdolecek static void
   2070   1.1  jdolecek emuxki_close(void *addr)
   2071   1.1  jdolecek {
   2072  1.40      kent 	struct emuxki_softc *sc;
   2073   1.1  jdolecek 
   2074  1.40      kent 	sc = addr;
   2075   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2076  1.58   tsutsui 	printf("%s: emu10K1_close called\n", device_xname(sc->sc_dev));
   2077   1.1  jdolecek #endif
   2078   1.1  jdolecek 
   2079   1.1  jdolecek 	/* No multiple voice support for now */
   2080   1.8  jdolecek 	if (sc->rvoice != NULL) {
   2081   1.1  jdolecek 		emuxki_voice_delete(sc->rvoice);
   2082   1.8  jdolecek 		sc->rvoice = NULL;
   2083   1.8  jdolecek 	}
   2084   1.8  jdolecek 	if (sc->pvoice != NULL) {
   2085   1.1  jdolecek 		emuxki_voice_delete(sc->pvoice);
   2086   1.8  jdolecek 		sc->pvoice = NULL;
   2087   1.8  jdolecek 	}
   2088   1.1  jdolecek }
   2089   1.1  jdolecek 
   2090   1.1  jdolecek static int
   2091  1.49  christos emuxki_query_encoding(void *addr, struct audio_encoding *fp)
   2092   1.1  jdolecek {
   2093   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2094  1.40      kent 	struct emuxki_softc *sc;
   2095   1.1  jdolecek 
   2096  1.40      kent 	sc = addr;
   2097  1.58   tsutsui 	printf("%s: emuxki_query_encoding called\n", device_xname(sc->sc_dev));
   2098   1.1  jdolecek #endif
   2099   1.1  jdolecek 
   2100   1.1  jdolecek 	switch (fp->index) {
   2101   1.1  jdolecek 	case 0:
   2102   1.1  jdolecek 		strcpy(fp->name, AudioEulinear);
   2103   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR;
   2104   1.1  jdolecek 		fp->precision = 8;
   2105   1.1  jdolecek 		fp->flags = 0;
   2106   1.1  jdolecek 		break;
   2107   1.1  jdolecek 	case 1:
   2108   1.1  jdolecek 		strcpy(fp->name, AudioEmulaw);
   2109   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULAW;
   2110   1.1  jdolecek 		fp->precision = 8;
   2111   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2112   1.1  jdolecek 		break;
   2113   1.1  jdolecek 	case 2:
   2114   1.1  jdolecek 		strcpy(fp->name, AudioEalaw);
   2115   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ALAW;
   2116   1.1  jdolecek 		fp->precision = 8;
   2117   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2118   1.1  jdolecek 		break;
   2119   1.1  jdolecek 	case 3:
   2120   1.1  jdolecek 		strcpy(fp->name, AudioEslinear);
   2121   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR;
   2122   1.1  jdolecek 		fp->precision = 8;
   2123   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2124   1.1  jdolecek 		break;
   2125   1.1  jdolecek 	case 4:
   2126   1.1  jdolecek 		strcpy(fp->name, AudioEslinear_le);
   2127   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
   2128   1.1  jdolecek 		fp->precision = 16;
   2129   1.1  jdolecek 		fp->flags = 0;
   2130   1.1  jdolecek 		break;
   2131   1.1  jdolecek 	case 5:
   2132   1.1  jdolecek 		strcpy(fp->name, AudioEulinear_le);
   2133   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
   2134   1.1  jdolecek 		fp->precision = 16;
   2135   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2136   1.1  jdolecek 		break;
   2137   1.1  jdolecek 	case 6:
   2138   1.1  jdolecek 		strcpy(fp->name, AudioEslinear_be);
   2139   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
   2140   1.1  jdolecek 		fp->precision = 16;
   2141   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2142   1.1  jdolecek 		break;
   2143   1.1  jdolecek 	case 7:
   2144   1.1  jdolecek 		strcpy(fp->name, AudioEulinear_be);
   2145   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
   2146   1.1  jdolecek 		fp->precision = 16;
   2147   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   2148   1.1  jdolecek 		break;
   2149   1.1  jdolecek 	default:
   2150  1.40      kent 		return EINVAL;
   2151   1.1  jdolecek 	}
   2152  1.40      kent 	return 0;
   2153   1.1  jdolecek }
   2154   1.1  jdolecek 
   2155   1.1  jdolecek static int
   2156  1.60  jmcneill emuxki_set_vparms(struct emuxki_softc *sc, struct emuxki_voice *voice,
   2157  1.60  jmcneill     const audio_params_t *p, stream_filter_list_t *fil)
   2158   1.1  jdolecek {
   2159  1.39      kent 	int mode, i;
   2160   1.1  jdolecek 
   2161   1.1  jdolecek 	mode = (voice->use & EMU_VOICE_USE_PLAY) ?
   2162   1.1  jdolecek 		AUMODE_PLAY : AUMODE_RECORD;
   2163  1.39      kent 	i = auconv_set_converter(emuxki_formats, EMUXKI_NFORMATS,
   2164  1.39      kent 				 mode, p, FALSE, fil);
   2165  1.39      kent 	if (i < 0)
   2166  1.39      kent 		return EINVAL;
   2167  1.39      kent 	if (fil->req_size > 0)
   2168  1.39      kent 		p = &fil->filters[0].param;
   2169  1.60  jmcneill 	return emuxki_voice_set_audioparms(sc, voice, p->channels == 2,
   2170  1.60  jmcneill 	    p->precision == 16, p->sample_rate);
   2171   1.1  jdolecek }
   2172   1.1  jdolecek 
   2173   1.1  jdolecek static int
   2174  1.40      kent emuxki_set_params(void *addr, int setmode, int usemode, audio_params_t *play,
   2175  1.40      kent     audio_params_t *rec, stream_filter_list_t *pfil, stream_filter_list_t *rfil)
   2176   1.1  jdolecek {
   2177  1.40      kent 	struct emuxki_softc *sc;
   2178   1.1  jdolecek 	struct audio_params *p;
   2179   1.8  jdolecek 	struct emuxki_voice *v;
   2180  1.39      kent 	stream_filter_list_t *fil;
   2181  1.40      kent 	int mode, error;
   2182   1.1  jdolecek 
   2183  1.40      kent 	sc = addr;
   2184   1.1  jdolecek 	for (mode = AUMODE_RECORD; mode != -1;
   2185   1.1  jdolecek 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
   2186   1.1  jdolecek 		if ((usemode & setmode & mode) == 0)
   2187   1.1  jdolecek 			continue;
   2188   1.1  jdolecek 
   2189   1.8  jdolecek 		if (mode == AUMODE_PLAY) {
   2190   1.8  jdolecek 			p = play;
   2191  1.39      kent 			fil = pfil;
   2192   1.8  jdolecek 			v = sc->pvoice;
   2193   1.8  jdolecek 		} else {
   2194   1.8  jdolecek 			p = rec;
   2195  1.39      kent 			fil = rfil;
   2196   1.8  jdolecek 			v = sc->rvoice;
   2197   1.8  jdolecek 		}
   2198   1.8  jdolecek 
   2199   1.8  jdolecek 		if (v == NULL) {
   2200   1.8  jdolecek 			continue;
   2201   1.8  jdolecek 		}
   2202   1.1  jdolecek 
   2203   1.1  jdolecek 		/* No multiple voice support for now */
   2204  1.60  jmcneill 		if ((error = emuxki_set_vparms(sc, v, p, fil)))
   2205  1.40      kent 			return error;
   2206   1.1  jdolecek 	}
   2207   1.1  jdolecek 
   2208  1.40      kent 	return 0;
   2209   1.1  jdolecek }
   2210   1.1  jdolecek 
   2211   1.1  jdolecek static int
   2212   1.1  jdolecek emuxki_halt_output(void *addr)
   2213   1.1  jdolecek {
   2214  1.40      kent 	struct emuxki_softc *sc;
   2215   1.1  jdolecek 
   2216  1.40      kent 	sc = addr;
   2217   1.1  jdolecek 	/* No multiple voice support for now */
   2218   1.1  jdolecek 	if (sc->pvoice == NULL)
   2219  1.40      kent 		return ENXIO;
   2220   1.1  jdolecek 
   2221   1.1  jdolecek 	emuxki_voice_halt(sc->pvoice);
   2222  1.40      kent 	return 0;
   2223   1.1  jdolecek }
   2224   1.1  jdolecek 
   2225   1.1  jdolecek static int
   2226   1.1  jdolecek emuxki_halt_input(void *addr)
   2227   1.1  jdolecek {
   2228  1.40      kent 	struct emuxki_softc *sc;
   2229   1.1  jdolecek 
   2230  1.40      kent 	sc = addr;
   2231   1.1  jdolecek #ifdef EMUXKI_DEBUG
   2232  1.58   tsutsui 	printf("%s: emuxki_halt_input called\n", device_xname(sc->sc_dev));
   2233   1.1  jdolecek #endif
   2234   1.1  jdolecek 
   2235   1.1  jdolecek 	/* No multiple voice support for now */
   2236   1.1  jdolecek 	if (sc->rvoice == NULL)
   2237  1.40      kent 		return ENXIO;
   2238   1.1  jdolecek 	emuxki_voice_halt(sc->rvoice);
   2239  1.40      kent 	return 0;
   2240   1.1  jdolecek }
   2241   1.1  jdolecek 
   2242   1.1  jdolecek static int
   2243   1.1  jdolecek emuxki_getdev(void *addr, struct audio_device *dev)
   2244   1.1  jdolecek {
   2245  1.40      kent 	struct emuxki_softc *sc;
   2246  1.40      kent 
   2247  1.40      kent 	sc = addr;
   2248  1.35  christos 	*dev = sc->sc_audv;
   2249  1.40      kent 	return 0;
   2250   1.1  jdolecek }
   2251   1.1  jdolecek 
   2252   1.1  jdolecek static int
   2253   1.1  jdolecek emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
   2254   1.1  jdolecek {
   2255  1.40      kent 	struct emuxki_softc *sc;
   2256   1.1  jdolecek 
   2257  1.40      kent 	sc = addr;
   2258   1.1  jdolecek 	return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
   2259   1.1  jdolecek }
   2260   1.1  jdolecek 
   2261   1.1  jdolecek static int
   2262   1.1  jdolecek emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
   2263   1.1  jdolecek {
   2264  1.40      kent 	struct emuxki_softc *sc;
   2265   1.1  jdolecek 
   2266  1.40      kent 	sc = addr;
   2267   1.1  jdolecek 	return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
   2268   1.1  jdolecek }
   2269   1.1  jdolecek 
   2270   1.1  jdolecek static int
   2271   1.1  jdolecek emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
   2272   1.1  jdolecek {
   2273  1.40      kent 	struct emuxki_softc *sc;
   2274   1.1  jdolecek 
   2275  1.40      kent 	sc = addr;
   2276   1.1  jdolecek 	return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
   2277   1.1  jdolecek }
   2278   1.1  jdolecek 
   2279   1.1  jdolecek static void *
   2280  1.60  jmcneill emuxki_allocm(void *addr, int direction, size_t size)
   2281   1.1  jdolecek {
   2282   1.1  jdolecek 	if (direction == AUMODE_PLAY)
   2283  1.60  jmcneill 		return emuxki_pmem_alloc(addr, size);
   2284   1.1  jdolecek 	else
   2285  1.60  jmcneill 		return emuxki_rmem_alloc(addr, size);
   2286   1.1  jdolecek }
   2287   1.1  jdolecek 
   2288   1.1  jdolecek static void
   2289  1.60  jmcneill emuxki_freem(void *addr, void *ptr, size_t size)
   2290   1.1  jdolecek {
   2291  1.40      kent 	struct emuxki_softc *sc;
   2292   1.1  jdolecek 	struct emuxki_mem *mem;
   2293  1.40      kent 	uint32_t *ptb, silentpage;
   2294  1.40      kent 	size_t numblocks;
   2295  1.60  jmcneill 	int i;
   2296   1.1  jdolecek 
   2297  1.40      kent 	sc = addr;
   2298   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
   2299   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
   2300   1.1  jdolecek 	LIST_FOREACH(mem, &sc->mem, next) {
   2301   1.1  jdolecek 		if (KERNADDR(mem->dmamem) != ptr)
   2302   1.1  jdolecek 			continue;
   2303   1.1  jdolecek 
   2304  1.60  jmcneill 		mutex_spin_enter(&sc->sc_intr_lock);
   2305   1.1  jdolecek 		if (mem->ptbidx != EMU_RMEM) {
   2306   1.1  jdolecek 			numblocks = DMASIZE(mem->dmamem) / EMU_PTESIZE;
   2307   1.1  jdolecek 			if (DMASIZE(mem->dmamem) % EMU_PTESIZE)
   2308   1.1  jdolecek 				numblocks++;
   2309   1.1  jdolecek 			for (i = 0; i < numblocks; i++)
   2310   1.1  jdolecek 				ptb[mem->ptbidx + i] =
   2311  1.34   tsutsui 				    htole32(silentpage | (mem->ptbidx + i));
   2312   1.1  jdolecek 		}
   2313   1.1  jdolecek 		LIST_REMOVE(mem, next);
   2314  1.60  jmcneill 		mutex_spin_exit(&sc->sc_intr_lock);
   2315   1.1  jdolecek 
   2316  1.60  jmcneill 		emuxki_mem_delete(mem, size);
   2317   1.1  jdolecek 		break;
   2318   1.1  jdolecek 	}
   2319   1.1  jdolecek }
   2320   1.1  jdolecek 
   2321  1.19    toshii /* blocksize should be a divisor of allowable buffersize */
   2322  1.19    toshii /* XXX probably this could be done better */
   2323  1.19    toshii static int
   2324  1.49  christos emuxki_round_blocksize(void *addr, int blksize,
   2325  1.49  christos     int mode, const audio_params_t* param)
   2326  1.19    toshii {
   2327  1.19    toshii #if 0
   2328  1.40      kent 	struct emuxki_softc *sc;
   2329  1.19    toshii 	struct audio_softc *au;
   2330  1.19    toshii #endif
   2331  1.19    toshii 	int bufsize;
   2332  1.19    toshii #if 0
   2333  1.40      kent 	sc = addr;
   2334  1.19    toshii 	if (sc == NULL)
   2335  1.19    toshii 		return blksize;
   2336  1.19    toshii 
   2337  1.57    cegger 	au = device_private(sc->sc_audev);
   2338  1.19    toshii 	if (au == NULL)
   2339  1.19    toshii 		return blksize;
   2340  1.19    toshii 
   2341  1.19    toshii 	bufsize = emuxki_round_buffersize(sc, AUMODE_RECORD,
   2342  1.19    toshii 	    au->sc_rr.bufsize);
   2343  1.19    toshii #else
   2344  1.19    toshii 	bufsize = 65536;
   2345  1.19    toshii #endif
   2346  1.19    toshii 
   2347  1.19    toshii 	while (bufsize > blksize)
   2348  1.19    toshii 		bufsize /= 2;
   2349  1.19    toshii 
   2350  1.19    toshii 	return bufsize;
   2351  1.19    toshii }
   2352  1.40      kent 
   2353   1.1  jdolecek static size_t
   2354  1.49  christos emuxki_round_buffersize(void *addr, int direction, size_t bsize)
   2355   1.1  jdolecek {
   2356   1.1  jdolecek 
   2357   1.1  jdolecek 	if (direction == AUMODE_PLAY) {
   2358   1.1  jdolecek 		if (bsize < EMU_PTESIZE)
   2359   1.1  jdolecek 			bsize = EMU_PTESIZE;
   2360   1.1  jdolecek 		else if (bsize > (EMU_PTESIZE * EMU_MAXPTE))
   2361   1.1  jdolecek 			bsize = EMU_PTESIZE * EMU_MAXPTE;
   2362   1.1  jdolecek 		/* Would be better if set to max available */
   2363   1.1  jdolecek 		else if (bsize % EMU_PTESIZE)
   2364   1.1  jdolecek 			bsize = bsize -
   2365   1.1  jdolecek 				(bsize % EMU_PTESIZE) +
   2366   1.1  jdolecek 				EMU_PTESIZE;
   2367   1.1  jdolecek 	} else {
   2368   1.1  jdolecek 		int idx;
   2369   1.1  jdolecek 
   2370   1.1  jdolecek 		/* find nearest lower recbuf size */
   2371  1.19    toshii 		for(idx = sizeof(emuxki_recbuf_sz) /
   2372  1.19    toshii 		    sizeof(emuxki_recbuf_sz[0]); --idx >= 0; ) {
   2373  1.19    toshii 			if (bsize >= emuxki_recbuf_sz[idx]) {
   2374  1.19    toshii 				bsize = emuxki_recbuf_sz[idx];
   2375   1.1  jdolecek 				break;
   2376   1.1  jdolecek 			}
   2377   1.1  jdolecek 		}
   2378   1.1  jdolecek 
   2379   1.1  jdolecek 		if (bsize == 0)
   2380   1.1  jdolecek 			bsize = 384;
   2381   1.1  jdolecek 	}
   2382   1.1  jdolecek 
   2383  1.40      kent 	return bsize;
   2384   1.1  jdolecek }
   2385   1.1  jdolecek 
   2386   1.1  jdolecek static paddr_t
   2387   1.1  jdolecek emuxki_mappage(void *addr, void *ptr, off_t off, int prot)
   2388   1.1  jdolecek {
   2389  1.40      kent 	struct emuxki_softc *sc;
   2390   1.1  jdolecek 	struct emuxki_mem *mem;
   2391   1.1  jdolecek 
   2392  1.40      kent 	sc = addr;
   2393  1.60  jmcneill 
   2394  1.60  jmcneill 	mutex_exit(&sc->sc_lock);
   2395   1.1  jdolecek 	LIST_FOREACH(mem, &sc->mem, next) {
   2396   1.1  jdolecek 		if (KERNADDR(mem->dmamem) == ptr) {
   2397   1.1  jdolecek 			struct dmamem *dm = mem->dmamem;
   2398   1.1  jdolecek 
   2399   1.1  jdolecek 			return bus_dmamem_mmap(dm->dmat, dm->segs, dm->nsegs,
   2400   1.1  jdolecek 			       off, prot, BUS_DMA_WAITOK);
   2401   1.1  jdolecek 		}
   2402   1.1  jdolecek 	}
   2403  1.60  jmcneill 	mutex_enter(&sc->sc_lock);
   2404   1.1  jdolecek 
   2405  1.40      kent 	return -1;
   2406   1.1  jdolecek }
   2407   1.1  jdolecek 
   2408   1.1  jdolecek static int
   2409  1.49  christos emuxki_get_props(void *addr)
   2410   1.1  jdolecek {
   2411  1.40      kent 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
   2412  1.40      kent 	    AUDIO_PROP_FULLDUPLEX;
   2413   1.1  jdolecek }
   2414   1.1  jdolecek 
   2415   1.1  jdolecek static int
   2416   1.1  jdolecek emuxki_trigger_output(void *addr, void *start, void *end, int blksize,
   2417  1.40      kent     void (*inth) (void *), void *inthparam, const audio_params_t *params)
   2418   1.1  jdolecek {
   2419  1.40      kent 	struct emuxki_softc *sc;
   2420   1.1  jdolecek 	/* No multiple voice support for now */
   2421  1.40      kent 	struct emuxki_voice *voice;
   2422  1.40      kent 	int error;
   2423   1.1  jdolecek 
   2424  1.40      kent 	sc = addr;
   2425  1.40      kent 	voice = sc->pvoice;
   2426   1.1  jdolecek 	if (voice == NULL)
   2427  1.40      kent 		return ENXIO;
   2428  1.60  jmcneill 	if ((error = emuxki_voice_set_audioparms(sc, voice, params->channels == 2,
   2429  1.40      kent 	    params->precision == 16, params->sample_rate)))
   2430  1.40      kent 		return error;
   2431   1.1  jdolecek 	if ((error = emuxki_voice_set_bufparms(voice, start,
   2432  1.50  christos 	    (char *)end - (char *)start, blksize)))
   2433  1.40      kent 		return error;
   2434   1.1  jdolecek 	emuxki_voice_commit_parms(voice);
   2435   1.1  jdolecek 	emuxki_voice_start(voice, inth, inthparam);
   2436   1.1  jdolecek 
   2437  1.40      kent 	return 0;
   2438   1.1  jdolecek }
   2439   1.1  jdolecek 
   2440   1.1  jdolecek static int
   2441   1.1  jdolecek emuxki_trigger_input(void *addr, void *start, void *end, int blksize,
   2442  1.40      kent     void (*inth) (void *), void *inthparam, const audio_params_t *params)
   2443   1.1  jdolecek {
   2444  1.40      kent 	struct emuxki_softc *sc;
   2445   1.1  jdolecek 	/* No multiple voice support for now */
   2446  1.40      kent 	struct emuxki_voice *voice;
   2447  1.35  christos 	int	error;
   2448   1.1  jdolecek 
   2449  1.40      kent 	sc = addr;
   2450  1.40      kent 	voice = sc->rvoice;
   2451   1.1  jdolecek 	if (voice == NULL)
   2452  1.40      kent 		return ENXIO;
   2453  1.60  jmcneill 	if ((error = emuxki_voice_set_audioparms(sc, voice,
   2454  1.60  jmcneill 	    params->channels == 2, params->precision == 16,
   2455  1.60  jmcneill 	    params->sample_rate)))
   2456  1.40      kent 		return error;
   2457   1.1  jdolecek 	if ((error = emuxki_voice_set_bufparms(voice, start,
   2458  1.50  christos 	    (char *)end - (char *)start, blksize)))
   2459  1.40      kent 		return error;
   2460   1.1  jdolecek 	emuxki_voice_start(voice, inth, inthparam);
   2461   1.1  jdolecek 
   2462  1.40      kent 	return 0;
   2463   1.1  jdolecek }
   2464   1.1  jdolecek 
   2465   1.1  jdolecek /*
   2466   1.1  jdolecek  * AC97 callbacks
   2467   1.1  jdolecek  */
   2468   1.1  jdolecek 
   2469   1.1  jdolecek static int
   2470   1.1  jdolecek emuxki_ac97_attach(void *arg, struct ac97_codec_if *codecif)
   2471   1.1  jdolecek {
   2472  1.40      kent 	struct emuxki_softc *sc;
   2473   1.1  jdolecek 
   2474  1.40      kent 	sc = arg;
   2475   1.1  jdolecek 	sc->codecif = codecif;
   2476  1.40      kent 	return 0;
   2477   1.1  jdolecek }
   2478   1.1  jdolecek 
   2479   1.1  jdolecek static int
   2480  1.40      kent emuxki_ac97_read(void *arg, uint8_t reg, uint16_t *val)
   2481   1.1  jdolecek {
   2482  1.40      kent 	struct emuxki_softc *sc;
   2483   1.1  jdolecek 
   2484  1.40      kent 	sc = arg;
   2485  1.60  jmcneill 	mutex_spin_enter(&sc->sc_ac97_index_lock);
   2486   1.1  jdolecek 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
   2487   1.1  jdolecek 	*val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA);
   2488  1.60  jmcneill 	mutex_spin_exit(&sc->sc_ac97_index_lock);
   2489   1.1  jdolecek 
   2490  1.40      kent 	return 0;
   2491   1.1  jdolecek }
   2492   1.1  jdolecek 
   2493   1.1  jdolecek static int
   2494  1.40      kent emuxki_ac97_write(void *arg, uint8_t reg, uint16_t val)
   2495   1.1  jdolecek {
   2496  1.40      kent 	struct emuxki_softc *sc;
   2497   1.1  jdolecek 
   2498  1.40      kent 	sc = arg;
   2499  1.60  jmcneill 	mutex_spin_enter(&sc->sc_ac97_index_lock);
   2500   1.1  jdolecek 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
   2501   1.1  jdolecek 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA, val);
   2502  1.60  jmcneill 	mutex_spin_exit(&sc->sc_ac97_index_lock);
   2503   1.1  jdolecek 
   2504  1.40      kent 	return 0;
   2505   1.1  jdolecek }
   2506   1.1  jdolecek 
   2507  1.36      kent static int
   2508  1.49  christos emuxki_ac97_reset(void *arg)
   2509   1.1  jdolecek {
   2510  1.40      kent 
   2511  1.36      kent 	return 0;
   2512   1.6  jdolecek }
   2513   1.6  jdolecek 
   2514   1.6  jdolecek enum ac97_host_flags
   2515  1.49  christos emuxki_ac97_flags(void *arg)
   2516   1.6  jdolecek {
   2517  1.40      kent 
   2518  1.40      kent 	return AC97_HOST_SWAPPED_CHANNELS;
   2519   1.1  jdolecek }
   2520  1.60  jmcneill 
   2521  1.60  jmcneill static void
   2522  1.60  jmcneill emuxki_get_locks(void *arg, kmutex_t **intr, kmutex_t **proc)
   2523  1.60  jmcneill {
   2524  1.60  jmcneill 	struct emuxki_softc *sc;
   2525  1.60  jmcneill 
   2526  1.60  jmcneill 	sc = arg;
   2527  1.60  jmcneill 	*intr = &sc->sc_intr_lock;
   2528  1.60  jmcneill 	*proc = &sc->sc_lock;
   2529  1.60  jmcneill }
   2530