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 /* $OpenBSD: pcppi.c,v 1.19 2022/04/06 18:59:28 naddy 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/device.h>
   35 #include <sys/errno.h>
   36 #include <sys/timeout.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 #include "hidkbd.h"
   49 #if NPCKBD > 0 || NHIDKBD > 0
   50 #include <dev/ic/pckbcvar.h>
   51 #include <dev/pckbc/pckbdvar.h>
   52 #include <dev/hid/hidkbdvar.h>
   53 void    pcppi_kbd_bell(void *, u_int, u_int, u_int, int);
   54 #endif
   55 
   56 struct pcppi_softc {
   57         struct device sc_dv;
   58 
   59         bus_space_tag_t sc_iot;
   60         bus_space_handle_t sc_ppi_ioh, sc_pit1_ioh;
   61 
   62         struct timeout sc_bell_timeout;
   63 
   64         int sc_bellactive, sc_bellpitch;
   65         int sc_slp;
   66         int sc_timeout;
   67 };
   68 
   69 int     pcppi_match(struct device *, void *, void *);
   70 void    pcppi_attach(struct device *, struct device *, void *);
   71 
   72 const struct cfattach pcppi_ca = {
   73         sizeof(struct pcppi_softc), pcppi_match, pcppi_attach,
   74 };
   75 
   76 struct cfdriver pcppi_cd = {
   77         NULL, "pcppi", DV_DULL
   78 };
   79 
   80 static void pcppi_bell_stop(void *);
   81 
   82 #define PCPPIPRI (PZERO - 1)
   83 
   84 int
   85 pcppi_match(struct device *parent, void *match, void *aux)
   86 {
   87         struct isa_attach_args *ia = aux;
   88         bus_space_handle_t ppi_ioh, pit1_ioh;
   89         int have_pit1, have_ppi, rv;
   90         u_int8_t v, nv;
   91 
   92         /* If values are hardwired to something that they can't be, punt. */
   93         if ((ia->ia_iobase != IOBASEUNK && ia->ia_iobase != IO_PPI) ||
   94             ia->ia_maddr != MADDRUNK || ia->ia_msize != 0 ||
   95             ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK)
   96                 return (0);
   97 
   98         rv = 0;
   99         have_pit1 = have_ppi = 0;
  100 
  101         if (bus_space_map(ia->ia_iot, IO_TIMER1, 4, 0, &pit1_ioh))
  102                 goto lose;
  103         have_pit1 = 1;
  104         if (bus_space_map(ia->ia_iot, IO_PPI, 1, 0, &ppi_ioh))
  105                 goto lose;
  106         have_ppi = 1;
  107 
  108         /*
  109          * Check for existence of PPI.  Realistically, this is either going to
  110          * be here or nothing is going to be here.
  111          *
  112          * We don't want to have any chance of changing speaker output (which
  113          * this test might, if it crashes in the middle, or something;
  114          * normally it's too quick to produce anything audible), but
  115          * many "combo chip" mock-PPI's don't seem to support the top bit
  116          * of Port B as a settable bit.  The bottom bit has to be settable,
  117          * since the speaker driver hardware still uses it.
  118          */
  119         v = bus_space_read_1(ia->ia_iot, ppi_ioh, 0);           /* XXX */
  120         bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v ^ 0x01);    /* XXX */
  121         nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0);          /* XXX */
  122         if (((nv ^ v) & 0x01) == 0x01)
  123                 rv = 1;
  124         bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v);           /* XXX */
  125         nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0);          /* XXX */
  126         if (((nv ^ v) & 0x01) != 0x00) {
  127                 rv = 0;
  128                 goto lose;
  129         }
  130 
  131         /*
  132          * We assume that the programmable interval timer is there.
  133          */
  134 
  135 lose:
  136         if (have_pit1)
  137                 bus_space_unmap(ia->ia_iot, pit1_ioh, 4);
  138         if (have_ppi)
  139                 bus_space_unmap(ia->ia_iot, ppi_ioh, 1);
  140         if (rv) {
  141                 ia->ia_iobase = IO_PPI;
  142                 ia->ia_iosize = 0x1;
  143                 ia->ia_msize = 0x0;
  144         }
  145         return (rv);
  146 }
  147 
  148 void
  149 pcppi_attach(struct device *parent, struct device *self, void *aux)
  150 {
  151         struct pcppi_softc *sc = (struct pcppi_softc *)self;
  152         struct isa_attach_args *ia = aux;
  153         bus_space_tag_t iot;
  154         struct pcppi_attach_args pa;
  155 
  156         timeout_set(&sc->sc_bell_timeout, pcppi_bell_stop, sc);
  157 
  158         sc->sc_iot = iot = ia->ia_iot;
  159 
  160         if (bus_space_map(iot, IO_TIMER1, 4, 0, &sc->sc_pit1_ioh) ||
  161             bus_space_map(iot, IO_PPI, 1, 0, &sc->sc_ppi_ioh))
  162                 panic("pcppi_attach: couldn't map");
  163 
  164         printf("\n");
  165 
  166         sc->sc_bellactive = sc->sc_bellpitch = sc->sc_slp = 0;
  167 
  168         /* Provide a beeper for the keyboard, if there isn't one already. */
  169 #if NPCKBD > 0
  170         pckbd_hookup_bell(pcppi_kbd_bell, sc);
  171 #endif
  172 #if NHIDKBD > 0
  173         hidkbd_hookup_bell(pcppi_kbd_bell, sc);
  174 #endif
  175 
  176         pa.pa_cookie = sc;
  177         while (config_found(self, &pa, 0))
  178                 ;
  179 }
  180 
  181 void
  182 pcppi_bell(pcppi_tag_t self, int pitch, int period_ms, int slp)
  183 {
  184         struct pcppi_softc *sc = self;
  185         int s1, s2;
  186 
  187         if (pitch < 0)
  188                 pitch = 0;
  189         else if (pitch > INT_MAX - TIMER_FREQ)
  190                 pitch = INT_MAX - TIMER_FREQ;
  191 
  192         if (period_ms < 0)
  193                 period_ms = 0;
  194         else if (period_ms > INT_MAX / 1000)
  195                 period_ms = INT_MAX / 1000;
  196 
  197         s1 = spltty(); /* ??? */
  198         if (sc->sc_bellactive) {
  199                 if (sc->sc_timeout) {
  200                         sc->sc_timeout = 0;
  201                         timeout_del(&sc->sc_bell_timeout);
  202                 }
  203                 if (sc->sc_slp)
  204                         wakeup(pcppi_bell_stop);
  205         }
  206         if (pitch == 0 || period_ms == 0) {
  207                 pcppi_bell_stop(sc);
  208                 sc->sc_bellpitch = 0;
  209                 splx(s1);
  210                 return;
  211         }
  212         if (!sc->sc_bellactive || sc->sc_bellpitch != pitch) {
  213                 s2 = splhigh();
  214                 bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_MODE,
  215                     TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
  216                 bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2,
  217                     TIMER_DIV(pitch) % 256);
  218                 bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2,
  219                     TIMER_DIV(pitch) / 256);
  220                 splx(s2);
  221                 /* enable speaker */
  222                 bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0,
  223                         bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0)
  224                         | PIT_SPKR);
  225         }
  226         sc->sc_bellpitch = pitch;
  227 
  228         sc->sc_bellactive = 1;
  229 
  230         if (slp & PCPPI_BELL_POLL) {
  231                 delay(period_ms * 1000);
  232                 pcppi_bell_stop(sc);
  233         } else {
  234                 sc->sc_timeout = 1;
  235                 timeout_add_msec(&sc->sc_bell_timeout, period_ms);
  236                 if (slp & PCPPI_BELL_SLEEP) {
  237                         sc->sc_slp = 1;
  238                         tsleep_nsec(pcppi_bell_stop, PCPPIPRI | PCATCH, "bell",
  239                             INFSLP);
  240                         sc->sc_slp = 0;
  241                 }
  242         }
  243         splx(s1);
  244 }
  245 
  246 static void
  247 pcppi_bell_stop(void *arg)
  248 {
  249         struct pcppi_softc *sc = arg;
  250         int s;
  251 
  252         s = spltty(); /* ??? */
  253         sc->sc_timeout = 0;
  254 
  255         /* disable bell */
  256         bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0,
  257                           bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0)
  258                           & ~PIT_SPKR);
  259         sc->sc_bellactive = 0;
  260         if (sc->sc_slp)
  261                 wakeup(pcppi_bell_stop);
  262         splx(s);
  263 }
  264 
  265 #if NPCKBD > 0 || NHIDKBD > 0
  266 void
  267 pcppi_kbd_bell(void *arg, u_int pitch, u_int period, u_int volume, int poll)
  268 {
  269         /*
  270          * NB: volume ignored.
  271          */
  272         pcppi_bell(arg, volume ? pitch : 0, period,
  273             poll ? PCPPI_BELL_POLL : 0);
  274 }
  275 #endif /* NPCKBD > 0 || NHIDKBD > 0 */

Cache object: 6a1c899840e1fd283f3dce680777dbbe


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