Annotation of sys/dev/isa/pcppi.c, Revision 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