From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/XENIX2.ASM | 626 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 626 insertions(+) create mode 100644 v2.0/source/XENIX2.ASM (limited to 'v2.0/source/XENIX2.ASM') diff --git a/v2.0/source/XENIX2.ASM b/v2.0/source/XENIX2.ASM new file mode 100644 index 0000000..1535dbb --- /dev/null +++ b/v2.0/source/XENIX2.ASM @@ -0,0 +1,626 @@ +; +; xenix file calls for MSDOS +; + +INCLUDE DOSSEG.ASM + +IFNDEF KANJI +KANJI EQU 0 ;FALSE +ENDIF + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xlist +.xcref +INCLUDE DOSSYM.ASM +INCLUDE DEVSYM.ASM +.cref +.list + +TITLE XENIX - IO system to mimic UNIX +NAME XENIX + + i_need NoSetDir,BYTE + i_need CURDRV,BYTE + i_need IOCALL,BYTE + i_need IOMED,BYTE + i_need IOSCNT,WORD + i_need IOXAD,DWORD + i_need DIRSTART,WORD + i_need ATTRIB,BYTE + i_need THISFCB,DWORD + i_need AuxStack,BYTE + i_need Creating,BYTE + i_need ThisDRV,BYTE + i_need NAME1,BYTE + i_need LastEnt,WORD + i_need ThisDPB,DWORD + i_need EntLast,WORD + i_need CurrentPDB,WORD + i_need sft_addr,DWORD ; pointer to head of table + i_need CURBUF,DWORD ; pointer to current buffer + i_need DMAADD,DWORD ; pointer to current dma address + +BREAK + +CODE ENDS +DATA SEGMENT BYTE PUBLIC 'DATA' + + +PushSave DW ? +PushES DW ? +PushBX DW ? + +xenix_count DW ? + +DATA ENDS +CODE SEGMENT BYTE PUBLIC 'CODE' + + +BREAK +; +; get_sf_from_sfn +; input: AX has sfn (0 based) +; DS is DOSGROUP +; output: JNC +; ES:DI is sf entry +; JC +; ES,DI indeterminate +; + procedure get_sf_from_sfn,NEAR + ASSUME DS:DOSGROUP,ES:NOTHING + PUSH AX ; we trash AX in process + LES DI,[sft_addr] + +get_sfn_loop: + CMP DI,-1 ; end of chain of tables? + JZ get_sf_invalid ; I guess so... + SUB AX,ES:[DI].sft_count ; chop number of entries in this table + JL get_sf_gotten ; sfn is in this table + LES DI,ES:[DI].sft_link ; step to next table + JMP get_sfn_loop + +get_sf_gotten: + ADD AX,ES:[DI].sft_count ; reset to index in this table + PUSH BX + MOV BX,SIZE sf_entry + MUL BL ; number of bytes offset into table + POP BX + ADD AX,sft_table ; offset into sf table structure + ADD DI,AX ; offset into memory + CLC + JMP SHORT get_sf_ret + +get_sf_jfn_invalid: +get_sf_invalid: + STC + +get_sf_jfn_ret: +get_sf_ret: + POP AX ; remember him? + RET +get_sf_from_sfn ENDP + +BREAK +; +; get_sf_from_jfn +; input: BX is jfn 0 based +; DS is DOSGROUP +; output: JNC +; ES:DI is sf entry +; JC +; ES,DI is indeterminate +; + procedure get_sf_from_jfn,NEAR + ASSUME DS:DOSGROUP,ES:NOTHING + PUSH AX ; save him + invoke get_jfn_pointer + JC get_sf_jfn_invalid + MOV AL,ES:[DI] ; get sfn + CMP AL,0FFh ; is it free? + JZ get_sf_jfn_invalid ; yep... error + XOR AH,AH + invoke get_sf_from_sfn ; check this sfn out... + JMP SHORT get_sf_jfn_ret ; condition codes are properly set + +get_sf_from_jfn ENDP + +BREAK +; +; get_jfn_pointer +; input: BX is jfn +; DS is DOSGROUP +; output: JNC +; ES:DI is pointer to jfn +; JC +; + procedure Get_jfn_pointer,NEAR + ASSUME DS:DOSGROUP,ES:NOTHING + CMP BX,FilPerProc + JAE get_jfn_bad + MOV ES,[CurrentPDB] + MOV DI,BX + ADD DI,PDB_JFN_Table + CLC + RET + +get_jfn_bad: + STC + RET +get_jfn_pointer ENDP + + +BREAK <$Close - release a handle> +; +; Assembler usage: +; MOV BX, handle +; MOV AH, Close +; INT int_command +; +; Error return: +; AX = error_invalid_handle +; + procedure $Close,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + context DS + + invoke get_jfn_pointer ; get jfn loc + JNC close_jfn +close_bad_handle: + error error_invalid_handle + +close_jfn: + MOV AL,BYTE PTR ES:[DI] + CMP AL,0FFh + JE close_bad_handle + MOV BYTE PTR ES:[DI],0FFh; + XOR AH,AH + invoke get_sf_from_sfn + JC close_bad_handle + PUSH ES + POP DS + ASSUME DS:NOTHING + DEC [DI].sf_ref_count ; no more reference + LEA DX,[DI].sf_fcb +; +; need to restuff Attrib if we are closing a protected file +; + TEST [DI.sf_fcb.fcb_DevID],devid_file_clean+devid_device + JNZ close_ok + PUSH WORD PTR [DI].sf_attr + invoke MOVNAMENOSET + POP BX + MOV [Attrib],BL + invoke FCB_CLOSE_INNER + CMP AL,0FFh ; file not found error? + JNZ close_ok + error error_file_not_found +close_ok: + transfer SYS_RET_OK + +$Close ENDP + + +BREAK +; PushDMA +; input: DS:DX is DMA +; output: DS:DX is normalized , ES:BX destroyed +; [DMAADD] is now set up to DS:DX +; old DMA is pushed + + procedure PushDMA,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + MOV PushES,ES + MOV PushBX,BX + POP PushSave + LES BX,DWORD PTR [DMAADD] ; get old dma + PUSH ES + PUSH BX + PUSH PushSave + invoke ptr_normalize ; get new dma + MOV WORD PTR [DMAADD],DX ; save IT! + MOV WORD PTR [DMAADD+2],DS + MOV ES,PushES + MOV BX,PushBX + RET +PushDMA ENDP + +; PopDMA +; input: old DMA under ret address on stack +; output: [DMAADD] set to old version and stack popped + procedure PopDMA,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + POP PushSave + POP WORD PTR [DMAADD] + POP WORD PTR [DMAADD+2] + PUSH PushSave + RET +PopDMA ENDP + +; ptr_normalize +; input: DS:DX is a pointer +; output: DS:DX is normalized (DX < 10h) + procedure ptr_normalize,NEAR + PUSH CX ; T1 = CX + PUSH DX ; T2 = DX + MOV CL,4 + SHR DX,CL ; DX = (DX >> 4) (using CX) + MOV CX,DS + ADD CX,DX + MOV DS,CX ; DS = DS + DX (using CX) + POP DX + AND DX,0Fh ; DX = T2 & 0Fh + POP CX ; CX = T1 + +; PUSH AX +; PUSH DX +; MOV AX,DS +; PUSH CX +; MOV CL,4 +; SHR DX,CL ; get upper part of dx +; POP CX +; ADD AX,DX ; add into seg address +; MOV DS,AX +; POP DX +; AND DX,0Fh ; save low part +; POP AX + + RET +ptr_normalize ENDP + +BREAK <$Read - Do file/device I/O> +; +; Assembler usage: +; LDS DX, buf +; MOV CX, count +; MOV BX, handle +; MOV AH, Read +; INT int_command +; AX has number of bytes read +; Errors: +; AX = read_invalid_handle +; = read_access_denied +; + + procedure $Read,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + invoke PushDMA + CALL IO_setup + JC IO_err + CMP ES:[DI].sf_mode,open_for_write + JNE read_setup +IO_bad_mode: + MOV AL,read_access_denied +IO_err: + invoke PopDMA + transfer SYS_RET_ERR + +read_setup: + invoke $FCB_RANDOM_READ_BLOCK ; do read +IO_done: + invoke get_user_stack ; get old frame + MOV AX,[SI].user_CX ; get returned CX + MOV CX,xenix_count + MOV [SI].user_CX,CX ; stash our CX + invoke PopDMA ; get old DMA + transfer SYS_RET_OK +$Read ENDP + +BREAK <$Write - Do file/device I/O> +; +; Assembler usage: +; LDS DX, buf +; MOV CX, count +; MOV BX, handle +; MOV AH, Write +; INT int_command +; AX has number of bytes written +; Errors: +; AX = write_invalid_handle +; = write_access_denied +; + + procedure $Write,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + invoke PushDMA + CALL IO_setup + JC IO_err + CMP ES:[DI].sf_mode,open_for_read + JE IO_bad_mode + invoke $FCB_RANDOM_WRITE_BLOCK ; do write + JMP IO_done + +$write ENDP + +IO_setup: + ASSUME DS:NOTHING,ES:NOTHING + context DS + MOV xenix_count,CX + invoke Get_sf_from_jfn + ; ES:DI is sf pointer + MOV AL,read_invalid_handle ;Assume an error + MOV CX,xenix_count + LEA DX,[DI].sf_fcb + PUSH ES + POP DS + ASSUME DS:NOTHING + RET + +BREAK <$LSEEK - set random record field> +; +; Assembler usage: +; MOV DX, offsetlow +; MOV CX, offsethigh +; MOV BX, handle +; MOV AL, method +; MOV AH, LSeek +; INT int_command +; DX:AX has the new location of the pointer +; Error returns: +; AX = error_invalid_handle +; = error_invalid_function + procedure $LSEEK,NEAR + ASSUME DS:NOTHING,ES:NOTHING + CMP AL,3 + JB lseek_get_sf + error error_invalid_function + +lseek_get_sf: + context DS + invoke get_sf_from_jfn + PUSH ES + POP DS + ASSUME DS:NOTHING + JC lseek_bad +; +; don't seek device +; + TEST [DI.sf_fcb+fcb_devid],devid_device + JZ lseek_dispatch + XOR AX,AX + XOR DX,DX + JMP SHORT lseek_ret +lseek_dispatch: + DEC AL + JL lseek_beginning + DEC AL + JL lseek_current +; move from end of file +; first, get end of file + XCHG AX,DX ; AX <- low + XCHG DX,CX ; DX <- high + ASSUME DS:NOTHING + ADD AX,[DI+sf_fcb+fcb_FILSIZ] + ADC DX,[DI+sf_fcb+fcb_FILSIZ+2] + JMP SHORT lseek_ret + +lseek_beginning: + XCHG AX,DX ; AX <- low + XCHG DX,CX ; DX <- high + +lseek_ret: + MOV WORD PTR [DI+sf_fcb+fcb_RR],AX + MOV WORD PTR [DI+sf_fcb+fcb_RR+2],DX + invoke get_user_stack + MOV [SI.user_DX],DX + MOV [SI.user_AX],AX + transfer SYS_RET_OK + +lseek_current: +; ES:DI is pointer to sf... need to invoke set random record for place + XCHG AX,DX ; AX <- low + XCHG DX,CX ; DX <- high + ADD AX,WORD PTR [DI+sf_fcb+fcb_RR] + ADC DX,WORD PTR [DI+sf_fcb+fcb_RR+2] + JMP lseek_ret + +lseek_bad: + error error_invalid_handle +$lseek ENDP + + +BREAK <$IOCTL - return/set device dependent stuff> +; +; Assembler usage: +; MOV BX, Handle +; MOV DX, Data +; +; (or LDS DX,BUF +; MOV CX,COUNT) +; +; MOV AH, Ioctl +; MOV AL, Request +; INT 21h +; +; Error returns: +; AX = error_invalid_handle +; = error_invalid_function +; = error_invalid_data + + procedure $IOCTL,NEAR + ASSUME DS:NOTHING,ES:NOTHING + MOV SI,DS ;Stash DS for calls 2,3,4 and 5 + context DS + CMP AL,3 + JA ioctl_check_block ;Block device + PUSH DX + invoke get_sf_from_jfn + POP DX ;Restore DATA + JNC ioctl_check_permissions ; have valid handle + error error_invalid_handle + +ioctl_check_permissions: + CMP AL,2 + JAE ioctl_control_string + CMP AL,0 + MOV AL,BYTE PTR ES:[DI+sf_fcb+fcb_devid] + JZ ioctl_read ; read the byte + OR DH,DH + JZ ioctl_check_device ; can I set with this data? + error error_invalid_data ; no DH <> 0 + +ioctl_check_device: + TEST AL,devid_ISDEV ; can I set this handle? + JZ ioctl_bad_fun ; no, it is a file. + MOV BYTE PTR ES:[DI+sf_fcb+fcb_devid],DL + transfer SYS_RET_OK + +ioctl_read: + XOR AH,AH + TEST AL,devid_ISDEV ; Should I set high byte + JZ ioctl_no_high ; no + LES DI,DWORD PTR ES:[DI+sf_fcb+fcb_FIRCLUS] ;Get device pointer + MOV AH,BYTE PTR ES:[DI.SDEVATT+1] ;Get high byte +ioctl_no_high: + invoke get_user_stack + MOV DX,AX + MOV [SI.user_DX],DX + transfer SYS_RET_OK + +ioctl_control_string: + TEST BYTE PTR ES:[DI+sf_fcb+fcb_devid],devid_ISDEV ; can I? + JZ ioctl_bad_fun ; no, it is a file. + LES DI,DWORD PTR ES:[DI+sf_fcb+fcb_FIRCLUS] ;Get device pointer + XOR BL,BL ; Unit number of char dev = 0 + JMP SHORT ioctl_do_string + +ioctl_check_block: + DEC AL + DEC AL ;4=2,5=3,6=4,7=5 + CMP AL,3 + JBE ioctl_get_dev + + MOV AH,1 + SUB AL,4 ;6=0,7=1 + JZ ioctl_get_status + MOV AH,3 + DEC AL + JNZ ioctl_bad_fun + +ioctl_get_status: + PUSH AX + invoke GET_IO_FCB + POP AX + JC ioctl_acc_err + invoke IOFUNC + MOV AH,AL + MOV AL,0FFH + JNZ ioctl_status_ret + INC AL +ioctl_status_ret: + transfer SYS_RET_OK + +ioctl_bad_fun: + error error_invalid_function + +ioctl_acc_err: + error error_access_denied + +ioctl_get_dev: + PUSH CX + PUSH DX + PUSH AX + PUSH SI ;DS in disguise + MOV AL,BL ;Drive + invoke GETTHISDRV + JC ioctl_bad_drv + invoke FATREAD ;"get" the drive + MOV BL,ES:[BP.dpb_UNIT] ; Unit number + LES DI,ES:[BP.dpb_driver_addr] + CLC ;Make sure error jump not taken +ioctl_bad_drv: + POP SI + POP AX + POP DX + POP CX + JC ioctl_acc_err +ioctl_do_string: + TEST ES:[DI.SDEVATT],DEVIOCTL ;See if device accepts control + JZ ioctl_bad_fun ;NO + DEC AL + DEC AL + JZ ioctl_control_read + MOV [IOCALL.REQFUNC],DEVWRIOCTL + JMP SHORT ioctl_control_call +ioctl_control_read: + MOV [IOCALL.REQFUNC],DEVRDIOCTL +ioctl_control_call: + MOV AL,DRDWRHL + MOV AH,BL ;Unit number + MOV WORD PTR [IOCALL.REQLEN],AX + XOR AX,AX + MOV [IOCALL.REQSTAT],AX + MOV [IOMED],AL + MOV [IOSCNT],CX + MOV WORD PTR [IOXAD],DX + MOV WORD PTR [IOXAD+2],SI + PUSH ES + POP DS +ASSUME DS:NOTHING + MOV SI,DI ;DS:SI -> driver + PUSH SS + POP ES + MOV BX,OFFSET DOSGROUP:IOCALL ;ES:BX -> Call header + invoke DEVIOCALL2 + MOV AX,[IOSCNT] ;Get actual bytes transferred + transfer SYS_RET_OK + +$IOCTL ENDP + +BREAK +; +; Assembler usage: +; MOV AH, FileTimes +; MOV AL, func +; MOV BX, handle +; ; if AL = 1 then then next two are mandatory +; MOV CX, time +; MOV DX, date +; INT 21h +; ; if AL = 0 then CX/DX has the last write time/date +; ; for the handle. +; +; Error returns: +; AX = error_invalid_function +; = error_invalid_handle +; +procedure $File_times,near + CMP AL,2 + JB filetimes_ok + error error_invalid_function + +filetimes_ok: + PUSH SS + POP DS + CALL Get_sf_from_jfn + JNC filetimes_disp + error error_invalid_handle + +filetimes_disp: + OR AL,AL + JNZ filetimes_set + MOV CX,ES:[DI.sf_fcb.fcb_FTIME] + MOV DX,ES:[DI.sf_fcb.fcb_FDATE] + invoke Get_user_stack + MOV [SI.user_CX],CX + MOV [SI.user_DX],DX + transfer SYS_RET_OK + +filetimes_set: + MOV ES:[DI.sf_fcb.fcb_FTIME],CX + MOV ES:[DI.sf_fcb.fcb_FDATE],DX + AND ES:[DI.sf_fcb.fcb_DEVID],NOT devid_file_clean + transfer SYS_RET_OK +$file_times ENDP + +do_ext + +CODE ENDS + END + \ No newline at end of file -- cgit v1.2.3