diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/vga_pci.c | 105 | ||||
-rw-r--r-- | sys/dev/pci/vga_pcivar.h | 23 | ||||
-rw-r--r-- | sys/dev/vesa/files.vesa | 11 | ||||
-rw-r--r-- | sys/dev/vesa/vesabios.c | 305 | ||||
-rw-r--r-- | sys/dev/vesa/vesabiosreg.h | 61 | ||||
-rw-r--r-- | sys/dev/vesa/vesabiosvar.h | 27 | ||||
-rw-r--r-- | sys/dev/vesa/vesafb.c | 337 | ||||
-rw-r--r-- | sys/dev/vesa/vesafbvar.h | 80 | ||||
-rw-r--r-- | sys/dev/wscons/wsconsio.h | 23 |
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. */ |