1*1dc652efSthorpej /* $NetBSD: auxio.c,v 1.27 2023/12/20 05:33:58 thorpej Exp $ */
22aba26f7Smrg
32aba26f7Smrg /*
4065f445dSmrg * Copyright (c) 2000, 2001, 2015 Matthew R. Green
52aba26f7Smrg * All rights reserved.
62aba26f7Smrg *
72aba26f7Smrg * Redistribution and use in source and binary forms, with or without
82aba26f7Smrg * modification, are permitted provided that the following conditions
92aba26f7Smrg * are met:
102aba26f7Smrg * 1. Redistributions of source code must retain the above copyright
112aba26f7Smrg * notice, this list of conditions and the following disclaimer.
122aba26f7Smrg * 2. Redistributions in binary form must reproduce the above copyright
132aba26f7Smrg * notice, this list of conditions and the following disclaimer in the
142aba26f7Smrg * documentation and/or other materials provided with the distribution.
152aba26f7Smrg *
162aba26f7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
172aba26f7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
182aba26f7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
192aba26f7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
202aba26f7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
212aba26f7Smrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
222aba26f7Smrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
232aba26f7Smrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
242aba26f7Smrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252aba26f7Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262aba26f7Smrg * SUCH DAMAGE.
272aba26f7Smrg */
282aba26f7Smrg
292aba26f7Smrg /*
30abcb6203Smrg * AUXIO registers support on the sbus & ebus2, used for the floppy driver
31abcb6203Smrg * and to control the system LED, for the BLINK option.
322aba26f7Smrg */
332aba26f7Smrg
34ed517291Slukem #include <sys/cdefs.h>
35*1dc652efSthorpej __KERNEL_RCSID(0, "$NetBSD: auxio.c,v 1.27 2023/12/20 05:33:58 thorpej Exp $");
36ed517291Slukem
37d00e9c25Sheas #include "opt_auxio.h"
38d00e9c25Sheas
392aba26f7Smrg #include <sys/param.h>
402aba26f7Smrg #include <sys/systm.h>
41abcb6203Smrg #include <sys/kernel.h>
42abcb6203Smrg #include <sys/callout.h>
432aba26f7Smrg #include <sys/errno.h>
442aba26f7Smrg #include <sys/device.h>
452aba26f7Smrg
462aba26f7Smrg #include <machine/autoconf.h>
472aba26f7Smrg #include <machine/cpu.h>
482aba26f7Smrg
49abcb6203Smrg #include <dev/ebus/ebusreg.h>
500eed6807Smrg #include <dev/ebus/ebusvar.h>
514887604bSnakayama #include <dev/sbus/sbusvar.h>
522aba26f7Smrg #include <sparc64/dev/auxioreg.h>
536238d5faSjnemeth #include <sparc64/dev/auxiovar.h>
54abcb6203Smrg
55065f445dSmrg static uint32_t auxio_read_led(struct auxio_softc *);
56065f445dSmrg static void auxio_write_led(struct auxio_softc *, uint32_t);
577e689e2dSmartin void auxio_attach_common(struct auxio_softc *);
582aba26f7Smrg
596238d5faSjnemeth extern struct cfdriver auxio_cd;
606238d5faSjnemeth
61065f445dSmrg static __inline__ uint32_t
auxio_read_led(struct auxio_softc * sc)62065f445dSmrg auxio_read_led(struct auxio_softc *sc)
63065f445dSmrg {
64065f445dSmrg uint32_t led;
65065f445dSmrg
66065f445dSmrg if (sc->sc_flags & AUXIO_EBUS)
67065f445dSmrg led = le32toh(bus_space_read_4(sc->sc_tag, sc->sc_led, 0));
68065f445dSmrg else
69065f445dSmrg led = bus_space_read_1(sc->sc_tag, sc->sc_led, 0);
70065f445dSmrg
71065f445dSmrg return led;
72065f445dSmrg }
73065f445dSmrg
74065f445dSmrg static __inline__ void
auxio_write_led(struct auxio_softc * sc,uint32_t led)75065f445dSmrg auxio_write_led(struct auxio_softc *sc, uint32_t led)
76065f445dSmrg {
77065f445dSmrg
78065f445dSmrg if (sc->sc_flags & AUXIO_EBUS)
79065f445dSmrg bus_space_write_4(sc->sc_tag, sc->sc_led, 0, htole32(led));
80065f445dSmrg else
81065f445dSmrg bus_space_write_1(sc->sc_tag, sc->sc_led, 0, led);
82065f445dSmrg }
83065f445dSmrg
84abcb6203Smrg #ifdef BLINK
8588ab7da9Sad static callout_t blink_ch;
86abcb6203Smrg static void auxio_blink(void *);
87abcb6203Smrg
887f549a86Smrg /* let someone disable it if it's already turned on; XXX sysctl? */
897f549a86Smrg int do_blink = 1;
907f549a86Smrg
91abcb6203Smrg static void
auxio_blink(void * x)921a509d61Scdi auxio_blink(void *x)
93abcb6203Smrg {
94abcb6203Smrg struct auxio_softc *sc = x;
95abcb6203Smrg int s;
961a509d61Scdi uint32_t led;
97abcb6203Smrg
987f549a86Smrg if (do_blink == 0)
997f549a86Smrg return;
1007f549a86Smrg
101065f445dSmrg mutex_enter(&sc->sc_lock);
102065f445dSmrg led = auxio_read_led(sc);
10343d3408bSbouyer led = led ^ AUXIO_LED_LED;
104065f445dSmrg auxio_write_led(sc, led);
105065f445dSmrg mutex_exit(&sc->sc_lock);
106abcb6203Smrg
107abcb6203Smrg /*
108abcb6203Smrg * Blink rate is:
109abcb6203Smrg * full cycle every second if completely idle (loadav = 0)
110abcb6203Smrg * full cycle every 2 seconds if loadav = 1
111abcb6203Smrg * full cycle every 3 seconds if loadav = 2
112abcb6203Smrg * etc.
113abcb6203Smrg */
114abcb6203Smrg s = (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1));
115abcb6203Smrg callout_reset(&blink_ch, s, auxio_blink, sc);
116abcb6203Smrg }
117abcb6203Smrg #endif
118abcb6203Smrg
1197e689e2dSmartin void
auxio_attach_common(struct auxio_softc * sc)1201a509d61Scdi auxio_attach_common(struct auxio_softc *sc)
121abcb6203Smrg {
122abcb6203Smrg static int do_once = 1;
123abcb6203Smrg
124abcb6203Smrg /* only start one blinker */
125abcb6203Smrg if (do_once) {
126065f445dSmrg mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
127d1f454e1Smlelstv #ifdef BLINK
128065f445dSmrg callout_init(&blink_ch, CALLOUT_MPSAFE);
129abcb6203Smrg auxio_blink(sc);
130d1f454e1Smlelstv #endif
131abcb6203Smrg do_once = 0;
132abcb6203Smrg }
133abcb6203Smrg printf("\n");
134abcb6203Smrg }
135abcb6203Smrg
1366238d5faSjnemeth int
auxio_fd_control(u_int32_t bits)1376238d5faSjnemeth auxio_fd_control(u_int32_t bits)
1386238d5faSjnemeth {
1396238d5faSjnemeth struct auxio_softc *sc;
1406238d5faSjnemeth u_int32_t led;
1416238d5faSjnemeth
1426238d5faSjnemeth if (auxio_cd.cd_ndevs == 0) {
1436238d5faSjnemeth return ENXIO;
1446238d5faSjnemeth }
1456238d5faSjnemeth
1466238d5faSjnemeth /*
1476238d5faSjnemeth * XXX This does not handle > 1 auxio correctly.
1486238d5faSjnemeth * We'll assume the floppy drive is tied to first auxio found.
1496238d5faSjnemeth */
1502dea63feScegger sc = device_lookup_private(&auxio_cd, 0);
151065f445dSmrg if (!sc) {
152065f445dSmrg return ENXIO;
153065f445dSmrg }
1546238d5faSjnemeth
155065f445dSmrg mutex_enter(&sc->sc_lock);
156065f445dSmrg led = auxio_read_led(sc);
1576238d5faSjnemeth led = (led & ~AUXIO_LED_FLOPPY_MASK) | bits;
158065f445dSmrg auxio_write_led(sc, led);
159065f445dSmrg mutex_exit(&sc->sc_lock);
1606238d5faSjnemeth
1616238d5faSjnemeth return 0;
1626238d5faSjnemeth }
163