/*static char *SCCSID = "@(#)selxport.h 6.8 92/03/11";*/

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


/*      This file contains exported routines from Selector Manager.
 */

/*   08/23/93  Change Team - Defect 73188
 *             Added another parameter to SELSwitchVdmLDT routine
 */


/* Definitions for selector fields */

#define SEL_512MEG      0x20000000L         /* Upper limit of selector tiling*/
#define SEL_128K        0x20000L            /* Page upper limit of sel tiling */
#define SEL_64K         0x10000L            /* 64Kb */
#define SEL_LADDR_SHIFT 13                  /* sel to laddr shift amount */
#define SEL_LADDR_MASK  0x1fff0000L         /* sel mask in flat address */
#define SEL_IPG_SHIFT   1                   /* sel to ipg shift amount */
#define SEL_IPG_MASK    0x1fff0L            /* sel mask in page address */
#define SEL_LDTBIT      0x4                 /* table bit */
#define SEL_RPLDPL_SHIFT 0x5                /* Rpl to Dpl shift */
#define SEL_RPL0        0x0                 /* Rpl ring 0 */
#define SEL_RPL1        0x1                 /* Rpl Ring 1 */
#define SEL_RPL2        0x2                 /* Rpl Ring 2 */
#define SEL_RPL3        0x3                 /* Rpl Ring 3 */
#define SEL_RPLMASK     SEL_RPL3            /* Rpl bits mask */
#define SEL_RPLCLR      0xfffc              /* Non Rpl bits mask */
#define SELECTOR_MASK   0x0fff8         /* selector index */
#define SEL_LOW_MASK    0x0f8           /* mask for low byte of sel indx */

#define SEL_SHIFT       0x3             /* Shift value for adjacent sels */
#define SEL_INCR        (0x1 << SEL_SHIFT)  /* Adjacent selectors increment */

#define HUGESHIFT       SEL_SHIFT
#define HUGEINCR        SEL_INCR

#define SEL_MAXDESC     (SEL_64K >> SEL_SHIFT) /* max no of descs in LDT/GDT */

#define USERLDTSEL      7               /* exported r/o selector of ldt */

struct seldesc_s {
    ulong_t     desc_cb;        /* size of descriptor */
    ulong_t     desc_laddr;     /* linear address in descriptor*/
    uchar_t     desc_acc;       /* access byte in descriptor */
    uchar_t     desc_attr;      /* D_UVIRT, D_BIG, D_G flags */
};

#define desc_sel        (SEL) desc_laddr    /* Selector if GATE descriptor */
#define desc_off        desc_cb             /* offset if GATE descriptor */
#define desc_cparm      desc_attr           /* parameter count if CALLGATE */

/*
;------------------------------------------------------------------
;
;       Infoseg Selector values and Linear addresses
;
;-------------------------------------------------------------------
*/

#define     SEL_TASKINFOLADDR   (0x1c000000 - 0x10000)
#define     SEL_TASKINFOSEG     \
    (((SEL_TASKINFOLADDR & SEL_LADDR_MASK) >> SEL_LADDR_SHIFT) | SEL_LDTBIT)

#define     SEL_SYSINFOLADDR    (SEL_TASKINFOLADDR - 0x10000)
#define     SEL_SYSINFOSEG      \
    (((SEL_SYSINFOLADDR & SEL_LADDR_MASK) >> SEL_LADDR_SHIFT) | SEL_LDTBIT)

/* Following is the THUNK selector used by thunk code */
#define     R3THKDS     (0x68 | SEL_RPL3)
/* WARNING: The value of the selector GDT_R3THKDS must be 068h !!! */

/*
;-------------------------------------------------------------------
;
;   Following are the flags definitions passed into function flags
;
;---------------------------------------------------------------------
*/

/*  SELAlloc flags definitions  */
/* WARNING: SELAlloc assumes that the memory corresponding to the
   descriptor is already allocated. It should only be called from
   VMAllocMem. Other callers should use SELAllocGDT, SELAllocLDT or
   SELReserveLDT. */

    /* BUGBUG: For v1.3, we force tile selectors as ring3 data if
     *  no selector map is requested */
#define  SELAL_GRAN4K    0x8000 /* used only if SELAL_EXPDN */
#define  SELAL_32BIT     0x4000 /* set if descriptor in 32 bit default format*/
#define  SELAL_GDTRPL0   0x2000 /* set if GDT selector not to be RPL stamped */
#define  SELAL_UVIRT     0x1000 /* set if descriptor is a uvirt */
#define  SELAL_ALLOCATED 0x0800 /* set if GDT selector already allocated */
#define  SELAL_SELMAP    0x0400 /* set if selector map requested */
#define  SELAL_BASEALL   0x0200 /* set if base selector maps all */
#define  SELAL_DISCSEG   0x0100 /* set if a discardable seg allocation,
                                     This flag is used by VMAllocMem
                                     not SELAlloc */
#define  SELAL_PRELOAD   0x0001 /* set if preload needed */
#define  SELAL_CODE      0x0008 /* set if selector is code */
#define  SELAL_EXPDN     0x0004 /* set if expand down descriptor */
#define  SELAL_CONFORM   0x0004 /* set if conforming code */
#define  SELAL_W         0x0002 /* set if writable data */
#define  SELAL_R         0x0002 /* set if readable code */
#define  SELAL_PRIVSHIFT SEL_RPLDPL_SHIFT
            /*shift 0|1|2|3 left by this amount for privilege */
#define  SELAL_PRIVMASK  0x60   /* Mask of privilege bits */

/*      SELSetDescInfo flags definitions */

#define  SELSD_ALL    0x00000       /* set up all fields of descriptor */
#define  SELSD_LIMIT  0x10000       /* update only the limit field */
#define  SELSD_GATE   0x20000       /* set up descriptor as a gate */
/* Following can be added if the parameter is SELSD_LIMIT */
#define  SELSD_SHARED   0x1000
#define  SELSD_ALIAS    0x0001
#define  SELSD_CSALIAS  SELSD_ALIAS
#define  SELSD_BASEALL  0x0004      /* valid for SELSD_LIMIT and SELSD_ALL */


/* Following can be passed to fs parameter in SELFreeTaskLDT. */
#define  SELFT_FREELDT    0       /* free entire LDT */
#define  SELFT_SHRINKLDT  1       /* shrink LDT */

/* Following are the flags passed to SELCheckAccess */
#define  SELCA_W        0x1         /* Check write access */
#define  SELCA_U        (SEL_RPL3 << SEL_RPLDPL_SHIFT)
            /* Check for access from user (Ring 3) level */
#define  SELCA_IOPL     (SEL_RPL2 << SEL_RPLDPL_SHIFT)
            /* Check for access from IOPL level */
#define  SELCA_PRIVMASK (SEL_RPLMASK << SEL_RPLDPL_SHIFT) /* not a flag */

/*  Following are the flags values for SELIfsAlloc */

#define SEL_IFSLDT      0x0001      /* Allocate in task area */
#define SEL_IFSGDT      0x0000      /* Allocate in system area */
#define SEL_IFSSWAP     0x0002      /* Alloocate swappable memory */
#define SEL_IFSFIXED    0x0000      /* Allocate fixed, contiguous memory */
#define SEL_IFSNONCONTIG 0x0004     /* Allocate discontiguous memory */
#define SEL_IFSRING0    0x0000      /* Allocate Ring 0 selector */
#define SEL_IFSRING1    0x2000      /* Allocate Ring 1 selector (INVALID) */
#define SEL_IFSRING2    0x4000      /* Allocate Ring 2 selector (INVALID) */
#define SEL_IFSRING3    0x6000      /* Allocate Ring 3 selector */

#define SEL_IFSRINGMASK 0x6000      /* Mask for ring level */
#define SEL_IFSRINGSHFT 0x0008      /* Shift to DPL */
#define SEL_IFSFLAGS    (SEL_IFSRINGMASK | SEL_IFSLDT | SEL_IFSSWAP \
              | SEL_IFSNONCONTIG)

/*  Following are the flags values for selGiveSeg and selGetSeg */

#define SEL_GS_HOBPTDA  0x0001      /* PTDA handle specified */


/*  Following are the flags values for SELFreeKHB */

#define    SEL_FREE_KHB_OVERRIDE       1


/* ASM
    ;***EM   LaToSelTiled - Convert LDT linear address to selector
    ;
    ;       For use when the address is known to be within the tiled area.
    ;       To convert addresses that may be packed, use _SELLaToSel.
    ;       Returns selector in ax, uses eax
    ;       Address must be below 512Meg
    LaToSelTiled MACRO laddr
        LOCAL   ?lts1

ifdef SELSTRICT
        cmp     laddr, SEL_512MEG
        jb      short ?lts1

        Panic   <'LaToSel'>
    ?lts1:
endif

        IFDIFI <eax>, <laddr>
            mov   eax, laddr
        ENDIF
        and   eax, SEL_LADDR_MASK
        shr   eax, SEL_LADDR_SHIFT
        or    eax, SEL_LDTBIT
    ENDM


    ;***EM  SelToLaTiled  - Convert LDT selector to linear address
    ;
    ;       The selector must be within the tiled area.  To convert
    ;       addresses that may be packed, use _SELSelToLa.
    ;       Returns laddr in eax, uses eax
    ;       Must be LDT selector
    SelToLaTiled    MACRO    sel
        LOCAL   ?stl1

ifdef SELSTRICT
        test    sel, SEL_LDTBIT
        jnz     short ?stl1

        Panic   <'SelToLa'>

    ?stl1:
endif

        IFDIFI <ax>, <sel>
            mov     ax, sel
        ENDIF
        shl     eax, SEL_LADDR_SHIFT
        and     eax, SEL_LADDR_MASK
    ENDM


    ;***EM   IpgToSelTiled - Convert LDT page address to selector
    ;
    ;       The target must be within the tiled region
    ;
    ;       Returns selector in ax, uses eax
    ;       Address must be below 128Kb, otherwise eax will be set to zero
    IpgToSelTiled MACRO ipg
        LOCAL   ?its1

ifdef SELSTRICT

        cmp     ipg, SEL_128K
        jb      short ?its1

        Panic   <'IpgToSel'>

    ?its1:
endif
        IFDIFI <eax>, <ipg>
            mov   eax, ipg
        ENDIF
        and   eax, SEL_IPG_MASK
        shr   eax, SEL_IPG_SHIFT
        or    eax, SEL_LDTBIT
    ENDM


    ;***EM  SelToIpgTiled - Convert LDT selector to page address
    ;
    ;       The target must be within the tiled region
    ;
    ;       Returns ipg in eax, uses eax
    ;       Must be LDT selector, otherwise -1 will be returned
    SelToIpgTiled   MACRO    sel
        LOCAL   ?sti1

ifdef SELSTRICT

        test    sel, SEL_LDTBIT
        jnz     short ?sti1

        Panic   <'SelToIpg'>
    ?sti1:
endif
        IFDIFI <ax>, <sel>
            mov     ax, sel
        ENDIF
        shl     eax, SEL_IPG_SHIFT
        and     eax, SEL_IPG_MASK
    ENDM


    ;***EM  SELRplStamp - RPL stamp given selector with access byte privilege
    ;
    SELRplStamp MACRO   sel, acc
        ;; returns RPL stamped selector in ax
        ;; uses ax, cl

        IFDIFI  <sel>, <ax>
            mov     ax, sel
        ENDIF
        IFDIFI  <acc>, <cl>
            mov     cl, acc
        ENDIF
        and     cl, D_PRIV
        shr     cl, SEL_RPLDPL_SHIFT
        and     ax, SEL_RPLCLR
        or      al, cl
    ENDM
 */


/* XLATOFF */

/*
* Public Data
*/

SEL     SelShrPackedStart;                   /* packed region starting selector */
SEL     SelShrPackedEnd;                     /* packed region ending selector   */

/***EP      LaToSelTiled - Convert linear address to selector
 *
 *          The target must be within the tiled area.  To convert addresses
 *          That might be in the packed region, use _SELLaToSel.
 *          LaToSel converts given linear address to ring0 LDT selector.
 *          The address must be below 512 Meg.
 *          This function is implemented as a macro
 *
 *          SEL     LaToSel(ulong_t laddr)
 */
#define _tsel(la) ((SEL) (((la & SEL_LADDR_MASK) >> SEL_LADDR_SHIFT) \
                             | SEL_LDTBIT))
#ifdef  SELSTRICT
 #define LaToSelTiled(la) ((la < SEL_512MEG) ? _tsel(la) : (SEL) panic(("LaToSel")))
#else
 #define LaToSelTiled(la)  (SEL) (_tsel(la))
#endif


/***EP      SelToLaTiled - Convert selector to linear address
 *
 *          The target must be within the tiled area.  To convert addresses
 *          that might be in the packed region, use _SELSelToLa.
 *          SelToLa converts selector to linear address
 *          Selector must be LDT selector
 *          This function is implemented as a macro
 *
 *          ulong_t SelToLa(SEL sel)
 */
#define _tola(s) ((((ulong_t) s) << SEL_LADDR_SHIFT) & SEL_LADDR_MASK)
#ifdef SELSTRICT
 #define SelToLaTiled(sel) ( (sel & SEL_LDTBIT) ?  _tola(sel) : \
        (ulong_t) (panic(("SelToLa"))) )
#else
 #define SelToLaTiled(sel) ((ulong_t) (_tola(sel)))
#endif

/***EP      IpgToSelTiled - Convert page address to selector
 *
 *          The target must be within the tiled area
 *
 *          IpgToSel converts given page address to ring0 LDT selector.
 *          The address must be below 128 Kb.
 *          This function is implemented as a macro
 *
 *          SEL     IpgToSel(ulong_t ipg)
 */
#define _itsel(i) (SEL) (((i & SEL_IPG_MASK) >> SEL_IPG_SHIFT) | SEL_LDTBIT)
#ifdef  SELSTRICT
 #define IpgToSelTiled(ipg) ((ipg < SEL_128K) ? _itsel(ipg) : \
            (SEL) panic(("IpgToSel")))
#else
 #define IpgToSelTiled(ipg) (_itsel(ipg))
#endif


/***EP      SelToIpgTiled - Convert selector to page address
 *
 *          The target must be within the tiled area
 *
 *          SelToIpg converts selector to page address
 *          Selector must be LDT selector
 *          This function is implemented as a macro
 *
 *          ulong_t SelToIpg(SEL sel)
 */
#define _toipg(s) (ulong_t) ((((ulong_t) s) << SEL_IPG_SHIFT) & SEL_IPG_MASK)
#ifdef SELSTRICT
 #define SelToIpgTiled(sel) ((sel & SEL_LDTBIT) ? _toipg(sel) : \
     (ulong_t) (panic(("SelToIpg"))))
#else
 #define SelToIpgTiled(sel) (_toipg(sel))
#endif


/***EP      SELRplStamp - Stamp given selector with given privilege
 *
 *          SELRplStamp stamps the given selector with privilege level
 *          obtained from the access byte
 *          This function is implemented as a macro
 *
 *          ENTRY   sel - selector
 *                  acc - access byte (only privilege bits needed)
 *          RETURN  sel with right RPL stamp
 *
 *          SELRplStamp(SEL sel, uchar_t acc)
 */
#define RplToDpl(a) ((((ulong_t) a) & D_PRIV) >> SEL_RPLDPL_SHIFT)
#define SELRplStamp(s,a) ((SEL) ((((ulong_t) s) & SEL_RPLCLR) | RplToDpl(a)))

extern SEL R0DS;
extern SEL R0CS;
extern SEL R0CSC;
extern SEL R2DS;
extern SEL R2CS;
extern SEL R3DS;
extern SEL R3PDS;
extern SEL R3CS;
extern SEL R3TIB;
extern  struct desctab      *SELGDTLaddr;

extern int  SELAlloc(VMOB *pob, VMAR *par, ulong_t cb, ulong_t flvm,
            ulong_t flsel, struct ptda_s *pptda, SEL *psel);
/* flvm parameter includes state of PAM_R, PAM_W, PAM_X, PAM_U and
   VMAC_ARENASHR, VMAC_ARENAPRV or VMAC_ARENASYS  */

extern void SELFree(VMOD *pod);

extern int SELAddDiscRec(VMHOB hob);   // AZ10331

extern void SELRemDiscRec(VMHOB hob);

int SELQueryFreeAlias(VMOD *pod);

extern ulong_t SELSelToLa(ulong_t sel, struct ptda_s *pptda);

extern SEL SELLaToSel(ulong_t laddr, struct ptda_s *pptda);

extern int  SELCopy(SEL sel, ushort_t csel, VMHOB hptdasrc, VMHOB hptdadest,
                ulong_t fl);

extern void SELAddPermission(ulong_t ipg, struct ptda_s *pptda, ulong_t cpg,
                ulong_t fl);

extern int  SELAllocGDT (SEL *psel);

extern int  SELFreeGDT(SEL sel);

extern int  SELAllocLDT (ulong_t flags, SEL sel, ushort_t numsels,
             VMHOB hptda);

extern void SELFreeLDT(SEL sel, ushort_t csel, VMHOB hptda);

extern int  SELLdrDesc(ulong_t laddr, ulong_t cb, SEL *psel);

extern int  SELReserveLDT(ulong_t flags, ushort_t numsels, VMHOB hptda,
             void *psel);

extern int SELGetOd(ulong_t fl, SEL sel, struct seldesc_s *pdesc, VMOD *pod);

extern int  SELGetSize(ulong_t laddr, SEL sel, VMHOB hptda, ulong_t cbmax,
             void *pcb);

extern  int SELGetSelector(VMHOB hob, SEL *psel);

extern int  SELGetDescInfo(SEL sel, VMHOB hptda, struct seldesc_s *pseldesc);

extern void SELSetDescInfo(ulong_t fl, ushort_t attr_acc, SEL sel,
              ulong_t cb, ulong_t laddr, VMHOB handle, VMHOB hptda,
              ulong_t cbold);

extern  void SELSetDescAll(ulong_t fl, ushort_t attr_acc, SEL sel,
                ulong_t cb, ulong_t laddr, struct ptda_s *pptda);

extern int  SELMapVirt(ulong_t laddr, ulong_t cb, SEL sel);

extern int  SELInitLDT(VMHOB hptda);

extern int  SELFreeTaskLDT(VMHOB hptda, ulong_t fl);

extern ulong_t SELConvertToSelOff(ulong_t laddr, uchar_t rpl, VMHOB hptda);

extern SEL     SELConvertToSelector(ulong_t laddr, uchar_t rpl, VMHOB hptda);

extern ulong_t SELConvertToLaddr(SEL sel);         /* WARNING :DO NOT USE!!*/

extern ulong_t SELConvertToLinear(SEL sel,struct ptda_s *pPtda);

extern  ulong_t SELVirtToLin(ulong_t offst, SEL sel);

extern  void    SELSetAccess(ulong_t ipg, struct ptda_s *pptda, ulong_t cpg,
                ulong_t fl);

extern int      SELCheckAccess(ulong_t fl, SEL sel, ulong_t offs, ulong_t cb,
                VMHOB hptda);

extern  int     SELSuBuff(struct FarPtr pUsr, void *psrc, ulong_t cb,
                ulong_t fl);
                /* pUsr ,ust be a 16:16 pointer in both SELSuBuff and
                    SELFuBuff */

extern  int     SELFuBuff(void *pdst, struct FarPtr pUsr, ulong_t cb,
                ulong_t fl);

extern void *SELInit(struct arena_s *arenainfo);

extern void SELReinit(void);

extern void SELRemoveAccess(ulong_t laddr, SEL sel);  /* Init time only */

extern int SELValidateKHBAddress(void *p, SEL *psel, VMHOB *phobOwner);

extern int SELAllocKHB(VMHKH hkh,
                        ulong_t cb,
                        ulong_t fl,
                        ulong_t flSelMgr,
                        VMHOB hobOwner,
                        void *pkhbi);

extern int SELReallocKHB(VMHKH hkh,
                          SEL sel,
                          ulong_t cb,
                          ulong_t fl,
                          void *pkhbi);

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

extern int SELMoveKHB(VMHKH hkhSource, VMHKH hkhDest, SEL sel, ulong_t fl);

extern int  SELIfsAlloc(ulong_t fl, ulong_t cb, SEL *psel, VMHOB owner);

extern int  SELIfsRealloc(SEL sel, ulong_t cb);

extern int  SELIfsFree(SEL sel);

extern int  SELIfsNoSwap(SEL sel);

extern int SELGetKHBI(ulong_t fl, VMKHBI *pkhbi);


/*
 *  DPMI support
 */
extern int SELCreateVdmLDT(void **pladdr);

extern int SELDestroyVdmLDT(void *p);

extern int SELAllocVdmSels(ushort_t csel, ushort_t *pcselmin, ushort_t *psel);

extern int SELFreeVdmSels(ushort_t sel, ushort_t cnt);

/* XLATON */

typedef struct selswitchvdm_s {
        ushort_t ssv_ldthandle;           // handle to LDT memory block
        ushort_t ssv_ldtpgmap;            // Bitmap of valid LDT pages
        ulong_t  ssv_ldtaddr;             // linear address of LDT
} SELSWINFO;

/* XLATOFF */

extern void SELSwitchVdmLDT(struct selswitchvdm_s *newldt,
                            struct selswitchvdm_s *curldt);    /* 73188 */

#define SEL_VDM_LDT_INCR 8 // distance between consecutive ldt selectors

struct selvdminfo_s {
        ulong_t  svi_linmax;            // top linear address in user space
        ulong_t  svi_cphysranges;       // number of entries in array below
        ulong_t *svi_physranges;        // pointer to array of physical frame
                                        //  pairs describing valid ram
};

extern int SELGetVdmInfo(struct selvdminfo_s *psvi);




/* XLATON */
