lasi.c revision 1.8
1/*	$OpenBSD: lasi.c,v 1.8 2002/03/14 01:26:31 millert Exp $	*/
2
3/*
4 * Copyright (c) 1998-2002 Michael Shalayeff
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 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Michael Shalayeff.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF MIND,
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#undef LASIDEBUG
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/device.h>
38#include <sys/reboot.h>
39
40#include <machine/bus.h>
41#include <machine/iomod.h>
42#include <machine/autoconf.h>
43
44#include <hppa/dev/cpudevs.h>
45
46#include <hppa/gsc/gscbusvar.h>
47
48struct lasi_hwr {
49	u_int32_t lasi_power;
50#define	LASI_BLINK	0x01
51#define	LASI_ON		0x02
52	u_int32_t lasi_error;
53	u_int32_t lasi_version;
54	u_int32_t lasi_reset;
55	u_int32_t lasi_arbmask;
56};
57
58struct lasi_trs {
59	u_int32_t lasi_irr;	/* int requset register */
60	u_int32_t lasi_imr;	/* int mask register */
61	u_int32_t lasi_ipr;	/* int pending register */
62	u_int32_t lasi_icr;	/* int command? register */
63	u_int32_t lasi_iar;	/* int acquire? register */
64};
65
66struct lasi_softc {
67	struct device sc_dev;
68	struct gscbus_ic sc_ic;
69
70	struct lasi_hwr volatile *sc_hw;
71	struct lasi_trs volatile *sc_trs;
72	struct gsc_attach_args ga;	/* for deferred attach */
73};
74
75int	lasimatch(struct device *, void *, void *);
76void	lasiattach(struct device *, struct device *, void *);
77void	lasi_gsc_attach(struct device *);
78
79struct cfattach lasi_ca = {
80	sizeof(struct lasi_softc), lasimatch, lasiattach
81};
82
83struct cfdriver lasi_cd = {
84	NULL, "lasi", DV_DULL
85};
86
87void lasi_intr_establish(void *v, u_int32_t mask);
88void lasi_intr_disestablish(void *v, u_int32_t mask);
89u_int32_t lasi_intr_check(void *v);
90void lasi_intr_ack(void *v, u_int32_t mask);
91void lasi_cold_hook(int on);
92
93
94int
95lasimatch(parent, cfdata, aux)
96	struct device *parent;
97	void *cfdata;
98	void *aux;
99{
100	register struct confargs *ca = aux;
101	/* register struct cfdata *cf = cfdata; */
102
103	if (ca->ca_type.iodc_type != HPPA_TYPE_BHA ||
104	    ca->ca_type.iodc_sv_model != HPPA_BHA_LASI)
105		return 0;
106
107	return 1;
108}
109
110void
111lasiattach(parent, self, aux)
112	struct device *parent;
113	struct device *self;
114	void *aux;
115{
116	register struct confargs *ca = aux;
117	register struct lasi_softc *sc = (struct lasi_softc *)self;
118	bus_space_handle_t ioh;
119	int s, in;
120
121	if (bus_space_map(ca->ca_iot, ca->ca_hpa + 0xc000,
122			  IOMOD_HPASIZE, 0, &ioh)) {
123#ifdef DEBUG
124		printf("lasiattach: can't map IO space\n");
125#endif
126		return;
127	}
128
129	sc->sc_trs = (struct lasi_trs *)ca->ca_hpa;
130	sc->sc_hw = (struct lasi_hwr *)(ca->ca_hpa + 0xc000);
131
132	/* XXX should we reset the chip here? */
133
134	printf (": rev %d.%d\n", (sc->sc_hw->lasi_version & 0xf0) >> 4,
135		sc->sc_hw->lasi_version & 0xf);
136
137	/* interrupts guts */
138	s = splhigh();
139	sc->sc_trs->lasi_iar = cpu_gethpa(0) | (31 - ca->ca_irq);
140	sc->sc_trs->lasi_icr = 0;
141	sc->sc_trs->lasi_imr = ~0U;
142	in = sc->sc_trs->lasi_irr;
143	sc->sc_trs->lasi_imr = 0;
144	splx(s);
145
146	sc->sc_ic.gsc_type = gsc_lasi;
147	sc->sc_ic.gsc_dv = sc;
148	sc->sc_ic.gsc_intr_establish = lasi_intr_establish;
149	sc->sc_ic.gsc_intr_disestablish = lasi_intr_disestablish;
150	sc->sc_ic.gsc_intr_check = lasi_intr_check;
151	sc->sc_ic.gsc_intr_ack = lasi_intr_ack;
152
153	sc->ga.ga_ca = *ca;	/* clone from us */
154	if (sc->sc_dev.dv_unit)
155		config_defer(self, lasi_gsc_attach);
156	else {
157		extern void (*cold_hook)(int);
158
159		lasi_gsc_attach(self);
160		cold_hook = lasi_cold_hook;
161	}
162}
163
164void
165lasi_gsc_attach(self)
166	struct device *self;
167{
168	struct lasi_softc *sc = (struct lasi_softc *)self;
169
170	sc->ga.ga_name = "gsc";
171	sc->ga.ga_ic = &sc->sc_ic;
172	config_found(self, &sc->ga, gscprint);
173}
174
175void
176lasi_cold_hook(on)
177	int on;
178{
179	register struct lasi_softc *sc = lasi_cd.cd_devs[0];
180
181	if (!sc)
182		return;
183
184	switch (on) {
185	case HPPA_COLD_COLD:
186		sc->sc_hw->lasi_power = LASI_BLINK;
187		break;
188	case HPPA_COLD_HOT:
189		sc->sc_hw->lasi_power = 0;
190		break;
191	case HPPA_COLD_OFF:
192		sc->sc_hw->lasi_power = LASI_BLINK;
193		break;
194	}
195}
196
197void
198lasi_intr_establish(v, mask)
199	void *v;
200	u_int32_t mask;
201{
202	register struct lasi_softc *sc = v;
203
204	sc->sc_trs->lasi_imr |= mask;
205}
206
207void
208lasi_intr_disestablish(v, mask)
209	void *v;
210	u_int32_t mask;
211{
212	register struct lasi_softc *sc = v;
213
214	sc->sc_trs->lasi_imr &= ~mask;
215}
216
217u_int32_t
218lasi_intr_check(v)
219	void *v;
220{
221	register struct lasi_softc *sc = v;
222	register u_int32_t irr, imr, ipr;
223
224	imr = sc->sc_trs->lasi_imr;
225	ipr = sc->sc_trs->lasi_ipr;
226	irr = sc->sc_trs->lasi_irr;
227	sc->sc_trs->lasi_irr = irr;
228
229#ifdef LASIDEBUG
230	printf ("%s: imr=0x%x, irr=0x%x, ipr=0x%x, iar=0x%x, icr=0x%x\n",
231		sc->sc_dev.dv_xname, imr, irr, ipr,
232		sc->sc_trs->lasi_iar, sc->sc_trs->lasi_icr);
233#endif
234
235	return irr;
236}
237
238void
239lasi_intr_ack(v, mask)
240	void *v;
241	u_int32_t mask;
242{
243	register struct lasi_softc *sc = v;
244
245	sc->sc_trs->lasi_imr |= mask;
246}
247