xref: /freebsd/sys/isa/syscons_isa.c (revision fe267a559009cbf34f9341666fe4d88a92c02d5e)
18a997770SDoug Rabson /*-
2*fe267a55SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*fe267a55SPedro F. Giffuni  *
48a997770SDoug Rabson  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
58a997770SDoug Rabson  * All rights reserved.
68a997770SDoug Rabson  *
78a997770SDoug Rabson  * Redistribution and use in source and binary forms, with or without
88a997770SDoug Rabson  * modification, are permitted provided that the following conditions
98a997770SDoug Rabson  * are met:
108a997770SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
118a997770SDoug Rabson  *    notice, this list of conditions and the following disclaimer as
128a997770SDoug Rabson  *    the first lines of this file unmodified.
138a997770SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
148a997770SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
158a997770SDoug Rabson  *    documentation and/or other materials provided with the distribution.
168a997770SDoug Rabson  *
178a997770SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
188a997770SDoug Rabson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
198a997770SDoug Rabson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
208a997770SDoug Rabson  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
218a997770SDoug Rabson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
228a997770SDoug Rabson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
238a997770SDoug Rabson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
248a997770SDoug Rabson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258a997770SDoug Rabson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268a997770SDoug Rabson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278a997770SDoug Rabson  */
288a997770SDoug Rabson 
298c9bbf48SDavid E. O'Brien #include <sys/cdefs.h>
308c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$");
318c9bbf48SDavid E. O'Brien 
328a997770SDoug Rabson #include "opt_syscons.h"
338a997770SDoug Rabson 
348a997770SDoug Rabson #include <sys/param.h>
358a997770SDoug Rabson #include <sys/systm.h>
368a997770SDoug Rabson #include <sys/kernel.h>
378a997770SDoug Rabson #include <sys/module.h>
388a997770SDoug Rabson #include <sys/bus.h>
39ce9edcf5SPoul-Henning Kamp #include <sys/cons.h>
4000d25f51SPoul-Henning Kamp #include <sys/kbio.h>
4100d25f51SPoul-Henning Kamp #include <sys/consio.h>
42dcb65c59SMatthew N. Dodd #include <sys/sysctl.h>
436e8394b8SKazutaka YOKOTA 
4421691935SPeter Wemm #if defined(__i386__) || defined(__amd64__)
456e8394b8SKazutaka YOKOTA 
466e8394b8SKazutaka YOKOTA #include <machine/clock.h>
476e8394b8SKazutaka YOKOTA #include <machine/md_var.h>
486e8394b8SKazutaka YOKOTA #include <machine/pc/bios.h>
496e8394b8SKazutaka YOKOTA 
506e8394b8SKazutaka YOKOTA #include <vm/vm.h>
516e8394b8SKazutaka YOKOTA #include <vm/pmap.h>
52092a5c45SJohn Baldwin #include <vm/vm_param.h>
536e8394b8SKazutaka YOKOTA 
546e8394b8SKazutaka YOKOTA #define BIOS_CLKED	(1 << 6)
556e8394b8SKazutaka YOKOTA #define BIOS_NLKED	(1 << 5)
566e8394b8SKazutaka YOKOTA #define BIOS_SLKED	(1 << 4)
576e8394b8SKazutaka YOKOTA #define BIOS_ALKED	0
586e8394b8SKazutaka YOKOTA 
5921691935SPeter Wemm #endif
608a997770SDoug Rabson 
618a997770SDoug Rabson #include <dev/syscons/syscons.h>
628a997770SDoug Rabson 
638a997770SDoug Rabson #include <isa/isavar.h>
648a997770SDoug Rabson 
656e8394b8SKazutaka YOKOTA static devclass_t	sc_devclass;
668a997770SDoug Rabson 
67e2f29c6eSKazutaka YOKOTA static sc_softc_t	main_softc;
686e8394b8SKazutaka YOKOTA 
69c20ac811SPeter Wemm static void
70c20ac811SPeter Wemm scidentify(driver_t *driver, device_t parent)
71c20ac811SPeter Wemm {
72b4f9625aSJung-uk Kim 
73c20ac811SPeter Wemm 	BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0);
74c20ac811SPeter Wemm }
75c20ac811SPeter Wemm 
768a997770SDoug Rabson static int
778a997770SDoug Rabson scprobe(device_t dev)
788a997770SDoug Rabson {
79b4f9625aSJung-uk Kim 
80f7f2df54SDoug Rabson 	/* No pnp support */
81f7f2df54SDoug Rabson 	if (isa_get_vendorid(dev))
82f7f2df54SDoug Rabson 		return (ENXIO);
83f7f2df54SDoug Rabson 
848a997770SDoug Rabson 	device_set_desc(dev, "System console");
85b4f9625aSJung-uk Kim 	return (sc_probe_unit(device_get_unit(dev), device_get_flags(dev)));
868a997770SDoug Rabson }
878a997770SDoug Rabson 
888a997770SDoug Rabson static int
898a997770SDoug Rabson scattach(device_t dev)
908a997770SDoug Rabson {
91b5b361cbSJohn Baldwin 
92b5b361cbSJohn Baldwin 	return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) |
93b5b361cbSJohn Baldwin 	    SC_AUTODETECT_KBD));
948a997770SDoug Rabson }
958a997770SDoug Rabson 
966e8394b8SKazutaka YOKOTA int
976e8394b8SKazutaka YOKOTA sc_max_unit(void)
986e8394b8SKazutaka YOKOTA {
99b4f9625aSJung-uk Kim 
100b4f9625aSJung-uk Kim 	return (devclass_get_maxunit(sc_devclass));
1016e8394b8SKazutaka YOKOTA }
1026e8394b8SKazutaka YOKOTA 
1036e8394b8SKazutaka YOKOTA sc_softc_t
1046e8394b8SKazutaka YOKOTA *sc_get_softc(int unit, int flags)
1056e8394b8SKazutaka YOKOTA {
1066e8394b8SKazutaka YOKOTA 	sc_softc_t *sc;
1076e8394b8SKazutaka YOKOTA 
1088f8e5879SPeter Wemm 	if (unit < 0)
109b4f9625aSJung-uk Kim 		return (NULL);
110b4f9625aSJung-uk Kim 	if ((flags & SC_KERNEL_CONSOLE) != 0) {
1116e8394b8SKazutaka YOKOTA 		/* FIXME: clear if it is wired to another unit! */
112e2f29c6eSKazutaka YOKOTA 		sc = &main_softc;
1136e8394b8SKazutaka YOKOTA 	} else {
114b4f9625aSJung-uk Kim 	        sc = device_get_softc(devclass_get_device(sc_devclass, unit));
1158f8e5879SPeter Wemm 		if (sc == NULL)
116b4f9625aSJung-uk Kim 			return (NULL);
117e2f29c6eSKazutaka YOKOTA 	}
1186e8394b8SKazutaka YOKOTA 	sc->unit = unit;
119b4f9625aSJung-uk Kim 	if ((sc->flags & SC_INIT_DONE) == 0) {
1206e8394b8SKazutaka YOKOTA 		sc->keyboard = -1;
1216e8394b8SKazutaka YOKOTA 		sc->adapter = -1;
12209132359SKazutaka YOKOTA 		sc->cursor_char = SC_CURSOR_CHAR;
123e2f29c6eSKazutaka YOKOTA 		sc->mouse_char = SC_MOUSE_CHAR;
1246e8394b8SKazutaka YOKOTA 	}
125b4f9625aSJung-uk Kim 	return (sc);
1266e8394b8SKazutaka YOKOTA }
1276e8394b8SKazutaka YOKOTA 
1286e8394b8SKazutaka YOKOTA sc_softc_t
1296e8394b8SKazutaka YOKOTA *sc_find_softc(struct video_adapter *adp, struct keyboard *kbd)
1306e8394b8SKazutaka YOKOTA {
1316e8394b8SKazutaka YOKOTA 	sc_softc_t *sc;
1326e8394b8SKazutaka YOKOTA 	int i;
133b4f9625aSJung-uk Kim 	int units;
1346e8394b8SKazutaka YOKOTA 
1356e8394b8SKazutaka YOKOTA 	sc = &main_softc;
136b4f9625aSJung-uk Kim 	if ((adp == NULL || adp == sc->adp) &&
137b4f9625aSJung-uk Kim 	    (kbd == NULL || kbd == sc->kbd))
138b4f9625aSJung-uk Kim 		return (sc);
1396e8394b8SKazutaka YOKOTA 	units = devclass_get_maxunit(sc_devclass);
1406e8394b8SKazutaka YOKOTA 	for (i = 0; i < units; ++i) {
141b4f9625aSJung-uk Kim 	        sc = device_get_softc(devclass_get_device(sc_devclass, i));
1426e8394b8SKazutaka YOKOTA 		if (sc == NULL)
1436e8394b8SKazutaka YOKOTA 			continue;
144b4f9625aSJung-uk Kim 		if ((adp == NULL || adp == sc->adp) &&
145b4f9625aSJung-uk Kim 		    (kbd == NULL || kbd == sc->kbd))
146b4f9625aSJung-uk Kim 			return (sc);
1476e8394b8SKazutaka YOKOTA 	}
148b4f9625aSJung-uk Kim 	return (NULL);
1496e8394b8SKazutaka YOKOTA }
1506e8394b8SKazutaka YOKOTA 
1516e8394b8SKazutaka YOKOTA int
1526e8394b8SKazutaka YOKOTA sc_get_cons_priority(int *unit, int *flags)
1536e8394b8SKazutaka YOKOTA {
154c864c67bSPeter Wemm 	const char *at;
155fa091a48SJung-uk Kim 	int f, u;
1566e8394b8SKazutaka YOKOTA 
1576e8394b8SKazutaka YOKOTA 	*unit = -1;
15881e3fd99SPeter Wemm 	for (u = 0; u < 16; u++) {
1598a9bc9c0SJohn Baldwin 		if (resource_disabled(SC_DRIVER_NAME, u))
1606e8394b8SKazutaka YOKOTA 			continue;
16181e3fd99SPeter Wemm 		if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0)
16281e3fd99SPeter Wemm 			continue;
1636e8394b8SKazutaka YOKOTA 		if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0)
1646e8394b8SKazutaka YOKOTA 			f = 0;
1656e8394b8SKazutaka YOKOTA 		if (f & SC_KERNEL_CONSOLE) {
1666e8394b8SKazutaka YOKOTA 			/* the user designates this unit to be the console */
1676e8394b8SKazutaka YOKOTA 			*unit = u;
1686e8394b8SKazutaka YOKOTA 			*flags = f;
1696e8394b8SKazutaka YOKOTA 			break;
1706e8394b8SKazutaka YOKOTA 		}
1716e8394b8SKazutaka YOKOTA 		if (*unit < 0) {
1726e8394b8SKazutaka YOKOTA 			/* ...otherwise remember the first found unit */
1736e8394b8SKazutaka YOKOTA 			*unit = u;
1746e8394b8SKazutaka YOKOTA 			*flags = f;
1756e8394b8SKazutaka YOKOTA 		}
1766e8394b8SKazutaka YOKOTA 	}
177b5b361cbSJohn Baldwin 	if (*unit < 0) {
178b5b361cbSJohn Baldwin 		*unit = 0;
179b5b361cbSJohn Baldwin 		*flags = 0;
180b5b361cbSJohn Baldwin 	}
1816e8394b8SKazutaka YOKOTA #if 0
182b4f9625aSJung-uk Kim 	return ((*flags & SC_KERNEL_CONSOLE) != 0 ? CN_INTERNAL : CN_NORMAL);
1836e8394b8SKazutaka YOKOTA #endif
184b4f9625aSJung-uk Kim 	return (CN_INTERNAL);
1856e8394b8SKazutaka YOKOTA }
1866e8394b8SKazutaka YOKOTA 
1876e8394b8SKazutaka YOKOTA void
1886e8394b8SKazutaka YOKOTA sc_get_bios_values(bios_values_t *values)
1896e8394b8SKazutaka YOKOTA {
19021691935SPeter Wemm #if defined(__i386__) || defined(__amd64__)
191b4f9625aSJung-uk Kim 	uint8_t shift;
1926e8394b8SKazutaka YOKOTA 
193b4f9625aSJung-uk Kim 	shift = *(uint8_t *)BIOS_PADDRTOVADDR(0x417);
194b4f9625aSJung-uk Kim 	values->shift_state = ((shift & BIOS_CLKED) != 0 ? CLKED : 0) |
195b4f9625aSJung-uk Kim 	    ((shift & BIOS_NLKED) != 0 ? NLKED : 0) |
196b4f9625aSJung-uk Kim 	    ((shift & BIOS_SLKED) != 0 ? SLKED : 0) |
197b4f9625aSJung-uk Kim 	    ((shift & BIOS_ALKED) != 0 ? ALKED : 0);
19821691935SPeter Wemm #endif
1996e8394b8SKazutaka YOKOTA 	values->bell_pitch = BELL_PITCH;
2006e8394b8SKazutaka YOKOTA }
2016e8394b8SKazutaka YOKOTA 
2026e8394b8SKazutaka YOKOTA int
2036e8394b8SKazutaka YOKOTA sc_tone(int herz)
2046e8394b8SKazutaka YOKOTA {
205b4f9625aSJung-uk Kim 
2061d73a9dcSPoul-Henning Kamp #if defined(HAS_TIMER_SPKR)
2076e8394b8SKazutaka YOKOTA 	if (herz) {
20824072ca3SYoshihiro Takahashi 		if (timer_spkr_acquire())
209b4f9625aSJung-uk Kim 			return (EBUSY);
210e4659858SPoul-Henning Kamp 		timer_spkr_setfreq(herz);
211b4f9625aSJung-uk Kim 	} else
21224072ca3SYoshihiro Takahashi 		timer_spkr_release();
21321691935SPeter Wemm #endif
2146e8394b8SKazutaka YOKOTA 
215b4f9625aSJung-uk Kim 	return (0);
2166e8394b8SKazutaka YOKOTA }
2176e8394b8SKazutaka YOKOTA 
218c20ac811SPeter Wemm static device_method_t sc_methods[] = {
219c20ac811SPeter Wemm 	DEVMETHOD(device_identify,	scidentify),
220c20ac811SPeter Wemm 	DEVMETHOD(device_probe,         scprobe),
221c20ac811SPeter Wemm 	DEVMETHOD(device_attach,        scattach),
222c20ac811SPeter Wemm 	{ 0, 0 }
223c20ac811SPeter Wemm };
224c20ac811SPeter Wemm 
225c20ac811SPeter Wemm static driver_t sc_driver = {
226c20ac811SPeter Wemm 	SC_DRIVER_NAME,
227c20ac811SPeter Wemm 	sc_methods,
228c20ac811SPeter Wemm 	sizeof(sc_softc_t),
229c20ac811SPeter Wemm };
230c20ac811SPeter Wemm 
2318a997770SDoug Rabson DRIVER_MODULE(sc, isa, sc_driver, sc_devclass, 0, 0);
232