home *** CD-ROM | disk | FTP | other *** search
- #ifdef WINDOWS
- #include <dos.h>
- #include <windows.h>
- #include "dpmi.h"
-
- #define MAKEP(seg, ofs) ((void far *)MAKELONG((ofs), (seg)))
-
- static unsigned __0000H;
-
-
- dpmi_rmode_intr(unsigned intno, unsigned flags,
- unsigned copywords, RMODE_CALL far *rmode_call)
- {
- /* Copying won't work here - fail if they try it. */
- if(copywords) return 0;
-
- /* To make DPMI reset the 8259's and A20 for real mode, set BH=1 */
- if (flags) intno |= 0x100;
-
- _asm {
- push di
- mov ax, 0300h /* simulate real-mode interrupt */
- mov bx, word ptr intno /* interrupt number, flags */
- mov cx, 0 /* words to copy from pmode to rmode stack */
- les di, dword ptr rmode_call /* ES:DI = addr of rmode call struct */
- int 31h /* call DPMI */
- jc error
- mov ax, 1 /* return TRUE */
- jmp short done
- }
- error:
- _asm xor ax, ax /* return FALSE */
- done:
- _asm pop di
- }
-
- unsigned
- dpmi_sel(void)
- {
- asm {
- xor ax, ax
- mov cx, 1
- int 31h
- jc error
- jmp short done
- }
- error:
- asm xor ax, ax
- done:;
- }
-
- dpmi_set_descriptor(unsigned pmodesel, DESCRIPTOR far *d)
- {
- asm {
- push di
- mov ax, 0ch
- mov bx, word ptr pmodesel
- les di, dword ptr d
- int 31h
- jc error
- mov ax, 1
- jmp short done
- }
- error:
- asm xor ax, ax
- done:
- asm pop di
- }
-
- dpmi_get_descriptor(unsigned pmodesel, DESCRIPTOR far *d)
- {
- asm {
- push di
- mov ax, 0bh
- mov bx, word ptr pmodesel
- les di, dword ptr d
- int 31h
- jc error
- mov ax, 1
- jmp short done
- }
- error:
- asm xor ax, ax
- done:
- asm pop di
- }
-
- void far (*dpmi_make_callback(void far (*p)(), RMODE_CALL far *rc))()
- {
- _asm {
- push ds
- push si
- push di
- lds si, dword ptr p /* pmode call-back procedure address */
- les di, dword ptr rc /* pmode address of static stuct to use */
- mov ax, 0303h /* allocate call-back address */
- int 31h /* call DPMI */
- pop di
- pop si
- pop ds
- jc error
- mov ax, dx /* return rmode seg:ofs on success */
- mov dx, cx
- jmp short done
- }
- error:
- _asm xor ax, ax
- _asm mov dx, ax
- done:;
- }
-
- int
- dpmi_free_callback(void far (*p)())
- {
- _asm {
- mov dx, word ptr p
- mov cx, word ptr p+2
- mov ax, 0304h
- int 31h
- mov ax, 0
- jc done
- inc ax
- }
- done:;
- }
-
- unsigned
- verw(unsigned sel)
- {
- asm mov ax, 1
- asm verw sel
- asm je short ok
- asm xor ax, ax
- ok:;
- }
-
- unsigned
- MapRealSeg(unsigned rpara, DWORD size, unsigned far *psel)
- {
- DESCRIPTOR d;
- unsigned long addr;
- unsigned sel = dpmi_sel();
- if(!sel)
- return 0;
-
- if(!verw(FP_SEG(psel)))
- return(490);
-
- dpmi_get_descriptor(FP_SEG(psel), &d);
- d.limit = (unsigned)size - 1;
- addr = ((unsigned long)rpara) << 4;
- d.addr_lo = (unsigned)addr; d.addr_hi = (unsigned char)(addr >> 16);
- d.res1 = d.addr_xhi = 0;
- dpmi_set_descriptor(sel, &d);
- *psel = sel;
- return 0;
- }
-
- void far *
- ProtToReal(void far *prot)
- {
- unsigned long base = GetSelectorBase(FP_SEG(prot));
- if(base >= 0x100000L)
- return NULL;
- else
- return MAKEP(base >> 4, (base & 0x0f) + FP_OFF(prot));
- }
-
- void far *
- map_real(void far *rptr, unsigned long size)
- {
- unsigned seg, ofs, sel;
-
- /* If not running standard or enhanced, nothing more to do */
- if(!(GetWinFlags() & WF_PMODE))
- return rptr;
-
- if(!__0000H)
- __0000H = LOWORD(GetProcAddress(GetModuleHandle("KERNEL"), "__0000H"));
-
- seg = FP_SEG(rptr); ofs = FP_OFF(rptr);
- if((seg < 0x1000) && ((ofs + size) < 0xffff))
- return(MAKEP(__0000H, (seg << 4) + ofs));
- if(MapRealSeg(seg, size + ofs, &sel) != 0)
- return 0;
- return(MAKEP(sel, ofs));
- }
-
- void
- unmap_real(void far *p)
- {
- unsigned sel = FP_SEG(p);
-
- /* If not running standard or enhanced, nothing more to do */
- if(!(GetWinFlags() & WF_PMODE))
- return;
-
- if(sel != __0000H) {
- asm {
- mov ax, 1
- mov bx, word ptr sel
- int 31h
- jc error
- mov ax, 1
- jmp short done
- }
- error:
- asm xor ax, ax
- done:;
- }
- }
-
- /*
- * Replacement intr() function to perform a real-mode software
- * interrupt under DPMI.
- */
- void
- pmode_intr(int intno, struct REGPACK _FAR *regs)
- {
- RMODE_CALL pregs;
- register RMODE_CALL *pp = &pregs;
- register struct REGPACK far *rp = regs;
-
- pp->res1 = 0;
- pp->flags = rp->r_flags;
- pp->eax = rp->r_ax;
- pp->ebx = rp->r_bx;
- pp->ecx = rp->r_cx;
- pp->edx = rp->r_dx;
- pp->esi = rp->r_si;
- pp->edi = rp->r_di;
- pp->ebp = rp->r_bp;
- pp->ds = rp->r_ds;
- pp->es = rp->r_es;
- pp->ss = pp->sp = 0; /* 0:0 -> DPMI provides a 30-word stack */
- pp->fs = pp->gs = pp->ds;
- dpmi_rmode_intr(intno, 0, 0, (RMODE_CALL far *)pp);
- rp->r_ax = pp->eax;
- rp->r_bx = pp->ebx;
- rp->r_cx = pp->ecx;
- rp->r_dx = pp->edx;
- rp->r_si = pp->esi;
- rp->r_di = pp->edi;
- rp->r_bp = pp->ebp;
- rp->r_ds = pp->ds;
- rp->r_es = pp->es;
- rp->r_flags = pp->flags;
- }
-
- #endif
-