Home | History | Annotate | Line # | Download | only in pci
emuxki.c revision 1.15
      1  1.15   thorpej /*	$NetBSD: emuxki.c,v 1.15 2003/01/31 00:07:41 thorpej Exp $	*/
      2   1.1  jdolecek 
      3   1.1  jdolecek /*-
      4   1.1  jdolecek  * Copyright (c) 2001 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.1  jdolecek  * by Yannick Montulet.
      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  * 3. All advertising materials mentioning features or use of this software
     19   1.1  jdolecek  *    must display the following acknowledgement:
     20   1.1  jdolecek  *	This product includes software developed by the NetBSD
     21   1.1  jdolecek  *	Foundation, Inc. and its contributors.
     22   1.1  jdolecek  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1  jdolecek  *    contributors may be used to endorse or promote products derived
     24   1.1  jdolecek  *    from this software without specific prior written permission.
     25   1.1  jdolecek  *
     26   1.1  jdolecek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1  jdolecek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1  jdolecek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1  jdolecek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1  jdolecek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1  jdolecek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1  jdolecek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1  jdolecek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1  jdolecek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1  jdolecek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1  jdolecek  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1  jdolecek  */
     38   1.1  jdolecek 
     39   1.1  jdolecek /*
     40   1.1  jdolecek  * Driver for Creative Labs SBLive! series and probably PCI512.
     41   1.1  jdolecek  *
     42   1.1  jdolecek  * Known bugs:
     43   1.1  jdolecek  * - inversed stereo at ac97 codec level
     44   1.1  jdolecek  *   (XXX jdolecek - don't see the problem? maybe because auvia(4) has
     45   1.1  jdolecek  *    it swapped too?)
     46   1.1  jdolecek  * - bass disapear when you plug rear jack-in on Cambridge FPS2000 speakers
     47   1.1  jdolecek  *   (and presumably all speakers that support front and rear jack-in)
     48   1.1  jdolecek  *
     49   1.1  jdolecek  * TODO:
     50   1.1  jdolecek  * - Digital Outputs
     51   1.1  jdolecek  * - (midi/mpu),joystick support
     52   1.1  jdolecek  * - Single source recording
     53   1.1  jdolecek  * - Multiple voices play (problem with /dev/audio architecture)
     54   1.1  jdolecek  * - Multiple sources recording (Pb with audio(4))
     55   1.1  jdolecek  * - Independant modification of each channel's parameters (via mixer ?)
     56   1.1  jdolecek  * - DSP FX patches (to make fx like chipmunk)
     57   1.1  jdolecek  */
     58   1.4     lukem 
     59   1.4     lukem #include <sys/cdefs.h>
     60  1.15   thorpej __KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.15 2003/01/31 00:07:41 thorpej Exp $");
     61   1.1  jdolecek 
     62   1.5     lukem #include <sys/param.h>
     63   1.1  jdolecek #include <sys/device.h>
     64   1.1  jdolecek #include <sys/errno.h>
     65   1.1  jdolecek #include <sys/malloc.h>
     66   1.1  jdolecek #include <sys/systm.h>
     67   1.1  jdolecek #include <sys/audioio.h>
     68   1.1  jdolecek #include <sys/select.h>
     69   1.1  jdolecek #include <dev/pci/pcireg.h>
     70   1.1  jdolecek #include <dev/pci/pcivar.h>
     71   1.1  jdolecek #include <dev/pci/pcidevs.h>
     72   1.1  jdolecek #include <dev/audio_if.h>
     73   1.1  jdolecek #include <dev/audiovar.h>
     74   1.1  jdolecek #include <dev/auconv.h>
     75   1.1  jdolecek #include <dev/mulaw.h>
     76   1.1  jdolecek #include <dev/ic/ac97reg.h>
     77   1.1  jdolecek #include <dev/ic/ac97var.h>
     78   1.1  jdolecek 
     79   1.1  jdolecek #include <dev/pci/emuxkireg.h>
     80   1.1  jdolecek #include <dev/pci/emuxkivar.h>
     81   1.1  jdolecek 
     82   1.1  jdolecek /* autconf goo */
     83   1.3  jdolecek static int  emuxki_match(struct device *, struct cfdata *, void *);
     84   1.3  jdolecek static void emuxki_attach(struct device *, struct device *, void *);
     85   1.3  jdolecek static int  emuxki_detach(struct device *, int);
     86   1.1  jdolecek 
     87   1.1  jdolecek /* dma mem mgmt */
     88   1.3  jdolecek static struct dmamem *dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
     89   1.3  jdolecek 				 int, int, int);
     90   1.3  jdolecek static void           dmamem_free(struct dmamem *, int);
     91   1.1  jdolecek 
     92   1.1  jdolecek /* Emu10k1 init & shutdown */
     93   1.3  jdolecek static int  emuxki_init(struct emuxki_softc *);
     94   1.3  jdolecek static void emuxki_shutdown(struct emuxki_softc *);
     95   1.1  jdolecek 
     96   1.1  jdolecek /* Emu10k1 mem mgmt */
     97   1.3  jdolecek static void   *emuxki_pmem_alloc(struct emuxki_softc *, size_t,int,int);
     98   1.3  jdolecek static void   *emuxki_rmem_alloc(struct emuxki_softc *, size_t,int,int);
     99   1.1  jdolecek 
    100   1.1  jdolecek /*
    101   1.1  jdolecek  * Emu10k1 channels funcs : There is no direct access to channels, everything
    102   1.1  jdolecek  * is done through voices I will at least provide channel based fx params
    103   1.1  jdolecek  * modification, later...
    104   1.1  jdolecek  */
    105   1.1  jdolecek 
    106   1.1  jdolecek /* Emu10k1 voice mgmt */
    107   1.3  jdolecek static struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *,
    108   1.6  jdolecek 					     u_int8_t);
    109   1.3  jdolecek static void   emuxki_voice_delete(struct emuxki_voice *);
    110   1.3  jdolecek static int    emuxki_voice_set_audioparms(struct emuxki_voice *, u_int8_t,
    111   1.6  jdolecek 					  u_int8_t, u_int32_t);
    112   1.1  jdolecek /* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
    113   1.3  jdolecek static int emuxki_voice_set_bufparms(struct emuxki_voice *,
    114   1.6  jdolecek 				     void *, u_int32_t, u_int16_t);
    115   1.3  jdolecek static void emuxki_voice_commit_parms(struct emuxki_voice *);
    116   1.3  jdolecek static u_int32_t emuxki_voice_curaddr(struct emuxki_voice *);
    117   1.3  jdolecek static void emuxki_voice_start(struct emuxki_voice *,
    118   1.6  jdolecek 			       void (*) (void *), void *);
    119   1.3  jdolecek static void emuxki_voice_halt(struct emuxki_voice *);
    120   1.1  jdolecek 
    121   1.1  jdolecek /*
    122   1.1  jdolecek  * Emu10k1 stream mgmt : not done yet
    123   1.1  jdolecek  */
    124   1.1  jdolecek #if 0
    125   1.3  jdolecek static struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
    126   1.3  jdolecek static void   emuxki_stream_delete(struct emuxki_stream *);
    127   1.3  jdolecek static int    emuxki_stream_set_audio_params(struct emuxki_stream *, u_int8_t,
    128   1.6  jdolecek 					     u_int8_t, u_int8_t, u_int16_t);
    129   1.3  jdolecek static void   emuxki_stream_start(struct emuxki_stream *);
    130   1.3  jdolecek static void   emuxki_stream_halt(struct emuxki_stream *);
    131   1.1  jdolecek #endif
    132   1.1  jdolecek 
    133   1.1  jdolecek /* audio interface callbacks */
    134   1.1  jdolecek 
    135   1.3  jdolecek static int	emuxki_open(void *, int);
    136   1.3  jdolecek static void	emuxki_close(void *);
    137   1.1  jdolecek 
    138   1.3  jdolecek static int	emuxki_query_encoding(void *, struct audio_encoding *);
    139   1.3  jdolecek static int	emuxki_set_params(void *, int, int,
    140   1.6  jdolecek 				  struct audio_params *,
    141   1.6  jdolecek 				  struct audio_params *);
    142   1.1  jdolecek 
    143   1.3  jdolecek static size_t	emuxki_round_buffersize(void *, int, size_t);
    144   1.1  jdolecek 
    145   1.3  jdolecek static int	emuxki_trigger_output(void *, void *, void *, int,
    146   1.1  jdolecek 				      void (*)(void *), void *,
    147   1.3  jdolecek 				      struct audio_params *);
    148   1.3  jdolecek static int	emuxki_trigger_input(void *, void *, void *, int,
    149   1.6  jdolecek 				     void (*) (void *), void *,
    150   1.6  jdolecek 				     struct audio_params *);
    151   1.3  jdolecek static int	emuxki_halt_output(void *);
    152   1.3  jdolecek static int	emuxki_halt_input(void *);
    153   1.3  jdolecek 
    154   1.3  jdolecek static int	emuxki_getdev(void *, struct audio_device *);
    155   1.3  jdolecek static int	emuxki_set_port(void *, mixer_ctrl_t *);
    156   1.3  jdolecek static int	emuxki_get_port(void *, mixer_ctrl_t *);
    157   1.3  jdolecek static int	emuxki_query_devinfo(void *, mixer_devinfo_t *);
    158   1.1  jdolecek 
    159   1.6  jdolecek static void    *emuxki_allocm(void *, int, size_t, int, int);
    160   1.3  jdolecek static void	emuxki_freem(void *, void *, int);
    161   1.1  jdolecek 
    162   1.3  jdolecek static paddr_t	emuxki_mappage(void *, void *, off_t, int);
    163   1.3  jdolecek static int	emuxki_get_props(void *);
    164   1.1  jdolecek 
    165   1.1  jdolecek /* Interrupt handler */
    166   1.3  jdolecek static int  emuxki_intr(void *);
    167   1.1  jdolecek 
    168   1.1  jdolecek /* Emu10k1 AC97 interface callbacks */
    169   1.3  jdolecek static int  emuxki_ac97_attach(void *, struct ac97_codec_if *);
    170   1.3  jdolecek static int  emuxki_ac97_read(void *, u_int8_t, u_int16_t *);
    171   1.3  jdolecek static int  emuxki_ac97_write(void *, u_int8_t, u_int16_t);
    172   1.3  jdolecek static void emuxki_ac97_reset(void *);
    173   1.6  jdolecek static enum ac97_host_flags emuxki_ac97_flags(void *);
    174   1.1  jdolecek 
    175   1.1  jdolecek /*
    176   1.1  jdolecek  * Autoconfig goo.
    177   1.1  jdolecek  */
    178  1.11   thorpej CFATTACH_DECL(emuxki, sizeof(struct emuxki_softc),
    179  1.12   thorpej     emuxki_match, emuxki_attach, emuxki_detach, NULL);
    180   1.1  jdolecek 
    181   1.1  jdolecek static struct audio_hw_if emuxki_hw_if = {
    182   1.1  jdolecek 	emuxki_open,
    183   1.1  jdolecek 	emuxki_close,
    184   1.1  jdolecek 	NULL,			/* drain */
    185   1.1  jdolecek 	emuxki_query_encoding,
    186   1.1  jdolecek 	emuxki_set_params,
    187   1.1  jdolecek 	NULL,			/* round blocksize */
    188   1.1  jdolecek 	NULL,			/* commit settings */
    189   1.1  jdolecek 	NULL,			/* init_output */
    190   1.1  jdolecek 	NULL,			/* init_input */
    191   1.1  jdolecek 	NULL,			/* start_output */
    192   1.1  jdolecek 	NULL,			/* start_input */
    193   1.1  jdolecek 	emuxki_halt_output,
    194   1.1  jdolecek 	emuxki_halt_input,
    195   1.1  jdolecek 	NULL,			/* speaker_ctl */
    196   1.1  jdolecek 	emuxki_getdev,
    197   1.1  jdolecek 	NULL,			/* setfd */
    198   1.1  jdolecek 	emuxki_set_port,
    199   1.1  jdolecek 	emuxki_get_port,
    200   1.1  jdolecek 	emuxki_query_devinfo,
    201   1.1  jdolecek 	emuxki_allocm,
    202   1.1  jdolecek 	emuxki_freem,
    203   1.1  jdolecek 	emuxki_round_buffersize,
    204   1.1  jdolecek 	emuxki_mappage,
    205   1.1  jdolecek 	emuxki_get_props,
    206   1.1  jdolecek 	emuxki_trigger_output,
    207   1.1  jdolecek 	emuxki_trigger_input,
    208   1.1  jdolecek 	NULL,			/* dev_ioctl */
    209   1.1  jdolecek };
    210   1.1  jdolecek 
    211   1.1  jdolecek /*
    212   1.1  jdolecek  * Dma memory mgmt
    213   1.1  jdolecek  */
    214   1.1  jdolecek 
    215   1.1  jdolecek static void
    216   1.1  jdolecek dmamem_delete(struct dmamem *mem, int type)
    217   1.1  jdolecek {
    218   1.1  jdolecek 	free(mem->segs, type);
    219   1.1  jdolecek 	free(mem, type);
    220   1.1  jdolecek }
    221   1.1  jdolecek 
    222   1.1  jdolecek static struct dmamem *
    223   1.1  jdolecek dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align,
    224   1.1  jdolecek 	     int nsegs, int type, int flags)
    225   1.1  jdolecek {
    226   1.1  jdolecek 	struct dmamem	*mem;
    227   1.1  jdolecek 	int		bus_dma_flags;
    228   1.1  jdolecek 
    229   1.1  jdolecek 	/* Allocate memory for structure */
    230   1.1  jdolecek 	if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
    231   1.1  jdolecek 		return (NULL);
    232   1.1  jdolecek 	mem->dmat = dmat;
    233   1.1  jdolecek 	mem->size = size;
    234   1.1  jdolecek 	mem->align = align;
    235   1.1  jdolecek 	mem->nsegs = nsegs;
    236   1.1  jdolecek 	mem->bound = 0;
    237   1.1  jdolecek 
    238   1.1  jdolecek 	mem->segs = malloc(mem->nsegs * sizeof(*(mem->segs)), type, flags);
    239   1.1  jdolecek 	if (mem->segs == NULL) {
    240   1.1  jdolecek 		free(mem, type);
    241   1.1  jdolecek 		return (NULL);
    242   1.1  jdolecek 	}
    243   1.1  jdolecek 
    244   1.1  jdolecek 	bus_dma_flags = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
    245   1.1  jdolecek 	if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
    246   1.1  jdolecek 			     mem->segs, mem->nsegs, &(mem->rsegs),
    247   1.1  jdolecek 			     bus_dma_flags)) {
    248   1.1  jdolecek 		dmamem_delete(mem, type);
    249   1.1  jdolecek 		return (NULL);
    250   1.1  jdolecek 	}
    251   1.1  jdolecek 
    252   1.1  jdolecek 	if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
    253   1.1  jdolecek 			   &(mem->kaddr), bus_dma_flags | BUS_DMA_COHERENT)) {
    254   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    255   1.1  jdolecek 		dmamem_delete(mem, type);
    256   1.1  jdolecek 		return (NULL);
    257   1.1  jdolecek 	}
    258   1.1  jdolecek 
    259   1.1  jdolecek 	if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
    260   1.1  jdolecek 			      mem->bound, bus_dma_flags, &(mem->map))) {
    261   1.1  jdolecek 		bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
    262   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    263   1.1  jdolecek 		dmamem_delete(mem, type);
    264   1.1  jdolecek 		return (NULL);
    265   1.1  jdolecek 	}
    266   1.1  jdolecek 
    267   1.1  jdolecek 	if (bus_dmamap_load(dmat, mem->map, mem->kaddr,
    268   1.1  jdolecek 			    mem->size, NULL, bus_dma_flags)) {
    269   1.1  jdolecek 		bus_dmamap_destroy(dmat, mem->map);
    270   1.1  jdolecek 		bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
    271   1.1  jdolecek 		bus_dmamem_free(dmat, mem->segs, mem->nsegs);
    272   1.1  jdolecek 		dmamem_delete(mem, type);
    273   1.1  jdolecek 		return (NULL);
    274   1.1  jdolecek 	}
    275   1.1  jdolecek 
    276   1.1  jdolecek 	return (mem);
    277   1.1  jdolecek }
    278   1.1  jdolecek 
    279   1.1  jdolecek static void
    280   1.1  jdolecek dmamem_free(struct dmamem *mem, int type)
    281   1.1  jdolecek {
    282   1.1  jdolecek 	bus_dmamap_unload(mem->dmat, mem->map);
    283   1.1  jdolecek 	bus_dmamap_destroy(mem->dmat, mem->map);
    284   1.1  jdolecek 	bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
    285   1.1  jdolecek 	bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
    286   1.1  jdolecek 	dmamem_delete(mem, type);
    287   1.1  jdolecek }
    288   1.1  jdolecek 
    289   1.1  jdolecek 
    290   1.1  jdolecek /*
    291   1.1  jdolecek  * Autoconf device callbacks : attach and detach
    292   1.1  jdolecek  */
    293   1.1  jdolecek 
    294   1.1  jdolecek static void
    295   1.1  jdolecek emuxki_pci_shutdown(struct emuxki_softc *sc)
    296   1.1  jdolecek {
    297   1.1  jdolecek 	if (sc->sc_ih != NULL)
    298   1.1  jdolecek 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    299   1.1  jdolecek 	if (sc->sc_ios)
    300   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    301   1.1  jdolecek }
    302   1.1  jdolecek 
    303   1.1  jdolecek static int
    304   1.1  jdolecek emuxki_scinit(struct emuxki_softc *sc)
    305   1.1  jdolecek {
    306   1.1  jdolecek 	int             err;
    307   1.1  jdolecek 
    308   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    309   1.1  jdolecek 		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
    310   1.1  jdolecek 		EMU_HCFG_MUTEBUTTONENABLE);
    311   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
    312   1.1  jdolecek 		EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE);
    313   1.1  jdolecek 
    314   1.1  jdolecek 	if ((err = emuxki_init(sc)))
    315   1.1  jdolecek 		return (err);
    316   1.1  jdolecek 
    317   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    318   1.9  jdolecek 		EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE |
    319   1.1  jdolecek 		EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
    320   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
    321   1.1  jdolecek 		bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
    322   1.1  jdolecek 		EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
    323   1.1  jdolecek 		EMU_INTE_MUTEENABLE);
    324   1.1  jdolecek 
    325   1.1  jdolecek 	/* No multiple voice support for now */
    326   1.1  jdolecek 	sc->pvoice = sc->rvoice = NULL;
    327   1.1  jdolecek 
    328   1.1  jdolecek 	return (0);
    329   1.1  jdolecek }
    330   1.1  jdolecek 
    331   1.1  jdolecek static int
    332   1.1  jdolecek emuxki_ac97_init(struct emuxki_softc *sc)
    333   1.1  jdolecek {
    334   1.1  jdolecek 	sc->hostif.arg = sc;
    335   1.1  jdolecek 	sc->hostif.attach = emuxki_ac97_attach;
    336   1.1  jdolecek 	sc->hostif.read = emuxki_ac97_read;
    337   1.1  jdolecek 	sc->hostif.write = emuxki_ac97_write;
    338   1.1  jdolecek 	sc->hostif.reset = emuxki_ac97_reset;
    339   1.6  jdolecek 	sc->hostif.flags = emuxki_ac97_flags;
    340   1.1  jdolecek 	return (ac97_attach(&(sc->hostif)));
    341   1.1  jdolecek }
    342   1.1  jdolecek 
    343   1.1  jdolecek static int
    344   1.1  jdolecek emuxki_match(struct device *parent, struct cfdata *match, void *aux)
    345   1.1  jdolecek {
    346   1.1  jdolecek 	struct pci_attach_args *pa = aux;
    347   1.1  jdolecek 
    348   1.1  jdolecek 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CREATIVELABS &&
    349   1.1  jdolecek 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE)
    350   1.1  jdolecek 		return (1);
    351   1.1  jdolecek 
    352   1.1  jdolecek 	return (0);
    353   1.1  jdolecek }
    354   1.1  jdolecek 
    355   1.1  jdolecek static void
    356   1.1  jdolecek emuxki_attach(struct device *parent, struct device *self, void *aux)
    357   1.1  jdolecek {
    358   1.1  jdolecek 	struct emuxki_softc *sc = (struct emuxki_softc *) self;
    359   1.1  jdolecek 	struct pci_attach_args *pa = aux;
    360   1.1  jdolecek 	char            devinfo[256];
    361   1.1  jdolecek 	pci_intr_handle_t ih;
    362   1.1  jdolecek 	const char     *intrstr;
    363   1.1  jdolecek 
    364  1.15   thorpej 	aprint_naive(": Audio controller\n");
    365  1.15   thorpej 
    366   1.1  jdolecek 	if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
    367   1.1  jdolecek 	    &(sc->sc_iot), &(sc->sc_ioh), &(sc->sc_iob),
    368   1.1  jdolecek 			   &(sc->sc_ios))) {
    369  1.15   thorpej 		aprint_error(": can't map iospace\n");
    370   1.1  jdolecek 		return;
    371   1.1  jdolecek 	}
    372   1.1  jdolecek 	pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo);
    373  1.15   thorpej 	aprint_normal(": %s\n", devinfo);
    374   1.1  jdolecek 
    375   1.1  jdolecek 	sc->sc_pc   = pa->pa_pc;
    376   1.1  jdolecek 	sc->sc_dmat = pa->pa_dmat;
    377   1.1  jdolecek 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
    378   1.1  jdolecek 		pci_conf_read(pa->pa_pc, pa->pa_tag,
    379   1.1  jdolecek 		(PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE));
    380   1.1  jdolecek 
    381   1.1  jdolecek 	if (pci_intr_map(pa, &ih)) {
    382  1.15   thorpej 		aprint_error("%s: couldn't map interrupt\n",
    383   1.2  jdolecek 			sc->sc_dev.dv_xname);
    384   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    385   1.1  jdolecek 		return;
    386   1.1  jdolecek 	}
    387   1.1  jdolecek 
    388   1.1  jdolecek 	intrstr = pci_intr_string(pa->pa_pc, ih);
    389   1.1  jdolecek 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, emuxki_intr,
    390   1.1  jdolecek 		sc);
    391   1.1  jdolecek 	if (sc->sc_ih == NULL) {
    392  1.15   thorpej 		aprint_error("%s: couldn't establish interrupt",
    393  1.15   thorpej 		    sc->sc_dev.dv_xname);
    394   1.1  jdolecek 		if (intrstr != NULL)
    395  1.15   thorpej 			aprint_normal(" at %s", intrstr);
    396  1.15   thorpej 		aprint_normal("\n");
    397   1.1  jdolecek 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    398   1.1  jdolecek 		return;
    399   1.1  jdolecek 	}
    400  1.15   thorpej 	aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
    401   1.1  jdolecek 
    402   1.1  jdolecek 	if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
    403   1.1  jdolecek 	    (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL)
    404   1.1  jdolecek 		emuxki_pci_shutdown(sc);
    405   1.1  jdolecek }
    406   1.1  jdolecek 
    407   1.1  jdolecek static int
    408   1.1  jdolecek emuxki_detach(struct device *self, int flags)
    409   1.1  jdolecek {
    410   1.1  jdolecek 	struct emuxki_softc *sc = (struct emuxki_softc *) self;
    411   1.1  jdolecek 	int             err = 0;
    412   1.1  jdolecek 
    413   1.1  jdolecek         if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
    414   1.1  jdolecek 	        err = config_detach(sc->sc_audev, 0);
    415   1.1  jdolecek 
    416   1.1  jdolecek 	/* All voices should be stopped now but add some code here if not */
    417   1.1  jdolecek 
    418   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
    419   1.1  jdolecek 		EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
    420   1.1  jdolecek 		EMU_HCFG_MUTEBUTTONENABLE);
    421   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, 0);
    422   1.1  jdolecek 
    423   1.1  jdolecek 	emuxki_shutdown(sc);
    424   1.1  jdolecek 
    425   1.1  jdolecek 	emuxki_pci_shutdown(sc);
    426   1.1  jdolecek 
    427   1.1  jdolecek 	return (0);
    428   1.1  jdolecek }
    429   1.1  jdolecek 
    430   1.1  jdolecek 
    431   1.1  jdolecek /* Misc stuff relative to emu10k1 */
    432   1.1  jdolecek 
    433   1.1  jdolecek static u_int32_t
    434   1.1  jdolecek emuxki_rate_to_pitch(u_int32_t rate)
    435   1.1  jdolecek {
    436   1.1  jdolecek 	static const u_int32_t logMagTable[128] = {
    437   1.1  jdolecek 		0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3,
    438   1.1  jdolecek 		0x13aa2, 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a,
    439   1.1  jdolecek 		0x2655d, 0x28ed5, 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb,
    440   1.1  jdolecek 		0x381b6, 0x3a93d, 0x3d081, 0x3f782, 0x41e42, 0x444c1, 0x46b01,
    441   1.1  jdolecek 		0x49101, 0x4b6c4, 0x4dc49, 0x50191, 0x5269e, 0x54b6f, 0x57006,
    442   1.1  jdolecek 		0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 0x646ee, 0x66a00,
    443   1.1  jdolecek 		0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 0x759d4,
    444   1.1  jdolecek 		0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
    445   1.1  jdolecek 		0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20,
    446   1.1  jdolecek 		0x93d26, 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec,
    447   1.1  jdolecek 		0xa11d8, 0xa2f9d, 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241,
    448   1.1  jdolecek 		0xadf26, 0xafbe7, 0xb1885, 0xb3500, 0xb5157, 0xb6d8c, 0xb899f,
    449   1.1  jdolecek 		0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 0xc1404, 0xc2f50, 0xc4a7b,
    450   1.1  jdolecek 		0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 0xceaec, 0xd053f,
    451   1.1  jdolecek 		0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 0xdba4a,
    452   1.1  jdolecek 		0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
    453   1.1  jdolecek 		0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a,
    454   1.1  jdolecek 		0xf2c83, 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57,
    455   1.1  jdolecek 		0xfd1a7, 0xfe8df
    456   1.1  jdolecek 	};
    457   1.1  jdolecek 	static const u_int8_t logSlopeTable[128] = {
    458   1.1  jdolecek 		0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
    459   1.1  jdolecek 		0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
    460   1.1  jdolecek 		0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
    461   1.1  jdolecek 		0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
    462   1.1  jdolecek 		0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
    463   1.1  jdolecek 		0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
    464   1.1  jdolecek 		0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
    465   1.1  jdolecek 		0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
    466   1.1  jdolecek 		0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
    467   1.1  jdolecek 		0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
    468   1.1  jdolecek 		0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
    469   1.1  jdolecek 		0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
    470   1.1  jdolecek 		0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
    471   1.1  jdolecek 		0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
    472   1.1  jdolecek 		0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
    473   1.1  jdolecek 		0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
    474   1.1  jdolecek 	};
    475   1.1  jdolecek 	int8_t          i;
    476   1.1  jdolecek 
    477   1.1  jdolecek 	if (rate == 0)
    478   1.1  jdolecek 		return 0;	/* Bail out if no leading "1" */
    479   1.1  jdolecek 	rate *= 11185;		/* Scale 48000 to 0x20002380 */
    480   1.1  jdolecek 	for (i = 31; i > 0; i--) {
    481   1.1  jdolecek 		if (rate & 0x80000000) {	/* Detect leading "1" */
    482   1.1  jdolecek 			return (((u_int32_t) (i - 15) << 20) +
    483   1.1  jdolecek 				logMagTable[0x7f & (rate >> 24)] +
    484   1.1  jdolecek 				(0x7f & (rate >> 17)) *
    485   1.1  jdolecek 				logSlopeTable[0x7f & (rate >> 24)]);
    486   1.1  jdolecek 		}
    487   1.1  jdolecek 		rate <<= 1;
    488   1.1  jdolecek 	}
    489   1.1  jdolecek 
    490   1.1  jdolecek 	return 0;		/* Should never reach this point */
    491   1.1  jdolecek }
    492   1.1  jdolecek 
    493   1.1  jdolecek /* Emu10k1 Low level */
    494   1.1  jdolecek 
    495   1.1  jdolecek static u_int32_t
    496   1.1  jdolecek emuxki_read(struct emuxki_softc *sc, u_int16_t chano, u_int32_t reg)
    497   1.1  jdolecek {
    498   1.1  jdolecek 	u_int32_t       ptr, mask = 0xffffffff;
    499   1.1  jdolecek 	u_int8_t        size, offset = 0;
    500   1.1  jdolecek 	int             s;
    501   1.1  jdolecek 
    502   1.1  jdolecek 	ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
    503   1.1  jdolecek 		(chano & EMU_PTR_CHNO_MASK);
    504   1.1  jdolecek 	if (reg & 0xff000000) {
    505   1.1  jdolecek 		size = (reg >> 24) & 0x3f;
    506   1.1  jdolecek 		offset = (reg >> 16) & 0x1f;
    507   1.1  jdolecek 		mask = ((1 << size) - 1) << offset;
    508   1.1  jdolecek 	}
    509   1.1  jdolecek 
    510   1.1  jdolecek 	s = splaudio();
    511   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
    512   1.1  jdolecek 	ptr = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_DATA) & mask)
    513   1.1  jdolecek 		>> offset;
    514   1.1  jdolecek 	splx(s);
    515   1.1  jdolecek 
    516   1.1  jdolecek 	return (ptr);
    517   1.1  jdolecek }
    518   1.1  jdolecek 
    519   1.1  jdolecek static void
    520   1.1  jdolecek emuxki_write(struct emuxki_softc *sc, u_int16_t chano,
    521   1.1  jdolecek 	      u_int32_t reg, u_int32_t data)
    522   1.1  jdolecek {
    523   1.1  jdolecek 	u_int32_t       ptr, mask;
    524   1.1  jdolecek 	u_int8_t        size, offset;
    525   1.1  jdolecek 	int             s;
    526   1.1  jdolecek 
    527   1.1  jdolecek 	ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
    528   1.1  jdolecek 		(chano & EMU_PTR_CHNO_MASK);
    529   1.1  jdolecek 	if (reg & 0xff000000) {
    530   1.1  jdolecek 		size = (reg >> 24) & 0x3f;
    531   1.1  jdolecek 		offset = (reg >> 16) & 0x1f;
    532   1.1  jdolecek 		mask = ((1 << size) - 1) << offset;
    533   1.1  jdolecek 		data = ((data << offset) & mask) |
    534   1.1  jdolecek 			(emuxki_read(sc, chano, reg & 0xffff) & ~mask);
    535   1.1  jdolecek 	}
    536   1.1  jdolecek 
    537   1.1  jdolecek 	s = splaudio();
    538   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
    539   1.1  jdolecek 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_DATA, data);
    540   1.1  jdolecek 	splx(s);
    541   1.1  jdolecek }
    542   1.1  jdolecek 
    543   1.1  jdolecek /* Microcode should this go in /sys/dev/microcode ? */
    544   1.1  jdolecek 
    545   1.1  jdolecek static void
    546   1.1  jdolecek emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data)
    547   1.1  jdolecek {
    548   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICROCODEBASE + pc, data);
    549   1.1  jdolecek }
    550   1.1  jdolecek 
    551   1.1  jdolecek static void
    552   1.1  jdolecek emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
    553   1.1  jdolecek 		  u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y)
    554   1.1  jdolecek {
    555   1.1  jdolecek 	emuxki_write_micro(sc, *pc << 1,
    556   1.1  jdolecek 		((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
    557   1.1  jdolecek 		(y & EMU_DSP_LOWORD_OPY_MASK));
    558   1.1  jdolecek 	emuxki_write_micro(sc, (*pc << 1) + 1,
    559   1.1  jdolecek 		((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
    560   1.1  jdolecek 		((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
    561   1.1  jdolecek 		(a & EMU_DSP_HIWORD_OPA_MASK));
    562   1.1  jdolecek 	(*pc)++;
    563   1.1  jdolecek }
    564   1.1  jdolecek 
    565   1.1  jdolecek /* init and shutdown */
    566   1.1  jdolecek 
    567   1.1  jdolecek static void
    568   1.1  jdolecek emuxki_initfx(struct emuxki_softc *sc)
    569   1.1  jdolecek {
    570   1.1  jdolecek 	u_int16_t       pc;
    571   1.1  jdolecek 
    572   1.1  jdolecek 	/* Set all GPRs to 0 */
    573   1.1  jdolecek 	for (pc = 0; pc < 256; pc++)
    574   1.1  jdolecek 		emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
    575   1.1  jdolecek 	for (pc = 0; pc < 160; pc++) {
    576   1.1  jdolecek 		emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
    577   1.1  jdolecek 		emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
    578   1.1  jdolecek 	}
    579   1.1  jdolecek 	pc = 0;
    580   1.1  jdolecek 	/* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
    581   1.1  jdolecek 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    582   1.1  jdolecek 			  EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
    583   1.1  jdolecek 			  EMU_DSP_CST(0),
    584   1.1  jdolecek 			  EMU_DSP_FX(0), EMU_DSP_CST(4));
    585   1.1  jdolecek 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    586   1.1  jdolecek 			  EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
    587   1.1  jdolecek 			  EMU_DSP_CST(0),
    588   1.1  jdolecek 			  EMU_DSP_FX(1), EMU_DSP_CST(4));
    589   1.1  jdolecek 
    590   1.1  jdolecek 	/* Rear channel OUT (l/r) = FX[2/3] * 4 */
    591   1.1  jdolecek #if 0
    592   1.1  jdolecek 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    593   1.1  jdolecek 			  EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN),
    594   1.1  jdolecek 			  EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
    595   1.1  jdolecek 			  EMU_DSP_FX(0), EMU_DSP_CST(4));
    596   1.1  jdolecek 	emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
    597   1.1  jdolecek 			  EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN),
    598   1.1  jdolecek 			  EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
    599   1.1  jdolecek 			  EMU_DSP_FX(1), EMU_DSP_CST(4));
    600   1.1  jdolecek #endif
    601   1.1  jdolecek 	/* zero out the rest of the microcode */
    602   1.1  jdolecek 	while (pc < 512)
    603   1.1  jdolecek 		emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
    604   1.1  jdolecek 				  EMU_DSP_CST(0), EMU_DSP_CST(0),
    605   1.1  jdolecek 				  EMU_DSP_CST(0), EMU_DSP_CST(0));
    606   1.1  jdolecek 
    607   1.1  jdolecek 	emuxki_write(sc, 0, EMU_DBG, 0);	/* Is it really necessary ? */
    608   1.1  jdolecek }
    609   1.1  jdolecek 
    610   1.1  jdolecek static int
    611   1.1  jdolecek emuxki_init(struct emuxki_softc *sc)
    612   1.1  jdolecek {
    613   1.1  jdolecek 	u_int16_t       i;
    614   1.1  jdolecek 	u_int32_t       spcs, *ptb;
    615   1.1  jdolecek 	bus_addr_t      silentpage;
    616   1.1  jdolecek 
    617   1.1  jdolecek 	/* disable any channel interrupt */
    618   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    619   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    620   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    621   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    622   1.1  jdolecek 
    623   1.1  jdolecek 	/* Set recording buffers sizes to zero */
    624   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    625   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    626   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    627   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    628   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    629   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    630   1.1  jdolecek 
    631   1.1  jdolecek 	/* Initialize all channels to stopped and no effects */
    632   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    633   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
    634   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IP, 0);
    635   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
    636   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
    637   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    638   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    639   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCR, 0);
    640   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PSST, 0);
    641   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DSL, 0x10);	/* Why 16 ? */
    642   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CCCA, 0);
    643   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z1, 0);
    644   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_Z2, 0);
    645   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
    646   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
    647   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
    648   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
    649   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PEFE, 0);
    650   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
    651   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 24);
    652   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 24);
    653   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
    654   1.1  jdolecek 
    655   1.1  jdolecek 		/* these are last so OFF prevents writing */
    656   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0);
    657   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0);
    658   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0);
    659   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
    660   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0);
    661   1.1  jdolecek 	}
    662   1.1  jdolecek 
    663   1.1  jdolecek 	/* set digital outputs format */
    664   1.1  jdolecek 	spcs = (EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
    665   1.1  jdolecek 	      EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
    666   1.1  jdolecek 		EMU_SPCS_GENERATIONSTATUS | 0x00001200 /* Cat code. */ |
    667   1.1  jdolecek 		0x00000000 /* IEC-958 Mode */ | EMU_SPCS_EMPHASIS_NONE |
    668   1.1  jdolecek 		EMU_SPCS_COPYRIGHT);
    669   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS0, spcs);
    670   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS1, spcs);
    671   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SPCS2, spcs);
    672   1.1  jdolecek 
    673   1.1  jdolecek 	/* Let's play with sound processor */
    674   1.1  jdolecek 	emuxki_initfx(sc);
    675   1.1  jdolecek 
    676   1.1  jdolecek 	/* Here is our Page Table */
    677   1.1  jdolecek 	if ((sc->ptb = dmamem_alloc(sc->sc_dmat,
    678   1.1  jdolecek 	    EMU_MAXPTE * sizeof(u_int32_t),
    679   1.1  jdolecek 	    EMU_DMA_ALIGN, EMU_DMAMEM_NSEG,
    680   1.1  jdolecek 	    M_DEVBUF, M_WAITOK)) == NULL)
    681   1.1  jdolecek 		return (ENOMEM);
    682   1.1  jdolecek 
    683   1.1  jdolecek 	/* This is necessary unless you like Metallic noise... */
    684   1.1  jdolecek 	if ((sc->silentpage = dmamem_alloc(sc->sc_dmat, EMU_PTESIZE,
    685   1.1  jdolecek 	    EMU_DMA_ALIGN, EMU_DMAMEM_NSEG, M_DEVBUF, M_WAITOK))==NULL){
    686   1.1  jdolecek 		dmamem_free(sc->ptb, M_DEVBUF);
    687   1.1  jdolecek 		return (ENOMEM);
    688   1.1  jdolecek 	}
    689   1.1  jdolecek 
    690   1.1  jdolecek 	/* Zero out the silent page */
    691   1.1  jdolecek 	/* This might not be always true, it might be 128 for 8bit channels */
    692   1.1  jdolecek 	memset(KERNADDR(sc->silentpage), 0, DMASIZE(sc->silentpage));
    693   1.1  jdolecek 
    694   1.1  jdolecek 	/*
    695   1.1  jdolecek 	 * Set all the PTB Entries to the silent page We shift the physical
    696   1.1  jdolecek 	 * address by one and OR it with the page number. I don't know what
    697   1.1  jdolecek 	 * the ORed index is for, might be a very useful unused feature...
    698   1.1  jdolecek 	 */
    699   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
    700   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
    701   1.1  jdolecek 	for (i = 0; i < EMU_MAXPTE; i++)
    702   1.1  jdolecek 		ptb[i] = silentpage | i;
    703   1.1  jdolecek 
    704   1.1  jdolecek 	/* Write PTB address and set TCB to none */
    705   1.1  jdolecek 	emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
    706   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCBS, 0);	/* This means 16K TCB */
    707   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCB, 0);	/* No TCB use for now */
    708   1.1  jdolecek 
    709   1.1  jdolecek 	/*
    710   1.1  jdolecek 	 * Set channels MAPs to the silent page.
    711   1.1  jdolecek 	 * I don't know what MAPs are for.
    712   1.1  jdolecek 	 */
    713   1.1  jdolecek 	silentpage |= EMU_CHAN_MAP_PTI_MASK;
    714   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    715   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_MAPA, silentpage);
    716   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_MAPB, silentpage);
    717   1.1  jdolecek 		sc->channel[i] = NULL;
    718   1.1  jdolecek 	}
    719   1.1  jdolecek 
    720   1.1  jdolecek 	/* Init voices list */
    721   1.1  jdolecek 	LIST_INIT(&(sc->voices));
    722   1.1  jdolecek 
    723   1.1  jdolecek 	/* Timer is stopped */
    724   1.1  jdolecek 	sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
    725   1.1  jdolecek 	return (0);
    726   1.1  jdolecek }
    727   1.1  jdolecek 
    728   1.1  jdolecek static void
    729   1.1  jdolecek emuxki_shutdown(struct emuxki_softc *sc)
    730   1.1  jdolecek {
    731   1.1  jdolecek 	u_int32_t       i;
    732   1.1  jdolecek 
    733   1.1  jdolecek 	/* Disable any Channels interrupts */
    734   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEL, 0);
    735   1.1  jdolecek 	emuxki_write(sc, 0, EMU_CLIEH, 0);
    736   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEL, 0);
    737   1.1  jdolecek 	emuxki_write(sc, 0, EMU_SOLEH, 0);
    738   1.1  jdolecek 
    739   1.1  jdolecek 	/*
    740   1.1  jdolecek 	 * Should do some voice(stream) stopping stuff here, that's what will
    741   1.1  jdolecek 	 * stop and deallocate all channels.
    742   1.1  jdolecek 	 */
    743   1.1  jdolecek 
    744   1.1  jdolecek 	/* Stop all channels */
    745   1.1  jdolecek 	/* XXX This shouldn't be necessary, I'll remove once everything works */
    746   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++)
    747   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
    748   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i++) {
    749   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_VTFT, 0);
    750   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CVCF, 0);
    751   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
    752   1.1  jdolecek 		emuxki_write(sc, i, EMU_CHAN_CPF, 0);
    753   1.1  jdolecek 	}
    754   1.1  jdolecek 
    755   1.1  jdolecek 	/*
    756   1.1  jdolecek 	 * Deallocate Emu10k1 caches and recording buffers. Again it will be
    757   1.1  jdolecek 	 * removed because it will be done in voice shutdown.
    758   1.1  jdolecek 	 */
    759   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
    760   1.1  jdolecek 	emuxki_write(sc, 0, EMU_MICBA, 0);
    761   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
    762   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXBA, 0);
    763   1.1  jdolecek 	emuxki_write(sc, 0, EMU_FXWC, 0);
    764   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
    765   1.1  jdolecek 	emuxki_write(sc, 0, EMU_ADCBA, 0);
    766   1.1  jdolecek 
    767   1.1  jdolecek 	/*
    768   1.1  jdolecek 	 * XXX I don't know yet how I will handle tank cache buffer,
    769   1.1  jdolecek 	 * I don't even clearly  know what it is for.
    770   1.1  jdolecek 	 */
    771   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCB, 0);	/* 16K again */
    772   1.1  jdolecek 	emuxki_write(sc, 0, EMU_TCBS, 0);
    773   1.1  jdolecek 
    774   1.1  jdolecek 	emuxki_write(sc, 0, EMU_DBG, 0x8000);	/* necessary ? */
    775   1.1  jdolecek 
    776   1.1  jdolecek 	dmamem_free(sc->silentpage, M_DEVBUF);
    777   1.1  jdolecek 	dmamem_free(sc->ptb, M_DEVBUF);
    778   1.1  jdolecek }
    779   1.1  jdolecek 
    780   1.1  jdolecek /* Emu10k1 Memory managment */
    781   1.1  jdolecek 
    782   1.1  jdolecek static struct emuxki_mem *
    783   1.1  jdolecek emuxki_mem_new(struct emuxki_softc *sc, int ptbidx,
    784   1.1  jdolecek 		size_t size, int type, int flags)
    785   1.1  jdolecek {
    786   1.1  jdolecek 	struct emuxki_mem *mem;
    787   1.1  jdolecek 
    788   1.1  jdolecek 	if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
    789   1.1  jdolecek 		return (NULL);
    790   1.1  jdolecek 
    791   1.1  jdolecek 	mem->ptbidx = ptbidx;
    792   1.1  jdolecek 	if ((mem->dmamem = dmamem_alloc(sc->sc_dmat, size, EMU_DMA_ALIGN,
    793   1.1  jdolecek 	    EMU_DMAMEM_NSEG, type, flags)) == NULL) {
    794   1.1  jdolecek 		free(mem, type);
    795   1.1  jdolecek 		return (NULL);
    796   1.1  jdolecek 	}
    797   1.1  jdolecek 	return (mem);
    798   1.1  jdolecek }
    799   1.1  jdolecek 
    800   1.1  jdolecek static void
    801   1.1  jdolecek emuxki_mem_delete(struct emuxki_mem *mem, int type)
    802   1.1  jdolecek {
    803   1.1  jdolecek 	dmamem_free(mem->dmamem, type);
    804   1.1  jdolecek 	free(mem, type);
    805   1.1  jdolecek }
    806   1.1  jdolecek 
    807   1.1  jdolecek static void *
    808   1.1  jdolecek emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags)
    809   1.1  jdolecek {
    810   1.1  jdolecek 	int             i, j, s;
    811   1.1  jdolecek 	size_t          numblocks;
    812   1.1  jdolecek 	struct emuxki_mem *mem;
    813   1.1  jdolecek 	u_int32_t      *ptb, silentpage;
    814   1.1  jdolecek 
    815   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
    816   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
    817   1.1  jdolecek 	numblocks = size / EMU_PTESIZE;
    818   1.1  jdolecek 	if (size % EMU_PTESIZE)
    819   1.1  jdolecek 		numblocks++;
    820   1.1  jdolecek 
    821   1.1  jdolecek 	for (i = 0; i < EMU_MAXPTE; i++)
    822   1.1  jdolecek 		if ((ptb[i] & EMU_CHAN_MAP_PTE_MASK) == silentpage) {
    823   1.1  jdolecek 			/* We look for a free PTE */
    824   1.1  jdolecek 			s = splaudio();
    825   1.1  jdolecek 			for (j = 0; j < numblocks; j++)
    826   1.1  jdolecek 				if ((ptb[i + j] & EMU_CHAN_MAP_PTE_MASK)
    827   1.1  jdolecek 				    != silentpage)
    828   1.1  jdolecek 					break;
    829   1.1  jdolecek 			if (j == numblocks) {
    830   1.1  jdolecek 				if ((mem = emuxki_mem_new(sc, i,
    831   1.1  jdolecek 						size, type, flags)) == NULL) {
    832   1.1  jdolecek 					splx(s);
    833   1.1  jdolecek 					return (NULL);
    834   1.1  jdolecek 				}
    835   1.1  jdolecek 				for (j = 0; j < numblocks; j++)
    836   1.1  jdolecek 					ptb[i + j] =
    837   1.1  jdolecek 						(((DMAADDR(mem->dmamem) +
    838   1.1  jdolecek 						 j * EMU_PTESIZE)) << 1)
    839   1.1  jdolecek 						| (i + j);
    840   1.1  jdolecek 				LIST_INSERT_HEAD(&(sc->mem), mem, next);
    841   1.1  jdolecek 				splx(s);
    842   1.1  jdolecek 				return (KERNADDR(mem->dmamem));
    843   1.1  jdolecek 			} else
    844   1.1  jdolecek 				i += j;
    845   1.1  jdolecek 			splx(s);
    846   1.1  jdolecek 		}
    847   1.1  jdolecek 	return (NULL);
    848   1.1  jdolecek }
    849   1.1  jdolecek 
    850   1.1  jdolecek static void *
    851   1.1  jdolecek emuxki_rmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags)
    852   1.1  jdolecek {
    853   1.1  jdolecek 	struct emuxki_mem *mem;
    854   1.1  jdolecek 	int             s;
    855   1.1  jdolecek 
    856   1.1  jdolecek 	mem = emuxki_mem_new(sc, EMU_RMEM, size, type, flags);
    857   1.1  jdolecek 	if (mem == NULL)
    858   1.1  jdolecek 		return (NULL);
    859   1.1  jdolecek 
    860   1.1  jdolecek 	s = splaudio();
    861   1.1  jdolecek 	LIST_INSERT_HEAD(&(sc->mem), mem, next);
    862   1.1  jdolecek 	splx(s);
    863   1.1  jdolecek 
    864   1.1  jdolecek 	return (KERNADDR(mem->dmamem));
    865   1.1  jdolecek }
    866   1.1  jdolecek 
    867   1.1  jdolecek /*
    868   1.1  jdolecek  * emuxki_channel_* : Channel managment functions
    869   1.1  jdolecek  * emuxki_chanparms_* : Channel parameters modification functions
    870   1.1  jdolecek  */
    871   1.1  jdolecek 
    872   1.1  jdolecek /*
    873   1.1  jdolecek  * is splaudio necessary here, can the same voice be manipulated by two
    874   1.1  jdolecek  * different threads at a time ?
    875   1.1  jdolecek  */
    876   1.1  jdolecek static void
    877   1.1  jdolecek emuxki_chanparms_set_defaults(struct emuxki_channel *chan)
    878   1.1  jdolecek {
    879   1.1  jdolecek 	chan->fxsend.a.level = chan->fxsend.b.level =
    880   1.7  jdolecek 	chan->fxsend.c.level = chan->fxsend.d.level = 0xc0;	/* not max */
    881   1.1  jdolecek 	chan->fxsend.a.dest = 0x0;
    882   1.1  jdolecek 	chan->fxsend.b.dest = 0x1;
    883   1.1  jdolecek 	chan->fxsend.c.dest = 0x2;
    884   1.1  jdolecek 	chan->fxsend.d.dest = 0x3;
    885   1.1  jdolecek 
    886   1.1  jdolecek 	chan->pitch.intial = 0x0000;	/* shouldn't it be 0xE000 ? */
    887   1.1  jdolecek 	chan->pitch.current = 0x0000;	/* should it be 0x0400 */
    888   1.1  jdolecek 	chan->pitch.target = 0x0000;	/* the unity pitch shift ? */
    889   1.1  jdolecek 	chan->pitch.envelope_amount = 0x00;	/* none */
    890   1.1  jdolecek 
    891   1.1  jdolecek 	chan->initial_attenuation = 0x00;	/* no attenuation */
    892   1.1  jdolecek 	chan->volume.current = 0x0000;	/* no volume */
    893   1.1  jdolecek 	chan->volume.target = 0xffff;
    894   1.1  jdolecek 	chan->volume.envelope.current_state = 0x8000;	/* 0 msec delay */
    895   1.1  jdolecek 	chan->volume.envelope.hold_time = 0x7f;	/* 0 msec */
    896   1.1  jdolecek 	chan->volume.envelope.attack_time = 0x7F;	/* 5.5msec */
    897   1.1  jdolecek 	chan->volume.envelope.sustain_level = 0x7F;	/* full  */
    898   1.1  jdolecek 	chan->volume.envelope.decay_time = 0x7F;	/* 22msec  */
    899   1.1  jdolecek 
    900   1.1  jdolecek 	chan->filter.initial_cutoff_frequency = 0xff;	/* no filter */
    901   1.1  jdolecek 	chan->filter.current_cutoff_frequency = 0xffff;	/* no filtering */
    902   1.1  jdolecek 	chan->filter.target_cutoff_frequency = 0xffff;	/* no filtering */
    903   1.1  jdolecek 	chan->filter.lowpass_resonance_height = 0x0;
    904   1.1  jdolecek 	chan->filter.interpolation_ROM = 0x1;	/* full band */
    905   1.1  jdolecek 	chan->filter.envelope_amount = 0x7f;	/* none */
    906   1.1  jdolecek 	chan->filter.LFO_modulation_depth = 0x00;	/* none */
    907   1.1  jdolecek 
    908   1.1  jdolecek 	chan->loop.start = 0x000000;
    909   1.1  jdolecek 	chan->loop.end = 0x000010;	/* Why ? */
    910   1.1  jdolecek 
    911   1.1  jdolecek 	chan->modulation.envelope.current_state = 0x8000;
    912   1.1  jdolecek 	chan->modulation.envelope.hold_time = 0x00;	/* 127 better ? */
    913   1.1  jdolecek 	chan->modulation.envelope.attack_time = 0x00;	/* infinite */
    914   1.1  jdolecek 	chan->modulation.envelope.sustain_level = 0x00;	/* off */
    915   1.1  jdolecek 	chan->modulation.envelope.decay_time = 0x7f;	/* 22 msec */
    916   1.1  jdolecek 	chan->modulation.LFO_state = 0x8000;
    917   1.1  jdolecek 
    918   1.1  jdolecek 	chan->vibrato_LFO.state = 0x8000;
    919   1.1  jdolecek 	chan->vibrato_LFO.modulation_depth = 0x00;	/* none */
    920   1.1  jdolecek 	chan->vibrato_LFO.vibrato_depth = 0x00;
    921   1.1  jdolecek 	chan->vibrato_LFO.frequency = 0x00;	/* Why set to 24 when
    922   1.1  jdolecek 						 * initialized ? */
    923   1.1  jdolecek 
    924   1.1  jdolecek 	chan->tremolo_depth = 0x00;
    925   1.1  jdolecek }
    926   1.1  jdolecek 
    927   1.1  jdolecek /* only call it at splaudio */
    928   1.1  jdolecek static struct emuxki_channel *
    929   1.1  jdolecek emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num)
    930   1.1  jdolecek {
    931   1.1  jdolecek 	struct emuxki_channel *chan;
    932   1.1  jdolecek 
    933   1.1  jdolecek 	chan = malloc(sizeof(struct emuxki_channel), M_DEVBUF, M_WAITOK);
    934   1.1  jdolecek 	if (chan == NULL)
    935   1.1  jdolecek 		return (NULL);
    936   1.1  jdolecek 
    937   1.1  jdolecek 	chan->voice = voice;
    938   1.1  jdolecek 	chan->num = num;
    939   1.1  jdolecek 	emuxki_chanparms_set_defaults(chan);
    940   1.1  jdolecek 	chan->voice->sc->channel[num] = chan;
    941   1.1  jdolecek 	return (chan);
    942   1.1  jdolecek }
    943   1.1  jdolecek 
    944   1.1  jdolecek /* only call it at splaudio */
    945   1.1  jdolecek static void
    946   1.1  jdolecek emuxki_channel_delete(struct emuxki_channel *chan)
    947   1.1  jdolecek {
    948   1.1  jdolecek 	chan->voice->sc->channel[chan->num] = NULL;
    949   1.1  jdolecek 	free(chan, M_DEVBUF);
    950   1.1  jdolecek }
    951   1.1  jdolecek 
    952   1.1  jdolecek static void
    953   1.1  jdolecek emuxki_channel_set_fxsend(struct emuxki_channel *chan,
    954   1.1  jdolecek 			   struct emuxki_chanparms_fxsend *fxsend)
    955   1.1  jdolecek {
    956   1.1  jdolecek 	/* Could do a memcpy ...*/
    957   1.1  jdolecek 	chan->fxsend.a.level = fxsend->a.level;
    958   1.1  jdolecek 	chan->fxsend.b.level = fxsend->b.level;
    959   1.1  jdolecek 	chan->fxsend.c.level = fxsend->c.level;
    960   1.1  jdolecek 	chan->fxsend.d.level = fxsend->d.level;
    961   1.1  jdolecek 	chan->fxsend.a.dest = fxsend->a.dest;
    962   1.1  jdolecek 	chan->fxsend.b.dest = fxsend->b.dest;
    963   1.1  jdolecek 	chan->fxsend.c.dest = fxsend->c.dest;
    964   1.1  jdolecek 	chan->fxsend.d.dest = fxsend->d.dest;
    965   1.1  jdolecek }
    966   1.1  jdolecek 
    967   1.1  jdolecek static void
    968   1.1  jdolecek emuxki_channel_set_srate(struct emuxki_channel *chan, u_int32_t srate)
    969   1.1  jdolecek {
    970   1.1  jdolecek 	chan->pitch.target = (srate << 8) / 375;
    971   1.1  jdolecek 	chan->pitch.target = (chan->pitch.target >> 1) +
    972   1.1  jdolecek 		(chan->pitch.target & 1);
    973   1.1  jdolecek 	chan->pitch.target &= 0xffff;
    974   1.1  jdolecek 	chan->pitch.current = chan->pitch.target;
    975   1.1  jdolecek 	chan->pitch.intial =
    976   1.1  jdolecek 		(emuxki_rate_to_pitch(srate) >> 8) & EMU_CHAN_IP_MASK;
    977   1.1  jdolecek }
    978   1.1  jdolecek 
    979   1.1  jdolecek /* voice params must be set before calling this */
    980   1.1  jdolecek static void
    981   1.1  jdolecek emuxki_channel_set_bufparms(struct emuxki_channel *chan,
    982   1.1  jdolecek 			     u_int32_t start, u_int32_t end)
    983   1.1  jdolecek {
    984   1.1  jdolecek 	u_int8_t        shift;
    985   1.1  jdolecek 	struct emuxki_voice *voice = chan->voice;
    986   1.1  jdolecek 
    987   1.1  jdolecek 	shift = voice->stereo + voice->b16;
    988   1.1  jdolecek 	chan->loop.start = start & EMU_CHAN_PSST_LOOPSTARTADDR_MASK;
    989   1.1  jdolecek 	chan->loop.end = end & EMU_CHAN_DSL_LOOPENDADDR_MASK;
    990   1.1  jdolecek }
    991   1.1  jdolecek 
    992   1.1  jdolecek static void
    993   1.1  jdolecek emuxki_channel_commit_parms(struct emuxki_channel *chan)
    994   1.1  jdolecek {
    995   1.1  jdolecek 	struct emuxki_voice *voice = chan->voice;
    996   1.1  jdolecek 	struct emuxki_softc *sc = voice->sc;
    997   1.1  jdolecek 	u_int32_t start, mapval;
    998   1.1  jdolecek 	u_int8_t chano = chan->num;
    999   1.1  jdolecek 	int s;
   1000   1.1  jdolecek 
   1001   1.1  jdolecek 	start = chan->loop.start +
   1002   1.1  jdolecek 		(voice->stereo ? 28 : 30) * (voice->b16 + 1);
   1003   1.1  jdolecek 	mapval = DMAADDR(sc->silentpage) << 1 | EMU_CHAN_MAP_PTI_MASK;
   1004   1.1  jdolecek 
   1005   1.1  jdolecek 	s = splaudio();
   1006   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo);
   1007   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FXRT,
   1008   1.1  jdolecek 		(chan->fxsend.d.dest << 28) | (chan->fxsend.c.dest << 24) |
   1009   1.1  jdolecek 		(chan->fxsend.b.dest << 20) | (chan->fxsend.a.dest << 16));
   1010   1.1  jdolecek 	emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX,
   1011   1.1  jdolecek 		(chan->fxsend.a.level << 8) | chan->fxsend.b.level);
   1012   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DSL,
   1013   1.1  jdolecek 		(chan->fxsend.d.level << 24) | chan->loop.end);
   1014   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PSST,
   1015   1.1  jdolecek 		(chan->fxsend.c.level << 24) | chan->loop.start);
   1016   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCCA,
   1017   1.1  jdolecek 		(chan->filter.lowpass_resonance_height << 28) |
   1018   1.1  jdolecek 		(chan->filter.interpolation_ROM << 25) |
   1019   1.1  jdolecek 		(voice->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT) | start);
   1020   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_Z1, 0);
   1021   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_Z2, 0);
   1022   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_MAPA, mapval);
   1023   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_MAPB, mapval);
   1024   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRFILTER,
   1025   1.1  jdolecek 		chan->filter.current_cutoff_frequency);
   1026   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_FILTERTARGET,
   1027   1.1  jdolecek 		chan->filter.target_cutoff_frequency);
   1028   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ATKHLDM,
   1029   1.1  jdolecek 		(chan->modulation.envelope.hold_time << 8) |
   1030   1.1  jdolecek 		chan->modulation.envelope.attack_time);
   1031   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DCYSUSM,
   1032   1.1  jdolecek 		(chan->modulation.envelope.sustain_level << 8) |
   1033   1.1  jdolecek 		chan->modulation.envelope.decay_time);
   1034   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_LFOVAL1,
   1035   1.1  jdolecek 		chan->modulation.LFO_state);
   1036   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_LFOVAL2,
   1037   1.1  jdolecek 		chan->vibrato_LFO.state);
   1038   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FMMOD,
   1039   1.1  jdolecek 		(chan->vibrato_LFO.modulation_depth << 8) |
   1040   1.1  jdolecek 		chan->filter.LFO_modulation_depth);
   1041   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_TREMFRQ,
   1042   1.1  jdolecek 		(chan->tremolo_depth << 8));
   1043   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_FM2FRQ2,
   1044   1.1  jdolecek 		(chan->vibrato_LFO.vibrato_depth << 8) |
   1045   1.1  jdolecek 		chan->vibrato_LFO.frequency);
   1046   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ENVVAL,
   1047   1.1  jdolecek 		chan->modulation.envelope.current_state);
   1048   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ATKHLDV,
   1049   1.1  jdolecek 		(chan->volume.envelope.hold_time << 8) |
   1050   1.1  jdolecek 		chan->volume.envelope.attack_time);
   1051   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_ENVVOL,
   1052   1.1  jdolecek 		chan->volume.envelope.current_state);
   1053   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PEFE,
   1054   1.1  jdolecek 		(chan->pitch.envelope_amount << 8) |
   1055   1.1  jdolecek 		chan->filter.envelope_amount);
   1056   1.1  jdolecek 	splx(s);
   1057   1.1  jdolecek }
   1058   1.1  jdolecek 
   1059   1.1  jdolecek static void
   1060   1.1  jdolecek emuxki_channel_start(struct emuxki_channel *chan)
   1061   1.1  jdolecek {
   1062   1.1  jdolecek 	struct emuxki_voice *voice = chan->voice;
   1063   1.1  jdolecek 	struct emuxki_softc *sc = voice->sc;
   1064   1.1  jdolecek 	u_int8_t        cache_sample, cache_invalid_size, chano = chan->num;
   1065   1.1  jdolecek 	u_int32_t       sample;
   1066   1.1  jdolecek 	int             s;
   1067   1.1  jdolecek 
   1068   1.1  jdolecek 	cache_sample = voice->stereo ? 4 : 2;
   1069   1.1  jdolecek 	sample = voice->b16 ? 0x00000000 : 0x80808080;
   1070   1.1  jdolecek 	cache_invalid_size = (voice->stereo ? 28 : 30) * (voice->b16 + 1);
   1071   1.1  jdolecek 
   1072   1.1  jdolecek 	s = splaudio();
   1073   1.1  jdolecek 	while (cache_sample--) {
   1074   1.1  jdolecek 		emuxki_write(sc, chano, EMU_CHAN_CD0 + cache_sample,
   1075   1.1  jdolecek 			sample);
   1076   1.1  jdolecek 	}
   1077   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
   1078   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_READADDRESS, 64);
   1079   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE,
   1080   1.1  jdolecek 		cache_invalid_size);
   1081   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IFATN,
   1082   1.1  jdolecek 		(chan->filter.target_cutoff_frequency << 8) |
   1083   1.1  jdolecek 		chan->initial_attenuation);
   1084   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET,
   1085   1.1  jdolecek 		chan->volume.target);
   1086   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL,
   1087   1.1  jdolecek 		chan->volume.current);
   1088   1.1  jdolecek 	emuxki_write(sc, 0,
   1089   1.1  jdolecek 		EMU_MKSUBREG(1, chano, EMU_SOLEL + (chano >> 5)),
   1090   1.1  jdolecek 		0);	/* Clear stop on loop */
   1091   1.1  jdolecek 	emuxki_write(sc, 0,
   1092   1.1  jdolecek 		EMU_MKSUBREG(1, chano, EMU_CLIEL + (chano >> 5)),
   1093   1.1  jdolecek 		0);	/* Clear loop interrupt */
   1094   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_DCYSUSV,
   1095   1.1  jdolecek 		(chan->volume.envelope.sustain_level << 8) |
   1096   1.1  jdolecek 		chan->volume.envelope.decay_time);
   1097   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET,
   1098   1.1  jdolecek 		chan->pitch.target);
   1099   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH,
   1100   1.1  jdolecek 		chan->pitch.current);
   1101   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IP, chan->pitch.intial);
   1102   1.1  jdolecek 
   1103   1.1  jdolecek 	splx(s);
   1104   1.1  jdolecek }
   1105   1.1  jdolecek 
   1106   1.1  jdolecek static void
   1107   1.1  jdolecek emuxki_channel_stop(struct emuxki_channel *chan)
   1108   1.1  jdolecek {
   1109   1.1  jdolecek 	int s;
   1110   1.1  jdolecek 	u_int8_t chano = chan->num;
   1111   1.1  jdolecek 	struct emuxki_softc *sc = chan->voice->sc;
   1112   1.1  jdolecek 
   1113   1.1  jdolecek 	s = splaudio();
   1114   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET, 0);
   1115   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH, 0);
   1116   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IFATN_ATTENUATION, 0xff);
   1117   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET, 0);
   1118   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL, 0);
   1119   1.1  jdolecek 	emuxki_write(sc, chano, EMU_CHAN_IP, 0);
   1120   1.1  jdolecek 	splx(s);
   1121   1.1  jdolecek }
   1122   1.1  jdolecek 
   1123   1.1  jdolecek /*
   1124   1.1  jdolecek  * Voices managment
   1125   1.1  jdolecek  * emuxki_voice_dataloc : use(play or rec) independant dataloc union helpers
   1126   1.1  jdolecek  * emuxki_voice_channel_* : play part of dataloc union helpers
   1127   1.1  jdolecek  * emuxki_voice_recsrc_* : rec part of dataloc union helpers
   1128   1.1  jdolecek  */
   1129   1.1  jdolecek 
   1130   1.1  jdolecek /* Allocate channels for voice in case of play voice */
   1131   1.1  jdolecek static int
   1132   1.1  jdolecek emuxki_voice_channel_create(struct emuxki_voice *voice)
   1133   1.1  jdolecek {
   1134   1.1  jdolecek 	struct emuxki_channel **channel = voice->sc->channel;
   1135   1.1  jdolecek 	u_int8_t i, stereo = voice->stereo;
   1136   1.1  jdolecek 	int s;
   1137   1.1  jdolecek 
   1138   1.1  jdolecek 	for (i = 0; i < EMU_NUMCHAN; i += stereo + 1) {
   1139   1.1  jdolecek 		if ((stereo && (channel[i + 1] != NULL)) ||
   1140   1.1  jdolecek 		    (channel[i] != NULL))	/* Looking for free channels */
   1141   1.1  jdolecek 			continue;
   1142   1.1  jdolecek 		s = splaudio();
   1143   1.1  jdolecek 		if (stereo) {
   1144   1.1  jdolecek 			voice->dataloc.chan[1] =
   1145   1.1  jdolecek 				emuxki_channel_new(voice, i + 1);
   1146   1.1  jdolecek 			if (voice->dataloc.chan[1] == NULL) {
   1147   1.1  jdolecek 				splx(s);
   1148   1.1  jdolecek 				return (ENOMEM);
   1149   1.1  jdolecek 			}
   1150   1.1  jdolecek 		}
   1151   1.1  jdolecek 		voice->dataloc.chan[0] = emuxki_channel_new(voice, i);
   1152   1.1  jdolecek 		if (voice->dataloc.chan[0] == NULL) {
   1153   1.1  jdolecek 			if (stereo) {
   1154   1.1  jdolecek 				emuxki_channel_delete(voice->dataloc.chan[1]);
   1155   1.1  jdolecek 				voice->dataloc.chan[1] = NULL;
   1156   1.1  jdolecek 			}
   1157   1.1  jdolecek 			splx(s);
   1158   1.1  jdolecek 			return (ENOMEM);
   1159   1.1  jdolecek 		}
   1160   1.1  jdolecek 		splx(s);
   1161   1.1  jdolecek 		return (0);
   1162   1.1  jdolecek 	}
   1163   1.1  jdolecek 	return (EAGAIN);
   1164   1.1  jdolecek }
   1165   1.1  jdolecek 
   1166   1.1  jdolecek /* When calling this function we assume no one can access the voice */
   1167   1.1  jdolecek static void
   1168   1.1  jdolecek emuxki_voice_channel_destroy(struct emuxki_voice *voice)
   1169   1.1  jdolecek {
   1170   1.1  jdolecek 	emuxki_channel_delete(voice->dataloc.chan[0]);
   1171   1.1  jdolecek 	voice->dataloc.chan[0] = NULL;
   1172   1.1  jdolecek 	if (voice->stereo)
   1173   1.1  jdolecek 		emuxki_channel_delete(voice->dataloc.chan[1]);
   1174   1.1  jdolecek 	voice->dataloc.chan[1] = NULL;
   1175   1.1  jdolecek }
   1176   1.1  jdolecek 
   1177   1.1  jdolecek /*
   1178   1.1  jdolecek  * Will come back when used in voice_dataloc_create
   1179   1.1  jdolecek  */
   1180   1.1  jdolecek #if 0
   1181   1.1  jdolecek static int
   1182   1.1  jdolecek emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
   1183   1.1  jdolecek {
   1184   1.1  jdolecek 	if (voice->emu->recsrc[source] != NULL)
   1185   1.1  jdolecek 		return (EBUSY);
   1186   1.1  jdolecek 	voice->emu->recsrc[source] = voice;
   1187   1.1  jdolecek 	return (0);
   1188   1.1  jdolecek }
   1189   1.1  jdolecek #endif
   1190   1.1  jdolecek 
   1191   1.1  jdolecek /* When calling this function we assume the voice is stopped */
   1192   1.1  jdolecek static void
   1193   1.1  jdolecek emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source)
   1194   1.1  jdolecek {
   1195   1.1  jdolecek 	sc->recsrc[source] = NULL;
   1196   1.1  jdolecek }
   1197   1.1  jdolecek 
   1198   1.1  jdolecek static int
   1199   1.1  jdolecek emuxki_voice_dataloc_create(struct emuxki_voice *voice)
   1200   1.1  jdolecek {
   1201   1.1  jdolecek 	int             error;
   1202   1.1  jdolecek 
   1203   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1204   1.1  jdolecek 		if ((error = emuxki_voice_channel_create(voice)))
   1205   1.1  jdolecek 			return (error);
   1206   1.1  jdolecek 	} else {
   1207   1.1  jdolecek 		/*
   1208   1.1  jdolecek 		 * Commented out because i don't know how to get the selected
   1209   1.1  jdolecek 		 * recording source
   1210   1.1  jdolecek 		 */
   1211   1.1  jdolecek #if 0
   1212   1.1  jdolecek 		if (emuxki_recsrc_reserve(voice, recsrc))
   1213   1.1  jdolecek 			return (EBUSY);
   1214   1.1  jdolecek 		printf("Which rec src do i have to create!!!\n");
   1215   1.1  jdolecek #endif
   1216   1.1  jdolecek 		return (EBUSY);	/* just return an error, no real meaning */
   1217   1.1  jdolecek 	}
   1218   1.1  jdolecek 	return (0);
   1219   1.1  jdolecek }
   1220   1.1  jdolecek 
   1221   1.1  jdolecek static void
   1222   1.1  jdolecek emuxki_voice_dataloc_destroy(struct emuxki_voice *voice)
   1223   1.1  jdolecek {
   1224   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1225   1.1  jdolecek 		if (voice->dataloc.chan[0] != NULL)
   1226   1.1  jdolecek 			emuxki_voice_channel_destroy(voice);
   1227   1.1  jdolecek 	} else {
   1228   1.1  jdolecek 		if (voice->dataloc.source != EMU_RECSRC_NOTSET) {
   1229   1.1  jdolecek 			emuxki_voice_recsrc_release(voice->sc,
   1230   1.1  jdolecek 						     voice->dataloc.source);
   1231   1.1  jdolecek 			voice->dataloc.source = EMU_RECSRC_NOTSET;
   1232   1.1  jdolecek 		}
   1233   1.1  jdolecek 	}
   1234   1.1  jdolecek }
   1235   1.1  jdolecek 
   1236   1.1  jdolecek static struct emuxki_voice *
   1237   1.1  jdolecek emuxki_voice_new(struct emuxki_softc *sc, u_int8_t use)
   1238   1.1  jdolecek {
   1239   1.1  jdolecek 	struct emuxki_voice *voice;
   1240   1.1  jdolecek 	int             s;
   1241   1.1  jdolecek 
   1242   1.7  jdolecek 	s = splaudio();
   1243   1.7  jdolecek 	voice = sc->lvoice;
   1244   1.7  jdolecek 	sc->lvoice = NULL;
   1245   1.7  jdolecek 	splx(s);
   1246   1.7  jdolecek 
   1247   1.7  jdolecek 	if (!voice) {
   1248   1.7  jdolecek 		if (!(voice = malloc(sizeof(*voice), M_DEVBUF, M_WAITOK)))
   1249   1.7  jdolecek 			return (NULL);
   1250   1.7  jdolecek 		voice->sc = sc;
   1251   1.7  jdolecek 		voice->state = !EMU_VOICE_STATE_STARTED;
   1252   1.7  jdolecek 		voice->stereo = EMU_VOICE_STEREO_NOTSET;
   1253   1.7  jdolecek 		voice->b16 = 0;
   1254   1.7  jdolecek 		voice->sample_rate = 0;
   1255   1.7  jdolecek 		if (use & EMU_VOICE_USE_PLAY)
   1256   1.7  jdolecek 			voice->dataloc.chan[0] = voice->dataloc.chan[0] = NULL;
   1257   1.7  jdolecek 		else
   1258   1.7  jdolecek 			voice->dataloc.source = EMU_RECSRC_NOTSET;
   1259   1.7  jdolecek 		voice->buffer = NULL;
   1260   1.7  jdolecek 		voice->blksize = 0;
   1261   1.7  jdolecek 		voice->trigblk = 0;
   1262   1.7  jdolecek 		voice->blkmod = 0;
   1263   1.7  jdolecek 		voice->inth = NULL;
   1264   1.7  jdolecek 		voice->inthparam = NULL;
   1265   1.7  jdolecek 	}
   1266   1.1  jdolecek 	voice->use = use;
   1267   1.1  jdolecek 
   1268   1.1  jdolecek 	s = splaudio();
   1269   1.1  jdolecek 	LIST_INSERT_HEAD((&sc->voices), voice, next);
   1270   1.1  jdolecek 	splx(s);
   1271   1.1  jdolecek 
   1272   1.1  jdolecek 	return (voice);
   1273   1.1  jdolecek }
   1274   1.1  jdolecek 
   1275   1.1  jdolecek static void
   1276   1.1  jdolecek emuxki_voice_delete(struct emuxki_voice *voice)
   1277   1.1  jdolecek {
   1278   1.7  jdolecek 	struct emuxki_softc *sc = voice->sc;
   1279   1.7  jdolecek 	struct emuxki_voice *lvoice;
   1280   1.7  jdolecek 	int s;
   1281   1.1  jdolecek 
   1282   1.1  jdolecek 	if (voice->state & EMU_VOICE_STATE_STARTED)
   1283   1.1  jdolecek 		emuxki_voice_halt(voice);
   1284   1.1  jdolecek 
   1285   1.1  jdolecek 	s = splaudio();
   1286   1.1  jdolecek 	LIST_REMOVE(voice, next);
   1287   1.7  jdolecek 	lvoice = sc->lvoice;
   1288   1.7  jdolecek 	sc->lvoice = voice;
   1289   1.1  jdolecek 	splx(s);
   1290   1.1  jdolecek 
   1291   1.7  jdolecek 	if (lvoice) {
   1292   1.7  jdolecek 		emuxki_voice_dataloc_destroy(lvoice);
   1293   1.7  jdolecek 		free(lvoice, M_DEVBUF);
   1294   1.7  jdolecek 	}
   1295   1.1  jdolecek }
   1296   1.1  jdolecek 
   1297   1.1  jdolecek static int
   1298   1.1  jdolecek emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo)
   1299   1.1  jdolecek {
   1300   1.1  jdolecek 	int	error;
   1301   1.1  jdolecek 	struct emuxki_chanparms_fxsend fxsend;
   1302   1.1  jdolecek 
   1303   1.1  jdolecek 	emuxki_voice_dataloc_destroy(voice);
   1304   1.1  jdolecek 	voice->stereo = stereo;
   1305   1.1  jdolecek 	if ((error = emuxki_voice_dataloc_create(voice)))
   1306   1.1  jdolecek 	  return (error);
   1307   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1308   1.1  jdolecek 		fxsend.a.dest = 0x0;
   1309   1.1  jdolecek 		fxsend.b.dest = 0x1;
   1310   1.1  jdolecek 		fxsend.c.dest = 0x2;
   1311   1.1  jdolecek 		fxsend.d.dest = 0x3;
   1312   1.1  jdolecek 		if (voice->stereo) {
   1313   1.7  jdolecek 			fxsend.a.level = fxsend.c.level = 0xc0;
   1314   1.1  jdolecek 			fxsend.b.level = fxsend.d.level = 0x00;
   1315   1.1  jdolecek 			emuxki_channel_set_fxsend(voice->dataloc.chan[0],
   1316   1.1  jdolecek 						   &fxsend);
   1317   1.1  jdolecek 			fxsend.a.level = fxsend.c.level = 0x00;
   1318   1.7  jdolecek 			fxsend.b.level = fxsend.d.level = 0xc0;
   1319   1.1  jdolecek 			emuxki_channel_set_fxsend(voice->dataloc.chan[1],
   1320   1.1  jdolecek 						   &fxsend);
   1321   1.1  jdolecek 		} /* No else : default is good for mono */
   1322   1.1  jdolecek 	}
   1323   1.1  jdolecek 	return (0);
   1324   1.1  jdolecek }
   1325   1.1  jdolecek 
   1326   1.1  jdolecek static int
   1327   1.1  jdolecek emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate)
   1328   1.1  jdolecek {
   1329   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1330   1.1  jdolecek 		if ((srate < 4000) || (srate > 48000))
   1331   1.1  jdolecek 			return (EINVAL);
   1332   1.1  jdolecek 		voice->sample_rate = srate;
   1333   1.1  jdolecek 		emuxki_channel_set_srate(voice->dataloc.chan[0], srate);
   1334   1.1  jdolecek 		if (voice->stereo)
   1335   1.1  jdolecek 			emuxki_channel_set_srate(voice->dataloc.chan[1],
   1336   1.1  jdolecek 						  srate);
   1337   1.1  jdolecek 	} else {
   1338   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1339   1.1  jdolecek 		printf("Recording voice set_srate not implemented\n");
   1340   1.1  jdolecek #endif
   1341   1.1  jdolecek 		return (EINVAL);
   1342   1.1  jdolecek 	}
   1343   1.1  jdolecek 	return (0);
   1344   1.1  jdolecek }
   1345   1.1  jdolecek 
   1346   1.1  jdolecek static int
   1347   1.1  jdolecek emuxki_voice_set_audioparms(struct emuxki_voice *voice, u_int8_t stereo,
   1348   1.1  jdolecek 			     u_int8_t b16, u_int32_t srate)
   1349   1.1  jdolecek {
   1350   1.1  jdolecek 	int             error;
   1351   1.1  jdolecek 
   1352   1.1  jdolecek 	if (voice->stereo == stereo && voice->b16 == b16 &&
   1353   1.1  jdolecek 	    voice->sample_rate == srate)
   1354   1.1  jdolecek 		return (0);
   1355   1.1  jdolecek 
   1356   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1357   1.1  jdolecek 	printf("Setting %s voice params : %s, %u bits, %u hz\n",
   1358   1.1  jdolecek 	       (voice->use & EMU_VOICE_USE_PLAY) ? "play" : "record",
   1359   1.1  jdolecek 	       stereo ? "stereo" : "mono", (b16 + 1) * 8, srate);
   1360   1.1  jdolecek #endif
   1361   1.1  jdolecek 
   1362   1.1  jdolecek 	if (voice->stereo != stereo) {
   1363   1.1  jdolecek 		if ((error = emuxki_voice_set_stereo(voice, stereo)))
   1364   1.1  jdolecek 			return (error);
   1365   1.1  jdolecek 	 }
   1366   1.1  jdolecek 	voice->b16 = b16;
   1367   1.1  jdolecek 	if (voice->sample_rate != srate)
   1368   1.1  jdolecek 		emuxki_voice_set_srate(voice, srate);
   1369   1.1  jdolecek 	return (0);
   1370   1.1  jdolecek }
   1371   1.1  jdolecek 
   1372   1.1  jdolecek /* voice audio parms (see just before) must be set prior to this */
   1373   1.1  jdolecek static int
   1374   1.1  jdolecek emuxki_voice_set_bufparms(struct emuxki_voice *voice, void *ptr,
   1375   1.1  jdolecek 			   u_int32_t bufsize, u_int16_t blksize)
   1376   1.1  jdolecek {
   1377   1.1  jdolecek 	struct emuxki_mem *mem;
   1378   1.1  jdolecek 	struct emuxki_channel **chan;
   1379   1.1  jdolecek 	u_int32_t start, end;
   1380   1.1  jdolecek 	u_int8_t sample_size;
   1381   1.1  jdolecek 	int error = EFAULT;
   1382   1.1  jdolecek 
   1383   1.1  jdolecek 	LIST_FOREACH(mem, &voice->sc->mem, next) {
   1384   1.1  jdolecek 		if (KERNADDR(mem->dmamem) != ptr)
   1385   1.1  jdolecek 			continue;
   1386   1.1  jdolecek 
   1387   1.1  jdolecek 		voice->buffer = mem;
   1388   1.1  jdolecek 		sample_size = (voice->b16 + 1) * (voice->stereo + 1);
   1389   1.1  jdolecek 		voice->blksize = blksize / sample_size;
   1390   1.1  jdolecek 		voice->trigblk = 0;	/* This shouldn't be needed */
   1391   1.1  jdolecek 		voice->blkmod = bufsize / blksize;
   1392   1.1  jdolecek 		if (bufsize % blksize) 	  /* This should not happen */
   1393   1.1  jdolecek 			voice->blkmod++;
   1394   1.1  jdolecek 		error = 0;
   1395   1.1  jdolecek 
   1396   1.1  jdolecek 		if (voice->use & EMU_VOICE_USE_PLAY) {
   1397   1.1  jdolecek 			chan = voice->dataloc.chan;
   1398   1.1  jdolecek 			start = mem->ptbidx << 12;
   1399   1.1  jdolecek 			end = start + bufsize / sample_size;
   1400   1.1  jdolecek 			emuxki_channel_set_bufparms(chan[0],
   1401   1.1  jdolecek 						     start, end);
   1402   1.1  jdolecek 			if (voice->stereo)
   1403   1.1  jdolecek 				emuxki_channel_set_bufparms(chan[1],
   1404   1.1  jdolecek 				     start, end);
   1405   1.1  jdolecek 			voice->timerate = (u_int32_t) 48000 *
   1406   1.1  jdolecek 			                voice->blksize / voice->sample_rate;
   1407   1.1  jdolecek 			if (voice->timerate < 5)
   1408   1.1  jdolecek 				error = EINVAL;
   1409   1.1  jdolecek 		} else {
   1410   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1411   1.1  jdolecek 			printf("Rec voice set bufparms not implemented\n");
   1412   1.1  jdolecek #endif
   1413   1.1  jdolecek 			error = ENODEV;
   1414   1.1  jdolecek 		}
   1415   1.1  jdolecek 
   1416   1.1  jdolecek 		break;
   1417   1.1  jdolecek 	}
   1418   1.1  jdolecek 
   1419   1.1  jdolecek 	return (error);
   1420   1.1  jdolecek }
   1421   1.1  jdolecek 
   1422   1.1  jdolecek static void
   1423   1.1  jdolecek emuxki_voice_commit_parms(struct emuxki_voice *voice)
   1424   1.1  jdolecek {
   1425   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1426   1.1  jdolecek 		emuxki_channel_commit_parms(voice->dataloc.chan[0]);
   1427   1.1  jdolecek 		if (voice->stereo)
   1428   1.1  jdolecek 			emuxki_channel_commit_parms(voice->dataloc.chan[1]);
   1429   1.1  jdolecek 	}
   1430   1.1  jdolecek }
   1431   1.1  jdolecek 
   1432   1.1  jdolecek static u_int32_t
   1433   1.1  jdolecek emuxki_voice_curaddr(struct emuxki_voice *voice)
   1434   1.1  jdolecek {
   1435   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY)
   1436   1.1  jdolecek 		return (emuxki_read(voice->sc,
   1437   1.1  jdolecek 				     voice->dataloc.chan[0]->num,
   1438   1.1  jdolecek 				     EMU_CHAN_CCCA_CURRADDR) -
   1439   1.1  jdolecek 			voice->dataloc.chan[0]->loop.start);
   1440   1.1  jdolecek 	return (0);
   1441   1.1  jdolecek }
   1442   1.1  jdolecek 
   1443   1.1  jdolecek static void
   1444   1.1  jdolecek emuxki_resched_timer(struct emuxki_softc *sc)
   1445   1.1  jdolecek {
   1446   1.1  jdolecek 	struct emuxki_voice *voice;
   1447   1.1  jdolecek 	u_int16_t       timerate = 1024;
   1448   1.1  jdolecek 	u_int8_t	active = 0;
   1449   1.1  jdolecek 	int s;
   1450   1.1  jdolecek 
   1451   1.1  jdolecek 	s = splaudio();
   1452   1.1  jdolecek 	LIST_FOREACH(voice, &sc->voices, next) {
   1453   1.1  jdolecek 		if ((voice->use & EMU_VOICE_USE_PLAY) == 0 ||
   1454   1.1  jdolecek 		    (voice->state & EMU_VOICE_STATE_STARTED) == 0)
   1455   1.1  jdolecek 			continue;
   1456   1.1  jdolecek 		active = 1;
   1457   1.1  jdolecek 		if (voice->timerate < timerate)
   1458   1.1  jdolecek 			timerate = voice->timerate;
   1459   1.1  jdolecek 	}
   1460   1.1  jdolecek 
   1461   1.1  jdolecek 	if (timerate & ~EMU_TIMER_RATE_MASK)
   1462   1.1  jdolecek 		timerate = 0;
   1463  1.14      tron 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_TIMER, timerate);
   1464   1.1  jdolecek 	if (!active && (sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
   1465   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
   1466   1.1  jdolecek 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) &
   1467   1.1  jdolecek 			~EMU_INTE_INTERTIMERENB);
   1468   1.1  jdolecek 		sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
   1469   1.1  jdolecek 	} else if (active && !(sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
   1470   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
   1471   1.1  jdolecek 			bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
   1472   1.1  jdolecek 			EMU_INTE_INTERTIMERENB);
   1473   1.1  jdolecek 		sc->timerstate |= EMU_TIMER_STATE_ENABLED;
   1474   1.1  jdolecek 	}
   1475   1.1  jdolecek 	splx(s);
   1476   1.1  jdolecek }
   1477   1.1  jdolecek 
   1478   1.1  jdolecek static void
   1479   1.1  jdolecek emuxki_voice_start(struct emuxki_voice *voice,
   1480   1.1  jdolecek 		    void (*inth) (void *), void *inthparam)
   1481   1.1  jdolecek {
   1482   1.1  jdolecek 	voice->inth = inth;
   1483   1.1  jdolecek 	voice->inthparam = inthparam;
   1484   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1485   1.1  jdolecek 		voice->trigblk = 1;
   1486   1.1  jdolecek 		emuxki_channel_start(voice->dataloc.chan[0]);
   1487   1.1  jdolecek 		if (voice->stereo)
   1488   1.1  jdolecek 			emuxki_channel_start(voice->dataloc.chan[1]);
   1489   1.1  jdolecek 	}
   1490   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1491   1.1  jdolecek 	else
   1492   1.1  jdolecek 		printf("Recording voice start not implemented\n");
   1493   1.1  jdolecek #endif
   1494   1.1  jdolecek 	voice->state |= EMU_VOICE_STATE_STARTED;
   1495   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY)
   1496   1.1  jdolecek 		emuxki_resched_timer(voice->sc);
   1497   1.1  jdolecek }
   1498   1.1  jdolecek 
   1499   1.1  jdolecek static void
   1500   1.1  jdolecek emuxki_voice_halt(struct emuxki_voice *voice)
   1501   1.1  jdolecek {
   1502   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY) {
   1503   1.1  jdolecek 		emuxki_channel_stop(voice->dataloc.chan[0]);
   1504   1.1  jdolecek 		if (voice->stereo)
   1505   1.1  jdolecek 			emuxki_channel_stop(voice->dataloc.chan[1]);
   1506   1.1  jdolecek 	}
   1507   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1508   1.1  jdolecek 	else
   1509   1.1  jdolecek 		printf("Recording voice halt not implemented\n");
   1510   1.1  jdolecek #endif
   1511   1.1  jdolecek 	voice->state &= ~EMU_VOICE_STATE_STARTED;
   1512   1.1  jdolecek 	if (voice->use & EMU_VOICE_USE_PLAY)
   1513   1.1  jdolecek 		emuxki_resched_timer(voice->sc);
   1514   1.1  jdolecek }
   1515   1.1  jdolecek 
   1516   1.1  jdolecek /*
   1517   1.1  jdolecek  * The interrupt handler
   1518   1.1  jdolecek  */
   1519   1.1  jdolecek static int
   1520   1.1  jdolecek emuxki_intr(void *arg)
   1521   1.1  jdolecek {
   1522   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   1523   1.1  jdolecek 	u_int32_t       ipr, curblk;
   1524   1.1  jdolecek 	struct emuxki_voice *voice;
   1525  1.13  jdolecek 	int claim = 0;
   1526   1.1  jdolecek 
   1527   1.1  jdolecek 	while ((ipr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_IPR))) {
   1528   1.1  jdolecek 		if (ipr & EMU_IPR_INTERVALTIMER) {
   1529   1.1  jdolecek 			LIST_FOREACH(voice, &sc->voices, next) {
   1530   1.1  jdolecek 				if ((voice->use & EMU_VOICE_USE_PLAY)==0 ||
   1531   1.1  jdolecek 				    (voice->state &
   1532   1.1  jdolecek 				      EMU_VOICE_STATE_STARTED) == 0)
   1533   1.1  jdolecek 					continue;
   1534   1.1  jdolecek 
   1535   1.1  jdolecek 				curblk = emuxki_voice_curaddr(voice) /
   1536   1.1  jdolecek 				       voice->blksize;
   1537   1.1  jdolecek 				if (curblk == voice->trigblk) {
   1538   1.1  jdolecek 					voice->inth(voice->inthparam);
   1539   1.1  jdolecek 					voice->trigblk++;
   1540   1.1  jdolecek 					voice->trigblk %= voice->blkmod;
   1541   1.1  jdolecek 				}
   1542   1.1  jdolecek 			}
   1543   1.1  jdolecek 		}
   1544   1.1  jdolecek 
   1545   1.1  jdolecek 		/* Got interrupt */
   1546   1.1  jdolecek 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_IPR, ipr);
   1547  1.13  jdolecek 
   1548  1.13  jdolecek 		claim = 1;
   1549   1.1  jdolecek 	}
   1550   1.1  jdolecek 
   1551  1.13  jdolecek 	return (claim);
   1552   1.1  jdolecek }
   1553   1.1  jdolecek 
   1554   1.1  jdolecek 
   1555   1.1  jdolecek /*
   1556   1.1  jdolecek  * Audio Architecture callbacks
   1557   1.1  jdolecek  */
   1558   1.1  jdolecek 
   1559   1.1  jdolecek static int
   1560   1.1  jdolecek emuxki_open(void *addr, int flags)
   1561   1.1  jdolecek {
   1562   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1563   1.1  jdolecek 
   1564   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1565   1.1  jdolecek 	printf("%s: emuxki_open called\n", sc->sc_dev.dv_xname);
   1566   1.1  jdolecek #endif
   1567   1.1  jdolecek 
   1568   1.1  jdolecek 	/*
   1569   1.1  jdolecek 	 * Multiple voice support would be added as soon as I find a way to
   1570   1.1  jdolecek 	 * trick the audio arch into supporting multiple voices.
   1571   1.1  jdolecek 	 * Or I might integrate a modified audio arch supporting
   1572   1.1  jdolecek 	 * multiple voices.
   1573   1.1  jdolecek 	 */
   1574   1.1  jdolecek 
   1575   1.1  jdolecek 	/*
   1576   1.1  jdolecek 	 * I did this because i have problems identifying the selected
   1577   1.1  jdolecek 	 * recording source(s) which is necessary when setting recording
   1578   1.1  jdolecek 	 * params This will be adressed very soon
   1579   1.1  jdolecek 	 */
   1580   1.1  jdolecek 	if (flags & AUOPEN_READ)
   1581   1.1  jdolecek 		return (EOPNOTSUPP);
   1582   1.1  jdolecek 
   1583   1.1  jdolecek 	if (flags & AUOPEN_WRITE) {
   1584   1.1  jdolecek 		sc->pvoice = emuxki_voice_new(sc, EMU_VOICE_USE_PLAY);
   1585   1.1  jdolecek 		if (sc->pvoice == NULL) {
   1586   1.8  jdolecek 			if (sc->rvoice) {
   1587   1.1  jdolecek 				emuxki_voice_delete(sc->rvoice);
   1588   1.8  jdolecek 				sc->rvoice = NULL;
   1589   1.8  jdolecek 			}
   1590   1.1  jdolecek 			return (EBUSY);
   1591   1.1  jdolecek 		}
   1592   1.1  jdolecek 	}
   1593   1.1  jdolecek 
   1594   1.1  jdolecek 	return (0);
   1595   1.1  jdolecek }
   1596   1.1  jdolecek 
   1597   1.1  jdolecek static void
   1598   1.1  jdolecek emuxki_close(void *addr)
   1599   1.1  jdolecek {
   1600   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1601   1.1  jdolecek 
   1602   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1603   1.1  jdolecek 	printf("%s: emu10K1_close called\n", sc->sc_dev.dv_xname);
   1604   1.1  jdolecek #endif
   1605   1.1  jdolecek 
   1606   1.1  jdolecek 	/* No multiple voice support for now */
   1607   1.8  jdolecek 	if (sc->rvoice != NULL) {
   1608   1.1  jdolecek 		emuxki_voice_delete(sc->rvoice);
   1609   1.8  jdolecek 		sc->rvoice = NULL;
   1610   1.8  jdolecek 	}
   1611   1.8  jdolecek 	if (sc->pvoice != NULL) {
   1612   1.1  jdolecek 		emuxki_voice_delete(sc->pvoice);
   1613   1.8  jdolecek 		sc->pvoice = NULL;
   1614   1.8  jdolecek 	}
   1615   1.1  jdolecek }
   1616   1.1  jdolecek 
   1617   1.1  jdolecek static int
   1618   1.1  jdolecek emuxki_query_encoding(void *addr, struct audio_encoding *fp)
   1619   1.1  jdolecek {
   1620   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1621   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1622   1.1  jdolecek 
   1623   1.1  jdolecek 	printf("%s: emuxki_query_encoding called\n", sc->sc_dev.dv_xname);
   1624   1.1  jdolecek #endif
   1625   1.1  jdolecek 
   1626   1.1  jdolecek 	switch (fp->index) {
   1627   1.1  jdolecek 	case 0:
   1628   1.1  jdolecek 		strcpy(fp->name, AudioEulinear);
   1629   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR;
   1630   1.1  jdolecek 		fp->precision = 8;
   1631   1.1  jdolecek 		fp->flags = 0;
   1632   1.1  jdolecek 		break;
   1633   1.1  jdolecek 	case 1:
   1634   1.1  jdolecek 		strcpy(fp->name, AudioEmulaw);
   1635   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULAW;
   1636   1.1  jdolecek 		fp->precision = 8;
   1637   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   1638   1.1  jdolecek 		break;
   1639   1.1  jdolecek 	case 2:
   1640   1.1  jdolecek 		strcpy(fp->name, AudioEalaw);
   1641   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ALAW;
   1642   1.1  jdolecek 		fp->precision = 8;
   1643   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   1644   1.1  jdolecek 		break;
   1645   1.1  jdolecek 	case 3:
   1646   1.1  jdolecek 		strcpy(fp->name, AudioEslinear);
   1647   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR;
   1648   1.1  jdolecek 		fp->precision = 8;
   1649   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   1650   1.1  jdolecek 		break;
   1651   1.1  jdolecek 	case 4:
   1652   1.1  jdolecek 		strcpy(fp->name, AudioEslinear_le);
   1653   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
   1654   1.1  jdolecek 		fp->precision = 16;
   1655   1.1  jdolecek 		fp->flags = 0;
   1656   1.1  jdolecek 		break;
   1657   1.1  jdolecek 	case 5:
   1658   1.1  jdolecek 		strcpy(fp->name, AudioEulinear_le);
   1659   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
   1660   1.1  jdolecek 		fp->precision = 16;
   1661   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   1662   1.1  jdolecek 		break;
   1663   1.1  jdolecek 	case 6:
   1664   1.1  jdolecek 		strcpy(fp->name, AudioEslinear_be);
   1665   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
   1666   1.1  jdolecek 		fp->precision = 16;
   1667   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   1668   1.1  jdolecek 		break;
   1669   1.1  jdolecek 	case 7:
   1670   1.1  jdolecek 		strcpy(fp->name, AudioEulinear_be);
   1671   1.1  jdolecek 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
   1672   1.1  jdolecek 		fp->precision = 16;
   1673   1.1  jdolecek 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
   1674   1.1  jdolecek 		break;
   1675   1.1  jdolecek 	default:
   1676   1.1  jdolecek 		return (EINVAL);
   1677   1.1  jdolecek 	}
   1678   1.1  jdolecek 	return (0);
   1679   1.1  jdolecek }
   1680   1.1  jdolecek 
   1681   1.1  jdolecek static int
   1682   1.1  jdolecek emuxki_set_vparms(struct emuxki_voice *voice, struct audio_params *p)
   1683   1.1  jdolecek {
   1684   1.1  jdolecek 	u_int8_t        b16, mode;
   1685   1.1  jdolecek 
   1686   1.1  jdolecek 	mode = (voice->use & EMU_VOICE_USE_PLAY) ?
   1687   1.1  jdolecek 		AUMODE_PLAY : AUMODE_RECORD;
   1688   1.1  jdolecek 	p->factor = 1;
   1689   1.1  jdolecek 	p->sw_code = NULL;
   1690   1.1  jdolecek 	if (p->channels != 1 && p->channels != 2)
   1691   1.1  jdolecek 		return (EINVAL);/* Will change when streams come in use */
   1692   1.1  jdolecek 
   1693   1.1  jdolecek 	switch (p->encoding) {
   1694   1.1  jdolecek 	case AUDIO_ENCODING_ULAW:
   1695   1.1  jdolecek 		if (mode == AUMODE_PLAY) {
   1696   1.1  jdolecek 			p->factor = 2;
   1697   1.1  jdolecek 			p->sw_code = mulaw_to_slinear16_le;
   1698   1.1  jdolecek 			b16 = 1;
   1699   1.1  jdolecek 		} else {
   1700   1.1  jdolecek 			p->sw_code = ulinear8_to_mulaw;
   1701   1.1  jdolecek 			b16 = 0;
   1702   1.1  jdolecek 		}
   1703   1.1  jdolecek 		break;
   1704   1.1  jdolecek 
   1705   1.1  jdolecek 	case AUDIO_ENCODING_ALAW:
   1706   1.1  jdolecek 		if (mode == AUMODE_PLAY) {
   1707   1.1  jdolecek 			p->factor = 2;
   1708   1.1  jdolecek 			p->sw_code = alaw_to_slinear16_le;
   1709   1.1  jdolecek 			b16 = 1;
   1710   1.1  jdolecek 		} else {
   1711   1.1  jdolecek 			p->sw_code = ulinear8_to_alaw;
   1712   1.1  jdolecek 			b16 = 0;
   1713   1.1  jdolecek 		}
   1714   1.1  jdolecek 		break;
   1715   1.1  jdolecek 
   1716   1.1  jdolecek 	case AUDIO_ENCODING_SLINEAR_LE:
   1717   1.1  jdolecek 		if (p->precision == 8)
   1718   1.1  jdolecek 			p->sw_code = change_sign8;
   1719   1.1  jdolecek 		b16 = (p->precision == 16);
   1720   1.1  jdolecek 		break;
   1721   1.1  jdolecek 
   1722   1.1  jdolecek 	case AUDIO_ENCODING_ULINEAR_LE:
   1723   1.1  jdolecek 		if (p->precision == 16)
   1724   1.1  jdolecek 			p->sw_code = change_sign16_le;
   1725   1.1  jdolecek 		b16 = (p->precision == 16);
   1726   1.1  jdolecek 		break;
   1727   1.1  jdolecek 
   1728   1.1  jdolecek 	case AUDIO_ENCODING_SLINEAR_BE:
   1729   1.1  jdolecek 		if (p->precision == 16)
   1730   1.1  jdolecek 			p->sw_code = swap_bytes;
   1731   1.1  jdolecek 		else
   1732   1.1  jdolecek 			p->sw_code = change_sign8;
   1733   1.1  jdolecek 		b16 = (p->precision == 16);
   1734   1.1  jdolecek 		break;
   1735   1.1  jdolecek 
   1736   1.1  jdolecek 	case AUDIO_ENCODING_ULINEAR_BE:
   1737   1.1  jdolecek 		if (p->precision == 16) {
   1738   1.1  jdolecek 			if (mode == AUMODE_PLAY)
   1739   1.1  jdolecek 				p->sw_code = swap_bytes_change_sign16_le;
   1740   1.1  jdolecek 			else
   1741   1.1  jdolecek 				p->sw_code = change_sign16_swap_bytes_le;
   1742   1.1  jdolecek 		}
   1743   1.1  jdolecek 		b16 = (p->precision == 16);
   1744   1.1  jdolecek 		break;
   1745   1.1  jdolecek 
   1746   1.1  jdolecek 	default:
   1747   1.1  jdolecek 		return (EINVAL);
   1748   1.1  jdolecek 	}
   1749   1.1  jdolecek 
   1750   1.1  jdolecek 	return (emuxki_voice_set_audioparms(voice, p->channels == 2,
   1751   1.1  jdolecek 				     b16, p->sample_rate));
   1752   1.1  jdolecek }
   1753   1.1  jdolecek 
   1754   1.1  jdolecek static int
   1755   1.1  jdolecek emuxki_set_params(void *addr, int setmode, int usemode,
   1756   1.1  jdolecek 		   struct audio_params *play, struct audio_params *rec)
   1757   1.1  jdolecek {
   1758   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1759   1.1  jdolecek 	int             mode, error;
   1760   1.1  jdolecek 	struct audio_params *p;
   1761   1.8  jdolecek 	struct emuxki_voice *v;
   1762   1.1  jdolecek 
   1763   1.1  jdolecek 	for (mode = AUMODE_RECORD; mode != -1;
   1764   1.1  jdolecek 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
   1765   1.1  jdolecek 		if ((usemode & setmode & mode) == 0)
   1766   1.1  jdolecek 			continue;
   1767   1.1  jdolecek 
   1768   1.8  jdolecek 		if (mode == AUMODE_PLAY) {
   1769   1.8  jdolecek 			p = play;
   1770   1.8  jdolecek 			v = sc->pvoice;
   1771   1.8  jdolecek 		} else {
   1772   1.8  jdolecek 			p = rec;
   1773   1.8  jdolecek 			v = sc->rvoice;
   1774   1.8  jdolecek 		}
   1775   1.8  jdolecek 
   1776   1.8  jdolecek 		if (v == NULL) {
   1777   1.8  jdolecek 			continue;
   1778   1.8  jdolecek 		}
   1779   1.1  jdolecek 
   1780   1.1  jdolecek 		/* No multiple voice support for now */
   1781   1.8  jdolecek 		if ((error = emuxki_set_vparms(v, p)))
   1782   1.1  jdolecek 			return (error);
   1783   1.1  jdolecek 	}
   1784   1.1  jdolecek 
   1785   1.1  jdolecek 	return (0);
   1786   1.1  jdolecek }
   1787   1.1  jdolecek 
   1788   1.1  jdolecek static int
   1789   1.1  jdolecek emuxki_halt_output(void *addr)
   1790   1.1  jdolecek {
   1791   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1792   1.1  jdolecek 
   1793   1.1  jdolecek 	/* No multiple voice support for now */
   1794   1.1  jdolecek 	if (sc->pvoice == NULL)
   1795   1.1  jdolecek 		return (ENXIO);
   1796   1.1  jdolecek 
   1797   1.1  jdolecek 	emuxki_voice_halt(sc->pvoice);
   1798   1.1  jdolecek 	return (0);
   1799   1.1  jdolecek }
   1800   1.1  jdolecek 
   1801   1.1  jdolecek static int
   1802   1.1  jdolecek emuxki_halt_input(void *addr)
   1803   1.1  jdolecek {
   1804   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1805   1.1  jdolecek 
   1806   1.1  jdolecek #ifdef EMUXKI_DEBUG
   1807   1.1  jdolecek 	printf("%s: emuxki_halt_input called\n", sc->sc_dev.dv_xname);
   1808   1.1  jdolecek #endif
   1809   1.1  jdolecek 
   1810   1.1  jdolecek 	/* No multiple voice support for now */
   1811   1.1  jdolecek 	if (sc->rvoice == NULL)
   1812   1.1  jdolecek 		return (ENXIO);
   1813   1.1  jdolecek 	emuxki_voice_halt(sc->rvoice);
   1814   1.1  jdolecek 	return (0);
   1815   1.1  jdolecek }
   1816   1.1  jdolecek 
   1817   1.1  jdolecek static int
   1818   1.1  jdolecek emuxki_getdev(void *addr, struct audio_device *dev)
   1819   1.1  jdolecek {
   1820   1.1  jdolecek 	strncpy(dev->name, "Creative EMU10k1", sizeof(dev->name));
   1821   1.1  jdolecek 	strcpy(dev->version, "");
   1822   1.1  jdolecek 	strncpy(dev->config, "emuxki", sizeof(dev->config));
   1823   1.1  jdolecek 
   1824   1.1  jdolecek 	return (0);
   1825   1.1  jdolecek }
   1826   1.1  jdolecek 
   1827   1.1  jdolecek static int
   1828   1.1  jdolecek emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
   1829   1.1  jdolecek {
   1830   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1831   1.1  jdolecek 
   1832   1.1  jdolecek 	return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
   1833   1.1  jdolecek }
   1834   1.1  jdolecek 
   1835   1.1  jdolecek static int
   1836   1.1  jdolecek emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
   1837   1.1  jdolecek {
   1838   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1839   1.1  jdolecek 
   1840   1.1  jdolecek 	return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
   1841   1.1  jdolecek }
   1842   1.1  jdolecek 
   1843   1.1  jdolecek static int
   1844   1.1  jdolecek emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
   1845   1.1  jdolecek {
   1846   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1847   1.1  jdolecek 
   1848   1.1  jdolecek 	return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
   1849   1.1  jdolecek }
   1850   1.1  jdolecek 
   1851   1.1  jdolecek static void *
   1852   1.1  jdolecek emuxki_allocm(void *addr, int direction, size_t size, int type, int flags)
   1853   1.1  jdolecek {
   1854   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1855   1.1  jdolecek 
   1856   1.1  jdolecek 	if (direction == AUMODE_PLAY)
   1857   1.1  jdolecek 		return emuxki_pmem_alloc(sc, size, type, flags);
   1858   1.1  jdolecek 	else
   1859   1.1  jdolecek 		return emuxki_rmem_alloc(sc, size, type, flags);
   1860   1.1  jdolecek }
   1861   1.1  jdolecek 
   1862   1.1  jdolecek static void
   1863   1.1  jdolecek emuxki_freem(void *addr, void *ptr, int type)
   1864   1.1  jdolecek {
   1865   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1866   1.1  jdolecek 	int             i, s;
   1867   1.1  jdolecek 	struct emuxki_mem *mem;
   1868   1.1  jdolecek 	size_t          numblocks;
   1869   1.1  jdolecek 	u_int32_t      *ptb, silentpage;
   1870   1.1  jdolecek 
   1871   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
   1872   1.1  jdolecek 	silentpage = DMAADDR(sc->silentpage) << 1;
   1873   1.1  jdolecek 	LIST_FOREACH(mem, &sc->mem, next) {
   1874   1.1  jdolecek 		if (KERNADDR(mem->dmamem) != ptr)
   1875   1.1  jdolecek 			continue;
   1876   1.1  jdolecek 
   1877   1.1  jdolecek 		s = splaudio();
   1878   1.1  jdolecek 		if (mem->ptbidx != EMU_RMEM) {
   1879   1.1  jdolecek 			numblocks = DMASIZE(mem->dmamem) / EMU_PTESIZE;
   1880   1.1  jdolecek 			if (DMASIZE(mem->dmamem) % EMU_PTESIZE)
   1881   1.1  jdolecek 				numblocks++;
   1882   1.1  jdolecek 			for (i = 0; i < numblocks; i++)
   1883   1.1  jdolecek 				ptb[mem->ptbidx + i] =
   1884   1.1  jdolecek 					silentpage | (mem->ptbidx + i);
   1885   1.1  jdolecek 		}
   1886   1.1  jdolecek 		LIST_REMOVE(mem, next);
   1887   1.1  jdolecek 		splx(s);
   1888   1.1  jdolecek 
   1889   1.1  jdolecek 		emuxki_mem_delete(mem, type);
   1890   1.1  jdolecek 		break;
   1891   1.1  jdolecek 	}
   1892   1.1  jdolecek }
   1893   1.1  jdolecek 
   1894   1.1  jdolecek static size_t
   1895   1.1  jdolecek emuxki_round_buffersize(void *addr, int direction, size_t bsize)
   1896   1.1  jdolecek {
   1897   1.1  jdolecek 	static const int recbuf_sz[] = {
   1898   1.1  jdolecek 		0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
   1899   1.1  jdolecek 		2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
   1900   1.1  jdolecek 		12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
   1901   1.1  jdolecek 		57344, 65536
   1902   1.1  jdolecek 	};
   1903   1.1  jdolecek 
   1904   1.1  jdolecek 	if (direction == AUMODE_PLAY) {
   1905   1.1  jdolecek 		if (bsize < EMU_PTESIZE)
   1906   1.1  jdolecek 			bsize = EMU_PTESIZE;
   1907   1.1  jdolecek 		else if (bsize > (EMU_PTESIZE * EMU_MAXPTE))
   1908   1.1  jdolecek 			bsize = EMU_PTESIZE * EMU_MAXPTE;
   1909   1.1  jdolecek 		/* Would be better if set to max available */
   1910   1.1  jdolecek 		else if (bsize % EMU_PTESIZE)
   1911   1.1  jdolecek 			bsize = bsize -
   1912   1.1  jdolecek 				(bsize % EMU_PTESIZE) +
   1913   1.1  jdolecek 				EMU_PTESIZE;
   1914   1.1  jdolecek 	} else {
   1915   1.1  jdolecek 		int idx;
   1916   1.1  jdolecek 
   1917   1.1  jdolecek 		/* find nearest lower recbuf size */
   1918   1.1  jdolecek 		for(idx=32; --idx >= 0; ) {
   1919   1.1  jdolecek 			if (bsize >= recbuf_sz[idx]) {
   1920   1.1  jdolecek 				bsize = recbuf_sz[idx];
   1921   1.1  jdolecek 				break;
   1922   1.1  jdolecek 			}
   1923   1.1  jdolecek 		}
   1924   1.1  jdolecek 
   1925   1.1  jdolecek 		if (bsize == 0)
   1926   1.1  jdolecek 			bsize = 384;
   1927   1.1  jdolecek 	}
   1928   1.1  jdolecek 
   1929   1.1  jdolecek 	return (bsize);
   1930   1.1  jdolecek }
   1931   1.1  jdolecek 
   1932   1.1  jdolecek static paddr_t
   1933   1.1  jdolecek emuxki_mappage(void *addr, void *ptr, off_t off, int prot)
   1934   1.1  jdolecek {
   1935   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1936   1.1  jdolecek 	struct emuxki_mem *mem;
   1937   1.1  jdolecek 	u_int32_t      *ptb;
   1938   1.1  jdolecek 
   1939   1.1  jdolecek 	ptb = KERNADDR(sc->ptb);
   1940   1.1  jdolecek 	LIST_FOREACH(mem, &sc->mem, next) {
   1941   1.1  jdolecek 		if (KERNADDR(mem->dmamem) == ptr) {
   1942   1.1  jdolecek 			struct dmamem *dm = mem->dmamem;
   1943   1.1  jdolecek 
   1944   1.1  jdolecek 			return bus_dmamem_mmap(dm->dmat, dm->segs, dm->nsegs,
   1945   1.1  jdolecek 			       off, prot, BUS_DMA_WAITOK);
   1946   1.1  jdolecek 		}
   1947   1.1  jdolecek 	}
   1948   1.1  jdolecek 
   1949   1.1  jdolecek 	return (-1);
   1950   1.1  jdolecek }
   1951   1.1  jdolecek 
   1952   1.1  jdolecek static int
   1953   1.1  jdolecek emuxki_get_props(void *addr)
   1954   1.1  jdolecek {
   1955   1.1  jdolecek 	return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
   1956   1.1  jdolecek 		AUDIO_PROP_FULLDUPLEX);
   1957   1.1  jdolecek }
   1958   1.1  jdolecek 
   1959   1.1  jdolecek static int
   1960   1.1  jdolecek emuxki_trigger_output(void *addr, void *start, void *end, int blksize,
   1961   1.1  jdolecek 		       void (*inth) (void *), void *inthparam,
   1962   1.1  jdolecek 		       struct audio_params *params)
   1963   1.1  jdolecek {
   1964   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1965   1.1  jdolecek 	/* No multiple voice support for now */
   1966   1.1  jdolecek 	struct emuxki_voice *voice = sc->pvoice;
   1967   1.1  jdolecek 	int             error;
   1968   1.1  jdolecek 
   1969   1.1  jdolecek 	if (voice == NULL)
   1970   1.1  jdolecek 		return (ENXIO);
   1971   1.1  jdolecek 	if ((error = emuxki_set_vparms(voice, params)))
   1972   1.1  jdolecek 		return (error);
   1973   1.1  jdolecek 	if ((error = emuxki_voice_set_bufparms(voice, start,
   1974   1.1  jdolecek 				(caddr_t)end - (caddr_t)start, blksize)))
   1975   1.1  jdolecek 		return (error);
   1976   1.1  jdolecek 	emuxki_voice_commit_parms(voice);
   1977   1.1  jdolecek 	emuxki_voice_start(voice, inth, inthparam);
   1978   1.1  jdolecek 
   1979   1.1  jdolecek 	return (0);
   1980   1.1  jdolecek }
   1981   1.1  jdolecek 
   1982   1.1  jdolecek static int
   1983   1.1  jdolecek emuxki_trigger_input(void *addr, void *start, void *end, int blksize,
   1984   1.1  jdolecek 		      void (*inth) (void *), void *inthparam,
   1985   1.1  jdolecek 		      struct audio_params *params)
   1986   1.1  jdolecek {
   1987   1.1  jdolecek 	struct emuxki_softc *sc = addr;
   1988   1.1  jdolecek 	/* No multiple voice support for now */
   1989   1.1  jdolecek 	struct emuxki_voice *voice = sc->rvoice;
   1990   1.1  jdolecek 	int             error;
   1991   1.1  jdolecek 
   1992   1.1  jdolecek 	if (voice == NULL)
   1993   1.1  jdolecek 		return (ENXIO);
   1994   1.1  jdolecek 	if ((error = emuxki_set_vparms(voice, params)))
   1995   1.1  jdolecek 		return (error);
   1996   1.1  jdolecek 	if ((error = emuxki_voice_set_bufparms(voice, start,
   1997   1.1  jdolecek 						(caddr_t)end - (caddr_t)start,
   1998   1.1  jdolecek 						blksize)))
   1999   1.1  jdolecek 		return (error);
   2000   1.1  jdolecek 	emuxki_voice_commit_parms(voice); /* Useless for record ? */
   2001   1.1  jdolecek 	emuxki_voice_start(voice, inth, inthparam);
   2002   1.1  jdolecek 
   2003   1.1  jdolecek 	return (0);
   2004   1.1  jdolecek }
   2005   1.1  jdolecek 
   2006   1.1  jdolecek 
   2007   1.1  jdolecek /*
   2008   1.1  jdolecek  * AC97 callbacks
   2009   1.1  jdolecek  */
   2010   1.1  jdolecek 
   2011   1.1  jdolecek static int
   2012   1.1  jdolecek emuxki_ac97_attach(void *arg, struct ac97_codec_if *codecif)
   2013   1.1  jdolecek {
   2014   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   2015   1.1  jdolecek 
   2016   1.1  jdolecek 	sc->codecif = codecif;
   2017   1.1  jdolecek 	return (0);
   2018   1.1  jdolecek }
   2019   1.1  jdolecek 
   2020   1.1  jdolecek static int
   2021   1.1  jdolecek emuxki_ac97_read(void *arg, u_int8_t reg, u_int16_t *val)
   2022   1.1  jdolecek {
   2023   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   2024   1.1  jdolecek 	int s;
   2025   1.1  jdolecek 
   2026   1.1  jdolecek 	s = splaudio();
   2027   1.1  jdolecek 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
   2028   1.1  jdolecek 	*val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA);
   2029   1.1  jdolecek 	splx(s);
   2030   1.1  jdolecek 
   2031   1.1  jdolecek 	return (0);
   2032   1.1  jdolecek }
   2033   1.1  jdolecek 
   2034   1.1  jdolecek static int
   2035   1.1  jdolecek emuxki_ac97_write(void *arg, u_int8_t reg, u_int16_t val)
   2036   1.1  jdolecek {
   2037   1.1  jdolecek 	struct emuxki_softc *sc = arg;
   2038   1.1  jdolecek 	int s;
   2039   1.1  jdolecek 
   2040   1.1  jdolecek 	s = splaudio();
   2041   1.1  jdolecek 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
   2042   1.1  jdolecek 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA, val);
   2043   1.1  jdolecek 	splx(s);
   2044   1.1  jdolecek 
   2045   1.1  jdolecek 	return (0);
   2046   1.1  jdolecek }
   2047   1.1  jdolecek 
   2048   1.1  jdolecek static void
   2049   1.1  jdolecek emuxki_ac97_reset(void *arg)
   2050   1.1  jdolecek {
   2051   1.6  jdolecek }
   2052   1.6  jdolecek 
   2053   1.6  jdolecek enum ac97_host_flags
   2054   1.6  jdolecek emuxki_ac97_flags(void *arg)
   2055   1.6  jdolecek {
   2056   1.6  jdolecek   return (AC97_HOST_SWAPPED_CHANNELS);
   2057   1.1  jdolecek }
   2058