mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-12-01 18:15:47 +00:00
439 lines
12 KiB
NASM
439 lines
12 KiB
NASM
|
;
|
|||
|
; Device call routines 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 DEV - Device call routines
|
|||
|
NAME Dev
|
|||
|
|
|||
|
i_need IOXAD,DWORD
|
|||
|
i_need IOSCNT,WORD
|
|||
|
i_need DEVIOBUF,4
|
|||
|
i_need IOCALL,BYTE
|
|||
|
i_need IOMED,BYTE
|
|||
|
i_need IORCHR,BYTE
|
|||
|
i_need CALLSCNT,WORD
|
|||
|
i_need DMAAdd,DWORD
|
|||
|
i_need NullDevPt,DWORD
|
|||
|
i_need CallDevAd,DWORD
|
|||
|
i_need Attrib,BYTE
|
|||
|
i_need NULDEV,DWORD
|
|||
|
i_need Name1,BYTE
|
|||
|
i_need DevPt,DWORD
|
|||
|
i_need DPBHead,DWORD
|
|||
|
i_need NumIO,BYTE
|
|||
|
i_need ThisDPB,DWORD
|
|||
|
i_need DevCall,DWORD
|
|||
|
i_need VerFlg,BYTE
|
|||
|
|
|||
|
SUBTTL IOFUNC -- DO FUNCTION 1-12 I/O
|
|||
|
PAGE
|
|||
|
IOFUNC_RETRY:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
invoke restore_world
|
|||
|
|
|||
|
procedure IOFUNC,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DS:SI Points to FCB
|
|||
|
; AH is function code
|
|||
|
; = 0 Input
|
|||
|
; = 1 Input Status
|
|||
|
; = 2 Output
|
|||
|
; = 3 Output Status
|
|||
|
; = 4 Flush
|
|||
|
; AL = character if output
|
|||
|
; Function:
|
|||
|
; Perform indicated I/O to device or file
|
|||
|
; Outputs:
|
|||
|
; AL is character if input
|
|||
|
; If a status call
|
|||
|
; zero set if not ready
|
|||
|
; zero reset if ready (character in AL for input status)
|
|||
|
; For regular files:
|
|||
|
; Input Status
|
|||
|
; Gets character but restores fcb_RR field
|
|||
|
; Zero set on EOF
|
|||
|
; Input
|
|||
|
; Gets character advances fcb_RR field
|
|||
|
; Returns ^Z on EOF
|
|||
|
; Output Status
|
|||
|
; Always ready
|
|||
|
; AX altered, all other registers preserved
|
|||
|
|
|||
|
MOV WORD PTR [IOXAD+2],SS
|
|||
|
MOV WORD PTR [IOXAD],OFFSET DOSGROUP:DEVIOBUF
|
|||
|
MOV WORD PTR [IOSCNT],1
|
|||
|
MOV WORD PTR [DEVIOBUF],AX
|
|||
|
|
|||
|
IOFUNC2:
|
|||
|
TEST [SI.fcb_DEVID],080H
|
|||
|
JNZ IOTODEV
|
|||
|
JMP IOTOFILE
|
|||
|
|
|||
|
IOTODEV:
|
|||
|
invoke save_world
|
|||
|
PUSH DS
|
|||
|
PUSH SS
|
|||
|
POP ES
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
XOR BX,BX
|
|||
|
MOV [IOCALL.REQSTAT],BX
|
|||
|
MOV BYTE PTR [IOMED],BL
|
|||
|
|
|||
|
MOV BX,OFFSET DOSGROUP:IOCALL
|
|||
|
|
|||
|
MOV CX,(DEVRD SHL 8) OR DRDWRHL
|
|||
|
OR AH,AH
|
|||
|
JZ DCALLR
|
|||
|
MOV CX,(DEVRDND SHL 8) OR DRDNDHL
|
|||
|
DEC AH
|
|||
|
JZ DCALLR
|
|||
|
MOV CX,(DEVWRT SHL 8) OR DRDWRHL
|
|||
|
DEC AH
|
|||
|
JZ DCALLO
|
|||
|
MOV CX,(DEVOST SHL 8) OR DSTATHL
|
|||
|
DEC AH
|
|||
|
JZ DCALLO
|
|||
|
DFLUSH:
|
|||
|
MOV CX,(DEVIFL SHL 8) OR DFLSHL
|
|||
|
DCALLR:
|
|||
|
MOV AH,86H
|
|||
|
DCALL:
|
|||
|
MOV [IOCALL.REQLEN],CL
|
|||
|
MOV [IOCALL.REQFUNC],CH
|
|||
|
MOV CL,AH
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
CALL DEVIOCALL
|
|||
|
MOV DI,[IOCALL.REQSTAT]
|
|||
|
TEST DI,STERR
|
|||
|
JZ OKDEVIO
|
|||
|
MOV AH,CL
|
|||
|
invoke CHARHARD
|
|||
|
CMP AL,1
|
|||
|
JZ IOFUNC_RETRY
|
|||
|
;Know user must have wanted ignore. Make sure device shows ready so
|
|||
|
;that DOS doesn't get caught in a status loop when user simply wants
|
|||
|
;to ignore the error.
|
|||
|
AND BYTE PTR [IOCALL.REQSTAT+1], NOT (STBUI SHR 8)
|
|||
|
OKDEVIO:
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
CMP CH,DEVRDND
|
|||
|
JNZ DNODRD
|
|||
|
MOV AL,BYTE PTR [IORCHR]
|
|||
|
MOV [DEVIOBUF],AL
|
|||
|
|
|||
|
DNODRD: MOV AH,BYTE PTR [IOCALL.REQSTAT+1]
|
|||
|
NOT AH ; Zero = busy, not zero = ready
|
|||
|
AND AH,STBUI SHR 8
|
|||
|
|
|||
|
invoke restore_world
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV AX,WORD PTR [DEVIOBUF]
|
|||
|
return
|
|||
|
|
|||
|
DCALLO:
|
|||
|
MOV AH,87H
|
|||
|
JMP SHORT DCALL
|
|||
|
|
|||
|
IOTOFILE:
|
|||
|
ASSUME DS:NOTHING
|
|||
|
OR AH,AH
|
|||
|
JZ IOIN
|
|||
|
DEC AH
|
|||
|
JZ IOIST
|
|||
|
DEC AH
|
|||
|
JZ IOUT
|
|||
|
return ; NON ZERO FLAG FOR OUTPUT STATUS
|
|||
|
|
|||
|
IOIST:
|
|||
|
PUSH WORD PTR [SI.fcb_RR] ; Save position
|
|||
|
PUSH WORD PTR [SI.fcb_RR+2]
|
|||
|
CALL IOIN
|
|||
|
POP WORD PTR [SI.fcb_RR+2] ; Restore position
|
|||
|
POP WORD PTR [SI.fcb_RR]
|
|||
|
return
|
|||
|
|
|||
|
IOUT:
|
|||
|
CALL SETXADDR
|
|||
|
invoke STORE
|
|||
|
invoke FINNOSAV
|
|||
|
CALL RESTXADDR ; If you change this into a jmp don't come
|
|||
|
return ; crying to me when things don't work ARR
|
|||
|
|
|||
|
IOIN:
|
|||
|
CALL SETXADDR
|
|||
|
invoke LOAD
|
|||
|
PUSH CX
|
|||
|
invoke FINNOSAV
|
|||
|
POP CX
|
|||
|
OR CX,CX ; Check EOF
|
|||
|
CALL RESTXADDR
|
|||
|
MOV AL,[DEVIOBUF] ; Get byte from trans addr
|
|||
|
retnz
|
|||
|
MOV AL,1AH ; ^Z if EOF
|
|||
|
return
|
|||
|
|
|||
|
SETXADDR:
|
|||
|
POP WORD PTR [CALLSCNT] ; Return address
|
|||
|
invoke save_world
|
|||
|
PUSH WORD PTR [DMAADD] ; Save Disk trans addr
|
|||
|
PUSH WORD PTR [DMAADD+2]
|
|||
|
PUSH DS
|
|||
|
PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
MOV CX,WORD PTR [IOXAD+2]
|
|||
|
MOV WORD PTR [DMAADD+2],CX
|
|||
|
MOV CX,WORD PTR [IOXAD]
|
|||
|
MOV WORD PTR [DMAADD],CX ; Set byte trans addr
|
|||
|
MOV CX,[IOSCNT] ; ioscnt specifies length of buffer
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV [SI.fcb_RECSIZ],1 ; One byte per record
|
|||
|
MOV DX,SI ; FCB to DS:DX
|
|||
|
invoke GETRRPOS
|
|||
|
JMP SHORT RESTRET ; RETURN ADDRESS
|
|||
|
|
|||
|
RESTXADDR:
|
|||
|
POP WORD PTR [CALLSCNT] ; Return address
|
|||
|
POP WORD PTR [DMAADD+2] ; Restore Disk trans addr
|
|||
|
POP WORD PTR [DMAADD]
|
|||
|
invoke restore_world
|
|||
|
RESTRET:JMP WORD PTR [CALLSCNT] ; Return address
|
|||
|
IOFUNC ENDP
|
|||
|
|
|||
|
SUBTTL DEVIOCALL, DEVIOCALL2 - CALL A DEVICE
|
|||
|
PAGE
|
|||
|
procedure DEVIOCALL,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DS:SI Points to device FCB
|
|||
|
; ES:BX Points to request data
|
|||
|
; Function:
|
|||
|
; Call the device
|
|||
|
; Outputs:
|
|||
|
; None
|
|||
|
; DS:SI,AX destroyed, others preserved
|
|||
|
|
|||
|
LDS SI,DWORD PTR [SI.fcb_FIRCLUS]
|
|||
|
|
|||
|
entry DEVIOCALL2
|
|||
|
; As above only DS:SI points to device header on entry, and DS:SI is preserved
|
|||
|
MOV AX,[SI.SDEVSTRAT]
|
|||
|
MOV WORD PTR [CALLDEVAD],AX
|
|||
|
MOV WORD PTR [CALLDEVAD+2],DS
|
|||
|
CALL DWORD PTR [CALLDEVAD]
|
|||
|
MOV AX,[SI.SDEVINT]
|
|||
|
MOV WORD PTR [CALLDEVAD],AX
|
|||
|
CALL DWORD PTR [CALLDEVAD]
|
|||
|
return
|
|||
|
DEVIOCALL ENDP
|
|||
|
|
|||
|
SUBTTL DEVNAME - LOOK FOR NAME OF DEVICE
|
|||
|
PAGE
|
|||
|
procedure DEVNAME,NEAR
|
|||
|
ASSUME DS:DOSGROUP,ES:DOSGROUP
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DS,ES:DOSGROUP
|
|||
|
; Filename in NAME1
|
|||
|
; Function:
|
|||
|
; Determine if file is in list of I/O drivers
|
|||
|
; Outputs:
|
|||
|
; Carry set if name not found
|
|||
|
; ELSE
|
|||
|
; Zero flag set
|
|||
|
; BH = Bit 7,6 = 1, bit 5 = 0 (cooked mode)
|
|||
|
; bits 0-4 set from low byte of attribute word
|
|||
|
; DEVPT = DWORD pointer to Device header of device
|
|||
|
; Registers BX destroyed
|
|||
|
|
|||
|
PUSH SI
|
|||
|
PUSH DI
|
|||
|
PUSH CX
|
|||
|
|
|||
|
IF KANJI
|
|||
|
PUSH WORD PTR [NAME1]
|
|||
|
CMP [NAME1],5
|
|||
|
JNZ NOKTR
|
|||
|
MOV [NAME1],0E5H
|
|||
|
NOKTR:
|
|||
|
ENDIF
|
|||
|
|
|||
|
TEST BYTE PTR [ATTRIB],attr_volume_id ; If looking for VOL id don't find devs
|
|||
|
JNZ RET31
|
|||
|
MOV SI,OFFSET DOSGROUP:NULDEV
|
|||
|
LOOKIO:
|
|||
|
ASSUME DS:NOTHING
|
|||
|
TEST [SI.SDEVATT],DEVTYP
|
|||
|
JZ SKIPDEV ; Skip block devices
|
|||
|
PUSH SI
|
|||
|
ADD SI,SDEVNAME
|
|||
|
MOV DI,OFFSET DOSGROUP:NAME1
|
|||
|
MOV CX,4 ; All devices are 8 letters
|
|||
|
REPE CMPSW ; Check for name in list
|
|||
|
POP SI
|
|||
|
JZ IOCHK ; Found it?
|
|||
|
SKIPDEV:
|
|||
|
LDS SI,DWORD PTR [SI] ; Get address of next device
|
|||
|
CMP SI,-1 ; At end of list?
|
|||
|
JNZ LOOKIO
|
|||
|
RET31: STC ; Not found
|
|||
|
RETNV: PUSH SS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DOSGROUP
|
|||
|
|
|||
|
IF KANJI
|
|||
|
POP WORD PTR [NAME1]
|
|||
|
ENDIF
|
|||
|
|
|||
|
POP CX
|
|||
|
POP DI
|
|||
|
POP SI
|
|||
|
RET
|
|||
|
|
|||
|
IOCHK:
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV WORD PTR [DEVPT+2],DS ; Save pointer to device
|
|||
|
MOV BH,BYTE PTR [SI.SDEVATT]
|
|||
|
OR BH,0C0H
|
|||
|
AND BH,NOT 020H ;Clears Carry
|
|||
|
MOV WORD PTR [DEVPT],SI
|
|||
|
JMP RETNV
|
|||
|
DevName ENDP
|
|||
|
|
|||
|
procedure GetBP,NEAR
|
|||
|
ASSUME DS:DOSGROUP,ES:NOTHING
|
|||
|
|
|||
|
; 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
|
|||
|
; No other registers altered
|
|||
|
|
|||
|
LES BP,[DPBHEAD] ; Just in case drive isn't valid
|
|||
|
AND AL,3FH ; Mask out dirty and device bits
|
|||
|
CMP AL,BYTE PTR [NUMIO]
|
|||
|
CMC
|
|||
|
JC GOTDPB ; Get drive A
|
|||
|
FNDDPB:
|
|||
|
CMP AL,ES:[BP.dpb_drive]
|
|||
|
JZ GOTDPB ; Carry is clear if jump executed
|
|||
|
LES BP,ES:[BP.dpb_next_dpb]
|
|||
|
JMP SHORT FNDDPB
|
|||
|
GOTDPB:
|
|||
|
MOV WORD PTR [THISDPB],BP
|
|||
|
MOV WORD PTR [THISDPB+2],ES
|
|||
|
RET
|
|||
|
GetBP ENDP
|
|||
|
|
|||
|
SUBTTL SETREAD, SETWRITE -- SET UP HEADER BLOCK
|
|||
|
PAGE
|
|||
|
procedure SETREAD,NEAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DS:BX = Transfer Address
|
|||
|
; CX = Record Count
|
|||
|
; DX = Starting Record
|
|||
|
; AH = Media Byte
|
|||
|
; AL = Unit Code
|
|||
|
; Function:
|
|||
|
; Set up the device call header at DEVCALL
|
|||
|
; Output:
|
|||
|
; ES:BX Points to DEVCALL
|
|||
|
; No other registers effected
|
|||
|
|
|||
|
PUSH DI
|
|||
|
PUSH CX
|
|||
|
PUSH AX
|
|||
|
MOV CL,DEVRD
|
|||
|
SETCALLHEAD:
|
|||
|
MOV AL,DRDWRHL
|
|||
|
PUSH SS
|
|||
|
POP ES
|
|||
|
MOV DI,OFFSET DOSGROUP:DEVCALL
|
|||
|
STOSB ; length
|
|||
|
POP AX
|
|||
|
STOSB ; Unit
|
|||
|
PUSH AX
|
|||
|
MOV AL,CL
|
|||
|
STOSB ; Command code
|
|||
|
XOR AX,AX
|
|||
|
STOSW ; Status
|
|||
|
ADD DI,8 ; Skip link fields
|
|||
|
POP AX
|
|||
|
XCHG AH,AL
|
|||
|
STOSB ; Media byte
|
|||
|
XCHG AL,AH
|
|||
|
PUSH AX
|
|||
|
MOV AX,BX
|
|||
|
STOSW
|
|||
|
MOV AX,DS
|
|||
|
STOSW ; Transfer addr
|
|||
|
POP CX ; Real AX
|
|||
|
POP AX ; Real CX
|
|||
|
STOSW ; Count
|
|||
|
XCHG AX,DX ; AX=Real DX, DX=real CX, CX=real AX
|
|||
|
STOSW ; Start
|
|||
|
XCHG AX,CX
|
|||
|
XCHG DX,CX
|
|||
|
POP DI
|
|||
|
MOV BX,OFFSET DOSGROUP:DEVCALL
|
|||
|
RET
|
|||
|
|
|||
|
entry SETWRITE
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
|
|||
|
; Inputs:
|
|||
|
; DS:BX = Transfer Address
|
|||
|
; CX = Record Count
|
|||
|
; DX = Starting Record
|
|||
|
; AH = Media Byte
|
|||
|
; AL = Unit Code
|
|||
|
; Function:
|
|||
|
; Set up the device call header at DEVCALL
|
|||
|
; Output:
|
|||
|
; ES:BX Points to DEVCALL
|
|||
|
; No other registers effected
|
|||
|
|
|||
|
PUSH DI
|
|||
|
PUSH CX
|
|||
|
PUSH AX
|
|||
|
MOV CL,DEVWRT
|
|||
|
ADD CL,[VERFLG]
|
|||
|
JMP SHORT SETCALLHEAD
|
|||
|
SETREAD ENDP
|
|||
|
|
|||
|
do_ext
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
END
|
|||
|
|