xref: /netbsd-src/sys/arch/sparc64/dev/auxio.c (revision 1dc652ef5a0bffbd0917f95e0797bad8c6fc8efd)
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