home *** CD-ROM | disk | FTP | other *** search
- /* This file is DPMIUTIL.C
- ** Copyright (c) Rainer Schnitker 10/91
- */
-
- /* This file need Turbo C to compile,
- ** but there are only TurboC specials like asm { statement }
- ** Function used : allocmem(),MK_FP(),FP_SEG(),FP_OFF()
- ** Compile options : -ms (because of other segments in protected mode)
- ** -2 (protected mode)
- ** -B (Assembler lines)
- */
-
- #include "DPMI.H"
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
-
- /* CPU switching for DPMI 0.9 */
-
- void real_to_protected()
- {
- unsigned int speicherseg;
- WORD rax,seg,off,hostreq;
- DWORD PM_jump ;
- int status;
- asm { mov ax,1687h /* DMPI supported ? */
- int 2fh
- mov rax,ax
- mov off,di
- mov seg,es
- mov hostreq,si }
- if (rax){
- printf("no dpmi supported\n");
- exit(1);
- }
-
- PM_jump = (long)seg ;
- PM_jump <<= 16 ;
- PM_jump += (long)off ;
-
- status=allocmem(hostreq,&speicherseg); /* for DPMI-Stack */
- if (status!=-1) { /* reserve */
- printf("allocmem() error\n");
- exit(1);
- }
- asm { mov es,speicherseg ;
- mov ax,0 ;
- call DWORD PTR PM_jump ;
- jnc PMOK ; }
-
- printf("Can't switch to Protected Mode!");
- exit(1);
-
- PMOK:
- printf("CPU in Protected Mode\n");
- printf("CS=%X DS=%X ES=%X SS=%X\n",_CS,_DS,_ES,_SS);
-
- _BL=0x23 ; /* Control Break -> protected_to_real() */
- _CX=_CS ;
- asm mov dx,OFFSET MYINT ;
- DPMI(0x0205);
-
- }
-
- void protected_to_real()
- {
- printf("CPU in Real Mode\n");
- asm MYINT LABEL byte ;
- asm { mov ax,4C00h
- int 21h } /* program ends here */
- }
-
- /* LDT Descriptor management services DPMI 0.9 */
-
- WORD AllocLDT(WORD anzahl)
- {
- _CX=anzahl;
- DPMI(0x0000);
- asm jnc OKallocldt ;
- return 0;
- OKallocldt:
- return _AX;
- }
-
- int FreeLDT(WORD sel)
- {
- _BX=sel;
- DPMI(0x0001);
- asm jnc OKfreeldt;
- return -1;
- OKfreeldt:
- return 0;
- }
-
- WORD SegtoSel(WORD seg)
- {
- _BX=seg;
- DPMI(0x0002);
- asm jnc OKsegsel;
- return 0;
- OKsegsel:
- return _AX;
- }
-
- WORD SelInc()
- {
- DPMI(0x0003);
- return _AX ;
- }
-
- int LockSel(WORD sel)
- {
- _BX=sel ;
- DPMI(0x0004);
- asm jnc OKlocksel;
- return -1;
- OKlocksel:
- return 0;
- }
-
- int UnlockSel(WORD sel)
- {
- _BX=sel ;
- DPMI(0x0005);
- asm jnc OKunlocksel;
- return -1;
- OKunlocksel:
- return 0;
- }
-
- DWORD GetBaseAddress(WORD sel)
- {
- _BX=sel;
- DPMI(0x0006);
- asm jnc OKgetbase;
- return 0;
- OKgetbase:
- return ( (DWORD)_DX | ( (DWORD)_CX <<16 ) );
- }
-
- int SetBaseAddress(WORD sel,DWORD address)
- {
- _CX=(WORD) (address>>16);
- _DX=(WORD) address ;
- _BX=sel;
- DPMI(0x0007);
- asm jnc OKsetbase;
- return -1;
- OKsetbase:
- return 0;
- }
-
- int SetLimit(WORD sel,DWORD limit)
- {
- _BX=sel;
- _CX=(WORD) (limit>>16) ;
- _DX=(WORD) limit ;
- DPMI(0x0008);
- asm jnc OKsetlimit;
- return -1;
- OKsetlimit:
- return 0;
- }
-
- int SetAccess(WORD sel,BYTE access,BYTE extaccess)
- {
- _BX=sel;
- _CL=access;
- _CH=extaccess;
- DPMI(0x0009);
- asm jnc OKsetaccess;
- return -1;
- OKsetaccess:
- return 0;
- }
-
- WORD CreatAlias(WORD segsel)
- {
- _BX=segsel;
- DPMI(0x000a);
- asm jnc OKcreatalias;
- return 0;
- OKcreatalias:
- return _AX ;
- }
-
- int GetDescriptor(WORD sel,DESCRIPTOR *d)
- {
- asm push es ;
- _BX=sel;
- _ES=FP_SEG(d);
- _DI=FP_OFF(d);
- DPMI(0x000b);
- asm pop es ;
- asm jnc OKgetdisc ;
- return -1;
- OKgetdisc:
- return 0;
- }
-
- int SetDescriptor(WORD sel,DESCRIPTOR *d)
- {
- asm push es ;
- _BX=sel;
- _ES=FP_SEG(d);
- _DI=FP_OFF(d);
- DPMI(0x000c);
- asm pop es ;
- asm jnc OKsetdisc ;
- return -1;
- OKsetdisc:
- return 0;
- }
-
- int AllocSpecialLDT(WORD sel)
- {
- _BX=sel;
- DPMI(0x000d);
- asm jnc OKspecial;
- return -1 ;
- OKspecial:
- return 0 ;
- }
-
- /* Interrupt Services DPMI 0.9 */
-
- int GetExceptionVector(BYTE b,WORD *sel,WORD *off)
- {
- _BL=b;
- DPMI(0x0202);
- asm jnc OKgetexeption;
- return -1;
- OKgetexeption:
- *sel=_CX;
- *off=_DX;
- return 0;
- }
-
- int SetExceptionVector(BYTE b,WORD sel,WORD off)
- {
- _BL=b;
- _CX= sel;
- _DX= off;
- DPMI(0x0203);
- asm jnc OKsetexeption;
- return -1;
- OKsetexeption:
- return 0;
- }
-
- int GetPMinterruptVector(BYTE b,WORD *sel,WORD *off)
- {
- _BL=b;
- DPMI(0x0204);
- asm jnc OKgetpmiv;
- return -1;
- OKgetpmiv:
- *sel=_CX;
- *off=_DX;
- return 0;
- }
-
- int SetPMinterruptVector(BYTE b,WORD sel,WORD off)
- {
- _BL=b;
- _CX= sel;
- _DX= off;
- DPMI(0x0205);
- asm jnc OKsetpmiv;
- return -1;
- OKsetpmiv:
- return 0;
- }
-
- /* Memory managment services DPMI 0.9 */
-
- void getfreeinfo(FREEMEMINFO *fm)
- {
- asm push es ;
- _ES=FP_SEG(fm) ; _DI=FP_OFF(fm) ;
- DPMI(0x500);
- asm pop es ;
- }
-
- void printfreeinfo(FREEMEMINFO *fm)
- {
- printf("Largest available block : %lu Byte \n",fm->i1);
- printf("Number free pages : %3lu = %4lu KB\n",fm->i2,fm->i2*4);
- printf("Number free pages to lock : %3lu = %4lu KB\n",fm->i3,fm->i3*4);
- printf("Number pages of linear addr space : %3lu = %4lu KB\n",fm->i4,fm->i4*4);
- printf("Number pages not locked : %3lu = %4lu KB\n",fm->i5,fm->i5*4);
- printf("Number pages not used : %3lu = %4lu KB\n",fm->i6,fm->i6*4);
- printf("Number pages managed by the Dpmi : %3lu = %4lu KB\n",fm->i7,fm->i7*4);
- printf("Number pages free addr space : %3lu = %4lu KB\n",fm->i8,fm->i8*4);
- printf("Number pages in swapfile : %3lu = %4lu KB\n",fm->i9,fm->i9*4);
- }
-
- DWORD GlobalAlloc(DWORD bytes,DWORD *memhandle)
- {
- _BX=(WORD) (bytes>>16);
- _CX=(WORD) bytes ;
- DPMI(0x501);
- asm jnc OKalloc;
- return 0 ;
- OKalloc:
- *memhandle = (DWORD)_CX | ( (DWORD)_BX <<16 ) ;
- return ( (DWORD)_DI | ( (DWORD)_SI <<16 ) );
- }
-
- int GlobalFree(DWORD handle)
- {
- _SI=(WORD) (handle>>16);
- _DI=(WORD) handle ;
- DPMI(0x0502);
- asm jnc OKFREE ;
- return -1 ;
- OKFREE:
- return 0 ;
- }
-
- /* Page locking services DPMI 0.9 */
-
- int LockLinRegion(DWORD size,DWORD address)
- {
- _BX=(WORD) (address>>16);
- _CX=(WORD) address;
- _SI=(WORD) (size>>16);
- _DI=(WORD) size;
- DPMI(0x0600);
- asm jnc oklocklin;
- return -1;
- oklocklin:
- return 0;
- }
-
- int UnlockLinRegion(DWORD size,DWORD address)
- {
- _BX=(WORD) (address>>16);
- _CX=(WORD) address;
- _SI=(WORD) (size>>16);
- _DI=(WORD) size;
- DPMI(0x0600);
- asm jnc okunlocklin;
- return -1;
- okunlocklin:
- return 0;
- }
-
- /* Other multiplex int 2F */
-
- void Yield() /* give control to operating system (like GetMassage) */
- {
- _AX=0x1680 ;
- asm int 2Fh ;
- }
-
- /* Protected mode API */
-
- DWORD lsl(WORD sel) /* load selector limit */
- {
- asm { db 66h;
- sub ax,ax; /* sub eax,eax */
- db 66h;
- mov bx,ax; /* mov ebx,eax */
- mov bx,sel
- db 66h;
- lsl ax,bx; /* lsl eax,ebx */
- db 66h;
- mov dx,ax ; /* mov eax,eax ax:low word */
- db 66h ;
- shr dx,16 /* shr edx,16 dx:high word */
- }
- }
-
- WORD lsl16(WORD sel) /* 16-bit version of lsl for 80286 */
- {
- asm sub ax,ax
- asm lsl ax,sel
- return _AX ;
- }
-
- WORD lar(WORD sel) /* load access rights */
- {
- asm sub ax,ax ;
- asm lar ax,sel;
- asm shr ax,8 ;
- return _AX ;
- }
-
- WORD verr(WORD sel) /* verify read */
- {
- asm mov ax,1 ;
- asm verr sel ;
- asm je okr ;
- asm dec ax ;
- okr:
- return _AX ;
- }
-
- WORD verw(WORD sel) /* verify write */
- {
- asm mov ax,1 ;
- asm verw sel ;
- asm je okw ;
- asm dec ax ;
- okw:
- return _AX ;
- }
-
- void sgdt(GDTR *g) /* save gdt table */
- {
- asm mov si,g ;
- asm sgdt [si] ;
- }
-
- void sidt(GDTR *g) /* save idt table */
- {
- asm mov si,g ;
- asm sidt [si] ;
- }
-
- WORD sldt(void) /* save ldt-selector */
- {
- asm sldt ax ;
- return _AX ;
- }
-
- WORD str(void) /* save task-register */
- {
- asm str ax ;
- return _AX ;
- }
-
- /* Protected mode utilities */
-
- void far * incfp(void far *a) /* get next selector */
- {
- FP_SEG(a)+=SelInc();
- return(a);
- }
-
- void far * decfp(void far *a) /* get previous selector */
- {
- FP_SEG(a)-=SelInc();
- return(a);
- }
-
- void printdescriptor(DESCRIPTOR d)
- {
- printf("b=%02X%02X%04X lim=%01X%04X p=%u dpl=%u %s t4=%X t=%u %s %s\n",
- d.base_hi,d.base_mi,d.base_lo,
- d.lim_hi&15,d.lim_lo,
- (d.access&128)>>7,
- (d.access&96)>>5,
- (d.access&16) ? "MEMseg" : "SYSseg",
- (d.access&15),
- (d.access&7),
- (d.lim_hi & 64) ? "32bit" : "16bit" ,
- (d.lim_hi & 128) ? "paging": " " );
- }
-
- void farcopy(void far *dest,void far *source,DWORD bytes)
- {
- unsigned long i ;
-
- bytes++; /* if bytes %2 = 1 */
- bytes>>=1;
- poke( FP_SEG(dest),FP_OFF(dest),peek(FP_SEG(source),FP_OFF(source)) );
- for (i=1; i< bytes ; i++) {
- FP_OFF(dest)+=2 ;
- if (FP_OFF(dest)==0) dest=incfp(dest);
- FP_OFF(source)+=2 ;
- if (FP_OFF(source)==0) source=incfp(source);
- poke( FP_SEG(dest),FP_OFF(dest),peek(FP_SEG(source),FP_OFF(source)) );
- }
- }
-
- /* high level C-function using DPMI-API */
- /* malloc,free */
-
- #define PAGESIZE 4096
- #define PAGEBUCKET 11
- #define NBUCKETS 30
- #define MAGIC 0xFFF0
-
- union overhead {
- struct {
- WORD page;
- WORD offset;
- } free ;
- struct {
- WORD magic ;
- WORD index ;
- } use ;
- } ;
-
- static union overhead nextf[NBUCKETS];
-
- void far * morepages(WORD bucket)
- {
- WORD nblks,i,page,nsel,nextpage;
- DWORD sz,handle,memaddress;
-
- sz = ((DWORD)1) << (bucket + 2) ;
-
- if (sz<PAGESIZE) /* 1st case : divide 4K-Page in sz-big blocks */
- {
- if ((handle=GlobalAlloc(PAGESIZE,&memaddress))==0)
- return NULL ;
- if ( (page=AllocLDT(1)) ==0) { /* no more selectors ? */
- GlobalFree(handle); /* free memory */
- return NULL;
- }
- if (SetBaseAddress(page,memaddress)==-1) return NULL;
- if (SetLimit(page,PAGESIZE-1)==-1) return NULL;
-
- nblks = PAGESIZE / (WORD)sz ; /* number of pieces */
- nblks--;
- nextf[bucket].free.page=page; /* freelist -> second block */
- nextf[bucket].free.offset=sz;
- for (i=1;i< (nblks);i++) /* fill header of blocks */
- {
- poke(page,i*sz,page);
- poke(page,i*sz +2,(i+1)*sz);
- }
- poke(page,nblks*sz,0); /* last block -> NULL */
- poke(page,nblks*sz+2,0);
- }
-
- else { /* 2.nd case : one selectors per 64 KB */
- if ((handle=GlobalAlloc(sz,&memaddress))==0) return NULL ;
- nsel=(WORD) ((sz-1)>>16); /* nsel = number of selectors */
- nsel++;
- if ((page=AllocLDT(nsel))==0) { /* no more selectors? */
- GlobalFree(handle) ; /* free memory */
- return NULL;
- }
- if (sz>0x10000L) sz=0x10000L ; /* divide in 64KB */
- nextpage=page;
- for (i=1;i<=nsel;i++) {
- if (SetBaseAddress(nextpage,memaddress)==-1)
- printf("error set Base\n");
- if (SetLimit(nextpage,sz-1)==-1)
- printf("error set Limit\n");
- memaddress+=0x10000L ;
- nextpage+=SelInc(); /* get next selector number */
- }
- }
- return (MK_FP(page,0)) ;
- }
-
- void far *extmalloc(DWORD nbytes)
- {
- WORD bucket, n=0 ;
- DWORD amt ;
- union overhead far *fp;
-
- if (nbytes == 0 ) return NULL;
- nbytes+= sizeof(union overhead) ;
-
- if (nbytes <= PAGESIZE ) { /* nbytes <= PAGE */
- amt = 4; /* bucket = 1..12 */
- bucket = 0;
- n = 0 ;
- }
- else { /* nbytes > PAGE */
- amt = PAGESIZE; /* bucket = 13..30 */
- bucket = PAGEBUCKET;
- n=PAGESIZE;
- }
- while (nbytes > amt + n) {
- amt <<= 1;
- if (amt == 0)
- return NULL;
- bucket++;
- }
-
- if (nextf[bucket].free.page == 0) { /* no mem in list */
- fp=(union overhead far *)morepages(bucket);
- if ((fp) == NULL) /* no mem from dpmi */
- return NULL;
- }
- else { /* mem available in list */
- /* now : nextf[] -> myblock -> nextp */
-
- /* fp -> myblock */
- fp=(union overhead far *)MK_FP(nextf[bucket].free.page,nextf[bucket].free.offset);
- /* nextf[] -> nextp */
- nextf[bucket].free.page =fp->free.page;
- nextf[bucket].free.offset=fp->free.offset;
- }
- fp->use.magic= MAGIC ;
- fp->use.index= bucket;
- return ((void far *)(fp+1));
- }
-
- void extfree(void far *p)
- {
- union overhead far *fp ;
- WORD bucket ;
-
- fp=(union overhead far *)p - 1; /* get header */
- if (fp->use.magic!= MAGIC) return ; /* bad pointer */
- bucket = fp->use.index ; /* get size of pointer */
- /* nextf[] -> nextp */
- /* wanted : nextf[] -> fp -> nextf */
- fp->free.page=nextf[bucket].free.page;
- fp->free.offset=nextf[bucket].free.offset;
- nextf[bucket].free.page = FP_SEG(fp);
- nextf[bucket].free.offset=FP_OFF(fp);
- }
-