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: *** TODO: ADD YOUR OS ENVIRONMENT NAME HERE ***
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"
41 /* TODO: Include any OS specific headers here! */
43 /*--------------------------- Global variables ----------------------------*/
45 /* TODO: If you support access to the BIOS, the following VESABuf globals */
46 /* keep track of a single VESA transfer buffer. If you don't support */
47 /* access to the BIOS, remove these variables. */
49 static uint VESABuf_len = 1024; /* Length of the VESABuf buffer */
50 static void *VESABuf_ptr = NULL; /* Near pointer to VESABuf */
51 static uint VESABuf_rseg; /* Real mode segment of VESABuf */
52 static uint VESABuf_roff; /* Real mode offset of VESABuf */
54 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
56 /*----------------------------- Implementation ----------------------------*/
58 /****************************************************************************
60 Initialise the PM library.
61 ****************************************************************************/
62 void PMAPI PM_init(void)
64 /* TODO: Do any initialisation in here. This includes getting IOPL */
65 /* access for the process calling PM_init. This will get called */
68 /* TODO: If you support the supplied MTRR register stuff (you need to */
69 /* be at ring 0 for this!), you should initialise it in here. */
74 /****************************************************************************
76 Return the operating system type identifier.
77 ****************************************************************************/
78 long PMAPI PM_getOSType(void)
80 /* TODO: Change this to return the define for your OS from drvlib/os.h */
84 /****************************************************************************
86 Return the runtime type identifier (always PM_386 for protected mode)
87 ****************************************************************************/
88 int PMAPI PM_getModeType(void)
91 /****************************************************************************
93 Add a file directory separator to the end of the filename.
94 ****************************************************************************/
95 void PMAPI PM_backslash(
99 if (s[pos-1] != '/') {
105 /****************************************************************************
107 Add a user defined PM_fatalError cleanup function.
108 ****************************************************************************/
109 void PMAPI PM_setFatalErrorCleanup(
110 void (PMAPIP cleanup)(void))
112 fatalErrorCleanup = cleanup;
115 /****************************************************************************
117 Report a fatal error condition and halt the program.
118 ****************************************************************************/
119 void PMAPI PM_fatalError(
122 /* TODO: If you are running in a GUI environment without a console, */
123 /* this needs to be changed to bring up a fatal error message */
124 /* box and terminate the program. */
125 if (fatalErrorCleanup)
127 fprintf(stderr,"%s\n", msg);
131 /****************************************************************************
133 Exit handler to kill the VESA transfer buffer.
134 ****************************************************************************/
135 static void ExitVBEBuf(void)
137 /* TODO: If you do not have BIOS access, remove this function. */
139 PM_freeRealSeg(VESABuf_ptr);
143 /****************************************************************************
145 Allocate the real mode VESA transfer buffer for communicating with the BIOS.
146 ****************************************************************************/
147 void * PMAPI PM_getVESABuf(
152 /* TODO: If you do not have BIOS access, simply delete the guts of */
153 /* this function and return NULL. */
155 /* Allocate a global buffer for communicating with the VESA VBE */
156 if ((VESABuf_ptr = PM_allocRealSeg(VESABuf_len, &VESABuf_rseg, &VESABuf_roff)) == NULL)
161 *rseg = VESABuf_rseg;
162 *roff = VESABuf_roff;
166 /****************************************************************************
168 Check if a key has been pressed.
169 ****************************************************************************/
170 int PMAPI PM_kbhit(void)
172 /* TODO: This function checks if a key is available to be read. This */
173 /* should be implemented, but is mostly used by the test programs */
178 /****************************************************************************
180 Wait for and return the next keypress.
181 ****************************************************************************/
182 int PMAPI PM_getch(void)
184 /* TODO: This returns the ASCII code of the key pressed. This */
185 /* should be implemented, but is mostly used by the test programs */
190 /****************************************************************************
192 Open a fullscreen console mode for output.
193 ****************************************************************************/
194 int PMAPI PM_openConsole(void)
196 /* TODO: Opens up a fullscreen console for graphics output. If your */
197 /* console does not have graphics/text modes, this can be left */
198 /* empty. The main purpose of this is to disable console switching */
199 /* when in graphics modes if you can switch away from fullscreen */
200 /* consoles (if you want to allow switching, this can be done */
201 /* elsewhere with a full save/restore state of the graphics mode). */
205 /****************************************************************************
207 Return the size of the state buffer used to save the console state.
208 ****************************************************************************/
209 int PMAPI PM_getConsoleStateSize(void)
211 /* TODO: Returns the size of the console state buffer used to save the */
212 /* state of the console before going into graphics mode. This is */
213 /* used to restore the console back to normal when we are done. */
217 /****************************************************************************
219 Save the state of the console into the state buffer.
220 ****************************************************************************/
221 void PMAPI PM_saveConsoleState(
225 /* TODO: Saves the state of the console into the state buffer. This is */
226 /* used to restore the console back to normal when we are done. */
227 /* We will always restore 80x25 text mode after being in graphics */
228 /* mode, so if restoring text mode is all you need to do this can */
232 /****************************************************************************
234 Restore the state of the console from the state buffer.
235 ****************************************************************************/
236 void PMAPI PM_restoreConsoleState(
237 const void *stateBuf,
240 /* TODO: Restore the state of the console from the state buffer. This is */
241 /* used to restore the console back to normal when we are done. */
242 /* We will always restore 80x25 text mode after being in graphics */
243 /* mode, so if restoring text mode is all you need to do this can */
247 /****************************************************************************
249 Close the console and return to non-fullscreen console mode.
250 ****************************************************************************/
251 void PMAPI PM_closeConsole(
254 /* TODO: Close the console when we are done, going back to text mode. */
257 /****************************************************************************
259 Set the location of the OS console cursor.
260 ****************************************************************************/
261 void PM_setOSCursorLocation(
265 /* TODO: Set the OS console cursor location to the new value. This is */
266 /* generally used for new OS ports (used mostly for DOS). */
269 /****************************************************************************
271 Set the width of the OS console.
272 ****************************************************************************/
273 void PM_setOSScreenWidth(
277 /* TODO: Set the OS console screen width. This is generally unused for */
281 /****************************************************************************
283 Set the real time clock handler (used for software stereo modes).
284 ****************************************************************************/
285 ibool PMAPI PM_setRealTimeClockHandler(
289 /* TODO: Install a real time clock interrupt handler. Normally this */
290 /* will not be supported from most OS'es in user land, so an */
291 /* alternative mechanism is needed to enable software stereo. */
292 /* Hence leave this unimplemented unless you have a high priority */
293 /* mechanism to call the 32-bit callback when the real time clock */
294 /* interrupt fires. */
298 /****************************************************************************
300 Set the real time clock frequency (for stereo modes).
301 ****************************************************************************/
302 void PMAPI PM_setRealTimeClockFrequency(
305 /* TODO: Set the real time clock interrupt frequency. Used for stereo */
306 /* LC shutter glasses when doing software stereo. Usually sets */
307 /* the frequency to around 2048 Hz. */
310 /****************************************************************************
312 Restore the original real time clock handler.
313 ****************************************************************************/
314 void PMAPI PM_restoreRealTimeClockHandler(void)
316 /* TODO: Restores the real time clock handler. */
319 /****************************************************************************
321 Return the current operating system path or working directory.
322 ****************************************************************************/
323 char * PMAPI PM_getCurrentPath(
327 return getcwd(path,maxLen);
330 /****************************************************************************
332 Return the drive letter for the boot drive.
333 ****************************************************************************/
334 char PMAPI PM_getBootDrive(void)
336 /* TODO: Return the boot drive letter for the OS. Normally this is 'c' */
337 /* for DOS based OS'es and '/' for Unices. */
341 /****************************************************************************
343 Return the path to the VBE/AF driver files (legacy and not used).
344 ****************************************************************************/
345 const char * PMAPI PM_getVBEAFPath(void)
347 return PM_getNucleusConfigPath();
350 /****************************************************************************
352 Return the path to the Nucleus driver files.
353 ****************************************************************************/
354 const char * PMAPI PM_getNucleusPath(void)
356 /* TODO: Change this to the default path to Nucleus driver files. The */
357 /* following is the default for Unices. */
358 char *env = getenv("NUCLEUS_PATH");
359 return env ? env : "/usr/lib/nucleus";
362 /****************************************************************************
364 Return the path to the Nucleus configuration files.
365 ****************************************************************************/
366 const char * PMAPI PM_getNucleusConfigPath(void)
368 static char path[256];
369 strcpy(path,PM_getNucleusPath());
371 strcat(path,"config");
375 /****************************************************************************
377 Return a unique identifier for the machine if possible.
378 ****************************************************************************/
379 const char * PMAPI PM_getUniqueID(void)
381 /* TODO: Return a unique ID for the machine. If a unique ID is not */
382 /* available, return the machine name. */
383 static char buf[128];
384 gethostname(buf, 128);
388 /****************************************************************************
390 Get the name of the machine on the network.
391 ****************************************************************************/
392 const char * PMAPI PM_getMachineName(void)
394 /* TODO: Return the network machine name for the machine. */
395 static char buf[128];
396 gethostname(buf, 128);
400 /****************************************************************************
402 Return a pointer to the real mode BIOS data area.
403 ****************************************************************************/
404 void * PMAPI PM_getBIOSPointer(void)
406 /* TODO: This returns a pointer to the real mode BIOS data area. If you */
407 /* do not support BIOS access, you can simply return NULL here. */
409 zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF,true);
410 return (void*)(zeroPtr + 0x400);
413 /****************************************************************************
415 Return a pointer to 0xA0000 physical VGA graphics framebuffer.
416 ****************************************************************************/
417 void * PMAPI PM_getA0000Pointer(void)
419 static void *bankPtr;
421 bankPtr = PM_mapPhysicalAddr(0xA0000,0xFFFF,true);
425 /****************************************************************************
427 Map a physical address to a linear address in the callers process.
428 ****************************************************************************/
429 void * PMAPI PM_mapPhysicalAddr(
434 /* TODO: This function maps a physical memory address to a linear */
435 /* address in the address space of the calling process. */
437 /* NOTE: This function *must* be able to handle any phsyical base */
438 /* address, and hence you will have to handle rounding of */
439 /* the physical base address to a page boundary (ie: 4Kb on */
440 /* x86 CPU's) to be able to properly map in the memory */
443 /* NOTE: If possible the isCached bit should be used to ensure that */
444 /* the PCD (Page Cache Disable) and PWT (Page Write Through) */
445 /* bits are set to disable caching for a memory mapping used */
446 /* for MMIO register access. We also disable caching using */
447 /* the MTRR registers for Pentium Pro and later chipsets so if */
448 /* MTRR support is enabled for your OS then you can safely ignore */
449 /* the isCached flag and always enable caching in the page */
454 /****************************************************************************
456 Free a physical address mapping allocated by PM_mapPhysicalAddr.
457 ****************************************************************************/
458 void PMAPI PM_freePhysicalAddr(
462 /* TODO: This function will free a physical memory mapping previously */
463 /* allocated with PM_mapPhysicalAddr() if at all possible. If */
464 /* you can't free physical memory mappings, simply do nothing. */
467 /****************************************************************************
469 Find the physical address of a linear memory address in current process.
470 ****************************************************************************/
471 ulong PMAPI PM_getPhysicalAddr(void *p)
473 /* TODO: This function should find the physical address of a linear */
478 void PMAPI PM_sleep(ulong milliseconds)
480 /* TODO: Put the process to sleep for milliseconds */
483 int PMAPI PM_getCOMPort(int port)
485 /* TODO: Re-code this to determine real values using the Plug and Play */
486 /* manager for the OS. */
488 case 0: return 0x3F8;
489 case 1: return 0x2F8;
494 int PMAPI PM_getLPTPort(int port)
496 /* TODO: Re-code this to determine real values using the Plug and Play */
497 /* manager for the OS. */
499 case 0: return 0x3BC;
500 case 1: return 0x378;
501 case 2: return 0x278;
506 /****************************************************************************
508 Allocate a block of (unnamed) shared memory.
509 ****************************************************************************/
510 void * PMAPI PM_mallocShared(
513 /* TODO: This is used to allocate memory that is shared between process */
514 /* that all access the common Nucleus drivers via a common display */
515 /* driver DLL. If your OS does not support shared memory (or if */
516 /* the display driver does not need to allocate shared memory */
517 /* for each process address space), this should just call PM_malloc. */
518 return PM_malloc(size);
521 /****************************************************************************
523 Free a block of shared memory.
524 ****************************************************************************/
525 void PMAPI PM_freeShared(
528 /* TODO: Free the shared memory block. This will be called in the context */
529 /* of the original calling process that allocated the shared */
530 /* memory with PM_mallocShared. Simply call PM_free if you do not */
535 /****************************************************************************
537 Map a linear memory address to the calling process address space. The
538 address will have been allocated in another process using the
539 PM_mapPhysicalAddr function.
540 ****************************************************************************/
541 void * PMAPI PM_mapToProcess(
545 /* TODO: This function is used to map a physical memory mapping */
546 /* previously allocated with PM_mapPhysicalAddr into the */
547 /* address space of the calling process. If the memory mapping */
548 /* allocated by PM_mapPhysicalAddr is global to all processes, */
549 /* simply return the pointer. */
551 /* NOTE: This function must also handle rounding to page boundaries, */
552 /* since this function is used to map in shared memory buffers */
553 /* allocated with PM_mapPhysicalAddr(). Hence if you aligned */
554 /* the physical address above, then you also need to do it here. */
558 /****************************************************************************
560 Map a real mode pointer to a protected mode pointer.
561 ****************************************************************************/
562 void * PMAPI PM_mapRealPointer(
566 /* TODO: This function maps a real mode memory pointer into the */
567 /* calling processes address space as a 32-bit near pointer. If */
568 /* you do not support BIOS access, simply return NULL here. */
570 zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF);
571 return (void*)(zeroPtr + MK_PHYS(r_seg,r_off));
574 /****************************************************************************
576 Allocate a block of real mode memory
577 ****************************************************************************/
578 void * PMAPI PM_allocRealSeg(
583 /* TODO: This function allocates a block of real mode memory for the */
584 /* calling process used to communicate with real mode BIOS */
585 /* functions. If you do not support BIOS access, simply return */
590 /****************************************************************************
592 Free a block of real mode memory.
593 ****************************************************************************/
594 void PMAPI PM_freeRealSeg(
597 /* TODO: Frees a previously allocated real mode memory block. If you */
598 /* do not support BIOS access, this function should be empty. */
601 /****************************************************************************
603 Issue a real mode interrupt (parameters in DPMI compatible structure)
604 ****************************************************************************/
605 void PMAPI DPMI_int86(
609 /* TODO: This function calls the real mode BIOS using the passed in */
610 /* register structure. If you do not support real mode BIOS */
611 /* access, this function should be empty. */
614 /****************************************************************************
616 Issue a real mode interrupt.
617 ****************************************************************************/
623 /* TODO: This function calls the real mode BIOS using the passed in */
624 /* register structure. If you do not support real mode BIOS */
625 /* access, this function should return 0. */
629 /****************************************************************************
631 Issue a real mode interrupt.
632 ****************************************************************************/
639 /* TODO: This function calls the real mode BIOS using the passed in */
640 /* register structure. If you do not support real mode BIOS */
641 /* access, this function should return 0. */
645 /****************************************************************************
647 Call a real mode far function.
648 ****************************************************************************/
649 void PMAPI PM_callRealMode(
655 /* TODO: This function calls a real mode far function with a far call. */
656 /* If you do not support BIOS access, this function should be */
660 /****************************************************************************
662 Return the amount of available memory.
663 ****************************************************************************/
664 void PMAPI PM_availableMemory(
668 /* TODO: Report the amount of available memory, both the amount of */
669 /* physical memory left and the amount of virtual memory left. */
670 /* If the OS does not provide these services, report 0's. */
671 *physical = *total = 0;
674 /****************************************************************************
676 Allocate a block of locked, physical memory for DMA operations.
677 ****************************************************************************/
678 void * PMAPI PM_allocLockedMem(
684 /* TODO: Allocate a block of locked, physical memory of the specified */
685 /* size. This is used for bus master operations. If this is not */
686 /* supported by the OS, return NULL and bus mastering will not */
691 /****************************************************************************
693 Free a block of locked physical memory.
694 ****************************************************************************/
695 void PMAPI PM_freeLockedMem(
700 /* TODO: Free a memory block allocated with PM_allocLockedMem. */
703 /****************************************************************************
705 Call the VBE/Core software interrupt to change display banks.
706 ****************************************************************************/
707 void PMAPI PM_setBankA(
712 /* TODO: This does a bank switch function by calling the real mode */
713 /* VESA BIOS. If you do not support BIOS access, this function should */
718 PM_int86(0x10,®s,®s);
721 /****************************************************************************
723 Call the VBE/Core software interrupt to change display banks.
724 ****************************************************************************/
725 void PMAPI PM_setBankAB(
730 /* TODO: This does a bank switch function by calling the real mode */
731 /* VESA BIOS. If you do not support BIOS access, this function should */
736 PM_int86(0x10,®s,®s);
740 PM_int86(0x10,®s,®s);
743 /****************************************************************************
745 Call the VBE/Core software interrupt to change display start address.
746 ****************************************************************************/
747 void PMAPI PM_setCRTStart(
754 /* TODO: This changes the display start address by calling the real mode */
755 /* VESA BIOS. If you do not support BIOS access, this function */
756 /* should be empty. */
761 PM_int86(0x10,®s,®s);
764 /****************************************************************************
766 Enable write combining for the memory region.
767 ****************************************************************************/
768 ibool PMAPI PM_enableWriteCombine(
773 /* TODO: This function should enable Pentium Pro and Pentium II MTRR */
774 /* write combining for the passed in physical memory base address */
775 /* and length. Normally this is done via calls to an OS specific */
776 /* device driver as this can only be done at ring 0. */
778 /* NOTE: This is a *very* important function to implement! If you do */
779 /* not implement, graphics performance on the latest Intel chips */
780 /* will be severly impaired. For sample code that can be used */
781 /* directly in a ring 0 device driver, see the MSDOS implementation */
782 /* which includes assembler code to do this directly (if the */
783 /* program is running at ring 0). */
787 /****************************************************************************
789 Execute the POST on the secondary BIOS for a controller.
790 ****************************************************************************/
791 ibool PMAPI PM_doBIOSPOST(
796 /* TODO: This function is used to run the BIOS POST code on a secondary */
797 /* controller to initialise it for use. This is not necessary */
798 /* for multi-controller operation, but it will make it a lot */
799 /* more convenicent for end users (otherwise they have to boot */
800 /* the system once with the secondary controller as primary, and */
801 /* then boot with both controllers installed). */
803 /* Even if you don't support full BIOS access, it would be */
804 /* adviseable to be able to POST the secondary controllers in the */
805 /* system using this function as a minimum requirement. Some */
806 /* graphics hardware has registers that contain values that only */
807 /* the BIOS knows about, which makes bring up a card from cold */
808 /* reset difficult if the BIOS has not POST'ed it. */
812 /****************************************************************************
814 Load an OS specific shared library or DLL. If the OS does not support
815 shared libraries, simply return NULL.
816 ****************************************************************************/
817 PM_MODULE PMAPI PM_loadLibrary(
818 const char *szDLLName)
820 /* TODO: This function should load a native shared library from disk */
821 /* given the path to the library. */
826 /****************************************************************************
828 Get the address of a named procedure from a shared library.
829 ****************************************************************************/
830 void * PMAPI PM_getProcAddress(
832 const char *szProcName)
834 /* TODO: This function should return the address of a named procedure */
835 /* from a native shared library. */
841 /****************************************************************************
843 Unload a shared library.
844 ****************************************************************************/
845 void PMAPI PM_freeLibrary(
848 /* TODO: This function free a previously loaded native shared library. */
852 /****************************************************************************
854 Enable requested I/O privledge level (usually only to set to a value of
855 3, and then restore it back again). If the OS is protected this function
856 must be implemented in order to enable I/O port access for ring 3
857 applications. The function should return the IOPL level active before
858 the switch occurred so it can be properly restored.
859 ****************************************************************************/
860 int PMAPI PM_setIOPL(
863 /* TODO: This function should enable IOPL for the task (if IOPL is */
864 /* not always enabled for the app through some other means). */
868 /****************************************************************************
870 Function to find the first file matching a search criteria in a directory.
871 ****************************************************************************/
872 void *PMAPI PM_findFirstFile(
873 const char *filename,
874 PM_findData *findData)
876 /* TODO: This function should start a directory enumeration search */
877 /* given the filename (with wildcards). The data should be */
878 /* converted and returned in the findData standard form. */
881 return PM_FILE_INVALID;
884 /****************************************************************************
886 Function to find the next file matching a search criteria in a directory.
887 ****************************************************************************/
888 ibool PMAPI PM_findNextFile(
890 PM_findData *findData)
892 /* TODO: This function should find the next file in directory enumeration */
893 /* search given the search criteria defined in the call to */
894 /* PM_findFirstFile. The data should be converted and returned */
895 /* in the findData standard form. */
901 /****************************************************************************
903 Function to close the find process
904 ****************************************************************************/
905 void PMAPI PM_findClose(
908 /* TODO: This function should close the find process. This may do */
909 /* nothing for some OS'es. */
913 /****************************************************************************
915 Function to determine if a drive is a valid drive or not. Under Unix this
916 function will return false for anything except a value of 3 (considered
917 the root drive, and equivalent to C: for non-Unix systems). The drive
925 ****************************************************************************/
926 ibool PMAPI PM_driveValid(
934 /****************************************************************************
936 Function to get the current working directory for the specififed drive.
937 Under Unix this will always return the current working directory regardless
938 of what the value of 'drive' is.
939 ****************************************************************************/
940 void PMAPI PM_getdcwd(
949 /****************************************************************************
951 Function to change the file attributes for a specific file.
952 ****************************************************************************/
953 void PMAPI PM_setFileAttr(
954 const char *filename,
957 /* TODO: Set the file attributes for a file */
962 /****************************************************************************
964 Function to create a directory.
965 ****************************************************************************/
966 ibool PMAPI PM_mkdir(
967 const char *filename)
969 return mkdir(filename) == 0;
972 /****************************************************************************
974 Function to remove a directory.
975 ****************************************************************************/
976 ibool PMAPI PM_rmdir(
977 const char *filename)
979 return rmdir(filename) == 0;