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