/*
Copyright (c) 1993 Xerox Corporation.  All rights reserved.
*/
/*
$Id$

$Date$
 *
 * Virtual Dirty bytes
 */

#ifndef ←←PCR←VD←h
#define ←←PCR←VD←h

#include <config/PCR←StdTypes.h>

/*
 * The dirty byte for a logical page contains a dirty bit
 *   and a write-protect disable count.
 * The implementation is not allowed to write-protect a page
 *   for which the disable count is nonzero; such pages may
 *   appear dirty.
 */

typedef volatile unsigned char PCR←VD←DB;

#define PCR←VD←DB←dirtyBit		0x1
#define PCR←VD←DB←disabledOnce		0x2
#define PCR←VD←DB←disabledMask		0xfe

/*
 * Initialization
 */

extern PCR←ERes
PCR←VD←Start(
    unsigned long pageSize,
    void * addr,
    unsigned long bytes
);
/*
    Start the package using the specified logical pagesize.
    Subsequent get/set/clear requests will only be allowed
      in the region [addr, addr+bytes).
    Pages in the region initially appear disabled and dirty.
*/

/*
 * Enable/Disable write-protecting pages.
 *
 * Disable-Enable pairs nest.
 *
 * These are intended to be fast enough to use in system
 *   call wrappers.
 */

extern void
PCR←VD←WriteProtectDisable(
    void *addr,
    unsigned long bytes
);
/*
    Ensure that logical pages in the specified range will not
      be write-protected.
    Such pages may always appear dirty.
    It is acceptable for [addr..addr+bytes) to extend outside
      the address range specified to PCR←VD←Start.
    This is a no-op if called before PCR←VD←Start.
*/


extern void
PCR←VD←WriteProtectEnable(
    void *addr,
    unsigned long bytes
);
/*
    Undo the effect of a previous PCR←VD←WriteProtectDisable.
    This needs to be called once after PCR←VD←Start to
      enable checking pages.
    It is acceptable for [addr..addr+bytes) to extend outside
      the address range specified to PCR←VD←Start.
    Immediately after enabling, a page may always appear dirty.
    Like PCR←VD←WriteProtectDisable, this is a no-op
      if called before PCR←VD←Start.
*/


extern void
PCR←VD←StackWriteProtectDisable(
    void *addr,
    unsigned long bytes
);

extern void
PCR←VD←StackWriteProtectEnable(
    void *addr,
    unsigned long bytes
);
/*
    Accelerator when pages are known to be on thread stacks.
*/
#define PCR←VD←StackWriteProtectDisable(a,b) { }

#define PCR←VD←StackWriteProtectEnable(a,b) { }
    /* for now the stacks are never write protected */


extern PCR←ERes
PCR←VD←InitWriteProtectDisabled(
    void *addr,
    unsigned long bytes
);
/*
    Set address range disabled as in PCR←VD←WriteProtectDisable.
    The client promises not to call PCR←VD←WriteProtectEnable on the range.
    Unlike PCR←VD←WriteProtectDisable, this proc is effective even if
      called before PCR←VD←Start; 
*/

/*
 * Dirty Byte manipulation
 *
 * These procs return previous dirty byte values if db != NIL.
 */

extern PCR←ERes
PCR←VD←Get(
    void *addr,
    unsigned long bytes,
    PCR←VD←DB *db
);

extern PCR←ERes
PCR←VD←Set(
    void *addr,
    unsigned long bytes,
    PCR←VD←DB *db
);

extern PCR←ERes
PCR←VD←Clear(
    void *addr,
    unsigned long bytes,
    PCR←VD←DB *db
);


#endif /* !←←PCR←VD←h */

/*
$Log$
*/