xref: /openbsd-src/sys/arch/sparc64/dev/auxio.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: auxio.c,v 1.7 2005/03/09 18:41:48 miod Exp $	*/
2 /*	$NetBSD: auxio.c,v 1.1 2000/04/15 03:08:13 mrg Exp $	*/
3 
4 /*
5  * Copyright (c) 2000 Matthew R. Green
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * AUXIO registers support on the sbus & ebus2.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/device.h>
40 #include <sys/timeout.h>
41 #include <sys/kernel.h>
42 
43 #include <machine/autoconf.h>
44 #include <machine/cpu.h>
45 
46 #include <sparc64/dev/ebusreg.h>
47 #include <sparc64/dev/ebusvar.h>
48 #include <sparc64/dev/sbusvar.h>
49 #include <sparc64/dev/auxioreg.h>
50 #include <sparc64/dev/auxiovar.h>
51 
52 #define	AUXIO_ROM_NAME		"auxio"
53 
54 /*
55  * ebus code.
56  */
57 int	auxio_ebus_match(struct device *, void *, void *);
58 void	auxio_ebus_attach(struct device *, struct device *, void *);
59 int	auxio_sbus_match(struct device *, void *, void *);
60 void	auxio_sbus_attach(struct device *, struct device *, void *);
61 void	auxio_attach_common(struct auxio_softc *);
62 
63 struct cfattach auxio_ebus_ca = {
64 	sizeof(struct auxio_softc), auxio_ebus_match, auxio_ebus_attach
65 };
66 
67 struct cfattach auxio_sbus_ca = {
68 	sizeof(struct auxio_softc), auxio_sbus_match, auxio_sbus_attach
69 };
70 
71 struct cfdriver auxio_cd = {
72 	NULL, "auxio", DV_DULL
73 };
74 
75 void auxio_led_blink(void *, int);
76 
77 int
78 auxio_ebus_match(parent, cf, aux)
79 	struct device *parent;
80 	void *cf;
81 	void *aux;
82 {
83 	struct ebus_attach_args *ea = aux;
84 
85 	return (strcmp(AUXIO_ROM_NAME, ea->ea_name) == 0);
86 }
87 
88 void
89 auxio_ebus_attach(parent, self, aux)
90 	struct device *parent, *self;
91 	void *aux;
92 {
93 	struct auxio_softc *sc = (struct auxio_softc *)self;
94 	struct ebus_attach_args *ea = aux;
95 
96 	if (ea->ea_nregs < 1 || ea->ea_nvaddrs < 1) {
97 		printf(": no registers??\n");
98 		return;
99 	}
100 
101 	sc->sc_tag = ea->ea_memtag;
102 
103 	if (ea->ea_nregs != 5 || ea->ea_nvaddrs != 5) {
104 		printf(": not 5 (%d) registers, only setting led",
105 		    ea->ea_nregs);
106 		sc->sc_flags = AUXIO_LEDONLY|AUXIO_EBUS;
107 	} else {
108 		sc->sc_flags = AUXIO_EBUS;
109 		if (bus_space_map(sc->sc_tag, ea->ea_vaddrs[2],
110 		    sizeof(u_int32_t), BUS_SPACE_MAP_PROMADDRESS,
111 		    &sc->sc_freq)) {
112 			printf(": unable to map freq\n");
113 			return;
114 		}
115 		if (bus_space_map(sc->sc_tag, ea->ea_vaddrs[3],
116 		    sizeof(u_int32_t), BUS_SPACE_MAP_PROMADDRESS,
117 		    &sc->sc_scsi)) {
118 			printf(": unable to map SCSI\n");
119 			return;
120 		}
121 		if (bus_space_map(sc->sc_tag, ea->ea_vaddrs[4],
122 		    sizeof(u_int32_t), BUS_SPACE_MAP_PROMADDRESS,
123 		    &sc->sc_temp)) {
124 			printf(": unable to map temp\n");
125 			return;
126 		}
127 	}
128 
129 	if (bus_space_map(sc->sc_tag, ea->ea_vaddrs[0], sizeof(u_int32_t),
130 	    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_led)) {
131 		printf(": unable to map LED\n");
132 		return;
133 	}
134 
135 	auxio_attach_common(sc);
136 }
137 
138 int
139 auxio_sbus_match(parent, cf, aux)
140 	struct device *parent;
141 	void *cf;
142 	void *aux;
143 {
144 	struct sbus_attach_args *sa = aux;
145 
146 	return (strcmp(AUXIO_ROM_NAME, sa->sa_name) == 0);
147 }
148 
149 void
150 auxio_sbus_attach(parent, self, aux)
151 	struct device *parent, *self;
152 	void *aux;
153 {
154 	struct auxio_softc *sc = (struct auxio_softc *)self;
155 	struct sbus_attach_args *sa = aux;
156 
157 	sc->sc_tag = sa->sa_bustag;
158 
159 	if (sa->sa_nreg < 1 || sa->sa_npromvaddrs < 1) {
160 		printf(": no registers??\n");
161 		return;
162 	}
163 
164 	if (sa->sa_nreg != 1 || sa->sa_npromvaddrs != 1) {
165 		printf(": not 1 (%d/%d) registers??", sa->sa_nreg, sa->sa_npromvaddrs);
166 		return;
167 	}
168 
169 	/* sbus auxio only has one set of registers */
170 	sc->sc_flags = AUXIO_LEDONLY|AUXIO_SBUS;
171 	if (bus_space_map(sc->sc_tag, sa->sa_promvaddr, 1,
172 	    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_led)) {
173 		printf(": couldn't map registers\n");
174 		return;
175 	}
176 
177 	auxio_attach_common(sc);
178 }
179 
180 void
181 auxio_attach_common(sc)
182 	struct auxio_softc *sc;
183 {
184 	sc->sc_blink.bl_func = auxio_led_blink;
185 	sc->sc_blink.bl_arg = sc;
186 	blink_led_register(&sc->sc_blink);
187 	printf("\n");
188 }
189 
190 void
191 auxio_led_blink(void *vsc, int on)
192 {
193 	struct auxio_softc *sc = vsc;
194 	u_int32_t led;
195 	int s;
196 
197 	s = splhigh();
198 
199 	if (sc->sc_flags & AUXIO_EBUS)
200 		led = letoh32(bus_space_read_4(sc->sc_tag, sc->sc_led, 0));
201 	else
202 		led = bus_space_read_1(sc->sc_tag, sc->sc_led, 0);
203 
204 	if (on)
205 		led |= AUXIO_LED_LED;
206 	else
207 		led &= ~AUXIO_LED_LED;
208 
209 	if (sc->sc_flags & AUXIO_EBUS)
210 		bus_space_write_4(sc->sc_tag, sc->sc_led, 0, htole32(led));
211 	else
212 		bus_space_write_1(sc->sc_tag, sc->sc_led, 0, led);
213 
214 	splx(s);
215 }
216 
217 int
218 auxio_fd_control(u_int32_t bits)
219 {
220 	struct auxio_softc *sc;
221 	u_int32_t led;
222 
223 	if (auxio_cd.cd_ndevs == 0) {
224 		return ENXIO;
225 	}
226 
227 	/*
228 	 * XXX This does not handle > 1 auxio correctly.
229 	 * We'll assume the floppy drive is tied to first auxio found.
230 	 */
231 	sc = (struct auxio_softc *)auxio_cd.cd_devs[0];
232 	if (sc->sc_flags & AUXIO_EBUS)
233 		led = letoh32(bus_space_read_4(sc->sc_tag, sc->sc_led, 0));
234 	else
235 		led = bus_space_read_1(sc->sc_tag, sc->sc_led, 0);
236 
237 	led = (led & ~AUXIO_LED_FLOPPY_MASK) | bits;
238 
239 	if (sc->sc_flags & AUXIO_EBUS)
240 		bus_space_write_4(sc->sc_tag, sc->sc_led, 0, htole32(led));
241 	else
242 		bus_space_write_1(sc->sc_tag, sc->sc_led, 0, led);
243 
244 	return 0;
245 }
246