changeset 0:7b21e0889b05

Initial miniport commit; nearly identical to its sibling in the Open Watcom source tree.
author Michal Necasek <mnecasek@yahoo.com>
date Thu, 17 Jul 2014 23:22:50 +0200
parents
children 6d1e2fb6763b
files boxv.c boxv.h boxv_io.h disk1 makefile oemsetup.inf readme.txt videomp.c videomp.h videomp.rc vidmini.inf vidmpdat.c
diffstat 12 files changed, 2191 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/boxv.c	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,431 @@
+#include "boxv.h"
+#include "boxv_io.h"
+
+/*-------------- VGA Specific ----------------*/
+
+/* VGA I/O port addresses. */
+#define VGA_CRTC            0x3D4   /* Color only! */
+#define VGA_ATTR_W          0x3C0
+#define VGA_ATTR_R          0x3C1
+#define VGA_MISC_OUT_W      0x3C2
+#define VGA_SEQUENCER       0x3C4
+#define VGA_SEQUENCER_DATA  0x3C5
+#define VGA_PIXEL_MASK      0x3C6
+#define VGA_DAC_W_INDEX     0x3C8
+#define VGA_DAC_DATA        0x3C9
+#define VGA_MISC_OUT_R      0x3CC
+#define VGA_GRAPH_CNTL      0x3CE
+#define VGA_GRAPH_CNTL_DATA 0x3CF
+#define VGA_STAT_ADDR       0x3DA   /* Color only! */
+
+/* VGA Attribute Controller register indexes. */
+#define VGA_AR_MODE         0x10
+#define VGA_AR_OVERSCAN     0x11
+#define VGA_AR_PLANE_EN     0x12
+#define VGA_AR_PIX_PAN      0x13
+#define VGA_AR_COLOR_SEL    0x14
+
+/* VGA Graphics Controller register indexes. */
+#define VGA_GR_SET_RESET    0x00
+#define VGA_GR_DATA_ROTATE  0x03
+#define VGA_GR_READ_MAP_SEL 0x04
+#define VGA_GR_MODE         0x05
+#define VGA_GR_MISC         0x06
+#define VGA_GR_BIT_MASK     0x08
+
+/* VGA Sequencer register indexes. */
+#define VGA_SR_RESET        0x00
+#define VGA_SR_CLK_MODE     0x01
+#define VGA_SR_PLANE_MASK   0x02
+#define VGA_SR_MEM_MODE     0x04
+
+/* Sequencer constants. */
+#define VGA_SR0_NORESET     0x03
+#define VGA_SR0_RESET       0x00
+#define VGA_SR1_BLANK       0x20
+
+/* VGA CRTC register indexes. */
+#define VGA_CR_HORZ_TOTAL   0x00
+#define VGA_CR_CUR_START    0x0A
+#define VGA_CR_CUR_END      0x0B
+#define VGA_CR_START_HI     0x0C
+#define VGA_CR_START_LO     0x0D
+#define VGA_CR_CUR_POS_HI   0x0E
+#define VGA_CR_CUR_POS_LO   0x0F
+#define VGA_CR_VSYNC_START  0x10
+#define VGA_CR_VSYNC_END    0x11
+
+/* VGA Input Status Register 1 constants. */
+#define VGA_STAT_VSYNC      0x08
+
+/*------------ End VGA Specific --------------*/
+
+/*------------- bochs Specific ---------------*/
+
+#define VBE_DISPI_BANK_ADDRESS          0xA0000
+#define VBE_DISPI_BANK_SIZE_KB          64
+
+#define VBE_DISPI_MAX_XRES              1024
+#define VBE_DISPI_MAX_YRES              768
+
+#define VBE_DISPI_IOPORT_INDEX          0x01CE
+#define VBE_DISPI_IOPORT_DATA           0x01CF
+
+#define VBE_DISPI_INDEX_ID              0x0
+#define VBE_DISPI_INDEX_XRES            0x1
+#define VBE_DISPI_INDEX_YRES            0x2
+#define VBE_DISPI_INDEX_BPP             0x3
+#define VBE_DISPI_INDEX_ENABLE          0x4
+#define VBE_DISPI_INDEX_BANK            0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
+#define VBE_DISPI_INDEX_X_OFFSET        0x8
+#define VBE_DISPI_INDEX_Y_OFFSET        0x9
+
+#define VBE_DISPI_ID0                   0xB0C0
+#define VBE_DISPI_ID1                   0xB0C1
+#define VBE_DISPI_ID2                   0xB0C2
+#define VBE_DISPI_ID3                   0xB0C3
+#define VBE_DISPI_ID4                   0xB0C4
+
+#define VBE_DISPI_DISABLED              0x00
+#define VBE_DISPI_ENABLED               0x01
+#define VBE_DISPI_GETCAPS               0x02
+#define VBE_DISPI_8BIT_DAC              0x20
+#define VBE_DISPI_LFB_ENABLED           0x40
+#define VBE_DISPI_NOCLEARMEM            0x80
+
+#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
+
+/*------------ End bochs Specific -------------*/
+
+
+typedef unsigned char   v_byte;
+typedef unsigned short  v_word;
+
+/* A structure describing the contents of VGA registers for a mode set. */
+typedef struct {
+    v_byte          misc;           /* Miscellaneous register. */
+    v_byte          seq[5];         /* Sequencer registers. */
+    v_byte          crtc[25];       /* CRTC registers. */
+    v_byte          gctl[9];        /* Graphics controller registers. */
+    v_byte          atr[21];        /* Attribute registers. */        
+} v_vgaregs;
+
+/* A structure fully describing a graphics or text mode. */
+typedef struct {
+    int             mode_no;        /* Internal mode number. */
+    int             xres;           /* Horizontal (X) resolution. */
+    int             yres;           /* Vertical (Y) resolution. */
+    int             bpp;            /* Bits per pixel. */
+    int             ext;            /* Non-zero for extended modes. */
+    v_vgaregs      *vgaregs;       /* Contents of VGA registers. */ 
+} v_mode;
+
+v_vgaregs       vga_regs_ext = {
+    0xe3, { 0x01, 0x01, 0x0f, 0x00, 0x0a }, {
+    0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
+    0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xea, 0x0c, 0xdf, 0x28, 0x4f, 0xe7, 0x04, 0xe3, 0xff }, {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff }, {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x41, 0x00, 0x0f, 0x00, 0x00 }
+};
+
+v_mode          mode_640_480_8 = {
+    0x101, 640, 480, 8, 1, &vga_regs_ext
+};
+
+v_mode          mode_800_600_8 = {
+    0x103, 800, 600, 8, 1, &vga_regs_ext
+};
+
+v_mode          mode_1024_768_8 = {
+    0x105, 1024, 768, 8, 1, &vga_regs_ext
+};
+
+v_mode          mode_640_480_16 = {
+    0x111, 640, 480, 16, 1, &vga_regs_ext
+};
+
+v_mode          mode_800_600_16 = {
+    0x114, 800, 600, 16, 1, &vga_regs_ext
+};
+
+v_mode          mode_1024_768_16 = {
+    0x117, 1024, 768, 16, 1, &vga_regs_ext
+};
+
+v_mode          mode_640_480_32 = {
+    0x129, 640, 480, 32, 1, &vga_regs_ext
+};
+
+v_mode          mode_800_600_32 = {
+    0x12E, 800, 600, 32, 1, &vga_regs_ext
+};
+
+v_mode          mode_1024_768_32 = {
+    0x138, 1024, 768, 32, 1, &vga_regs_ext
+};
+
+v_mode          *mode_list[] = {
+    &mode_640_480_8,
+    &mode_800_600_8,
+    &mode_1024_768_8,
+    &mode_640_480_16,
+    &mode_800_600_16,
+    &mode_1024_768_16,
+    &mode_640_480_32,
+    &mode_800_600_32,
+    &mode_1024_768_32,
+    NULL
+};
+
+/* Write a single value to an indexed register at a specified 
+ * index. Suitable for the CRTC or graphics controller.
+ */
+static void vid_wridx( void *cx, int idx_reg, int idx, v_byte data )
+{
+    vid_outw( cx, idx_reg, idx | (data << 8) );
+}
+
+/* Program a sequence of bytes into an indexed register, starting
+ * at index 0. Suitable for loading the CRTC or graphics controller.
+ */
+static void vid_wridx_s( void *cx, int idx_reg, int count, v_byte *data )
+{
+    int     idx;
+
+    for( idx = 0; idx < count; ++idx )
+        vid_wridx( cx, idx_reg, idx, data[idx] );   /* Write index/data. */
+}
+
+/* Program a sequence of bytes into the attribute controller, starting 
+ * at index 0. Note: This function may not be interrupted by code which
+ * also accesses the attribute controller.
+ */
+static void vid_wratc_s( void *cx, int count, v_byte *data )
+{
+    int     idx;
+
+    vid_inb( cx, VGA_STAT_ADDR );               /* Reset flip-flop. */
+    for( idx = 0; idx < count; ++idx ) {
+        vid_outb( cx, VGA_ATTR_W, idx );        /* Write index. */
+        vid_outb( cx, VGA_ATTR_W, data[idx] );  /* Write data. */
+    }
+}
+
+v_mode *find_mode( int mode_no )
+{
+    v_mode      **p_mode;
+    v_mode      *mode;
+
+    mode = NULL;
+    for( p_mode = mode_list; *p_mode; ++p_mode ) {
+        if( (*p_mode)->mode_no == mode_no ) {
+            mode = *p_mode;
+            break;
+        }
+    }
+    return( mode );
+}
+
+/* Enumerate all available modes. Runs a callback for each mode; if the
+ * callback returns zero, the enumeration is terminated.
+ */
+void BOXV_mode_enumerate( void *cx, int (cb)( void *cx, BOXV_mode_t *mode ) )
+{
+    BOXV_mode_t     mode_info;
+    v_mode          **p_mode;
+    v_mode          *mode;
+
+    for( p_mode = mode_list; *p_mode; ++p_mode ) {
+        mode = *p_mode;
+        mode_info.mode_no = mode->mode_no;
+        mode_info.xres    = mode->xres;
+        mode_info.yres    = mode->yres;
+        mode_info.bpp     = mode->bpp;
+        if( !cb( cx, &mode_info ) )
+            break;
+    }
+}
+
+/* Set an extended non-VGA mode with given parameters. 8bpp and higher only.
+ * Returns non-zero value on failure.
+ */
+int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_yres )
+{
+    /* Do basic parameter validation. */
+    if( v_xres < xres || v_yres < yres )
+        return( -1 );
+
+    /* Put the hardware into a state where the mode can be safely set. */
+    vid_inb( cx, VGA_STAT_ADDR );                   /* Reset flip-flop. */
+    vid_outb( cx, VGA_ATTR_W, 0 );                  /* Disable palette. */
+    vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR_RESET );
+
+    /* Disable the extended display registers. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED );
+
+    /* Program the extended non-VGA registers. */
+
+    /* Set X resoultion. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, xres );
+    /* Set Y resoultion. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, yres );
+    /* Set bits per pixel. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, bpp );
+    /* Set the virtual resolution. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, v_xres );
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_HEIGHT );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, v_yres );
+    /* Reset the current bank. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BANK );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 );
+    /* Set the X and Y display offset to 0. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_X_OFFSET );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 );
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_Y_OFFSET );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 );
+    /* Enable the extended display registers. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC );
+
+    /* Re-enable the sequencer. */
+    vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR0_NORESET );
+
+    /* Re-enable palette. */
+    vid_outb( cx, VGA_ATTR_W, 0x20 );               
+
+    return( 0 );
+}
+
+/* Set the requested mode (text or graphics). 
+ * Returns non-zero value on failure.
+ */
+int BOXV_mode_set( void *cx, int mode_no )
+{
+    v_mode          *mode;
+    v_vgaregs       *vgarg;
+
+    mode = find_mode( mode_no );
+    if( !mode )
+        return( -1 );
+
+    /* Put the hardware into a state where the mode can be safely set. */
+    vid_inb( cx, VGA_STAT_ADDR );                   /* Reset flip-flop. */
+    vid_outb( cx, VGA_ATTR_W, 0 );                  /* Disable palette. */
+    vid_wridx( cx, VGA_CRTC, VGA_CR_VSYNC_END, 0 ); /* Unlock CR0-CR7. */
+    vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR_RESET );
+
+    /* Disable the extended display registers. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED );
+
+    /* Optionally program the extended non-VGA registers. */
+    if( mode->ext ) {
+        /* Set X resoultion. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, mode->xres );
+        /* Set Y resoultion. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, mode->yres );
+        /* Set bits per pixel. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, mode->bpp );
+        /* Set the virtual resolution. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, mode->xres );
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_HEIGHT );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, mode->yres );
+        /* Reset the current bank. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BANK );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 );
+        /* Set the X and Y display offset to 0. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_X_OFFSET );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 );
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_Y_OFFSET );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 );
+        /* Enable the extended display registers. */
+        vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE );
+        vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC );
+    }
+
+    vgarg = mode->vgaregs;
+
+    /* Program misc. output register. */
+    vid_outb( cx, VGA_MISC_OUT_W, vgarg->misc );
+
+    /* Program the sequencer. */
+    vid_wridx_s( cx, VGA_SEQUENCER, sizeof( vgarg->seq ), vgarg->seq );
+    vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR0_NORESET );
+
+    /* Program the CRTC and graphics controller. */
+    vid_wridx_s( cx, VGA_CRTC, sizeof( vgarg->crtc ), vgarg->crtc );
+    vid_wridx_s( cx, VGA_GRAPH_CNTL, sizeof( vgarg->gctl ), vgarg->gctl );
+
+    /* Finally program the attribute controller. */
+    vid_wratc_s( cx, sizeof( vgarg->atr ), vgarg->atr );
+    vid_outb( cx, VGA_ATTR_W, 0x20 );               /* Re-enable palette. */
+
+    return( 0 );
+}
+
+/* Program the DAC. Each of the 'count' entries is 4 bytes in size,
+ * red/green/blue/unused.
+ * Returns non-zero on failure.
+ */
+int BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal )
+{
+    v_byte      *prgbu = pal;
+
+    /* Basic argument validation. */
+    if( start + count > 256 )
+        return( -1 );
+
+    /* Write the starting index. */
+    vid_outb( cx, VGA_DAC_W_INDEX, start );
+    /* Load the RGB data. */
+    while( count-- ) {
+        vid_outb( cx, VGA_DAC_DATA, *prgbu++ );
+        vid_outb( cx, VGA_DAC_DATA, *prgbu++ );
+        vid_outb( cx, VGA_DAC_DATA, *prgbu++ );
+        ++prgbu;
+    }
+    return( 0 );
+}
+
+/* Detect the presence of a supported adapter and amount of installed
+ * video memory. Returns zero if not found.
+ */
+int BOXV_detect( void *cx, unsigned long *vram_size )
+{
+    v_word      boxv_id;
+
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID );
+    boxv_id = vid_inw( cx, VBE_DISPI_IOPORT_DATA );
+    if( vram_size ) {
+        *vram_size = vid_ind( cx, VBE_DISPI_IOPORT_DATA );
+    }
+    if( boxv_id >= VBE_DISPI_ID0 && boxv_id <= VBE_DISPI_ID4 )
+        return( boxv_id );
+    else
+        return( 0 );
+}
+
+/* Disable extended mode and place the hardware into a VGA compatible state.
+ * Returns non-zero on failure.
+ */
+int BOXV_ext_disable( void *cx )
+{
+    /* Disable the extended display registers. */
+    vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE );
+    vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED );
+    return( 0 );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/boxv.h	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,24 @@
+/*
+ * Public interface to the boxv library.
+ */
+
+/* PCI vendor and device IDs. */
+#define BOXV_PCI_VEN    0x80EE
+#define BOXV_PCI_DEV    0xBEEF
+
+/* A structure describing mode information. Note: The mode numbers
+ * usually match VBE, but this should not be relied upon.
+ */
+typedef struct {
+    int     mode_no;        /* Mode number */
+    int     xres;           /* Horizontal resolution */
+    int     yres;           /* Vertical resolution */
+    int     bpp;            /* Color depth */
+} BOXV_mode_t;
+
+extern void BOXV_mode_enumerate( void *cx, int (cb)( void *cx, BOXV_mode_t *mode ) );
+extern int  BOXV_detect( void *cx, unsigned long *vram_size );
+extern int  BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_yres );
+extern int  BOXV_mode_set( void *cx, int mode_no );
+extern int  BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal );
+extern int  BOXV_ext_disable( void *cx );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/boxv_io.h	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,44 @@
+
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include "videomp.h"
+
+/* In this case, vid_in/out cannot be defined as macros because NT uses
+ * a pretty funky interface for I/O port access.
+ */
+
+static void vid_outb( void *cx, unsigned port, unsigned val )
+{
+    PHW_DEV_EXT     pExt = cx;
+    
+    VideoPortWritePortUchar( pExt->IOAddrVGA + port, val );
+}
+
+static void vid_outw( void *cx, unsigned port, unsigned val )
+{
+    PHW_DEV_EXT     pExt = cx;
+    
+    VideoPortWritePortUshort( (PUSHORT)(pExt->IOAddrVGA + port), val );
+}
+
+static unsigned vid_inb( void *cx, unsigned port )
+{
+    PHW_DEV_EXT     pExt = cx;
+
+    return( VideoPortReadPortUchar( pExt->IOAddrVGA + port ) );
+}
+
+static unsigned vid_inw( void *cx, unsigned port )
+{
+    PHW_DEV_EXT     pExt = cx;
+
+    return( VideoPortReadPortUshort( (PUSHORT)(pExt->IOAddrVGA + port) ) );
+}
+
+static unsigned vid_ind( void *cx, unsigned port )
+{
+    PHW_DEV_EXT     pExt = cx;
+
+    return( VideoPortReadPortUlong( (PULONG)(pExt->IOAddrVGA + port) ) );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/disk1	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,1 @@
+fdsjk
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,61 @@
+CC = wcc386
+RC = wrc
+CFLAGS = -q -s -ecd -wx
+RCFLAGS = -q -r -zm
+INCS = -I"$(%WATCOM)/h/nt/ddk"
+LIBS = $(%WATCOM)/lib386/nt/ddk
+
+# Debug flag - note that the video port in Windows NT 3.x only exports
+# VideoDebugPort in checked builds!
+#CFLAGS += -DDBG
+
+CFLAGS += -d1 -hc
+
+OBJS = videomp.obj vidmpdat.obj boxv.obj
+
+.c.obj : .autodepend
+    $(CC) $(CFLAGS) $(INCS) $<
+
+boxvideo.sys : $(OBJS) $(__MAKEFILES__) videomp.res
+    wlink op quiet, map name $@ format windows nt runtime native=1.0 &
+      debug codeview op symf, cvpack &
+      option start='_DriverEntry@8' &
+      option offset=0x10000, checksum, osversion=1.0, version=1.0 &
+      option stack=0x100000, heapsize=0x100000 &
+      segment class CODE nonpageable, class DATA nonpageable &
+      file { $OBJS } libpath $(LIBS) lib videoprt resource videomp.res
+
+# Normally we would like to use the following:
+#      option alignment=0x20, objalign=0x20
+# but that causes the driver image to fail loading on old NT releases;
+# the driver is small enough that it's not worth the trouble
+
+videomp.res : videomp.rc
+    $(RC) $(RCFLAGS) $(INCS) $<
+
+# Create a 1.44MB distribution floppy image.
+# NB: The mkimage tool is not supplied.
+videomp.img : boxvideo.sys disk1 readme.txt oemsetup.inf vidmini.inf
+    if not exist dist mkdir dist
+    cp disk1        dist
+    cp boxvideo.sys dist
+    cp boxvideo.sym dist
+    cp oemsetup.inf dist
+    cp vidmini.inf  dist
+    cp readme.txt   dist
+    mkimage -l VIDEOMP -o videomp.img dist
+    
+clean : .symbolic
+    rm -f *.obj
+    rm -f *.sys
+    rm -f *.sym
+    rm -f *.res
+    rm -f *.map
+    rm -f videomp.img
+    rm -f dist/disk1
+    rm -f dist/boxvideo.sys
+    rm -f dist/boxvideo.sym
+    rm -f dist/oemsetup.inf
+    rm -f dist/vidmini.inf
+    rm -f dist/readme.txt
+    if exist dist rmdir dist
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/oemsetup.inf	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,577 @@
+;-----------------------------------------------------------------------
+; OPTION TYPE
+; -----------
+; This identifies the Option type we are dealing with.  The different
+; possible types are:
+;
+; COMPUTER, DISPLAY, MOUSE, KEYBOARD, LAYOUT, SCSI, PRINTER, ...
+;-----------------------------------------------------------------------
+
+[Identification]
+    OptionType = VIDEO
+
+;-----------------------------------------------------------------------
+; LANGUAGES SUPPORTED
+; -------------------
+;
+; The languages supported by the OEM INF, For every language supported
+; we need to have a separate text section for every displayable text
+; section.
+;
+;-----------------------------------------------------------------------
+
+[LanguagesSupported]
+    ENG
+
+;-----------------------------------------------------------------------
+; OPTION LIST
+; -----------
+; This section lists the OEM Option key names.  These keys are locale
+; independent and used to represent the option in a locale independent
+; manner.
+;
+;-----------------------------------------------------------------------
+
+;
+; Option list order:
+; Option = Miniport driver, BitsPerPel, XResolution, YResolution, VRefresh, Interlaced
+;
+; If you don't want to create a VRefresh or Interlaced value under the service
+; parameters then use the value ""
+
+[Options]
+    "VirtualBox 640x480x8"             = boxv,      8,  640, 480, 60, 0
+    "VirtualBox 800x600x8"             = boxv,      8,  800, 600, 60, 0
+    "VirtualBox 1024x768x8"            = boxv,      8, 1024, 768, 60, 0
+    "VirtualBox 1152x864x8"            = boxv,      8, 1152, 864, 60, 0
+    "VirtualBox 640x480x16"            = boxv,     16,  640, 480, 60, 0
+    "VirtualBox 800x600x16"            = boxv,     16,  800, 600, 60, 0
+    "VirtualBox 1024x768x16"           = boxv,     16, 1024, 768, 60, 0
+    "VirtualBox 1152x864x16"           = boxv,     16, 1152, 864, 60, 0
+    "VirtualBox 640x480x32"            = boxv,     32,  640, 480, 60, 0
+    "VirtualBox 800x600x32"            = boxv,     32,  800, 600, 60, 0
+    "VirtualBox 1024x768x32"           = boxv,     32, 1024, 768, 60, 0
+    "VirtualBox 1152x864x32"           = boxv,     32, 1152, 864, 60, 0
+
+;
+; This maps detected options into the options we support
+;
+; Format: DetectedOption = MappedOption
+;
+
+[MapOfOptions]
+    "VirtualBox 640x480x8"             = "VirtualBox 640x480x8"
+    "VirtualBox 800x600x8"             = "VirtualBox 800x600x8"
+    "VirtualBox 1024x768x8"            = "VirtualBox 1024x768x8"
+    "VirtualBox 640x480x16"            = "VirtualBox 640x480x16"
+    "VirtualBox 800x600x16"            = "VirtualBox 800x600x16"
+    "VirtualBox 1024x768x16"           = "VirtualBox 1024x768x16"
+    "VirtualBox 640x480x32"            = "VirtualBox 640x480x32"
+    "VirtualBox 800x600x32"            = "VirtualBox 800x600x32"
+    "VirtualBox 1024x768x32"           = "VirtualBox 1024x768x32"
+
+;
+; Order of the information:
+;
+; Port driver = Type, Group, ErrorControl, Tag, InstalledDisplay, VgaCompatible, EventMessageFile, TypesSupported
+;
+
+[MiniportDrivers]
+    boxv      = !SERVICE_KERNEL_DRIVER, Video, !SERVICE_ERROR_IGNORE, 12,  {framebuf}, 0 , %SystemRoot%\System32\IoLogMsg.dll , 7
+
+;-----------------------------------------------------------------------
+; OPTION TEXT SECTION
+; -------------------
+; These are text strings used to identify the option to the user.  There
+; are separate sections for each language supported.  The format of the
+; section name is "OptionsText" concatenated with the Language represented
+; by the section.
+;
+;-----------------------------------------------------------------------
+
+[OptionsTextENG]
+    "VirtualBox 640x480x8"     =  "VirtualBox 640x480, 256 colors"
+    "VirtualBox 800x600x8"     =  "VirtualBox 800x600, 256 colors"
+    "VirtualBox 1024x768x8"    =  "VirtualBox 1024x768, 256 colors"
+    "VirtualBox 1152x864x8"    =  "VirtualBox 1152x864, 256 colors"
+    "VirtualBox 640x480x16"    =  "VirtualBox 640x480, 64K colors"
+    "VirtualBox 800x600x16"    =  "VirtualBox 800x600, 64K colors"
+    "VirtualBox 1024x768x16"   =  "VirtualBox 1024x768, 64K colors"
+    "VirtualBox 1152x864x16"   =  "VirtualBox 1152x864, 64K colors"
+    "VirtualBox 640x480x32"    =  "VirtualBox 640x480, True Color"
+    "VirtualBox 800x600x32"    =  "VirtualBox 800x600, True Color"
+    "VirtualBox 1024x768x32"   =  "VirtualBox 1024x768, True Color"
+    "VirtualBox 1152x864x32"   =  "VirtualBox 1152x864, True Color"
+
+;---------------------------------------------------------------------------
+; 1. Identify
+;
+; DESCRIPTION:   To verify that this INF deals with the same type of options
+;                as we are choosing currently.
+;
+; INPUT:         None
+;
+; OUTPUT:        $($R0): STATUS: STATUS_SUCCESSFUL
+;                $($R1): Option Type (COMPUTER ...)
+;                $($R2): Diskette description
+;---------------------------------------------------------------------------
+
+[Identify]
+    ;
+    ;
+    read-syms Identification
+
+    set Status     = STATUS_SUCCESSFUL
+    set Identifier = $(OptionType)
+    set Media      = #("Source Media Descriptions", 1, 1)
+
+    Return $(Status) $(Identifier) $(Media)
+
+
+
+;------------------------------------------------------------------------
+; 2. ReturnOptions:
+;
+; DESCRIPTION:   To return the option list supported by this INF and the
+;                localised text list representing the options.
+;
+;
+; INPUT:         $($0):  Language used. ( ENG | FRN | ... )
+;
+; OUTPUT:        $($R0): STATUS: STATUS_SUCCESSFUL |
+;                                STATUS_NOLANGUAGE
+;                                STATUS_FAILED
+;
+;                $($R1): Option List
+;                $($R2): Option Text List
+;------------------------------------------------------------------------
+
+[ReturnOptions]
+    ;
+    ;
+    set Status        = STATUS_FAILED
+    set OptionList     = {}
+    set OptionTextList = {}
+
+    ;
+    ; Check if the language requested is supported
+    ;
+    set LanguageList = ^(LanguagesSupported, 1)
+    Ifcontains(i) $($0) in $(LanguageList)
+        goto returnoptions
+    else
+        set Status = STATUS_NOLANGUAGE
+        goto finish_ReturnOptions
+    endif
+
+    ;
+    ; form a list of all the options and another of the text representing
+    ;
+
+returnoptions = +
+    set OptionList     = ^(Options, 0)
+    set OptionTextList = ^(OptionsText$($0), 1)
+    set Status         = STATUS_SUCCESSFUL
+
+finish_ReturnOptions = +
+    Return $(Status) $(OptionList) $(OptionTextList)
+
+
+;---------------------------------------------------------------------------
+; MapToSupportedOption
+;
+; DESCRIPTION:   To map a hardware detected option to the NT Supported
+;                option which represents it.
+;
+; INPUT:         $($0): Option
+;
+; OUTPUT:        $($R0): STATUS: STATUS_SUCCESSFUL
+;                $($R1): Mapped Option
+;
+;---------------------------------------------------------------------------
+
+[MapToSupportedOption]
+    ;
+    set Status = STATUS_FAILED
+    set MappedOption = $($0)
+
+    ;
+    ; If the option is one we can support using one of our standard options
+    ; then map it to the standard option else pass it back as such to be
+    ; an OEM installed option
+    ;
+
+    set OptionList = ^(MapOfOptions, 0)
+    ifcontains $($0) in $(OptionList)
+        set MappedOption = #(MapOfOptions, $($0), 1)
+    endif
+
+    set Status = STATUS_SUCCESSFUL
+    Return $(Status) $(MappedOption)
+
+
+
+[ServicesEntry]
+    CurrentEntry = "" ? $(!LIBHANDLE) GetDevicemapValue Video \Device\Video0
+
+;
+; InstallOption:
+;
+; FUNCTION:  To copy files representing Options
+;            To configure the installed option
+;            To update the registry for the installed option
+;
+; INPUT:     $($0):  Language to use
+;            $($1):  OptionID to install
+;            $($2):  SourceDirectory
+;            $($3):  AddCopy  (YES | NO)
+;            $($4):  DoCopy   (YES | NO)
+;            $($5):  DoConfig (YES | NO)
+;
+; OUTPUT:    $($R0): STATUS: STATUS_SUCCESSFUL |
+;                            STATUS_NOLANGUAGE |
+;                            STATUS_USERCANCEL |
+;                            STATUS_FAILED
+;
+
+[InstallOption]
+
+    ;
+    ; Set default values for
+    ;
+    set Status   = STATUS_FAILED
+    set DrivesToFree = {}
+
+    ;
+    ; extract parameters
+    ;
+    set Option   = $($1)
+    set SrcDir   = $($2)
+    set AddCopy  = $($3)
+    set DoCopy   = $($4)
+    set DoConfig = $($5)
+
+    ;
+    ; Check if the language requested is supported
+    ;
+    set LanguageList = ^(LanguagesSupported, 1)
+    Ifcontains(i) $($0) in $(LanguageList)
+    else
+        set Status = STATUS_NOLANGUAGE
+        goto finish_InstallOption
+    endif
+    read-syms Strings$($0)
+
+    ;
+    ; check to see if Option is supported.
+    ;
+
+    set OptionList = ^(Options, 0)
+    ifcontains $(Option) in $(OptionList)
+    else
+        goto finish_InstallOption
+    endif
+    set OptionList = ""
+
+    ;
+    ; Option has been defined already
+    ;
+
+    set MiniportDriver    = #(Options, $(Option), 1)
+    set BitsPerPel        = #(Options, $(Option), 2)
+    set XResolution       = #(Options, $(Option), 3)
+    set YResolution       = #(Options, $(Option), 4)
+    set VRefresh          = #(Options, $(Option), 5)
+    set Interlaced        = #(Options, $(Option), 6)
+
+    set Type              = $(#(MiniportDrivers, $(MiniportDriver), 1))
+    set Group             =   #(MiniportDrivers, $(MiniportDriver), 2)
+    set ErrorControl      = $(#(MiniportDrivers, $(MiniportDriver), 3))
+    set Tag               =   #(MiniportDrivers, $(MiniportDriver), 4)
+    set InstalledDisplays =   #(MiniportDrivers, $(MiniportDriver), 5)
+    set VgaCompatible     =   #(MiniportDrivers, $(MiniportDriver), 6)
+    set EventMessageFile  =   #(MiniportDrivers, $(MiniportDriver), 7)
+    set TypesSupported    =   #(MiniportDrivers, $(MiniportDriver), 8)
+
+
+    read-syms ServicesEntry
+    detect    ServicesEntry
+
+installtheoption = +
+
+    ;
+    ; Code to add files to copy list
+    ;
+
+    ifstr(i) $(AddCopy) == "YES"
+        set DoActualCopy = NO
+        set FileToCheck = #(Files-DisplayMiniportDrivers, $(MiniportDriver), 2)
+        LibraryProcedure STATUS,$(!LIBHANDLE),CheckFileExistance $(!STF_WINDOWSSYSPATH)"\drivers\"$(FileToCheck)
+        ifstr(i) $(STATUS) == NO
+            set DoActualCopy = YES
+            goto addfiles
+        endif
+        ForListDo $(InstalledDisplays)
+            set FileToCheck = #(Files-DisplayDLLs, $($), 2)
+            LibraryProcedure STATUS,$(!LIBHANDLE),CheckFileExistance $(!STF_WINDOWSSYSPATH)"\"$(FileToCheck)
+            ifstr(i) $(STATUS) == NO
+                set DoActualCopy = YES
+            endif
+        EndForListDo
+
+addfiles = +
+        ifstr(i) $(DoActualCopy) == NO
+            shell "subroutn.inf" DriversExist $($0) $(String1)
+            ifint $($ShellCode) != $(!SHELL_CODE_OK)
+                Debug-Output "VIDEO.INF: shelling DriversExist failed"
+                goto finish_InstallOption
+            endif
+
+            ifstr(i) $($R0) == STATUS_CURRENT
+            else-ifstr(i) $($R0) == STATUS_NEW
+                set DoActualCopy = YES
+            else-ifstr(i) $($R0) == STATUS_USERCANCEL
+                Debug-Output "VIDEO.INF: User cancelled video installation"
+                goto finish_InstallOption
+            else
+                Debug-Output "VIDEO.INF: Error reported in DriversExist routine in SUBROUTN.INF"
+                goto finish_InstallOption
+            endif
+        endif
+
+        ifstr(i) $(DoActualCopy) == YES
+
+            shell "subroutn.inf" DoAskSourceEx $(SrcDir) $(String2)
+            ifint $($ShellCode) != $(!SHELL_CODE_OK)
+                Debug-Output "Video.INF: shelling DoAskSourceEx failed"
+                goto finish_InstallOption
+            endif
+
+            ifstr(i) $($R0) == STATUS_SUCCESSFUL
+                set SrcDir = $($R1)
+                ifstr(i) $($R2) != ""
+                    set DrivesToFree = >($(DrivesToFree), $($R2))
+                endif
+            else
+                Debug-Output "Video.inf: User cancelled asking source."
+                goto finish_InstallOption
+            endif
+
+            install Install-AddCopyOption
+            ifstr(i) $(STF_INSTALL_OUTCOME) != "STF_SUCCESS"
+                Debug-Output "Adding video files to copy list failed"
+                goto finish_InstallOption
+            endif
+        else
+            set DoCopy = NO
+        endif
+    endif
+
+    ifstr(i) $(DoCopy) == "YES"
+        read-syms ProgressCopy$($0)
+        install Install-DoCopyOption
+        ifstr(i) $(STF_INSTALL_OUTCOME) == "STF_FAILURE"
+            Debug-Output "Copying files failed"
+            goto finish_InstallOption
+        else-ifstr(i) $(STF_INSTALL_OUTCOME) == "STF_USERQUIT"
+            set Status = STATUS_USERCANCEL
+            goto finish_InstallOption
+        endif
+    endif
+
+    ifstr(i) $(DoConfig) == "YES"
+
+        ;
+        ; first run a privilege check on modifying the setup node
+        ;
+
+        shell "registry.inf" CheckSetupModify
+        ifint $($ShellCode) != $(!SHELL_CODE_OK)
+            goto finish_InstallOption
+        endif
+
+        ifstr(i) $($R0) != STATUS_SUCCESSFUL
+            goto finish_InstallOption
+        endif
+
+        ;
+        ; first make a new video entry, the entry is created automatically
+        ; enabled
+        ;
+
+        set ServiceNode   = $(MiniportDriver)
+        set ServiceBinary = %SystemRoot%\System32\drivers\#(Files-DisplayMiniportDrivers, $(MiniportDriver), 2)
+
+        set ServicesValues   = { +
+                {Type,           0, $(!REG_VT_DWORD),     $(Type)                  }, +
+                {Start,          0, $(!REG_VT_DWORD),     $(!SERVICE_SYSTEM_START) }, +
+                {Group,          0, $(!REG_VT_SZ),        $(Group)                 }, +
+                {ErrorControl,   0, $(!REG_VT_DWORD),     $(ErrorControl)          }, +
+                {Tag,            0, $(!REG_VT_DWORD),     $(Tag)                   }, +
+                {BinaryPathName, 0, $(!REG_VT_EXPAND_SZ), $(ServiceBinary)         }  +
+                }
+        set ParametersValues = { +
+                {InstalledDisplayDrivers,     0, $(!REG_VT_MULTI_SZ), $(InstalledDisplays) }, +
+                {VgaCompatible,               0, $(!REG_VT_DWORD),    $(VgaCompatible)     }, +
+                {DefaultSettings.BitsPerPel,  0, $(!REG_VT_DWORD),    $(BitsPerPel)        }, +
+                {DefaultSettings.XResolution, 0, $(!REG_VT_DWORD),    $(XResolution)       }, +
+                {DefaultSettings.YResolution, 0, $(!REG_VT_DWORD),    $(YResolution)       }  +
+                }
+
+        ifstr(i) $(VRefresh) != ""
+            set VRefreshValue = {DefaultSettings.VRefresh, 0, $(!REG_VT_DWORD), $(VRefresh)}
+            set ParametersValue = >($(ParametersValue), $(VRefreshValue))
+        endif
+
+        ifstr(i) $(Interlaced) != ""
+            set InterlacedValue = {DefaultSettings.Interlaced, 0, $(!REG_VT_DWORD), $(Interlaced)}
+            set ParametersValue = >($(ParametersValue), $(InterlacedValue))
+        endif
+
+        set DeviceValues     = {}
+        set EventLogValues   = { +
+                {EventMessageFile, 0, $(!REG_VT_EXPAND_SZ), $(EventMessageFile) }, +
+                {TypesSupported,   0, $(!REG_VT_DWORD),     $(TypesSupported)   }  +
+                }
+
+
+        shell "registry.inf"  MakeServicesEntry $(ServiceNode)      +
+                                                $(ServicesValues)   +
+                                                $(ParametersValues) +
+                                                $(DeviceValues)     +
+                                                $(EventLogValues)   +
+                                                Device0
+
+
+        ifint $($ShellCode) != $(!SHELL_CODE_OK)
+            Debug-Output "Couldn't execute MakeServicesEntry in registry.inf"
+            goto finish_InstallOption
+        endif
+
+        ifstr(i) $($R0) != STATUS_SUCCESSFUL
+            Debug-Output "MakeServicesEntry failed for video"
+            goto finish_InstallOption
+        endif
+
+        ;
+        ;
+        ; then disable the previous video entry
+        ;
+
+        ifstr(i) $(CurrentEntry) != $(MiniportDriver)
+            ifstr(i) $(CurrentEntry) != VGA
+                ifstr(i) $(CurrentEntry) != ""
+                    shell "registry.inf" ModifyServicesEntry $(CurrentEntry) $(!SERVICE_DISABLED)
+
+                    ifint $($ShellCode) != $(!SHELL_CODE_OK)
+                        Debug-Output "Couldn't find DisableServicesEntry in registry.inf"
+                        goto errorconfig
+                    endif
+
+                    ifstr(i) $($R0) != STATUS_SUCCESSFUL
+                        Debug-Output "DisableServices entry failed"
+                    endif
+                endif
+            endif
+        endif
+
+        goto configdone
+
+errorconfig = +
+        ifstr(i) $(CurrentEntry) != $(MiniportDriver)
+            shell "registry.inf" ModifyServicesEntry $(MiniportDriver) $(!SERVICE_DISABLED)
+            ifstr(i) $(CurrentEntry) != ""
+                shell "registry.inf" ModifyServicesEntry $(CurrentEntry) $(!SERVICE_SYSTEM_START)
+            endif
+        endif
+        goto finish_InstallOption
+
+configdone = +
+
+    endif
+
+    set Status = STATUS_SUCCESSFUL
+
+finish_InstallOption = +
+    ForListDo $(DrivesToFree)
+        LibraryProcedure STATUS,$(!LIBHANDLE), DeleteNetConnection $($) "TRUE"
+    EndForListDo
+
+    Return $(Status)
+
+
+[Install-AddCopyOption]
+
+    set STF_VITAL = ""
+    ;
+    ; Add the files to the copy list
+    ;
+    AddSectionKeyFileToCopyList   Files-DisplayMiniportDrivers +
+                                  $(MiniportDriver)            +
+                                  $(SrcDir)                    +
+                                  $(!STF_WINDOWSSYSPATH)\drivers
+
+    ForListDo $(InstalledDisplays)
+        AddSectionKeyFileToCopyList   Files-DisplayDLLs          +
+                                      $($)                       +
+                                      $(SrcDir)                  +
+                                      $(!STF_WINDOWSSYSPATH)
+
+    EndForListDo
+
+    exit
+
+
+[Install-DoCopyOption]
+
+    ;
+    ; Copy files in the copy list
+    ;
+    CopyFilesInCopyList
+    exit
+
+;**************************************************************************
+; PROGRESS GUAGE VARIABLES
+;**************************************************************************
+
+[ProgressCopyENG]
+    ProCaption   = "Windows NT Setup"
+    ProCancel    = "Cancel"
+    ProCancelMsg = "Windows NT is not correcly installed.  Are you sure you want "+
+                   "to cancel copying files?"
+    ProCancelCap = "Setup Message"
+    ProText1     = "Copying:"
+    ProText2     = "To:"
+
+[StringsENG]
+    String1 = "Display"
+    String2 = "Please enter the full path to the Windows NT Display "+
+              "driver files.  Then choose Continue."
+
+
+
+;-----------------------------------------------------------------------
+; SOURCE MEDIA DESCRIPTIONS
+; -------------------------
+; The OEM should list all the diskette labels here.  The source media
+; description is used during copy to prompt the user for a diskette
+; if the source is diskettes.
+;
+; Use 1 = "Diskette 1 Label" , TAGFILE = disk1
+;     2 = "Diskette 2 Label" , TAGFILE = disk2
+;     ...
+;-----------------------------------------------------------------------
+
+[Source Media Descriptions]
+    1  = "OEM DISK (VIDEO)"  , TAGFILE = disk1
+    2  = "Windows NT CD-ROM" , TAGFILE = cdrom.w
+
+
+[Files-DisplayDLLs]
+; Because this .INF script appears to be unable to copy from two different
+; drives, we can't ask the user to insert the NT CD-ROM with framebuf.dll;
+; the user must manually copy it alongside the video miniport.
+framebuf = 1,framebuf.dll , SIZE=999
+
+[Files-DisplayMiniportDrivers]
+boxv = 1,boxvideo.sys , SIZE=999
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme.txt	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,39 @@
+
+ Windows NT Video Miniport Programming Example
+ ---------------------------------------------
+
+ The sample video miniport supports the virtual SVGA chip supported by the
+VirtualBox hypervisor. It may also work with bochs and qemu, but this has not
+been tested; small changes may be required.
+
+ The source code is split into two parts: The boxv module (boxv*) and the
+miniport proper (videomp*). The boxv module provides a simple collection of
+routines to set modes on the VirtualBox/qemu/bochs virtual SVGA chip. The
+vidmini module implements the Windows NT video miniport interface.
+
+ The miniport only provides minimal mode setting and palette access interface
+since the virtual hardware does not support hardware cursors etc. All drawing
+is left to framebuf.dll, the default Windows NT framebuffer display driver.
+
+ Please refer to the Windows NT DDK for documentation on the video miniport
+interface.
+
+
+ Supported Windows Versions
+
+ The miniport supports all Windows NT x86 versions from the original NT 3.1
+up to 6.2 (Windows 7). Windows XP and above ships with a VGA/VESA driver which
+provides similar functionality, but blocks power management (hibernation).
+
+
+ Installation
+
+ The installation method depends on Windows version used. For Windows NT 3.1,
+the Setup applet must be used. For all other versions, the display property
+dialog should be used. There are two versions of the INF file: oemsetup.inf
+for Windows NT 3.x and vidmini.inf for Windows NT 4 and later versions.
+
+ Important: For Windows NT 3.x, the framebuf.dll library provided on the NT
+installation media is required and should be copied to the directory which
+contains the INF file. For Windows NT 4.0 and later, framebuf.dll
+is already preinstalled on the system.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videomp.c	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,758 @@
+/* 
+ * Windows NT Video Miniport for the VirtualBox/bochs/qemu SVGA adapter.
+ * This miniport programs the hardware directly and does not use or require
+ * the video BIOS or VBE.
+ *
+ * NB: This is not a "VGA compatible" miniport and standard VGA modes are
+ * handled by the default VGA miniport.
+ */
+
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include <dderror.h>
+#include <stddef.h>
+
+#include "videomp.h"
+#include "boxv.h"
+
+
+/* Number of PCI access ranges. */
+#define NUM_PCI_RANGES      3
+
+/* RGB color channel constants. */
+typedef enum {
+    CHANNEL_RED,
+    CHANNEL_GREEN,
+    CHANNEL_BLUE
+} COLOR_CHANNEL;
+
+
+#if defined( ALLOC_PRAGMA )
+#pragma alloc_text( PAGE, DriverEntry )
+#pragma alloc_text( PAGE, HwVidFindAdapter )
+#pragma alloc_text( PAGE, HwVidInitialize )
+#pragma alloc_text( PAGE, HwVidStartIO )
+#endif
+
+
+/* Calculate pitch based on scanline length and bit depth. */
+static ULONG vmpPitchByBpp( ULONG Length, UCHAR Bpp )
+{
+    ULONG   ulPitch = 0;
+
+    switch( Bpp ) {
+    case 4:
+        ulPitch = (Length + 1) / 2;
+        break;
+    case 8:
+        ulPitch = Length;
+        break;
+    case 15:
+    case 16:
+        ulPitch = Length * 2;
+        break;
+    case 24:
+        ulPitch = Length * 3;
+        break;
+    case 32:
+        ulPitch = Length * 4;
+        break;
+    }
+    return( ulPitch );
+}
+
+
+/* Validate a given mode and set the appropriate flag. Note that the
+ * validation criteria are somewhat arbitrary.
+ */
+static void vmpValidateMode( PVIDEOMP_MODE Mode, ULONG FramebufLen )
+{
+    ULONG   ulModeMem;
+
+    Mode->bValid = FALSE;
+
+    do {
+        /* Horizontal resolution should be divisible by 8. */
+        if( Mode->HorzRes % 8)
+            break;
+        
+        /* Validate memory requirements. */
+        ulModeMem = vmpPitchByBpp( Mode->HorzRes, Mode->Bpp ) * Mode->VertRes;
+        if( ulModeMem > FramebufLen )
+            break;
+
+        /* Passed all checks, mode is valid. */
+        Mode->bValid = TRUE;
+    } while( 0 );
+}
+
+/* Determine whether the supported adapter is present. Note that this 
+ * function is not allowed to change the state of the adapter!
+ */
+VP_STATUS HwVidFindAdapter( PVOID HwDevExt, PVOID HwContext, PWSTR ArgumentString,
+                            PVIDEO_PORT_CONFIG_INFO ConfigInfo, PUCHAR Again )
+{
+    PHW_DEV_EXT             pExt = HwDevExt;
+    PVOID                   *pVirtAddr;
+    ULONG                   i;
+    INT                     chip_id;
+    VP_STATUS               status;
+    ULONG                   cbVramSize;
+    PWSTR                   pwszDesc;
+    ULONG                   cbDesc;
+#ifdef USE_GETACCESSRANGES
+    VIDEO_ACCESS_RANGE      pciAccessRanges[NUM_PCI_RANGES];
+    USHORT                  usVendorId = BOXV_PCI_VEN;
+    USHORT                  usDeviceId = BOXV_PCI_DEV;
+    ULONG                   ulSlot = 0;
+#endif
+
+    //@todo: The framebuffer address should not be hardcoded for non-PCI access
+#define NUM_ACCESS_RANGES   2
+    VIDEO_ACCESS_RANGE accessRanges[NUM_ACCESS_RANGES] = {
+        /* StartLo     StartHi     Len       IO Vis Shr */
+        { 0x000001CE, 0x00000000, 0x00000002, 1, 1, 0 },    /* I/O ports */
+        { 0xE0000000, 0x00000000, 0x00400000, 0, 1, 0 }     /* Framebuffer */
+    };
+
+    VideoDebugPrint( (1, "videomp: HwVidFindAdapter\n") );
+
+    /* Fail if the passed structure is smaller than the NT 3.1 version. */
+    if( ConfigInfo->Length < offsetof( VIDEO_PORT_CONFIG_INFO, DmaChannel ) ) {
+        return( ERROR_INVALID_PARAMETER );
+    }
+
+    /* Sadly, VideoPortGetAccessRanges was not present in NT 3.1. There is no
+     * reasonably simple way to dynamically import port driver routines on 
+     * newer versions, so we'll just do without. 
+     */
+#ifdef USE_GETACCESSRANGES
+    /* If PCI is supported, query the bus for resource mappings. */
+    if( ConfigInfo->AdapterInterfaceType == PCIBus ) {
+        /* Ask for bus specific access ranges. */
+        VideoPortZeroMemory( pciAccessRanges, sizeof( pciAccessRanges ) );
+        status = VideoPortGetAccessRanges( HwDevExt, 0, NULL,
+                                           NUM_PCI_RANGES, pciAccessRanges,
+                                           &usVendorId, &usDeviceId, &ulSlot );
+        if( status == NO_ERROR ) {
+            VideoDebugPrint( (1, "videomp: Found adapter in PCI slot %d\n", ulSlot) );
+            pExt->ulSlot = ulSlot;
+            /* The framebuffer is in the first slot of the PCI ranges. Copy
+             * the data into the access ranges we're going to request.
+             */
+            accessRanges[1].RangeStart  = pciAccessRanges[0].RangeStart;
+            accessRanges[1].RangeLength = pciAccessRanges[0].RangeLength;
+        } else {
+            /* On NT versions without PCI support, we won't even attempt this.
+             * So if we tried to query the PCI device and failed to find it, 
+             * it really isn't there and we have to give up. 
+             */
+            VideoDebugPrint( (1, "videomp: PCI adapter not found\n") );
+            return( ERROR_DEV_NOT_EXIST );
+        }
+    }
+#endif
+
+    /* Some versions of vga.sys trap accesses to ports 0x1CE-0x1CF used on
+     * old ATI cards. On Windows 2000 and later we can report legacy
+     * resources to resolve this conflict. On NT 4 and older, we use a hack
+     * and claim other, non-conflicting ports.
+     */
+    if( PortVersion < VP_VER_W2K )
+        accessRanges[0].RangeStart = RtlConvertUlongToLargeInteger( 0x1CC );
+ 
+    /* Check for a conflict in case someone else claimed our resources. */
+    status = VideoPortVerifyAccessRanges( HwDevExt, NUM_ACCESS_RANGES, accessRanges );
+    if( status != NO_ERROR ) {
+        return( status );
+    }
+
+    /* Indicate no emulator support. */
+    ConfigInfo->NumEmulatorAccessEntries     = 0;
+    ConfigInfo->EmulatorAccessEntries        = NULL;
+    ConfigInfo->EmulatorAccessEntriesContext = 0;
+
+    ConfigInfo->HardwareStateSize = 0;
+
+    ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart  = 0;
+    ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0;
+    ConfigInfo->VdmPhysicalVideoMemoryLength           = 0;
+
+    /* Describe the framebuffer. We claimed the range already. */
+    pExt->PhysicalFrameAddress = accessRanges[1].RangeStart;
+
+
+    /*
+     * Map all memory and I/O ranges into system virtual address space.
+     * NB: The virtual addresses in the HwDevExt must match the number
+     * and type of AccessRange entries.
+     */
+    pVirtAddr = &pExt->IoPorts;
+
+    /* Attempt to claim and map the memory and I/O address ranges. */
+    for( i = 0; i < NUM_ACCESS_RANGES; ++i, ++pVirtAddr ) {
+        *pVirtAddr = VideoPortGetDeviceBase( pExt, 
+                                             accessRanges[i].RangeStart,
+                                             accessRanges[i].RangeLength,
+                                             accessRanges[i].RangeInIoSpace );
+        if( *pVirtAddr == NULL ) {
+            return( ERROR_INVALID_PARAMETER );
+        }
+    }
+
+    /* Verify that supported hardware is present. */
+    chip_id = BOXV_detect( pExt, &pExt->FramebufLen );
+    if( !chip_id ) {
+        /* If supported hardware was not found, free allocated resources. */
+        pVirtAddr = &pExt->IoPorts;
+        for( i = 0; i < NUM_ACCESS_RANGES; ++i, ++pVirtAddr )
+            VideoPortFreeDeviceBase( pExt, *pVirtAddr );
+
+        return( ERROR_DEV_NOT_EXIST );
+    }
+
+    /* We need to access VGA and other I/O ports. Fortunately the HAL doesn't 
+     * care at all how the I/O ports are or aren't mapped on x86 platforms.
+     */
+    pExt->IOAddrVGA = NULL;
+
+    /* Only support one attached monitor. */
+    pExt->NumMonitors = 1;
+
+    /* Set up mode information. */
+    pExt->CurrentModeNumber = 0;
+    pExt->NumValidModes     = 0;
+
+    for( i = 0; i < ulAllModes; ++i ) {
+        vmpValidateMode( &VideoModes[i], pExt->FramebufLen );
+        if( VideoModes[i].bValid )
+            ++pExt->NumValidModes;
+    }
+
+    /* Only one adapter supported, no need to call us again. */
+    *Again = 0;
+
+    /* Report the hardware names via registry. */
+
+#define TEMP_CHIP_NAME  L"bochs Mk II"
+    pwszDesc = TEMP_CHIP_NAME;
+    cbDesc   = sizeof( TEMP_CHIP_NAME );
+
+    VideoPortSetRegistryParameters( pExt, L"HardwareInformation.ChipType",
+                                    pwszDesc, cbDesc );
+
+#define TEMP_DAC_NAME  L"Integrated DAC"
+    pwszDesc = TEMP_DAC_NAME;
+    cbDesc   = sizeof( TEMP_DAC_NAME );
+    VideoPortSetRegistryParameters( pExt, L"HardwareInformation.DacType",
+                                    pwszDesc, cbDesc );
+
+#define TEMP_ADAPTER_NAME  L"VirtualBox/bochs"
+    pwszDesc = TEMP_ADAPTER_NAME;
+    cbDesc   = sizeof( TEMP_ADAPTER_NAME );
+    VideoPortSetRegistryParameters( pExt, L"HardwareInformation.AdapterString",
+                                    pwszDesc, cbDesc );
+
+    cbVramSize = pExt->FramebufLen;
+    VideoPortSetRegistryParameters( pExt, L"HardwareInformation.MemorySize",
+                                    &cbVramSize, sizeof( ULONG ) );
+    /* All is well. */
+    return( NO_ERROR );
+}
+
+
+/* Perform one-time device initialization. Once this function has been
+ * entered, the miniport may change adapter state.
+ */
+BOOLEAN HwVidInitialize( PVOID HwDevExt )
+{
+    VideoDebugPrint( (1, "videomp: HwVidInitialize\n") );
+    return( TRUE );
+}
+
+
+/* Determine pixel mask given color depth and color channel. */
+static ULONG vmpMaskByBpp( UCHAR Bpp, COLOR_CHANNEL Channel )
+{
+    ULONG   ulMask;
+
+    switch( Bpp ) {
+    case 24:
+    case 32:
+        ulMask = 0x00FF0000 >> (Channel * 8);
+        break;
+    case 15:
+        ulMask = 0x00007C00 >> (Channel * 5);
+        break;
+    case 16:
+        switch( Channel ) {
+        case CHANNEL_RED:
+            ulMask = 0x0000F800;
+            break;
+        case CHANNEL_GREEN:
+            ulMask = 0x000007E0;
+            break;
+        case CHANNEL_BLUE:
+            ulMask = 0x0000001F;
+            break;
+        }
+        break;
+    case 4:
+    case 8:
+    default:
+        ulMask = 0;     /* Palettized modes don't have a mask. */
+    }
+
+    return( ulMask );
+}
+
+/* Fill out NT specific video mode information struct based on resolution
+ * and color depth.
+ */
+static void vmpFillModeInfo( PVIDEO_MODE_INFORMATION ModeInfo, USHORT HRes, USHORT VRes, UCHAR Bpp)
+{
+    /* First the basic mode information. */
+    ModeInfo->Length          = sizeof( VIDEO_MODE_INFORMATION );
+    ModeInfo->ModeIndex       = 0;      /* Filled in later. */
+    ModeInfo->VisScreenWidth  = HRes;   /* Horizontal resolution in pixels. */
+    ModeInfo->VisScreenHeight = VRes;   /* Vertical resolution in pixels. */
+
+    /* Assume no rounding is necessary. */
+    ModeInfo->ScreenStride    = vmpPitchByBpp( HRes, Bpp );
+
+    ModeInfo->NumberOfPlanes  = 1;      /* Always one plane - packed pixel only. */
+    ModeInfo->BitsPerPlane    = Bpp;    /* Number of bits per pixel. */
+    ModeInfo->Frequency       = 60;     /* Irrelevant; just make something up. */
+
+    /* Screen size is made up, but should correspond to aspect ratio. */
+    ModeInfo->XMillimeter     = 320;
+    ModeInfo->YMillimeter     = ModeInfo->XMillimeter * VRes / HRes;
+
+    /* The DAC always works with 8 bits per channel. */
+    ModeInfo->NumberRedBits   = 8;      /* Red pixels in DAC. */
+    ModeInfo->NumberGreenBits = 8;      /* Green pixels in DAC. */
+    ModeInfo->NumberBlueBits  = 8;      /* Blue pixels in DAC. */
+
+    /* Pixel mask depends on color depth. */
+    ModeInfo->RedMask         = vmpMaskByBpp( Bpp, CHANNEL_RED );
+    ModeInfo->GreenMask       = vmpMaskByBpp( Bpp, CHANNEL_GREEN );
+    ModeInfo->BlueMask        = vmpMaskByBpp( Bpp, CHANNEL_BLUE );
+
+    /* Mode attributes are only different for 8bpp modes. */
+    ModeInfo->AttributeFlags      = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR;
+    if( Bpp <= 8 )
+        ModeInfo->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
+
+    /* Strictly speaking, the following don't need to be filled out. */
+    ModeInfo->VideoMemoryBitmapWidth       = 0;
+    ModeInfo->VideoMemoryBitmapHeight      = 0;
+    ModeInfo->DriverSpecificAttributeFlags = 0;
+}
+
+/* Main I/O request handler routine. */
+BOOLEAN HwVidStartIO( PVOID HwDevExt, PVIDEO_REQUEST_PACKET ReqPkt )
+{
+    PHW_DEV_EXT                         pExt = HwDevExt;
+    VP_STATUS                           status = NO_ERROR;
+    PVIDEO_MODE_INFORMATION             modeInfo;
+    PVIDEO_MEMORY                       vidMem;
+    PVIDEO_SHARE_MEMORY                 pShrMem;
+    PVOID                               virtualAddress;
+    ULONG                               inIoSpace;
+    ULONG                               modeNumber;
+    ULONG                               ulLen;
+    ULONG                               i;
+
+    VideoDebugPrint( (2, "videomp: HwVidStartIO: ") );
+
+    /* Process the VRP. Required requests are handled first. */
+    switch( ReqPkt->IoControlCode ) {
+    case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
+    {
+        PVIDEO_NUM_MODES        numModes;
+
+        VideoDebugPrint( (2, "QUERY_NUM_AVAIL_MODES\n") );        
+        if( ReqPkt->OutputBufferLength < sizeof( VIDEO_NUM_MODES ) ) {
+            status = ERROR_INSUFFICIENT_BUFFER;
+        } else {
+            ReqPkt->StatusBlock->Information = sizeof( VIDEO_NUM_MODES );
+            numModes = (PVIDEO_NUM_MODES)ReqPkt->OutputBuffer;
+            numModes->ModeInformationLength = sizeof( VIDEO_MODE_INFORMATION );
+            numModes->NumModes = pExt->NumValidModes;
+        }
+        break;
+    }
+
+    case IOCTL_VIDEO_QUERY_AVAIL_MODES:
+        VideoDebugPrint( (2, "QUERY_AVAIL_MODES\n") );
+        ulLen = pExt->NumValidModes * sizeof( VIDEO_MODE_INFORMATION );
+        if( ReqPkt->OutputBufferLength < ulLen ) {
+            status = ERROR_INSUFFICIENT_BUFFER;
+        } else {
+            ReqPkt->StatusBlock->Information = ulLen;
+            modeInfo = ReqPkt->OutputBuffer;
+            for( i = 0; i < ulAllModes; ++i ) {
+                if( VideoModes[i].bValid ) {
+                    vmpFillModeInfo( modeInfo, VideoModes[i].HorzRes,
+                                     VideoModes[i].VertRes, VideoModes[i].Bpp );
+                    modeInfo->ModeIndex = i; //VideoModes[i].modeInformation.ModeIndex;
+
+                    modeInfo++;
+                }
+            }
+        }
+        break;
+
+    case IOCTL_VIDEO_QUERY_CURRENT_MODE:
+        VideoDebugPrint( (2, "QUERY_CURRENT_MODE\n") );
+        if( ReqPkt->OutputBufferLength < sizeof( VIDEO_MODE_INFORMATION ) ) {
+            status = ERROR_INSUFFICIENT_BUFFER;
+        } else {
+            ReqPkt->StatusBlock->Information = sizeof( VIDEO_MODE_INFORMATION );
+            modeInfo  = ReqPkt->OutputBuffer;
+            vmpFillModeInfo( modeInfo, 
+                             VideoModes[pExt->CurrentModeNumber].HorzRes,
+                             VideoModes[pExt->CurrentModeNumber].VertRes,
+                             VideoModes[pExt->CurrentModeNumber].Bpp );
+            modeInfo->ModeIndex = pExt->CurrentModeNumber; //VideoModes[pExt->CurrentModeNumber].modeInformation.ModeIndex;
+        }
+
+        break;
+
+    case IOCTL_VIDEO_SET_CURRENT_MODE:
+        VideoDebugPrint( (2, "SET_CURRENT_MODE\n") );
+
+        /* Ensure the mode is valid. */
+        modeNumber = ((PVIDEO_MODE)(ReqPkt->InputBuffer))->RequestedMode;
+
+        if( (modeNumber > ulAllModes) || (!VideoModes[modeNumber].bValid) ) {
+            status = ERROR_INVALID_PARAMETER;
+            break;
+        }
+
+        BOXV_ext_mode_set( pExt, VideoModes[modeNumber].HorzRes, 
+                           VideoModes[modeNumber].VertRes, VideoModes[modeNumber].Bpp,
+                           VideoModes[modeNumber].HorzRes, VideoModes[modeNumber].VertRes );
+
+        pExt->CurrentModeNumber = modeNumber;
+        break;
+
+    case IOCTL_VIDEO_RESET_DEVICE:
+        VideoDebugPrint( (2, "RESET_DEVICE\n") );
+	/* Not calling the following routine avoids some visual glitches. */
+        /* BOXV_ext_disable( pExt ); */
+        break;
+
+    case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
+    {
+        PVIDEO_MEMORY_INFORMATION           memInfo;
+
+        VideoDebugPrint( (2, "MAP_VIDEO_MEMORY\n") );
+        if( (ReqPkt->OutputBufferLength < sizeof( VIDEO_MEMORY_INFORMATION )) ||
+            (ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY )) ) {
+
+            status = ERROR_INSUFFICIENT_BUFFER;
+            break;
+        }
+
+        ReqPkt->StatusBlock->Information =  sizeof( VIDEO_MEMORY_INFORMATION );
+
+        vidMem    = (PVIDEO_MEMORY)ReqPkt->InputBuffer;
+        memInfo   = ReqPkt->OutputBuffer;
+        inIoSpace = FALSE;
+
+        memInfo->VideoRamBase   = vidMem->RequestedVirtualAddress;
+        memInfo->VideoRamLength = pExt->FramebufLen;
+
+        status = VideoPortMapMemory( pExt, pExt->PhysicalFrameAddress,
+                                     &memInfo->VideoRamLength, &inIoSpace,
+                                     &memInfo->VideoRamBase );
+
+        /* The framebuffer covers the entire video memory. */
+        memInfo->FrameBufferBase   = memInfo->VideoRamBase;
+        memInfo->FrameBufferLength = memInfo->VideoRamLength;
+        break;
+    }
+
+    case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
+        VideoDebugPrint( (2, "UNMAP_VIDEO_MEMORY\n") );
+        if( ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY ) ) {
+            status = ERROR_INSUFFICIENT_BUFFER;
+        } else {
+            vidMem  = (PVIDEO_MEMORY)ReqPkt->InputBuffer;
+            status = VideoPortUnmapMemory( pExt,
+                                           vidMem->RequestedVirtualAddress,
+                                           0 );
+        }
+        break;
+
+    /* The following request is required for palettized modes. */
+    case IOCTL_VIDEO_SET_COLOR_REGISTERS:
+    {
+        PVIDEO_CLUT     clutBuffer;
+
+        VideoDebugPrint( (2, "SET_COLOR_REGISTERS\n") );
+        clutBuffer = ReqPkt->InputBuffer;
+
+        if( (ReqPkt->InputBufferLength < sizeof( VIDEO_CLUT ) - sizeof( ULONG )) ||
+            (ReqPkt->InputBufferLength < sizeof( VIDEO_CLUT ) +
+                    (sizeof( ULONG ) * (clutBuffer->NumEntries - 1)) ) ) {
+
+            status = ERROR_INSUFFICIENT_BUFFER;
+            break;
+        }
+
+        if( VideoModes[pExt->CurrentModeNumber].Bpp == 8 ) {
+            BOXV_dac_set( pExt, clutBuffer->FirstEntry, clutBuffer->NumEntries,
+                          clutBuffer->LookupTable );
+        }
+        break;
+    }
+
+    /* The following requests are optional. */
+    case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
+    {
+        PVIDEO_POINTER_CAPABILITIES     ptrCaps = ReqPkt->OutputBuffer;
+
+        VideoDebugPrint( (2, "QUERY_POINTER_CAPABILITIES\n") );
+        if( ReqPkt->OutputBufferLength < sizeof( VIDEO_POINTER_CAPABILITIES ) ) {
+            ReqPkt->StatusBlock->Information = 0;
+            status = ERROR_INSUFFICIENT_BUFFER;
+        }
+
+        ptrCaps->Flags = 0;     /* Indicate no pointer support. */
+        ptrCaps->MaxWidth = ptrCaps->MaxHeight = 0;
+        /* Documentation and sample code disagree on whether no display
+         * memory for cursor is indicated by 0 or -1.
+         */
+        ptrCaps->HWPtrBitmapStart = ptrCaps->HWPtrBitmapEnd = ~0;
+
+        ReqPkt->StatusBlock->Information = sizeof( VIDEO_POINTER_CAPABILITIES );
+        break;
+    }
+
+    /* The share/unshare IOCTLs are new for NT 3.51. */
+    case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
+    {
+        PVIDEO_SHARE_MEMORY_INFORMATION     pShrMemInfo;
+        PHYSICAL_ADDRESS                    shareAddress;
+        ULONG                               sharedViewSize;
+
+        VideoDebugPrint( (2, "SHARE_VIDEO_MEMORY\n") );
+        if( (ReqPkt->OutputBufferLength < sizeof( VIDEO_SHARE_MEMORY_INFORMATION )) ||
+            (ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY )) ) {
+
+            status = ERROR_INSUFFICIENT_BUFFER;
+            break;
+        }
+
+        pShrMem = ReqPkt->InputBuffer;
+
+        if( (pShrMem->ViewOffset > pExt->FramebufLen) ||
+            ((pShrMem->ViewOffset + pShrMem->ViewSize) > pExt->FramebufLen) ) {
+
+            status = ERROR_INVALID_PARAMETER;
+            break;
+        }
+
+        ReqPkt->StatusBlock->Information = sizeof( VIDEO_SHARE_MEMORY_INFORMATION );
+
+        /* The input buffer is also the output buffer; remember the input. */
+        virtualAddress = pShrMem->ProcessHandle;
+        sharedViewSize = pShrMem->ViewSize;
+
+        inIoSpace = FALSE;
+
+        /* NB: ViewOffset is not being taken into account. */
+        shareAddress.QuadPart = pExt->PhysicalFrameAddress.QuadPart;
+
+        status = VideoPortMapMemory( pExt, shareAddress,
+                                     &sharedViewSize, &inIoSpace,
+                                     &virtualAddress );
+
+        pShrMemInfo = ReqPkt->OutputBuffer;
+        pShrMemInfo->SharedViewOffset = pShrMem->ViewOffset;
+        pShrMemInfo->VirtualAddress   = virtualAddress;
+        pShrMemInfo->SharedViewSize   = sharedViewSize;
+        break;
+    }
+
+    case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
+        VideoDebugPrint( (2, "UNSHARE_VIDEO_MEMORY\n") );
+        if( ReqPkt->InputBufferLength < sizeof( VIDEO_SHARE_MEMORY ) ) {
+            status = ERROR_INSUFFICIENT_BUFFER;
+            break;
+        }
+
+        pShrMem = ReqPkt->InputBuffer;
+        status = VideoPortUnmapMemory( pExt, pShrMem->RequestedVirtualAddress,
+                                       pShrMem->ProcessHandle );
+        break;
+
+
+    /* The child state IOCTLs are new for NT 5.0 (Windows 2000). */
+    case IOCTL_VIDEO_GET_CHILD_STATE:
+    {
+        PULONG      pChildIndex;
+        PULONG      pChildState;
+
+        VideoDebugPrint( (2, "GET_CHILD_STATE\n") );
+        if( ReqPkt->InputBufferLength < sizeof( ULONG ) ||
+            ReqPkt->OutputBufferLength < sizeof( ULONG ) ) {
+            status = ERROR_INSUFFICIENT_BUFFER;
+            break;
+        }
+
+        pChildIndex = ReqPkt->InputBuffer;
+        pChildState = ReqPkt->OutputBuffer;
+
+        /* Always say the child is active. */
+        *pChildState = VIDEO_CHILD_ACTIVE;
+        break;
+    }
+
+    /* Any other request is invalid and fails. */
+    default:
+        VideoDebugPrint( (1, "Unhandled IoControlCode %08x!\n", ReqPkt->IoControlCode) );
+        status = ERROR_INVALID_FUNCTION;
+        break;
+    }
+
+    ReqPkt->StatusBlock->Status = status;
+    return( TRUE );
+}
+
+/* Validate support for a requested power state. */
+VP_STATUS HwGetPowerState( PVOID HwDevExt, ULONG HwId,
+                           PVIDEO_POWER_MANAGEMENT VideoPowerControl )
+{
+    VideoDebugPrint( (1, "videomp: HwGetPowerState\n") );
+    return( NO_ERROR );
+}
+
+/* Set the device power state. */
+VP_STATUS HwSetPowerState( PVOID HwDevExt, ULONG HwId,
+                           PVIDEO_POWER_MANAGEMENT VideoPowerControl )
+{
+    VideoDebugPrint( (1, "videomp: HwSetPowerState\n") );
+    return( NO_ERROR );
+}
+
+/* Return child device descriptors. In this case just a single monitor. */
+VP_STATUS HwGetChildDesc( PVOID HwDevExt, PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
+                          PVIDEO_CHILD_TYPE VideoChildType, PUCHAR pChildDescriptor,
+                          PULONG UId, PULONG pUnused )
+{
+    PHW_DEV_EXT     pExt = HwDevExt;
+
+    VideoDebugPrint( (1, "videomp: HwGetChildDesc\n") );
+
+    if( ChildEnumInfo->ChildIndex > 0 ) {
+        if( (int)ChildEnumInfo->ChildIndex <= pExt->NumMonitors ) {
+            *VideoChildType = Monitor;
+            *UId = ChildEnumInfo->ChildIndex;
+            return( VIDEO_ENUM_MORE_DEVICES );
+        }
+    }
+
+    return( ERROR_NO_MORE_DEVICES );
+}
+
+/* Reset the adapter into a VGA-compatible state. */
+BOOLEAN HwVidResetHw( PVOID HwDevExt, ULONG Columns, ULONG Rows )
+{
+    PHW_DEV_EXT     pExt = HwDevExt;
+
+    VideoDebugPrint( (1, "videomp: HwVidResetHw\n") );
+
+    BOXV_ext_disable( pExt );
+    /* Indicate that we didn't actually set the requested text mode. */
+    return( FALSE );
+}
+
+/* Standard NT driver initialization entry point. */
+ULONG DriverEntry( PVOID Context1, PVOID Context2 )
+{
+    VIDEO_HW_INITIALIZATION_DATA    hwInitData;
+    ULONG                           status;
+
+    VideoDebugPrint( (1, "videomp: DriverEntry\n") );
+
+    /* Prepare the initialization structure. */
+    VideoPortZeroMemory( &hwInitData, sizeof( VIDEO_HW_INITIALIZATION_DATA ) );
+    hwInitData.HwInitDataSize = sizeof( VIDEO_HW_INITIALIZATION_DATA );
+
+    /* Set up driver callbacks. */
+    hwInitData.HwFindAdapter = HwVidFindAdapter;
+    hwInitData.HwInitialize  = HwVidInitialize;
+    hwInitData.HwStartIO     = HwVidStartIO;
+    /* There's no interrupt or timer callback. */
+    hwInitData.HwInterrupt   = NULL;
+    hwInitData.HwTimer       = NULL;
+    hwInitData.HwResetHw     = HwVidResetHw;
+
+    /* Power and child device management callbacks were added in NT 5.0. */
+    hwInitData.HwGetPowerState           = HwGetPowerState;
+    hwInitData.HwSetPowerState           = HwSetPowerState;
+    hwInitData.HwGetVideoChildDescriptor = HwGetChildDesc;
+
+    /* Report legacy resources. */
+    hwInitData.HwLegacyResourceList  = LegacyRanges;
+    hwInitData.HwLegacyResourceCount = ulNumLegacyRanges;
+
+    /* Report the device extension size. */
+    hwInitData.HwDeviceExtensionSize = sizeof( HW_DEV_EXT );
+
+    /* Refer to the CurrentControlSet\Services\xxx\Device0 registry key. */
+    hwInitData.StartingDeviceNumber = 0;
+
+    /* Later NT versions support PCI; recent versions ignore this entirely */
+    hwInitData.AdapterInterfaceType = PCIBus;
+
+    /* The PsGetVersion function was not available in NT 3.x. We therefore 
+     * implement a poor man's version detection by successively reducing the
+     * HwInitDataSize until the video miniport (we hope) accepts it.
+     */
+    do {
+        /* First try with NT 5.1 (Windows XP) structure size. */
+        VideoDebugPrint( (1, "videomp: Trying DDI 5.1 HwInitDataSize\n") );
+        hwInitData.HwInitDataSize = SIZE_OF_WXP_VIDEO_HW_INITIALIZATION_DATA;
+        PortVersion = VP_VER_XP;
+        status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL );
+        if( status != STATUS_REVISION_MISMATCH ) {
+            /* If status is anything other than a version mismatch, don't
+             * try calling VideoPortInitialize again. The call may have
+             * succeeded, or it failed for some reason whe can't easily fix.
+             */
+            break;
+        }
+
+        /* Try the NT 5.0 (Windows 2000) structure size. */
+        VideoDebugPrint( (1, "videomp: Trying DDI 5.0 HwInitDataSize\n") );
+        hwInitData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA;
+        PortVersion = VP_VER_W2K;
+        status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL );
+        if( status != STATUS_REVISION_MISMATCH ) {
+            break;
+        }
+
+        /* Try the NT 4.0 (and also NT 3.51) structure size. */
+        VideoDebugPrint( (1, "videomp: Trying DDI 4.0 HwInitDataSize\n") );
+        hwInitData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA;
+        PortVersion = VP_VER_NT4;
+        status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL );
+        if( status != STATUS_REVISION_MISMATCH ) {
+            break;
+        }
+
+        /* Try the original NT 3.1/3.5 HwInitDataSize. No PCI support. */
+        VideoDebugPrint( (1, "videomp: Trying DDI 3.1 HwInitDataSize\n") );
+        hwInitData.HwInitDataSize = offsetof( VIDEO_HW_INITIALIZATION_DATA, HwResetHw );
+        hwInitData.AdapterInterfaceType = Isa;
+        PortVersion = VP_VER_NT31;
+        status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL );
+    } while( 0 );
+    VideoDebugPrint( (1, "videomp: VideoPortInitialize rc=%08x\n", status ) );
+    return( status );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videomp.h	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,39 @@
+/*
+ * Internal video miniport interfaces.
+ */
+
+/* Video Port versions that affect miniport behavior. */
+
+#define VP_VER_NT31     0x030100
+#define VP_VER_NT4      0x040000        /* Also NT 3.51 */
+#define VP_VER_W2K      0x050000
+#define VP_VER_XP       0x050100
+
+/* Video mode description structure */
+typedef struct {
+    USHORT              HorzRes;                /* Horizontal resolution */
+    USHORT              VertRes;                /* Vertical resolution */
+    UCHAR               Bpp;                    /* Bits per pixel */
+    BOOLEAN             bValid;                 /* Valid mode flag */
+} VIDEOMP_MODE, *PVIDEOMP_MODE;
+
+/* The device extension - private miniport data */
+typedef struct {
+    PVOID               IoPorts;                /* I/O ports mapping */
+    PVOID               FrameAddress;           /* Framebuffer mapping */
+    PHYSICAL_ADDRESS    PhysicalFrameAddress;   /* Physical FB address */
+    ULONG               FramebufLen;            /* Framebuffer length */
+    ULONG               CurrentModeNumber;      /* Current mode index */
+    ULONG               NumValidModes;          /* Number of valid modes */
+    ULONG               NumMonitors;            /* Number of attached monitors */
+    PUCHAR              IOAddrVGA;              /* VGA I/O ports mapping */
+    ULONG               ulSlot;                 /* PCI slot the adapter is in. */
+    ULONG               PortVersion;            /* Video Port version */
+} HW_DEV_EXT, *PHW_DEV_EXT;
+
+/* Variables defined in vidmpdat.c */
+extern VIDEOMP_MODE         VideoModes[];
+extern ULONG                ulAllModes;
+extern VIDEO_ACCESS_RANGE   LegacyRanges[];
+extern ULONG                ulNumLegacyRanges;
+extern ULONG                PortVersion;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videomp.rc	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,33 @@
+#include <windows.h>
+
+#define VMP_VERSION     1,00,00,002
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION    VMP_VERSION
+PRODUCTVERSION VMP_VERSION
+FILEFLAGSMASK  VS_FFI_FILEFLAGSMASK
+FILEFLAGS      0
+FILEOS         VOS_NT_WINDOWS32
+FILETYPE       VFT_DRV
+FILESUBTYPE    VFT2_DRV_DISPLAY
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904B0"   /* US English, Unicode codepage */
+        BEGIN
+            VALUE "CompanyName",     "OS/2 Museum"
+            VALUE "FileDescription", "Boxvideo Video Miniport Driver"
+            VALUE "FileVersion",     "1.3"
+            VALUE "InternalName",    "boxvideo.sys"
+            VALUE "LegalCopyright",  "Copyright \251 2014 The OS/2 Museum"
+            VALUE "OriginalFilename","boxvideo.sys"
+            VALUE "ProductName",     "Sample Video Miniport"
+            VALUE "ProductVersion",  "1.3"
+        END
+
+    END
+
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0409, 0x04B0
+    END
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vidmini.inf	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,112 @@
+; vidmini.inf
+;
+; Installation INF for the vidmini graphics driver.
+;
+
+[Version]
+Signature = "$WINDOWS NT$"
+Provider  = %BOXV%
+ClassGUID = {4D36E968-E325-11CE-BFC1-08002BE10318}
+Class     = Display
+
+[DestinationDirs]
+DefaultDestDir    = 11
+vidmini.Miniport  = 12  ; drivers
+vidmini.Display   = 11  ; system32
+
+;
+; Driver information
+;
+
+[Manufacturer]
+%BOXV% = BOXV.Mfg
+
+[BOXV.Mfg]
+%BOXV% SVGA = vidmini, PCI\VEN_80EE&DEV_BEEF
+
+
+;
+; General installation section
+;
+
+[vidmini]
+CopyFiles = vidmini.Miniport, vidmini.Display
+
+;
+; File sections
+;
+
+[vidmini.Miniport]
+boxvideo.sys,,,0x100
+
+[vidmini.Display]
+; The framebuf display driver is shipped with and pre-installed by NT 4.
+; Note that earlier NT version shipped with framebuf.dll but didn't
+; pre-install it.
+
+;
+; Service (driver) Installation
+;
+
+[vidmini.Services]
+AddService = vidmini, 0x00000002, vidmini_Service_Inst, vidmini_EventLog_Inst
+
+[vidmini_Service_Inst]
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER
+StartType      = 1                  ; SERVICE_SYSTEM_START
+ErrorControl   = 0                  ; SERVICE_ERROR_IGNORE
+LoadOrderGroup = Video
+ServiceBinary  = %12%\boxvideo.sys
+
+[vidmini_EventLog_Inst]
+AddReg = vidmini_EventLog_AddReg
+
+[vidmini_EventLog_AddReg]
+HKR,,EventMessageFile,0x00020000,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\boxvideo.sys"
+HKR,,TypesSupported,0x00010001,7
+
+
+;
+; Software Installation
+;
+
+[vidmini.SoftwareSettings]
+AddReg = vidmini_SoftwareDeviceSettings                                                                                     
+
+[vidmini_SoftwareDeviceSettings]
+HKR,, InstalledDisplayDrivers, %REG_MULTI_SZ%, framebuf
+HKR,, VgaCompatible,           %REG_DWORD%,    0
+
+
+;
+; Source file information
+;
+
+[SourceDisksNames.x86]
+1 = %DiskId%,,,""
+
+[SourceDisksFiles]
+vidmini.sys  = 1
+; framebuf.dll = 1   ; already preinstalled by NT, no need to copy
+
+
+
+[Strings]
+
+;
+; Non-Localizable Strings
+;
+
+REG_SZ        = 0x00000000
+REG_MULTI_SZ  = 0x00010000
+REG_EXPAND_SZ = 0x00020000
+REG_BINARY    = 0x00000001
+REG_DWORD     = 0x00010001
+
+;
+; Localizable Strings
+;
+
+DiskId    = "BOXV Installation Disk"
+GraphAdap = "Graphics Adapter"
+BOXV      = "VirtualBox"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vidmpdat.c	Thu Jul 17 23:22:50 2014 +0200
@@ -0,0 +1,72 @@
+/*
+ * Video miniport static data.
+ */
+
+#include <miniport.h>
+#include <ntddvdeo.h>
+#include <video.h>
+#include "videomp.h"
+
+#if defined(ALLOC_PRAGMA)
+#pragma data_seg("PAGE")
+#endif
+
+/*
+ * Legacy resources claimed by the device.
+ *
+ *               RangeStart        RangeLength
+ *               |                 |      RangeInIoSpace
+ *               |                 |      |  RangeVisible
+ *         +-----+-----+           |      |  |  RangeShareable
+ *        low         high         |      |  |  |  RangePassive
+ *         v           v           v      v  v  v  v
+ */
+VIDEO_ACCESS_RANGE  LegacyRanges[] = {
+    { 0x000001CE, 0x00000000, 0x00000002, 1, 1, 1, 0 }, /* 0x1CE-0x1CF */
+    { 0x000003B0, 0x00000000, 0x0000000C, 1, 1, 1, 0 }, /* 0x3B0-0x3BB */
+    { 0x000003C0, 0x00000000, 0x00000020, 1, 1, 1, 0 }, /* 0x3C0-0x3DF */
+    { 0x000A0000, 0x00000000, 0x00020000, 0, 0, 1, 0 }  /* 0xA0000-0xBFFFF */
+};
+
+ULONG   ulNumLegacyRanges = sizeof( LegacyRanges ) / sizeof( VIDEO_ACCESS_RANGE );
+
+/* Define a resolution for all supported color depths. */
+#define MODE_RES( x, y )   \
+    { x, y, 8 }, { x, y, 15 }, { x, y, 16 }, { x, y, 24 }, { x, y, 32 }
+
+
+/* Table of supported modes. Note that the resolutions we can set are
+ * quite arbitrary, but there's no point in reporting a massive list. 
+ * All modes start out as unsupported and must be validated. 
+ */
+VIDEOMP_MODE    VideoModes[] = {
+    MODE_RES(  640,  480 ),
+    MODE_RES(  800,  600 ),
+    MODE_RES( 1024,  768 ),
+    MODE_RES( 1152,  864 ),
+    MODE_RES( 1280,  720 ),
+    MODE_RES( 1280,  800 ),
+    MODE_RES( 1280,  960 ),
+    MODE_RES( 1360,  768 ),
+    MODE_RES( 1360, 1024 ),
+    MODE_RES( 1366,  768 ),
+    MODE_RES( 1400, 1050 ),
+    MODE_RES( 1440,  900 ),
+    MODE_RES( 1600, 1200 ),
+    MODE_RES( 1680, 1050 ),
+    MODE_RES( 1920, 1080 ),
+    MODE_RES( 1920, 1200 ),
+    MODE_RES( 2048, 1152 ),
+    MODE_RES( 2048, 1536 ),
+    MODE_RES( 2560, 1600 )
+};
+
+ULONG   ulAllModes = sizeof( VideoModes ) / sizeof( VideoModes[0] );
+
+/* Video Port interface version. Needs to be global because DriverEntry can
+ * no longer pass context information to HwVidFindAdapter. */
+ULONG   PortVersion;
+
+#if defined( ALLOC_PRAGMA )
+#pragma data_seg()
+#endif