| /**************************************************************************** |
| * |
| * SciTech Nucleus Graphics Architecture |
| * |
| * Copyright (C) 1991-1998 SciTech Software, Inc. |
| * All rights reserved. |
| * |
| * ====================================================================== |
| * |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW| |
| * | | |
| * |This copyrighted computer code contains proprietary technology | |
| * |owned by SciTech Software, Inc., located at 505 Wall Street, | |
| * |Chico, CA 95928 USA (http://www.scitechsoft.com). | |
| * | | |
| * |The contents of this file are subject to the SciTech Nucleus | |
| * |License; you may *not* use this file or related software except in | |
| * |compliance with the License. You may obtain a copy of the License | |
| * |at http://www.scitechsoft.com/nucleus-license.txt | |
| * | | |
| * |Software distributed under the License is distributed on an | |
| * |"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
| * |implied. See the License for the specific language governing | |
| * |rights and limitations under the License. | |
| * | | |
| * |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW| |
| * ====================================================================== |
| * |
| * Language: ANSI C |
| * Environment: Any 32-bit protected mode environment |
| * |
| * Description: C module for the Graphics Accelerator Driver API. Uses |
| * the SciTech PM library for interfacing with DOS |
| * extender specific functions. |
| * |
| ****************************************************************************/ |
| |
| #include "nucleus/graphics.h" |
| #include "nucleus/agp.h" |
| |
| /*---------------------------- Global Variables ---------------------------*/ |
| |
| #ifndef DEBUG_AGP_DRIVER |
| static AGP_exports _AGP_exports; |
| static int loaded = false; |
| static PE_MODULE *hModBPD = NULL; |
| |
| static N_imports _N_imports = { |
| sizeof(N_imports), |
| _OS_delay, |
| }; |
| |
| static AGP_imports _AGP_imports = { |
| sizeof(AGP_imports), |
| }; |
| #endif |
| |
| #include "pmimp.h" |
| |
| /*----------------------------- Implementation ----------------------------*/ |
| |
| #define DLL_NAME "agp.bpd" |
| |
| #ifndef DEBUG_AGP_DRIVER |
| /**************************************************************************** |
| REMARKS: |
| Fatal error handler for non-exported GA_exports. |
| ****************************************************************************/ |
| static void _AGP_fatalErrorHandler(void) |
| { |
| PM_fatalError("Unsupported AGP export function called! Please upgrade your copy of AGP!\n"); |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| shared - True to load the driver into shared memory. |
| |
| REMARKS: |
| Loads the Nucleus binary portable DLL into memory and initilises it. |
| ****************************************************************************/ |
| static ibool LoadDriver(void) |
| { |
| AGP_initLibrary_t AGP_initLibrary; |
| AGP_exports *agpExp; |
| char filename[PM_MAX_PATH]; |
| char bpdpath[PM_MAX_PATH]; |
| int i,max; |
| ulong *p; |
| |
| /* Check if we have already loaded the driver */ |
| if (loaded) |
| return true; |
| PM_init(); |
| |
| /* Open the BPD file */ |
| if (!PM_findBPD(DLL_NAME,bpdpath)) |
| return false; |
| strcpy(filename,bpdpath); |
| strcat(filename,DLL_NAME); |
| if ((hModBPD = PE_loadLibrary(filename,false)) == NULL) |
| return false; |
| if ((AGP_initLibrary = (AGP_initLibrary_t)PE_getProcAddress(hModBPD,"_AGP_initLibrary")) == NULL) |
| return false; |
| bpdpath[strlen(bpdpath)-1] = 0; |
| if (strcmp(bpdpath,PM_getNucleusPath()) == 0) |
| strcpy(bpdpath,PM_getNucleusConfigPath()); |
| else { |
| PM_backslash(bpdpath); |
| strcat(bpdpath,"config"); |
| } |
| if ((agpExp = AGP_initLibrary(bpdpath,filename,GA_getSystemPMImports(),&_N_imports,&_AGP_imports)) == NULL) |
| PM_fatalError("AGP_initLibrary failed!\n"); |
| _AGP_exports.dwSize = sizeof(_AGP_exports); |
| max = sizeof(_AGP_exports)/sizeof(AGP_initLibrary_t); |
| for (i = 0,p = (ulong*)&_AGP_exports; i < max; i++) |
| *p++ = (ulong)_AGP_fatalErrorHandler; |
| memcpy(&_AGP_exports,agpExp,MIN(sizeof(_AGP_exports),agpExp->dwSize)); |
| loaded = true; |
| return true; |
| } |
| |
| /* The following are stub entry points that the application calls to |
| * initialise the Nucleus loader library, and we use this to load our |
| * driver DLL from disk and initialise the library using it. |
| */ |
| |
| /* {secret} */ |
| int NAPI AGP_status(void) |
| { |
| if (!loaded) |
| return nDriverNotFound; |
| return _AGP_exports.AGP_status(); |
| } |
| |
| /* {secret} */ |
| const char * NAPI AGP_errorMsg( |
| N_int32 status) |
| { |
| if (!loaded) |
| return "Unable to load Nucleus device driver!"; |
| return _AGP_exports.AGP_errorMsg(status); |
| } |
| |
| /* {secret} */ |
| AGP_devCtx * NAPI AGP_loadDriver(N_int32 deviceIndex) |
| { |
| if (!LoadDriver()) |
| return NULL; |
| return _AGP_exports.AGP_loadDriver(deviceIndex); |
| } |
| |
| /* {secret} */ |
| void NAPI AGP_unloadDriver( |
| AGP_devCtx *dc) |
| { |
| if (loaded) |
| _AGP_exports.AGP_unloadDriver(dc); |
| } |
| |
| /* {secret} */ |
| void NAPI AGP_getGlobalOptions( |
| AGP_globalOptions *options) |
| { |
| if (LoadDriver()) |
| _AGP_exports.AGP_getGlobalOptions(options); |
| } |
| |
| /* {secret} */ |
| void NAPI AGP_setGlobalOptions( |
| AGP_globalOptions *options) |
| { |
| if (LoadDriver()) |
| _AGP_exports.AGP_setGlobalOptions(options); |
| } |
| |
| /* {secret} */ |
| void NAPI AGP_saveGlobalOptions( |
| AGP_globalOptions *options) |
| { |
| if (loaded) |
| _AGP_exports.AGP_saveGlobalOptions(options); |
| } |
| #endif |
| |
| /* {secret} */ |
| void NAPI _OS_delay8253(N_uint32 microSeconds); |
| |
| /**************************************************************************** |
| REMARKS: |
| This function delays for the specified number of microseconds |
| ****************************************************************************/ |
| void NAPI _OS_delay( |
| N_uint32 microSeconds) |
| { |
| static ibool inited = false; |
| static ibool haveRDTSC; |
| LZTimerObject tm; |
| |
| if (!inited) { |
| #ifndef __WIN32_VXD__ |
| /* This has been causing problems in VxD's for some reason, so for now */ |
| /* we avoid using it. */ |
| if (_GA_haveCPUID() && (_GA_getCPUIDFeatures() & CPU_HaveRDTSC) != 0) { |
| ZTimerInit(); |
| haveRDTSC = true; |
| } |
| else |
| #endif |
| haveRDTSC = false; |
| inited = true; |
| } |
| if (haveRDTSC) { |
| LZTimerOnExt(&tm); |
| while (LZTimerLapExt(&tm) < microSeconds) |
| ; |
| LZTimerOnExt(&tm); |
| } |
| else |
| _OS_delay8253(microSeconds); |
| } |