syscons_cbus.c revision 105320
1/*-
2 * Copyright (c) 1999 FreeBSD(98) Porting Team.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer as
10 *    the first lines of this file unmodified.
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 AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/pc98/cbus/syscons_cbus.c 105320 2002-10-17 12:54:51Z nyan $
27 */
28
29#include "opt_syscons.h"
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/bus.h>
36#include <sys/cons.h>
37#include <sys/consio.h>
38
39#include <machine/clock.h>
40
41#include <pc98/pc98/pc98.h>
42#include <pc98/pc98/pc98_machdep.h>
43
44#include <dev/syscons/syscons.h>
45
46#include <i386/isa/timerreg.h>
47
48#include <isa/isavar.h>
49
50static devclass_t	sc_devclass;
51
52static sc_softc_t main_softc;
53
54static void
55scidentify (driver_t *driver, device_t parent)
56{
57	BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0);
58}
59
60static int
61scprobe(device_t dev)
62{
63	/* No pnp support */
64	if (isa_get_vendorid(dev))
65		return (ENXIO);
66
67	device_set_desc(dev, "System console");
68	return sc_probe_unit(device_get_unit(dev), device_get_flags(dev));
69}
70
71static int
72scattach(device_t dev)
73{
74	return sc_attach_unit(device_get_unit(dev), device_get_flags(dev));
75}
76
77static int	sc_cur_scr;
78
79static int
80scsuspend(device_t dev)
81{
82#ifndef SC_NO_SUSPEND_VTYSWITCH
83	int		retry = 10;
84	static int	dummy;
85	sc_softc_t	*sc;
86
87	sc = &main_softc;
88	sc_cur_scr = sc->cur_scp->index;
89	do {
90		sc_switch_scr(sc, 0);
91		if (!sc->switch_in_progress) {
92			break;
93		}
94		tsleep(&dummy, 0, "scsuspend", 100);
95	} while (retry--);
96
97#endif
98	return (0);
99}
100
101static int
102scresume(device_t dev)
103{
104#ifndef SC_NO_SUSPEND_VTYSWITCH
105	sc_softc_t	*sc;
106
107	sc = &main_softc;
108	sc_switch_scr(sc, sc_cur_scr);
109
110#endif
111	return (0);
112}
113
114int
115sc_max_unit(void)
116{
117	return devclass_get_maxunit(sc_devclass);
118}
119
120sc_softc_t
121*sc_get_softc(int unit, int flags)
122{
123	sc_softc_t *sc;
124
125	if (unit < 0)
126		return NULL;
127	if (flags & SC_KERNEL_CONSOLE) {
128		/* FIXME: clear if it is wired to another unit! */
129		sc = &main_softc;
130	} else {
131	        sc = (sc_softc_t *)device_get_softc(devclass_get_device(sc_devclass, unit));
132		if (sc == NULL)
133			return NULL;
134	}
135	sc->unit = unit;
136	if (!(sc->flags & SC_INIT_DONE)) {
137		sc->keyboard = -1;
138		sc->adapter = -1;
139		sc->mouse_char = SC_MOUSE_CHAR;
140	}
141	return sc;
142}
143
144sc_softc_t
145*sc_find_softc(struct video_adapter *adp, struct keyboard *kbd)
146{
147	sc_softc_t *sc;
148	int units;
149	int i;
150
151	sc = &main_softc;
152	if (((adp == NULL) || (adp == sc->adp))
153	    && ((kbd == NULL) || (kbd == sc->kbd)))
154		return sc;
155	units = devclass_get_maxunit(sc_devclass);
156	for (i = 0; i < units; ++i) {
157	        sc = (sc_softc_t *)device_get_softc(devclass_get_device(sc_devclass, i));
158		if (sc == NULL)
159			continue;
160		if (((adp == NULL) || (adp == sc->adp))
161		    && ((kbd == NULL) || (kbd == sc->kbd)))
162			return sc;
163	}
164	return NULL;
165}
166
167int
168sc_get_cons_priority(int *unit, int *flags)
169{
170	int disabled;
171	const char *at;
172	int u, f;
173
174	*unit = -1;
175	for (u = 0; u < 16; u++) {
176		if ((resource_int_value(SC_DRIVER_NAME, u, "disabled",
177					&disabled) == 0) && disabled)
178			continue;
179		if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0)
180			continue;
181		if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0)
182			f = 0;
183		if (f & SC_KERNEL_CONSOLE) {
184			/* the user designates this unit to be the console */
185			*unit = u;
186			*flags = f;
187			break;
188		}
189		if (*unit < 0) {
190			/* ...otherwise remember the first found unit */
191			*unit = u;
192			*flags = f;
193		}
194	}
195	if (*unit < 0)
196		return CN_DEAD;
197	return CN_INTERNAL;
198}
199
200void
201sc_get_bios_values(bios_values_t *values)
202{
203	values->cursor_start = 15;
204	values->cursor_end = 16;
205	values->shift_state = 0;
206	if (pc98_machine_type & M_8M)
207		values->bell_pitch = BELL_PITCH_8M;
208	else
209		values->bell_pitch = BELL_PITCH_5M;
210}
211
212int
213sc_tone(int herz)
214{
215	int pitch;
216
217	if (herz) {
218		/* enable counter 1 */
219		outb(0x35, inb(0x35) & 0xf7);
220		/* set command for counter 1, 2 byte write */
221		if (acquire_timer1(TIMER_16BIT | TIMER_SQWAVE))
222			return EBUSY;
223		/* set pitch */
224		pitch = timer_freq/herz;
225		outb(TIMER_CNTR1, pitch);
226		outb(TIMER_CNTR1, pitch >> 8);
227	} else {
228		/* disable counter 1 */
229		outb(0x35, inb(0x35) | 0x08);
230		release_timer1();
231	}
232	return 0;
233}
234
235static device_method_t sc_methods[] = {
236	DEVMETHOD(device_identify,	scidentify),
237	DEVMETHOD(device_probe,         scprobe),
238	DEVMETHOD(device_attach,        scattach),
239	DEVMETHOD(device_suspend,       scsuspend),
240	DEVMETHOD(device_resume,        scresume),
241	{ 0, 0 }
242};
243
244static driver_t sc_driver = {
245	SC_DRIVER_NAME,
246	sc_methods,
247	sizeof(sc_softc_t),
248};
249
250DRIVER_MODULE(sc, isa, sc_driver, sc_devclass, 0, 0);
251