1 /* $NetBSD: auxio.c,v 1.3 2001/10/23 20:59:42 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2000, 2001 Matthew R. Green 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. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * AUXIO registers support on the sbus & ebus2, used for the floppy driver 33 * and to control the system LED, for the BLINK option. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/callout.h> 40 #include <sys/errno.h> 41 #include <sys/device.h> 42 #include <sys/malloc.h> 43 44 #include <machine/autoconf.h> 45 #include <machine/cpu.h> 46 47 #include <dev/ebus/ebusreg.h> 48 #include <sparc64/dev/ebusvar.h> 49 #include <sparc64/dev/sbusvar.h> 50 #include <sparc64/dev/auxioreg.h> 51 52 /* 53 * on sun4u, auxio exists with one register (LED) on the sbus, and 5 54 * registers on the ebus2 (pci) (LED, PCIMODE, FREQUENCY, SCSI 55 * OSCILLATOR, and TEMP SENSE. 56 */ 57 58 struct auxio_softc { 59 struct device sc_dev; 60 61 /* parent's tag */ 62 bus_space_tag_t sc_tag; 63 64 /* handles to the various auxio regsiter sets */ 65 bus_space_handle_t sc_led; 66 bus_space_handle_t sc_pci; 67 bus_space_handle_t sc_freq; 68 bus_space_handle_t sc_scsi; 69 bus_space_handle_t sc_temp; 70 71 int sc_flags; 72 #define AUXIO_LEDONLY 0x1 73 #define AUXIO_EBUS 0x2 74 #define AUXIO_SBUS 0x4 75 }; 76 77 #define AUXIO_ROM_NAME "auxio" 78 79 void auxio_attach_common(struct auxio_softc *); 80 int auxio_ebus_match(struct device *, struct cfdata *, void *); 81 void auxio_ebus_attach(struct device *, struct device *, void *); 82 int auxio_sbus_match(struct device *, struct cfdata *, void *); 83 void auxio_sbus_attach(struct device *, struct device *, void *); 84 85 struct cfattach auxio_ebus_ca = { 86 sizeof(struct auxio_softc), auxio_ebus_match, auxio_ebus_attach 87 }; 88 struct cfattach auxio_sbus_ca = { 89 sizeof(struct auxio_softc), auxio_sbus_match, auxio_sbus_attach 90 }; 91 92 #ifdef BLINK 93 static struct callout blink_ch = CALLOUT_INITIALIZER; 94 95 static void auxio_blink(void *); 96 97 static void 98 auxio_blink(x) 99 void *x; 100 { 101 struct auxio_softc *sc = x; 102 int s; 103 u_int32_t led; 104 105 s = splhigh(); 106 if (sc->sc_flags & AUXIO_EBUS) 107 led = le32toh(bus_space_read_4(sc->sc_tag, sc->sc_led, 0)); 108 else 109 led = bus_space_read_1(sc->sc_tag, sc->sc_led, 0); 110 if (led & AUXIO_LED_LED) 111 led = 0; 112 else 113 led = AUXIO_LED_LED; 114 if (sc->sc_flags & AUXIO_EBUS) 115 bus_space_write_4(sc->sc_tag, sc->sc_led, 0, htole32(led)); 116 else 117 bus_space_write_1(sc->sc_tag, sc->sc_led, 0, led); 118 splx(s); 119 120 /* 121 * Blink rate is: 122 * full cycle every second if completely idle (loadav = 0) 123 * full cycle every 2 seconds if loadav = 1 124 * full cycle every 3 seconds if loadav = 2 125 * etc. 126 */ 127 s = (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1)); 128 callout_reset(&blink_ch, s, auxio_blink, sc); 129 } 130 #endif 131 132 void 133 auxio_attach_common(sc) 134 struct auxio_softc *sc; 135 { 136 #ifdef BLINK 137 static int do_once = 1; 138 139 /* only start one blinker */ 140 if (do_once) { 141 auxio_blink(sc); 142 do_once = 0; 143 } 144 #endif 145 printf("\n"); 146 } 147 148 int 149 auxio_ebus_match(parent, cf, aux) 150 struct device *parent; 151 struct cfdata *cf; 152 void *aux; 153 { 154 struct ebus_attach_args *ea = aux; 155 156 return (strcmp(AUXIO_ROM_NAME, ea->ea_name) == 0); 157 } 158 159 void 160 auxio_ebus_attach(parent, self, aux) 161 struct device *parent, *self; 162 void *aux; 163 { 164 struct auxio_softc *sc = (struct auxio_softc *)self; 165 struct ebus_attach_args *ea = aux; 166 167 if (ea->ea_nregs < 1 || ea->ea_nvaddrs < 1) { 168 printf(": no registers??\n"); 169 return; 170 } 171 172 if (ea->ea_nregs != 5 || ea->ea_nvaddrs != 5) { 173 printf(": not 5 (%d) registers, only setting led", 174 ea->ea_nregs); 175 sc->sc_flags = AUXIO_LEDONLY|AUXIO_EBUS; 176 } else { 177 sc->sc_flags = AUXIO_EBUS; 178 sc->sc_pci = (bus_space_handle_t)(u_long)ea->ea_vaddrs[1]; 179 sc->sc_freq = (bus_space_handle_t)(u_long)ea->ea_vaddrs[2]; 180 sc->sc_scsi = (bus_space_handle_t)(u_long)ea->ea_vaddrs[3]; 181 sc->sc_temp = (bus_space_handle_t)(u_long)ea->ea_vaddrs[4]; 182 } 183 sc->sc_led = (bus_space_handle_t)(u_long)ea->ea_vaddrs[0]; 184 185 sc->sc_tag = ea->ea_bustag; 186 187 auxio_attach_common(sc); 188 } 189 190 int 191 auxio_sbus_match(parent, cf, aux) 192 struct device *parent; 193 struct cfdata *cf; 194 void *aux; 195 { 196 struct sbus_attach_args *sa = aux; 197 198 return (strcmp(AUXIO_ROM_NAME, sa->sa_name) == 0); 199 } 200 201 void 202 auxio_sbus_attach(parent, self, aux) 203 struct device *parent, *self; 204 void *aux; 205 { 206 struct auxio_softc *sc = (struct auxio_softc *)self; 207 struct sbus_attach_args *sa = aux; 208 209 if (sa->sa_nreg < 1 || sa->sa_npromvaddrs < 1) { 210 printf(": no registers??\n"); 211 return; 212 } 213 214 if (sa->sa_nreg != 1 || sa->sa_npromvaddrs != 1) { 215 printf(": not 1 (%d/%d) registers??", sa->sa_nreg, 216 sa->sa_npromvaddrs); 217 return; 218 } 219 220 /* sbus auxio only has one set of registers */ 221 sc->sc_flags = AUXIO_LEDONLY|AUXIO_SBUS; 222 sc->sc_led = (bus_space_handle_t)(u_long)sa->sa_promvaddr; 223 224 sc->sc_tag = sa->sa_bustag; 225 226 auxio_attach_common(sc); 227 } 228