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