; ; LibInit.asm library stub to do local init for a Dynamic linked library ; ; NOTE!!!! link this MODULE first or you will be sorry!!!! ; ?PLM=1 ; pascal call convention ?WIN=0 ; Windows prolog/epilog code ?DF=1 PMODE=1 .286 .xlist include cmacros.inc include windows.inc include sysinfo.inc include mmddk.inc include mmsystem.inc include timer.inc ;include vtdapi.inc .list .list sBegin Data ; ; Stuff needed to avoid the C runtime coming in ; ; also known as "MAGIC THAT SAVED ME" - Glenn Steffler 2/7/90 ; ; Do not remove!! ; DD 0 ; So null pointers get 0 maxRsrvPtrs = 5 DW maxRsrvPtrs usedRsrvPtrs = 0 labelDP DefRsrvPtr MACRO name globalW name,0 usedRsrvPtrs = usedRsrvPtrs + 1 ENDM DefRsrvPtr pLocalHeap ; Local heap pointer DefRsrvPtr pAtomTable ; Atom table pointer DefRsrvPtr pStackTop ; top of stack DefRsrvPtr pStackMin ; minimum value of SP DefRsrvPtr pStackBot ; bottom of stack if maxRsrvPtrs-usedRsrvPtrs DW maxRsrvPtrs-usedRsrvPtrs DUP (0) endif public __acrtused __acrtused = 1 sEnd Data ; ; ; END of nasty stuff... ; externA WinFlags externFP LocalInit externFP Disable286 externFP Enable286 externW wMaxResolution externW wMinPeriod ; here lies the global data sBegin Data public wEnabled wEnabled dw 0 ; enable = 1 ;disable = 0 public PS2_MCA ifdef NEC_98 PS2_MCA db 0 ; Micro Channel Flag public bClockFlag ; save machine clock bClockFlag db 0 ; 5Mhz = 0 ; 8Mhz = other else ; NEC_98 PS2_MCA db ? ; Micro Channel Flag endif ; NEC_98 sEnd Data assumes es,nothing sBegin CodeInit assumes cs,CodeInit assumes ds,Data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Library unload function ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Disable routine is same as WEP cProc WEP,,<> ; parmW silly_param cBegin nogen errn$ Disable cEnd nogen cProc Disable,,<> ; parmW silly_param cBegin nogen push ds mov ax,DGROUP ; set up DS==DGROUP for exported funcs mov ds,ax assumes ds,Data xor ax,ax ; return value = no error cmp wEnabled,ax ; Q: enabled ? jz dis_done ; N: exit mov wEnabled,ax ; disabled now mov ax,WinFlags test ax,WF_WIN386 jnz dis_386 ; running under win286 dis_286: call Disable286 jmp dis_done ; running under win386 dis_386: call Disable286 dis_done: pop ds ret 2 cEnd nogen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Library Enable function ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cProc Enable,,<> ; parmW silly_param cBegin nogen mov ax,wEnabled or ax,ax ; Q: already enabled ? jnz enable_done ; Y: exit inc wEnabled ; mark as being enabled ifdef NEC_98 ; ; Get system clock ; mov ax,0002h mov bx,0040h ; get segment addres ; make descriptor(real mode segment) ; return the segment descriptor ; in the case of exist the appointed segment descriptor already ; (not make sure repeatedly) int 31h jc error_exit ; in the case of failed ->jmp push es mov es,ax mov al,byte ptr es:[101h] ; get system info and al,80h mov byte ptr bClockFlag,al ; save clock pop es endif ; NEC_98 mov ax,WinFlags test ax,WF_WIN386 jnz enable_386 ; running under win286 enable_286: call Enable286 jmp enable_done ; running under win386 enable_386: call Enable286 enable_done: ret 2 ifdef NEC_98 error_exit: dec wEnabled ; mark as being enabled xor ax,ax ret 2 endif ; NEC_98 cEnd nogen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Library entry point ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; public LibInit LibInit proc far ; CX = size of heap ; DI = module handle ; DS = automatic data segment ; ES:SI = address of command line (not used) jcxz lib_heapok ; heap size zero? jump over unneeded LocalInit call cCall LocalInit, ; dataseg, 0, heapsize or ax,ax jnz lib_heapok ; if heap set continue on lib_error: xor ax,ax ret ; return FALSE (ax = 0) -- couldn't init lib_heapok: mov ax,WinFlags test ax,WF_WIN386 jnz lib_386 ; running under win286 lib_286: call Lib286Init jmp lib_realdone ; win 286 will enable timer on first event request ; running under win386 lib_386: call Lib286Init lib_realdone: ret LibInit endp sEnd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Win 386 timer VTD code for initialization, and removal ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; externFP GetVersion ; in KERNEL externFP MessageBox ; in USER externFP LoadString ; in USER sBegin CodeInit assumes cs,CodeInit assumes ds,Data ;externNP VTDAPI_GetEntryPt ; Assumes DI contains module handle cProc WarningMessage <> LocalV aszErrorTitle, 32 LocalV aszErrorMsg, 256 cBegin lea ax, WORD PTR aszErrorTitle cCall LoadString, lea ax, WORD PTR aszErrorMsg cCall LoadString, lea ax, WORD PTR aszErrorTitle lea bx, WORD PTR aszErrorMsg cCall MessageBox, cEnd if 0 Lib386Init proc near call VTDAPI_GetEntryPt ; this will return 0 if the VxD is not loaded or ax,ax jnz Lib386InitOk ifndef NEC_98 DOUT endif ; NEC_98 ; ; warn the USER that we can't find our VxD, under windows 3.0 ; we can't bring up a message box, so only do this in win 3.1 ; cCall GetVersion xchg al,ah cmp ax,030Ah jb Lib386InitFail cCall WarningMessage,<> Lib386InitFail: xor ax,ax Lib386InitOk: ret Lib386Init endp endif Disable386 proc near errn$ Enable386 ; fall through Disable386 endp Enable386 proc near mov ax,1 ; nothing to do ret Enable386 endp sEnd Code386 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Win 286 timer drv code for initialization, and removal ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; externW Events externFP tddISR ; in local.asm externFP GlobalWire ; in KERNEL externFP GlobalPageLock ; in KERNEL sBegin CodeInit assumes cs,CodeInit assumes ds,Data Lib286Init proc near ; get the system configuration ; ; the FIXED_286 segment is not loaded, load it and pagelock it. ; mov dx,seg tddISR ; get the 286 code segment mov es,dx mov ax,es:[0] ; load it! cCall GlobalWire, ; get it low in memory cCall GlobalPageLock, ; and nail it down! ifndef NEC_98 mov PS2_MCA,0 ; Initialize PS2_MCA = FALSE stc ; Set this in case BIOS doesn't mov ah,GetSystemConfig int 15h jc Lib286Init_NoMicroChannel ; Successful call? or ah,ah ; Valid return? jnz Lib286Init_NoMicroChannel test es:[bx.SD_feature1],SF1_MicroChnPresent jz Lib286Init_NoMicroChannel inc PS2_MCA ; PS2_MCA = TRUE endif ; NEC_98 Lib286Init_NoMicroChannel: push di push ds pop es mov di,DataOFFSET Events ; ES:DI --> Events xor ax,ax mov cx,(MAXEVENTS * SizeEvent)/2 rep stosw ; zero out event structures. ; set up one event as the standard call-back routine for the ; BIOS timer service ; ifdef NEC_98 mov ax,0002h mov bx,0040h int 31h jc error_init push es mov es,ax test byte ptr es:[101h],80h pop es mov cx,0f000h jz @f mov cx,0c300h @@: xor bx,bx else ; NEC_98 xor bx,bx ; BX:CX = 64k xor cx,cx inc bx endif ; NEC_98 mov di,DataOFFSET Events ; DS:DI --> Events mov [di].evTime.lo,cx ; Program next at ~= 55ms mov [di].evTime.hi,bx ; standard 18.2 times per second event mov [di].evDelay.lo,cx ; First event will be set off mov [di].evDelay.hi,bx ; at 55ms (65536 ticks) mov [di].evResolution,TDD_MINRESOLUTION ; Allow 55ms either way mov [di].evFlags,TIME_BIOSEVENT+TIME_PERIODIC mov ax,WinFlags test ax,WF_CPU286 jz @f mov wMaxResolution,TDD_MAX286RESOLUTION mov wMinPeriod,TDD_MIN286PERIOD @@: ifdef NEC_98 mov ax,0001h else ; NEC_98 mov ax,bx ; Return TRUE endif ; NEC_98 mov [di].evID,ax ; enable event pop di ret ifdef NEC_98 error_init: xor ax,ax pop di ret endif ; NEC_98 Lib286Init endp sEnd end LibInit