Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/dev/pci Pull up revisions 1.1-1.7 (new, via patch, ...



details:   https://anonhg.NetBSD.org/src/rev/fb8fe9b539bc
branches:  netbsd-1-5
changeset: 492576:fb8fe9b539bc
user:      he <he%NetBSD.org@localhost>
date:      Sat Jan 19 21:55:09 2002 +0000

description:
Pull up revisions 1.1-1.7 (new, via patch, requested by he):
  Add driver for Creative Labs SBLive! EMU10000 and (probably) PCI512.
  Fixes PR#15260.

diffstat:

 sys/dev/pci/emuxki.c |  2055 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 2055 insertions(+), 0 deletions(-)

diffs (truncated from 2059 to 300 lines):

diff -r 5482cf59c1e6 -r fb8fe9b539bc sys/dev/pci/emuxki.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/emuxki.c      Sat Jan 19 21:55:09 2002 +0000
@@ -0,0 +1,2055 @@
+/*     $NetBSD: emuxki.c,v 1.7.4.2 2002/01/19 21:55:09 he Exp $        */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Yannick Montulet.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Driver for Creative Labs SBLive! series and probably PCI512.
+ * 
+ * Known bugs:
+ * - inversed stereo at ac97 codec level
+ *   (XXX jdolecek - don't see the problem? maybe because auvia(4) has
+ *    it swapped too?)
+ * - bass disapear when you plug rear jack-in on Cambridge FPS2000 speakers
+ *   (and presumably all speakers that support front and rear jack-in)
+ *
+ * TODO:
+ * - Digital Outputs
+ * - (midi/mpu),joystick support
+ * - Single source recording
+ * - Multiple voices play (problem with /dev/audio architecture)
+ * - Multiple sources recording (Pb with audio(4))
+ * - Independant modification of each channel's parameters (via mixer ?)
+ * - DSP FX patches (to make fx like chipmunk)
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.7.4.2 2002/01/19 21:55:09 he Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/audioio.h>
+#include <sys/select.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/audio_if.h>
+#include <dev/audiovar.h>
+#include <dev/auconv.h>
+#include <dev/mulaw.h>
+#include <dev/ic/ac97reg.h>
+#include <dev/ic/ac97var.h>
+
+#include <dev/pci/emuxkireg.h>
+#include <dev/pci/emuxkivar.h>
+
+/* autconf goo */
+static int  emuxki_match(struct device *, struct cfdata *, void *);
+static void emuxki_attach(struct device *, struct device *, void *);
+static int  emuxki_detach(struct device *, int);
+
+/* dma mem mgmt */
+static struct dmamem *dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
+                                int, int, int);
+static void           dmamem_free(struct dmamem *, int);
+
+/* Emu10k1 init & shutdown */
+static int  emuxki_init(struct emuxki_softc *);
+static void emuxki_shutdown(struct emuxki_softc *);
+
+/* Emu10k1 mem mgmt */
+static void   *emuxki_pmem_alloc(struct emuxki_softc *, size_t,int,int);
+static void   *emuxki_rmem_alloc(struct emuxki_softc *, size_t,int,int);
+
+/*
+ * Emu10k1 channels funcs : There is no direct access to channels, everything
+ * is done through voices I will at least provide channel based fx params
+ * modification, later...
+ */
+
+/* Emu10k1 voice mgmt */
+static struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *,
+                                            u_int8_t);
+static void   emuxki_voice_delete(struct emuxki_voice *);
+static int    emuxki_voice_set_audioparms(struct emuxki_voice *, u_int8_t,
+                                         u_int8_t, u_int32_t);
+/* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
+static int emuxki_voice_set_bufparms(struct emuxki_voice *,
+                                    void *, u_int32_t, u_int16_t);
+static void emuxki_voice_commit_parms(struct emuxki_voice *);
+static u_int32_t emuxki_voice_curaddr(struct emuxki_voice *);
+static void emuxki_voice_start(struct emuxki_voice *,
+                              void (*) (void *), void *);
+static void emuxki_voice_halt(struct emuxki_voice *);
+
+/*
+ * Emu10k1 stream mgmt : not done yet
+ */
+#if 0
+static struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
+static void   emuxki_stream_delete(struct emuxki_stream *);
+static int    emuxki_stream_set_audio_params(struct emuxki_stream *, u_int8_t,
+                                            u_int8_t, u_int8_t, u_int16_t);
+static void   emuxki_stream_start(struct emuxki_stream *);
+static void   emuxki_stream_halt(struct emuxki_stream *);
+#endif
+
+/* audio interface callbacks */
+
+static int     emuxki_open(void *, int);
+static void    emuxki_close(void *);
+
+static int     emuxki_query_encoding(void *, struct audio_encoding *);
+static int     emuxki_set_params(void *, int, int,
+                                 struct audio_params *,
+                                 struct audio_params *);
+
+static size_t  emuxki_round_buffersize(void *, int, size_t);
+
+static int     emuxki_trigger_output(void *, void *, void *, int,
+                                     void (*)(void *), void *,
+                                     struct audio_params *);
+static int     emuxki_trigger_input(void *, void *, void *, int,
+                                    void (*) (void *), void *,
+                                    struct audio_params *);
+static int     emuxki_halt_output(void *);
+static int     emuxki_halt_input(void *);
+
+static int     emuxki_getdev(void *, struct audio_device *);
+static int     emuxki_set_port(void *, mixer_ctrl_t *);
+static int     emuxki_get_port(void *, mixer_ctrl_t *);
+static int     emuxki_query_devinfo(void *, mixer_devinfo_t *);
+
+static void    *emuxki_allocm(void *, int, size_t, int, int);
+static void    emuxki_freem(void *, void *, int);
+
+static paddr_t emuxki_mappage(void *, void *, off_t, int);
+static int     emuxki_get_props(void *);
+
+/* Interrupt handler */
+static int  emuxki_intr(void *);
+
+/* Emu10k1 AC97 interface callbacks */
+static int  emuxki_ac97_attach(void *, struct ac97_codec_if *);
+static int  emuxki_ac97_read(void *, u_int8_t, u_int16_t *);
+static int  emuxki_ac97_write(void *, u_int8_t, u_int16_t);
+static void emuxki_ac97_reset(void *);
+static enum ac97_host_flags emuxki_ac97_flags(void *);
+
+/*
+ * Autoconfig goo.
+ */
+struct cfattach emuxki_ca = {
+        sizeof(struct emuxki_softc),
+        emuxki_match,
+        emuxki_attach,
+       emuxki_detach,
+       NULL              /* config activate */
+};
+
+static struct audio_hw_if emuxki_hw_if = {
+       emuxki_open,
+       emuxki_close,
+       NULL,                   /* drain */
+       emuxki_query_encoding,
+       emuxki_set_params,
+       NULL,                   /* round blocksize */
+       NULL,                   /* commit settings */
+       NULL,                   /* init_output */
+       NULL,                   /* init_input */
+       NULL,                   /* start_output */
+       NULL,                   /* start_input */
+       emuxki_halt_output,
+       emuxki_halt_input,
+       NULL,                   /* speaker_ctl */
+       emuxki_getdev,
+       NULL,                   /* setfd */
+       emuxki_set_port,
+       emuxki_get_port,
+       emuxki_query_devinfo,
+       emuxki_allocm,
+       emuxki_freem,
+       emuxki_round_buffersize,
+       emuxki_mappage,
+       emuxki_get_props,
+       emuxki_trigger_output,
+       emuxki_trigger_input,
+};
+
+/*
+ * Dma memory mgmt
+ */
+
+static void
+dmamem_delete(struct dmamem *mem, int type)
+{
+       free(mem->segs, type);
+       free(mem, type);
+}
+
+static struct dmamem *
+dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align,
+            int nsegs, int type, int flags)
+{
+       struct dmamem   *mem;
+       int             bus_dma_flags;
+
+       /* Allocate memory for structure */
+       if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
+               return (NULL);
+       mem->dmat = dmat;
+       mem->size = size;
+       mem->align = align;
+       mem->nsegs = nsegs;
+       mem->bound = 0;
+
+       mem->segs = malloc(mem->nsegs * sizeof(*(mem->segs)), type, flags);
+       if (mem->segs == NULL) {
+               free(mem, type);
+               return (NULL);
+       }
+
+       bus_dma_flags = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
+       if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
+                            mem->segs, mem->nsegs, &(mem->rsegs),
+                            bus_dma_flags)) {
+               dmamem_delete(mem, type);
+               return (NULL);
+       }
+
+       if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
+                          &(mem->kaddr), bus_dma_flags | BUS_DMA_COHERENT)) {
+               bus_dmamem_free(dmat, mem->segs, mem->nsegs);
+               dmamem_delete(mem, type);
+               return (NULL);
+       }
+
+       if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
+                             mem->bound, bus_dma_flags, &(mem->map))) {
+               bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
+               bus_dmamem_free(dmat, mem->segs, mem->nsegs);
+               dmamem_delete(mem, type);
+               return (NULL);
+       }
+
+       if (bus_dmamap_load(dmat, mem->map, mem->kaddr, 
+                           mem->size, NULL, bus_dma_flags)) {
+               bus_dmamap_destroy(dmat, mem->map);
+               bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
+               bus_dmamem_free(dmat, mem->segs, mem->nsegs);
+               dmamem_delete(mem, type);
+               return (NULL);
+       }
+
+       return (mem);
+}
+
+static void
+dmamem_free(struct dmamem *mem, int type)
+{
+       bus_dmamap_unload(mem->dmat, mem->map);
+       bus_dmamap_destroy(mem->dmat, mem->map);
+       bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
+       bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
+       dmamem_delete(mem, type);
+}
+
+
+/*
+ * Autoconf device callbacks : attach and detach
+ */



Home | Main Index | Thread Index | Old Index