[BACK]Return to pcppi.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/pcppi.c, Revision 1.1.1.1

1.1       nbrk        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 */

CVSweb