PAGE ,132 ;  ;AN000; ; SCCSID = @(#)ifsfdos.asm 1.0 87/08/29 ;AN000; TITLE IFSFUNC DOS CALLBACK ROUTINES - Routines for ifs ;AN000; NAME IFSFDOS ;AN000; ;*********************************************************************************** ;AN000; ; ;AN000; ; IFS DOS Callback Routines ;AN000; ; ;AN000; ; IFSFDOS ;AN000; ; ;AN000; ; REVISION HISTORY: ;AN000; ; A000 - Original version 4.00 AUG 1987 DCR - 96 ;AN000; ; A001 - DCR 47 Get disk/device pause status AUG '87 RG ;AN000; ; A002 - PTM 2610 Time/date problems DEC '87 RG ;AN000; ; ;AN000; ; LOC - ;AN000; ; ;AN000; ;*********************************************************************************** ;AN000; ;AN000; .xlist ;AN000; .xcref ;AN000; INCLUDE IFSFSYM.INC ;AN000; INCLUDE IFSSYM.INC ;AN000; INCLUDE DOSSYM.INC ;AN000; INCLUDE DEVSYM.INC ;AN000; .cref ;AN000; .list ;AN000; .sall ;AN000; ;AN000; AsmVars ;AN000; ;AN000; IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; IFSSEG ENDS ;AN000; ;AN000; include dosseg.asm ;AN000; ;AN000; DATA SEGMENT WORD PUBLIC 'DATA' ;AN000; ; DOSGROUP data ;AN000; Extrn YEAR:WORD Extrn YRTAB:BYTE Extrn MONTAB:BYTE DATA ENDS ;AN000; ;AN000; IFSSEG SEGMENT BYTE PUBLIC 'IFSSEG' ;AN000; ASSUME SS:DOSGROUP,CS:IFSSEG ;AN000; ;AN000; ;IFS Data ;AN000; ;AN000; Extrn IFSFUNC_FLAGS:WORD ;AN000; Extrn DOSCALL@:DWORD ;AN000; Extrn fAssign:BYTE ;AN001; Extrn fPrint:BYTE ;AN001; ;AN000; ;AN000; BREAK ;AN000; ;************************************************************************************ ;AN000; ; ;AN000; ; SET_IFS_DOSCALL@ ;AN000; ; ;AN000; ;Called by: ;AN000; ; IFSFUNCINIT ;AN000; ; ;AN000; ; Routines called: ;AN000; ; none ;AN000; ; ;AN000; ; Inputs: ;AN000; ; DS-ifsseg ;AN000; ; ;AN000; ; Function: ;AN000; ; replace ifs_doscall@ addresses in all ifs driver headers with ;AN000; ; ifsfunc address ;AN000; ; ;AN000; ; Outputs: ;AN000; ; none ;AN000; ; ;AN000; ; Notes: all preserved ;AN000; ; ;AN000; ;************************************************************************************ ;AN000; ;AN000; procedure SET_IFS_DOSCALL@,NEAR ;AN000; ASSUME DS:IFSSEG ;AN000; TEST IFSFUNC_FLAGS,NO_IFS_DRIVERS ;AN000; JZ SID_20 ;AN000; transfer ifs_1000 ;AN000; SID_20: ;AN000; SaveReg ;AN000; MOV AH,Get_In_Vars ; Get ptr to ifs hdr chain ;AN000; INT 21h ; es:bx -> sysinitvars ;AN000; LES DI,ES:[BX.SYSI_IFS] ; es:di -> 1st ifs driver ;AN000; SaveReg ;AN000; LES DI,ES:[DI.IFS_DOSCALL@] ;AN000; MOV WORD PTR [DOSCALL@],DI ;AN000; MOV WORD PTR [DOSCALL@+2],ES ;AN000; RestoreReg ; 1st driver addr ;AN000; MOV SI,OFFSET IFSFUNC_DOSCALL@ ;AN000; SID_40: ; *** loop here on ifs_doscall@ fixing ;AN000; MOV WORD PTR ES:[DI.IFS_DOSCALL@],SI ;AN000; MOV WORD PTR ES:[DI.IFS_DOSCALL@+2],DS ;AN000; LES DI,ES:[DI.IFS_NEXT] ; check next fs driver ;AN000; CMP DI,NULL_PTR ; if ptr null, end of ifs drivers ;AN000; JNE SID_40 ;AN000; MOV AX,ES ;AN000; CMP AX,NULL_PTR ;AN000; JNE SID_40 ;AN000; ;AN000; SID_1000: ;AN000; RestoreReg ;AN000; return ;AN000; ;AN000; EndProc SET_IFS_DOSCALL@ ;AN000; ;AN000; ;AN000; ;AN000; BREAK ;AN000; ;************************************************************************************ ;AN000; ; ;AN000; ; IFSFUNC_DOSCALL@ ;AN000; ; ;AN000; ;Called by: ;AN000; ; IFS Drivers ;AN000; ; ;AN000; ; Routines called: ;AN000; ; none ;AN000; ; ;AN000; ; Inputs: ;AN000; ; SS-dosgroup ;AN000; ; ;AN000; ; Function: ;AN000; ; ;AN000; ; Outputs: ;AN000; ; none ;AN000; ; ;AN000; ; Notes: none preserved ;AN000; ; ;AN000; ;************************************************************************************ ;AN000; ;AN000; procedure IFSFUNC_DOSCALL@,FAR ;AN000; ;AN000; CMP AH,33 ;AN001; JNE ID_20 ;AN000; CALL DOS_RETURN_ASSIGN_MODE ;AN001; JMP SHORT ID_1000 ;AN001; ID_20: ;AN001; CMP AH,34 ;AN000; JNE ID_40 ;AN000; CALL DOS_TO_NET_DATE ;AN000; JMP SHORT ID_1000 ;AN000; ID_40: ;AN000; CMP AH,35 ;AN000; JNE ID_100 ;AN000; CALL NET_TO_DOS_DATE ;AN000; JMP SHORT ID_1000 ;AN000; ID_100: ;AN000; CALL CS:[DOSCALL@] ;AN000; ;AN000; ID_1000: ;AN000; RET ;AN000; ;AN000; ;AN000; EndProc IFSFUNC_DOSCALL@ ;AN000; BREAK ;AN000; ;************************************************************************************ ; ; DOS_RETURN_ASSIGN_MODE ; ; Called by: IFSFUNC_DOSCALL@ ; ; Routines called: None ; ; Inputs: ; BL = macro type ; 3 - device ; 4 - drive ; Function: ; If macro type = 3 (network printer) THEN ; BX = fPrint .AND. 1 ; Elseif macro type = 4 (network disk) THEN ; BX = fAssign .AND. 1 ; Else set error_invalid_function ; ; Output: ; Carry clear - BH = mode (0 - off, 1 - on) ; Carry set - AL error code ; ; Notes: This routine needed only for UNC file system. This is the ; only FS that supports pause. ; ;************************************************************************************ Procedure DOS_RETURN_ASSIGN_MODE,NEAR ;AN001; ASSUME DS:NOTHING,ES:NOTHING ;AN001; ;AN001; CMP BL,3 ; if (type == drive) ;AN001; JZ DRAM_20 ;AN001; CMP BL,4 ;AN001; JNZ DRAM_60 ;AN001; MOV BH,fAssign ; t = fAssign; ;AN001; JMP Short DRAM_40 ; else ;AN001; DRAM_20: ; if (type == print) ;AN001; MOV BH,fPrint ; t = fPrint; ;AN001; DRAM_40: ;AN001; AND BH,1 ; return t&1; ;AN001; transfer ifs_990 ; go to general good ret in util ;AN001; ;AN001; DRAM_60: ;AN001; MOV AL,error_invalid_function ;AN001; transfer ifs_980 ; go to general bad ret in util ;AN001; ;AN001; EndProc DOS_RETURN_ASSIGN_MODE ;AN001; BREAK ;AN000; ;************************************************************************************ ; ; DOS_TO_NET ; ; Called by: IFSFUNC_DOSCALL@ ; ; Routines called: None ; ; Inputs: ;AN000; ; DX = MS-DOS Date ;AN000; ; CX = MS-DOS Time ;AN000; ; Function: ;AN000; ; Convert DOS Date Time to Network date ;AN000; ; Outputs: ;AN000; ; DX:CX = Seconds since 1-1-70 ;AN000; ; No other registers Revised ;AN000; ; ;************************************************************************************ FOURYEARS = (3*365) + 366 ; Days in four years ;AN000; procedure DOS_TO_NET_DATE,NEAR ;AN000; ASSUME DS:NOTHING,ES:NOTHING ;AN000; ;AN000; OR AL,AL ; check where to get dos date/time ;AN002; JNZ DTND_20 ;AN002; CallInstall DATE16,MultDOS,13 ; Get local date/time ;AN000; MOV CX,DX ;AN000; XCHG AX,DX ;AN000; ;AN000; DTND_20: ;AN002; PUSH DS ;AN000; PUSH SS ;AN000; POP DS ;AN000; ASSUME DS:DOSGROUP ;AN000; PUSH [YEAR] ; The routines in DOS (in particular ;AN000; ; GET_DATE) do not like [YEAR] ;AN000; ; getting changed by the call ;AN000; ; to SETYEAR. ;AN000; PUSH SI ;AN000; PUSH BX ;AN000; PUSH AX ;AN000; PUSH CX ;AN000; PUSH DX ;AN000; ;AN000; MOV CL,9 ;AN000; SHR DX,CL ; Year to DL ;AN000; MOV CX,DX ; Year in CX (CL) ;AN000; POP DX ;AN000; AND DX,1FFH ; Mask off year ;AN000; SHL DX,1 ;AN000; SHL DX,1 ;AN000; SHL DX,1 ; Month in DH ;AN000; SHR DL,1 ;AN000; SHR DL,1 ;AN000; SHR DL,1 ; Right justify day in DL ;AN000; CallInstall SetYear,MultDOS,27 ; Set [YEAR] and # days in FEB ;AN000; SHR CX,1 ;AN000; SHR CX,1 ; Divide year by 4, chuck remainder ;AN000; MOV AX,FOURYEARS ;AN000; MOV BX,DX ; Get DX out of way ;AN000; MUL CX ; # days in AX ;AN000; MOV CL,BYTE PTR [YEAR] ;AN000; AND CL,3 ; Get remainder from / by 4 ;AN000; MOV SI,OFFSET DOSGROUP:YRTAB ;AN000; MOV DX,AX ;AN000; SHL CX,1 ; Two entries/year ;AN000; CallInstall DSum,MultDOS,28,, ;AN000; MOV CL,BH ; Month ;AN000; DEC CX ; Make 0 indexed ;AN000; MOV SI,OFFSET DOSGROUP:MONTAB ;AN000; CallInstall DSum,MultDOS,28,, ;AN000; MOV CL,BL ; day of month ;AN000; DEC CX ; Make 0 indexed ;AN000; ADD CX,DX ; CX is days since 1-1-80 ;AN000; ; ;AN000; ; The following three instructions implement this: ;AN000; ; ;AN000; ; CX * 15180H sec/day = (CX * 5180H) + (CX * 10000H) ;AN000; ; ;AN000; MOV AX,5180h ;AN000; MUL CX ; (DX:AX) = days * 5180h ;AN000; ADD DX,CX ; (DX:AX) = days * 15180h = seconds ;AN000; ;AN000; ADD AX,0A600H ;AN000; ADC DX,012CEH ; Bias by # seconds from 1-1-70 to ;AN000; ; 1-1-80 (12CEA600H) ;AN000; POP BX ; Get DOS time ;AN000; PUSH AX ;AN000; PUSH DX ; Save date seconds ;AN000; PUSH BX ;AN000; MOV CL,11 ;AN000; SHR BX,CL ; BX is hours ;AN000; MOV AX,60 ;AN000; MUL BX ; AX hours converted to minutes ;AN000; ; 5A0H min/day so DX = 0 ;AN000; POP BX ;AN000; PUSH BX ;AN000; AND BX,7FFH ; Mask off hours ;AN000; MOV CL,5 ;AN000; SHR BX,CL ; BX is minutes ;AN000; ADD AX,BX ; AX is minutes ;AN000; MOV BX,60 ;AN000; MUL BX ; DX:AX is hours:min converted to sec ;AN000; POP BX ;AN000; AND BX,1FH ; BX is seconds/2 ;AN000; SHL BX,1 ; BX is seconds ;AN000; ADD AX,BX ;AN000; ADC DX,0 ;AN000; MOV CX,AX ; DX:CX is DOS time in seconds ;AN000; POP BX ;AN000; POP SI ; BX:SI is DOS Date in seconds ;AN000; ADD CX,SI ;AN000; ADC DX,BX ; DX:CX is NET time ;AN000; POP AX ;AN000; POP BX ;AN000; POP SI ;AN000; POP [YEAR] ;AN000; POP DS ;AN000; return ;AN000; ;AN000; EndProc DOS_TO_NET_DATE ;AN000; ;AN000; ; Inputs: ;AN000; ; DX:CX = Seconds since 1-1-70 ;AN000; ; Function: ;AN000; ; Convert Network date to DOS Date Time ;AN000; ; NOTE: WARNING!!!!!!! ;AN000; ; This routine WILL NOT convert network times > 92CEA5FFH ;AN000; ; (7FFFFFFF + 12CEA600). If such a time is encountered this ;AN000; ; routine returns 1-1-80 0:0:0. ;AN000; ; Outputs: ;AN000; ; DX = MS-DOS Date ;AN000; ; CX = MS-DOS Time ;AN000; ; No other registers Revised ;AN000; ;AN000; procedure NET_TO_DOS_DATE,NEAR ;AN000; ASSUME DS:NOTHING,ES:NOTHING ;AN000; SUB CX,0A600H ;AN000; SBB DX,012CEH ; UnBias by # seconds from 1-1-70 to ;AN000; ; 1-1-80 (12CEA600H) ;AN000; JNC GO_ON ;AN000; ; Date is before 1-1-80 ;AN000; TO_BIG_LITTLE_TIME: ;AN000; XOR DX,DX ;AN000; MOV CX,DX ; Set 1-1-80 0:0:0 ;AN000; return ;AN000; ;AN000; GO_ON: ;AN000; TEST DX,8000H ; Check for high bit ;AN000; JNZ TO_BIG_LITTLE_TIME ;AN000; PUSH DS ;AN000; PUSH SS ;AN000; POP DS ;AN000; ASSUME DS:DOSGROUP ;AN000; PUSH [YEAR] ; The routines in DOS (in particular ;AN000; ; GET_DATE) do not like [YEAR] ;AN000; ; getting changed by the call ;AN000; ; to SETYEAR. ;AN000; PUSH AX ;AN000; PUSH BX ;AN000; PUSH SI ;AN000; PUSH BP ;AN000; XCHG AX,CX ; DX:AX # seconds ;AN000; MOV SI,0A8C0h ; (si) = seconds in a half day ;AN000; ; 15180H/2 ;AN000; ; ;AN000; ; NOTE: The following DIV is the reason we can't convert times with the ;AN000; ; high bit set (after they're unbiased by 1-1-80 - 1-1-70). ;AN000; ; If we tried one it MIGHT overflow. The cutoff is ;AN000; ; actually (A8C0 * FFFF) + A8BF = A8BFFFFF but we choose a smaller ;AN000; ; number (7FFFFFFF) because it's easier to test for. 7FFFFFFF = ;AN000; ; about 68 years from 1-1-80 which is 1-1-2048. ;AN000; ; ;AN000; DIV SI ; (AX) = 2*days ;AN000; ; (CX) = half-day remainder ;AN000; MOV BX,DX ;AN000; XOR DX,DX ;AN000; MOV CX,DX ;AN000; SHR AX,1 ; DX:AX = days ;AN000; JNC NTDD1 ; didn't shift off a bit, no extra rem ;AN000; ADD BX,0A8C0h ; did shift bit, adjust remainder ;AN000; ADC CX,0 ; by extra 1/2 day of seconds ;AN000; ;AN000; ;DX:AX is # days since 1-1-80 ;AN000; ;CX:BX is seconds into that day ;AN000; NTDD1: ;AN000; PUSH DX ;AN000; PUSH AX ;AN000; MOV DX,CX ;AN000; MOV AX,BX ;AN000; MOV CX,60 ; 60 sec/min ;AN000; DIV CX ;AN000; ;AX is min, DX(DL) is secs ;AN000; DIV CL ; 60 min/hr ;AN000; ;AH is Min, AL is hrs ;AN000; SHR DL,1 ; Div seconds by 2 ;AN000; AND DL,1FH ; DL is seconds/2 ;AN000; MOV DH,AH ; Copy min to DH ;AN000; MOV CL,5 ;AN000; SHL AH,CL ; Low 3 bits of min in high 3 bits ;AN000; OR DL,AH ; DL is now low byte of time ;AN000; MOV CL,3 ;AN000; SHR DH,CL ; High 3 bits of min to low 3 bits ;AN000; AND DH,7 ;AN000; MOV CL,3 ;AN000; SHL AL,CL ; Hours to high 5 bits ;AN000; AND AL,0F8H ;AN000; OR DH,AL ; DX is now DOS time ;AN000; MOV CX,DX ;AN000; POP AX ;AN000; POP DX ; DX:AX days since 1-1-80 ;AN000; PUSH CX ; Stash time ;AN000; MOV CX,FOURYEARS ;AN000; DIV CX ; AX # four year increments ;AN000; ; DX remainder days ;AN000; SHL AX,1 ;AN000; SHL AX,1 ;AN000; SHL AX,1 ; Mult by 8 (AX # 1/2 years) ;AN000; MOV CX,AX ;AN000; MOV SI,OFFSET DOSGROUP:YRTAB ;AN000; CallInstall DSlide,MultDOS,29,, ;AN000; SHR CX,1 ; 1/2 years to whole years ;AN000; JNC SK ;AN000; ADD DX,200 ; Extra 1/2 year ;AN000; SK: ;AN000; CallInstall SetYear,multDOS,27 ;AN000; PUSH CX ;AN000; MOV CL,1 ; At least at first month in year ;AN000; MOV SI,OFFSET DOSGROUP:MONTAB ;AN000; CallInstall DSlide,MultDOS,29,, ;AN000; INC DX ; Days start at 1 ;AN000; POP AX ;AN000; MOV CH,CL ;AN000; ; DL is day, CH is month, AL is year ;AN000; SHL AL,1 ; Year to high 7 bits ;AN000; AND AL,0FEH ;AN000; MOV AH,CH ;AN000; MOV CL,3 ;AN000; SHR AH,CL ; High bit of month to bit 0 ;AN000; AND AH,1 ;AN000; OR AH,AL ; AH is high byte of date ;AN000; AND DL,1FH ; Day is low 5 bits ;AN000; MOV CL,5 ;AN000; SHL CH,CL ; Low 3 bits of month to high 3 bits ;AN000; AND CH,0E0H ;AN000; OR DL,CH ;AN000; MOV DH,AH ; Date in DX ;AN000; POP CX ; Time to CX ;AN000; POP BP ;AN000; POP SI ;AN000; POP BX ;AN000; POP AX ;AN000; POP [YEAR] ;AN000; POP DS ;AN000; return ;AN000; ;AN000; EndProc NET_TO_DOS_DATE ;AN000; ;AN000; IFSSEG ENDS ;AN000; END ;AN000;