summaryrefslogtreecommitdiffstats
path: root/private/mvdm/vdd/samples/sample2
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/vdd/samples/sample2')
-rw-r--r--private/mvdm/vdd/samples/sample2/16bits/16bits.asm217
-rw-r--r--private/mvdm/vdd/samples/sample2/16bits/16bits.inc43
-rw-r--r--private/mvdm/vdd/samples/sample2/16bits/makefile42
-rw-r--r--private/mvdm/vdd/samples/sample2/dirs1
-rw-r--r--private/mvdm/vdd/samples/sample2/vdd/makefile11
-rw-r--r--private/mvdm/vdd/samples/sample2/vdd/sources23
-rw-r--r--private/mvdm/vdd/samples/sample2/vdd/vdd.c385
-rw-r--r--private/mvdm/vdd/samples/sample2/vdd/vdd.def6
-rw-r--r--private/mvdm/vdd/samples/sample2/vdd/vdd.h67
9 files changed, 795 insertions, 0 deletions
diff --git a/private/mvdm/vdd/samples/sample2/16bits/16bits.asm b/private/mvdm/vdd/samples/sample2/16bits/16bits.asm
new file mode 100644
index 000000000..093e69e91
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/16bits/16bits.asm
@@ -0,0 +1,217 @@
+ TITLE Sample 16 Bits DOS application
+;---------------------------------------------------------------;
+;
+ include 16bits.inc
+
+ DOSSEG
+ .MODEL SMALL
+
+ .STACK 100h
+
+ .DATA
+
+
+DMAWriteBuffer label byte
+ db 64 dup (?)
+DMA_BUFFER_SIZE equ $ - DMAWriteBuffer
+
+DMAReadBuffer label byte
+ db DMA_BUFFER_SIZE dup (?)
+
+MIOPattern label byte
+ db 00, 0FFh, 0AAh, 055h
+MIOPATTERN_SIZE equ $ - MIOPattern
+
+public start
+
+ .CODE
+start:
+ jmp short RealStart
+OldVector label dword
+ dd ?
+DMACompleted db ?
+
+RealStart:
+ mov ax,@DATA
+ mov ds,ax
+ mov es,ax
+ assume ds:@DATA, es:@DATA
+
+;Hook interrupt(DMA terminate count notification)
+ push ds
+ mov al, DMA_INTERRUPT
+ mov ah, 35h
+ int 21h
+ mov word ptr cs:OldVector, bx
+ mov word ptr cs:OldVector + 2, es
+ mov dx, offset ISRDMACompleted
+ mov ax, cs
+ mov ds, ax
+ mov al, DMA_INTERRUPT
+ mov ah, 25h
+ int 21h
+ pop ds
+
+
+;VDD operation.
+;(1). Hook the I/O port.
+;(2). Keep the port status up-to-date if a write operation is performed
+; by 16 bits application(this program).
+;(3). Simulate DMA operation and generate a fake interrupt for 16bits
+; applicatiion if the DMA operation reaches its TC.
+;
+;
+;16bits application
+;(1). Output one byte to the port and then request DMA operation.
+;(2). Wait for DMA operation completed.
+;(3). goto step (1) if there are more data to be transferred.
+;Note that the given I/O must be a R/W port.
+
+;Here we do a DMA write operation upon I/O mapped I/O
+ mov cx, DMA_BUFFER_SIZE
+ mov si, offset DMAWriteBuffer
+DMATransferLoop_Fast:
+ mov dx, IO_PORT_DMA
+ mov al, cl
+ out dx, al ;write I/O the current count
+ cli
+ mov cs:DMACompleted, FALSE ;reset TC flag
+ sti
+;channel #1, write op, no auto init, addr inc, single transfer
+ mov al, 01000101B
+ call SetupDMAOperation
+;Fire the DMA WRITE operation, this will cause VDD to gain control
+;and start DMA operation.
+ mov dx, IO_PORT_FIRE_DMA_FAST
+ out dx, al
+;In real world(there is a real hardware adapter), we won't do this
+;idle loop, rather, we can do something useful(like, read the DMA current
+;count and display the progress and so forth)provided that we can regain
+;control while DMA operation is in progress(VDD spawns a new thread to
+;handle DMA operation and returns to us immediately)
+;
+;Since we are simulating DMA operation without hardware, we always
+;start the DMA operation with transfer count set to 1 byte. In reality
+;this is should not be the case because it will slow down the data transfer.
+
+WaitForDMA_Fast:
+ cmp cs:DMACompleted, TRUE
+ jnz WaitForDMA_Fast
+ inc si
+ loop DMATransferLoop_Fast
+;
+;Now do a DMA read operation
+ mov cx, DMA_BUFFER_SIZE
+ mov si, offset DMAWriteBuffer
+ mov di, offset DMAReadBuffer
+DMATransferLoop_Slow:
+;channel #1, read op, no auto init, addr inc, single transfer
+ mov al, 01001001B
+ cli
+ mov cs:DMACompleted, FALSE
+ sti
+ call SetupDMAOperation
+;Fire the DMA READ operation
+ mov dx, IO_PORT_FIRE_DMA_SLOW
+ out dx, al
+WaitForDMA_Slow:
+ cmp cs:DMACompleted, TRUE
+ jne WaitForDMA_Slow
+ mov dx, IO_PORT_DMA
+ in al, dx
+ mov [di], al
+ inc di ;advance our buffer
+ inc si ;and the DMA buffer
+ loop DMATransferLoop_Slow
+;
+;The DMAWriteBuffer and DMAReadBuffer should have the same contents.
+;If they don't, it failed. ....
+
+
+;Memory mapped I/O
+ mov ax, MIO_SEGMENT
+ mov es, ax
+ mov bx, MIOPATTERN_SIZE
+ mov si, offset MIOPattern
+
+MIO_Loop:
+ cld
+ lodsb ;get next pattern
+ mov cx, MIO_PORT_RANGE
+ mov di, MIO_PORT_FIRST
+rep stosb ;fill all I/O with the pattern
+ mov cx, MIO_PORT_RANGE
+ dec di
+ std
+repe scasb ;
+ je @F
+; call ErrorMIO ;if any i/o failed,
+@@:
+ dec bx ;next pattern
+ jnz MIO_Loop
+
+;Before terminate, retsore everything we have touched
+ push ds
+ lds dx, cs:OldVector
+ mov al, DMA_INTERRUPT
+ mov ah, 25h
+ int 21h
+ pop ds
+ mov ah, 04Ch
+ int 21h
+
+;-------------------------------------------------------;
+;Setup DMA operation
+;Input: ds:si = seg:offset of memeory address
+; al = DMA mode
+;output: NONE
+;Modified: AX, DX
+;-------------------------------------------------------;
+SetupDMAOperation proc
+ push cx
+ mov dx, DMA_PORT_FLIPFLOP
+ out dx, al
+ mov dx, DMA_PORT_MODE ;more register
+ out dx, al
+ mov ax, ds ;transfer address -> page:offset
+ mov cl, 4 ;page: A16 ~ A19, offset A0 ~ A15
+ rol ax, cl
+ mov ch, al
+ and al, 0F0h
+ add ax, si
+ jnc @F
+ inc ch
+@@:
+ mov dx, DMA_PORT_ADDR
+ out dx, al ;offset lower byte
+ mov al, ah
+ out dx, al ;and higher byte
+ mov dx, DMA_PORT_PAGE ;page register
+ mov al, ch
+ and al, 0Fh ;only 4 bits allowed
+ out dx, al
+ mov al, 1 ;single transfer, one byte
+ mov dx, DMA_PORT_COUNT
+ out dx, al
+ dec al
+ out dx, al ;higher byte set to 0
+ mov dx, DMA_PORT_REQUEST ;request channel #1
+ mov al, 00000101B
+ out dx, al
+ mov dx, DMA_PORT_SNGLE_MASK ;start DMA transfer
+ mov al, 00000001B
+ out dx, al
+ pop cx
+ ret
+SetupDMAOperation endp
+
+
+ISRDMACompleted proc far
+ mov byte ptr DMACompleted, TRUE
+ mov al, 20h
+ out 20h, al
+ out 0A0h, al
+ iret
+ISRDMACompleted endp
+
+END start
diff --git a/private/mvdm/vdd/samples/sample2/16bits/16bits.inc b/private/mvdm/vdd/samples/sample2/16bits/16bits.inc
new file mode 100644
index 000000000..dd4fd0115
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/16bits/16bits.inc
@@ -0,0 +1,43 @@
+;---------------------------------------------------;
+; Include file for 16bits sample application
+; Copyright (C) 1992, Microsoft Corporation
+;---------------------------------------------------;
+
+TRUE equ 0FFh
+FALSE equ NOT(TRUE)
+
+;
+;I/O mapped I/O port equates
+;
+IO_PORT_FIRST equ 790h ;The first I/O port addr
+IO_PORT_LAST equ 793h ;The last I/O port addr
+IO_PORT_FIRE_DMA_SLOW equ IO_PORT_FIRST ;Port addr to trigger DMA
+IO_PORT_FIRE_DMA_FAST equ IO_PORT_FIRST + 1 ;port to trigger DMA
+IO_PORT_DMA equ IO_PORT_FIRST+2 ;port connnected to DMA channel
+;
+;Memory mapped I/O port equates ;segment address
+;
+MIO_SEGMENT equ 0C000h
+MIO_PORT_FIRST equ 0 ;The first port addr(offset)
+MIO_PORT_LAST equ 07 ;the last port addr(offset)
+MIO_PORT_RANGE equ MIO_PORT_LAST - MIO_PORT_FIRST + 1
+MIO_PORT_FIRE_DMA equ MIO_PORT_FIRST ;Port to trigger DMA
+MIO_PORT_DMA equ MIO_PORT_FIRST+1;port connected to DMA channel
+;
+;DMA equates
+;
+DMA_INTERRUPT equ 70h + 2 ;slave PIC, line #2(0 based)
+DMA_CHANNEL equ 01h ;DMA #1, channel #1(0 based)
+
+DMA_PORT_BASE equ 00
+DMA_PORT_PAGE equ 083h
+DMA_PORT_ADDR equ DMA_PORT_BASE + 2
+DMA_PORT_COUNT equ DMA_PORT_BASE + 3
+DMA_PORT_CMD equ DMA_PORT_BASE + 8
+DMA_PORT_REQUEST equ DMA_PORT_BASE + 9
+DMA_PORT_SNGLE_MASK equ DMA_PORT_BASE + 10
+DMA_PORT_MODE equ DMA_PORT_BASE + 11
+DMA_PORT_FLIPFLOP equ DMA_PORT_BASE + 12
+DMA_PORT_TEMP equ DMA_PORT_BASE + 13
+DMA_PORT_CLEARMASK equ DMA_PORT_BASE + 14
+DMA_PORT_WRTEMASK equ DMA_PORT_BASE + 15
diff --git a/private/mvdm/vdd/samples/sample2/16bits/makefile b/private/mvdm/vdd/samples/sample2/16bits/makefile
new file mode 100644
index 000000000..d394d22f1
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/16bits/makefile
@@ -0,0 +1,42 @@
+# Makefile for 16bits module of third part apps making bop calls
+#
+
+########## Path definition so we find 16 bit tools ##########
+# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be
+# in a directory that is greater than 128 chars down the path, even if
+# rc 3.1 is running as an OS/2 app.
+
+PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH)
+
+.SUFFIXES:
+.SUFFIXES: .c .obj .lst .exe .exc .exs .com .sal .cod .sil .inc .skl .cla .cl1 .ctl .asm .idx .msg
+
+MAKE =nmake
+asm =masm
+awarn =-W1
+aflags =-Mx -t $(awarn) $(extasw)
+ainc =-I.
+link_opts = /MAP
+LINK =link
+exelink =/E
+
+
+.asm.obj:
+ $(asm) $(ainc) $(aflags) $*.asm;
+
+.asm.lst:
+ $(asm) -l $(ainc) $(aflags) $*.asm;
+
+all: 16bits.exe
+
+clean:
+ if exist *.obj del *.obj
+ if exist *.exe del *.exe
+ if exist *.map del *.map
+ if exist *.sym del *.sym
+ if exist *.exe del *.exe
+
+16bits.exe: 16bits.obj
+ link16 $(link_opts) 16bits.obj, 16bits.exe, 16bits.map;
+
+16bits.obj: 16bits.inc
diff --git a/private/mvdm/vdd/samples/sample2/dirs b/private/mvdm/vdd/samples/sample2/dirs
new file mode 100644
index 000000000..19983aa36
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/dirs
@@ -0,0 +1 @@
+DIRS=vdd
diff --git a/private/mvdm/vdd/samples/sample2/vdd/makefile b/private/mvdm/vdd/samples/sample2/vdd/makefile
new file mode 100644
index 000000000..85f1ecf36
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/vdd/makefile
@@ -0,0 +1,11 @@
+# Sample VDD makefile
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+
+
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/mvdm/vdd/samples/sample2/vdd/sources b/private/mvdm/vdd/samples/sample2/vdd/sources
new file mode 100644
index 000000000..8622d9d42
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/vdd/sources
@@ -0,0 +1,23 @@
+INDENTED_DIRECTIVES=1
+
+MAJORCOMP=vdd
+MINORCOMP=vdd
+
+TARGETNAME=vdd
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntvdm.lib
+
+DLLENTRY=VDDInitialize
+DLLBASE=0x2000000
+
+INCLUDES=.
+
+SOURCES=vdd.c
+
+C_DEFINES=-DWIN_32 -DDEBUG
+
+UMTYPE=windows
+UMTEST=
+UMLIBS=
diff --git a/private/mvdm/vdd/samples/sample2/vdd/vdd.c b/private/mvdm/vdd/samples/sample2/vdd/vdd.c
new file mode 100644
index 000000000..53c22d2bb
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/vdd/vdd.c
@@ -0,0 +1,385 @@
+/*++
+ *
+ * VDD v1.0
+ *
+ * Copyright (c) 1991, Microsoft Corporation
+ *
+ * VDD.C - Sample VDD for NT-MVDM
+ *
+--*/
+
+#include "vdd.h"
+
+/** Global variables **/
+
+ HANDLE hVDD; /* VDD module handle */
+ HANDLE hVddHeap; /* VDD local heap */
+ PBYTE IOBuffer; /* buffer to simulate I/O Read and Write */
+ ULONG MIOAddress; /* memory mapped I/O linear address */
+ PVOID BaseAddress; /* memory mapped I/O virtual address */
+ BOOLEAN IOHook; /* true if we installed a I/O hooked */
+ BOOLEAN MIOHook; /* true if we installed a memory hook */
+ static VDD_IO_PORTRANGE PortRange;
+
+
+BOOL
+VDDInitialize(
+ HANDLE hVdd,
+ DWORD dwReason,
+ LPVOID lpReserved)
+
+/*++
+
+Routine Description:
+
+ The DllEntryPoint for the Vdd which handles intialization and termination
+
+Arguments:
+
+ hVdd - The handle to the VDD
+
+ Reason - flag word thatindicates why Dll Entry Point was invoked
+
+ lpReserved - Unused
+
+Return Value:
+ BOOL bRet - if (dwReason == DLL_PROCESS_ATTACH)
+ TRUE - Dll Intialization successful
+ FALSE - Dll Intialization failed
+ else
+ always returns TRUE
+--*/
+
+{
+ int i;
+ VDD_IO_HANDLERS IOHandlers;
+
+
+
+/**
+ keep a copy of VDD handle in global variable so the other functions
+ can see it
+**/
+ hVDD = hVdd;
+
+ switch ( dwReason ) {
+
+ case DLL_PROCESS_ATTACH:
+
+ // Allocate VDD's local heap
+ hVddHeap = HeapCreate(0, 0x1000, 0x10000);
+
+ if (!hVddHeap) {
+ OutputDebugString("VDD: Can't create local heap");
+ return FALSE;
+ }
+
+ IOBuffer = (PBYTE)HeapAlloc(hVddHeap,0,IO_PORT_RANGE);
+
+ if (!IOBuffer) {
+ OutputDebugString("VDD: Can't allocate IO buffer from heap");
+ HeapDestroy(hVddHeap);
+ return FALSE;
+ }
+
+ // communicate to appropriate Device driver about your arrival
+
+ // Set emulated I/O to floating
+ for (i = 0 ; i < IO_PORT_RANGE; i++)
+ IOBuffer[i] = FLOATING_IO;
+
+
+ IOHandlers.inb_handler = MyInB;
+ IOHandlers.inw_handler = NULL;
+ IOHandlers.insb_handler = NULL;
+ IOHandlers.insw_handler = NULL;
+ IOHandlers.outb_handler = MyOutB;
+ IOHandlers.outw_handler = NULL;
+ IOHandlers.outsb_handler = NULL;
+ IOHandlers.outsw_handler = NULL;
+ PortRange.First = IO_PORT_FIRST;
+ PortRange.Last = IO_PORT_LAST;
+
+ // hook I/O mapped I/O
+ IOHook = VDDInstallIOHook(hVDD, (WORD) 1, &PortRange, &IOHandlers);
+
+ // get 32 bits linear address of memory mapped I/O
+ MIOAddress = (ULONG) GetVDMPointer(MIO_ADDRESS, MIO_PORT_RANGE, 0);
+ // hook memory mapped I/O
+ MIOHook = VDDInstallMemoryHook(hVDD, (PVOID) MIOAddress, MIO_PORT_RANGE,
+ (PVDD_MEMORY_HANDLER)MyMIOHandler);
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ // communicate to appropriate Device driver about your departure
+ if (IOHook)
+ VDDDeInstallIOHook(hVDD, 1, &PortRange);
+ if (MIOHook) {
+ VDDDeInstallMemoryHook(hVDD, (PVOID) MIOAddress, MIO_PORT_RANGE);
+ if (BaseAddress) {
+ VDDFreeMem(BaseAddress, PAGE_SIZE, MEM_DECOMMIT);
+ }
+ }
+
+ // Deallocate VDD's local heap if needed
+ HeapDestroy(hVddHeap);
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+MyInB(
+WORD Port,
+PBYTE Buffer
+)
+
+{
+// Simply provide the data from our buffer
+ *Buffer = IOBuffer[Port - IO_PORT_FIRST];
+}
+
+VOID
+MyOutB(
+WORD Port,
+BYTE Data
+)
+
+{
+ // update our local buffer.
+ // In real application, the VDD might want to call its associated
+ // device driver to update the change.
+
+ IOBuffer[Port - IO_PORT_FIRST] = (BYTE)Data;
+
+ // If the IO port is the one to trigger DMA operation, do it
+ // To demonstarte the two options in handling DMA operation, we
+ // use two ports here to trigger different DMS operation schemes.
+
+ if (Port == IO_PORT_FIRE_DMA_FAST) {
+ FastDMA();
+ }
+ else {
+ if(Port == IO_PORT_FIRE_DMA_SLOW) {
+ SlowDMA();
+ }
+ }
+}
+
+
+VOID
+MyMIOHandler(
+ULONG Address, // faulting linear address
+ULONG RWFlags // 1 if write opertion, 0 if read
+)
+{
+
+ // map the memory for the memory mapped I/O so that we won't
+ // get page fault on our memory mapped I/O after this.
+ // We may reserve the memory during DLL_PROCESS_ATTACH (by using
+ // MEM_RESERVE rather than MEM_COMMIT we did here).
+ // The solution applied here is not the best solution(it is the
+ // simplest solution though). A better way to handle memory mapped
+ // I/O is to hook the page fault as we did here and decode the faulting
+ // instruction, simulate its operation and advance 16 bits application
+ // program counter(getIP and setIP).
+
+ BaseAddress = VDDAllocMem ((LPVOID) MIOAddress, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE);
+ if (!BaseAddress) {
+ OutputDebugString("VDD: Can't allocate virtual memory");
+ }
+}
+
+
+/** DMA operation support
+
+Facts:
+ - All DMA I/O ports are trapped and maintained by MVDM.
+ - VDD provides necessary buffers and calls its associated device
+ driver to carry out the real work(in this case, device driver
+ will perform real DMA operation with the buffer provided by
+ VDD as the source(DMA READ) or destination(DMA WRITE).
+ -The device driver has full knowledge of which I/O port(s) are
+ connectted to the DMA request channel.
+Therefore, the responsibilities of VDD are:
+ (1). Allocate necessary buffers
+ (2). if it is a DMA write operation(data from I/O to memory)
+ - calls device driver to perform the DMA operation with
+ newly allocated memory as the target buffer for DMA operation.
+ - calls MVDM DMA support routine to transfer data from
+ local buffer to 16bits application buffer.
+ - Simulate an interrupt to the 16 bits applications to notify
+ the completion.
+ if it is a DMA read operation(data from memory to I/O)
+ - calls MVDM DMA service to copy data from 16bits application
+ to the newly allocated buffer.
+ - calls the device driver to carry out DMA operation with
+ the allocated buffer as the source of the operation.
+ - Simulate an interrupt to the 16bits application to notify
+ the completion.
+The SlowDMA simulates a DMA READ operation by using VDDRequestDMA service.
+The FastDMA simulates a DMA WRITE operation by using VDDQueryDMA and VDDSetDMA
+services.
+
+** NOTE **
+We run the DMA in the same thread here so that before we return, there is no
+way for 16 bits application to regain control. In real world, it would
+be appropriate for VDDs to create a thread to do the actual DMA transfer
+(interactes with device driver) so that it won't block the 16bits
+application from running which will allow 16 bits application to provide
+useful information to the users(the application can read DMA registers and
+display the progress to the user and so forth)
+**/
+
+
+// This function perform DMA READ operation by using VDDRequestDMA service
+BOOLEAN
+SlowDMA()
+{
+ PBYTE DMABuffer, CurDMABuffer;
+ DWORD BufferLen;
+ DWORD PacketLen;
+
+ //first find out how big the buffer we need and then allocate
+ //the buffer from local heap.
+ //give 0 for buffer length to ask buffer length
+ //the length returned from VDDRequestDMA is the number of byte
+ //the DMA operation has to carry out. If the DMA channel is a 16bits
+ //the returned length will be 2 times the count value set to the
+ // DMA count register.
+
+ BufferLen = VDDRequestDMA(hVDD, DMA_CHANNEL, 0, 0);
+
+ CurDMABuffer = DMABuffer = (PBYTE)HeapAlloc(hVddHeap, 0, BufferLen);
+ if (!DMABuffer) {
+ OutputDebugString("VDD: Can't allocate heap memory for VDDRequestDMA");
+ return(FALSE);
+ }
+
+ // Since this is a DMA read operation(memory -> I/O), 16bits application
+ // should have provided necessary data in its local memory and the memory
+ // address can be derived from DMA base address register and page register.
+ // We don't want to deal with DMA register in this DMS operation scheme,
+ // therefore, we ask MVDM to copy the application data to our local buffer.
+ // It may be the case that applications requested a very big data transfer,
+ // 128K bytes for example, and we may not allocate enough buffer from our
+ // local heap. To overcome the problem, we have to break the data transfer
+ // to multiple subblocks and transfer each subblock by calling our device
+ // driver. Here we assume we can get the enough buffer from local heap.
+ //
+ // The device driver should take care of 64k wrap problem of DMA operation.
+
+ BufferLen = VDDRequestDMA(hVDD, DMA_CHANNEL, CurDMABuffer, BufferLen);
+
+ // MVDM updates DMA registers on each VDDReauestDMA. Therefore, after we
+ // made this call, the DMA registers maintained by MVDM have been set
+ // to the states as the DMA operation has been done(and it is not yet).
+ // It may be the case that the 16bits application regains control(as we
+ // create a different thread to do the operation) and issues another
+ // DMA operation before we(and the device driver) complete the current
+ // DMA operation. Keep away from using global variables in this
+ // case.
+
+ // We have source data in our local buffer, time to ask device
+ // driver to transfer the data to I/O. In case that the device driver
+ // can not transfer the whole buffer in a single service call, we
+ // call the device driver repeatly until we consume the entire buffer
+
+ while( BufferLen > 0) {
+ PacketLen = FakeDD_DMARead(CurDMABuffer, (WORD)BufferLen);
+ CurDMABuffer += PacketLen;
+ BufferLen -= PacketLen;
+ }
+
+
+ // DMA transfer completed; we simulate an interrupt to the 16bits
+ // application. Note that the DMA I/O ports should have been set
+ // accordingly by MVDM(through VDDReauestDMA).
+ // A real VDD may not do thing this way(VDD has to wait for device
+ // driver to finish the data transfer before returning to 16bits application
+ // Instead, the VDD and its associated device driver can keep synchronized
+ // by using semaphore or other events so that they can keep running in
+ // parallel and when receiving a event signal(triggered by the device driver to
+ // to notify completion of DMA operation) the VDD can then simulate the
+ // interrupt to the 16bits application
+
+ VDDSimulateInterrupt(DMA_INTERRUPT_PIC, DMA_INTERRUPT_LINE, 1);
+ HeapFree(hVddHeap, 0, DMABuffer);
+ return (TRUE);
+
+}
+
+ // This function simulate a DMA write(I/O to memory) operation
+ // It uses VDDQueryDMA and VDDSetDMA services to gain speed
+
+BOOLEAN
+FastDMA()
+{
+ ULONG DMAAddress;
+ DWORD Size, PacketLen;
+
+ VDD_DMA_INFO DMAInfo;
+
+ // Get the current DMA registers setting
+ VDDQueryDMA(hVDD, DMA_CHANNEL, &DMAInfo);
+
+ // if the DMA channel is not 1 16bits channel, adjust the size
+ Size = (DMAInfo.count << DMA_SHIFT_COUNT);
+
+ // seg:off of the DMA transfer address
+ DMAAddress = (((ULONG)DMAInfo.page) << (12 + 16))
+ + (DMAInfo.addr >> DMA_SHIFT_COUNT);
+
+ // Get DMA transfer 32bits linear address
+ DMAAddress = (ULONG) GetVDMPointer(DMAAddress, Size, 0);
+
+ while(Size) {
+ PacketLen = FakeDD_DMAWrite((PBYTE)DMAAddress, (WORD)Size);
+ DMAAddress += PacketLen;
+ Size -= PacketLen;
+ DMAInfo.addr += PacketLen;
+ DMAInfo.count -= (PacketLen >> DMA_SHIFT_COUNT);
+
+ // We have to upate the DMA registers even though we are not done
+ // the transfer yet. It is a good practice to update the DMA
+ // register each time we have really transferred data so that
+ // if the 16bits application regains control before DMA operation
+ // totally completed, it can get the partial result states and
+ // report to users.
+
+ VDDSetDMA(hVDD, DMA_CHANNEL, VDD_DMA_ADDR | VDD_DMA_COUNT,
+ &DMAInfo);
+ }
+
+ // see note on SlowDMA
+ VDDSimulateInterrupt(DMA_INTERRUPT_PIC, DMA_INTERRUPT_LINE, 1);
+ return(TRUE);
+}
+
+ // This function is a fake service which should be provided by device
+ // drivers in the real world. The thing we do here is to simulate
+ // a DMA operation transferring data from the given buffer to
+ // to the pre-defined memory mapped I/O port(DMA READ).
+
+WORD FakeDD_DMARead(PBYTE Buffer, WORD Size)
+{
+ IOBuffer[IO_PORT_DMA - IO_PORT_FIRST] = Buffer[0];
+ return (1);
+}
+
+ //This function calls device driver services to start DMA operation
+ //and requests the device driver to write the data to the given buffer.
+ //Since we are simulating the operation, we simply fill the buffer by
+ //reading the predefined I/O port
+
+WORD FakeDD_DMAWrite(PBYTE Buffer, WORD Size)
+{
+ *Buffer = IOBuffer[IO_PORT_DMA - IO_PORT_FIRST];
+ return(1);
+}
diff --git a/private/mvdm/vdd/samples/sample2/vdd/vdd.def b/private/mvdm/vdd/samples/sample2/vdd/vdd.def
new file mode 100644
index 000000000..d4bfcb805
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/vdd/vdd.def
@@ -0,0 +1,6 @@
+LIBRARY VDD
+
+DESCRIPTION 'Sample ISV VDD for NT-MVDM'
+
+EXPORTS
+ VDDInitialize
diff --git a/private/mvdm/vdd/samples/sample2/vdd/vdd.h b/private/mvdm/vdd/samples/sample2/vdd/vdd.h
new file mode 100644
index 000000000..fca8b1871
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/vdd/vdd.h
@@ -0,0 +1,67 @@
+/* vdd.h - main include file for the VDD
+ *
+ */
+
+
+#include "windows.h"
+
+// VDD services header
+#include <vddsvc.h>
+
+// private macro definitions
+
+
+#define PAGE_SIZE 0x1000
+/*disconnected I/O value */
+#define FLOATING_IO 0xFF
+#define FLOATING_MIO 0xFF
+
+// I/O mapped I/O
+#define IO_PORT_FIRST 0x790
+#define IO_PORT_LAST 0x793
+#define IO_PORT_FIRE_DMA_SLOW IO_PORT_FIRST
+#define IO_PORT_FIRE_DMA_FAST IO_PORT_FIRST + 1
+#define IO_PORT_DMA IO_PORT_FIRST + 2
+#define IO_PORT_RANGE IO_PORT_LAST - IO_PORT_FIRST + 1
+
+// memory mapped I/O
+#define MIO_SEGMENT 0xC000
+#define MIO_PORT_FIRST 0
+#define MIO_PORT_LAST 7
+#define MIO_PORT_FIRE_DMA MIO_PORT_FIRST
+#define MIO_PORT_DMA MIO_PORT_FIRST + 1
+#define MIO_PORT_RANGE MIO_PORT_LAST - MIO_PORT_FIRST + 1
+#define MIO_ADDRESS ((((ULONG)MIO_SEGMENT) << 16) | MIO_PORT_FIRST)
+
+// DMA
+#define DMA_CHANNEL 1
+#define DMA_PORT_BASE 0
+#define DMA_SHIFT_COUNT 0
+#define DMA_INTERRUPT_LINE 2
+#define DMA_INTERRUPT_PIC ICA_SLAVE
+#define DMA_PORT_PAGE 0x83
+#define DMA_PORT_ADDR DMA_PORT_BASE + 2
+#define DMA_PORT_COUNT DMA_PORT_BASE + 3
+#define DMA_PORT_CMD DMA_PORT_BASE + 8
+#define DMA_PORT_REQUEST DMA_PORT_BASE + 9
+#define DMA_PORT_SNGLE_MASK DMA_PORT_BASE + 10
+#define DMA_PORT_MODE DMA_PORT_BASE + 11
+#define DMA_PORT_FLIPFLOP DMA_PORT_BASE + 12
+#define DMA_PORT_TEMP DMA_PORT_BASE + 13
+#define DMA_PORT_CLEARMASK DMA_PORT_BASE + 14
+#define DMA_PORT_WRTEMASK DMA_PORT_BASE + 15
+
+
+/* function prototype definitions */
+
+/* entry function of VDD */
+BOOL VddDllEntry(HANDLE hVdd, DWORD dwReason, LPVOID lpReserved);
+
+/* private functions */
+VOID MyInB(WORD, PBYTE);
+VOID MyOutB(WORD, BYTE);
+VOID MyMIOHandler(ULONG, ULONG);
+WORD FakeDD_DMARead(PBYTE, WORD);
+WORD FakeDD_DMAWrite(PBYTE, WORD);
+BOOLEAN SlowDMA();
+BOOLEAN FastDMA();