/* This file is DPMI_V1.C
**
** this program shows the GDT, IDT and LDT tables
** compile with smallmodel,protected mode instuctions
** link with dpmiutil.obj
*/

#include <stdlib.h>
#include <stdio.h>
#include "DPMI.H"
#include <dos.h>

void protected_program()
{
    GDTR gdtr;               /* struct for sgdt,sidt call */
    WORD sel,ldtsel,idtsel;
    DWORD gdtbase,ldtbase,idtbase,handle;
    WORD gdtlimit,ldtlimit,idtlimit;
    unsigned i;
    DESCRIPTOR far *gdt ;
    GATE far *idt;

    sgdt(&gdtr) ;
    printf("\nGDT : limit %04X address %04X%04X \n",
            gdtr.limit,gdtr.hi,gdtr.lo);
    printf("LDT selector= %X\n",(ldtsel=sldt()) );
    printf("Task selector= %X\n",str());
    printf("CS selector= %X   ",_CS );
    printf("DS selector= %X\n",_DS );

    /* now we must alloced one selector and set the address
    **    to the gdt address and limit */

    gdtbase=(DWORD)gdtr.hi<<16 | gdtr.lo ;
    gdtlimit=gdtr.limit;

    if ((sel=AllocLDT(1))==0) {
        printf("error allocldt\n") ;
        return ;
        }
    if ((SetBaseAddress(sel,gdtbase))==-1) {
        printf("err setbase\n");
        return ;
        }
    if ((SetLimit(sel,gdtlimit))==-1) {
        printf("err setlimit\n");
        return ;
        }

    /* the same procedure for the idt table */
    sidt(&gdtr) ;
    printf("IDT : limit %04X address %04X%04X \n",gdtr.limit,gdtr.hi,gdtr.lo);
    idtbase=((DWORD)gdtr.hi <<16) | gdtr.lo ;
    idtlimit=gdtr.limit;

    printf("GLOBALE DESCRIPTOR TABELLE:\n");
    gdt=MK_FP(sel,0);       /* this is a protected mode pointer */
    gdtlimit++;
    gdtlimit/=8;            /* one descriptor = 8 bytes */

    for (i=0;i< gdtlimit ;i++) {
        printf("g=%2X l=%2X ",i<<3,(i<<3)+5);
        printdescriptor(gdt[i]);
        if (ldtsel==i*8) {   /* to get the address of the ldt table */
            ldtlimit=(DWORD)gdt[i].lim_hi;
            ldtlimit &= 15;
            ldtlimit<<=16;
            ldtlimit|= gdt[i].lim_lo;
            ldtbase=(DWORD)gdt[i].base_hi;
            ldtbase<<=8;
            ldtbase|=gdt[i].base_mi;
            ldtbase<<=16;
            ldtbase|=gdt[i].base_lo;
            }
        }
    printf("ldtbase ldt=%lX  limit %lX\n",ldtbase,ldtlimit);
    printf("gebrauchter selektor %X\n",sel);
    if ((SetBaseAddress(sel,ldtbase))==-1) {printf("err setbase\n"); return ; } ;
    if ((SetLimit(sel,ldtlimit))==-1) {printf("err setlimit\n"); return ; } ;

    printf("LOKALE DESCRIPTOR TABELLE:\n");
    ldtlimit++;
    ldtlimit/=8;
    for (i=0;i< ldtlimit ;i++) {
        printf("g=%2X l=%2X ",i<<3,(i<<3) +5);
        printdescriptor(gdt[i]);
        }

    printf("INTERRUPT DESCRIPTOR TABELLE:\n");
    if ((SetBaseAddress(sel,idtbase))==-1) {
        printf("err setbase\n");
        return ;
        }
    if ((SetLimit(sel,idtlimit))==-1) {
        printf("err setlimit\n");
        return ;
        }

    idt=MK_FP(sel,0);
    idtlimit++;
    idtlimit/=8;

    for (i=0;i<idtlimit;i++)
        printf("sel %04X off %04X%04X count=%02X type=%02X dpl=%u\n",
            idt[i].sel,idt[i].off_hi,idt[i].off_hi,
            idt[i].count,idt[i].type&7,(idt[i].type&96)>>5);

    if ((FreeLDT(sel))==-1) {
        printf("err freeldt\n");
        return ;
        }
}

void main()
{
    real_to_protected();
    protected_program();
    protected_to_real();
}
