xref: /freebsd/sys/isa/syscons_isa.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
18a997770SDoug Rabson /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fe267a55SPedro 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>
308a997770SDoug Rabson #include "opt_syscons.h"
318a997770SDoug Rabson 
328a997770SDoug Rabson #include <sys/param.h>
338a997770SDoug Rabson #include <sys/systm.h>
348a997770SDoug Rabson #include <sys/kernel.h>
358a997770SDoug Rabson #include <sys/module.h>
368a997770SDoug Rabson #include <sys/bus.h>
37ce9edcf5SPoul-Henning Kamp #include <sys/cons.h>
3800d25f51SPoul-Henning Kamp #include <sys/kbio.h>
3900d25f51SPoul-Henning Kamp #include <sys/consio.h>
40dcb65c59SMatthew N. Dodd #include <sys/sysctl.h>
416e8394b8SKazutaka YOKOTA 
4221691935SPeter Wemm #if defined(__i386__) || defined(__amd64__)
436e8394b8SKazutaka YOKOTA 
446e8394b8SKazutaka YOKOTA #include <machine/clock.h>
456e8394b8SKazutaka YOKOTA #include <machine/md_var.h>
466e8394b8SKazutaka YOKOTA #include <machine/pc/bios.h>
476e8394b8SKazutaka YOKOTA 
486e8394b8SKazutaka YOKOTA #include <vm/vm.h>
496e8394b8SKazutaka YOKOTA #include <vm/pmap.h>
50092a5c45SJohn Baldwin #include <vm/vm_param.h>
516e8394b8SKazutaka YOKOTA 
526e8394b8SKazutaka YOKOTA #define BIOS_CLKED	(1 << 6)
536e8394b8SKazutaka YOKOTA #define BIOS_NLKED	(1 << 5)
546e8394b8SKazutaka YOKOTA #define BIOS_SLKED	(1 << 4)
556e8394b8SKazutaka YOKOTA #define BIOS_ALKED	0
566e8394b8SKazutaka YOKOTA 
5721691935SPeter Wemm #endif
588a997770SDoug Rabson 
598a997770SDoug Rabson #include <dev/syscons/syscons.h>
608a997770SDoug Rabson 
618a997770SDoug Rabson #include <isa/isavar.h>
628a997770SDoug Rabson 
63e2f29c6eSKazutaka YOKOTA static sc_softc_t	main_softc;
646e8394b8SKazutaka YOKOTA 
65c20ac811SPeter Wemm static void
scidentify(driver_t * driver,device_t parent)66c20ac811SPeter Wemm scidentify(driver_t *driver, device_t parent)
67c20ac811SPeter Wemm {
68b4f9625aSJung-uk Kim 
69c20ac811SPeter Wemm 	BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0);
70c20ac811SPeter Wemm }
71c20ac811SPeter Wemm 
728a997770SDoug Rabson static int
scprobe(device_t dev)738a997770SDoug Rabson scprobe(device_t dev)
748a997770SDoug Rabson {
75b4f9625aSJung-uk Kim 
76f7f2df54SDoug Rabson 	/* No pnp support */
77f7f2df54SDoug Rabson 	if (isa_get_vendorid(dev))
78f7f2df54SDoug Rabson 		return (ENXIO);
79f7f2df54SDoug Rabson 
808a997770SDoug Rabson 	device_set_desc(dev, "System console");
81b4f9625aSJung-uk Kim 	return (sc_probe_unit(device_get_unit(dev), device_get_flags(dev)));
828a997770SDoug Rabson }
838a997770SDoug Rabson 
848a997770SDoug Rabson static int
scattach(device_t dev)858a997770SDoug Rabson scattach(device_t dev)
868a997770SDoug Rabson {
87b5b361cbSJohn Baldwin 
88b5b361cbSJohn Baldwin 	return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) |
89b5b361cbSJohn Baldwin 	    SC_AUTODETECT_KBD));
908a997770SDoug Rabson }
918a997770SDoug Rabson 
926e8394b8SKazutaka YOKOTA int
sc_max_unit(void)936e8394b8SKazutaka YOKOTA sc_max_unit(void)
946e8394b8SKazutaka YOKOTA {
95b4f9625aSJung-uk Kim 
966b06f746SJohn Baldwin 	return (devclass_get_maxunit(devclass_find("sc")));
976e8394b8SKazutaka YOKOTA }
986e8394b8SKazutaka YOKOTA 
996e8394b8SKazutaka YOKOTA sc_softc_t
sc_get_softc(int unit,int flags)1006e8394b8SKazutaka YOKOTA *sc_get_softc(int unit, int flags)
1016e8394b8SKazutaka YOKOTA {
1026e8394b8SKazutaka YOKOTA 	sc_softc_t *sc;
1036e8394b8SKazutaka YOKOTA 
1048f8e5879SPeter Wemm 	if (unit < 0)
105b4f9625aSJung-uk Kim 		return (NULL);
106b4f9625aSJung-uk Kim 	if ((flags & SC_KERNEL_CONSOLE) != 0) {
1076e8394b8SKazutaka YOKOTA 		/* FIXME: clear if it is wired to another unit! */
108e2f29c6eSKazutaka YOKOTA 		sc = &main_softc;
1096e8394b8SKazutaka YOKOTA 	} else {
1106b06f746SJohn Baldwin 	        sc = device_get_softc(devclass_get_device(devclass_find("sc"),
1116b06f746SJohn Baldwin 		    unit));
1128f8e5879SPeter Wemm 		if (sc == NULL)
113b4f9625aSJung-uk Kim 			return (NULL);
114e2f29c6eSKazutaka YOKOTA 	}
1156e8394b8SKazutaka YOKOTA 	sc->unit = unit;
116b4f9625aSJung-uk Kim 	if ((sc->flags & SC_INIT_DONE) == 0) {
1176e8394b8SKazutaka YOKOTA 		sc->adapter = -1;
11809132359SKazutaka YOKOTA 		sc->cursor_char = SC_CURSOR_CHAR;
119e2f29c6eSKazutaka YOKOTA 		sc->mouse_char = SC_MOUSE_CHAR;
1206e8394b8SKazutaka YOKOTA 	}
121b4f9625aSJung-uk Kim 	return (sc);
1226e8394b8SKazutaka YOKOTA }
1236e8394b8SKazutaka YOKOTA 
1246e8394b8SKazutaka YOKOTA sc_softc_t
sc_find_softc(struct video_adapter * adp,struct keyboard * kbd)1256e8394b8SKazutaka YOKOTA *sc_find_softc(struct video_adapter *adp, struct keyboard *kbd)
1266e8394b8SKazutaka YOKOTA {
1276b06f746SJohn Baldwin 	devclass_t dc;
1286e8394b8SKazutaka YOKOTA 	sc_softc_t *sc;
1296e8394b8SKazutaka YOKOTA 	int i;
130b4f9625aSJung-uk Kim 	int units;
1316e8394b8SKazutaka YOKOTA 
1326e8394b8SKazutaka YOKOTA 	sc = &main_softc;
133b4f9625aSJung-uk Kim 	if ((adp == NULL || adp == sc->adp) &&
134b4f9625aSJung-uk Kim 	    (kbd == NULL || kbd == sc->kbd))
135b4f9625aSJung-uk Kim 		return (sc);
1366b06f746SJohn Baldwin 	dc = devclass_find("sc");
1376b06f746SJohn Baldwin 	units = devclass_get_maxunit(dc);
1386e8394b8SKazutaka YOKOTA 	for (i = 0; i < units; ++i) {
1396b06f746SJohn Baldwin 	        sc = device_get_softc(devclass_get_device(dc, i));
1406e8394b8SKazutaka YOKOTA 		if (sc == NULL)
1416e8394b8SKazutaka YOKOTA 			continue;
142b4f9625aSJung-uk Kim 		if ((adp == NULL || adp == sc->adp) &&
143b4f9625aSJung-uk Kim 		    (kbd == NULL || kbd == sc->kbd))
144b4f9625aSJung-uk Kim 			return (sc);
1456e8394b8SKazutaka YOKOTA 	}
146b4f9625aSJung-uk Kim 	return (NULL);
1476e8394b8SKazutaka YOKOTA }
1486e8394b8SKazutaka YOKOTA 
1496e8394b8SKazutaka YOKOTA int
sc_get_cons_priority(int * unit,int * flags)1506e8394b8SKazutaka YOKOTA sc_get_cons_priority(int *unit, int *flags)
1516e8394b8SKazutaka YOKOTA {
152c864c67bSPeter Wemm 	const char *at;
153fa091a48SJung-uk Kim 	int f, u;
1546e8394b8SKazutaka YOKOTA 
1556e8394b8SKazutaka YOKOTA 	*unit = -1;
15681e3fd99SPeter Wemm 	for (u = 0; u < 16; u++) {
1578a9bc9c0SJohn Baldwin 		if (resource_disabled(SC_DRIVER_NAME, u))
1586e8394b8SKazutaka YOKOTA 			continue;
15981e3fd99SPeter Wemm 		if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0)
16081e3fd99SPeter Wemm 			continue;
1616e8394b8SKazutaka YOKOTA 		if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0)
1626e8394b8SKazutaka YOKOTA 			f = 0;
1636e8394b8SKazutaka YOKOTA 		if (f & SC_KERNEL_CONSOLE) {
1646e8394b8SKazutaka YOKOTA 			/* the user designates this unit to be the console */
1656e8394b8SKazutaka YOKOTA 			*unit = u;
1666e8394b8SKazutaka YOKOTA 			*flags = f;
1676e8394b8SKazutaka YOKOTA 			break;
1686e8394b8SKazutaka YOKOTA 		}
1696e8394b8SKazutaka YOKOTA 		if (*unit < 0) {
1706e8394b8SKazutaka YOKOTA 			/* ...otherwise remember the first found unit */
1716e8394b8SKazutaka YOKOTA 			*unit = u;
1726e8394b8SKazutaka YOKOTA 			*flags = f;
1736e8394b8SKazutaka YOKOTA 		}
1746e8394b8SKazutaka YOKOTA 	}
175b5b361cbSJohn Baldwin 	if (*unit < 0) {
176b5b361cbSJohn Baldwin 		*unit = 0;
177b5b361cbSJohn Baldwin 		*flags = 0;
178b5b361cbSJohn Baldwin 	}
1796e8394b8SKazutaka YOKOTA #if 0
180b4f9625aSJung-uk Kim 	return ((*flags & SC_KERNEL_CONSOLE) != 0 ? CN_INTERNAL : CN_NORMAL);
1816e8394b8SKazutaka YOKOTA #endif
182b4f9625aSJung-uk Kim 	return (CN_INTERNAL);
1836e8394b8SKazutaka YOKOTA }
1846e8394b8SKazutaka YOKOTA 
1856e8394b8SKazutaka YOKOTA void
sc_get_bios_values(bios_values_t * values)1866e8394b8SKazutaka YOKOTA sc_get_bios_values(bios_values_t *values)
1876e8394b8SKazutaka YOKOTA {
18821691935SPeter Wemm #if defined(__i386__) || defined(__amd64__)
189b4f9625aSJung-uk Kim 	uint8_t shift;
1906e8394b8SKazutaka YOKOTA 
191b4f9625aSJung-uk Kim 	shift = *(uint8_t *)BIOS_PADDRTOVADDR(0x417);
192b4f9625aSJung-uk Kim 	values->shift_state = ((shift & BIOS_CLKED) != 0 ? CLKED : 0) |
193b4f9625aSJung-uk Kim 	    ((shift & BIOS_NLKED) != 0 ? NLKED : 0) |
194b4f9625aSJung-uk Kim 	    ((shift & BIOS_SLKED) != 0 ? SLKED : 0) |
195b4f9625aSJung-uk Kim 	    ((shift & BIOS_ALKED) != 0 ? ALKED : 0);
19621691935SPeter Wemm #endif
1976e8394b8SKazutaka YOKOTA 	values->bell_pitch = BELL_PITCH;
1986e8394b8SKazutaka YOKOTA }
1996e8394b8SKazutaka YOKOTA 
2006e8394b8SKazutaka YOKOTA int
sc_tone(int herz)2016e8394b8SKazutaka YOKOTA sc_tone(int herz)
2026e8394b8SKazutaka YOKOTA {
203b4f9625aSJung-uk Kim 
2041d73a9dcSPoul-Henning Kamp #if defined(HAS_TIMER_SPKR)
2056e8394b8SKazutaka YOKOTA 	if (herz) {
20624072ca3SYoshihiro Takahashi 		if (timer_spkr_acquire())
207b4f9625aSJung-uk Kim 			return (EBUSY);
208e4659858SPoul-Henning Kamp 		timer_spkr_setfreq(herz);
209b4f9625aSJung-uk Kim 	} else
21024072ca3SYoshihiro Takahashi 		timer_spkr_release();
21121691935SPeter Wemm #endif
2126e8394b8SKazutaka YOKOTA 
213b4f9625aSJung-uk Kim 	return (0);
2146e8394b8SKazutaka YOKOTA }
2156e8394b8SKazutaka YOKOTA 
216c20ac811SPeter Wemm static device_method_t sc_methods[] = {
217c20ac811SPeter Wemm 	DEVMETHOD(device_identify,	scidentify),
218c20ac811SPeter Wemm 	DEVMETHOD(device_probe,         scprobe),
219c20ac811SPeter Wemm 	DEVMETHOD(device_attach,        scattach),
220c20ac811SPeter Wemm 	{ 0, 0 }
221c20ac811SPeter Wemm };
222c20ac811SPeter Wemm 
223c20ac811SPeter Wemm static driver_t sc_driver = {
224c20ac811SPeter Wemm 	SC_DRIVER_NAME,
225c20ac811SPeter Wemm 	sc_methods,
226c20ac811SPeter Wemm 	sizeof(sc_softc_t),
227c20ac811SPeter Wemm };
228c20ac811SPeter Wemm 
229be275086SJohn Baldwin DRIVER_MODULE(sc, isa, sc_driver, 0, 0);
230