/* * wininit.c * * Initialization for running WATTCP as a Windows DLL. */ #ifdef WINDOWS #include #include #include "wattcp.h" #include "errors.h" #include "dpmi.h" extern struct pkt_struct far *pktstruct; /* PCPKT.C */ extern DWORD far *interrupts; /* PCPKT.C */ extern unsigned long far *realclock; /* PCTCP.C */ extern struct pkt_struct far *pktstruct_raddr; /* PCPKT.C */ extern void far (*_pktentry_raddr)(); /* PCPKT.C */ extern void (*do_intr)(); /* PCPKT.C */ /* Values returned by DPMI mapping functions */ static void far (*MkCallbackRet)(); static DWORD DosAllocRet; static RMODE_CALL rmode_call; /* * Windows-aware yield function, called when the library is * busy-waiting for something to happen. */ void win_yield(void) { MSG msg; while(PeekMessage((LPMSG)&msg, 0, 0, 0, PM_REMOVE)) { if(msg.message == WM_PAINT) /* PeekMessage() leaves WM_PAINT's in the queue */ GetMessage((LPMSG)&msg, 0, 0, 0); TranslateMessage((LPMSG)&msg); DispatchMessage((LPMSG)&msg); } } /* * Upcall routine for use in Windows. The packet driver's call to * pktentry_raddr in real-mode will cause DPMI to enter protected * mode, disable interrupts and call WinCallback(), which then calls * this function and returns to real-mode. */ RMODE_CALL far * WinPktEntry(RMODE_CALL far *rc, unsigned short far *rmstack) { register int i; /* Find and set the program's DS - rc supposedly points into it. */ _asm { push di les di, rc mov di, es mov ds, di pop di } /* First fix up the real-mode return address and stack */ rc->ip = *rmstack++; rc->cs = *rmstack; rc->sp += 4; if((rc->eax & 0xff) == 0) { /* Assume failure */ rc->es = rc->edi = 0; /* If the packet isn't too big, find a free buffer */ if((unsigned short)rc->ecx <= BUFSIZE) { for(i = 0; i < MAXBUFS; i++) { if(pktstruct->buf[i][0] == 0) { rc->edi = FP_OFF(&pktstruct_raddr->buf[i][2]); rc->es = FP_SEG(&pktstruct_raddr->buf[i][2]); break; } } } } else { /* Mark a buffer ready to use */ if(rc->esi != 0) *((byte far *)pktstruct+(unsigned short)rc->esi-2) = 1; } return rc; } /* * Callback function for protected mode Windows. */ void WinCallback(void) { _asm { push ds /* DS:SI-> real-mode stack */ push si push es /* ES:DI-> RMODE_CALL struct */ push di call WinPktEntry mov di, ax /* return RMODE_CALL ptr to DPMI */ mov es, dx mov sp, bp pop bp iret } } int WinInit(void) { extern void pmode_intr(); /* Install a Windows-aware system yield function */ sock_yield((tcp_Socket *)0, win_yield); /* If not running standard or enhanced, nothing more to do */ if(!(GetWinFlags() & WF_PMODE)) return(SUCCESS); /* Use the dpmi intr() substitute. */ do_intr = pmode_intr; /* Map in low memory and fix pointers to it. */ interrupts = (DWORD far *)map_real((void far *)0, 0x400L); realclock = (unsigned long far *)map_real((void far *)0x46c, 4L); if(!interrupts || !realclock) { sock_exit(); return(ER_MAP); } /* Get a real-mode address for the upcall routine accessed by */ /* the packet driver. */ MkCallbackRet = dpmi_make_callback((void far (*)())WinCallback,&rmode_call); if(!MkCallbackRet) { sock_exit(); return(ER_CALLBACK); } _pktentry_raddr = MkCallbackRet; /* Get a real-mode address for the data accessed by the packet */ /* driver and lock it down. If it isn't in DOS memory, move it */ /* there first. */ /* if(!(pktstruct_raddr = (void far *)ProtToReal(pktstruct))) */ { struct pkt_struct far *temp; DosAllocRet = GlobalDosAlloc((DWORD)((sizeof(*pktstruct)+15)&~15)); if(!DosAllocRet) { sock_exit(); return(ER_DOSALLOC); } /* The high word of DosAllocRet is the rmode segment. The */ /* low word is the protected-mode selector. Build them */ /* into full adresses. */ pktstruct_raddr = (void far *)(DosAllocRet & 0xffff0000L); temp = (struct pkt_struct far *)(DosAllocRet << 16); /* Parts of the static struct are initialized, so copy */ /* the contents into the new area. Then point to it. */ *temp = *pktstruct; pktstruct = temp; } return(SUCCESS); } void WinExit(void) { return; if(MkCallbackRet) dpmi_free_callback(MkCallbackRet); if(DosAllocRet) GlobalDosFree(DosAllocRet); MkCallbackRet = NULL; DosAllocRet = 0; } #endif