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 SMX embedded systems development.
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"
48 #include <sys/nearptr.h>
57 /*--------------------------- Global variables ----------------------------*/
64 #define MAX_RM_BLOCKS 10
69 } rmBlocks[MAX_RM_BLOCKS];
71 static uint VESABuf_len = 1024; /* Length of the VESABuf buffer */
72 static void *VESABuf_ptr = NULL; /* Near pointer to VESABuf */
73 static uint VESABuf_rseg; /* Real mode segment of VESABuf */
74 static uint VESABuf_roff; /* Real mode offset of VESABuf */
75 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
76 ushort _VARAPI _PM_savedDS = 0;
77 static ulong PDB = 0,*pPDB = NULL;
78 static uint VXD_version = -1;
80 /*----------------------------- Implementation ----------------------------*/
82 ulong _ASMAPI _PM_getPDB(void);
83 void _ASMAPI _PM_VxDCall(VXD_regs *regs,uint off,uint sel);
85 /****************************************************************************
87 External function to call the PMHELP helper VxD.
88 ****************************************************************************/
89 void PMAPI PM_VxDCall(
94 /****************************************************************************
96 BCD coded version number of the VxD, or 0 if not loaded (ie: 0x202 - 2.2)
99 This function gets the version number for the VxD that we have connected to.
100 ****************************************************************************/
101 uint PMAPI PMHELP_getVersion(void)
103 return VXD_version = 0;
106 void PMAPI PM_init(void)
113 /****************************************************************************
115 base - The starting physical base address of the region
116 size - The size in bytes of the region
117 type - Type to place into the MTRR register
120 Error code describing the result.
123 Function to enable write combining for the specified region of memory.
124 ****************************************************************************/
125 int PMAPI PM_enableWriteCombine(
131 return MTRR_enableWriteCombine(base,size,type);
133 return PM_MTRR_NOT_SUPPORTED;
137 ibool PMAPI PM_haveBIOSAccess(void)
140 long PMAPI PM_getOSType(void)
143 int PMAPI PM_getModeType(void)
146 void PMAPI PM_backslash(char *s)
148 uint pos = strlen(s);
149 if (s[pos-1] != '\\') {
155 void PMAPI PM_setFatalErrorCleanup(
156 void (PMAPIP cleanup)(void))
158 fatalErrorCleanup = cleanup;
161 void MGLOutput(char *);
163 void PMAPI PM_fatalError(const char *msg)
165 if (fatalErrorCleanup)
168 // No support for fprintf() under smx currently!
169 // fprintf(stderr,"%s\n", msg);
173 static void ExitVBEBuf(void)
176 PM_freeRealSeg(VESABuf_ptr);
180 void * PMAPI PM_getVESABuf(uint *len,uint *rseg,uint *roff)
183 /* Allocate a global buffer for communicating with the VESA VBE */
184 if ((VESABuf_ptr = PM_allocRealSeg(VESABuf_len, &VESABuf_rseg, &VESABuf_roff)) == NULL)
189 *rseg = VESABuf_rseg;
190 *roff = VESABuf_roff;
194 int PMAPI PM_int386(int intno, PMREGS *in, PMREGS *out)
198 return PM_int386x(intno,in,out,&sregs);
201 /* Routines to set and get the real mode interrupt vectors, by making
202 * direct real mode calls to DOS and bypassing the DOS extenders API.
203 * This is the safest way to handle this, as some servers try to be
204 * smart about changing real mode vectors.
207 void PMAPI _PM_getRMvect(int intno, long *realisr)
215 PM_int86x(0x21, ®s, ®s, &sregs);
216 *realisr = ((long)sregs.es << 16) | regs.x.bx;
219 void PMAPI _PM_setRMvect(int intno, long realisr)
227 sregs.ds = (int)(realisr >> 16);
228 regs.x.dx = (int)(realisr & 0xFFFF);
229 PM_int86x(0x21, ®s, ®s, &sregs);
232 void PMAPI _PM_addRealModeBlock(void *mem,uint tag)
236 for (i = 0; i < MAX_RM_BLOCKS; i++) {
237 if (rmBlocks[i].p == NULL) {
239 rmBlocks[i].tag = tag;
243 PM_fatalError("To many real mode memory block allocations!");
246 uint PMAPI _PM_findRealModeBlock(void *mem)
250 for (i = 0; i < MAX_RM_BLOCKS; i++) {
251 if (rmBlocks[i].p == mem)
252 return rmBlocks[i].tag;
254 PM_fatalError("Could not find prior real mode memory block allocation!");
258 char * PMAPI PM_getCurrentPath(
262 return getcwd(path,maxLen);
265 char PMAPI PM_getBootDrive(void)
268 const char * PMAPI PM_getVBEAFPath(void)
271 const char * PMAPI PM_getNucleusPath(void)
273 static char path[256];
276 if ((env = getenv("NUCLEUS_PATH")) != NULL)
278 return "c:\\nucleus";
281 const char * PMAPI PM_getNucleusConfigPath(void)
283 static char path[256];
284 strcpy(path,PM_getNucleusPath());
286 strcat(path,"config");
290 const char * PMAPI PM_getUniqueID(void)
293 const char * PMAPI PM_getMachineName(void)
296 int PMAPI PM_kbhit(void)
301 hit = EVT_peekNext(&evt,EVT_KEYDOWN | EVT_KEYREPEAT);
302 EVT_flush(~(EVT_KEYDOWN | EVT_KEYREPEAT));
306 int PMAPI PM_getch(void)
310 EVT_halt(&evt,EVT_KEYDOWN);
311 return EVT_asciiCode(evt.message);
314 PM_HWND PMAPI PM_openConsole(PM_HWND hwndUser,int device,int xRes,int yRes,int bpp,ibool fullScreen)
316 /* Not used for SMX */
326 int PMAPI PM_getConsoleStateSize(void)
328 return sizeof(DOS_stateBuf);
331 void PMAPI PM_saveConsoleState(void *stateBuf,PM_HWND hwndConsole)
334 DOS_stateBuf *sb = stateBuf;
336 /* Save the old video mode state */
338 PM_int86(0x10,®s,®s);
339 sb->oldMode = regs.h.al & 0x7F;
340 sb->old50Lines = false;
341 if (sb->oldMode == 0x3) {
345 PM_int86(0x10,®s,®s);
346 sb->old50Lines = (regs.h.dl == 42 || regs.h.dl == 49);
351 void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags))
353 /* Not used for SMX */
357 void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND hwndConsole)
360 const DOS_stateBuf *sb = stateBuf;
362 /* Retore 50 line mode if set */
363 if (sb->old50Lines) {
366 PM_int86(0x10,®s,®s);
371 void PMAPI PM_closeConsole(PM_HWND hwndConsole)
373 /* Not used for SMX */
377 void PMAPI PM_setOSCursorLocation(int x,int y)
379 uchar *_biosPtr = PM_getBIOSPointer();
380 PM_setByte(_biosPtr+0x50,x);
381 PM_setByte(_biosPtr+0x51,y);
384 void PMAPI PM_setOSScreenWidth(int width,int height)
386 uchar *_biosPtr = PM_getBIOSPointer();
387 PM_setWord(_biosPtr+0x4A,width);
388 PM_setWord(_biosPtr+0x4C,width*2);
389 PM_setByte(_biosPtr+0x84,height-1);
391 PM_setWord(_biosPtr+0x60,0x0607);
392 PM_setByte(_biosPtr+0x85,0x08);
395 PM_setWord(_biosPtr+0x60,0x0D0E);
396 PM_setByte(_biosPtr+0x85,0x016);
400 void * PMAPI PM_mallocShared(long size)
402 return PM_malloc(size);
405 void PMAPI PM_freeShared(void *ptr)
410 #define GetRMVect(intno,isr) *(isr) = ((ulong*)rmZeroPtr)[intno]
411 #define SetRMVect(intno,isr) ((ulong*)rmZeroPtr)[intno] = (isr)
413 ibool PMAPI PM_doBIOSPOST(
419 static int firstTime = true;
420 static uchar *rmZeroPtr;
421 long Current10,Current6D,Current42;
425 /* Create a zero memory mapping for us to use */
427 rmZeroPtr = PM_mapPhysicalAddr(0,0x7FFF,true);
431 /* Remap the secondary BIOS to 0xC0000 physical */
432 if (BIOSPhysAddr != 0xC0000L || BIOSLen > 32768) {
433 /* SMX cannot virtually remap the BIOS, so we can only work if all
434 * the secondary controllers are identical, and we then use the
435 * BIOS on the first controller for all the remaining controllers.
437 * For OS'es that do virtual memory, and remapping of 0xC0000
438 * physical (perhaps a copy on write mapping) should be all that
444 /* Save current handlers of int 10h and 6Dh */
445 GetRMVect(0x10,&Current10);
446 GetRMVect(0x6D,&Current6D);
448 /* POST the secondary BIOS */
449 GetRMVect(0x42,&Current42);
450 SetRMVect(0x10,Current42); /* Restore int 10h to STD-BIOS */
452 PM_callRealMode(0xC000,0x0003,®s,&sregs);
454 /* Restore current handlers */
455 SetRMVect(0x10,Current10);
456 SetRMVect(0x6D,Current6D);
458 /* Second the primary BIOS mappin 1:1 for 0xC0000 physical */
459 if (BIOSPhysAddr != 0xC0000L) {
460 /* SMX does not support this */
466 void PMAPI PM_sleep(ulong milliseconds)
468 ulong microseconds = milliseconds * 1000L;
472 while (LZTimerLapExt(&tm) < microseconds)
477 int PMAPI PM_getCOMPort(int port)
480 case 0: return 0x3F8;
481 case 1: return 0x2F8;
486 int PMAPI PM_getLPTPort(int port)
489 case 0: return 0x3BC;
490 case 1: return 0x378;
491 case 2: return 0x278;
496 PM_MODULE PMAPI PM_loadLibrary(
497 const char *szDLLName)
503 void * PMAPI PM_getProcAddress(
505 const char *szProcName)
512 void PMAPI PM_freeLibrary(
518 int PMAPI PM_setIOPL(
524 /****************************************************************************
526 Internal function to convert the find data to the generic interface.
527 ****************************************************************************/
528 static void convertFindData(
529 PM_findData *findData,
532 ulong dwSize = findData->dwSize;
534 memset(findData,0,findData->dwSize);
535 findData->dwSize = dwSize;
536 if (blk->attrib & _A_RDONLY)
537 findData->attrib |= PM_FILE_READONLY;
538 if (blk->attrib & _A_SUBDIR)
539 findData->attrib |= PM_FILE_DIRECTORY;
540 if (blk->attrib & _A_ARCH)
541 findData->attrib |= PM_FILE_ARCHIVE;
542 if (blk->attrib & _A_HIDDEN)
543 findData->attrib |= PM_FILE_HIDDEN;
544 if (blk->attrib & _A_SYSTEM)
545 findData->attrib |= PM_FILE_SYSTEM;
546 findData->sizeLo = blk->size;
547 strncpy(findData->name,blk->name,PM_MAX_PATH);
548 findData->name[PM_MAX_PATH-1] = 0;
551 #define FIND_MASK (_A_RDONLY | _A_ARCH | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM)
553 /****************************************************************************
555 Function to find the first file matching a search criteria in a directory.
556 ****************************************************************************/
557 void * PMAPI PM_findFirstFile(
558 const char *filename,
559 PM_findData *findData)
563 if ((blk = PM_malloc(sizeof(*blk))) == NULL)
564 return PM_FILE_INVALID;
565 if (_dos_findfirst((char*)filename,FIND_MASK,blk) == 0) {
566 convertFindData(findData,blk);
569 return PM_FILE_INVALID;
572 /****************************************************************************
574 Function to find the next file matching a search criteria in a directory.
575 ****************************************************************************/
576 ibool PMAPI PM_findNextFile(
578 PM_findData *findData)
580 struct find_t *blk = handle;
582 if (_dos_findnext(blk) == 0) {
583 convertFindData(findData,blk);
589 /****************************************************************************
591 Function to close the find process
592 ****************************************************************************/
593 void PMAPI PM_findClose(
599 /****************************************************************************
601 Function to determine if a drive is a valid drive or not. Under Unix this
602 function will return false for anything except a value of 3 (considered
603 the root drive, and equivalent to C: for non-Unix systems). The drive
611 ****************************************************************************/
612 ibool PMAPI PM_driveValid(
616 regs.h.dl = (uchar)(drive - 'A' + 1);
617 regs.h.ah = 0x36; // Get disk information service
618 PM_int86(0x21,®s,®s);
619 return regs.x.ax != 0xFFFF; // AX = 0xFFFF if disk is invalid
622 /****************************************************************************
624 Function to get the current working directory for the specififed drive.
625 Under Unix this will always return the current working directory regardless
626 of what the value of 'drive' is.
627 ****************************************************************************/
628 void PMAPI PM_getdcwd(
633 uint oldDrive,maxDrives;
634 _dos_getdrive(&oldDrive);
635 _dos_setdrive(drive,&maxDrives);
637 _dos_setdrive(oldDrive,&maxDrives);
640 /****************************************************************************
642 Function to change the file attributes for a specific file.
643 ****************************************************************************/
644 void PMAPI PM_setFileAttr(
645 const char *filename,
648 #if defined(TNT) && defined(_MSC_VER)
651 if (attrib & PM_FILE_READONLY)
652 attr |= FILE_ATTRIBUTE_READONLY;
653 if (attrib & PM_FILE_ARCHIVE)
654 attr |= FILE_ATTRIBUTE_ARCHIVE;
655 if (attrib & PM_FILE_HIDDEN)
656 attr |= FILE_ATTRIBUTE_HIDDEN;
657 if (attrib & PM_FILE_SYSTEM)
658 attr |= FILE_ATTRIBUTE_SYSTEM;
659 SetFileAttributes((LPSTR)filename, attr);
663 if (attrib & PM_FILE_READONLY)
665 if (attrib & PM_FILE_ARCHIVE)
667 if (attrib & PM_FILE_HIDDEN)
669 if (attrib & PM_FILE_SYSTEM)
671 _dos_setfileattr(filename,attr);
675 /****************************************************************************
677 Function to create a directory.
678 ****************************************************************************/
679 ibool PMAPI PM_mkdir(
680 const char *filename)
683 return mkdir(filename,S_IRUSR) == 0;
685 //AM: return mkdir(filename) == 0;
690 /****************************************************************************
692 Function to remove a directory.
693 ****************************************************************************/
694 ibool PMAPI PM_rmdir(
695 const char *filename)
697 //AM: return rmdir(filename) == 0;
701 /****************************************************************************
703 Allocates a block of locked, physically contiguous memory. The memory
704 may be required to be below the 16Meg boundary.
705 ****************************************************************************/
706 void * PMAPI PM_allocLockedMem(
716 /* Under DOS the only way to know the physical memory address is to
717 * allocate the memory below the 1Meg boundary as real mode memory.
718 * We also allocate 4095 bytes more memory than we need, so we can
719 * properly page align the start of the memory block for DMA operations.
723 if ((p = PM_allocRealSeg((size + 0xFFF) & ~0xFFF,&r_seg,&r_off)) == NULL)
725 *physAddr = ((r_seg << 4) + r_off + 0xFFF) & ~0xFFF;
726 PM_lockDataPages(p,size*2,&lh);
730 void PMAPI PM_freeLockedMem(void *p,uint size,ibool contiguous)
736 /*-------------------------------------------------------------------------*/
737 /* Generic DPMI routines common to 16/32 bit code */
738 /*-------------------------------------------------------------------------*/
740 ulong PMAPI DPMI_mapPhysicalToLinear(ulong physAddr,ulong limit)
745 if (physAddr < 0x100000L) {
746 /* We can't map memory below 1Mb, but the linear address are already
747 * mapped 1:1 for this memory anyway so we just return the base address.
752 /* Round the physical address to a 4Kb boundary and the limit to a
753 * 4Kb-1 boundary before passing the values to DPMI as some extenders
754 * will fail the calls unless this is the case. If we round the
755 * physical address, then we also add an extra offset into the address
758 physOfs = physAddr & 4095;
759 physAddr = physAddr & ~4095;
760 limit = ((limit+physOfs+1+4095) & ~4095)-1;
762 r.x.ax = 0x800; /* DPMI map physical to linear */
763 r.x.bx = physAddr >> 16;
764 r.x.cx = physAddr & 0xFFFF;
765 r.x.si = limit >> 16;
766 r.x.di = limit & 0xFFFF;
767 PM_int386(0x31, &r, &r);
770 return ((ulong)r.x.bx << 16) + r.x.cx + physOfs;
773 int PMAPI DPMI_setSelectorBase(ushort sel,ulong linAddr)
777 r.x.ax = 7; /* DPMI set selector base address */
779 r.x.cx = linAddr >> 16;
780 r.x.dx = linAddr & 0xFFFF;
781 PM_int386(0x31, &r, &r);
787 ulong PMAPI DPMI_getSelectorBase(ushort sel)
791 r.x.ax = 6; /* DPMI get selector base address */
793 PM_int386(0x31, &r, &r);
794 return ((ulong)r.x.cx << 16) + r.x.dx;
797 int PMAPI DPMI_setSelectorLimit(ushort sel,ulong limit)
801 r.x.ax = 8; /* DPMI set selector limit */
803 r.x.cx = limit >> 16;
804 r.x.dx = limit & 0xFFFF;
805 PM_int386(0x31, &r, &r);
811 uint PMAPI DPMI_createSelector(ulong base,ulong limit)
816 /* Allocate 1 descriptor */
819 PM_int386(0x31, &r, &r);
820 if (r.x.cflag) return 0;
823 /* Set the descriptor access rights (for a 32 bit page granular
829 PM_int386(0x31, &r, &r);
831 /* Map physical memory and create selector */
832 if ((base = DPMI_mapPhysicalToLinear(base,limit)) == 0xFFFFFFFFUL)
834 if (!DPMI_setSelectorBase(sel,base))
836 if (!DPMI_setSelectorLimit(sel,limit))
841 void PMAPI DPMI_freeSelector(uint sel)
847 PM_int386(0x31, &r, &r);
850 int PMAPI DPMI_lockLinearPages(ulong linear,ulong len)
854 r.x.ax = 0x600; /* DPMI Lock Linear Region */
855 r.x.bx = (linear >> 16); /* Linear address in BX:CX */
856 r.x.cx = (linear & 0xFFFF);
857 r.x.si = (len >> 16); /* Length in SI:DI */
858 r.x.di = (len & 0xFFFF);
859 PM_int386(0x31, &r, &r);
863 int PMAPI DPMI_unlockLinearPages(ulong linear,ulong len)
867 r.x.ax = 0x601; /* DPMI Unlock Linear Region */
868 r.x.bx = (linear >> 16); /* Linear address in BX:CX */
869 r.x.cx = (linear & 0xFFFF);
870 r.x.si = (len >> 16); /* Length in SI:DI */
871 r.x.di = (len & 0xFFFF);
872 PM_int386(0x31, &r, &r);
876 void * PMAPI DPMI_mapPhysicalAddr(ulong base,ulong limit,ibool isCached)
882 /* Get the base address for the default DS selector */
884 DSBaseAddr = DPMI_getSelectorBase(sregs.ds);
885 if ((base < 0x100000) && (DSBaseAddr == 0)) {
886 /* DS is zero based, so we can directly access the first 1Mb of
887 * system memory (like under DOS4GW).
892 /* Map the memory to a linear address using DPMI function 0x800 */
893 if ((linAddr = DPMI_mapPhysicalToLinear(base,limit)) == 0) {
894 if (base >= 0x100000)
896 /* If the linear address mapping fails but we are trying to
897 * map an area in the first 1Mb of system memory, then we must
898 * be running under a Windows or OS/2 DOS box. Under these
899 * environments we can use the segment wrap around as a fallback
900 * measure, as this does work properly.
905 /* Now expand the default DS selector to 4Gb so we can access it */
906 if (!DPMI_setSelectorLimit(sregs.ds,0xFFFFFFFFUL))
909 /* Finally enable caching for the page tables that we just mapped in,
910 * since DOS4GW and PMODE/W create the page table entries without
911 * caching enabled which hurts the performance of the linear framebuffer
912 * as it disables write combining on Pentium Pro and above processors.
914 * For those processors cache disabling is better handled through the
915 * MTRR registers anyway (we can write combine a region but disable
916 * caching) so that MMIO register regions do not screw up.
919 if ((PDB = _PM_getPDB()) != 0 && DSBaseAddr == 0) {
920 int startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage;
921 ulong pageTable,*pPageTable;
924 pPDB = (ulong*)DPMI_mapPhysicalToLinear(PDB,0xFFF);
929 startPDB = (linAddr >> 22) & 0x3FF;
930 startPage = (linAddr >> 12) & 0x3FF;
931 endPDB = ((linAddr+limit) >> 22) & 0x3FF;
932 endPage = ((linAddr+limit) >> 12) & 0x3FF;
933 for (iPDB = startPDB; iPDB <= endPDB; iPDB++) {
934 pageTable = pPDB[iPDB] & ~0xFFF;
935 if (pageTable >= 0x100000)
936 pPageTable = (ulong*)DPMI_mapPhysicalToLinear(pageTable,0xFFF);
938 pPageTable = (ulong*)pageTable;
939 start = (iPDB == startPDB) ? startPage : 0;
940 end = (iPDB == endPDB) ? endPage : 0x3FF;
941 for (iPage = start; iPage <= end; iPage++)
942 pPageTable[iPage] &= ~0x18;
948 /* Now return the base address of the memory into the default DS */
949 return (void*)(linAddr - DSBaseAddr);
952 /* Some DOS extender implementations do not directly support calling a
953 * real mode procedure from protected mode. However we can simulate what
954 * we need temporarily hooking the INT 6Ah vector with a small real mode
955 * stub that will call our real mode code for us.
958 static uchar int6AHandler[] = {
959 0x00,0x00,0x00,0x00, /* __PMODE_callReal variable */
961 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PMODE_callReal] */
964 static uchar *crPtr = NULL; /* Pointer to of int 6A handler */
965 static uint crRSeg,crROff; /* Real mode seg:offset of handler */
967 void PMAPI PM_callRealMode(uint seg,uint off, RMREGS *in,
974 /* Allocate and copy the memory block only once */
975 crPtr = PM_allocRealSeg(sizeof(int6AHandler), &crRSeg, &crROff);
976 memcpy(crPtr,int6AHandler,sizeof(int6AHandler));
978 PM_setWord(crPtr,off); /* Plug in address to call */
979 PM_setWord(crPtr+2,seg);
980 p = PM_mapRealPointer(0,0x6A * 4);
981 oldOff = PM_getWord(p); /* Save old handler address */
982 oldSeg = PM_getWord(p+2);
983 PM_setWord(p,crROff+4); /* Hook 6A handler */
984 PM_setWord(p+2,crRSeg);
985 PM_int86x(0x6A, in, in, sregs); /* Call real mode code */
986 PM_setWord(p,oldOff); /* Restore old handler */
987 PM_setWord(p+2,oldSeg);
990 void * PMAPI PM_getBIOSPointer(void)
991 { return PM_mapPhysicalAddr(0x400,0xFFFF,true); }
993 void * PMAPI PM_getA0000Pointer(void)
994 { return PM_mapPhysicalAddr(0xA0000,0xFFFF,true); }
996 void * PMAPI PM_mapPhysicalAddr(ulong base,ulong limit,ibool isCached)
997 { return DPMI_mapPhysicalAddr(base,limit,isCached); }
999 void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit)
1001 /* Mapping cannot be free */
1004 ulong PMAPI PM_getPhysicalAddr(void *p)
1006 // TODO: This function should find the physical address of a linear
1009 return 0xFFFFFFFFUL;
1012 void * PMAPI PM_mapToProcess(void *base,ulong limit)
1018 void * PMAPI PM_mapRealPointer(uint r_seg,uint r_off)
1020 static uchar *zeroPtr = NULL;
1023 zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF,true);
1024 return (void*)(zeroPtr + MK_PHYS(r_seg,r_off));
1027 void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off)
1032 r.x.ax = 0x100; /* DPMI allocate DOS memory */
1033 r.x.bx = (size + 0xF) >> 4; /* number of paragraphs */
1034 PM_int386(0x31, &r, &r);
1036 return NULL; /* DPMI call failed */
1037 *r_seg = r.x.ax; /* Real mode segment */
1039 p = PM_mapRealPointer(*r_seg,*r_off);
1040 _PM_addRealModeBlock(p,r.x.dx);
1044 void PMAPI PM_freeRealSeg(void *mem)
1048 r.x.ax = 0x101; /* DPMI free DOS memory */
1049 r.x.dx = _PM_findRealModeBlock(mem);/* DX := selector from 0x100 */
1050 PM_int386(0x31, &r, &r);
1053 static DPMI_handler_t DPMI_int10 = NULL;
1055 void PMAPI DPMI_setInt10Handler(DPMI_handler_t handler)
1057 DPMI_int10 = handler;
1060 void PMAPI DPMI_int86(int intno, DPMI_regs *regs)
1065 if (intno == 0x10 && DPMI_int10) {
1066 if (DPMI_int10(regs))
1070 r.x.ax = 0x300; /* DPMI issue real interrupt */
1075 r.e.edi = (uint)regs;
1076 PM_int386x(0x31, &r, &r, &sr); /* Issue the interrupt */
1079 #define IN(reg) rmregs.reg = in->e.reg
1080 #define OUT(reg) out->e.reg = rmregs.reg
1082 int PMAPI PM_int86(int intno, RMREGS *in, RMREGS *out)
1086 memset(&rmregs, 0, sizeof(rmregs));
1087 IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);
1089 // These real mode ints may cause crashes.
1090 //AM: DPMI_int86(intno,&rmregs); /* DPMI issue real interrupt */
1092 OUT(eax); OUT(ebx); OUT(ecx); OUT(edx); OUT(esi); OUT(edi);
1093 out->x.cflag = rmregs.flags & 0x1;
1097 int PMAPI PM_int86x(int intno, RMREGS *in, RMREGS *out,
1102 memset(&rmregs, 0, sizeof(rmregs));
1103 IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);
1104 rmregs.es = sregs->es;
1105 rmregs.ds = sregs->ds;
1107 //AM: DPMI_int86(intno,&rmregs); /* DPMI issue real interrupt */
1109 OUT(eax); OUT(ebx); OUT(ecx); OUT(edx); OUT(esi); OUT(edi);
1110 sregs->es = rmregs.es;
1111 sregs->cs = rmregs.cs;
1112 sregs->ss = rmregs.ss;
1113 sregs->ds = rmregs.ds;
1114 out->x.cflag = rmregs.flags & 0x1;
1121 uint LargestBlockAvail;
1122 uint MaxUnlockedPage;
1123 uint LargestLockablePage;
1125 uint NumFreePagesAvail;
1126 uint NumPhysicalPagesFree;
1127 uint TotalPhysicalPages;
1128 uint FreeLinAddrSpace;
1129 uint SizeOfPageFile;
1135 void PMAPI PM_availableMemory(ulong *physical,ulong *total)
1142 r.x.ax = 0x500; /* DPMI get free memory info */
1144 r.e.edi = (uint)&memInfo;
1145 PM_int386x(0x31, &r, &r, &sr); /* Issue the interrupt */
1146 *physical = memInfo.NumPhysicalPagesFree * 4096;
1147 *total = memInfo.LargestBlockAvail;
1148 if (*total < *physical)
1152 /****************************************************************************
1154 Function to get the file attributes for a specific file.
1155 ****************************************************************************/
1156 uint PMAPI PM_getFileAttr(
1157 const char *filename)
1159 // TODO: Implement this!
1163 /****************************************************************************
1165 Function to get the file time and date for a specific file.
1166 ****************************************************************************/
1167 ibool PMAPI PM_getFileTime(
1168 const char *filename,
1172 // TODO: Implement this!
1176 /****************************************************************************
1178 Function to set the file time and date for a specific file.
1179 ****************************************************************************/
1180 ibool PMAPI PM_setFileTime(
1181 const char *filename,
1185 // TODO: Implement this!