summaryrefslogtreecommitdiffstats
path: root/private/mvdm/vdd/vddserv.doc
blob: 175fa7b7f228e82e4ec4c7e042009366d0b43c71 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791


Installable Virtual Device Driver (VDD) Support For NTVDM
==========================================================

Problem:
--------
There is a class of DOS applications which run on their
own custom hardware. Generally these applications will
have a pluggable card and a 16bit device driver for their
card. As these cards are beyond the scope of normal PC
architecture, NTVDM cannot virtualize them in a secure
manner. So all such applications are not supported under
NTVDM.

Solution:
---------

If an ISV is writing an NT native device driver for such a
card, it is technically quite simple to provide the support
such that the DOS application runs unmodified and in a secure
fashion. The vendor has to write a Virtual Device Driver (VDD)
which will virtualize the card for the DOS application by calling
the native device driver.


	    -----------------------
	    |			  |
	    |	DOS Application	  |	  V86 mode
	    |			  |
	    -----------------------
      I/O-map |	 ^     |Mem-Map	| DMA
      IO      |	 |     |IO	|
    -------------|-----------------------------
	      |  |     |	|
	      V  |     V	V
	    -----------------------
	    |		   | DMA  |
	    |	    NTVDM  -------|	  NT User mode code
	    |			  |
	    -----------------------
		 ^     |
		 |     | Dispatches the event to VDD
		 |     V
	    -----------------------
	    |			  |
	    |	     VDD	  |	  VDD is a DLL attached to NTVDM
	    |			  |
	    -----------------------
		 ^     |
		 |     | Call the real driver
    -------------|-----------------------------
		 |     |
		 |     V
	    -----------------------
	    |			  |
	    |  NT Device Driver	  |	  Kernel mode
	    |			  |
	    -----------------------
		 ^     |
		 |     | Carries out the operation with its card
		 |     V
	    -----------------------
	    |			  |
	    |	 Plugged Card	  |
	    |			  |
	    -----------------------

Following are the main work items to achieve the above solution:

    a. Loading the VDD
    b. Support for I/O mapped I/O
    c. Support for Memory mapped I/O
    d. Support for DMA operations
    e. Register manipulation services
    f. Memory accessing services
    g. Interrupt simulation services
    h. Miscelleneous services


a. Loading the VDD:

    The system administrator will add the command lines in the
    \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\CONTROL\"VirtualDeviceDrivers"
    section of the registry for all the VDDs to be loaded in the
    VDM process. The command line format is REG_MULT_SZ (i.e. ASCIIZZ).
    This key will laways be present and install program just need to
    add their VDD name.

    [VirtualDeviceDrivers]
      VDD = <full-path of the VDD1.DLL>\0<full-path of the VDD2>\0\0

    VDD ACTION :

    NTVDM will load all these VDDs from the registry at the VDM process
    initialization time and call their initialization routine. VDDs should
    make sure at this time that their respective NT device driver is
    present and make all the resource allocations. The VDD handle passed
    in this initialization routine will be the Id of the VDD when calling
    the VDD services as described below.


b. Support for I/O mapped I/O:

   Following services will be provided for VDDs to deal with  IO
   ports:

   BOOL VDDInstallIOHook (HANDLE, IO_PORT_RANGE, IO_PORT_HANDLERS);
   BOOL VDDDeInstallIOHook (HANDLE, IO_PORT_RANGE);

   The HANDLE is the one passed to the VDD in its DLLInit routine.
   Only one IO hook may be installed for a given port, all subsequent
   requests will fail. On DeInstalling, the default IO hook will be
   placed, which means no one is hooked on those IO ports. IO_PORT_HANDLERS
   should atleast provide a byte read and a byte write handler. In addition,
   word and string handlers can also be provided. In the absense of word
   or string handlers, these will be emulated using byte handlers.
   A port has to be hooked for both read and write. VDDs should not hook
   DMA ports as these are virtualized by NTVDM and services are provided
   for VDDs to access DMA.

   VDD Action:  On an IO access (or on a series of IO accesses) the VDD
                can check if it needs to start the DMA. If so it can call
                the DMA services given in the following section. If it
                does'nt require the DMA or if the DMA has transfered the
                buffer, then the VDD can call its NT device driver to
                complete the desired request. (Its also possible that the
                VDD first requests the device driver and than using DMA
                services copies the contents to the VDM buffer).


c. Support for Memory mapped I/O:

   Following services will be  provided for VDDs to deal with their
   memory mapped addresses:

   BOOL VDDInstallMemoryHooks (HANDLE, ADDR_RANGE, MEMORY_HANDLER);
   BOOL VDDDeInstallMemoryHooks (HANDLE, ADDR_RANGE);

   The addr_range should be a valid range i.e. above RMSIZE and below system
   rom. Only one Memory hook may be installed for a given range, all subsequent
   requests will fail. On deinstalling the range, VDD will no longer get page
   fault on those ranges.     Memory_handler will
   tell on which address the fault occured and whether it was a
   read or write fault. On its return from the memory handler it will be
   assumed that the fault was handled.


   A port-range will actually result in a whole page to be reserved. That
   means the page will not remain available to EMM for EMM page frames and
   UMBs.

   VDD Action: It can map the normal memory and let the app write to it.
	       Later they can use the WIN32 API's or its device driver
	       as per the case to deal the whole memory range.

d. Support for DMA operations

   Following DMA service will be provided for the VDD:

   DWORD VDDRequestDMA (HANDLE, DMA_CHANNEL, BUFFER, TRANSFER_BYTES);
   BOOL VDDQueryDMA (HANDLE, DMA_CHANNEL, DMA_INFO_BUFFER);
   BOOL VDDSetDma (HANDLE, DMA_CHANNEL, INDEX, DMA_INFO_BUFFER);

   NTVDM will control all the DMA ports and will maintain all the
   information on per channel basis. There are two flavors in which
   a VDD can carry-out the DMA operations. It can call VDDRequestDMA
   and this service will interpret the DMA registers and do the
   DMA transfer. It should be clear at this point that this will
   involve two buffer copyings. For example, the VDD will ask the device
   driver to trasnfer some data in a buffer (allocated by VDD) then it will
   call this service to transfer this buffer to the address DOS application
   has asked for (through DMA programming).

   On the other hand, a VDD can collect all the DMA registers using
   VDDQueryDMA and figure out where the DOS application	has asked the
   DMA to take place, in what mode and how much to transfer. Then it can
   call the NT device driver with same address as asked by DOS app. In this
   case there will be only one copying. VDD should use VDDSetDMA after
   such an operation to update the DMA state.

e. Register manipulation services:

   See the reference section for details. There is a get and a set service
   for each V86 registers.


f: Memory Accessing services:

   Following services are provided for Manipulating VDM's memory.

   PVOID GetVDMPointer(ULONG Address, ULONG Size, BOOL ProtectedMode);
   BOOL	FreeVDMPointer(ULONG Address, ULONG Size, BOOL ProtectedMode);
   BOOL	FlushVDMPointer(ULONG Addr,
			ULONG Size, PVOID Buffer, BOOL ProtectedMode);

g: Interrupt simulation services

   Following services is provided for simulating an interrupt to the VDM.

   VOID VDDSimulateInterrupt (BYTE ms, BYTE line, WORD count);


h. Miscellaneous Services

   Following services will be provided for memory allocation/deallocation.

   VDDAllocMem (HANDLE, ADDRESS, PAGES);
   VDDFreeMem  (HANDLE, ADDRESS, PAGES);

   VDD will use VDDAllocMem when it gets a page fault on a page which
   it has hooked using VDDInstallMemoryHook. Later it can free this memory
   using VDDFreeMem. We are asking VDDs to use WIN32 API for all their needs
   and here also a VDD could have used VirtualAlloc and VirtualFree. The
   problem is that on a non-x86 machine this would'nt have worked because
   on such a plateform the VDM memory is under the emulator's control and it
   has to be told of such memory changes.

   Following service will be provided for VDM termination.

   VDDTerminateVDM (VOID);

   VDD will use this service to terminate the VDM. For instance if a VDD
   fails to allocate memory on a memory mapped IO, it may want to terminate
   the VDM as its state is inconsistenet.

   VDDs should always use these services to achieve plateform independence.



---------------- REFERENCE SECTION -------------------------

/** Basic typedefs of VDD IO hooks **/

typedef VOID (*PFNVDD_INB)   (WORD iport,BYTE * data);
typedef VOID (*PFNVDD_INW)   (WORD iport,WORD * data);
typedef VOID (*PFNVDD_INSB)  (WORD iport,BYTE * data,WORD count);
typedef VOID (*PFNVDD_INSW)  (WORD iport,WORD * data,WORD count);
typedef VOID (*PFNVDD_OUTB)  (WORD iport,BYTE data);
typedef VOID (*PFNVDD_OUTW)  (WORD iport,WORD data);
typedef VOID (*PFNVDD_OUTSB) (WORD iport,BYTE * data,WORD count);
typedef VOID (*PFNVDD_OUTSW) (WORD iport,WORD * data,WORD count);

/**  Array of handlers for VDD IO hooks. **/

typedef struct _VDD_IO_HANDLERS {
    PFNVDD_INB	 inb_handler;
    PFNVDD_INW	 inw_handler;
    PFNVDD_INSB	 insb_handler;
    PFNVDD_INSW	 insw_handler;
    PFNVDD_OUTB	 outb_handler;
    PFNVDD_OUTW	 outw_handler;
    PFNVDD_OUTSB outsb_handler;
    PFNVDD_OUTSW outsw_handler;
} VDD_IO_HANDLERS, *PVDD_IO_HANDLERS;

/** Port Range structure **/
typedef struct _VDD_IO_PORTRANGE {
        WORD   First;
        WORD   Last;
} VDD_IO_PORTRANGE, *PVDD_IO_PORTRANGE;

/**  Memory mapped I/O handler. **/

typedef VOID (*PVDD_MEMORY_HANDLER) (PVOID FaultAddress, ULONG RWMode);

/** Buffer for returning DMA information **/
typedef struct _VDD_DMA_INFO {
    WORD    addr;
    WORD    count;
    WORD    page;
    BYTE    status;
    BYTE    mode;
    BYTE    mask;
} VDD_DMA_INFO, *PVDD_DMA_INFO;

/*** VDDInstallIOHook - This service is provided for VDDs to hook the
 *			IO ports they are responsible for.
 *
 * INPUT:
 *      hVDD      ; VDD Handle
 *      cPortRange; Number of VDD_IO_PORTRANGE structures
 *      pPortRange; Pointer to array of VDD_IO_PORTRANGE
 *	IOhandler : VDD handler for the ports.
 *
 * OUTPUT
 *	SUCCESS : Returns TRUE
 *	FAILURE : Returns FALSE
 *		  GetLastError has the extended error information.
 *
 * NOTES:
 *      1. The first one to hook a port will get control. Subsequent
 *         requests will be failed. There is no concept of chaining
 *         the hooks.
 *
 *	2. IOHandler must atleast provide a byte read and a byte write
 *	   handler. Others can be NULL.
 *
 *	3. If word or string handlers are not provided, their effect
 *	   will be emulated using byte handlers.
 *
 *	4. VDDs should not hook DMA ports. NTVDM manages it for all
 *	   the clients and services are provided to perform DMA
 *	   operations and to access and modify DMA data.
 *
 *	5. VDDs should not hook video ports as well. Such a hooking
 *	   will succeed but there is no gurantee that the IO handler will
 *         get called.
 *
 *      6. Each Vdd is allowed to install only one set of IO hooks
 *         at a time.
 *
 *      7. Extended Error codes:
 *
 *         ERROR_ACCESS_DENIED   - One of the requested ports is already hooked
 *         ERROR_ALREADY_EXISTS  - Vdd already has active IO port handlers
 *         ERROR_OUTOFMEMORY     - Insufficient resources for additional VDD
 *                                 Port handler set.
 *         ERROR_INVALID_ADDRESS - One of the IO port handlers has an invalid
 *                                 address.
 */
BOOL VDDInstallIOHook (
     HANDLE            hVdd,
     WORD              cPortRange,
     PVDD_IO_PORTRANGE pPortRange,
     PVDD_IO_HANDLERS  pIOFn
);

/*** VDDDeInstallIOHook - This service is provided for VDDs to unhook the
 *			  IO ports they have hooked.
 *
 * INPUT:
 *	hVDD	: VDD Handle
 *
 * OUTPUT
 *	None
 *
 * NOTES
 *
 *	1. On Deinstalling a hook, the defult hook is placed back on
 *	   those ports. Default hook  returns 0xff on reading
 *	   and ignores the write operations.
 *
 */
VOID VDDDeInstallIOHook (
     HANDLE            hVdd,
     WORD              cPortRange,
     PVDD_IO_PORTRANGE pPortRange
);

/*** VDDInstallMemoryHook - This service is provided for VDDs to hook the
 *			    Memory Mapped IO addresses they are resposible
 *			    for.
 *
 * INPUT:
 *	hVDD	: VDD Handle
 *      addr    : Starting linear address
 *      count   : Number of bytes
 *	MemoryHandler : VDD handler for the memory addresses
 *
 *
 * OUTPUT
 *	SUCCESS : Returns TRUE
 *	FAILURE : Returns FALSE
 *		  GetLastError has the extended error information.
 *
 * NOTES
 *	1. The first one to hook an address will get the control. There
 *	   is no concept of chaining the hooks. VDD should grab the
 *	   memory range in its initialization routine. After all
 *	   the VDDs are loaded, EMM will eat up all the remaining
 *	   memory ranges for UMB support.
 *
 *	2. Memory handler will be called with the address on which the
 *	   page fault occured and with a falg telling whether it was a
 *	   read or write operation.
 *
 *	3. On returning from the hook handler it will be assumed that
 *	   the page fault was handled and the return will go back to the
 *	   VDM.
 *
 *	4. Installing a hook on a memory range will result in the
 *         consumption of memory based upon page boundaries. The Starting
 *         address is rounded down, and the count is rounded up to the
 *         next page boundary. The VDD's memory hook handler will be
 *         invoked for all addreses within the page(s) hooked. The page(s)
 *         will be set aside as mapped reserved sections, and will no
 *         longer be available for use by NTVDM or other VDDs. The VDD is
 *         permitted to manipulate the memory (commit, free, etc) as needed.
 *
 *	5. After calling the MemoryHandler, NTVDM will return to the
 *	   faulting cs:ip in the 16bit app. If the VDD does'nt want
 *	   that to happen it should adjust cs:ip appropriatly by using
 *	   setCS and setIP.
 *
 *	6. Only one VDD will be allowed to have memory hooks in a page.
 *	   In other words a page si owned by a VDD exclusively.
 *
 *	7. Extended Error codes:
 *
 *         ERROR_ACCESS_DENIED   - One of the requested ports is already hooked
 *	   ERROR_OUTOFMEMORY	 - Insufficient resources.
 */
BOOL VDDInstallMemoryHook (
     HANDLE hVDD,
     PVOID pStart,
     DWORD count,
     PVDD_MEMORY_HANDLER MemoryHandler
);

/*** VDDDeInstallMemoryHook - This service is provided for VDDs to unhook the
 *			      Memory Mapped IO addresses.
 *
 * INPUT:
 *	hVDD	: VDD Handle
 *	addr	: Starting linear address
 *	count	: Number of addresses
 *
 * OUTPUT
 *	None
 *
 * NOTES
 *	1. On Deinstalling a hook, the memory range becomes invalid.
 *	   VDM's access of this memory range will cause a page fault.
 *
 *	2. Extended Error codes:
 *	   ERROR_INVALID_PARAMETER - One of the parameter is invalid.
 */
BOOL VDDDeInstallMemoryHook (
     HANDLE hVDD,
     PVOID pStart,
     DWORD count
);

/*** VDDRequestDMA - This service is provided for VDDs to request a DMA
 *		     transfer.
 *
 * INPUT:
 *	hVDD	 VDD Handle
 *	iChannel DMA Channel on which the operation to take place
 *	Buffer	 Buffer where to or from transfer to take place
 *      length   Transfer Count (in bytes)
 *               If Zero, returns the Current VDMA transfer count
 *               in bytes.
 *
 * OUTPUT
 *      DWORD    returns bytes transferred
 *		 if Zero  and GetLastError is set means operation failed.
 *		 if Zero  and GetLastError is clear means VDMA transfer count
 *					   was zero.
 *
 * NOTES
 *	1. This service is intended for those VDDs which do not want to
 *	   carry on the DMA operation on their own. Carrying on a DMA
 *	   operation involves understanding all the DMA registers and
 *	   figuring out what has to be copied, from where and how much.
 *
 *	2. This service will be slower than using VDDQueryDMA/VDDSetDMA and
 *         doing the transfer on your own.
 *
 *      3. Extended Error codes:
 *
 *         ERROR_ALREADY_EXISTS  - Vdd already has active IO port handlers
 *         ERROR_OUTOFMEMORY     - Insufficient resources for additional VDD
 *                                 Port handler set.
 *         ERROR_INVALID_ADDRESS - One of the IO port handlers has an invalid
 *                                 address.
 *
 */
DWORD VDDRequestDMA (
    HANDLE hVDD,
    WORD   iChannel,
    PVOID  Buffer,
    DWORD  length
);

/*** VDDQueryDMA -   This service is provided for VDDs to collect all the DMA
 *		     data.
 *
 * INPUT:
 *	hVDD	 VDD Handle
 *	iChannel DMA Channel for which to query
 *	Buffer	 Buffer where information will be returned
 *
 * OUTPUT
 *	SUCCESS : Returns TRUE
 *	FAILURE : Returns FALSE
 *		  GetLastError has the extended error information.
 *
 *
 * NOTES
 *	1. This service is intended for those VDD which are doing
 *	   performance critical work. These VDD can do their own DMA
 *	   transfers and avoid one extra buffer copying which is a
 *	   overhead in using VDDRequestDMA.
 *
 *	2. VDDs should use VDDSetDMA to properly update the state of
 *         DMA after carrying on the operation.
 *
 *      3. Extended Error codes:
 *
 *         ERROR_INVALID_ADDRESS - Invalid channel
 *
 */
BOOL VDDQueryDMA (
     HANDLE        hVDD,
     WORD          iChannel,
     PVDD_DMA_INFO pDmaInfo
);

/*** VDDSetDMA - This service is provided for VDDs to set the DMA data.
 *
 * INPUT:
 *	hVDD	 VDD Handle
 *	iChannel DMA Channel for which to query
 *      fDMA     Bit Mask indicating which DMA data fields are to be set
 *		 VDD_DMA_ADDR
 *		 VDD_DMA_COUNT
 *		 VDD_DMA_PAGE
 *		 VDD_DMA_STATUS
 *		 VDD_DMA_ALL  (all Above)
 *	Buffer	 Buffer with DMA data
 *
 * OUTPUT
 *	SUCCESS : Returns TRUE
 *	FAILURE : Returns FALSE
 *		  GetLastError has the extended error information.
 *
 * NOTES
 *
 *      1. Extended Error codes:
 *
 *         ERROR_INVALID_ADDRESS - Invalid channel
 *
 */
BOOL VDDSetDMA (
    HANDLE hVDD,
    WORD iChannel,
    WORD fDMA,
    PVDD_DMA_INFO pDmaInfo
);

/** VDDAllocMem - Allocates memory at a given virtual address.
 *
 *   INPUT
 *	hVDD   : VDD
 *	Address: Address where memory is to be allocated (between 640k and 1Mb)
 *	nBytes : Number of bytes to allocate
 *
 *   OUTPUT
 *	SUCCESS : Returns TRUE
 *	FAILURE : Returns FALSE
 *		  GetLastError has the extended error information.
 * Notes:
 *	1. VDDs have to use this service instead of WIN32 VirtualAlloc
 *	   to be plateform independent. On non-x86 machines VDDAllocMem
 *	   tells the CPU emulator about this memory allocation.
 *
 *	2. The address will be made page aligned downwards and nBytes will
 *	   be streched upward to be page aligned.
 *
 *	3. Extended Error codes:
 *	   ERROR_OUTOFMEMORY	 - Insufficient memory
 *	   ERROR_INVALID_ADDRESS - Invalid address
 */
VOID VDDAllocMem (
     HANDLE hVDD,
     PVOID  Address,
     ULONG  nBytes
);

/** VDDFreeMem - Free memory at a given virtual address.
 *
 *   INPUT
 *	hVDD   : VDD
 *	Address: Address where memory is to be freed
 *	nBytes : Number of bytes to free
 *
 *   OUTPUT
 *	SUCCESS : Returns TRUE
 *	FAILURE : Returns FALSE
 *		  GetLastError has the extended error information.
 *
 * Notes:
 *      1. Extended Error codes:
 *	   ERROR_INVALID_ADDRESS - Invalid address
 *
 *	2. The address will be made page aligned downwards and nBytes will
 *	   be streched upward to be page aligned.
 *
 */
VOID VDDFreeMem (
     HANDLE hVDD,
     PVOID  Address,
     ULONG  nBytes
);

/** VDDTerminateVDM - Terminate the VDM.
 *
 *   INPUT
 *	None
 *
 *   OUTPUT
 *	None
 *
 * Notes:
 *	1. VDD should call this service on encoutering a fatal error,
 *	   such that VDDs state is inconsistent.
 *
 *	2. VDD can use MessageBox WIN32 API to putup a popup before
 *	   terminating the VDM.
 */
VOID VDDTerminateVDM (
     VOID
);

/**  Register Manipulation services
 *
 */

ULONG	getEAX(VOID);
USHORT	getAX(VOID);
UCHAR	getAL(VOID);
UCHAR	getAH(VOID);
ULONG	getEBX(VOID);
USHORT	getBX(VOID);
UCHAR	getBL(VOID);
UCHAR	getBH(VOID);
ULONG	getECX(VOID);
USHORT	getCX(VOID);
UCHAR	getCL(VOID);
UCHAR	getCH(VOID);
ULONG	getEDX(VOID);
USHORT	getDX(VOID);
UCHAR	getDL(VOID);
UCHAR	getDH(VOID);
ULONG	getESP(VOID);
USHORT	getSP(VOID);
ULONG	getEBP(VOID);
USHORT	getBP(VOID);
ULONG	getESI(VOID);
USHORT	getSI(VOID);
ULONG	getEDI(VOID);
USHORT	getDI(VOID);
ULONG	getEIP(VOID);
USHORT	getIP(VOID);
USHORT	getCS(VOID);
USHORT	getSS(VOID);
USHORT	getDS(VOID);
USHORT	getES(VOID);
USHORT	getFS(VOID);
USHORT	getGS(VOID);
ULONG	getCF(VOID);
ULONG	getPF(VOID);
ULONG	getAF(VOID);
ULONG	getZF(VOID);
ULONG	getSF(VOID);
ULONG	getIF(VOID);
ULONG	getDF(VOID);
ULONG	getOF(VOID);
USHORT	getMSW(VOID);

VOID	setEAX(ULONG);
VOID	setAX(USHORT);
VOID	setAH(UCHAR);
VOID	setAL(UCHAR);
VOID	setEBX(ULONG);
VOID	setBX(USHORT);
VOID	setBH(UCHAR);
VOID	setBL(UCHAR);
VOID	setECX(ULONG);
VOID	setCX(USHORT);
VOID	setCH(UCHAR);
VOID	setCL(UCHAR);
VOID	setEDX(ULONG);
VOID	setDX(USHORT);
VOID	setDH(UCHAR);
VOID	setDL(UCHAR);
VOID	setESP(ULONG);
VOID	setSP(USHORT);
VOID	setEBP(ULONG);
VOID	setBP(USHORT);
VOID	setESI(ULONG);
VOID	setSI(USHORT);
VOID	setEDI(ULONG);
VOID	setDI(USHORT);
VOID	setEIP(ULONG);
VOID	setIP(USHORT);
VOID	setCS(USHORT);
VOID	setSS(USHORT);
VOID	setDS(USHORT);
VOID	setES(USHORT);
VOID	setFS(USHORT);
VOID	setGS(USHORT);
VOID	setCF(ULONG);
VOID	setPF(ULONG);
VOID	setAF(ULONG);
VOID	setZF(ULONG);
VOID	setSF(ULONG);
VOID	setIF(ULONG);
VOID	setDF(ULONG);
VOID	setOF(ULONG);
VOID	setMSW(USHORT);

/** GetVDMPointer - Findout the linear address of a given VDM address
 *
 *   INPUT
 *	Address - seg/sel:off (hi word has segment or selector and loword
 *		  is offset)
 *	Size	- Range of the pointer
 *	ProtectMode - If protectmode == TRUE its sel:off
 *		      If protectmode == FALSE its seg:off
 *
 *   OUTPUT
 *	Returns Linear address.
 *
 *   NOTES:
 *	1. VDDs should use this service to convert the address rather
 *	   than shifting the seg by 4 and adding the offset. This makes
 *	   them plateform independent. On non-x86 machine VDM's 0 and
 *	   the process's 0 are different and the actual adddress conversion
 *	   is provided by the CPU emulator.
 */
PVOID GetVDMPointer(
      ULONG Address,
      ULONG Size,
      BOOL ProtectedMode
);

/** FlushVDMPointer - Flushes the contents (required because of emulator)
 *
 *   INPUT
 *	Address - seg/sel:off (hi word has segment or selector and loword
 *		  is offset)
 *	Size	- Range of the pointer
 *	Buffer	- Address returned by GetVDMPointer.
 *	ProtectMode - If protecmeode == TRUE its sel:off
 *		      If protecmeode == FALSE its seg:off
 *
 *   OUTPUT
 *	Returns Linear address.
 *
 *   NOTES:
 *	1. VDDs should use this service to make sure that on non-x86
 *	   machines, the CPU emulator gets a chance to flush any data
 *	   associated with a memory range.
 */
BOOL  FlushVDMPointer(
      ULONG Addr,
      ULONG Size,
      PVOID Buffer,
      BOOL ProtectedMode
);

/** FreeVDMPointer - Frees a pointer previously returned by GetVDMPointer
 *
 *   INPUT
 *	Address - seg/sel:off (hi word has segment or selector and loword
 *		  is offset)
 *	Size	- Range of the pointer
 *	ProtectMode - If protecmeode == TRUE its sel:off
 *		      If protecmeode == FALSE its seg:off
 *
 *   OUTPUT
 *	None
 *
 *   NOTES:
 *	1. FreeVDMPointer does FlushVDMPointer as well.
 */
BOOL  FreeVDMPointer(
      ULONG Address,
      ULONG Size,
      BOOL ProtectedMode
);

/** VDDSimulateInterrupt - Simulates an interrupt to the VDM.
 *
 *   INPUT
 *	ms    -	Is either ICA_MASTER or ICA_SLAVE as appropriate
 *	line  - Interrupt line
 *	count - allows a batch of interrupts to be delivered but will usually
 *		be 1.
 *
 *   OUTPUT
 *	None
 */
VOID VDDSimulateInterrupt (
     BYTE ms,
     BYTE line,
     WORD count
);