vga_isa.c revision 199229
150276Speter/*-
297049Speter * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
350276Speter * All rights reserved.
450276Speter *
550276Speter * Redistribution and use in source and binary forms, with or without
650276Speter * modification, are permitted provided that the following conditions
750276Speter * are met:
850276Speter * 1. Redistributions of source code must retain the above copyright
950276Speter *    notice, this list of conditions and the following disclaimer as
1050276Speter *    the first lines of this file unmodified.
1150276Speter * 2. Redistributions in binary form must reproduce the above copyright
1250276Speter *    notice, this list of conditions and the following disclaimer in the
1350276Speter *    documentation and/or other materials provided with the distribution.
1450276Speter *
1550276Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1650276Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1750276Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1850276Speter * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1950276Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2050276Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2150276Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2250276Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2350276Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2450276Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2550276Speter */
2650276Speter
2750276Speter#include <sys/cdefs.h>
2850276Speter__FBSDID("$FreeBSD: head/sys/isa/vga_isa.c 199229 2009-11-12 17:56:56Z jkim $");
2950276Speter
3050276Speter#include "opt_vga.h"
3150276Speter#include "opt_fb.h"
3297049Speter#include "opt_syscons.h"	/* should be removed in the future, XXX */
3350276Speter
3450276Speter#include <sys/param.h>
3550276Speter#include <sys/systm.h>
3650276Speter#include <sys/kernel.h>
3750276Speter#include <sys/malloc.h>
3850276Speter#include <sys/module.h>
3950276Speter#include <sys/conf.h>
4050276Speter#include <sys/bus.h>
4150276Speter#include <sys/fbio.h>
4250276Speter
4350276Speter#include <machine/bus.h>
4450276Speter#include <machine/resource.h>
4550276Speter
4650276Speter#include <sys/rman.h>
4750276Speter
4850276Speter#include <vm/vm.h>
4950276Speter#include <vm/pmap.h>
5050276Speter
5150276Speter#include <machine/md_var.h>
5297049Speter#ifdef __i386__
5397049Speter#include <machine/pc/bios.h>
5497049Speter#endif
5550276Speter
5697049Speter#include <dev/fb/fbreg.h>
5750276Speter#include <dev/fb/vgareg.h>
5897049Speter
5950276Speter#include <isa/isareg.h>
6050276Speter#include <isa/isavar.h>
6150276Speter
6250276Speterstatic void
6350276Spetervga_suspend(device_t dev)
6450276Speter{
6550276Speter	vga_softc_t *sc;
6650276Speter	int nbytes;
6750276Speter
6850276Speter	sc = device_get_softc(dev);
6950276Speter
7050276Speter	/* Save the video state across the suspend. */
7150276Speter	if (sc->state_buf != NULL)
7297049Speter		goto save_palette;
7350276Speter	nbytes = vidd_save_state(sc->adp, NULL, 0);
7450276Speter	if (nbytes <= 0)
7550276Speter		goto save_palette;
7650276Speter	sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT);
7750276Speter	if (sc->state_buf == NULL)
7850276Speter		goto save_palette;
7950276Speter	if (bootverbose)
8050276Speter		device_printf(dev, "saving %d bytes of video state\n", nbytes);
8150276Speter	if (vidd_save_state(sc->adp, sc->state_buf, nbytes) != 0) {
8250276Speter		device_printf(dev, "failed to save state (nbytes=%d)\n",
8350276Speter		    nbytes);
8450276Speter		free(sc->state_buf, M_TEMP);
8550276Speter		sc->state_buf = NULL;
8650276Speter	}
8750276Speter
8850276Spetersave_palette:
8950276Speter	/* Save the color palette across the suspend. */
9050276Speter	if (sc->pal_buf != NULL)
9150276Speter		return;
9250276Speter	sc->pal_buf = malloc(256 * 3, M_TEMP, M_NOWAIT);
9350276Speter	if (sc->pal_buf == NULL)
9450276Speter		return;
9550276Speter	if (bootverbose)
9650276Speter		device_printf(dev, "saving color palette\n");
9750276Speter	if (vidd_save_palette(sc->adp, sc->pal_buf) != 0) {
9850276Speter		device_printf(dev, "failed to save palette\n");
9950276Speter		free(sc->pal_buf, M_TEMP);
10050276Speter		sc->pal_buf = NULL;
10150276Speter	}
10250276Speter}
10350276Speter
10450276Speterstatic void
10550276Spetervga_resume(device_t dev)
10650276Speter{
10750276Speter	vga_softc_t *sc;
10850276Speter
10950276Speter	sc = device_get_softc(dev);
11050276Speter
11150276Speter	if (sc->state_buf != NULL) {
11250276Speter		if (vidd_load_state(sc->adp, sc->state_buf) != 0)
11350276Speter			device_printf(dev, "failed to reload state\n");
11450276Speter		free(sc->state_buf, M_TEMP);
11550276Speter		sc->state_buf = NULL;
11650276Speter	}
11750276Speter	if (sc->pal_buf != NULL) {
11850276Speter		if (vidd_load_palette(sc->adp, sc->pal_buf) != 0)
11950276Speter			device_printf(dev, "failed to reload palette\n");
12050276Speter		free(sc->pal_buf, M_TEMP);
12150276Speter		sc->pal_buf = NULL;
12250276Speter	}
12350276Speter}
12450276Speter
12550276Speter#define VGA_SOFTC(unit)		\
12650276Speter	((vga_softc_t *)devclass_get_softc(isavga_devclass, unit))
12750276Speter
12850276Speterstatic devclass_t	isavga_devclass;
12950276Speter
13050276Speter#ifdef FB_INSTALL_CDEV
13150276Speter
13250276Speterstatic d_open_t		isavga_open;
13350276Speterstatic d_close_t	isavga_close;
13450276Speterstatic d_read_t		isavga_read;
13550276Speterstatic d_write_t	isavga_write;
13650276Speterstatic d_ioctl_t	isavga_ioctl;
13750276Speterstatic d_mmap_t		isavga_mmap;
13850276Speter
13950276Speterstatic struct cdevsw isavga_cdevsw = {
14050276Speter	.d_version =	D_VERSION,
14150276Speter	.d_flags =	D_NEEDGIANT,
14250276Speter	.d_open =	isavga_open,
14350276Speter	.d_close =	isavga_close,
14450276Speter	.d_read =	isavga_read,
14550276Speter	.d_write =	isavga_write,
14650276Speter	.d_ioctl =	isavga_ioctl,
14750276Speter	.d_mmap =	isavga_mmap,
14850276Speter	.d_name =	VGA_DRIVER_NAME,
14950276Speter};
15050276Speter
15150276Speter#endif /* FB_INSTALL_CDEV */
15250276Speter
15350276Speterstatic void
15450276Speterisavga_identify(driver_t *driver, device_t parent)
15550276Speter{
15650276Speter	BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, VGA_DRIVER_NAME, 0);
15750276Speter}
15850276Speter
15950276Speterstatic int
16050276Speterisavga_probe(device_t dev)
16150276Speter{
16250276Speter	video_adapter_t adp;
16350276Speter	int error;
16450276Speter
16550276Speter	/* No pnp support */
16650276Speter	if (isa_get_vendorid(dev))
16750276Speter		return (ENXIO);
16850276Speter
16950276Speter	error = vga_probe_unit(device_get_unit(dev), &adp, device_get_flags(dev));
17050276Speter	if (error == 0) {
17150276Speter		device_set_desc(dev, "Generic ISA VGA");
17250276Speter		bus_set_resource(dev, SYS_RES_IOPORT, 0,
17350276Speter				 adp.va_io_base, adp.va_io_size);
17450276Speter		bus_set_resource(dev, SYS_RES_MEMORY, 0,
17550276Speter				 adp.va_mem_base, adp.va_mem_size);
17650276Speter#if 0
17750276Speter		isa_set_port(dev, adp.va_io_base);
17850276Speter		isa_set_portsize(dev, adp.va_io_size);
17950276Speter		isa_set_maddr(dev, adp.va_mem_base);
18050276Speter		isa_set_msize(dev, adp.va_mem_size);
18150276Speter#endif
18250276Speter	}
18350276Speter	return (error);
18450276Speter}
18550276Speter
18650276Speterstatic int
18750276Speterisavga_attach(device_t dev)
18850276Speter{
18950276Speter	vga_softc_t *sc;
19050276Speter	int unit;
19150276Speter	int rid;
19250276Speter	int error;
19350276Speter
19450276Speter	unit = device_get_unit(dev);
19550276Speter	sc = device_get_softc(dev);
19650276Speter
19750276Speter	rid = 0;
19850276Speter	bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
19950276Speter				  0, ~0, 0, RF_ACTIVE | RF_SHAREABLE);
20050276Speter	rid = 0;
20150276Speter	bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
20250276Speter				 0, ~0, 0, RF_ACTIVE | RF_SHAREABLE);
20350276Speter
20450276Speter	error = vga_attach_unit(unit, sc, device_get_flags(dev));
20550276Speter	if (error)
20650276Speter		return (error);
20750276Speter
20850276Speter#ifdef FB_INSTALL_CDEV
20950276Speter	/* attach a virtual frame buffer device */
21050276Speter	error = fb_attach(VGA_MKMINOR(unit), sc->adp, &isavga_cdevsw);
21150276Speter	if (error)
21297049Speter		return (error);
21397049Speter#endif /* FB_INSTALL_CDEV */
21497049Speter
21597049Speter	if (0 && bootverbose)
21697049Speter		vidd_diag(sc->adp, bootverbose);
21797049Speter
21897049Speter#if 0 /* experimental */
21997049Speter	device_add_child(dev, "fb", -1);
22097049Speter	bus_generic_attach(dev);
22197049Speter#endif
22297049Speter
22397049Speter	return (0);
22497049Speter}
22597049Speter
22697049Speterstatic int
22797049Speterisavga_suspend(device_t dev)
22897049Speter{
22997049Speter	int error;
23097049Speter
23197049Speter	error = bus_generic_suspend(dev);
23297049Speter	if (error != 0)
23397049Speter		return (error);
23497049Speter	vga_suspend(dev);
23597049Speter
23697049Speter	return (error);
23797049Speter}
23897049Speter
23997049Speterstatic int
24097049Speterisavga_resume(device_t dev)
24197049Speter{
24297049Speter
24397049Speter	vga_resume(dev);
24497049Speter
24597049Speter	return (bus_generic_resume(dev));
24697049Speter}
24797049Speter
24897049Speter#ifdef FB_INSTALL_CDEV
24950276Speter
25050276Speterstatic int
25150276Speterisavga_open(struct cdev *dev, int flag, int mode, struct thread *td)
25250276Speter{
25350276Speter	return (vga_open(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td));
25450276Speter}
25550276Speter
25650276Speterstatic int
25750276Speterisavga_close(struct cdev *dev, int flag, int mode, struct thread *td)
25850276Speter{
25950276Speter	return (vga_close(dev, VGA_SOFTC(VGA_UNIT(dev)), flag, mode, td));
26050276Speter}
26150276Speter
26297049Speterstatic int
26397049Speterisavga_read(struct cdev *dev, struct uio *uio, int flag)
26497049Speter{
26597049Speter	return (vga_read(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag));
26697049Speter}
26797049Speter
26897049Speterstatic int
26997049Speterisavga_write(struct cdev *dev, struct uio *uio, int flag)
27097049Speter{
27197049Speter	return (vga_write(dev, VGA_SOFTC(VGA_UNIT(dev)), uio, flag));
27297049Speter}
27397049Speter
27497049Speterstatic int
27550276Speterisavga_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
27697049Speter{
27797049Speter	return (vga_ioctl(dev, VGA_SOFTC(VGA_UNIT(dev)), cmd, arg, flag, td));
27897049Speter}
27950276Speter
28050276Speterstatic int
28150276Speterisavga_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int prot)
28250276Speter{
28350276Speter	return (vga_mmap(dev, VGA_SOFTC(VGA_UNIT(dev)), offset, paddr, prot));
28450276Speter}
28550276Speter
28650276Speter#endif /* FB_INSTALL_CDEV */
28750276Speter
28850276Speterstatic device_method_t isavga_methods[] = {
28950276Speter	DEVMETHOD(device_identify,	isavga_identify),
29050276Speter	DEVMETHOD(device_probe,		isavga_probe),
29150276Speter	DEVMETHOD(device_attach,	isavga_attach),
29250276Speter	DEVMETHOD(device_suspend,	isavga_suspend),
29350276Speter	DEVMETHOD(device_resume,	isavga_resume),
29497049Speter
29597049Speter	DEVMETHOD(bus_print_child,	bus_generic_print_child),
29697049Speter	{ 0, 0 }
29797049Speter};
29897049Speter
29997049Speterstatic driver_t isavga_driver = {
30097049Speter	VGA_DRIVER_NAME,
30197049Speter	isavga_methods,
30297049Speter	sizeof(vga_softc_t),
30397049Speter};
30497049Speter
30597049SpeterDRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0);
30697049Speter
30797049Speterstatic devclass_t	vgapm_devclass;
30897049Speter
30997049Speterstatic void
31097049Spetervgapm_identify(driver_t *driver, device_t parent)
31150276Speter{
31250276Speter
31350276Speter	if (device_get_flags(parent) != 0)
31450276Speter		device_add_child(parent, "vgapm", 0);
31550276Speter}
31650276Speter
31750276Speterstatic int
31850276Spetervgapm_probe(device_t dev)
31950276Speter{
32050276Speter
32150276Speter	device_set_desc(dev, "VGA suspend/resume");
32250276Speter	device_quiet(dev);
32350276Speter
32497049Speter	return (BUS_PROBE_DEFAULT);
32597049Speter}
32697049Speter
32797049Speterstatic int
32897049Spetervgapm_attach(device_t dev)
32997049Speter{
33097049Speter
33197049Speter	return (0);
33297049Speter}
33397049Speter
33497049Speterstatic int
33597049Spetervgapm_suspend(device_t dev)
33697049Speter{
33797049Speter	device_t vga_dev;
33897049Speter	int error;
33997049Speter
34097049Speter	error = bus_generic_suspend(dev);
34197049Speter	if (error != 0)
34297049Speter		return (error);
34397049Speter	vga_dev = devclass_get_device(isavga_devclass, 0);
34497049Speter	if (vga_dev == NULL)
34597049Speter		return (0);
34697049Speter	vga_suspend(vga_dev);
34797049Speter
34897049Speter	return (0);
34997049Speter}
35097049Speter
35197049Speterstatic int
35297049Spetervgapm_resume(device_t dev)
35397049Speter{
35497049Speter	device_t vga_dev;
35597049Speter
35697049Speter	vga_dev = devclass_get_device(isavga_devclass, 0);
35797049Speter	if (vga_dev != NULL)
35897049Speter		vga_resume(vga_dev);
35997049Speter
36097049Speter	return (bus_generic_resume(dev));
36197049Speter}
36297049Speter
36397049Speterstatic device_method_t vgapm_methods[] = {
36497049Speter	DEVMETHOD(device_identify,	vgapm_identify),
36597049Speter	DEVMETHOD(device_probe,		vgapm_probe),
36697049Speter	DEVMETHOD(device_attach,	vgapm_attach),
36797049Speter	DEVMETHOD(device_suspend,	vgapm_suspend),
36897049Speter	DEVMETHOD(device_resume,	vgapm_resume),
36997049Speter	{ 0, 0 }
37097049Speter};
37197049Speter
37297049Speterstatic driver_t vgapm_driver = {
37397049Speter	"vgapm",
37497049Speter	vgapm_methods,
37597049Speter	0
37697049Speter};
37797049Speter
37897049SpeterDRIVER_MODULE(vgapm, vgapci, vgapm_driver, vgapm_devclass, 0, 0);
37997049Speter