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