diff options
Diffstat (limited to 'private/mvdm/vdd/samples/sample2')
-rw-r--r-- | private/mvdm/vdd/samples/sample2/16bits/16bits.asm | 217 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/16bits/16bits.inc | 43 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/16bits/makefile | 42 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/dirs | 1 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/vdd/makefile | 11 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/vdd/sources | 23 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/vdd/vdd.c | 385 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/vdd/vdd.def | 6 | ||||
-rw-r--r-- | private/mvdm/vdd/samples/sample2/vdd/vdd.h | 67 |
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(); |