1 /* $NetBSD: vrled.c,v 1.6 2002/10/02 05:26:56 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2000 SATO Kazumi. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/device.h> 31 #include <sys/reboot.h> 32 33 #include <machine/bus.h> 34 #include <machine/config_hook.h> 35 36 #include <hpcmips/vr/vripif.h> 37 #include <hpcmips/vr/vrledvar.h> 38 #include <hpcmips/vr/vrledreg.h> 39 40 41 #ifdef VRLEDDEBUG 42 #ifndef VRLEDDEBUG_CONF 43 #define VRLEDDEBUG_CONF 0 44 #endif /* VRLEDDEBUG_CONF */ 45 int vrleddebug = VRLEDDEBUG_CONF; 46 #define DPRINTF(arg) if (vrleddebug) printf arg; 47 #define VPRINTF(arg) if (bootverbose||vrleddebug) printf arg; 48 #else /* VRLEDDEBUG */ 49 #define DPRINTF(arg) 50 #define VPRINTF(arg) if (bootverbose) printf arg; 51 #endif /* VRLEDDEBUG */ 52 53 static int vrledmatch(struct device *, struct cfdata *, void *); 54 static void vrledattach(struct device *, struct device *, void *); 55 56 static void vrled_write(struct vrled_softc *, int, unsigned short); 57 static unsigned short vrled_read(struct vrled_softc *, int); 58 59 static void vrled_stop(struct vrled_softc *); 60 static void vrled_on(struct vrled_softc *); 61 static void vrled_blink(struct vrled_softc *); 62 static void vrled_flash(struct vrled_softc *); 63 static void vrled_change_state(struct vrled_softc *); 64 static int vrled_event(void *, int, long, void *); 65 66 int vrled_intr(void *); 67 68 CFATTACH_DECL(vrled, sizeof(struct vrled_softc), 69 vrledmatch, vrledattach, NULL, NULL); 70 71 struct vrled_softc *this_led; 72 73 static inline void 74 vrled_write(struct vrled_softc *sc, int port, unsigned short val) 75 { 76 77 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 78 } 79 80 static inline unsigned short 81 vrled_read(struct vrled_softc *sc, int port) 82 { 83 84 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 85 } 86 87 static int 88 vrledmatch(struct device *parent, struct cfdata *cf, void *aux) 89 { 90 91 return (1); 92 } 93 94 static void 95 vrledattach(struct device *parent, struct device *self, void *aux) 96 { 97 struct vrled_softc *sc = (struct vrled_softc *)self; 98 struct vrip_attach_args *va = aux; 99 100 bus_space_tag_t iot = va->va_iot; 101 bus_space_handle_t ioh; 102 103 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 104 printf(": can't map bus space\n"); 105 return; 106 } 107 108 sc->sc_iot = iot; 109 sc->sc_ioh = ioh; 110 111 if (!(sc->sc_handler = 112 vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY, 113 vrled_intr, sc))) { 114 printf (": can't map interrupt line.\n"); 115 return; 116 } 117 118 printf("\n"); 119 /* clear interrupt status */ 120 vrled_write(sc, LEDINT_REG_W, LEDINT_ALL); 121 122 /* basic setup */ 123 sc->sc_state_cnt = 1; 124 vrled_write(sc, LEDASTC_REG_W, 1); /* 1time */ 125 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 126 vrled_stop(sc); 127 128 sc->sc_hook = config_hook(CONFIG_HOOK_SET, 129 CONFIG_HOOK_LED, CONFIG_HOOK_SHARE, vrled_event, sc); 130 131 this_led = sc; 132 } 133 134 135 /* 136 * LED interrupt handler. 137 * 138 */ 139 int 140 vrled_intr(void *arg) 141 { 142 struct vrled_softc *sc = arg; 143 unsigned int intstat; 144 145 intstat = vrled_read(sc, LEDINT_REG_W); 146 /* clear interrupt status */ 147 vrled_write(sc, LEDINT_REG_W, intstat); 148 if (intstat&LEDINT_AUTOSTOP) { 149 vrled_change_state(sc); 150 } 151 return (0); 152 } 153 154 /* 155 * LED turn OFF 156 * 157 */ 158 void 159 vrled_stop(struct vrled_softc *sc) 160 { 161 vrled_write(sc, LEDHTS_REG_W, LEDHTS_DIV16SEC); 162 vrled_write(sc, LEDLTS_REG_W, LEDLTS_4SEC); 163 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 164 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 165 166 sc->sc_state = LEDOFF; 167 sc->sc_next = LEDOFF; 168 } 169 170 /* 171 * LED turn ON 172 * 173 */ 174 void 175 vrled_on(struct vrled_softc *sc) 176 { 177 vrled_write(sc, LEDHTS_REG_W, LEDHTS_SEC); 178 vrled_write(sc, LEDLTS_REG_W, LEDLTS_DIV16SEC); 179 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 180 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 181 182 sc->sc_state = LEDON; 183 sc->sc_next = LEDON; 184 } 185 186 /* 187 * LED blink 188 * 189 */ 190 void 191 vrled_blink(struct vrled_softc *sc) 192 { 193 int ledhts; 194 int ledlts; 195 196 switch (sc->sc_next) { 197 case LED1SB: 198 ledhts = LEDHTS_DIV2SEC; 199 ledlts = LEDLTS_DIV2SEC; 200 break; 201 case LED2SB: 202 ledhts = LEDHTS_SEC; 203 ledlts = LEDLTS_SEC; 204 break; 205 default: 206 vrled_stop(sc); 207 return; 208 } 209 210 vrled_write(sc, LEDHTS_REG_W, ledhts); 211 vrled_write(sc, LEDLTS_REG_W, ledlts); 212 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 213 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 214 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 215 216 sc->sc_state = sc->sc_next; 217 } 218 219 /* 220 * LED flash once 221 * 222 */ 223 void 224 vrled_flash(struct vrled_softc *sc) 225 { 226 int ledhts; 227 int ledlts; 228 229 switch (sc->sc_next) { 230 case LED8DIVF: 231 ledhts = LEDHTS_DIV16SEC; 232 ledlts = LEDLTS_DIV16SEC; 233 break; 234 case LED4DIVF: 235 ledhts = LEDHTS_DIV8SEC; 236 ledlts = LEDLTS_DIV8SEC; 237 break; 238 case LED2DIVF: 239 ledhts = LEDHTS_DIV4SEC; 240 ledlts = LEDLTS_DIV4SEC; 241 break; 242 case LED1SF: 243 ledhts = LEDHTS_DIV2SEC; 244 ledlts = LEDLTS_DIV2SEC; 245 break; 246 default: 247 vrled_stop(sc); 248 return; 249 } 250 251 vrled_write(sc, LEDHTS_REG_W, ledhts); 252 vrled_write(sc, LEDLTS_REG_W, ledlts); 253 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 254 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 255 256 sc->sc_state = sc->sc_next; 257 sc->sc_next = LEDOFF; 258 sc->sc_state_cnt = 1; 259 } 260 261 /* 262 * Change LED state 263 * 264 */ 265 void 266 vrled_change_state(struct vrled_softc *sc) 267 { 268 269 switch (sc->sc_next) { 270 case LEDOFF: 271 vrled_stop(sc); 272 break; 273 case LEDON: 274 vrled_on(sc); 275 break; 276 case LED1SB: 277 case LED2SB: 278 vrled_blink(sc); 279 break; 280 case LED8DIVF: 281 case LED4DIVF: 282 case LED2DIVF: 283 case LED1SF: 284 vrled_flash(sc); 285 break; 286 default: 287 vrled_stop(sc); 288 break; 289 } 290 } 291 292 /* 293 * Set LED state 294 * 295 */ 296 void 297 vrled_set_state(struct vrled_softc *sc, vrled_status state) 298 { 299 300 int ledstate; 301 302 ledstate = vrled_read(sc, LEDCNT_REG_W); 303 if (ledstate&LEDCNT_BLINK) { /* currently processing */ 304 if (sc->sc_next == state) 305 sc->sc_state_cnt++; 306 switch (sc->sc_next) { 307 case LEDOFF: 308 case LEDON: 309 sc->sc_next = state; 310 break; 311 case LED8DIVF: 312 case LED4DIVF: 313 case LED2DIVF: 314 case LED1SF: 315 switch (state) { 316 case LEDOFF: 317 case LED8DIVF: 318 case LED4DIVF: 319 case LED2DIVF: 320 case LED1SF: 321 sc->sc_next = state; 322 break; 323 default: 324 break; 325 } 326 break; 327 case LED1SB: 328 case LED2SB: 329 switch (state) { 330 case LEDOFF: 331 case LEDON: 332 case LED1SB: 333 case LED2SB: 334 sc->sc_next = state; 335 break; 336 default: 337 break; 338 } 339 break; 340 default: 341 sc->sc_next = LEDOFF; 342 break; 343 } 344 return; 345 } 346 sc->sc_next = state; 347 vrled_change_state(sc); 348 } 349 350 /* 351 * LED config hook events 352 * 353 */ 354 int 355 vrled_event(void *ctx, int type, long id, void *msg) 356 { 357 struct vrled_softc *sc = (struct vrled_softc *)ctx; 358 int why =*(int *)msg; 359 360 if (type != CONFIG_HOOK_SET 361 || id != CONFIG_HOOK_LED) 362 return (1); 363 if (msg == NULL) 364 return (1); 365 366 switch (why) { 367 case CONFIG_HOOK_LED_OFF: 368 vrled_set_state(sc, LEDOFF); 369 break; 370 case CONFIG_HOOK_LED_ON: 371 vrled_set_state(sc, LEDON); 372 break; 373 case CONFIG_HOOK_LED_FLASH: 374 vrled_set_state(sc, LED8DIVF); 375 break; 376 case CONFIG_HOOK_LED_FLASH2: 377 vrled_set_state(sc, LED4DIVF); 378 break; 379 case CONFIG_HOOK_LED_FLASH5: 380 vrled_set_state(sc, LED2DIVF); 381 break; 382 case CONFIG_HOOK_LED_BLINK: 383 vrled_set_state(sc, LED1SB); 384 break; 385 case CONFIG_HOOK_LED_BLINK2: 386 vrled_set_state(sc, LED2SB); 387 break; 388 default: 389 vrled_set_state(sc, LEDOFF); 390 } 391 return (0); 392 } 393 394 /* end */ 395