]> git.sur5r.net Git - u-boot/blob - board/MAI/bios_emulator/scitech/src/pm/vdd/pm.c
* Code cleanup:
[u-boot] / board / MAI / bios_emulator / scitech / src / pm / vdd / pm.c
1 /****************************************************************************
2 *
3 *                   SciTech OS Portability Manager Library
4 *
5 *  ========================================================================
6 *
7 *    The contents of this file are subject to the SciTech MGL Public
8 *    License Version 1.0 (the "License"); you may not use this file
9 *    except in compliance with the License. You may obtain a copy of
10 *    the License at http://www.scitechsoft.com/mgl-license.txt
11 *
12 *    Software distributed under the License is distributed on an
13 *    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 *    implied. See the License for the specific language governing
15 *    rights and limitations under the License.
16 *
17 *    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 *
19 *    The Initial Developer of the Original Code is SciTech Software, Inc.
20 *    All Rights Reserved.
21 *
22 *  ========================================================================
23 *
24 * Language:     ANSI C
25 * Environment:  32-bit OS/2 VDD
26 *
27 * Description:  Implementation for the OS Portability Manager Library, which
28 *               contains functions to implement OS specific services in a
29 *               generic, cross platform API. Porting the OS Portability
30 *               Manager library is the first step to porting any SciTech
31 *               products to a new platform.
32 *
33 ****************************************************************************/
34
35 #include "pmapi.h"
36 #include "drvlib/os/os.h"
37 #include "sdd/sddhelp.h"
38 #include "mtrr.h"
39
40 #define TRACE(a)
41
42 /*--------------------------- Global variables ----------------------------*/
43
44 #define MAX_MEMORY_SHARED           100
45 #define MAX_MEMORY_MAPPINGS         100
46
47 /* TODO: I think the global and linear members will be the same, but not sure yet. */
48 typedef struct {
49     void    *linear;
50     ulong   global;
51     ulong   length;
52     int     npages;
53     } memshared;
54
55 typedef struct {
56     ulong   physical;
57     ulong   linear;
58     ulong   length;
59     int     npages;
60     ibool   isCached;
61     } mmapping;
62
63 static int          numMappings = 0;
64 static memshared    shared[MAX_MEMORY_MAPPINGS] = {0};
65 static mmapping     maps[MAX_MEMORY_MAPPINGS];
66 ibool               _PM_haveBIOS = TRUE;
67 char                _PM_cntPath[PM_MAX_PATH] = "";     /* there just isn't any */
68 uchar               *_PM_rmBufAddr = NULL;
69 ushort _VARAPI      PM_savedDS = 0;   /* why can't I use the underscore prefix? */
70
71 HVDHSEM             hevFarCallRet = NULL;
72 HVDHSEM             hevIRet       = NULL;
73 HHOOK               hhookUserReturnHook = NULL;
74 HHOOK               hhookUserIRetHook   = NULL;
75
76 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
77
78 /*----------------------------- Implementation ----------------------------*/
79
80 /* Functions to read and write CMOS registers */
81
82 ulong   PMAPI _PM_getPDB(void);
83 uchar   PMAPI _PM_readCMOS(int index);
84 void    PMAPI _PM_writeCMOS(int index,uchar value);
85
86 VOID HOOKENTRY UserReturnHook(PVOID pRefData, PCRF pcrf);
87 VOID HOOKENTRY UserIRetHook(PVOID pRefData, PCRF pcrf);
88
89 void PMAPI PM_init(void)
90 {
91     MTRR_init();
92
93     /* Initialize VDD-specific data */
94     /* Note: PM_init must be (obviously) called in VDM task context! */
95     VDHCreateSem(&hevFarCallRet, VDH_EVENTSEM);
96     VDHCreateSem(&hevIRet, VDH_EVENTSEM);
97     hhookUserReturnHook = VDHAllocHook(VDH_RETURN_HOOK, (PFNARM)UserReturnHook, 0);
98     hhookUserIRetHook   = VDHAllocHook(VDH_RETURN_HOOK, (PFNARM)UserIRetHook, 0);
99
100     if ((hevIRet == NULL) || (hevFarCallRet == NULL) ||
101         (hhookUserReturnHook == NULL) || (hhookUserIRetHook == NULL)) {
102         /* something failed, we can't go on */
103         /* TODO: take some action here! */
104         }
105 }
106
107 /* Do some cleaning up */
108 void PMAPI PM_exit(void)
109 {
110     /* Note: Hooks allocated during or after VDM creation are deallocated automatically */
111     if (hevIRet != NULL)
112         VDHDestroySem(hevIRet);
113
114     if (hevFarCallRet != NULL)
115         VDHDestroySem(hevFarCallRet);
116 }
117
118 ibool PMAPI PM_haveBIOSAccess(void)
119 { return _PM_haveBIOS; }
120
121 long PMAPI PM_getOSType(void)
122 { return /*_OS_OS2VDD*/ _OS_OS2; }  /*FIX!! */
123
124 int PMAPI PM_getModeType(void)
125 { return PM_386; }
126
127 void PMAPI PM_backslash(char *s)
128 {
129     uint pos = strlen(s);
130     if (s[pos-1] != '\\') {
131         s[pos] = '\\';
132         s[pos+1] = '\0';
133         }
134 }
135
136 void PMAPI PM_setFatalErrorCleanup(
137     void (PMAPIP cleanup)(void))
138 {
139     fatalErrorCleanup = cleanup;
140 }
141
142 void PMAPI PM_fatalError(const char *msg)
143 {
144     if (fatalErrorCleanup)
145         fatalErrorCleanup();
146 /*    Fatal_Error_Handler(msg,0);  TODO: implement somehow! */
147 }
148
149 /****************************************************************************
150 PARAMETERS:
151 len     - Place to store the length of the buffer
152 rseg    - Place to store the real mode segment of the buffer
153 roff    - Place to store the real mode offset of the buffer
154
155 REMARKS:
156 This function returns the address and length of the global VESA transfer
157 buffer.
158 ****************************************************************************/
159 void * PMAPI PM_getVESABuf(
160     uint *len,
161     uint *rseg,
162     uint *roff)
163 {
164     if (_PM_rmBufAddr) {
165         *len = 0; /*VESA_BUF_SIZE; */
166         *rseg = (ulong)(_PM_rmBufAddr) >> 4;
167         *roff = (ulong)(_PM_rmBufAddr) & 0xF;
168         return _PM_rmBufAddr;
169         }
170     return NULL;
171 }
172
173 int PMAPI PM_int386(int intno, PMREGS *in, PMREGS *out)
174 {
175     /* Unused in VDDs */
176     return 0;
177 }
178
179 char * PMAPI PM_getCurrentPath(char *path,int maxLen)
180 {
181     strncpy(path, _PM_cntPath, maxLen);
182     path[maxLen - 1] = 0;
183     return path;
184 }
185
186 char PMAPI PM_getBootDrive(void)
187 {
188     ulong   boot = 3;
189     boot = VDHQuerySysValue(0, VDHGSV_BOOTDRV);
190     return (char)('a' + boot - 1);
191 }
192
193 const char * PMAPI PM_getVBEAFPath(void)
194 {
195     static char path[CCHMAXPATH];
196     strcpy(path,"x:\\");
197     path[0] = PM_getBootDrive();
198     return path;
199 }
200
201 const char * PMAPI PM_getNucleusPath(void)
202 {
203         static char path[CCHMAXPATH];
204         strcpy(path,"x:\\os2\\drivers");
205         path[0] = PM_getBootDrive();
206         PM_backslash(path);
207         strcat(path,"nucleus");
208         return path;
209 }
210
211 const char * PMAPI PM_getNucleusConfigPath(void)
212 {
213     static char path[256];
214     strcpy(path,PM_getNucleusPath());
215     PM_backslash(path);
216     strcat(path,"config");
217     return path;
218 }
219
220 const char * PMAPI PM_getUniqueID(void)
221 { return PM_getMachineName(); }
222
223 const char * PMAPI PM_getMachineName(void)
224 {
225     return "Unknown";
226 }
227
228 int PMAPI PM_kbhit(void)
229 { return 1; }
230
231 int PMAPI PM_getch(void)
232 { return 0; }
233
234 PM_HWND PMAPI PM_openConsole(PM_HWND hwndUser,int device,int xRes,int yRes,int bpp,ibool fullScreen)
235 {
236     /* Unused in VDDs */
237     return NULL;
238 }
239
240 int PMAPI PM_getConsoleStateSize(void)
241 {
242     /* Unused in VDDs */
243     return 1;
244 }
245
246 void PMAPI PM_saveConsoleState(void *stateBuf,PM_HWND hwndConsole)
247 {
248     /* Unused in VDDs */
249 }
250
251 void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags))
252 {
253     /* Unused in VDDs */
254 }
255
256 void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND hwndConsole)
257 {
258     /* Unused in VDDs */
259 }
260
261 void PMAPI PM_closeConsole(PM_HWND hwndConsole)
262 {
263     /* Unused in VDDs */
264 }
265
266 void PMAPI PM_setOSCursorLocation(int x,int y)
267 {
268     uchar *_biosPtr = PM_getBIOSPointer();
269     PM_setByte(_biosPtr+0x50,x);
270     PM_setByte(_biosPtr+0x51,y);
271 }
272
273 void PMAPI PM_setOSScreenWidth(int width,int height)
274 {
275     uchar *_biosPtr = PM_getBIOSPointer();
276     PM_setByte(_biosPtr+0x4A,width);
277     PM_setByte(_biosPtr+0x84,height-1);
278 }
279
280 /****************************************************************************
281 REMARKS:
282 Allocate a block of shared memory. For OS/2 VDD we allocate shared memory
283 as locked, global memory that is accessible from any memory context
284 (including interrupt time context), which allows us to load our important
285 data structure and code such that we can access it directly from a ring
286 0 interrupt context.
287 ****************************************************************************/
288 void * PMAPI PM_mallocShared(long size)
289 {
290     ULONG       nPages = (size + 0xFFF) >> 12;
291     int         i;
292
293     /* First find a free slot in our shared memory table */
294     for (i = 0; i < MAX_MEMORY_SHARED; i++) {
295         if (shared[i].linear == 0)
296             break;
297         }
298     if (i < MAX_MEMORY_SHARED) {
299         shared[i].linear = VDHAllocPages(NULL, nPages, VDHAP_SYSTEM | VDHAP_FIXED);
300         shared[i].npages = nPages;
301         shared[i].global = (ULONG)shared[i].linear;
302         return (void*)shared[i].global;
303         }
304     return NULL;
305 }
306
307 /****************************************************************************
308 REMARKS:
309 Free a block of shared memory
310 ****************************************************************************/
311 void PMAPI PM_freeShared(void *p)
312 {
313     int i;
314
315     /* Find a shared memory block in our table and free it */
316     for (i = 0; i < MAX_MEMORY_SHARED; i++) {
317         if (shared[i].global == (ulong)p) {
318             VDHFreePages(shared[i].linear);
319             shared[i].linear = 0;
320             break;
321             }
322         }
323 }
324
325 void * PMAPI PM_mapToProcess(void *base,ulong limit)
326 { return (void*)base; }
327
328 ibool PMAPI PM_doBIOSPOST(
329     ushort axVal,
330     ulong BIOSPhysAddr,
331     void *mappedBIOS,
332     ulong BIOSLen)
333 {
334     /* TODO: Figure out how to do this */
335     return false;
336 }
337
338 void * PMAPI PM_getBIOSPointer(void)
339 { return (void*)0x400; }
340
341 void * PMAPI PM_getA0000Pointer(void)
342 { return PM_mapPhysicalAddr(0xA0000,0xFFFF,true); }
343
344 /****************************************************************************
345 PARAMETERS:
346 base        - Physical base address of the memory to maps in
347 limit       - Limit of physical memory to region to maps in
348
349 RETURNS:
350 Linear address of the newly mapped memory.
351
352 REMARKS:
353 Maps a physical memory range to a linear memory range.
354 ****************************************************************************/
355 ulong MapPhysicalToLinear(
356     ulong base,
357     ulong limit,
358     int *npages)
359 {
360     ulong   linear,length = limit+1;
361     int     i,ppage,flags;
362 #if 0
363     ppage = base >> 12;
364     *npages = (length + (base & 0xFFF) + 4095) >> 12;
365     flags = PR_FIXED | PR_STATIC;
366     if (base == 0xA0000) {
367         /* We require the linear address to be aligned to a 64Kb boundary
368          * for mapping the banked framebuffer (so we can do efficient
369          * carry checking for bank changes in the assembler code). The only
370          * way to ensure this is to force the linear address to be aligned
371          * to a 4Mb boundary.
372          */
373         flags |= PR_4MEG;
374         }
375     if ((linear = (ulong)PageReserve(PR_SYSTEM,*npages,flags)) == (ulong)-1)
376         return 0;
377     if (!PageCommitPhys(linear >> 12,*npages,ppage,PC_INCR | PC_USER | PC_WRITEABLE))
378         return 0;
379 #endif
380     return linear + (base & 0xFFF);
381 }
382
383 /****************************************************************************
384 PARAMETERS:
385 base        - Physical base address of the memory to map in
386 limit       - Limit of physical memory to region to map in
387 isCached    - True if the memory should be cached, false if not
388
389 RETURNS:
390 Linear address of the newly mapped memory.
391
392 REMARKS:
393 This function maps physical memory to linear memory, which can then be used
394 to create a selector or used directly from 32-bit protected mode programs.
395 This is better than DPMI 0x800, since it allows you to maps physical
396 memory below 1Mb, which gets this memory out of the way of the Windows VxD's
397 sticky paws.
398
399 NOTE:   If the memory is not expected to be cached, this function will
400         directly re-program the PCD (Page Cache Disable) bit in the
401         page tables. There does not appear to be a mechanism in the VMM
402         to control this bit via the regular interface.
403 ****************************************************************************/
404 void * PMAPI PM_mapPhysicalAddr(
405     ulong base,
406     ulong limit,
407     ibool isCached)
408 {
409     ulong   linear,length = limit+1;
410     int     i,npages;
411     ulong   PDB,*pPDB;
412
413     /* Search table of existing mappings to see if we have already mapped
414      * a region of memory that will serve this purpose.
415      */
416     for (i = 0; i < numMappings; i++) {
417         if (maps[i].physical == base && maps[i].length == length && maps[i].isCached == isCached)
418             return (void*)maps[i].linear;
419         }
420     if (numMappings == MAX_MEMORY_MAPPINGS)
421         return NULL;
422
423     /* We did not find any previously mapped memory region, so map it in.
424      * Note that we do not use MapPhysToLinear, since this function appears
425      * to have problems mapping memory in the 1Mb physical address space.
426      * Hence we use PageReserve and PageCommitPhys.
427      */
428     if ((linear = MapPhysicalToLinear(base,limit,&npages)) == 0)
429         return NULL;
430     maps[numMappings].physical = base;
431     maps[numMappings].length = length;
432     maps[numMappings].linear = linear;
433     maps[numMappings].npages = npages;
434     maps[numMappings].isCached = isCached;
435     numMappings++;
436
437 #if 0
438     /* Finally disable caching where necessary */
439     if (!isCached && (PDB = _PM_getPDB()) != 0) {
440         int     startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage;
441         ulong   pageTable,*pPageTable;
442
443         if (PDB >= 0x100000)
444             pPDB = (ulong*)MapPhysicalToLinear(PDB,0xFFF,&npages);
445         else
446             pPDB = (ulong*)PDB;
447         if (pPDB) {
448             startPDB = (linear >> 22) & 0x3FF;
449             startPage = (linear >> 12) & 0x3FF;
450             endPDB = ((linear+limit) >> 22) & 0x3FF;
451             endPage = ((linear+limit) >> 12) & 0x3FF;
452             for (iPDB = startPDB; iPDB <= endPDB; iPDB++) {
453                 pageTable = pPDB[iPDB] & ~0xFFF;
454                 if (pageTable >= 0x100000)
455                     pPageTable = (ulong*)MapPhysicalToLinear(pageTable,0xFFF,&npages);
456                 else
457                     pPageTable = (ulong*)pageTable;
458                 start = (iPDB == startPDB) ? startPage : 0;
459                 end = (iPDB == endPDB) ? endPage : 0x3FF;
460                 for (iPage = start; iPage <= end; iPage++)
461                     pPageTable[iPage] |= 0x10;
462                 PageFree((ulong)pPageTable,PR_STATIC);
463                 }
464             PageFree((ulong)pPDB,PR_STATIC);
465             }
466         }
467 #endif
468     return (void*)linear;
469 }
470
471 void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit)
472 {
473     /* We never free the mappings */
474 }
475
476 void PMAPI PM_sleep(ulong milliseconds)
477 {
478     /* We never sleep in a VDD */
479 }
480
481 int PMAPI PM_getCOMPort(int port)
482 {
483     /* TODO: Re-code this to determine real values using the Plug and Play */
484     /*       manager for the OS. */
485     switch (port) {
486         case 0: return 0x3F8;
487         case 1: return 0x2F8;
488         }
489     return 0;
490 }
491
492 int PMAPI PM_getLPTPort(int port)
493 {
494     /* TODO: Re-code this to determine real values using the Plug and Play */
495     /*       manager for the OS. */
496     switch (port) {
497         case 0: return 0x3BC;
498         case 1: return 0x378;
499         case 2: return 0x278;
500         }
501     return 0;
502 }
503
504 ulong PMAPI PM_getPhysicalAddr(void *p)
505 {
506         /* TODO: This function should find the physical address of a linear */
507         /*               address. */
508         return 0xFFFFFFFFUL;
509 }
510
511 void PMAPI _PM_freeMemoryMappings(void)
512 {
513     int i;
514 /*    for (i = 0; i < numMappings; i++) */
515 /*        PageFree(maps[i].linear,PR_STATIC); */
516 }
517
518 void * PMAPI PM_mapRealPointer(uint r_seg,uint r_off)
519 { return (void*)MK_PHYS(r_seg,r_off); }
520
521 void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off)
522 { return NULL; }
523
524 void PMAPI PM_freeRealSeg(void *mem)
525 { }
526
527 void PMAPI DPMI_int86(int intno, DPMI_regs *regs)
528 {
529     /* Unsed in VDDs */
530 }
531
532 /****************************************************************************
533 REMARKS:
534 Load the V86 registers in the client state, and save the original state
535 before loading the registers.
536 ****************************************************************************/
537 static void LoadV86Registers(
538     PCRF saveRegs,
539     RMREGS *in,
540     RMSREGS *sregs)
541 {
542     PCRF            pcrf;     /* current client register frame */
543
544     /* get pointer to registers */
545     pcrf = (PCRF)VDHQuerySysValue(CURRENT_VDM, VDHLSV_PCRF);
546
547     /* Note: We could do VDHPushRegs instead but this should be safer as it */
548     /* doesn't rely on the VDM session having enough free stack space. */
549     *saveRegs = *pcrf;        /* save all registers */
550
551     pcrf->crf_eax = in->e.eax;    /* load new values */
552     pcrf->crf_ebx = in->e.ebx;
553     pcrf->crf_ecx = in->e.ecx;
554     pcrf->crf_edx = in->e.edx;
555     pcrf->crf_esi = in->e.esi;
556     pcrf->crf_edi = in->e.edi;
557     pcrf->crf_es  = sregs->es;
558     pcrf->crf_ds  = sregs->ds;
559
560 }
561
562 /****************************************************************************
563 REMARKS:
564 Read the V86 registers from the client state and restore the original state.
565 ****************************************************************************/
566 static void ReadV86Registers(
567     PCRF saveRegs,
568     RMREGS *out,
569     RMSREGS *sregs)
570 {
571     PCRF            pcrf;     /* current client register frame */
572
573     /* get pointer to registers */
574     pcrf = (PCRF)VDHQuerySysValue(CURRENT_VDM, VDHLSV_PCRF);
575
576     /* read new register values */
577     out->e.eax = pcrf->crf_eax;
578     out->e.ebx = pcrf->crf_ebx;
579     out->e.ecx = pcrf->crf_ecx;
580     out->e.edx = pcrf->crf_edx;
581     out->e.esi = pcrf->crf_esi;
582     out->e.edi = pcrf->crf_edi;
583     sregs->es  = pcrf->crf_es;
584     sregs->ds  = pcrf->crf_ds;
585
586     /* restore original client registers */
587     *pcrf = *saveRegs;
588 }
589
590 /****************************************************************************
591 REMARKS: Used for far calls into V86 code
592 ****************************************************************************/
593 VOID HOOKENTRY UserReturnHook(
594   PVOID pRefData,
595   PCRF pcrf )
596 {
597     VDHPostEventSem(hevFarCallRet);
598 }
599
600 /****************************************************************************
601 REMARKS: Used for calling BIOS interrupts
602 ****************************************************************************/
603 VOID HOOKENTRY UserIRetHook(
604   PVOID pRefData,
605   PCRF pcrf )
606 {
607     VDHPostEventSem(hevIRet);
608 }
609
610 /****************************************************************************
611 REMARKS:
612 Call a V86 real mode function with the specified register values
613 loaded before the call. The call returns with a far ret.
614 Must be called from within a DOS session context!
615 ****************************************************************************/
616 void PMAPI PM_callRealMode(
617     uint seg,
618     uint off,
619     RMREGS *regs,
620     RMSREGS *sregs)
621 {
622     CRF   saveRegs;
623     FPFN  fnAddress;
624     ULONG rc;
625
626     TRACE("SDDHELP: Entering PM_callRealMode()\n");
627     LoadV86Registers(SSToDS(&saveRegs),regs,sregs);
628
629     /* set up return hook for call */
630     rc = VDHArmReturnHook(hhookUserReturnHook, VDHARH_CSEIP_HOOK);
631
632     VDHResetEventSem(hevFarCallRet);
633
634     /* the address is a 16:32 pointer */
635     OFFSETOF32(fnAddress)  = off;
636     SEGMENTOF32(fnAddress) = seg;
637     rc = VDHPushFarCall(fnAddress);
638     VDHYield(0);
639
640     /* wait until the V86 call returns - our return hook posts the semaphore */
641     rc = VDHWaitEventSem(hevFarCallRet, SEM_INDEFINITE_WAIT);
642
643     ReadV86Registers(SSToDS(&saveRegs),regs,sregs);
644     TRACE("SDDHELP: Exiting PM_callRealMode()\n");
645 }
646
647 /****************************************************************************
648 REMARKS:
649 Issue a V86 real mode interrupt with the specified register values
650 loaded before the interrupt.
651 Must be called from within a DOS session context!
652 ****************************************************************************/
653 int PMAPI PM_int86(
654     int intno,
655     RMREGS *in,
656     RMREGS *out)
657 {
658     RMSREGS    sregs = {0};
659     CRF        saveRegs;
660     ushort     oldDisable;
661     ULONG      rc;
662
663     memset(SSToDS(&sregs), 0, sizeof(sregs));
664
665 #if 0   /* do we need this?? */
666     /* Disable pass-up to our VDD handler so we directly call BIOS */
667     TRACE("SDDHELP: Entering PM_int86()\n");
668     if (disableTSRFlag) {
669         oldDisable = *disableTSRFlag;
670         *disableTSRFlag = 0;
671         }
672 #endif
673
674     LoadV86Registers(SSToDS(&saveRegs), in, SSToDS(&sregs));
675
676     VDHResetEventSem(hevIRet);
677     rc = VDHPushInt(intno);
678
679     /* set up return hook for interrupt */
680     rc = VDHArmReturnHook(hhookUserIRetHook, VDHARH_NORMAL_IRET);
681
682     VDHYield(0);
683
684     /* wait until the V86 IRETs - our return hook posts the semaphore */
685     rc = VDHWaitEventSem(hevIRet, 5000); /*SEM_INDEFINITE_WAIT); */
686
687     ReadV86Registers(SSToDS(&saveRegs), out, SSToDS(&sregs));
688
689 #if 0
690     /* Re-enable pass-up to our VDD handler if previously enabled */
691     if (disableTSRFlag)
692         *disableTSRFlag = oldDisable;
693 #endif
694
695     TRACE("SDDHELP: Exiting PM_int86()\n");
696     return out->x.ax;
697
698 }
699
700 /****************************************************************************
701 REMARKS:
702 Issue a V86 real mode interrupt with the specified register values
703 loaded before the interrupt.
704 ****************************************************************************/
705 int PMAPI PM_int86x(
706     int intno,
707     RMREGS *in,
708     RMREGS *out,
709     RMSREGS *sregs)
710 {
711     CRF             saveRegs;
712     ushort          oldDisable;
713     ULONG       rc;
714
715 #if 0
716     /* Disable pass-up to our VxD handler so we directly call BIOS */
717     TRACE("SDDHELP: Entering PM_int86x()\n");
718     if (disableTSRFlag) {
719         oldDisable = *disableTSRFlag;
720         *disableTSRFlag = 0;
721         }
722 #endif
723     LoadV86Registers(SSToDS(&saveRegs), in, sregs);
724
725     VDHResetEventSem(hevIRet);
726     rc = VDHPushInt(intno);
727
728     /* set up return hook for interrupt */
729     rc = VDHArmReturnHook(hhookUserIRetHook, VDHARH_NORMAL_IRET);
730
731     VDHYield(0);
732
733     /* wait until the V86 IRETs - our return hook posts the semaphore */
734     rc = VDHWaitEventSem(hevIRet, 5000); /*SEM_INDEFINITE_WAIT); */
735
736     ReadV86Registers(SSToDS(&saveRegs), out, sregs);
737
738 #if 0
739     /* Re-enable pass-up to our VxD handler if previously enabled */
740     if (disableTSRFlag)
741         *disableTSRFlag = oldDisable;
742 #endif
743
744     TRACE("SDDHELP: Exiting PM_int86x()\n");
745     return out->x.ax;
746 }
747
748 void PMAPI PM_availableMemory(ulong *physical,ulong *total)
749 { *physical = *total = 0; }
750
751 /****************************************************************************
752 REMARKS:
753 Allocates a block of locked physical memory.
754 ****************************************************************************/
755 void * PMAPI PM_allocLockedMem(
756     uint size,
757     ulong *physAddr,
758     ibool contiguous,
759     ibool below16M)
760 {
761     ULONG       flags = VDHAP_SYSTEM;
762     ULONG       nPages = (size + 0xFFF) >> 12;
763
764     flags |= (physAddr != NULL) ? VDHAP_PHYSICAL : VDHAP_FIXED;
765
766     return VDHAllocPages(physAddr, nPages, VDHAP_SYSTEM | VDHAP_PHYSICAL);
767 }
768
769 /****************************************************************************
770 REMARKS:
771 Frees a block of locked physical memory.
772 ****************************************************************************/
773 void PMAPI PM_freeLockedMem(
774     void *p,
775     uint size,
776     ibool contiguous)
777 {
778     if (p)
779         VDHFreePages((PVOID)p);
780 }
781
782 /****************************************************************************
783 REMARKS:
784 Lock linear memory so it won't be paged.
785 ****************************************************************************/
786 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
787 {
788     ULONG  lockHandle;
789
790     /* TODO: the lock handle is essential for the unlock operation!! */
791     lockHandle = VDHLockMem(p, len, 0, (PVOID)VDHLM_NO_ADDR, NULL);
792
793     if (lockHandle != NULL)
794        return 0;
795     else
796        return 1;
797 }
798
799 /****************************************************************************
800 REMARKS:
801 Unlock linear memory so it won't be paged.
802 ****************************************************************************/
803 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
804 {
805     /* TODO: implement - use a table of lock handles? */
806     /* VDHUnlockPages(lockHandle); */
807     return 0;
808 }
809
810 /****************************************************************************
811 REMARKS:
812 Lock linear memory so it won't be paged.
813 ****************************************************************************/
814 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
815 {
816     return PM_lockDataPages((void*)p,len,lh);
817 }
818
819 /****************************************************************************
820 REMARKS:
821 Unlock linear memory so it won't be paged.
822 ****************************************************************************/
823 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
824 {
825     return PM_unlockDataPages((void*)p,len,lh);
826 }
827
828 /****************************************************************************
829 REMARKS:
830 OS specific shared libraries not supported inside a VDD
831 ****************************************************************************/
832 PM_MODULE PMAPI PM_loadLibrary(
833     const char *szDLLName)
834 {
835     (void)szDLLName;
836     return NULL;
837 }
838
839 /****************************************************************************
840 REMARKS:
841 OS specific shared libraries not supported inside a VDD
842 ****************************************************************************/
843 void * PMAPI PM_getProcAddress(
844     PM_MODULE hModule,
845     const char *szProcName)
846 {
847     (void)hModule;
848     (void)szProcName;
849     return NULL;
850 }
851
852 /****************************************************************************
853 REMARKS:
854 OS specific shared libraries not supported inside a VDD
855 ****************************************************************************/
856 void PMAPI PM_freeLibrary(
857     PM_MODULE hModule)
858 {
859     (void)hModule;
860 }
861
862 /****************************************************************************
863 REMARKS:
864 Function to find the first file matching a search criteria in a directory.
865 ****************************************************************************/
866 void *PMAPI PM_findFirstFile(
867     const char *filename,
868     PM_findData *findData)
869 {
870     /* TODO: This function should start a directory enumeration search */
871     /*       given the filename (with wildcards). The data should be */
872     /*       converted and returned in the findData standard form. */
873     (void)filename;
874     (void)findData;
875     return PM_FILE_INVALID;
876 }
877
878 /****************************************************************************
879 REMARKS:
880 Function to find the next file matching a search criteria in a directory.
881 ****************************************************************************/
882 ibool PMAPI PM_findNextFile(
883     void *handle,
884     PM_findData *findData)
885 {
886     /* TODO: This function should find the next file in directory enumeration */
887     /*       search given the search criteria defined in the call to */
888     /*       PM_findFirstFile. The data should be converted and returned */
889     /*       in the findData standard form. */
890     (void)handle;
891     (void)findData;
892     return false;
893 }
894
895 /****************************************************************************
896 REMARKS:
897 Function to close the find process
898 ****************************************************************************/
899 void PMAPI PM_findClose(
900     void *handle)
901 {
902     /* TODO: This function should close the find process. This may do */
903     /*       nothing for some OS'es. */
904     (void)handle;
905 }
906
907 /****************************************************************************
908 REMARKS:
909 Function to determine if a drive is a valid drive or not. Under Unix this
910 function will return false for anything except a value of 3 (considered
911 the root drive, and equivalent to C: for non-Unix systems). The drive
912 numbering is:
913
914     1   - Drive A:
915     2   - Drive B:
916     3   - Drive C:
917     etc
918
919 ****************************************************************************/
920 ibool PMAPI PM_driveValid(
921     char drive)
922 {
923     /* Not applicable in a VDD */
924     (void)drive;
925     return false;
926 }
927
928 /****************************************************************************
929 REMARKS:
930 Function to get the current working directory for the specififed drive.
931 Under Unix this will always return the current working directory regardless
932 of what the value of 'drive' is.
933 ****************************************************************************/
934 void PMAPI PM_getdcwd(
935     int drive,
936     char *dir,
937     int len)
938 {
939     /* Not applicable in a VDD */
940     (void)drive;
941     (void)dir;
942     (void)len;
943 }
944
945 /****************************************************************************
946 PARAMETERS:
947 base    - The starting physical base address of the region
948 size    - The size in bytes of the region
949 type    - Type to place into the MTRR register
950
951 RETURNS:
952 Error code describing the result.
953
954 REMARKS:
955 Function to enable write combining for the specified region of memory.
956 ****************************************************************************/
957 int PMAPI PM_enableWriteCombine(
958     ulong base,
959     ulong size,
960     uint type)
961 {
962     return MTRR_enableWriteCombine(base,size,type);
963 }
964
965 /****************************************************************************
966 REMARKS:
967 Function to change the file attributes for a specific file.
968 ****************************************************************************/
969 void PMAPI PM_setFileAttr(
970     const char *filename,
971     uint attrib)
972 {
973     /* TODO: Implement this ? */
974     (void)filename;
975     (void)attrib;
976     PM_fatalError("PM_setFileAttr not implemented!");
977 }
978
979 /****************************************************************************
980 REMARKS:
981 Function to get the file attributes for a specific file.
982 ****************************************************************************/
983 uint PMAPI PM_getFileAttr(
984     const char *filename)
985 {
986     /* TODO: Implement this ? */
987     (void)filename;
988     PM_fatalError("PM_getFileAttr not implemented!");
989     return 0;
990 }
991
992 /****************************************************************************
993 REMARKS:
994 Function to create a directory.
995 ****************************************************************************/
996 ibool PMAPI PM_mkdir(
997     const char *filename)
998 {
999     /* TODO: Implement this ? */
1000     (void)filename;
1001     PM_fatalError("PM_mkdir not implemented!");
1002     return false;
1003 }
1004
1005 /****************************************************************************
1006 REMARKS:
1007 Function to remove a directory.
1008 ****************************************************************************/
1009 ibool PMAPI PM_rmdir(
1010     const char *filename)
1011 {
1012     /* TODO: Implement this ? */
1013     (void)filename;
1014     PM_fatalError("PM_rmdir not implemented!");
1015     return false;
1016 }
1017
1018 /****************************************************************************
1019 REMARKS:
1020 Function to get the file time and date for a specific file.
1021 ****************************************************************************/
1022 ibool PMAPI PM_getFileTime(
1023     const char *filename,
1024     ibool gmTime,
1025     PM_time *time)
1026 {
1027     /* TODO: Implement this ? */
1028     (void)filename;
1029     (void)gmTime;
1030     (void)time;
1031     PM_fatalError("PM_getFileTime not implemented!");
1032     return false;
1033 }
1034
1035 /****************************************************************************
1036 REMARKS:
1037 Function to set the file time and date for a specific file.
1038 ****************************************************************************/
1039 ibool PMAPI PM_setFileTime(
1040     const char *filename,
1041     ibool gmTime,
1042     PM_time *time)
1043 {
1044     /* TODO: Implement this ? */
1045     (void)filename;
1046     (void)gmTime;
1047     (void)time;
1048     PM_fatalError("PM_setFileTime not implemented!");
1049     return false;
1050 }