The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/cms.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: cms.c,v 1.7 2002/10/02 03:10:46 thorpej Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *        This product includes software developed by the NetBSD
   18  *        Foundation, Inc. and its contributors.
   19  * 4. Neither the name of The NetBSD Foundation nor the names of its
   20  *    contributors may be used to endorse or promote products derived
   21  *    from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33  * POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: cms.c,v 1.7 2002/10/02 03:10:46 thorpej Exp $");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/device.h>
   43 #include <sys/select.h>
   44 
   45 #include <machine/bus.h>
   46 
   47 #include <sys/audioio.h>
   48 #include <dev/audio_if.h>
   49 #include <dev/audiovar.h>
   50 
   51 #include <sys/midiio.h>
   52 #include <dev/midi_if.h>
   53 #include <dev/midivar.h>
   54 #include <dev/midisynvar.h>
   55 
   56 #include <dev/isa/isareg.h>
   57 #include <dev/isa/isavar.h>
   58 #include <dev/isa/cmsreg.h>
   59 
   60 #ifdef AUDIO_DEBUG
   61 #define DPRINTF(x)      if (cmsdebug) printf x
   62 int     cmsdebug = 0;
   63 #else
   64 #define DPRINTF(x)
   65 #endif
   66 
   67 struct cms_softc {
   68         struct midi_softc sc_mididev;
   69 
   70         bus_space_tag_t sc_iot;
   71         bus_space_handle_t sc_ioh;
   72 
   73         /* shadow registers for each chip */
   74         u_int8_t sc_shadowregs[32*2];
   75         midisyn sc_midisyn;
   76 };
   77 
   78 int     cms_probe __P((struct device *, struct cfdata *, void *));
   79 void    cms_attach __P((struct device *, struct device *, void *));
   80 
   81 CFATTACH_DECL(cms, sizeof(struct cms_softc),
   82     cms_probe, cms_attach, NULL, NULL);
   83 
   84 int     cms_open __P((midisyn *, int));
   85 void    cms_close __P((midisyn *));
   86 void    cms_on __P((midisyn *, u_int32_t, u_int32_t, u_int32_t));
   87 void    cms_off __P((midisyn *, u_int32_t, u_int32_t, u_int32_t));
   88 
   89 struct midisyn_methods midi_cms_hw = {
   90         cms_open,               /* open */
   91         cms_close,              /* close */
   92         0,                      /* ioctl */
   93         0,                      /* allocv */
   94         cms_on,                 /* noteon */
   95         cms_off,                /* noteoff */
   96         0,                      /* keypres */
   97         0,                      /* ctlchg */
   98         0,                      /* pgmchg */
   99         0,                      /* chnpres */
  100         0,                      /* pitchb */
  101         0,                      /* sysex */
  102 };
  103 
  104 static void cms_reset __P((struct cms_softc *));
  105 
  106 static char cms_note_table[] = {
  107         /* A  */ 3,
  108         /* A# */ 31,
  109         /* B  */ 58,
  110         /* C  */ 83,
  111         /* C# */ 107,
  112         /* D  */ 130,
  113         /* D# */ 151,
  114         /* E  */ 172,
  115         /* F  */ 191,
  116         /* F# */ 209,
  117         /* G  */ 226,
  118         /* G# */ 242,
  119 };
  120 
  121 #define NOTE_TO_OCTAVE(note) (((note)-CMS_FIRST_NOTE)/12)
  122 #define NOTE_TO_COUNT(note) cms_note_table[(((note)-CMS_FIRST_NOTE)%12)]
  123 
  124 int
  125 cms_probe(parent, match, aux)
  126         struct device *parent;
  127         struct cfdata *match;
  128         void *aux;
  129 {
  130         struct isa_attach_args *ia = aux;
  131         bus_space_tag_t iot;
  132         bus_space_handle_t ioh;
  133         int found = 0;
  134         int i;
  135 
  136         DPRINTF(("cms_probe():\n"));
  137 
  138         iot = ia->ia_iot;
  139 
  140         if (ia->ia_nio < 1)
  141                 return 0;
  142 
  143         if (ISA_DIRECT_CONFIG(ia))
  144                 return 0;
  145 
  146         if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
  147                 return 0;
  148 
  149         if (bus_space_map(iot, ia->ia_io[0].ir_addr, CMS_IOSIZE, 0, &ioh))
  150                 return 0;
  151 
  152         bus_space_write_1(iot, ioh, CMS_WREG, 0xaa);
  153         if (bus_space_read_1(iot, ioh, CMS_RREG) != 0xaa)
  154                 goto out;
  155 
  156         for (i = 0; i < 8; i++) {
  157                 if (bus_space_read_1(iot, ioh, CMS_MREG) != 0x7f)
  158                         goto out;
  159         }
  160         found = 1;
  161 
  162         ia->ia_nio = 1;
  163         ia->ia_io[0].ir_size = CMS_IOSIZE;
  164 
  165         ia->ia_niomem = 0;
  166         ia->ia_nirq = 0;
  167         ia->ia_ndrq = 0;
  168 
  169 out:
  170         bus_space_unmap(iot, ioh, CMS_IOSIZE);
  171 
  172         return found;
  173 }
  174 
  175 
  176 void
  177 cms_attach(parent, self, aux)
  178         struct device *parent, *self;
  179         void *aux;
  180 {
  181         struct cms_softc *sc = (struct cms_softc *)self;
  182         struct isa_attach_args *ia = aux;
  183         bus_space_tag_t iot;
  184         bus_space_handle_t ioh;
  185         midisyn *ms;
  186         struct audio_attach_args arg;
  187 
  188         printf("\n");
  189 
  190         DPRINTF(("cms_attach():\n"));
  191 
  192         iot = ia->ia_iot;
  193 
  194         if (bus_space_map(iot, ia->ia_io[0].ir_addr, CMS_IOSIZE, 0, &ioh)) {
  195                 printf(": can't map i/o space\n");
  196                 return;
  197         }
  198 
  199         sc->sc_iot = iot;
  200         sc->sc_ioh = ioh;
  201 
  202         /* now let's reset the chips */
  203         cms_reset(sc);
  204 
  205         ms = &sc->sc_midisyn;
  206         ms->mets = &midi_cms_hw;
  207         strcpy(ms->name, "Creative Music System");
  208         ms->nvoice = CMS_NVOICES;
  209         ms->flags = MS_DOALLOC;
  210         ms->data = sc;
  211 
  212         /* use the synthesiser */
  213         midisyn_attach(&sc->sc_mididev, ms);
  214 
  215         /* now attach the midi device to the synthesiser */
  216         arg.type = AUDIODEV_TYPE_MIDI;
  217         arg.hwif = sc->sc_mididev.hw_if;
  218         arg.hdl = sc->sc_mididev.hw_hdl;
  219         config_found((struct device *)&sc->sc_mididev, &arg, 0);
  220 }
  221 
  222 
  223 int
  224 cms_open(ms,flag)
  225         midisyn *ms;
  226         int flag;
  227 {
  228         struct cms_softc *sc = (struct cms_softc *)ms->data;
  229 
  230         cms_reset(sc);
  231 
  232         return 0;
  233 }
  234 
  235 void
  236 cms_close(ms)
  237         midisyn *ms;
  238 {
  239         struct cms_softc *sc = (struct cms_softc *)ms->data;
  240 
  241         cms_reset(sc);
  242 }
  243 
  244 void
  245 cms_on(ms, chan, note, vel)
  246         midisyn *ms;
  247         u_int32_t chan;
  248         u_int32_t note;
  249         u_int32_t vel;
  250 {
  251         struct cms_softc *sc = (struct cms_softc *)ms->data;
  252         int chip = CHAN_TO_CHIP(chan);
  253         int voice = CHAN_TO_VOICE(chan);
  254         u_int8_t octave;
  255         u_int8_t count;
  256         u_int8_t reg;
  257         u_int8_t vol;
  258 
  259         if (note < CMS_FIRST_NOTE)
  260                 return;
  261 
  262         octave = NOTE_TO_OCTAVE(note);
  263         count = NOTE_TO_COUNT(note);
  264 
  265         DPRINTF(("chip=%d voice=%d octave=%d count=%d offset=%d shift=%d\n",
  266                 chip, voice, octave, count, OCTAVE_OFFSET(voice),
  267                 OCTAVE_SHIFT(voice)));
  268 
  269         /* write the count */
  270         CMS_WRITE(sc, chip, CMS_IREG_FREQ0 + voice, count);
  271 
  272         /* select the octave */
  273         reg = CMS_READ(sc, chip, CMS_IREG_OCTAVE_1_0 + OCTAVE_OFFSET(voice));
  274         reg &= ~(0x0f<<OCTAVE_SHIFT(voice));
  275         reg |= ((octave&0x7)<<OCTAVE_SHIFT(voice));
  276         CMS_WRITE(sc, chip, CMS_IREG_OCTAVE_1_0 + OCTAVE_OFFSET(voice), reg);
  277 
  278         /* set the volume */
  279         vol = (vel>>3)&0x0f;
  280         CMS_WRITE(sc, chip, CMS_IREG_VOL0 + voice, ((vol<<4)|vol));
  281 
  282         /* enable the voice */
  283         reg = CMS_READ(sc, chip, CMS_IREG_FREQ_CTL);
  284         reg |= (1<<voice);
  285         CMS_WRITE(sc, chip, CMS_IREG_FREQ_CTL, reg);    
  286 }
  287 
  288 void
  289 cms_off(ms, chan, note, vel)
  290         midisyn *ms;
  291         u_int32_t chan;
  292         u_int32_t note;
  293         u_int32_t vel;
  294 {
  295         struct cms_softc *sc = (struct cms_softc *)ms->data;
  296         int chip = CHAN_TO_CHIP(chan);
  297         int voice = CHAN_TO_VOICE(chan);
  298         u_int8_t reg;
  299 
  300         if (note < CMS_FIRST_NOTE)
  301                 return;
  302 
  303         /* disable the channel */
  304         reg = CMS_READ(sc, chip, CMS_IREG_FREQ_CTL);
  305         reg &= ~(1<<voice);
  306         CMS_WRITE(sc, chip, CMS_IREG_FREQ_CTL, reg);    
  307 }
  308 
  309 static void
  310 cms_reset(sc)
  311         struct cms_softc *sc;
  312 {
  313         int i;
  314 
  315         DPRINTF(("cms_reset():\n"));
  316 
  317         for (i = 0; i < 6; i++) {
  318                 CMS_WRITE(sc, 0, CMS_IREG_VOL0+i, 0x00);
  319                 CMS_WRITE(sc, 1, CMS_IREG_VOL0+i, 0x00);
  320 
  321                 CMS_WRITE(sc, 0, CMS_IREG_FREQ0+i, 0x00);
  322                 CMS_WRITE(sc, 1, CMS_IREG_FREQ0+i, 0x00);
  323         }
  324 
  325         for (i = 0; i < 3; i++) {
  326                 CMS_WRITE(sc, 0, CMS_IREG_OCTAVE_1_0+i, 0x00);  
  327                 CMS_WRITE(sc, 1, CMS_IREG_OCTAVE_1_0+i, 0x00);  
  328         }
  329 
  330         CMS_WRITE(sc, 0, CMS_IREG_FREQ_CTL, 0x00);
  331         CMS_WRITE(sc, 1, CMS_IREG_FREQ_CTL, 0x00);
  332 
  333         CMS_WRITE(sc, 0, CMS_IREG_NOISE_CTL, 0x00);
  334         CMS_WRITE(sc, 1, CMS_IREG_NOISE_CTL, 0x00);
  335 
  336         CMS_WRITE(sc, 0, CMS_IREG_NOISE_BW, 0x00);
  337         CMS_WRITE(sc, 1, CMS_IREG_NOISE_BW, 0x00);
  338 
  339         /*
  340          * These registers don't appear to be useful, but must be
  341          * cleared otherwise certain voices don't work properly
  342          */
  343         CMS_WRITE(sc, 0, 0x18, 0x00);
  344         CMS_WRITE(sc, 1, 0x18, 0x00);
  345         CMS_WRITE(sc, 0, 0x19, 0x00);
  346         CMS_WRITE(sc, 1, 0x19, 0x00);
  347 
  348         CMS_WRITE(sc, 0, CMS_IREG_SYS_CTL, CMS_IREG_SYS_RESET);
  349         CMS_WRITE(sc, 1, CMS_IREG_SYS_CTL, CMS_IREG_SYS_RESET);
  350 
  351         CMS_WRITE(sc, 0, CMS_IREG_SYS_CTL, CMS_IREG_SYS_ENBL);
  352         CMS_WRITE(sc, 1, CMS_IREG_SYS_CTL, CMS_IREG_SYS_ENBL);
  353 }

Cache object: 8064a7ce778a50427c94784faaf5fda5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.