summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/vga_pci.c105
-rw-r--r--sys/dev/pci/vga_pcivar.h23
-rw-r--r--sys/dev/vesa/files.vesa11
-rw-r--r--sys/dev/vesa/vesabios.c305
-rw-r--r--sys/dev/vesa/vesabiosreg.h61
-rw-r--r--sys/dev/vesa/vesabiosvar.h27
-rw-r--r--sys/dev/vesa/vesafb.c337
-rw-r--r--sys/dev/vesa/vesafbvar.h80
-rw-r--r--sys/dev/wscons/wsconsio.h23
9 files changed, 967 insertions, 5 deletions
diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c
index 83588cb5680..d664b518569 100644
--- a/sys/dev/pci/vga_pci.c
+++ b/sys/dev/pci/vga_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vga_pci.c,v 1.24 2006/07/20 20:54:51 kettenis Exp $ */
+/* $OpenBSD: vga_pci.c,v 1.25 2006/11/27 18:04:28 gwk Exp $ */
/* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */
/*
@@ -89,10 +89,19 @@
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
+#ifdef VESAFB
+#include <dev/vesa/vesabiosvar.h>
+#endif
+
int vga_pci_match(struct device *, void *, void *);
void vga_pci_attach(struct device *, struct device *, void *);
paddr_t vga_pci_mmap(void* v, off_t off, int prot);
+#ifdef VESAFB
+int vesafb_putcmap(struct vga_pci_softc *, struct wsdisplay_cmap *);
+int vesafb_getcmap(struct vga_pci_softc *, struct wsdisplay_cmap *);
+#endif
+
struct cfattach vga_pci_ca = {
sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach,
};
@@ -143,6 +152,9 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux)
{
struct pci_attach_args *pa = aux;
pcireg_t reg;
+#ifdef VESAFB
+ struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
+#endif
/*
* Enable bus master; X might need this for accelerated graphics.
@@ -154,7 +166,16 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux)
#ifdef PCIAGP
agp_attach(parent, self, aux);
#endif
- printf("\n");
+#ifdef VESAFB
+ if (vesabios_softc != NULL && vesabios_softc->sc_nmodes > 0) {
+ sc->sc_textmode = vesafb_get_mode(sc);
+ printf(", vesafb\n");
+ vga_extended_attach(self, pa->pa_iot, pa->pa_memt,
+ WSDISPLAY_TYPE_PCIVGA, vga_pci_mmap);
+ return;
+ }
+#endif
+ printf("\n");
vga_common_attach(self, pa->pa_iot, pa->pa_memt,
WSDISPLAY_TYPE_PCIVGA);
}
@@ -162,6 +183,14 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux)
paddr_t
vga_pci_mmap(void *v, off_t off, int prot)
{
+#ifdef VESAFB
+ struct vga_config *vc = (struct vga_config *)v;
+ struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
+
+ if (sc->sc_mode == WSDISPLAYIO_MODE_DUMBFB) {
+ return atop(sc->sc_base + off);
+ }
+#endif
#ifdef PCIAGP
return agp_mmap(v, off, prot);
#else
@@ -170,7 +199,7 @@ vga_pci_mmap(void *v, off_t off, int prot)
}
int
-vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt,
+vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt,
pci_chipset_tag_t pc, int bus, int device, int function)
{
return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0));
@@ -180,8 +209,78 @@ int
vga_pci_ioctl(void *v, u_long cmd, caddr_t addr, int flag, struct proc *pb)
{
int error = 0;
+#ifdef VESAFB
+ struct vga_config *vc = (struct vga_config *)v;
+ struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
+ struct wsdisplay_fbinfo *wdf;
+ struct wsdisplay_gfx_mode *gfxmode;
+ int mode;
+#endif
switch (cmd) {
+#ifdef VESAFB
+ case WSDISPLAYIO_SMODE:
+ mode = *(u_int *)addr;
+ switch (mode) {
+ case WSDISPLAYIO_MODE_EMUL:
+ /* back to text mode */
+ vesafb_set_mode(sc, sc->sc_textmode);
+ sc->sc_mode = mode;
+ break;
+ case WSDISPLAYIO_MODE_DUMBFB:
+ if (sc->sc_gfxmode == -1)
+ return (-1);
+ vesafb_set_mode(sc, sc->sc_gfxmode);
+ sc->sc_mode = mode;
+ break;
+ default:
+ error = -1;
+ }
+ break;
+ case WSDISPLAYIO_GINFO:
+ if (sc->sc_gfxmode == -1)
+ return (-1);
+ wdf = (void *)addr;
+ wdf->height = sc->sc_height;
+ wdf->width = sc->sc_width;
+ wdf->depth = sc->sc_depth;
+ wdf->cmsize = 256;
+ break;
+
+ case WSDISPLAYIO_LINEBYTES:
+ if (sc->sc_gfxmode == -1)
+ return (-1);
+ *(u_int *)addr = sc->sc_linebytes;
+ break;
+
+ case WSDISPLAYIO_SVIDEO:
+ case WSDISPLAYIO_GVIDEO:
+ break;
+ case WSDISPLAYIO_GETCMAP:
+ if (sc->sc_depth == 8)
+ error = vesafb_getcmap(sc,
+ (struct wsdisplay_cmap *)addr);
+ break;
+
+ case WSDISPLAYIO_PUTCMAP:
+ if (sc->sc_depth == 8)
+ error = vesafb_putcmap(sc,
+ (struct wsdisplay_cmap *)addr);
+ break;
+
+ case WSDISPLAYIO_GETSUPPORTEDDEPTH:
+ *(int *)addr = vesafb_get_supported_depth(sc);
+ break;
+
+ case WSDISPLAYIO_SETGFXMODE:
+ gfxmode = (struct wsdisplay_gfx_mode *)addr;
+ sc->sc_gfxmode = vesafb_find_mode(sc, gfxmode->width,
+ gfxmode->height, gfxmode->depth);
+ if (sc->sc_gfxmode == -1)
+ error = -1;
+ break;
+
+#endif
#ifdef PCIAGP
case AGPIOC_INFO:
case AGPIOC_ACQUIRE:
diff --git a/sys/dev/pci/vga_pcivar.h b/sys/dev/pci/vga_pcivar.h
index 491a781d975..288fd357dc8 100644
--- a/sys/dev/pci/vga_pcivar.h
+++ b/sys/dev/pci/vga_pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vga_pcivar.h,v 1.6 2006/03/16 21:32:34 matthieu Exp $ */
+/* $OpenBSD: vga_pcivar.h,v 1.7 2006/11/27 18:04:28 gwk Exp $ */
/* $NetBSD: vga_pcivar.h,v 1.1 1998/03/22 15:16:19 drochner Exp $ */
/*
@@ -67,6 +67,20 @@ struct vga_pci_softc {
#if 0
struct vga_config *sc_vc; /* VGA configuration */
#endif
+#ifdef VESAFB
+ int sc_width;
+ int sc_height;
+ int sc_depth;
+ int sc_linebytes;
+ u_int32_t sc_base;
+ int sc_mode; /* WSDISPLAY_MODE_EMUL or _DUMBFB */
+ int sc_textmode; /* original VESA text mode */
+ int sc_gfxmode; /* VESA graphics mode */
+ u_char sc_cmap_red[256]; /* saved color map */
+ u_char sc_cmap_green[256];
+ u_char sc_cmap_blue[256];
+
+#endif
#ifdef PCIAGP
/* agp stuff */
bus_space_tag_t sc_bt, sc_memt;
@@ -112,4 +126,11 @@ int agp_ioctl(void *, u_long, caddr_t, int, struct proc *);
int vga_pci_cnattach(bus_space_tag_t, bus_space_tag_t,
pci_chipset_tag_t, int, int, int);
+#ifdef VESAFB
+int vesafb_find_mode(struct vga_pci_softc *, int, int, int);
+void vesafb_set_mode(struct vga_pci_softc *, int);
+int vesafb_get_mode(struct vga_pci_softc *);
+int vesafb_get_supported_depth(struct vga_pci_softc *);
+#endif
+
#endif /* _PCI_VGA_PCIVAR_H_ */
diff --git a/sys/dev/vesa/files.vesa b/sys/dev/vesa/files.vesa
new file mode 100644
index 00000000000..4a6861e85bf
--- /dev/null
+++ b/sys/dev/vesa/files.vesa
@@ -0,0 +1,11 @@
+# $OpenBSD: files.vesa,v 1.1 2006/11/27 18:04:28 gwk Exp $
+#
+# Config file and device description for VESA BIOS and framebuffer code
+# Included by ports that need it.
+
+define vesabios {}
+device vesabios
+attach vesabios at mainbus
+file dev/vesa/vesabios.c vesabios needs-flag
+
+file dev/vesa/vesafb.c vesafb needs-flag
diff --git a/sys/dev/vesa/vesabios.c b/sys/dev/vesa/vesabios.c
new file mode 100644
index 00000000000..09d0eb4bbd8
--- /dev/null
+++ b/sys/dev/vesa/vesabios.c
@@ -0,0 +1,305 @@
+/* $OpenBSD: */
+
+/*
+ * Copyright (c) 2002, 2004
+ * Matthias Drochner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <machine/frame.h>
+#include <machine/kvm86.h>
+
+#include <dev/vesa/vesabiosvar.h>
+#include <dev/vesa/vesabiosreg.h>
+
+struct vbeinfoblock
+{
+ char VbeSignature[4];
+ uint16_t VbeVersion;
+ uint32_t OemStringPtr;
+ uint32_t Capabilities;
+ uint32_t VideoModePtr;
+ uint16_t TotalMemory;
+ uint16_t OemSoftwareRev;
+ uint32_t OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
+ /* data area, in total max 512 bytes for VBE 2.0 */
+} __attribute__ ((packed));
+
+#define FAR2FLATPTR(p) ((p & 0xffff) + ((p >> 12) & 0xffff0))
+
+int vesabios_match(struct device *, void *, void *);
+void vesabios_attach(struct device *, struct device *, void *);
+int vesabios_print(void *, const char *);
+
+int vbegetinfo(struct vbeinfoblock **);
+void vbefreeinfo(struct vbeinfoblock *);
+#ifdef VESABIOSVERBOSE
+const char *mm2txt(unsigned int);
+#endif
+
+struct vesabios_softc *vesabios_softc;
+
+struct cfattach vesabios_ca = {
+ sizeof(struct vesabios_softc), vesabios_match, vesabios_attach
+};
+
+struct cfdriver vesabios_cd = {
+ NULL, "vesabios", DV_DULL
+};
+
+int
+vesabios_match(struct device *parent, void *match, void *aux)
+{
+
+ return (1);
+}
+
+int
+vbegetinfo(struct vbeinfoblock **vip)
+{
+ unsigned char *buf;
+ struct trapframe tf;
+ int res, error;
+
+ buf = kvm86_bios_addpage(0x2000);
+ if (!buf) {
+ printf("vbegetinfo: kvm86_bios_addpage(0x2000) failed\n");
+ return (ENOMEM);
+ }
+
+ memcpy(buf, "VBE2", 4);
+
+ memset(&tf, 0, sizeof(struct trapframe));
+ tf.tf_eax = 0x4f00; /* function code */
+ tf.tf_vm86_es = 0;
+ tf.tf_edi = 0x2000; /* buf ptr */
+
+ res = kvm86_bioscall(0x10, &tf);
+ if (res || (tf.tf_eax & 0xff) != 0x4f) {
+ printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax);
+ error = ENXIO;
+ goto out;
+ }
+
+ if (memcmp(((struct vbeinfoblock *)buf)->VbeSignature, "VESA", 4)) {
+ error = EIO;
+ goto out;
+ }
+
+ if (vip)
+ *vip = (struct vbeinfoblock *)buf;
+ return (0);
+
+out:
+ kvm86_bios_delpage(0x2000, buf);
+ return (error);
+}
+
+void
+vbefreeinfo(struct vbeinfoblock *vip)
+{
+
+ kvm86_bios_delpage(0x2000, vip);
+}
+
+int
+vbeprobe(void)
+{
+ struct vbeinfoblock *vi;
+ int found = 0;
+
+ if (vbegetinfo(&vi))
+ return (0);
+ if ((vi->VbeVersion >> 8) > 1) {
+ /* VESA bios is at least version 2.0 */
+ found = 1;
+ }
+ vbefreeinfo(vi);
+ return (found);
+}
+
+#ifdef VESABIOSVERBOSE
+const char *
+mm2txt(unsigned int mm)
+{
+ static char buf[30];
+ static const char *names[] = {
+ "Text mode",
+ "CGA graphics",
+ "Hercules graphics",
+ "Planar",
+ "Packed pixel",
+ "Non-chain 4, 256 color",
+ "Direct Color",
+ "YUV"
+ };
+
+ if (mm < sizeof(names)/sizeof(names[0]))
+ return (names[mm]);
+ snprintf(buf, sizeof(buf), "unknown memory model %d", mm);
+ return (buf);
+}
+#endif
+
+void
+vesabios_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct vesabios_softc *sc = (struct vesabios_softc *)self;
+ struct vbeinfoblock *vi;
+ unsigned char *buf;
+ struct trapframe tf;
+ int res;
+ char name[256];
+#define MAXMODES 60
+ uint16_t modes[MAXMODES];
+ int rastermodes[MAXMODES];
+ int textmodes[MAXMODES];
+ int nmodes, nrastermodes, ntextmodes, i;
+ uint32_t modeptr;
+ struct modeinfoblock *mi;
+
+ if (vbegetinfo(&vi)) {
+ printf("\n");
+ panic("vesabios_attach: disappeared");
+ }
+
+ printf(": version %d.%d",
+ vi->VbeVersion >> 8, vi->VbeVersion & 0xff);
+
+ res = kvm86_bios_read(FAR2FLATPTR(vi->OemVendorNamePtr),
+ name, sizeof(name));
+ if (res > 0) {
+ name[res - 1] = 0;
+ printf(", %s", name);
+ res = kvm86_bios_read(FAR2FLATPTR(vi->OemProductNamePtr),
+ name, sizeof(name));
+ if (res > 0) {
+ name[res - 1] = 0;
+ printf(" %s", name);
+ }
+ }
+ printf("\n");
+
+ nmodes = 0;
+ modeptr = FAR2FLATPTR(vi->VideoModePtr);
+ while (nmodes < MAXMODES) {
+ res = kvm86_bios_read(modeptr, (char *)&modes[nmodes], 2);
+ if (res != 2 || modes[nmodes] == 0xffff)
+ break;
+ nmodes++;
+ modeptr += 2;
+ }
+
+ vbefreeinfo(vi);
+ if (nmodes == 0)
+ return;
+
+ nrastermodes = ntextmodes = 0;
+
+ buf = kvm86_bios_addpage(0x2000);
+ if (!buf) {
+ printf("%s: kvm86_bios_addpage(0x2000) failed\n",
+ self->dv_xname);
+ return;
+ }
+ for (i = 0; i < nmodes; i++) {
+
+ memset(&tf, 0, sizeof(struct trapframe));
+ tf.tf_eax = 0x4f01; /* function code */
+ tf.tf_ecx = modes[i];
+ tf.tf_vm86_es = 0;
+ tf.tf_edi = 0x2000; /* buf ptr */
+
+ res = kvm86_bioscall(0x10, &tf);
+ if (res || (tf.tf_eax & 0xff) != 0x4f) {
+ printf("%s: vbecall: res=%d, ax=%x\n",
+ self->dv_xname, res, tf.tf_eax);
+ printf("%s: error getting info for mode %04x\n",
+ self->dv_xname, modes[i]);
+ continue;
+ }
+ mi = (struct modeinfoblock *)buf;
+#ifdef VESABIOSVERBOSE
+ printf("%s: VESA mode %04x: attributes %04x",
+ self->dv_xname, modes[i], mi->ModeAttributes);
+#endif
+ if (!(mi->ModeAttributes & 1)) {
+#ifdef VESABIOSVERBOSE
+ printf("\n");
+#endif
+ continue;
+ }
+ if (mi->ModeAttributes & 0x10) {
+ /* graphics */
+#ifdef VESABIOSVERBOSE
+ printf(", %dx%d %dbbp %s\n",
+ mi->XResolution, mi->YResolution,
+ mi->BitsPerPixel, mm2txt(mi->MemoryModel));
+#endif
+ if (mi->ModeAttributes & 0x80) {
+ /* flat buffer */
+ rastermodes[nrastermodes++] = modes[i];
+ }
+ } else {
+ /* text */
+#ifdef VESABIOSVERBOSE
+ printf(", text %dx%d\n",
+ mi->XResolution, mi->YResolution);
+#endif
+ if (!(mi->ModeAttributes & 0x20)) /* VGA compatible */
+ textmodes[ntextmodes++] = modes[i];
+ }
+ }
+ kvm86_bios_delpage(0x2000, buf);
+ if (nrastermodes > 0) {
+ sc->sc_modes =
+ (uint16_t *)malloc(sizeof(uint16_t)*nrastermodes,
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_modes == NULL) {
+ sc->sc_nmodes = 0;
+ return;
+ }
+ sc->sc_nmodes = nrastermodes;
+ for (i = 0; i < nrastermodes; i++)
+ sc->sc_modes[i] = rastermodes[i];
+ }
+ vesabios_softc = sc;
+}
+
+int
+vesabios_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ char *busname = aux;
+
+ if (pnp)
+ printf("%s at %s", busname, pnp);
+ return (UNCONF);
+}
diff --git a/sys/dev/vesa/vesabiosreg.h b/sys/dev/vesa/vesabiosreg.h
new file mode 100644
index 00000000000..131259a9cfe
--- /dev/null
+++ b/sys/dev/vesa/vesabiosreg.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: vesabiosreg.h,v 1.1 2006/11/27 18:04:28 gwk Exp $ */
+
+/*
+ * Written by M. Drochner
+ * Public domain.
+ */
+
+
+#ifndef _VESABIOSREG_H
+#define _VESABIOSREG_H
+
+struct modeinfoblock {
+ /* Mandatory information for all VBE revisions */
+ uint16_t ModeAttributes;
+ uint8_t WinAAttributes, WinBAttributes;
+ uint16_t WinGranularity, WinSize, WinASegment, WinBSegment;
+ uint32_t WinFuncPtr;
+ uint16_t BytesPerScanLine;
+ /* Mandatory information for VBE 1.2 and above */
+ uint16_t XResolution, YResolution;
+ uint8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
+ uint8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
+ uint8_t Reserved1;
+ /* Direct Color fields
+ (required for direct/6 and YUV/7 memory models) */
+ uint8_t RedMaskSize, RedFieldPosition;
+ uint8_t GreenMaskSize, GreenFieldPosition;
+ uint8_t BlueMaskSize, BlueFieldPosition;
+ uint8_t RsvdMaskSize, RsvdFieldPosition;
+ uint8_t DirectColorModeInfo;
+ /* Mandatory information for VBE 2.0 and above */
+ uint32_t PhysBasePtr;
+#ifdef VBE_2_0
+ uint32_t OffScreenMemOffset;
+ uint16_t OffScreenMemSize;
+ uint8_t Reserved2[206];
+#else
+ uint32_t Reserved2;
+ uint16_t Reserved3;
+
+ /* Mandatory information for VBE 3.0 and above */
+ uint16_t LinBytesPerScanLine;
+ uint8_t BnkNumberOfImagePages;
+ uint8_t LinNumberOfImagePages;
+ uint8_t LinRedMaskSize, LinRedFieldPosition;
+ uint8_t LinGreenMaskSize, LinGreenFieldPosition;
+ uint8_t LinBlueMaskSize, LinBlueFieldPosition;
+ uint8_t LinRsvdMaskSize, LinRsvdFieldPosition;
+ uint32_t MaxPixelClock;
+ uint8_t Reserved4[189];
+#endif
+} __attribute__ ((packed));
+
+struct paletteentry {
+ uint8_t Blue;
+ uint8_t Green;
+ uint8_t Red;
+ uint8_t Alignment;
+} __attribute__ ((packed));
+
+#endif /* !_VESABIOSREG_H */
diff --git a/sys/dev/vesa/vesabiosvar.h b/sys/dev/vesa/vesabiosvar.h
new file mode 100644
index 00000000000..38db88e8901
--- /dev/null
+++ b/sys/dev/vesa/vesabiosvar.h
@@ -0,0 +1,27 @@
+/* $OpenBSD: vesabiosvar.h,v 1.1 2006/11/27 18:04:28 gwk Exp $ */
+
+/*
+ * Copyright (c) 2006 Matthieu Herrb
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+extern int vbeprobe(void);
+
+struct vesabios_softc {
+ struct device sc_dev;
+ int sc_nmodes;
+ uint16_t *sc_modes;
+};
+
+extern struct vesabios_softc *vesabios_softc;
diff --git a/sys/dev/vesa/vesafb.c b/sys/dev/vesa/vesafb.c
new file mode 100644
index 00000000000..e1d6c9b1514
--- /dev/null
+++ b/sys/dev/vesa/vesafb.c
@@ -0,0 +1,337 @@
+/* $OpenBSD: vesafb.c,v 1.1 2006/11/27 18:04:28 gwk Exp $ */
+
+/*-
+ * Copyright (c) 2006 Jared D. McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2006 Matthieu Herrb
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/ic/mc6845reg.h>
+#include <dev/ic/pcdisplayvar.h>
+#include <dev/ic/vgareg.h>
+#include <dev/ic/vgavar.h>
+#include <dev/pci/vga_pcivar.h>
+
+#include <dev/vesa/vesabiosreg.h>
+#include <dev/vesa/vesabiosvar.h>
+
+#include <machine/frame.h>
+#include <machine/kvm86.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+
+#include <uvm/uvm_extern.h>
+
+
+
+void vesafb_set_mode(struct vga_pci_softc *, int);
+int vesafb_get_mode(struct vga_pci_softc *);
+void vesafb_get_mode_info(struct vga_pci_softc *, int, struct modeinfoblock *);
+void vesafb_set_palette(struct vga_pci_softc *, int, struct paletteentry);
+int vesafb_putcmap(struct vga_pci_softc *, struct wsdisplay_cmap *);
+int vesafb_getcmap(struct vga_pci_softc *, struct wsdisplay_cmap *);
+
+
+
+int
+vesafb_get_mode(struct vga_pci_softc *sc)
+{
+ struct trapframe tf;
+ int res;
+
+ bzero(&tf, sizeof(struct trapframe));
+ tf.tf_eax = 0x4f03;
+
+ res = kvm86_bioscall(0x10, &tf);
+ if (res || (tf.tf_eax & 0xff) != 0x4f) {
+ printf("%s: vbecall: res=%d, ax=%x\n",
+ sc->sc_dev.dv_xname, res, tf.tf_eax);
+ }
+ return tf.tf_ebx & 0xffff;
+}
+
+void
+vesafb_get_mode_info(struct vga_pci_softc *sc, int mode,
+ struct modeinfoblock *mi)
+{
+ struct trapframe tf;
+ unsigned char *buf;
+ int res;
+
+ buf = kvm86_bios_addpage(0x2000);
+ memset(&tf, 0, sizeof(struct trapframe));
+ tf.tf_eax = 0x4f01; /* function code */
+ tf.tf_ecx = mode;
+ tf.tf_vm86_es = 0;
+ tf.tf_edi = 0x2000; /* buf ptr */
+
+ res = kvm86_bioscall(0x10, &tf);
+ if (res || (tf.tf_eax & 0xff) != 0x4f) {
+ printf("%s: vbecall: res=%d, ax=%x\n",
+ sc->sc_dev.dv_xname, res, tf.tf_eax);
+ printf("%s: error getting info for mode %04x\n",
+ sc->sc_dev.dv_xname, mode);
+ return;
+ }
+ memcpy(mi, buf, sizeof(struct modeinfoblock));
+ kvm86_bios_delpage(0x2000, buf);
+}
+
+void
+vesafb_set_palette(struct vga_pci_softc *sc, int reg, struct paletteentry pe)
+{
+ struct trapframe tf;
+ int res;
+ char *buf;
+
+ buf = kvm86_bios_addpage(0x2000);
+
+ /*
+ * this function takes 8 bit per palette as input, but we're
+ * working in 6 bit mode here
+ */
+ pe.Red >>= 2;
+ pe.Green >>= 2;
+ pe.Blue >>= 2;
+
+ memcpy(buf, &pe, sizeof(struct paletteentry));
+
+ /* set palette */
+ memset(&tf, 0, sizeof(struct trapframe));
+ tf.tf_eax = 0x4f09; /* function code */
+ tf.tf_ebx = 0x0600; /* 6 bit per primary, set format */
+ tf.tf_ecx = 1;
+ tf.tf_edx = reg;
+ tf.tf_vm86_es = 0;
+ tf.tf_edi = 0x2000;
+
+ res = kvm86_bioscall(0x10, &tf);
+ if (res || (tf.tf_eax & 0xff) != 0x4f)
+ printf("%s: vbecall: res=%d, ax=%x\n",
+ sc->sc_dev.dv_xname, res, tf.tf_eax);
+
+ kvm86_bios_delpage(0x2000, buf);
+ return;
+}
+
+void
+vesafb_set_mode(struct vga_pci_softc *sc, int mode)
+{
+ struct trapframe tf;
+ int res;
+
+ bzero(&tf, sizeof(struct trapframe));
+ tf.tf_eax = 0x4f02;
+ tf.tf_ebx = mode | 0x4000; /* flat */
+
+ res = kvm86_bioscall(0x10, &tf);
+ if (res || (tf.tf_eax & 0xff) != 0x4f) {
+ printf("%s: vbecall: res=%d, ax=%x\n",
+ sc->sc_dev.dv_xname, res, tf.tf_eax);
+ return;
+ }
+}
+
+int
+vesafb_find_mode(struct vga_pci_softc *sc, int width, int height, int bpp)
+{
+ struct modeinfoblock mi;
+ int i;
+
+ if (vesabios_softc == NULL || vesabios_softc->sc_nmodes == 0)
+ return -1;
+
+ printf("vesafb_find_mode %d %d %d\n", width, height, bpp);
+ /* Choose a graphics mode */
+ for (i = 0; i < vesabios_softc->sc_nmodes; i++) {
+ vesafb_get_mode_info(sc, vesabios_softc->sc_modes[i], &mi);
+ if (mi.XResolution == width &&
+ mi.YResolution == height &&
+ mi.BitsPerPixel == bpp) {
+ sc->sc_width = mi.XResolution;
+ sc->sc_height = mi.YResolution;
+ sc->sc_depth = mi.BitsPerPixel;
+ sc->sc_linebytes = mi.BytesPerScanLine;
+ sc->sc_base = mi.PhysBasePtr;
+ break;
+ }
+ }
+ if (i == vesabios_softc->sc_nmodes)
+ return -1;
+ else
+ return vesabios_softc->sc_modes[i];
+}
+
+int
+vesafb_putcmap(struct vga_pci_softc *sc, struct wsdisplay_cmap *cm)
+{
+ struct paletteentry pe;
+ u_int idx, cnt;
+ u_char r[256], g[256], b[256];
+ u_char *rp, *gp, *bp;
+ int rv, i;
+
+ idx = cm->index;
+ cnt = cm->count;
+
+ if (idx >= 255 || cnt > 256 || idx + cnt > 256)
+ return EINVAL;
+
+ rv = copyin(cm->red, &r[idx], cnt);
+ if (rv)
+ return rv;
+ rv = copyin(cm->green, &g[idx], cnt);
+ if (rv)
+ return rv;
+ rv = copyin(cm->blue, &b[idx], cnt);
+ if (rv)
+ return rv;
+
+ memcpy(&sc->sc_cmap_red[idx], &r[idx], cnt);
+ memcpy(&sc->sc_cmap_green[idx], &g[idx], cnt);
+ memcpy(&sc->sc_cmap_blue[idx], &b[idx], cnt);
+
+ rp = &sc->sc_cmap_red[idx];
+ gp = &sc->sc_cmap_green[idx];
+ bp = &sc->sc_cmap_blue[idx];
+
+ for (i = 0; i < cnt; i++) {
+ pe.Blue = *bp;
+ pe.Green = *gp;
+ pe.Red = *rp;
+ pe.Alignment = 0;
+ vesafb_set_palette(sc, idx, pe);
+ idx++;
+ rp++, gp++, bp++;
+ }
+
+ return 0;
+}
+
+int
+vesafb_getcmap(struct vga_pci_softc *sc, struct wsdisplay_cmap *cm)
+{
+ u_int idx, cnt;
+ int rv;
+
+ idx = cm->index;
+ cnt = cm->count;
+
+ if (idx >= 255 || cnt > 256 || idx + cnt > 256)
+ return EINVAL;
+
+ rv = copyout(&sc->sc_cmap_red[idx], cm->red, cnt);
+ if (rv)
+ return rv;
+ rv = copyout(&sc->sc_cmap_green[idx], cm->green, cnt);
+ if (rv)
+ return rv;
+ rv = copyout(&sc->sc_cmap_blue[idx], cm->blue, cnt);
+ if (rv)
+ return rv;
+
+ return 0;
+}
+
+static int
+vesafb_getdepthflag(struct modeinfoblock *mi)
+{
+ int bpp, depth;
+
+
+ depth = mi->RedMaskSize + mi->GreenMaskSize + mi->BlueMaskSize;
+ bpp = mi->BitsPerPixel;
+ switch (depth) {
+ case 1:
+ return WSDISPLAYIO_DEPTH_1;
+ case 4:
+ return WSDISPLAYIO_DEPTH_4;
+ case 8:
+ return WSDISPLAYIO_DEPTH_8;
+ case 15:
+ return WSDISPLAYIO_DEPTH_15;
+ case 16:
+ return WSDISPLAYIO_DEPTH_16;
+ case 24:
+ switch (bpp) {
+ case 24:
+ return WSDISPLAYIO_DEPTH_24_24;
+ case 32:
+ return WSDISPLAYIO_DEPTH_24_32;
+ }
+ }
+ return 0;
+}
+
+
+int
+vesafb_get_supported_depth(struct vga_pci_softc *sc)
+{
+ int i, depths;
+ struct modeinfoblock mi;
+
+ depths = 0;
+
+ if (vesabios_softc == NULL || vesabios_softc->sc_nmodes == 0)
+ return 0;
+
+ for (i = 0; i < vesabios_softc->sc_nmodes; i++) {
+ vesafb_get_mode_info(sc, vesabios_softc->sc_modes[i], &mi);
+ depths |= vesafb_getdepthflag(&mi);
+ }
+ return depths;
+}
diff --git a/sys/dev/vesa/vesafbvar.h b/sys/dev/vesa/vesafbvar.h
new file mode 100644
index 00000000000..659f04670fe
--- /dev/null
+++ b/sys/dev/vesa/vesafbvar.h
@@ -0,0 +1,80 @@
+/* $OpenBSD: vesafbvar.h,v 1.1 2006/11/27 18:04:28 gwk Exp $ */
+
+/*-
+ * Copyright (c) 2006 Jared D. McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2006 Matthieu Herrb
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _VESAFBVAR_H
+#define _VESAFBVAR_H
+
+struct vesafb_softc {
+ struct device sc_dev;
+ struct modeinfoblock sc_mi;
+ int sc_mode;
+ int sc_gfxmode;
+ int sc_textmode;
+ int sc_isconsole;
+ char *sc_buf;
+ u_char *sc_bits;
+ u_char *sc_shadowbits;
+ u_char sc_cmap_red[256];
+ u_char sc_cmap_green[256];
+ u_char sc_cmap_blue[256];
+ int sc_wsmode;
+ int sc_nscreens;
+
+ int sc_pm;
+ uint8_t sc_pmver;
+ uint8_t sc_pmstates;
+ void *sc_powerhook;
+};
+
+
+int vesafb_cnattach(bus_space_tag_t, bus_space_tag_t,
+ pci_chipset_tag_t, int, int, int);
+
+#endif
diff --git a/sys/dev/wscons/wsconsio.h b/sys/dev/wscons/wsconsio.h
index 3fb5988a178..73ffb75dc3b 100644
--- a/sys/dev/wscons/wsconsio.h
+++ b/sys/dev/wscons/wsconsio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsconsio.h,v 1.42 2006/08/06 16:00:45 miod Exp $ */
+/* $OpenBSD: wsconsio.h,v 1.43 2006/11/27 18:04:28 gwk Exp $ */
/* $NetBSD: wsconsio.h,v 1.74 2005/04/28 07:15:44 martin Exp $ */
/*
@@ -436,6 +436,27 @@ struct wsdisplay_param {
#define WSDISPLAYIO_GPCIID _IOR('W', 91, struct pcisel)
+/* graphical mode control */
+
+#define WSDISPLAYIO_DEPTH_1 0x1
+#define WSDISPLAYIO_DEPTH_4 0x2
+#define WSDISPLAYIO_DEPTH_8 0x4
+#define WSDISPLAYIO_DEPTH_15 0x8
+#define WSDISPLAYIO_DEPTH_16 0x10
+#define WSDISPLAYIO_DEPTH_24_24 0x20
+#define WSDISPLAYIO_DEPTH_24_32 0x40
+#define WSDISPLAYIO_DEPTH_24 (WSDISPLAYIO_DEPTH_24_24|WSDISPLAYIO_DEPTH_24_32)
+
+#define WSDISPLAYIO_GETSUPPORTEDDEPTH _IOR('W', 92, unsigned int)
+
+struct wsdisplay_gfx_mode {
+ int width;
+ int height;
+ int depth;
+};
+
+#define WSDISPLAYIO_SETGFXMODE _IOW('W', 92, struct wsdisplay_gfx_mode)
+
/* XXX NOT YET DEFINED */
/* Mapping information retrieval. */