/*static char *SCCSID = "@(#)sellocal.h 6.6 91/11/22";*/
/*
 *      SCCSID = @(#)sellocal.h 6.6 91/11/22
 */

/*
 *       IBM/Microsoft Confidential
 *
 *       Copyright (c) IBM Corporation 1987, 1989
 *       Copyright (c) Microsoft Corporation 1987, 1989
 *
 *       All Rights Reserved
 */


/*      This file contains local routines of Selector Manager.
 */


#define SEL_MAXPG       (SEL_64K >> PAGESHIFT) /* max no of pages in LDT/GDT */
#define SEL_INFOSEGPG   (SEL_TASKINFOSEG >> PAGESHIFT)
                        /* Pageno in the LDT containing the infoseg */

#define SEL_INFOSEGSEL1 (0xdff4)       /* Infoseg selector (no privilege bits
                                        * set).
                                        */

#define SEL_INFOSEGSEL2 (0xdffc)       /* Infoseg selector (no privilege bits
                                        * set).
                                        */

#define SEL_LASTPACKSHR (0x0dffc)      /* Last packed selector in the shared
                                        * arena.
                                        */

#define SEL_LASTLDTOFF  (0x0fff8)       /* Offset into the LDT for the very
                                        * last selector.
                                        */

#define SEL_LASTLDTSEL  (0x0fffc)       /* Last selector in the LDT (no
                                        * privilege bits set).
                                        */

/* Following is the Selector Manager lock handle structure stored in BMP32
 * records
 */

struct  selLockHandle_s {
    struct vmlh_s  slh_plhpg;           /* Lock handle returned by VM */
    unsigned short slh_plhldt;          /* Index to LDT page lockhandle */
};

/* Following is the Selector Manager discardable segments RMP structure,
 * used to store a discardable segments soft lock count.
 */

struct selDiscSegRmpRec_s {
    ushort_t hob;                       /* Object handle of disc seg */
    uchar_t  softlocks;                 /* Soft lock count */
};

/* XLATOFF */

/***LP  selAssert - cause internal error if assertion fails
 *
 *      Given a boolean, this procedure causes an internal error if
 *      the boolean is false.  Typically, the value of this boolean is
 *      derived from some test expression.
 *
 *      selAssert (f)
 *
 *      ENTRY   f               - boolean value (int)
 *      RETURN  NONE
 *
 *      CALLS   panicfmt
 *
 *      WARNING This procedure is implemented as a macro.
 *
 *      EFFECTS NONE
 */

#ifdef  SELSTRICT
#  define selAssert(e) _assert(e)
#else
#  define selAssert(e)
#endif


/***LP  selIsValidLDTpg - Determine if given page is valid in the LDT.
 *
 *      selIsValidLDTpg returns FALSE if the given pageno is invalid in the
 *      task's LDT.
 *
 *      selIsValidLDTpg(pptda, i)
 *
 *      ENTRY   pptda           - pointer to task's ptda
 *              i               - page index into ptda 0 <= i < 16
 *      RETURN  int             - nonzero if given LDT page is valid
 *
 *      WARNING This procedure is implemented as a macro.
 *
 *      EFFECTS NONE
 */
#define selIsValidLDTpg(pptda, i)   (pptda->ptda_ldtpgmap & (1 << i))


/***LP  selVdmAllPositiveValid - all pages for positive selectors valid
 *
 *      selVdmAllPositiveValid returns true if all pages for positive
 *      selectors in the LDT are valid.
 *
 *      selVdmAllPositiveValid(pptda)
 *
 *      ENTRY   pptda           - pointer to task's ptda
 *
 *      RETURN  int             - nonzero if given LDT page is valid
 *
 *      WARNING This procedure is implemented as a macro.
 *
 *      EFFECTS NONE
 */
#define selVdmAllPositiveValid(pptda) (((pptda)->ptda_ldtpgmap & 0xff) == 0xff)


/***LP  selIsValidLDTsel - Determine if given selector is valid in the LDT.
 *
 *      selIsValidLDTsel returns FALSE if the given selector corresponds to
 *      an invalid region in the LDT.
 *
 *      selIsValidLDTsel(pptda, sel)
 *
 *      ENTRY   pptda           - pointer to task's ptda
 *              sel             - selector
 *      RETURN  int             - nonzero if given sel is in a valid region
 *
 *      WARNING This procedure is implemented as a macro.
 *
 *      EFFECTS NONE
 */
#define selIsValidLDTsel(ppt, s)   selIsValidLDTpg(ppt, (s >> PAGESHIFT))


/*      descfree_s - DPMI LDT free list header */
struct descfree_s {
        struct descfree_s *df_descNext; // next free block
        unsigned short    df_unused;    // unused
        unsigned short    df_cnt;       // number of contig commited free sels
};


/* Following are the local procedures/variables of Selector Manager */

extern  void    SELDiscSegInit(void);

extern  void    *selGetLDTAddr(VMHOB hptda);

extern  int     selIfsSegRealloc(ulong_t cb, SEL sel);

extern  SEL     SELMaxGDT;

extern  int     selAllocLDTSub(SEL sel, ushort_t csel, struct ptda_s *pptda);

extern  ulong_t selFreeLDTSub(SEL sel, ushort_t csel, struct ptda_s *pptda);

extern  ulong_t selFreeGDTSub(SEL sel);

extern int  selAllocLSHB(VMHKH hkh, ulong_t cb, ulong_t fl, ulong_t flselmgr,
            VMHOB hobOwner, VMAC *pac);

extern int  selReallocLSHB(VMHKH hkh, SEL sel, ulong_t cb, ulong_t fl,
            void **ppb);

extern void selFreeLSHB(VMHKH hkh, ulong_t fl, SEL sel);

extern int selGiveSeg(ulong_t fl, SEL sel, VMHOB hobPTDA);

extern int selGetSeg(SEL sel);
