xref: /freebsd/sys/isa/syscons_isa.c (revision fa091a4804a75b9621c5c0ba702a22c49b41c852)
18a997770SDoug Rabson /*-
28a997770SDoug Rabson  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
38a997770SDoug Rabson  * All rights reserved.
48a997770SDoug Rabson  *
58a997770SDoug Rabson  * Redistribution and use in source and binary forms, with or without
68a997770SDoug Rabson  * modification, are permitted provided that the following conditions
78a997770SDoug Rabson  * are met:
88a997770SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
98a997770SDoug Rabson  *    notice, this list of conditions and the following disclaimer as
108a997770SDoug Rabson  *    the first lines of this file unmodified.
118a997770SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
128a997770SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
138a997770SDoug Rabson  *    documentation and/or other materials provided with the distribution.
148a997770SDoug Rabson  *
158a997770SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
168a997770SDoug Rabson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
178a997770SDoug Rabson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
188a997770SDoug Rabson  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
198a997770SDoug Rabson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
208a997770SDoug Rabson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
218a997770SDoug Rabson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
228a997770SDoug Rabson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
238a997770SDoug Rabson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
248a997770SDoug Rabson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
258a997770SDoug Rabson  */
268a997770SDoug Rabson 
278c9bbf48SDavid E. O'Brien #include <sys/cdefs.h>
288c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$");
298c9bbf48SDavid E. O'Brien 
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 
635fa7c51fSRink Springer #include "opt_xbox.h"
645fa7c51fSRink Springer 
655fa7c51fSRink Springer #ifdef XBOX
665fa7c51fSRink Springer #include <machine/xbox.h>
675fa7c51fSRink Springer #endif
685fa7c51fSRink Springer 
696e8394b8SKazutaka YOKOTA static devclass_t	sc_devclass;
708a997770SDoug Rabson 
71e2f29c6eSKazutaka YOKOTA static sc_softc_t	main_softc;
72dcb65c59SMatthew N. Dodd #ifdef SC_NO_SUSPEND_VTYSWITCH
73dcb65c59SMatthew N. Dodd static int sc_no_suspend_vtswitch = 1;
74dcb65c59SMatthew N. Dodd #else
75dcb65c59SMatthew N. Dodd static int sc_no_suspend_vtswitch = 0;
76dcb65c59SMatthew N. Dodd #endif
77dcb65c59SMatthew N. Dodd static int sc_cur_scr;
78dcb65c59SMatthew N. Dodd 
79b4f9625aSJung-uk Kim TUNABLE_INT("hw.syscons.sc_no_suspend_vtswitch", &sc_no_suspend_vtswitch);
80dcb65c59SMatthew N. Dodd SYSCTL_DECL(_hw_syscons);
81dcb65c59SMatthew N. Dodd SYSCTL_INT(_hw_syscons, OID_AUTO, sc_no_suspend_vtswitch, CTLFLAG_RW,
82dcb65c59SMatthew N. Dodd     &sc_no_suspend_vtswitch, 0, "Disable VT switch before suspend.");
836e8394b8SKazutaka YOKOTA 
84c20ac811SPeter Wemm static void
85c20ac811SPeter Wemm scidentify(driver_t *driver, device_t parent)
86c20ac811SPeter Wemm {
87b4f9625aSJung-uk Kim 
88c20ac811SPeter Wemm 	BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0);
89c20ac811SPeter Wemm }
90c20ac811SPeter Wemm 
918a997770SDoug Rabson static int
928a997770SDoug Rabson scprobe(device_t dev)
938a997770SDoug Rabson {
94b4f9625aSJung-uk Kim 
95f7f2df54SDoug Rabson 	/* No pnp support */
96f7f2df54SDoug Rabson 	if (isa_get_vendorid(dev))
97f7f2df54SDoug Rabson 		return (ENXIO);
98f7f2df54SDoug Rabson 
998a997770SDoug Rabson 	device_set_desc(dev, "System console");
100b4f9625aSJung-uk Kim 	return (sc_probe_unit(device_get_unit(dev), device_get_flags(dev)));
1018a997770SDoug Rabson }
1028a997770SDoug Rabson 
1038a997770SDoug Rabson static int
1048a997770SDoug Rabson scattach(device_t dev)
1058a997770SDoug Rabson {
106b5b361cbSJohn Baldwin 
107b5b361cbSJohn Baldwin 	return (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) |
108b5b361cbSJohn Baldwin 	    SC_AUTODETECT_KBD));
1098a997770SDoug Rabson }
1108a997770SDoug Rabson 
1119c4d34dfSMitsuru IWASAKI static int
1129c4d34dfSMitsuru IWASAKI scsuspend(device_t dev)
1139c4d34dfSMitsuru IWASAKI {
1149c4d34dfSMitsuru IWASAKI 	int		retry = 10;
1159c4d34dfSMitsuru IWASAKI 	sc_softc_t	*sc;
1169c4d34dfSMitsuru IWASAKI 
1179c4d34dfSMitsuru IWASAKI 	sc = &main_softc;
118e8c321c9SNate Lawson 
119dd962f5bSJung-uk Kim 	if (sc->cur_scp == NULL || sc->suspend_in_progress)
120e8c321c9SNate Lawson 		return (0);
121e8c321c9SNate Lawson 
122dd962f5bSJung-uk Kim 	if (!sc_no_suspend_vtswitch) {
1239c4d34dfSMitsuru IWASAKI 		sc_cur_scr = sc->cur_scp->index;
1249c4d34dfSMitsuru IWASAKI 		do {
1259c4d34dfSMitsuru IWASAKI 			sc_switch_scr(sc, 0);
126*fa091a48SJung-uk Kim 			if (!sc->switch_in_progress)
1279c4d34dfSMitsuru IWASAKI 				break;
12884d37a46SJohn Baldwin 			pause("scsuspend", hz);
1299c4d34dfSMitsuru IWASAKI 		} while (retry--);
130dd962f5bSJung-uk Kim 	}
131dd962f5bSJung-uk Kim 
132dd962f5bSJung-uk Kim 	sc->suspend_in_progress = TRUE;
1339c4d34dfSMitsuru IWASAKI 
1349c4d34dfSMitsuru IWASAKI 	return (0);
1359c4d34dfSMitsuru IWASAKI }
1369c4d34dfSMitsuru IWASAKI 
1379c4d34dfSMitsuru IWASAKI static int
1389c4d34dfSMitsuru IWASAKI scresume(device_t dev)
1399c4d34dfSMitsuru IWASAKI {
1409c4d34dfSMitsuru IWASAKI 	sc_softc_t	*sc;
1419c4d34dfSMitsuru IWASAKI 
142dd962f5bSJung-uk Kim 	sc = &main_softc;
143dd962f5bSJung-uk Kim 
144dd962f5bSJung-uk Kim 	if (!sc->suspend_in_progress)
145dcb65c59SMatthew N. Dodd 		return (0);
146dcb65c59SMatthew N. Dodd 
147dd962f5bSJung-uk Kim 	sc->suspend_in_progress = FALSE;
148dd962f5bSJung-uk Kim 
149dd962f5bSJung-uk Kim 	if (!sc_no_suspend_vtswitch)
1509c4d34dfSMitsuru IWASAKI 		sc_switch_scr(sc, sc_cur_scr);
1519c4d34dfSMitsuru IWASAKI 
1529c4d34dfSMitsuru IWASAKI 	return (0);
1539c4d34dfSMitsuru IWASAKI }
1549c4d34dfSMitsuru IWASAKI 
1556e8394b8SKazutaka YOKOTA int
1566e8394b8SKazutaka YOKOTA sc_max_unit(void)
1576e8394b8SKazutaka YOKOTA {
158b4f9625aSJung-uk Kim 
159b4f9625aSJung-uk Kim 	return (devclass_get_maxunit(sc_devclass));
1606e8394b8SKazutaka YOKOTA }
1616e8394b8SKazutaka YOKOTA 
1626e8394b8SKazutaka YOKOTA sc_softc_t
1636e8394b8SKazutaka YOKOTA *sc_get_softc(int unit, int flags)
1646e8394b8SKazutaka YOKOTA {
1656e8394b8SKazutaka YOKOTA 	sc_softc_t *sc;
1666e8394b8SKazutaka YOKOTA 
1678f8e5879SPeter Wemm 	if (unit < 0)
168b4f9625aSJung-uk Kim 		return (NULL);
169b4f9625aSJung-uk Kim 	if ((flags & SC_KERNEL_CONSOLE) != 0) {
1706e8394b8SKazutaka YOKOTA 		/* FIXME: clear if it is wired to another unit! */
171e2f29c6eSKazutaka YOKOTA 		sc = &main_softc;
1726e8394b8SKazutaka YOKOTA 	} else {
173b4f9625aSJung-uk Kim 	        sc = device_get_softc(devclass_get_device(sc_devclass, unit));
1748f8e5879SPeter Wemm 		if (sc == NULL)
175b4f9625aSJung-uk Kim 			return (NULL);
176e2f29c6eSKazutaka YOKOTA 	}
1776e8394b8SKazutaka YOKOTA 	sc->unit = unit;
178b4f9625aSJung-uk Kim 	if ((sc->flags & SC_INIT_DONE) == 0) {
1796e8394b8SKazutaka YOKOTA 		sc->keyboard = -1;
1806e8394b8SKazutaka YOKOTA 		sc->adapter = -1;
18109132359SKazutaka YOKOTA 		sc->cursor_char = SC_CURSOR_CHAR;
182e2f29c6eSKazutaka YOKOTA 		sc->mouse_char = SC_MOUSE_CHAR;
1836e8394b8SKazutaka YOKOTA 	}
184b4f9625aSJung-uk Kim 	return (sc);
1856e8394b8SKazutaka YOKOTA }
1866e8394b8SKazutaka YOKOTA 
1876e8394b8SKazutaka YOKOTA sc_softc_t
1886e8394b8SKazutaka YOKOTA *sc_find_softc(struct video_adapter *adp, struct keyboard *kbd)
1896e8394b8SKazutaka YOKOTA {
1906e8394b8SKazutaka YOKOTA 	sc_softc_t *sc;
1916e8394b8SKazutaka YOKOTA 	int i;
192b4f9625aSJung-uk Kim 	int units;
1936e8394b8SKazutaka YOKOTA 
1946e8394b8SKazutaka YOKOTA 	sc = &main_softc;
195b4f9625aSJung-uk Kim 	if ((adp == NULL || adp == sc->adp) &&
196b4f9625aSJung-uk Kim 	    (kbd == NULL || kbd == sc->kbd))
197b4f9625aSJung-uk Kim 		return (sc);
1986e8394b8SKazutaka YOKOTA 	units = devclass_get_maxunit(sc_devclass);
1996e8394b8SKazutaka YOKOTA 	for (i = 0; i < units; ++i) {
200b4f9625aSJung-uk Kim 	        sc = device_get_softc(devclass_get_device(sc_devclass, i));
2016e8394b8SKazutaka YOKOTA 		if (sc == NULL)
2026e8394b8SKazutaka YOKOTA 			continue;
203b4f9625aSJung-uk Kim 		if ((adp == NULL || adp == sc->adp) &&
204b4f9625aSJung-uk Kim 		    (kbd == NULL || kbd == sc->kbd))
205b4f9625aSJung-uk Kim 			return (sc);
2066e8394b8SKazutaka YOKOTA 	}
207b4f9625aSJung-uk Kim 	return (NULL);
2086e8394b8SKazutaka YOKOTA }
2096e8394b8SKazutaka YOKOTA 
2106e8394b8SKazutaka YOKOTA int
2116e8394b8SKazutaka YOKOTA sc_get_cons_priority(int *unit, int *flags)
2126e8394b8SKazutaka YOKOTA {
213c864c67bSPeter Wemm 	const char *at;
214*fa091a48SJung-uk Kim 	int f, u;
2156e8394b8SKazutaka YOKOTA 
2165fa7c51fSRink Springer #ifdef XBOX
2175fa7c51fSRink Springer 	/*
2185fa7c51fSRink Springer 	 * The XBox Loader does not support hints, which makes our initial
2195fa7c51fSRink Springer 	 * console probe fail. Therefore, if an XBox is found, we hardcode the
2205fa7c51fSRink Springer 	 * existence of the console, as it is always there anyway.
2215fa7c51fSRink Springer 	 */
2225fa7c51fSRink Springer 	if (arch_i386_is_xbox) {
2235fa7c51fSRink Springer 		*unit = 0;
2245fa7c51fSRink Springer 		*flags = SC_KERNEL_CONSOLE;
225b4f9625aSJung-uk Kim 		return (CN_INTERNAL);
2265fa7c51fSRink Springer 	}
2275fa7c51fSRink Springer #endif
2285fa7c51fSRink Springer 
2296e8394b8SKazutaka YOKOTA 	*unit = -1;
23081e3fd99SPeter Wemm 	for (u = 0; u < 16; u++) {
2318a9bc9c0SJohn Baldwin 		if (resource_disabled(SC_DRIVER_NAME, u))
2326e8394b8SKazutaka YOKOTA 			continue;
23381e3fd99SPeter Wemm 		if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0)
23481e3fd99SPeter Wemm 			continue;
2356e8394b8SKazutaka YOKOTA 		if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0)
2366e8394b8SKazutaka YOKOTA 			f = 0;
2376e8394b8SKazutaka YOKOTA 		if (f & SC_KERNEL_CONSOLE) {
2386e8394b8SKazutaka YOKOTA 			/* the user designates this unit to be the console */
2396e8394b8SKazutaka YOKOTA 			*unit = u;
2406e8394b8SKazutaka YOKOTA 			*flags = f;
2416e8394b8SKazutaka YOKOTA 			break;
2426e8394b8SKazutaka YOKOTA 		}
2436e8394b8SKazutaka YOKOTA 		if (*unit < 0) {
2446e8394b8SKazutaka YOKOTA 			/* ...otherwise remember the first found unit */
2456e8394b8SKazutaka YOKOTA 			*unit = u;
2466e8394b8SKazutaka YOKOTA 			*flags = f;
2476e8394b8SKazutaka YOKOTA 		}
2486e8394b8SKazutaka YOKOTA 	}
249b5b361cbSJohn Baldwin 	if (*unit < 0) {
250b5b361cbSJohn Baldwin 		*unit = 0;
251b5b361cbSJohn Baldwin 		*flags = 0;
252b5b361cbSJohn Baldwin 	}
2536e8394b8SKazutaka YOKOTA #if 0
254b4f9625aSJung-uk Kim 	return ((*flags & SC_KERNEL_CONSOLE) != 0 ? CN_INTERNAL : CN_NORMAL);
2556e8394b8SKazutaka YOKOTA #endif
256b4f9625aSJung-uk Kim 	return (CN_INTERNAL);
2576e8394b8SKazutaka YOKOTA }
2586e8394b8SKazutaka YOKOTA 
2596e8394b8SKazutaka YOKOTA void
2606e8394b8SKazutaka YOKOTA sc_get_bios_values(bios_values_t *values)
2616e8394b8SKazutaka YOKOTA {
26221691935SPeter Wemm #if defined(__i386__) || defined(__amd64__)
263b4f9625aSJung-uk Kim 	uint8_t shift;
2646e8394b8SKazutaka YOKOTA 
265b4f9625aSJung-uk Kim 	values->cursor_start = *(uint8_t *)BIOS_PADDRTOVADDR(0x461);
266b4f9625aSJung-uk Kim 	values->cursor_end = *(uint8_t *)BIOS_PADDRTOVADDR(0x460);
267b4f9625aSJung-uk Kim 	shift = *(uint8_t *)BIOS_PADDRTOVADDR(0x417);
268b4f9625aSJung-uk Kim 	values->shift_state = ((shift & BIOS_CLKED) != 0 ? CLKED : 0) |
269b4f9625aSJung-uk Kim 	    ((shift & BIOS_NLKED) != 0 ? NLKED : 0) |
270b4f9625aSJung-uk Kim 	    ((shift & BIOS_SLKED) != 0 ? SLKED : 0) |
271b4f9625aSJung-uk Kim 	    ((shift & BIOS_ALKED) != 0 ? ALKED : 0);
27221691935SPeter Wemm #else
2736e8394b8SKazutaka YOKOTA 	values->cursor_start = 0;
2746e8394b8SKazutaka YOKOTA 	values->cursor_end = 32;
2756e8394b8SKazutaka YOKOTA 	values->shift_state = 0;
27621691935SPeter Wemm #endif
2776e8394b8SKazutaka YOKOTA 	values->bell_pitch = BELL_PITCH;
2786e8394b8SKazutaka YOKOTA }
2796e8394b8SKazutaka YOKOTA 
2806e8394b8SKazutaka YOKOTA int
2816e8394b8SKazutaka YOKOTA sc_tone(int herz)
2826e8394b8SKazutaka YOKOTA {
283b4f9625aSJung-uk Kim 
2841d73a9dcSPoul-Henning Kamp #if defined(HAS_TIMER_SPKR)
2856e8394b8SKazutaka YOKOTA 	if (herz) {
28624072ca3SYoshihiro Takahashi 		if (timer_spkr_acquire())
287b4f9625aSJung-uk Kim 			return (EBUSY);
288e4659858SPoul-Henning Kamp 		timer_spkr_setfreq(herz);
289b4f9625aSJung-uk Kim 	} else
29024072ca3SYoshihiro Takahashi 		timer_spkr_release();
29121691935SPeter Wemm #endif
2926e8394b8SKazutaka YOKOTA 
293b4f9625aSJung-uk Kim 	return (0);
2946e8394b8SKazutaka YOKOTA }
2956e8394b8SKazutaka YOKOTA 
296c20ac811SPeter Wemm static device_method_t sc_methods[] = {
297c20ac811SPeter Wemm 	DEVMETHOD(device_identify,	scidentify),
298c20ac811SPeter Wemm 	DEVMETHOD(device_probe,         scprobe),
299c20ac811SPeter Wemm 	DEVMETHOD(device_attach,        scattach),
3009c4d34dfSMitsuru IWASAKI 	DEVMETHOD(device_suspend,       scsuspend),
3019c4d34dfSMitsuru IWASAKI 	DEVMETHOD(device_resume,        scresume),
302c20ac811SPeter Wemm 	{ 0, 0 }
303c20ac811SPeter Wemm };
304c20ac811SPeter Wemm 
305c20ac811SPeter Wemm static driver_t sc_driver = {
306c20ac811SPeter Wemm 	SC_DRIVER_NAME,
307c20ac811SPeter Wemm 	sc_methods,
308c20ac811SPeter Wemm 	sizeof(sc_softc_t),
309c20ac811SPeter Wemm };
310c20ac811SPeter Wemm 
3118a997770SDoug Rabson DRIVER_MODULE(sc, isa, sc_driver, sc_devclass, 0, 0);
312dd962f5bSJung-uk Kim 
313dd962f5bSJung-uk Kim static devclass_t	scpm_devclass;
314dd962f5bSJung-uk Kim 
315dd962f5bSJung-uk Kim static void
316dd962f5bSJung-uk Kim scpm_identify(driver_t *driver, device_t parent)
317dd962f5bSJung-uk Kim {
318dd962f5bSJung-uk Kim 
319dd962f5bSJung-uk Kim 	device_add_child(parent, "scpm", 0);
320dd962f5bSJung-uk Kim }
321dd962f5bSJung-uk Kim 
322dd962f5bSJung-uk Kim static int
323dd962f5bSJung-uk Kim scpm_probe(device_t dev)
324dd962f5bSJung-uk Kim {
325dd962f5bSJung-uk Kim 
326dd962f5bSJung-uk Kim 	device_set_desc(dev, SC_DRIVER_NAME " suspend/resume");
327dd962f5bSJung-uk Kim 	device_quiet(dev);
328dd962f5bSJung-uk Kim 
329dd962f5bSJung-uk Kim 	return (BUS_PROBE_DEFAULT);
330dd962f5bSJung-uk Kim }
331dd962f5bSJung-uk Kim 
332dd962f5bSJung-uk Kim static int
333dd962f5bSJung-uk Kim scpm_attach(device_t dev)
334dd962f5bSJung-uk Kim {
335dd962f5bSJung-uk Kim 
336dd962f5bSJung-uk Kim 	bus_generic_probe(dev);
337dd962f5bSJung-uk Kim 	bus_generic_attach(dev);
338dd962f5bSJung-uk Kim 
339dd962f5bSJung-uk Kim 	return (0);
340dd962f5bSJung-uk Kim }
341dd962f5bSJung-uk Kim 
342dd962f5bSJung-uk Kim static int
343dd962f5bSJung-uk Kim scpm_suspend(device_t dev)
344dd962f5bSJung-uk Kim {
345dd962f5bSJung-uk Kim 	int error;
346dd962f5bSJung-uk Kim 
347dd962f5bSJung-uk Kim 	error = bus_generic_suspend(dev);
348dd962f5bSJung-uk Kim 	if (error != 0)
349dd962f5bSJung-uk Kim 		return (error);
350dd962f5bSJung-uk Kim 
351dd962f5bSJung-uk Kim 	return (scsuspend(dev));
352dd962f5bSJung-uk Kim }
353dd962f5bSJung-uk Kim 
354dd962f5bSJung-uk Kim static int
355dd962f5bSJung-uk Kim scpm_resume(device_t dev)
356dd962f5bSJung-uk Kim {
357dd962f5bSJung-uk Kim 
358dd962f5bSJung-uk Kim 	scresume(dev);
359dd962f5bSJung-uk Kim 
360dd962f5bSJung-uk Kim 	return (bus_generic_resume(dev));
361dd962f5bSJung-uk Kim }
362dd962f5bSJung-uk Kim 
363dd962f5bSJung-uk Kim static device_method_t scpm_methods[] = {
364dd962f5bSJung-uk Kim 	DEVMETHOD(device_identify,	scpm_identify),
365dd962f5bSJung-uk Kim 	DEVMETHOD(device_probe,		scpm_probe),
366dd962f5bSJung-uk Kim 	DEVMETHOD(device_attach,	scpm_attach),
367dd962f5bSJung-uk Kim 	DEVMETHOD(device_suspend,	scpm_suspend),
368dd962f5bSJung-uk Kim 	DEVMETHOD(device_resume,	scpm_resume),
369dd962f5bSJung-uk Kim 	{ 0, 0 }
370dd962f5bSJung-uk Kim };
371dd962f5bSJung-uk Kim 
372dd962f5bSJung-uk Kim static driver_t scpm_driver = {
373dd962f5bSJung-uk Kim 	"scpm",
374dd962f5bSJung-uk Kim 	scpm_methods,
375dd962f5bSJung-uk Kim 	0
376dd962f5bSJung-uk Kim };
377dd962f5bSJung-uk Kim 
378dd962f5bSJung-uk Kim DRIVER_MODULE(scpm, vgapm, scpm_driver, scpm_devclass, 0, 0);
379