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

Cache object: 839d3fc55928182cb9fbc1f6373beb60


[ 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.