// // Shared Memory Manager // #ifndef _H_SHM #define _H_SHM #include #include #include #include #include // // List of component IDs for the data blocks passed around using shared // memory. // #define SHM_OA_DATA 0 #define SHM_OA_FAST 1 #define SHM_BA_FAST 2 #define SHM_CM_FAST 3 // // Number of components (actual number of entries in the above list). // #define SHM_NUM_COMPONENTS 4 // // Structure to keep track of the buffer being used to pass data between // the display driver and the share core. // // busyFlag - indicates whether the display driver is using the memory // // newBuffer - index for which buffer the display driver should next // use to access the memory. // // currentBuffer - index for the buffer in use by the display driver if // busyFlag is set. // THIS FIELD IS USED ONLY BY THE DISPLAY DRIVER // // indexCount - count of how many times we have recursed into accessing // the buffer. The busyFlag and currentBuffer should only // be updated if indexCount was set to or changed from 0. // THIS FIELD IS USED ONLY BY THE DISPLAY DRIVER // // bufferBusy - indicates whether a particular buffer is being used // by the display driver. // // typedef struct tagBUFFER_CONTROL { long busyFlag; long newBuffer; long currentBuffer; long indexCount; long bufferBusy[2]; } BUFFER_CONTROL; typedef BUFFER_CONTROL FAR * LPBUFFER_CONTROL; // // Shared memory as used by the display driver and share core to // communicate. // // On Win95, we can not easily address memory that isn't in a 64K segment // So on both platforms, when we map the shared memory, we also return pointers // to the CM_FAST_DATA structures anda the OA_FAST_DATA structures, each of // which lives in its own segment. // // On NT, the CM_FAST_DATA blocks come right after this one, then the // OA_SHARED_DATA blocks. // // // GENERAL // ======= // // dataChanged - flags to indicate if a data block has been altered // (only used by the share core) // // FAST PATH DATA // ============== // // fastPath - buffer controls // // oaFast - OA fast changing data // // baFast - BA fast changing data // // DISPLAY DRIVER -> SHARE CORE // ============================ // // displayToCore - buffer controls // // typedef struct tagSHM_SHARED_MEMORY { // // Flag set by display driver when the display is in full screen mode. // (e.g. DOS full screen). // DWORD fullScreen; // // Flag set by display driver or core when system palette has altered // LONG pmPaletteChanged; // // Flag set by display driver when the cursor is hidden. // LONG cmCursorHidden; // // Data passed from the Display Driver up to the Share Core. // BUFFER_CONTROL displayToCore; long dataChanged[SHM_NUM_COMPONENTS]; // // Data passed regularly from the Display Driver to the Share Core. // // This buffer is switched on each periodic processing by the share // core. If the criteria for reading are satisfied, the main DD->SHCO // buffer is switched. // BUFFER_CONTROL fastPath; BA_FAST_DATA baFast[2]; OA_FAST_DATA oaFast[2]; CM_FAST_DATA cmFast[2]; // // DO NOT BUMP SHARED MEMORY SIZE PAST 64K // 16-bit display driver puts each oaData in a 64K block // The SHM_ESC_MAP_MEMORY request returns back the pointers // to each oaData in addition to the shared memory block. In the // the case of the 32-bit NT display driver, the memory allocated is // in fact contiguous, so there's no waste in that case. // } SHM_SHARED_MEMORY; typedef SHM_SHARED_MEMORY FAR * LPSHM_SHARED_MEMORY; // // Macros to access the shared memory // // // OVERVIEW // ~~~~~~~~ // // Note the following sets of macros are split into two parts - one for // accessing memory from the NT kernel and one for the Share Core. This // code plays a significant role in the synchronization of the shared // memory, so make sure you know how it works... // // The shared memory is double buffered, so that the kernel mode display // driver can come in at any point and is NEVER blocked by the share core // for access. The data is split into two major blocks - one to pass data // from the kernel to the Share Core and the other to pass the data back. // // The macros assume a certain structure to the shared memory which is // described below. // // NO VALIDATION OF POINTERS IS DONE IN THESE MACROS. // // // DISPLAY DRIVER ACCESS // ~~~~~~~~~~~~~~~~~~~~~ // // ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ // ³ Shared Memory ³ // ³ ~~~~~~~~~~~~~ ³ // ³ ³ // ³ ÉÍÍÍÍÍÍÍÍÍÍÍ» ÉÍÍÍÍÍÍÍÍÍÍÍ» ³ // ³ º º º º ³ // ³ º kernel º º fast path º ³ // ³ º -> SHCO º º º ³ // ³ º º º º ³ // ³ º º º º ³ // ³ º (details º º º ³ // ³ º below) º º º ³ // ³ º º º º ³ // ³ ÈÍÍÍÍÍÍÍÍÍÍͼ ÈÍÍÍÍÍÍÍÍÍÍͼ ³ // ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ // // // // ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» // º Kernel to share core data block º // º ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ º // º ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ º // º ³ ³ busyFlag ³ ³ º // º ³ Share Core ³ 1 ³ Display Driver³ º // º ³ ³ ³ ³ º // º ³ (read buffer) ³ newBuffer ³ (write buffer)³ º // º ³ ³ ³ ³ ³ º // º ³ ³<ÄÄÄÄÄÄÁÄÄÄÄÄÄ>³ ³ º // º ³ bufferBusy ³ ³ bufferBusy ³ º // º ³ 0 ³ ³ 1 ³ º // º ³ ³ currentBuffer ³ ³ º // º ³ ³ ³ ³ ³ º // º ³ ³ ÀÄÄÄÄÄÄ>³ ³ º // º ³ ³ ³ ³ º // º ³ ³ ³ ³ º // º ³ ³ indexCount ³ ³ º // º ³ ³ 5 ³ ³ º // º ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ º // º º // º º // ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ // // The entire major block has a busyFlag, which indicates if the display // driver is accessing any of its shared memory. This flag is set as soon // as the display driver needs access to the shared memory (i.e. on entry // to the display driver graphics functions). // // The display driver then reads the index (newBuffer in the above drawing) // to decide which buffer to use. This is stored in the currentBuffer // index to use until the display driver releases the shared memory. The // secondary bufferBusy is now set for the buffer in use. // // The indexCount is maintained of the number of times the display driver // has started access to a block of memory so that (both) busyFlag and // bufferBusy can be released when the display driver has truly finished // with the memory. // // // SHARE CORE ACCESS // ~~~~~~~~~~~~~~~~~ // // To access the shared memory, the share core just pulls out the data from // the buffer that the Share Core is not using (ie. the buffer pointed to // by NOT newBuffer). // // The synchronization between the two processes comes from the buffer // switch. // // // BUFFER SWITCHING (AND SYNCHRONIZATION) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Buffer switching is determined by the Share Core. Data is accumulated // by the Share Core and sent on the periodic timing events. For full // details on the swapping method, refer to NSHMINT.C // // Data (such as window tracking) can be passed down at the meoment it is // generated by using the OSI functions. // // The Share Core also determines when it wants to get the latest set of // orders and screen data area and forces the switch. This is detailed in // NSHMINT.C // // // THE MACROS! // ~~~~~~~~~~~ // // So, now we know a bit about the shared memory, what macros do we have to // access the shared memory? Here goes... // // // SHM_SYNC_READ - Force a sync of the read buffer between the tasks. // This should be called only by the Share Core. // // SHM_SYNC_FAST - Force a sync of the fast path buffer. // This should be called only by the Share Core. // // #ifdef DLL_DISP LPVOID SHM_StartAccess(int block); void SHM_StopAccess(int block); // // Macro to check any pointers that we are going to dereference. // #ifdef _DEBUG void SHM_CheckPointer(LPVOID ptr); #else #define SHM_CheckPointer(ptr) #endif // _DEBUG #else // !DLL_DISP void SHM_SwitchReadBuffer(void); void SHM_SwitchFastBuffer(void); #endif // DLL_DISP #endif // _H_SHM