1 /* $NetBSD: vrled.c,v 1.4 2002/01/27 14:18:13 takemura 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 struct cfattach vrled_ca = { 69 sizeof(struct vrled_softc), vrledmatch, vrledattach 70 }; 71 72 struct vrled_softc *this_led; 73 74 static inline void 75 vrled_write(struct vrled_softc *sc, int port, unsigned short val) 76 { 77 78 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 79 } 80 81 static inline unsigned short 82 vrled_read(struct vrled_softc *sc, int port) 83 { 84 85 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 86 } 87 88 static int 89 vrledmatch(struct device *parent, struct cfdata *cf, void *aux) 90 { 91 92 return (1); 93 } 94 95 static void 96 vrledattach(struct device *parent, struct device *self, void *aux) 97 { 98 struct vrled_softc *sc = (struct vrled_softc *)self; 99 struct vrip_attach_args *va = aux; 100 101 bus_space_tag_t iot = va->va_iot; 102 bus_space_handle_t ioh; 103 104 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 105 printf(": can't map bus space\n"); 106 return; 107 } 108 109 sc->sc_iot = iot; 110 sc->sc_ioh = ioh; 111 112 if (!(sc->sc_handler = 113 vrip_intr_establish(va->va_vc, va->va_unit, 0, IPL_TTY, 114 vrled_intr, sc))) { 115 printf (": can't map interrupt line.\n"); 116 return; 117 } 118 119 printf("\n"); 120 /* clear interrupt status */ 121 vrled_write(sc, LEDINT_REG_W, LEDINT_ALL); 122 123 /* basic setup */ 124 sc->sc_state_cnt = 1; 125 vrled_write(sc, LEDASTC_REG_W, 1); /* 1time */ 126 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 127 vrled_stop(sc); 128 129 sc->sc_hook = config_hook(CONFIG_HOOK_SET, 130 CONFIG_HOOK_LED, CONFIG_HOOK_SHARE, vrled_event, sc); 131 132 this_led = sc; 133 } 134 135 136 /* 137 * LED interrupt handler. 138 * 139 */ 140 int 141 vrled_intr(void *arg) 142 { 143 struct vrled_softc *sc = arg; 144 unsigned int intstat; 145 146 intstat = vrled_read(sc, LEDINT_REG_W); 147 /* clear interrupt status */ 148 vrled_write(sc, LEDINT_REG_W, intstat); 149 if (intstat&LEDINT_AUTOSTOP) { 150 vrled_change_state(sc); 151 } 152 return (0); 153 } 154 155 /* 156 * LED turn OFF 157 * 158 */ 159 void 160 vrled_stop(struct vrled_softc *sc) 161 { 162 vrled_write(sc, LEDHTS_REG_W, LEDHTS_DIV16SEC); 163 vrled_write(sc, LEDLTS_REG_W, LEDLTS_4SEC); 164 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 165 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 166 167 sc->sc_state = LEDOFF; 168 sc->sc_next = LEDOFF; 169 } 170 171 /* 172 * LED turn ON 173 * 174 */ 175 void 176 vrled_on(struct vrled_softc *sc) 177 { 178 vrled_write(sc, LEDHTS_REG_W, LEDHTS_SEC); 179 vrled_write(sc, LEDLTS_REG_W, LEDLTS_DIV16SEC); 180 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 181 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 182 183 sc->sc_state = LEDON; 184 sc->sc_next = LEDON; 185 } 186 187 /* 188 * LED blink 189 * 190 */ 191 void 192 vrled_blink(struct vrled_softc *sc) 193 { 194 int ledhts; 195 int ledlts; 196 197 switch (sc->sc_next) { 198 case LED1SB: 199 ledhts = LEDHTS_DIV2SEC; 200 ledlts = LEDLTS_DIV2SEC; 201 break; 202 case LED2SB: 203 ledhts = LEDHTS_SEC; 204 ledlts = LEDLTS_SEC; 205 break; 206 default: 207 vrled_stop(sc); 208 return; 209 } 210 211 vrled_write(sc, LEDHTS_REG_W, ledhts); 212 vrled_write(sc, LEDLTS_REG_W, ledlts); 213 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 214 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP); 215 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 216 217 sc->sc_state = sc->sc_next; 218 } 219 220 /* 221 * LED flash once 222 * 223 */ 224 void 225 vrled_flash(struct vrled_softc *sc) 226 { 227 int ledhts; 228 int ledlts; 229 230 switch (sc->sc_next) { 231 case LED8DIVF: 232 ledhts = LEDHTS_DIV16SEC; 233 ledlts = LEDLTS_DIV16SEC; 234 break; 235 case LED4DIVF: 236 ledhts = LEDHTS_DIV8SEC; 237 ledlts = LEDLTS_DIV8SEC; 238 break; 239 case LED2DIVF: 240 ledhts = LEDHTS_DIV4SEC; 241 ledlts = LEDLTS_DIV4SEC; 242 break; 243 case LED1SF: 244 ledhts = LEDHTS_DIV2SEC; 245 ledlts = LEDLTS_DIV2SEC; 246 break; 247 default: 248 vrled_stop(sc); 249 return; 250 } 251 252 vrled_write(sc, LEDHTS_REG_W, ledhts); 253 vrled_write(sc, LEDLTS_REG_W, ledlts); 254 vrled_write(sc, LEDASTC_REG_W, 2); /* 2time */ 255 vrled_write(sc, LEDCNT_REG_W, LEDCNT_AUTOSTOP|LEDCNT_BLINK); 256 257 sc->sc_state = sc->sc_next; 258 sc->sc_next = LEDOFF; 259 sc->sc_state_cnt = 1; 260 } 261 262 /* 263 * Change LED state 264 * 265 */ 266 void 267 vrled_change_state(struct vrled_softc *sc) 268 { 269 270 switch (sc->sc_next) { 271 case LEDOFF: 272 vrled_stop(sc); 273 break; 274 case LEDON: 275 vrled_on(sc); 276 break; 277 case LED1SB: 278 case LED2SB: 279 vrled_blink(sc); 280 break; 281 case LED8DIVF: 282 case LED4DIVF: 283 case LED2DIVF: 284 case LED1SF: 285 vrled_flash(sc); 286 break; 287 default: 288 vrled_stop(sc); 289 break; 290 } 291 } 292 293 /* 294 * Set LED state 295 * 296 */ 297 void 298 vrled_set_state(struct vrled_softc *sc, vrled_status state) 299 { 300 301 int ledstate; 302 303 ledstate = vrled_read(sc, LEDCNT_REG_W); 304 if (ledstate&LEDCNT_BLINK) { /* currently processing */ 305 if (sc->sc_next == state) 306 sc->sc_state_cnt++; 307 switch (sc->sc_next) { 308 case LEDOFF: 309 case LEDON: 310 sc->sc_next = state; 311 break; 312 case LED8DIVF: 313 case LED4DIVF: 314 case LED2DIVF: 315 case LED1SF: 316 switch (state) { 317 case LEDOFF: 318 case LED8DIVF: 319 case LED4DIVF: 320 case LED2DIVF: 321 case LED1SF: 322 sc->sc_next = state; 323 break; 324 default: 325 break; 326 } 327 break; 328 case LED1SB: 329 case LED2SB: 330 switch (state) { 331 case LEDOFF: 332 case LEDON: 333 case LED1SB: 334 case LED2SB: 335 sc->sc_next = state; 336 break; 337 default: 338 break; 339 } 340 break; 341 default: 342 sc->sc_next = LEDOFF; 343 break; 344 } 345 return; 346 } 347 sc->sc_next = state; 348 vrled_change_state(sc); 349 } 350 351 /* 352 * LED config hook events 353 * 354 */ 355 int 356 vrled_event(void *ctx, int type, long id, void *msg) 357 { 358 struct vrled_softc *sc = (struct vrled_softc *)ctx; 359 int why =*(int *)msg; 360 361 if (type != CONFIG_HOOK_SET 362 || id != CONFIG_HOOK_LED) 363 return (1); 364 if (msg == NULL) 365 return (1); 366 367 switch (why) { 368 case CONFIG_HOOK_LED_OFF: 369 vrled_set_state(sc, LEDOFF); 370 break; 371 case CONFIG_HOOK_LED_ON: 372 vrled_set_state(sc, LEDON); 373 break; 374 case CONFIG_HOOK_LED_FLASH: 375 vrled_set_state(sc, LED8DIVF); 376 break; 377 case CONFIG_HOOK_LED_FLASH2: 378 vrled_set_state(sc, LED4DIVF); 379 break; 380 case CONFIG_HOOK_LED_FLASH5: 381 vrled_set_state(sc, LED2DIVF); 382 break; 383 case CONFIG_HOOK_LED_BLINK: 384 vrled_set_state(sc, LED1SB); 385 break; 386 case CONFIG_HOOK_LED_BLINK2: 387 vrled_set_state(sc, LED2SB); 388 break; 389 default: 390 vrled_set_state(sc, LEDOFF); 391 } 392 return (0); 393 } 394 395 /* end */ 396