From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DOS/MS_CODE.ASM | 614 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 614 insertions(+) create mode 100644 v4.0/src/DOS/MS_CODE.ASM (limited to 'v4.0/src/DOS/MS_CODE.ASM') diff --git a/v4.0/src/DOS/MS_CODE.ASM b/v4.0/src/DOS/MS_CODE.ASM new file mode 100644 index 0000000..1bdd4af --- /dev/null +++ b/v4.0/src/DOS/MS_CODE.ASM @@ -0,0 +1,614 @@ +; SCCSID = @(#)mscode.asm 1.2 85/07/23 +; +; MSCODE.ASM -- MSDOS code +; + +.xlist +.xcref +include dossym.inc +include devsym.inc +include dosseg.asm +include ifssym.inc +include fastopen.inc +include fastxxxx.inc +.cref +.list + +AsmVars + +CODE SEGMENT BYTE PUBLIC 'CODE' + +ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + I_need InDos,BYTE ; TRUE => we are in dos, no interrupt + I_need OpenBuf,128 ; temp name buffer + I_need ExtErr,WORD ; extended error code + I_need User_SS,WORD ; stack segment from user + I_need User_SP,WORD ; stack pointer from user + I_need DskStack,BYTE ; stack segment inside DOS + I_need ThisCDS,DWORD ; Currently referenced CDS pointer + I_need ThisDPB,DWORD ; Currently referenced DPB pointer + I_need Err_Table_21 ; allowed return map table for errors + I_need FailErr,BYTE ; TRUE => system call is being failed + I_need ExtErr_Action,BYTE ; recommended action + I_need ExtErr_Class,BYTE ; error classification + I_need ExtErr_Locus,BYTE ; error location + I_need I21_Map_E_Tab,BYTE ; mapping extended error table + I_need User_In_AX,WORD ; initial input user AX + I_need FOO,WORD ; return address for dos 2f dispatch + I_need DTAB,WORD ; dos 2f dispatch table + I_need HIGH_SECTOR,WORD ; >32mb + I_need IFS_DRIVER_ERR,WORD ; >32mb + I_need FastOpenFlg,BYTE ; + I_need FastSeekFlg,BYTE ; + I_need CURSC_DRIVE,BYTE ; + +BREAK + +procedure SNULDEV,FAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + OR ES:[BX.REQSTAT],STDON ; Set done bit +entry INULDEV + RET ; MUST NOT BE A RETURN! +EndProc SNULDEV + +BREAK + + +TABLE SEGMENT +Public MSC001S,MSC001E +MSC001S label byte + IF IBM +; Codes returned by BIOS +ERRIN: + DB 2 ; NO RESPONSE + DB 6 ; SEEK FAILURE + DB 12 ; GENERAL ERROR + DB 4 ; BAD CRC + DB 8 ; SECTOR NOT FOUND + DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK +ERROUT: +; DISK ERRORS RETURNED FROM INT 25 and 26 + DB 80H ; NO RESPONSE + DB 40H ; Seek failure + DB 2 ; Address Mark not found + DB 10H ; BAD CRC + DB 4 ; SECTOR NOT FOUND + DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK + +NUMERR EQU $-ERROUT + ENDIF +MSC001E label byte + +TABLE ENDS + +; AbsSetup - setup for abs disk functions + +Procedure AbsSetup,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + INC INDOS + STI + CLD + PUSH DS + Context DS + CALL GETBP + JC errdriv ;PM. error drive ;AN000; + MOV ES:[BP.dpb_free_cnt],-1 ; do not trust user at all. +errdriv: + POP DS +ASSUME DS:NOTHING + retc + + MOV [HIGH_SECTOR],0 ;>32mb from API ;AN000; + CALL RW32_CONVERT ;>32mb convert 32bit format to 16bit ;AN000; + retc + + invoke SET_RQ_SC_PARMS ;LB. set up SC parms ;AN000; + PUSH DS + PUSH SI + PUSH AX + Context DS + MOV SI,OFFSET DOSGROUP:OPENBUF + MOV [SI],AL + ADD BYTE PTR [SI],"A" + MOV WORD PTR [SI+1],003AH ; ":",0 + MOV AX,0300H + CLC + INT int_IBM ; Will set carry if shared + POP AX + POP SI + POP DS +ASSUME DS:NOTHING + retnc + MOV ExtErr,error_not_supported + return +EndProc AbsSetup + +; Interrupt 25 handler. Performs absolute disk read. +; Inputs: AL - 0-based drive number +; DS:BX point to destination buffer +; CX number of logical sectors to read +; DX starting logical sector number (0-based) +; Outputs: Original flags still on stack +; Carry set +; AH error from BIOS +; AL same as low byte of DI from INT 24 + + procedure ABSDRD,FAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + + CLI + MOV [user_SS],SS + MOV [user_SP],SP + PUSH CS + POP SS +ASSUME SS:DOSGROUP + MOV SP,OFFSET DOSGROUP:DSKSTACK + invoke Save_World ;>32mb save all regs ;AN000; + PUSH ES + CALL AbsSetup + JC ILEAVE +if not ibmcopyright +; Here is a gross temporary fix to get around a serious design flaw in +; the secondary cache. The secondary cache does not check for media +; changed (it should). Hence, you can change disks, do an absolute +; read, and get data from the previous disk. To get around this, +; we just won't use the secondary cache for absolute disk reads. +; -mw 8/5/88 + EnterCrit critDisk + MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000; + LeaveCrit critDisk +endif + invoke DSKREAD +TLEAVE: + JZ ILEAVE + + IF IBM +; Translate the error code to ancient 1.1 codes + PUSH ES + PUSH CS + POP ES + XOR AH,AH ; Nul error code + MOV CX,NUMERR ; Number of possible error conditions + MOV DI,OFFSET DOSGROUP:ERRIN ; Point to error conditions + REPNE SCASB + JNZ LEAVECODE ; Not found + MOV AH,ES:[DI+NUMERR-1] ; Get translation +LEAVECODE: + POP ES + ENDIF + MOV [IFS_DRIVER_ERR],AX ;>32mb save error + STC +ILEAVE: + POP ES + invoke Restore_World ;>32mb ;AN000; + CLI + DEC INDOS + MOV SS,[user_SS] +ASSUME SS:NOTHING + MOV SP,[user_SP] + MOV AX,[IFS_DRIVER_ERR] ;>32mb restore error ;AN000; + STI + RET ; This must not be a RETURN! +EndProc ABSDRD + +; Interrupt 26 handler. Performs absolute disk write. +; Inputs: AL - 0-based drive number +; DS:BX point to source buffer +; CX number of logical sectors to write +; DX starting logical sector number (0-based) +; Outputs: Original flags still on stack +; Carry set +; AH error from BIOS +; AL same as low byte of DI from INT 24 + + procedure ABSDWRT,FAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + CLI + MOV [user_SS],SS + MOV [user_SP],SP + PUSH CS + POP SS +ASSUME SS:DOSGROUP + MOV SP,OFFSET DOSGROUP:DSKSTACK + invoke Save_World ;>32mb save all regs ;AN000; + + PUSH ES + CALL AbsSetup + JC ILEAVE + + EnterCrit critDisk + MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000; + CALL Fastxxx_Purge ; purge fatopen ;AN000; + LeaveCrit critDisk + + invoke DSKWRITE + JMP TLEAVE +EndProc ABSDWRT + +; Inputs: +; AL = Logical unit number (A = 0) +; Function: +; Find Drive Parameter Block +; Outputs: +; ES:BP points to DPB +; [THISDPB] = ES:BP +; Carry set if unit number bad or unit is a NET device. +; Later case sets extended error error_I24_not_supported +; No other registers altered + +Procedure GETBP,NEAR + DOSAssume CS,,"GetBP" + ASSUME ES:NOTHING + + PUSH AX + ADD AL,1 ; No increment; need carry flag + JC SkipGet + invoke GetThisDrv + JNC SkipGet ;PM. good drive ;AN000; + XOR AH,AH ;DCR. ax= error code ;AN000; + CMP AX,error_not_dos_disk ;DCR. is unknown media ? ;AN000; + JZ SkipGet ;DCR. yes, let it go ;AN000; + STC ;DCR. ;AN000; + MOV ExtErr,AX ;PM. invalid drive or Non DOS drive ;AN000; + MOV [IFS_DRIVER_ERR],0201H ;PM. other errors/unknown unit ;AN000; +SkipGet: + POP AX + retc + LES BP,[THISCDS] + TEST ES:[BP.curdir_flags],curdir_isnet ; Clears carry + JZ GETBP_CDS + LES BP,ES:[BP.curdir_ifs_hdr] ;IFS. if remote file ;AN000; + TEST ES:[BP.ifs_attribute],IFSREMOTE ;IFS. ;AN000; + LES BP,[THISCDS] + JZ GETBP_CDS ;IFS. then error ;AN000; + MOV ExtErr,error_not_supported + STC + return + +GETBP_CDS: + LES BP,ES:[BP.curdir_devptr] + + entry GOTDPB + DOSAssume CS,,"GotDPB" +; Load THISDPB from ES:BP + + MOV WORD PTR [THISDPB],BP + MOV WORD PTR [THISDPB+2],ES + return +EndProc GetBP + +BREAK + +ASSUME SS:DOSGROUP + +; +; These are the general system call exit mechanisms. All internal system +; calls will transfer (jump) to one of these at the end. Their sole purpose +; is to set the user's flags and set his AX register for return. +; + +procedure SYS_RETURN,NEAR + ASSUME DS:NOTHING,ES:NOTHING +entry SYS_RET_OK + invoke FETCHI_CHECK ; TAG checking for FETCHI + invoke get_user_stack + AND [SI.user_F],NOT f_Carry ; turn off user's carry flag + JMP SHORT DO_RET ; carry is now clear + +entry SYS_RET_ERR + XOR AH,AH ; hack to allow for smaller error rets + invoke ETAB_LK ; Make sure code is OK, EXTERR gets set + CALL ErrorMap +entry From_GetSet + invoke get_user_stack + OR [SI.user_F],f_Carry ; signal carry to user + STC ; also, signal internal error +DO_RET: + MOV [SI.user_AX],AX ; Really only sets AH + return + + entry FCB_RET_OK + entry CPMFunc + XOR AL,AL + return + + entry FCB_RET_ERR + XOR AH,AH + mov exterr,AX + CALL ErrorMap + MOV AL,-1 + return + + entry errorMap + PUSH SI + MOV SI,OFFSET DOSGROUP:ERR_TABLE_21 + CMP [FAILERR],0 ; Check for SPECIAL case. + JZ EXTENDED_NORMAL ; All is OK. + MOV [EXTERR],error_FAIL_I24 ; Ooops, this is the REAL reason + MOV SI,OFFSET DOSGROUP:ERR_TABLE_21 +EXTENDED_NORMAL: + invoke CAL_LK ; Set CLASS,ACTION,LOCUS for EXTERR + POP SI + return + +EndProc SYS_RETURN + +; Inputs: +; SI is OFFSET in DOSGROUP of CLASS,ACTION,LOCUS Table to use +; (DS NEED not be DOSGROUP) +; [EXTERR] is set with error +; Function: +; Look up and set CLASS ACTION and LOCUS values for GetExtendedError +; Outputs: +; [EXTERR_CLASS] set +; [EXTERR_ACTION] set +; [EXTERR_LOCUS] set (EXCEPT on certain errors as determined by table) +; Destroys SI, FLAGS + + procedure CAL_LK,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS + PUSH AX + PUSH BX + Context DS ; DS:SI -> Table + MOV BX,[EXTERR] ; Get error in BL +TABLK1: + LODSB + CMP AL,0FFH + JZ GOT_VALS ; End of table + CMP AL,BL + JZ GOT_VALS ; Got entry + ADD SI,3 ; Next table entry + JMP TABLK1 + +GOT_VALS: + LODSW ; AL is CLASS, AH is ACTION + CMP AH,0FFH + JZ NO_SET_ACT + MOV [EXTERR_ACTION],AH ; Set ACTION +NO_SET_ACT: + CMP AL,0FFH + JZ NO_SET_CLS + MOV [EXTERR_CLASS],AL ; Set CLASS +NO_SET_CLS: + LODSB ; Get LOCUS + CMP AL,0FFH + JZ NO_SET_LOC + MOV [EXTERR_LOCUS],AL +NO_SET_LOC: + POP BX + POP AX + POP DS + return +EndProc CAL_LK + +; Inputs: +; AX is error code +; [USER_IN_AX] has AH value of system call involved +; Function: +; Make sure error code is appropriate to this call. +; Outputs: +; AX MAY be mapped error code +; [EXTERR] = Input AX +; Destroys ONLY AX and FLAGS + + procedure ETAB_LK,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS + PUSH SI + PUSH CX + PUSH BX + Context DS + MOV [EXTERR],AX ; Set EXTERR with "real" error + MOV SI,OFFSET DOSGROUP:I21_MAP_E_TAB + MOV BH,AL ; Real code to BH + MOV BL,BYTE PTR [USER_IN_AX + 1] ; Sys call to BL +TABLK2: + LODSW + CMP AL,0FFH ; End of table? + JZ NOT_IN_TABLE ; Yes + CMP AL,BL ; Found call? + JZ GOT_CALL ; Yes + XCHG AH,AL ; Count to AL + XOR AH,AH ; Make word for add + ADD SI,AX ; Next table entry + JMP TABLK2 + +NOT_IN_TABLE: + MOV AL,BH ; Restore original code + JMP SHORT NO_MAP + +GOT_CALL: + MOV CL,AH + XOR CH,CH ; Count of valid err codes to CX +CHECK_CODE: + LODSB + CMP AL,BH ; Code OK? + JZ NO_MAP ; Yes + LOOP CHECK_CODE +NO_MAP: + XOR AH,AH ; AX is now valid code + POP BX + POP CX + POP SI + POP DS + return + +EndProc ETAB_LK + +BREAK + +IF installed + +; +; SetBad sets up info for bad functions +; +Procedure SetBad,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV AX,error_invalid_function ; ALL NET REQUESTS get inv func + MOV ExtErr_LOCUS,errLoc_UNK + STC + ret +EndProc SetBad +; +; BadCall is the initial routine for bad function calls +; +procedure BadCall,FAR + call SetBad + ret +EndProc BadCall +; +; OKCall always sets carry to off. +; +Procedure OKCall,FAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CLC + ret +EndProc OKCall + +; INT 2F handler works as follows: +; PUSH AX +; MOV AX,multiplex:function +; INT 2F +; POP ... +; The handler itself needs to make the AX available for the various routines. + +PUBLIC Int2F +INT2F PROC FAR + +INT2FNT: + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + STI + CMP AH,multNET + JNZ INT2FSHR +TestInstall: + OR AL,AL + JZ Leave2F +BadFunc: + CALL SetBad + entry Leave2F + RET 2 ; long return + clear flags off stack + +INT2FSHR: + CMP AH,multSHARE ; is this a share request + JZ TestInstall ; yes, check for installation + +INT2FNLS: + CMP AH,NLSFUNC ; is this a DOS 3.3 NLSFUNC request + JZ TestInstall ; yes check for installation + +INT2FDOS: + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CMP AH,multDOS + JZ DispatchDOS + IRET ; This assume that we are at the head + ; of the list +INT2F ENDP + +DispatchDOS: + PUSH FOO ; push return address + PUSH DTab ; push table address + PUSH AX ; push index + PUSH BP + MOV BP,SP +; stack looks like: +; 0 BP +; 2 DISPATCH +; 4 TABLE +; 6 RETURN +; 8 LONG-RETURN +; c FLAGS +; e AX + + MOV AX,[BP+0Eh] ; get AX value + POP BP + Invoke TableDispatch + JMP BadFunc ; return indicates invalid function + +Procedure INT2F_etcetera,NEAR + entry DosGetGroup + PUSH CS + POP DS + return + + entry DOSInstall + MOV AL,0FFh + return +EndProc INT2F_etcetera + +ENDIF +;Input: same as ABSDRD and ABSDWRT +; ES:BP -> DPB +;Functions: convert 32bit absolute RW input parms to 16bit input parms +;Output: carry set when CX=-1 and drive is less then 32mb +; carry clear, parms ok +; +Procedure RW32_CONVERT,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CMP CX,-1 ;>32mb new format ? ;AN000; + JZ new32format ;>32mb yes ;AN000; + PUSH AX ;>32mb save ax ;AN000; + PUSH DX ;>32mb save dx ;AN000; + MOV AX,ES:[BP.dpb_max_cluster] ;>32mb get max cluster # ;AN000; + MOV DL,ES:[BP.dpb_cluster_mask] ;>32mb ;AN000; + CMP DL,0FEH ;>32mb removable ? ;AN000; + JZ letold ;>32mb yes ;AN000; + INC DL ;>32mb ;AN000; + XOR DH,DH ;>32mb dx = sector/cluster ;AN000; + MUL DX ;>32mb dx:ax= max sector # ;AN000; + OR DX,DX ;>32mb > 32mb ? ;AN000; +letold: + POP DX ;>32mb retore dx ;AN000; + POP AX ;>32mb restore ax ;AN000; + JZ old_style ;>32mb no ;AN000; + MOV [IFS_DRIVER_ERR],0207H ;>32mb error ;AN000; + STC ;>32mb ;AN000; + return ;>32mb ;AN000; +new32format: + MOV DX,WORD PTR [BX.SECTOR_RBA+2];>32mb ;AN000; + MOV [HIGH_SECTOR],DX ;>32mb ;AN000; + MOV DX,WORD PTR [BX.SECTOR_RBA] ;>32mb ;AN000; + MOV CX,[BX.ABS_RW_COUNT] ;>32mb ;AN000; + LDS BX,[BX.BUFFER_ADDR] ;>32mb ;AN000; +old_style: ;>32mb ;AN000; + CLC ;>32mb ;AN000; + return ;>32mb ;AN000; +EndProc RW32_CONVERT + + +;Input: None +;Functions: Purge Fastopen/seek Cache Buffers +;Output: None +; +; +Procedure Fastxxx_Purge,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH AX ; save regs. ;AN000; + PUSH SI ;AN000; + PUSH DX ;AN000; + TEST FastSeekflg,Fast_yes ; fastseek installed ? ;AN000; + JZ topen ; no ;AN000; + MOV AH,FastSeek_ID ; set fastseek id ;AN000; + JMP SHORT dofast ; ;AN000; +topen: + TEST FastOpenflg,Fast_yes ; fastopen installed ? ;AN000; + JZ nofast ; no ;AN000; + MOV AH,FastOpen_ID ; set fastseek installed ;AN000; +dofast: + MOV AL,FONC_purge ; purge ;AN000; + MOV DL,ES:[BP.dpb_drive] ; set up drive number ;AN000; + invoke Fast_Dispatch ; call fastopen/seek ;AN000; +nofast: + POP DX ;AN000; + POP SI ; restore regs ;AN000; + POP AX ; ;AN000; + + return ; exit ;AN000; +EndProc Fastxxx_Purge + +CODE ENDS + \ No newline at end of file -- cgit v1.2.3