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