1/*	$OpenBSD: beeper.c,v 1.15 2022/10/16 01:22:39 jsg Exp $	*/
2
3/*
4 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Effort sponsored in part by the Defense Advanced Research Projects
29 * Agency (DARPA) and Air Force Research Laboratory, Air Force
30 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
31 *
32 */
33
34/*
35 * Driver for beeper device on SUNW,Ultra-1-Engine.
36 */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/device.h>
42#include <sys/conf.h>
43#include <sys/timeout.h>
44
45#include <machine/bus.h>
46#include <machine/autoconf.h>
47#include <machine/openfirm.h>
48
49#include <sparc64/dev/ebusreg.h>
50#include <sparc64/dev/ebusvar.h>
51
52#include "pckbd.h"
53#if NPCKBD > 0
54#include <dev/ic/pckbcvar.h>
55#include <dev/pckbc/pckbdvar.h>
56#endif
57
58struct beeper_softc {
59	struct device		sc_dev;
60	bus_space_tag_t		sc_iot;
61	bus_space_handle_t	sc_ioh;
62	struct timeout		sc_to;
63	int 			sc_belltimeout, sc_bellactive;
64};
65
66#define	BEEP_REG	0
67
68int	beeper_match(struct device *, void *, void *);
69void	beeper_attach(struct device *, struct device *, void *);
70
71const struct cfattach beeper_ca = {
72	sizeof(struct beeper_softc), beeper_match, beeper_attach
73};
74
75struct cfdriver beeper_cd = {
76	NULL, "beeper", DV_DULL
77};
78
79#if NPCKBD > 0
80void beeper_stop(void *);
81void beeper_bell(void *, u_int, u_int, u_int, int);
82#endif
83
84int
85beeper_match(struct device *parent, void *match, void *aux)
86{
87	struct ebus_attach_args *ea = aux;
88
89	if (strcmp(ea->ea_name, "beeper") == 0)
90		return (1);
91	return (0);
92}
93
94void
95beeper_attach(struct device *parent, struct device *self, void *aux)
96{
97	struct beeper_softc *sc = (void *)self;
98	struct ebus_attach_args *ea = aux;
99
100	sc->sc_iot = ea->ea_memtag;
101
102	/* Use prom address if available, otherwise map it. */
103	if (ea->ea_nvaddrs) {
104		if (bus_space_map(sc->sc_iot, ea->ea_vaddrs[0], 0,
105		    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) {
106			printf(": can't map PROM register space\n");
107			return;
108		}
109	} else if (ebus_bus_map(sc->sc_iot, 0,
110	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 0, 0,
111	    &sc->sc_ioh) != 0) {
112		printf(": can't map register space\n");
113                return;
114	}
115
116#if NPCKBD > 0
117	timeout_set(&sc->sc_to, beeper_stop, sc);
118	pckbd_hookup_bell(beeper_bell, sc);
119#endif
120	printf("\n");
121}
122
123#if NPCKBD > 0
124void
125beeper_stop(void *vsc)
126{
127	struct beeper_softc *sc = vsc;
128	int s;
129
130	s = spltty();
131	bus_space_write_4(sc->sc_iot, sc->sc_ioh, BEEP_REG, 0);
132	sc->sc_bellactive = 0;
133	sc->sc_belltimeout = 0;
134	splx(s);
135}
136
137void
138beeper_bell(void *vsc, u_int pitch, u_int period, u_int volume, int poll)
139{
140	struct beeper_softc *sc = vsc;
141	int s;
142
143	s = spltty();
144	if (sc->sc_bellactive) {
145		if (sc->sc_belltimeout == 0)
146			timeout_del(&sc->sc_to);
147	}
148	if (pitch == 0 || period == 0) {
149		beeper_stop(sc);
150		splx(s);
151		return;
152	}
153	if (!sc->sc_bellactive) {
154		sc->sc_bellactive = 1;
155		sc->sc_belltimeout = 1;
156		bus_space_write_4(sc->sc_iot, sc->sc_ioh, BEEP_REG, 1);
157		timeout_add_msec(&sc->sc_to, period);
158	}
159	splx(s);
160}
161#endif /* NPCKBD > 0 */
162