303 lines
9.5 KiB
C
303 lines
9.5 KiB
C
//
|
||
// Shared Memory Manager
|
||
//
|
||
|
||
#ifndef _H_SHM
|
||
#define _H_SHM
|
||
|
||
|
||
#include <oa.h>
|
||
#include <ba.h>
|
||
#include <osi.h>
|
||
#include <sbc.h>
|
||
#include <cm.h>
|
||
|
||
|
||
//
|
||
// 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
|
||
// ~~~~~~~~~~~~~~~~~~~~~
|
||
//
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
||
// <20> Shared Memory <20>
|
||
// <20> ~~~~~~~~~~~~~ <20>
|
||
// <20> <20>
|
||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> kernel <20> <20> fast path <20> <20>
|
||
// <20> <20> -> SHCO <20> <20> <20> <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> (details <20> <20> <20> <20>
|
||
// <20> <20> below) <20> <20> <20> <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ <20>
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//
|
||
//
|
||
//
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ
|
||
// <20> Kernel to share core data block <20>
|
||
// <20> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <20>
|
||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20>
|
||
// <20> <20> <20> busyFlag <20> <20> <20>
|
||
// <20> <20> Share Core <20> 1 <20> Display Driver<65> <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> (read buffer) <20> newBuffer <20> (write buffer)<29> <20>
|
||
// <20> <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> <20><<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>><3E> <20> <20>
|
||
// <20> <20> bufferBusy <20> <20> bufferBusy <20> <20>
|
||
// <20> <20> 0 <20> <20> 1 <20> <20>
|
||
// <20> <20> <20> currentBuffer <20> <20> <20>
|
||
// <20> <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>><3E> <20> <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> <20> <20> <20> <20>
|
||
// <20> <20> <20> indexCount <20> <20> <20>
|
||
// <20> <20> <20> 5 <20> <20> <20>
|
||
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>
|
||
// <20> <20>
|
||
// <20> <20>
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ
|
||
//
|
||
// 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
|
||
|