diff --git a/sys/arch/i386/bios/vesa_raster8.c b/sys/arch/i386/bios/vesa_raster8.c new file mode 100644 index 000000000000..8fd4a8eea336 --- /dev/null +++ b/sys/arch/i386/bios/vesa_raster8.c @@ -0,0 +1,183 @@ +/* $NetBSD: vesa_raster8.c,v 1.1 2002/07/10 19:15:42 drochner Exp $ */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +static int vesaraster8_match(struct device *, struct cfdata *, void *); +static void vesaraster8_attach(struct device *, struct device *, void *); + +struct vesaraster8sc { + struct device sc_dev; + int sc_mode; + struct rasops_info sc_ri; +}; + +struct cfattach vesarasterviii_ca = { + sizeof(struct vesaraster8sc), vesaraster8_match, vesaraster8_attach +}; + +static int +vesaraster8_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct vesabiosdev_attach_args *vaa = aux; + + if (strcmp(vaa->vbaa_type, "raster8")) + return (0); + + return (1); +} + +static void +vesaraster8_attach(parent, dev, aux) + struct device *parent, *dev; + void *aux; +{ + struct vesaraster8sc *sc = (struct vesaraster8sc *)dev; + struct vesabiosdev_attach_args *vaa = aux; + unsigned char *buf; + struct trapframe tf; + int res; + struct modeinfoblock *mi; + struct rasops_info *ri; + bus_space_handle_t h; + + buf = kvm86_bios_addpage(0x2000); + if (!buf) { + printf("vesaraster8_attach: kvm86_bios_addpage(0x2000) failed\n"); + return; + } + + sc->sc_mode = vaa->vbaa_modes[0]; /* XXX */ + + memset(&tf, 0, sizeof(struct trapframe)); + tf.tf_eax = 0x4f01; /* function code */ + tf.tf_ecx = sc->sc_mode; + tf.tf_es = 0; + tf.tf_edi = 0x2000; /* buf ptr */ + + res = kvm86_bioscall(0x10, &tf); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + goto out; + } + mi = (struct modeinfoblock *)buf; + + ri = &sc->sc_ri; + ri->ri_flg = RI_CENTER; + ri->ri_depth = 8; + ri->ri_width = mi->XResolution; + ri->ri_height = mi->YResolution; + ri->ri_stride = mi->BytesPerScanLine; + + res = _i386_memio_map(I386_BUS_SPACE_MEM, mi->PhysBasePtr, + ri->ri_height * ri->ri_stride, + BUS_SPACE_MAP_LINEAR, &h); + if (res) { + printf("framebuffer mapping failed\n"); + goto out; + } + ri->ri_bits = bus_space_vaddr(I386_BUS_SPACE_MEM, h); + + printf(": fb %dx%d @%x\n", ri->ri_width, ri->ri_height, + mi->PhysBasePtr); +out: + kvm86_bios_delpage(0x2000, buf); + return; +} + +#if 0 +static void +vb8test(sc) + struct vesaraster8sc *sc; +{ + struct trapframe tf; + int res; + int savbufsiz, i; + char *errstr = 0; + struct rasops_info *ri = &sc->sc_ri; + u_long attr; + + memset(&tf, 0, sizeof(struct trapframe)); + tf.tf_eax = 0x4f04; /* function code */ + tf.tf_edx = 0x0000; /* query */ + tf.tf_ecx = 0x000f; + + res = kvm86_bioscall(0x10, &tf); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + return; + } + savbufsiz = roundup(tf.tf_ebx * 64, NBPG) / NBPG; + printf("savbuf: %d pg\n", savbufsiz); + + for (i = 0; i < savbufsiz; i++) + (void)kvm86_bios_addpage(0x3000 + i * 0x1000); + + memset(&tf, 0, sizeof(struct trapframe)); + tf.tf_eax = 0x4f04; /* function code */ + tf.tf_edx = 0x0001; /* save */ + tf.tf_ecx = 0x000f; /* all (but framebuffer) */ + tf.tf_es = 0; + tf.tf_ebx = 0x3000; /* buffer */ + + res = kvm86_bioscall(0x10, &tf); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + return; + } + + memset(&tf, 0, sizeof(struct trapframe)); + tf.tf_eax = 0x4f02; /* function code */ + tf.tf_ebx = sc->sc_mode | 0x4000; /* flat */ + tf.tf_ebx |= 0x8000; /* XXX no clear (save fonts in fb) */ + + res = kvm86_bioscall(0x10, &tf); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + return; + } + + if (rasops_init(ri, 20, 50)) { + errstr = "rasops_init"; + goto back; + } + + ri->ri_ops.allocattr(ri, 0, 0, 0, &attr); + ri->ri_ops.putchar(ri, 1, 1, 'X', attr); + ri->ri_ops.putchar(ri, 1, 2, 'Y', attr); + ri->ri_ops.putchar(ri, 1, 3, 'Z', attr); + + delay(5000000); + errstr = 0; +back: + memset(&tf, 0, sizeof(struct trapframe)); + tf.tf_eax = 0x4f04; /* function code */ + tf.tf_edx = 0x0002; /* restore */ + tf.tf_ecx = 0x000f; + tf.tf_es = 0; + tf.tf_ebx = 0x3000; /* buffer */ + + res = kvm86_bioscall(0x10, &tf); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + return; + } + + if (errstr) + printf("error: %s\n", errstr); +} +#endif diff --git a/sys/arch/i386/bios/vesa_text.c b/sys/arch/i386/bios/vesa_text.c new file mode 100644 index 000000000000..5145cc0c8e8d --- /dev/null +++ b/sys/arch/i386/bios/vesa_text.c @@ -0,0 +1,57 @@ +/* $NetBSD: vesa_text.c,v 1.1 2002/07/10 19:15:43 drochner Exp $ */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int vesatext_match(struct device *, struct cfdata *, void *); +static void vesatext_attach(struct device *, struct device *, void *); + +struct vesatextsc { + struct device sc_dev; + int *sc_modes; + int sc_nmodes; +}; + +struct cfattach vesatext_ca = { + sizeof(struct vesatextsc), vesatext_match, vesatext_attach +}; + +static int +vesatext_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct vesabiosdev_attach_args *vaa = aux; + + if (strcmp(vaa->vbaa_type, "text")) + return (0); + + return (1); +} + +static void +vesatext_attach(parent, dev, aux) + struct device *parent, *dev; + void *aux; +{ + struct vesatextsc *sc = (struct vesatextsc *)dev; + struct vesabiosdev_attach_args *vaa = aux; + int i; + + sc->sc_modes = malloc(vaa->vbaa_nmodes * sizeof(int), + M_DEVBUF, M_NOWAIT); + sc->sc_nmodes = vaa->vbaa_nmodes; + for (i = 0; i < vaa->vbaa_nmodes; i++) + sc->sc_modes[i] = vaa->vbaa_modes[i]; + + printf("\n"); +} diff --git a/sys/arch/i386/bios/vesabios.c b/sys/arch/i386/bios/vesabios.c index 7ac1f90e41f9..95d7353e0840 100644 --- a/sys/arch/i386/bios/vesabios.c +++ b/sys/arch/i386/bios/vesabios.c @@ -1,12 +1,16 @@ -/* $NetBSD: vesabios.c,v 1.1 2002/07/07 12:59:58 drochner Exp $ */ +/* $NetBSD: vesabios.c,v 1.2 2002/07/10 19:15:43 drochner Exp $ */ #include #include #include +#include #include #include #include +#include + +#include "opt_vesabios.h" struct vbeinfoblock { @@ -21,10 +25,20 @@ struct vbeinfoblock /* data area, in total max 512 bytes for VBE 2.0 */ } __attribute__ ((packed)); +#define FAR2FLATPTR(p) ((p & 0xffff) + ((p >> 12) & 0xffff0)) + static int vesabios_match(struct device *, struct cfdata *, void *); +static void vesabios_attach(struct device *, struct device *, void *); +static int vesabios_print(void *, const char *); + +static int vbegetinfo(struct vbeinfoblock **); +static void vbefreeinfo(struct vbeinfoblock *); +#ifdef VESABIOSVERBOSE +static const char *mm2txt(unsigned int); +#endif struct cfattach vesabios_ca = { - sizeof(struct device), vesabios_match, 0 + sizeof(struct device), vesabios_match, vesabios_attach }; static int @@ -39,21 +53,21 @@ vesabios_match(parent, match, aux) if (strcmp(vaa->vaa_busname, "vesabios") != 0) return (0); - return (0); /* XXX for now */ + return (1); } -int -vbeprobe() +static int +vbegetinfo(vip) + struct vbeinfoblock **vip; { unsigned char *buf; struct trapframe tf; - int res, ok = 0; - struct vbeinfoblock *vi; + int res, error; buf = kvm86_bios_addpage(0x2000); if (!buf) { - printf("vbeprobe: kvm86_bios_addpage(0x2000) failed\n"); - return (0); + printf("vbegetinfo: kvm86_bios_addpage(0x2000) failed\n"); + return (ENOMEM); } memcpy(buf, "VBE2", 4); @@ -64,22 +78,200 @@ vbeprobe() tf.tf_edi = 0x2000; /* buf ptr */ res = kvm86_bioscall(0x10, &tf); - - printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); - if (res || tf.tf_eax != 0x004f) - goto out; - - vi = (struct vbeinfoblock *)buf; - if (memcmp(vi->VbeSignature, "VESA", 4)) { - printf("VESA: bad sig\n"); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + error = ENXIO; goto out; } - printf("VESA: version: %x, cap: %x, oem @%x, modes @%x\n", - vi->VbeVersion, vi->Capabilities, vi->OemStringPtr, - vi->VideoModePtr); - ok = 1; + + 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 (ok); + return (error); +} + +static void +vbefreeinfo(vip) + struct vbeinfoblock *vip; +{ + + kvm86_bios_delpage(0x2000, vip); +} + +int +vbeprobe() +{ + struct vbeinfoblock *vi; + + if (vbegetinfo(&vi)) + return (0); + vbefreeinfo(vi); + return (1); +} + +#ifdef VESABIOSVERBOSE +static const char * +mm2txt(mm) + 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 + +static void +vesabios_attach(parent, dev, aux) + struct device * parent, *dev; + void *aux; +{ + struct vbeinfoblock *vi; + unsigned char *buf; + struct trapframe tf; + int res; + char name[256]; +#define MAXMODES 60 + u_int16_t modes[MAXMODES]; + int raster8modes[MAXMODES]; + int textmodes[MAXMODES]; + int nmodes, nraster8modes, ntextmodes, i; + u_int32_t modeptr; + struct modeinfoblock *mi; + struct vesabiosdev_attach_args vbaa; + + if (vbegetinfo(&vi)) + 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; + + nraster8modes = ntextmodes = 0; + + buf = kvm86_bios_addpage(0x2000); + if (!buf) { + printf("vesabios_attach: kvm86_bios_addpage(0x2000) failed\n"); + 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_es = 0; + tf.tf_edi = 0x2000; /* buf ptr */ + + res = kvm86_bioscall(0x10, &tf); + if (res || tf.tf_eax != 0x004f) { + printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); + break; + } + mi = (struct modeinfoblock *)buf; +#ifdef VESABIOSVERBOSE + printf("VESA mode %04x: attributes %04x", + 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) + && mi->BitsPerPixel == 8 + && mi->MemoryModel == 4) { + /* flat buffer, 8bpp packed pixel */ + raster8modes[nraster8modes++] = modes[i]; + } + } else { + /* text */ +#ifdef VESABIOSVERBOSE + printf(", text %dx%d\n", + mi->XResolution, mi->YResolution); +#endif + textmodes[ntextmodes++] = modes[i]; + } + } + kvm86_bios_delpage(0x2000, buf); + + if (nraster8modes) { + vbaa.vbaa_type = "raster8"; + vbaa.vbaa_modes = raster8modes; + vbaa.vbaa_nmodes = nraster8modes; + + config_found(dev, &vbaa, vesabios_print); + } + if (textmodes) { + vbaa.vbaa_type = "text"; + vbaa.vbaa_modes = textmodes; + vbaa.vbaa_nmodes = ntextmodes; + + config_found(dev, &vbaa, vesabios_print); + } +} + +static int +vesabios_print(aux, pnp) + void *aux; + const char *pnp; +{ + struct vesabiosdev_attach_args *vbaa = aux; + + if (pnp) + printf("%s at %s", vbaa->vbaa_type, pnp); + return (UNCONF); } diff --git a/sys/arch/i386/bios/vesabios.h b/sys/arch/i386/bios/vesabios.h index 09bff9feb828..8824bf4ae3c3 100644 --- a/sys/arch/i386/bios/vesabios.h +++ b/sys/arch/i386/bios/vesabios.h @@ -1,7 +1,13 @@ -/* $NetBSD: vesabios.h,v 1.1 2002/07/07 12:59:58 drochner Exp $ */ +/* $NetBSD: vesabios.h,v 1.2 2002/07/10 19:15:43 drochner Exp $ */ int vbeprobe __P((void)); struct vesabios_attach_args { char *vaa_busname; }; + +struct vesabiosdev_attach_args { + char *vbaa_type; + int *vbaa_modes; + int vbaa_nmodes; +}; diff --git a/sys/arch/i386/bios/vesabiosreg.h b/sys/arch/i386/bios/vesabiosreg.h new file mode 100644 index 000000000000..3b36b65f087c --- /dev/null +++ b/sys/arch/i386/bios/vesabiosreg.h @@ -0,0 +1,27 @@ +/* $NetBSD: vesabiosreg.h,v 1.1 2002/07/10 19:15:43 drochner Exp $ */ + +struct modeinfoblock { + /* Mandatory information for all VBE revisions */ + u_int16_t ModeAttributes; + u_int8_t WinAAttributes, WinBAttributes; + u_int16_t WinGranularity, WinSize, WinASegment, WinBSegment; + u_int32_t WinFuncPtr; + u_int16_t BytesPerScanLine; + /* Mandatory information for VBE 1.2 and above */ + u_int16_t XResolution, YResolution; + u_int8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel; + u_int8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages; + u_int8_t Reserved1; + /* Direct Color fields + (required for direct/6 and YUV/7 memory models) */ + u_int8_t RedMaskSize, RedFieldPosition; + u_int8_t GreenMaskSize, GreenFieldPosition; + u_int8_t BlueMaskSize, BlueFieldPosition; + u_int8_t RsvdMaskSize, RsvdFieldPosition; + u_int8_t DirectColorModeInfo; + /* Mandatory information for VBE 2.0 and above */ + u_int32_t PhysBasePtr; + u_int32_t OffScreenMemOffset; + u_int16_t OffScreenMemSize; + u_int8_t Reserved2[206]; +} __attribute__ ((packed)); diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index 23ec07e40628..3fca1f9bd695 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $NetBSD: files.i386,v 1.210 2002/07/07 13:03:47 drochner Exp $ +# $NetBSD: files.i386,v 1.211 2002/07/10 19:15:43 drochner Exp $ # # new style config file for i386 architecture # @@ -451,6 +451,17 @@ file arch/i386/acpi/vald_acpi.c vald_acpi attach spic at acpi with spic_acpi file arch/i386/acpi/spic_acpi.c spic_acpi -device vesabios +device vesabios {} attach vesabios at mainbus file arch/i386/bios/vesabios.c vesabios needs-flag +defflag opt_vesabios.h VESABIOSVERBOSE + +include "dev/rasops/files.rasops" + +device vesarasterviii: rasops8 +attach vesarasterviii at vesabios +file arch/i386/bios/vesa_raster8.c vesarasterviii + +device vesatext +attach vesatext at vesabios +file arch/i386/bios/vesa_text.c vesatext