1 /****************************************************************************
3 * SciTech OS Portability Manager Library
5 * ========================================================================
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
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.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
25 * Environment: 32-bit Windows VxD
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.
33 ****************************************************************************/
36 #include "drvlib/os/os.h"
37 #include "sdd/sddhelp.h"
40 /*--------------------------- Global variables ----------------------------*/
42 #define MAX_MEMORY_SHARED 100
43 #define MAX_MEMORY_MAPPINGS 100
60 static int numMappings = 0;
61 static memshared shared[MAX_MEMORY_MAPPINGS] = {0};
62 static mmapping maps[MAX_MEMORY_MAPPINGS];
63 extern ibool _PM_haveBIOS;
64 char _PM_cntPath[PM_MAX_PATH] = "";
65 char _PM_nucleusPath[PM_MAX_PATH] = "";
66 uchar *_PM_rmBufAddr = NULL;
67 ushort _VARAPI _PM_savedDS = 0;
68 static uchar _PM_oldCMOSRegA;
69 static uchar _PM_oldCMOSRegB;
70 PM_intHandler _PM_rtcHandler = NULL;
71 IRQHANDLE RTCIRQHandle = 0;
72 VPICD_HWInt_THUNK RTCInt_Thunk;
74 static char *szWindowsKey = "Software\\Microsoft\\Windows\\CurrentVersion";
75 static char *szSystemRoot = "SystemRoot";
76 static char *szMachineNameKey = "System\\CurrentControlSet\\control\\ComputerName\\ComputerName";
77 static char *szMachineName = "ComputerName";
78 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
80 /*----------------------------- Implementation ----------------------------*/
82 /* Functions to read and write CMOS registers */
84 ulong PMAPI _PM_getPDB(void);
85 uchar PMAPI _PM_readCMOS(int index);
86 void PMAPI _PM_writeCMOS(int index,uchar value);
88 /****************************************************************************
90 PM_malloc override function for Nucleus drivers loaded in VxD's.
91 ****************************************************************************/
95 return PM_mallocShared(size);
98 /****************************************************************************
100 PM_calloc override function for Nucleus drivers loaded in VxD's.
101 ****************************************************************************/
106 void *p = PM_mallocShared(nelem * size);
108 memset(p,0,nelem * size);
112 /****************************************************************************
114 PM_realloc override function for Nucleus drivers loaded in VxD's.
115 ****************************************************************************/
120 void *p = PM_mallocShared(size);
128 /****************************************************************************
130 PM_free override function for Nucleus drivers loaded in VxD's.
131 ****************************************************************************/
138 /****************************************************************************
140 Initialise the PM library.
141 ****************************************************************************/
142 void PMAPI PM_init(void)
144 /* Override the default memory allocators for all Nucleus drivers
145 * loaded in SDDHELP/PMHELP. We do this so that we can ensure all memory
146 * dynamically allocated by Nucleus drivers and internal C runtime
147 * library functions are shared memory blocks that all processes
148 * connecting to SDDHELP can see.
150 PM_useLocalMalloc(VXD_malloc,VXD_calloc,VXD_realloc,VXD_free);
152 /* Initialiase the MTRR module */
156 ibool PMAPI PM_haveBIOSAccess(void)
157 { return _PM_haveBIOS; }
159 long PMAPI PM_getOSType(void)
160 { return _OS_WIN32VXD; }
162 int PMAPI PM_getModeType(void)
165 void PMAPI PM_backslash(char *s)
167 uint pos = strlen(s);
168 if (s[pos-1] != '\\') {
174 void PMAPI PM_setFatalErrorCleanup(
175 void (PMAPIP cleanup)(void))
177 fatalErrorCleanup = cleanup;
180 void PMAPI PM_fatalError(const char *msg)
182 if (fatalErrorCleanup)
184 Fatal_Error_Handler(msg,0);
187 /****************************************************************************
189 len - Place to store the length of the buffer
190 rseg - Place to store the real mode segment of the buffer
191 roff - Place to store the real mode offset of the buffer
194 This function returns the address and length of the global VESA transfer
195 buffer that is used for communicating with the VESA BIOS functions from
196 Win16 and Win32 programs under Windows.
197 ****************************************************************************/
198 void * PMAPI PM_getVESABuf(
203 /* If the VxD is dynamically loaded we will not have a real mode
204 * transfer buffer to return, so we fail the call.
207 *len = VESA_BUF_SIZE;
208 *rseg = (ulong)(_PM_rmBufAddr) >> 4;
209 *roff = (ulong)(_PM_rmBufAddr) & 0xF;
210 return _PM_rmBufAddr;
224 void PMAPI _PM_getRMvect(
231 Get_V86_Int_Vector(intno,&seg,&off);
232 *realisr = ((long)seg << 16) | (off & 0xFFFF);
235 void PMAPI _PM_setRMvect(
239 Set_V86_Int_Vector(intno,realisr >> 16,realisr & 0xFFFF);
242 char * PMAPI PM_getCurrentPath(
246 strncpy(path,_PM_cntPath,maxLen);
251 char PMAPI PM_getBootDrive(void)
254 const char * PMAPI PM_getVBEAFPath(void)
257 /****************************************************************************
259 szKey - Key to query (can contain version number formatting)
260 szValue - Value to get information for
261 value - Place to store the registry key data read
262 size - Size of the string buffer to read into
265 true if the key was found, false if not.
266 ****************************************************************************/
267 static ibool REG_queryString(
275 ibool status = false;
277 memset(value,0,sizeof(value));
278 if (RegOpenKey(HKEY_LOCAL_MACHINE,szKey,&hKey) == ERROR_SUCCESS) {
279 if (RegQueryValueEx(hKey,(PCHAR)szValue,(ulong*)NULL,(ulong*)&type,value,(ulong*)&size) == ERROR_SUCCESS)
286 const char * PMAPI PM_getNucleusPath(void)
288 static char path[256];
290 if (strlen(_PM_nucleusPath) > 0) {
291 strcpy(path,_PM_nucleusPath);
295 if (!REG_queryString(szWindowsKey,szSystemRoot,path,sizeof(path)))
296 strcpy(path,"c:\\windows");
298 strcat(path,"system\\nucleus");
302 const char * PMAPI PM_getNucleusConfigPath(void)
304 static char path[256];
305 strcpy(path,PM_getNucleusPath());
307 strcat(path,"config");
311 const char * PMAPI PM_getUniqueID(void)
312 { return PM_getMachineName(); }
314 const char * PMAPI PM_getMachineName(void)
316 static char name[256];
317 if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name)))
322 int PMAPI PM_kbhit(void)
325 int PMAPI PM_getch(void)
328 PM_HWND PMAPI PM_openConsole(
340 int PMAPI PM_getConsoleStateSize(void)
346 void PMAPI PM_saveConsoleState(
353 void PMAPI PM_setSuspendAppCallback(
354 int (_ASMAPIP saveState)(
360 void PMAPI PM_restoreConsoleState(
361 const void *stateBuf,
367 void PMAPI PM_closeConsole(
373 void PM_setOSCursorLocation(
377 uchar *_biosPtr = PM_getBIOSPointer();
378 PM_setByte(_biosPtr+0x50,x);
379 PM_setByte(_biosPtr+0x51,y);
382 void PM_setOSScreenWidth(
386 uchar *_biosPtr = PM_getBIOSPointer();
387 PM_setByte(_biosPtr+0x4A,width);
388 PM_setByte(_biosPtr+0x84,height-1);
391 /****************************************************************************
393 Allocate a block of shared memory. For Win9x we allocate shared memory
394 as locked, global memory that is accessible from any memory context
395 (including interrupt time context), which allows us to load our important
396 data structure and code such that we can access it directly from a ring
398 ****************************************************************************/
399 void * PMAPI PM_mallocShared(
403 DWORD pgNum,nPages = (size + 0xFFF) >> 12;
406 /* First find a free slot in our shared memory table */
407 for (i = 0; i < MAX_MEMORY_SHARED; i++) {
408 if (shared[i].linear == 0)
411 if (i < MAX_MEMORY_SHARED) {
412 PageAllocate(nPages,PG_SYS,0,0,0,0,NULL,0,&hMem,&shared[i].linear);
413 shared[i].npages = nPages;
414 pgNum = (ulong)shared[i].linear >> 12;
415 shared[i].global = LinPageLock(pgNum,nPages,PAGEMAPGLOBAL);
416 return (void*)shared[i].global;
421 /****************************************************************************
423 Free a block of shared memory
424 ****************************************************************************/
425 void PMAPI PM_freeShared(void *p)
429 /* Find a shared memory block in our table and free it */
430 for (i = 0; i < MAX_MEMORY_SHARED; i++) {
431 if (shared[i].global == (ulong)p) {
432 LinPageUnLock(shared[i].global >> 12,shared[i].npages,PAGEMAPGLOBAL);
433 PageFree((ulong)shared[i].linear,0);
434 shared[i].linear = 0;
440 /****************************************************************************
442 Maps a shared memory block into process address space. Does nothing since
443 the memory blocks are already globally7 mapped into all processes.
444 ****************************************************************************/
445 void * PMAPI PM_mapToProcess(
452 ibool PMAPI PM_doBIOSPOST(
458 /* TODO: Figure out how to do this */
462 void * PMAPI PM_getBIOSPointer(void)
463 { return (void*)0x400; }
465 void * PMAPI PM_getA0000Pointer(void)
466 { return PM_mapPhysicalAddr(0xA0000,0xFFFF,true); }
468 /****************************************************************************
470 base - Physical base address of the memory to maps in
471 limit - Limit of physical memory to region to maps in
474 Linear address of the newly mapped memory.
477 Maps a physical memory range to a linear memory range.
478 ****************************************************************************/
479 ulong _PM_mapPhysicalToLinear(
484 ulong linear,length = limit+1;
487 if (base < 0x100000) {
488 /* Windows 9x is zero based for the first meg of memory */
492 *npages = (length + (base & 0xFFF) + 4095) >> 12;
493 flags = PR_FIXED | PR_STATIC;
494 if (base == 0xA0000) {
495 /* We require the linear address to be aligned to a 64Kb boundary
496 * for mapping the banked framebuffer (so we can do efficient
497 * carry checking for bank changes in the assembler code). The only
498 * way to ensure this is to force the linear address to be aligned
503 if ((linear = (ulong)PageReserve(PR_SYSTEM,*npages,flags)) == (ulong)-1)
505 if (!PageCommitPhys(linear >> 12,*npages,ppage,PC_INCR | PC_USER | PC_WRITEABLE))
507 return linear + (base & 0xFFF);
510 /* Page table flags */
512 #define PAGE_FLAGS_PRESENT 0x00000001
513 #define PAGE_FLAGS_WRITEABLE 0x00000002
514 #define PAGE_FLAGS_USER 0x00000004
515 #define PAGE_FLAGS_WRITE_THROUGH 0x00000008
516 #define PAGE_FLAGS_CACHE_DISABLE 0x00000010
517 #define PAGE_FLAGS_ACCESSED 0x00000020
518 #define PAGE_FLAGS_DIRTY 0x00000040
519 #define PAGE_FLAGS_4MB 0x00000080
521 /****************************************************************************
523 base - Physical base address of the memory to maps in
524 limit - Limit of physical memory to region to maps in
525 isCached - True if the memory should be cached, false if not
528 Linear address of the newly mapped memory.
531 This function maps physical memory to linear memory, which can then be used
532 to create a selector or used directly from 32-bit protected mode programs.
533 This is better than DPMI 0x800, since it allows you to maps physical
534 memory below 1Mb, which gets this memory out of the way of the Windows VDD's
537 NOTE: If the memory is not expected to be cached, this function will
538 directly re-program the PCD (Page Cache Disable) bit in the
539 page tables. There does not appear to be a mechanism in the VMM
540 to control this bit via the regular interface.
541 ****************************************************************************/
542 void * PMAPI PM_mapPhysicalAddr(
547 ulong linear,length = limit+1;
551 /* Search table of existing mappings to see if we have already mapped
552 * a region of memory that will serve this purpose.
554 for (i = 0; i < numMappings; i++) {
555 if (maps[i].physical == base && maps[i].length == length && maps[i].isCached == isCached)
556 return (void*)maps[i].linear;
558 if (numMappings == MAX_MEMORY_MAPPINGS)
561 /* We did not find any previously mapped memory region, so maps it in.
562 * Note that we do not use MapPhysToLinear, since this function appears
563 * to have problems mapping memory in the 1Mb physical address space.
564 * Hence we use PageReserve and PageCommitPhys.
566 if ((linear = _PM_mapPhysicalToLinear(base,limit,&npages)) == 0xFFFFFFFF)
568 maps[numMappings].physical = base;
569 maps[numMappings].length = length;
570 maps[numMappings].linear = linear;
571 maps[numMappings].npages = npages;
572 maps[numMappings].isCached = isCached;
575 /* Finally disable caching where necessary */
576 if (!isCached && (PDB = _PM_getPDB()) != 0) {
577 int startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage;
578 ulong pageTable,*pPageTable;
579 pPDB = (ulong*)_PM_mapPhysicalToLinear(PDB,0xFFF,&npages);
581 startPDB = (linear >> 22) & 0x3FF;
582 startPage = (linear >> 12) & 0x3FF;
583 endPDB = ((linear+limit) >> 22) & 0x3FF;
584 endPage = ((linear+limit) >> 12) & 0x3FF;
585 for (iPDB = startPDB; iPDB <= endPDB; iPDB++) {
586 /* Set the bits in the page directory entry - required as per */
587 /* Pentium 4 manual. This also takes care of the 4MB page entries */
588 pPDB[iPDB] = pPDB[iPDB] |= (PAGE_FLAGS_WRITE_THROUGH | PAGE_FLAGS_CACHE_DISABLE);
589 if (!(pPDB[iPDB] & PAGE_FLAGS_4MB)) {
590 /* If we are dealing with 4KB pages then we need to iterate */
591 /* through each of the page table entries */
592 pageTable = pPDB[iPDB] & ~0xFFF;
593 pPageTable = (ulong*)_PM_mapPhysicalToLinear(pageTable,0xFFF,&npages);
594 start = (iPDB == startPDB) ? startPage : 0;
595 end = (iPDB == endPDB) ? endPage : 0x3FF;
596 for (iPage = start; iPage <= end; iPage++)
597 pPageTable[iPage] |= (PAGE_FLAGS_WRITE_THROUGH | PAGE_FLAGS_CACHE_DISABLE);
598 PageFree((ulong)pPageTable,PR_STATIC);
601 PageFree((ulong)pPDB,PR_STATIC);
605 return (void*)linear;
608 void PMAPI PM_freePhysicalAddr(
612 /* We never free the mappings */
615 void PMAPI PM_sleep(ulong milliseconds)
617 /* We never sleep in a VxD */
620 int PMAPI PM_getCOMPort(int port)
622 /* TODO: Re-code this to determine real values using the Plug and Play */
623 /* manager for the OS. */
625 case 0: return 0x3F8;
626 case 1: return 0x2F8;
627 case 2: return 0x3E8;
628 case 3: return 0x2E8;
633 int PMAPI PM_getLPTPort(int port)
635 /* TODO: Re-code this to determine real values using the Plug and Play */
636 /* manager for the OS. */
638 case 0: return 0x3BC;
639 case 1: return 0x378;
640 case 2: return 0x278;
645 ulong PMAPI PM_getPhysicalAddr(
650 /* Touch the memory before calling CopyPageTable. For some reason */
651 /* we need to do this on Windows 9x, otherwise the memory may not */
652 /* be paged in correctly. Of course if the passed in pointer is */
653 /* invalid, this function will fault, but we shouldn't be passed bogus */
654 /* pointers anyway ;-) */
657 /* Return assembled address value only if VMM service succeeds */
658 if (CopyPageTable(((DWORD)p) >> 12, 1, (PVOID*)&pte, 0))
659 return (pte & ~0xFFF) | (((DWORD)p) & 0xFFF);
661 /* Return failure to the caller! */
665 ibool PMAPI PM_getPhysicalAddrRange(
671 ulong linear = (ulong)p & ~0xFFF;
673 for (i = (length + 0xFFF) >> 12; i > 0; i--) {
674 if ((*physAddress++ = PM_getPhysicalAddr((void*)linear)) == 0xFFFFFFFF)
681 void PMAPI _PM_freeMemoryMappings(void)
684 for (i = 0; i < numMappings; i++)
685 PageFree(maps[i].linear,PR_STATIC);
688 void * PMAPI PM_mapRealPointer(
692 return (void*)MK_PHYS(r_seg,r_off);
695 void * PMAPI PM_allocRealSeg(
703 void PMAPI PM_freeRealSeg(
708 void PMAPI DPMI_int86(
715 /****************************************************************************
717 Load the V86 registers in the client state, and save the original state
718 before loading the registers.
719 ****************************************************************************/
720 static void LoadV86Registers(
721 CLIENT_STRUCT *saveRegs,
725 CLIENT_STRUCT newRegs;
727 Save_Client_State(saveRegs);
729 newRegs.CRS.Client_EAX = in->e.eax;
730 newRegs.CRS.Client_EBX = in->e.ebx;
731 newRegs.CRS.Client_ECX = in->e.ecx;
732 newRegs.CRS.Client_EDX = in->e.edx;
733 newRegs.CRS.Client_ESI = in->e.esi;
734 newRegs.CRS.Client_EDI = in->e.edi;
735 newRegs.CRS.Client_ES = sregs->es;
736 newRegs.CRS.Client_DS = sregs->ds;
737 Restore_Client_State(&newRegs);
740 /****************************************************************************
742 Read the V86 registers from the client state and restore the original state.
743 ****************************************************************************/
744 static void ReadV86Registers(
745 CLIENT_STRUCT *saveRegs,
749 CLIENT_STRUCT newRegs;
751 Save_Client_State(&newRegs);
752 out->e.eax = newRegs.CRS.Client_EAX;
753 out->e.ebx = newRegs.CRS.Client_EBX;
754 out->e.ecx = newRegs.CRS.Client_ECX;
755 out->e.edx = newRegs.CRS.Client_EDX;
756 out->e.esi = newRegs.CRS.Client_ESI;
757 out->e.edi = newRegs.CRS.Client_EDI;
758 sregs->es = newRegs.CRS.Client_ES;
759 sregs->ds = newRegs.CRS.Client_DS;
760 Restore_Client_State(saveRegs);
763 /****************************************************************************
765 Call a V86 real mode function with the specified register values
766 loaded before the call. The call returns with a far ret.
767 ****************************************************************************/
768 void PMAPI PM_callRealMode(
774 CLIENT_STRUCT saveRegs;
776 /* Bail if we do not have BIOS access (ie: the VxD was dynamically
777 * loaded, and not statically loaded.
782 _TRACE("SDDHELP: Entering PM_callRealMode()\n");
783 Begin_Nest_V86_Exec();
784 LoadV86Registers(&saveRegs,regs,sregs);
785 Simulate_Far_Call(seg, off);
787 ReadV86Registers(&saveRegs,regs,sregs);
789 _TRACE("SDDHELP: Exiting PM_callRealMode()\n");
792 /****************************************************************************
794 Issue a V86 real mode interrupt with the specified register values
795 loaded before the interrupt.
796 ****************************************************************************/
803 CLIENT_STRUCT saveRegs;
806 /* Bail if we do not have BIOS access (ie: the VxD was dynamically
807 * loaded, and not statically loaded.
814 /* Disable pass-up to our VxD handler so we directly call BIOS */
815 _TRACE("SDDHELP: Entering PM_int86()\n");
816 if (disableTSRFlag) {
817 oldDisable = *disableTSRFlag;
820 Begin_Nest_V86_Exec();
821 LoadV86Registers(&saveRegs,in,&sregs);
823 ReadV86Registers(&saveRegs,out,&sregs);
826 /* Re-enable pass-up to our VxD handler if previously enabled */
828 *disableTSRFlag = oldDisable;
830 _TRACE("SDDHELP: Exiting PM_int86()\n");
834 /****************************************************************************
836 Issue a V86 real mode interrupt with the specified register values
837 loaded before the interrupt.
838 ****************************************************************************/
845 CLIENT_STRUCT saveRegs;
848 /* Bail if we do not have BIOS access (ie: the VxD was dynamically
849 * loaded, and not statically loaded.
856 /* Disable pass-up to our VxD handler so we directly call BIOS */
857 _TRACE("SDDHELP: Entering PM_int86x()\n");
858 if (disableTSRFlag) {
859 oldDisable = *disableTSRFlag;
862 Begin_Nest_V86_Exec();
863 LoadV86Registers(&saveRegs,in,sregs);
865 ReadV86Registers(&saveRegs,out,sregs);
868 /* Re-enable pass-up to our VxD handler if previously enabled */
870 *disableTSRFlag = oldDisable;
872 _TRACE("SDDHELP: Exiting PM_int86x()\n");
876 /****************************************************************************
878 Returns available memory. Not possible under Windows.
879 ****************************************************************************/
880 void PMAPI PM_availableMemory(
884 *physical = *total = 0;
887 /****************************************************************************
889 Allocates a block of locked physical memory.
890 ****************************************************************************/
891 void * PMAPI PM_allocLockedMem(
898 DWORD nPages = (size + 0xFFF) >> 12;
899 DWORD flags = PAGEFIXED | PAGEUSEALIGN | (contiguous ? PAGECONTIG : 0);
900 DWORD maxPhys = below16M ? 0x00FFFFFF : 0xFFFFFFFF;
903 /* TODO: This may need to be modified if the memory needs to be globally */
904 /* accessible. Check how we implemented PM_mallocShared() as we */
905 /* may need to do something similar in here. */
906 PageAllocate(nPages,PG_SYS,0,0,0,maxPhys,physAddr,flags,&hMem,&p);
908 /* TODO: We may need to modify the memory blocks to disable caching via */
909 /* the page tables (PCD|PWT) since DMA memory blocks *cannot* be */
914 /****************************************************************************
916 Frees a block of locked physical memory.
917 ****************************************************************************/
918 void PMAPI PM_freeLockedMem(
924 PageFree((ulong)p,0);
927 /****************************************************************************
929 Allocates a page aligned and page sized block of memory
930 ****************************************************************************/
931 void * PMAPI PM_allocPage(
937 /* TODO: This will need to be modified if the memory needs to be globally */
938 /* accessible. Check how we implemented PM_mallocShared() as we */
939 /* may need to do something similar in here. */
940 PageAllocate(1,PG_SYS,0,0,0,0,0,PAGEFIXED,&hMem,&p);
944 /****************************************************************************
946 Free a page aligned and page sized block of memory
947 ****************************************************************************/
948 void PMAPI PM_freePage(
952 PageFree((ulong)p,0);
955 /****************************************************************************
957 Lock linear memory so it won't be paged.
958 ****************************************************************************/
959 int PMAPI PM_lockDataPages(
964 DWORD pgNum = (ulong)p >> 12;
965 DWORD nPages = (len + (ulong)p - (pgNum << 12) + 0xFFF) >> 12;
966 return LinPageLock(pgNum,nPages,0);
969 /****************************************************************************
971 Unlock linear memory so it won't be paged.
972 ****************************************************************************/
973 int PMAPI PM_unlockDataPages(
978 DWORD pgNum = (ulong)p >> 12;
979 DWORD nPages = (len + (ulong)p - (pgNum << 12) + 0xFFF) >> 12;
980 return LinPageUnLock(pgNum,nPages,0);
983 /****************************************************************************
985 Lock linear memory so it won't be paged.
986 ****************************************************************************/
987 int PMAPI PM_lockCodePages(
992 return PM_lockDataPages((void*)p,len,lh);
995 /****************************************************************************
997 Unlock linear memory so it won't be paged.
998 ****************************************************************************/
999 int PMAPI PM_unlockCodePages(
1004 return PM_unlockDataPages((void*)p,len,lh);
1007 /****************************************************************************
1009 Set the real time clock frequency (for stereo modes).
1010 ****************************************************************************/
1011 void PMAPI PM_setRealTimeClockFrequency(
1014 static short convert[] = {
1032 /* First clear any pending RTC timeout if not cleared */
1034 if (frequency == 0) {
1035 /* Disable RTC timout */
1036 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA);
1037 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB & 0x0F);
1040 /* Convert frequency value to RTC clock indexes */
1041 for (i = 0; convert[i] != -1; i++) {
1042 if (convert[i] == frequency)
1046 /* Set RTC timout value and enable timeout */
1047 _PM_writeCMOS(0x0A,0x20 | (i+3));
1048 _PM_writeCMOS(0x0B,(_PM_oldCMOSRegB & 0x0F) | 0x40);
1052 /****************************************************************************
1054 Real time clock interrupt handler, which calls the user registered C code.
1055 ****************************************************************************/
1056 static BOOL __stdcall RTCInt_Handler(
1060 static char inside = 0;
1062 /* Clear priority interrupt controller and re-enable interrupts so we
1063 * dont lock things up for long.
1065 VPICD_Phys_EOI(hIRQ);
1067 /* Clear real-time clock timeout */
1070 /* Now call the C based interrupt handler (but check for mutual
1071 * exclusion since we may still be servicing an old interrupt when a
1072 * new one comes along; if that happens we ignore the old one).
1083 /****************************************************************************
1085 Set the real time clock handler (used for software stereo modes).
1086 ****************************************************************************/
1087 ibool PMAPI PM_setRealTimeClockHandler(
1091 struct VPICD_IRQ_Descriptor IRQdesc;
1093 /* Save the old CMOS real time clock values */
1094 _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
1095 _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
1097 /* Set the real time clock interrupt handler */
1099 _PM_rtcHandler = ih;
1100 IRQdesc.VID_IRQ_Number = 0x8;
1101 IRQdesc.VID_Options = 0;
1102 IRQdesc.VID_Hw_Int_Proc = (DWORD)VPICD_Thunk_HWInt(RTCInt_Handler, &RTCInt_Thunk);
1103 IRQdesc.VID_EOI_Proc = 0;
1104 IRQdesc.VID_Virt_Int_Proc = 0;
1105 IRQdesc.VID_Mask_Change_Proc= 0;
1106 IRQdesc.VID_IRET_Proc = 0;
1107 IRQdesc.VID_IRET_Time_Out = 500;
1108 if ((RTCIRQHandle = VPICD_Virtualize_IRQ(&IRQdesc)) == 0)
1111 /* Program the real time clock default frequency */
1112 PM_setRealTimeClockFrequency(frequency);
1114 /* Unmask IRQ8 in the PIC */
1115 VPICD_Physically_Unmask(RTCIRQHandle);
1119 /****************************************************************************
1121 Restore the original real time clock handler.
1122 ****************************************************************************/
1123 void PMAPI PM_restoreRealTimeClockHandler(void)
1126 /* Restore CMOS registers and mask RTC clock */
1127 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA);
1128 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB);
1130 /* Restore the interrupt vector */
1131 VPICD_Set_Auto_Masking(RTCIRQHandle);
1132 VPICD_Force_Default_Behavior(RTCIRQHandle);
1137 /****************************************************************************
1139 OS specific shared libraries not supported inside a VxD
1140 ****************************************************************************/
1141 PM_MODULE PMAPI PM_loadLibrary(
1142 const char *szDLLName)
1148 /****************************************************************************
1150 OS specific shared libraries not supported inside a VxD
1151 ****************************************************************************/
1152 void * PMAPI PM_getProcAddress(
1154 const char *szProcName)
1161 /****************************************************************************
1163 OS specific shared libraries not supported inside a VxD
1164 ****************************************************************************/
1165 void PMAPI PM_freeLibrary(
1171 /****************************************************************************
1173 Function to find the first file matching a search criteria in a directory.
1174 ****************************************************************************/
1175 void *PMAPI PM_findFirstFile(
1176 const char *filename,
1177 PM_findData *findData)
1179 /* TODO: This function should start a directory enumeration search */
1180 /* given the filename (with wildcards). The data should be */
1181 /* converted and returned in the findData standard form. */
1184 return PM_FILE_INVALID;
1187 /****************************************************************************
1189 Function to find the next file matching a search criteria in a directory.
1190 ****************************************************************************/
1191 ibool PMAPI PM_findNextFile(
1193 PM_findData *findData)
1195 /* TODO: This function should find the next file in directory enumeration */
1196 /* search given the search criteria defined in the call to */
1197 /* PM_findFirstFile. The data should be converted and returned */
1198 /* in the findData standard form. */
1204 /****************************************************************************
1206 Function to close the find process
1207 ****************************************************************************/
1208 void PMAPI PM_findClose(
1211 /* TODO: This function should close the find process. This may do */
1212 /* nothing for some OS'es. */
1216 /****************************************************************************
1218 Function to determine if a drive is a valid drive or not. Under Unix this
1219 function will return false for anything except a value of 3 (considered
1220 the root drive, and equivalent to C: for non-Unix systems). The drive
1228 ****************************************************************************/
1229 ibool PMAPI PM_driveValid(
1232 /* Not supported in a VxD */
1237 /****************************************************************************
1239 Function to get the current working directory for the specififed drive.
1240 Under Unix this will always return the current working directory regardless
1241 of what the value of 'drive' is.
1242 ****************************************************************************/
1243 void PMAPI PM_getdcwd(
1248 /* Not supported in a VxD */
1254 /****************************************************************************
1256 base - The starting physical base address of the region
1257 size - The size in bytes of the region
1258 type - Type to place into the MTRR register
1261 Error code describing the result.
1264 Function to enable write combining for the specified region of memory.
1265 ****************************************************************************/
1266 int PMAPI PM_enableWriteCombine(
1271 return MTRR_enableWriteCombine(base,size,type);
1274 /****************************************************************************
1276 Function to change the file attributes for a specific file.
1277 ****************************************************************************/
1278 void PMAPI PM_setFileAttr(
1279 const char *filename,
1282 /* TODO: Implement this */
1285 PM_fatalError("PM_setFileAttr not implemented yet!");
1288 /****************************************************************************
1290 Function to get the file attributes for a specific file.
1291 ****************************************************************************/
1292 uint PMAPI PM_getFileAttr(
1293 const char *filename)
1295 /* TODO: Implement this */
1297 PM_fatalError("PM_getFileAttr not implemented yet!");
1301 /****************************************************************************
1303 Function to create a directory.
1304 ****************************************************************************/
1305 ibool PMAPI PM_mkdir(
1306 const char *filename)
1308 /* TODO: Implement this */
1310 PM_fatalError("PM_mkdir not implemented yet!");
1314 /****************************************************************************
1316 Function to remove a directory.
1317 ****************************************************************************/
1318 ibool PMAPI PM_rmdir(
1319 const char *filename)
1321 /* TODO: Implement this */
1323 PM_fatalError("PM_rmdir not implemented yet!");
1327 /****************************************************************************
1329 Function to get the file time and date for a specific file.
1330 ****************************************************************************/
1331 ibool PMAPI PM_getFileTime(
1332 const char *filename,
1336 /* TODO: Implement this! */
1340 PM_fatalError("PM_getFileTime not implemented yet!");
1344 /****************************************************************************
1346 Function to set the file time and date for a specific file.
1347 ****************************************************************************/
1348 ibool PMAPI PM_setFileTime(
1349 const char *filename,
1353 /* TODO: Implement this! */
1357 PM_fatalError("PM_setFileTime not implemented yet!");