root/dev/isa/pcppi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pcppi_match
  2. pcppi_attach
  3. pcppi_bell
  4. pcppi_bell_stop
  5. pcppi_pckbd_bell

    1 /* $OpenBSD: pcppi.c,v 1.7 2006/02/12 20:04:16 miod Exp $ */
    2 /* $NetBSD: pcppi.c,v 1.1 1998/04/15 20:26:18 drochner Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1996 Carnegie-Mellon University.
    6  * All rights reserved.
    7  *
    8  * Author: Chris G. Demetriou
    9  * 
   10  * Permission to use, copy, modify and distribute this software and
   11  * its documentation is hereby granted, provided that both the copyright
   12  * notice and this permission notice appear in all copies of the
   13  * software, derivative works or modified versions, and any portions
   14  * thereof, and that both notices appear in supporting documentation.
   15  * 
   16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
   17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
   18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   19  * 
   20  * Carnegie Mellon requests users of this software to return to
   21  *
   22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   23  *  School of Computer Science
   24  *  Carnegie Mellon University
   25  *  Pittsburgh PA 15213-3890
   26  *
   27  * any improvements or extensions that they make and grant Carnegie the
   28  * rights to redistribute these changes.
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/proc.h>
   35 #include <sys/device.h>
   36 #include <sys/errno.h>
   37 
   38 #include <machine/bus.h>
   39 
   40 #include <dev/isa/isareg.h>
   41 #include <dev/isa/isavar.h>
   42 #include <dev/isa/pcppireg.h>
   43 #include <dev/isa/pcppivar.h>
   44 
   45 #include <dev/ic/i8253reg.h>
   46 
   47 #include "pckbd.h"
   48 #if NPCKBD > 0
   49 #include <dev/ic/pckbcvar.h>
   50 #include <dev/pckbc/pckbdvar.h>
   51 
   52 void    pcppi_pckbd_bell(void *, u_int, u_int, u_int, int);
   53 #endif
   54 
   55 struct pcppi_softc {
   56         struct device sc_dv;
   57 
   58         bus_space_tag_t sc_iot;
   59         bus_space_handle_t sc_ppi_ioh, sc_pit1_ioh;
   60 
   61         struct timeout sc_bell_timeout;
   62 
   63         int sc_bellactive, sc_bellpitch;
   64         int sc_slp;
   65         int sc_timeout;
   66 };
   67 
   68 int     pcppi_match(struct device *, void *, void *);
   69 void    pcppi_attach(struct device *, struct device *, void *);
   70 
   71 struct cfattach pcppi_ca = {
   72         sizeof(struct pcppi_softc), pcppi_match, pcppi_attach,
   73 };
   74 
   75 struct cfdriver pcppi_cd = {
   76         NULL, "pcppi", DV_DULL
   77 };
   78 
   79 static void pcppi_bell_stop(void *);
   80 
   81 #define PCPPIPRI (PZERO - 1)
   82 
   83 int
   84 pcppi_match(parent, match, aux)
   85         struct device *parent;
   86         void *match;
   87         void *aux;
   88 {
   89         struct isa_attach_args *ia = aux;
   90         bus_space_handle_t ppi_ioh, pit1_ioh;
   91         int have_pit1, have_ppi, rv;
   92         u_int8_t v, nv;
   93 
   94         /* If values are hardwired to something that they can't be, punt. */
   95         if ((ia->ia_iobase != IOBASEUNK && ia->ia_iobase != IO_PPI) ||
   96             ia->ia_maddr != MADDRUNK || ia->ia_msize != 0 ||
   97             ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK)
   98                 return (0);
   99 
  100         rv = 0;
  101         have_pit1 = have_ppi = 0;
  102 
  103         if (bus_space_map(ia->ia_iot, IO_TIMER1, 4, 0, &pit1_ioh))
  104                 goto lose;
  105         have_pit1 = 1;
  106         if (bus_space_map(ia->ia_iot, IO_PPI, 1, 0, &ppi_ioh))
  107                 goto lose;
  108         have_ppi = 1;
  109 
  110         /*
  111          * Check for existence of PPI.  Realistically, this is either going to
  112          * be here or nothing is going to be here.
  113          *
  114          * We don't want to have any chance of changing speaker output (which
  115          * this test might, if it crashes in the middle, or something;
  116          * normally it's be to quick to produce anthing audible), but
  117          * many "combo chip" mock-PPI's don't seem to support the top bit
  118          * of Port B as a settable bit.  The bottom bit has to be settable,
  119          * since the speaker driver hardware still uses it.
  120          */
  121         v = bus_space_read_1(ia->ia_iot, ppi_ioh, 0);           /* XXX */
  122         bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v ^ 0x01);    /* XXX */
  123         nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0);          /* XXX */
  124         if (((nv ^ v) & 0x01) == 0x01)
  125                 rv = 1;
  126         bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v);           /* XXX */
  127         nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0);          /* XXX */
  128         if (((nv ^ v) & 0x01) != 0x00) {
  129                 rv = 0;
  130                 goto lose;
  131         }
  132 
  133         /*
  134          * We assume that the programmable interval timer is there.
  135          */
  136 
  137 lose:
  138         if (have_pit1)
  139                 bus_space_unmap(ia->ia_iot, pit1_ioh, 4);
  140         if (have_ppi)
  141                 bus_space_unmap(ia->ia_iot, ppi_ioh, 1);
  142         if (rv) {
  143                 ia->ia_iobase = IO_PPI;
  144                 ia->ia_iosize = 0x1;
  145                 ia->ia_msize = 0x0;
  146         }
  147         return (rv);
  148 }
  149 
  150 void
  151 pcppi_attach(parent, self, aux)
  152         struct device *parent, *self;
  153         void *aux;
  154 {
  155         struct pcppi_softc *sc = (struct pcppi_softc *)self;
  156         struct isa_attach_args *ia = aux;
  157         bus_space_tag_t iot;
  158         struct pcppi_attach_args pa;
  159 
  160         timeout_set(&sc->sc_bell_timeout, pcppi_bell_stop, sc);
  161 
  162         sc->sc_iot = iot = ia->ia_iot;
  163 
  164         if (bus_space_map(iot, IO_TIMER1, 4, 0, &sc->sc_pit1_ioh) ||
  165             bus_space_map(iot, IO_PPI, 1, 0, &sc->sc_ppi_ioh))
  166                 panic("pcppi_attach: couldn't map");
  167 
  168         printf("\n");
  169 
  170         sc->sc_bellactive = sc->sc_bellpitch = sc->sc_slp = 0;
  171 
  172 #if NPCKBD > 0
  173         /* Provide a beeper for the PC Keyboard, if there isn't one already. */
  174         pckbd_hookup_bell(pcppi_pckbd_bell, sc);
  175 #endif
  176 
  177         pa.pa_cookie = sc;
  178         while (config_found(self, &pa, 0));
  179 }
  180 
  181 void
  182 pcppi_bell(self, pitch, period, slp)
  183         pcppi_tag_t self;
  184         int pitch, period;
  185         int slp;
  186 {
  187         struct pcppi_softc *sc = self;
  188         int s1, s2;
  189 
  190         s1 = spltty(); /* ??? */
  191         if (sc->sc_bellactive) {
  192                 if (sc->sc_timeout) {
  193                         sc->sc_timeout = 0;
  194                         timeout_del(&sc->sc_bell_timeout);
  195                 }
  196                 if (sc->sc_slp)
  197                         wakeup(pcppi_bell_stop);
  198         }
  199         if (pitch == 0 || period == 0) {
  200                 pcppi_bell_stop(sc);
  201                 sc->sc_bellpitch = 0;
  202                 splx(s1);
  203                 return;
  204         }
  205         if (!sc->sc_bellactive || sc->sc_bellpitch != pitch) {
  206                 s2 = splhigh();
  207                 bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_MODE,
  208                     TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
  209                 bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2,
  210                     TIMER_DIV(pitch) % 256);
  211                 bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2,
  212                     TIMER_DIV(pitch) / 256);
  213                 splx(s2);
  214                 /* enable speaker */
  215                 bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0,
  216                         bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0)
  217                         | PIT_SPKR);
  218         }
  219         sc->sc_bellpitch = pitch;
  220 
  221         sc->sc_bellactive = 1;
  222 
  223         if (slp & PCPPI_BELL_POLL) {
  224                 delay((period * 1000000) / hz);
  225                 pcppi_bell_stop(sc);
  226         } else {
  227                 sc->sc_timeout = 1;
  228                 timeout_add(&sc->sc_bell_timeout, period);
  229                 if (slp & PCPPI_BELL_SLEEP) {
  230                         sc->sc_slp = 1;
  231                         tsleep(pcppi_bell_stop, PCPPIPRI | PCATCH, "bell", 0);
  232                         sc->sc_slp = 0;
  233                 }
  234         }
  235         splx(s1);
  236 }
  237 
  238 static void
  239 pcppi_bell_stop(arg)
  240         void *arg;
  241 {
  242         struct pcppi_softc *sc = arg;
  243         int s;
  244 
  245         s = spltty(); /* ??? */
  246         sc->sc_timeout = 0;
  247 
  248         /* disable bell */
  249         bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0,
  250                           bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0)
  251                           & ~PIT_SPKR);
  252         sc->sc_bellactive = 0;
  253         if (sc->sc_slp)
  254                 wakeup(pcppi_bell_stop);
  255         splx(s);
  256 }
  257 
  258 #if NPCKBD > 0
  259 void
  260 pcppi_pckbd_bell(arg, pitch, period, volume, poll)
  261         void *arg;
  262         u_int pitch, period, volume;
  263         int poll;
  264 {
  265         /*
  266          * Comes in as ms, goes out as ticks; volume ignored.
  267          */
  268         pcppi_bell(arg, volume ? pitch : 0, (period * hz) / 1000,
  269             poll ? PCPPI_BELL_POLL : 0);
  270 }
  271 #endif /* NPCKBD > 0 */

/* [<][>][^][v][top][bottom][index][help] */