mirror of https://github.com/AR1972/DOS3.3
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
494 lines
12 KiB
494 lines
12 KiB
|
|
;------------------------------------------------------------------------
|
|
; :
|
|
; File: ms96tpi.asm :
|
|
; :
|
|
; This file contains code to support the 96 tpi drives. The code :
|
|
; is included in the bio if the machine has at least one drive with :
|
|
; changeline support. If the machine has no changeline drives then :
|
|
; the code is not kept in the bio at system initialization time. :
|
|
; :
|
|
;------------------------------------------------------------------------
|
|
|
|
|
|
;------------------------------------------------------------------------
|
|
; :
|
|
; DISK OPEN/CLOSE ROUTINES :
|
|
; :
|
|
;------------------------------------------------------------------------
|
|
|
|
DSK$OPEN:
|
|
PUBLIC DSK$OPEN
|
|
Message fTestDisk,<"Disk Open "> ; print debug messages
|
|
MNUM fTestDisk,AX
|
|
Message fTestDisk,<CR,LF>
|
|
; AL is logical drive
|
|
call SetDrive ; Get BDS for drive
|
|
inc WORD PTR ds:[di].opcnt
|
|
jmp EXIT
|
|
|
|
DSK$CLOSE:
|
|
PUBLIC DSK$CLOSE
|
|
Message fTestDisk,<"Disk Close "> ; print debug messages
|
|
MNUM fTestDisk,AX
|
|
Message fTestDisk,<CR,LF>
|
|
; AL is logical drive
|
|
call SetDrive ; Get BDS for drive
|
|
cmp WORD PTR ds:[di].opcnt,0
|
|
jz EXITJX ; Watch out for wrap
|
|
dec WORD PTR ds:[di].opcnt
|
|
EXITJX:
|
|
jmp EXIT
|
|
|
|
;
|
|
; ChkOpCnt checks the number of open files on drive.
|
|
;
|
|
; Input : DS:DI points to current BDS for drive.
|
|
;
|
|
; Return : zero set if no open files
|
|
; zero reset if open files
|
|
;
|
|
|
|
ChkOpCnt:
|
|
Message fTest96,<"Check open count "> ; print debug messages
|
|
MNUM fTest96,AX
|
|
Message fTest96,<CR,LF>
|
|
cmp WORD PTR ds:[di].opcnt,0
|
|
ret
|
|
|
|
;
|
|
; At media check time, we need to really get down and check what the change is.
|
|
; This is GUARANTEED to be expensive.
|
|
;
|
|
; On entry AL contains logical drive number
|
|
;
|
|
|
|
public mediacheck
|
|
MediaCheck:
|
|
call CheckSingle ; make sure correct disk is in place
|
|
xor SI,SI
|
|
call HasChange
|
|
jz MediaRet
|
|
call CheckROMChange
|
|
jnz MediaDoVOLID
|
|
push AX
|
|
push DX
|
|
; see if changeline has been triggered
|
|
;;Rev 3.30 Modification
|
|
mov DL, DS:[DI.drivenum] ; set logical drive number
|
|
mov AH, 16h ; get changeline status
|
|
int 13h ; call rom diskette routine
|
|
;;End of Modification
|
|
pop DX
|
|
pop AX
|
|
jc MediaDoVolid ; if changeline was triggered jmp
|
|
mov SI,1 ; else signal no change
|
|
|
|
|
|
; There are some drives with changeline that "lose" the changeline indication
|
|
; if a different drive is accessed after the current one. In order to avoid
|
|
; missing a media change, we return an "I don't know" to DOS if the changeline
|
|
; is not active AND we are accessing a different drive from the last one.
|
|
; If we are accessing the same drive, then we can safely rely on the changeline
|
|
; status.
|
|
|
|
PUBLIC LOSECHNG
|
|
LOSECHNG:
|
|
mov bl,cs:[Tim_Drv] ; get last drive accessed
|
|
cmp byte ptr [di].DriveNum,bl
|
|
jz MediaRet
|
|
; Do the 2 second twiddle. If time >= 2 seconds, do a volid check.
|
|
; Otherwise return "I don't know" (Strictly speaking, we should return a
|
|
; "Not Changed" here since the 2 second test said no change.) - RS.
|
|
|
|
SaveReg <AX,CX,DX>
|
|
call Check_Time_Of_Access
|
|
RestoreReg <DX,CX,AX>
|
|
or si,si
|
|
jz MediaDoVolid ; Check_Time says ">= 2 secs passed"
|
|
xor si,si ; return "I don't know"
|
|
Public MediaRet
|
|
MediaRet:
|
|
ret
|
|
|
|
|
|
;
|
|
; MediaDoVolid: if this is called somehow the media was changed. Look at
|
|
; VID to see. We do not look at FAT because this may be different since we
|
|
; only set MedByt when doing a READ or WRITE.
|
|
;
|
|
|
|
MediaDoVolid:
|
|
call GETBP ; build a new BPB in current BDS
|
|
jc MediaRet
|
|
call Check_VID
|
|
jnc MediaRet
|
|
call MapError ; fix up AL for return to DOS
|
|
ret
|
|
|
|
;
|
|
; Checklatchio:
|
|
;
|
|
; Simple, quick check of latched change. If no indication, then return
|
|
; otherwise do expensive check. If the expensive test fails, POP off the
|
|
; return and set AL = 15 (for invalid media change) which will be returned to
|
|
; DOS.
|
|
;
|
|
public checklatchio
|
|
CheckLatchIO:
|
|
; If returning fake BPB then assume the disk has not changed
|
|
; test word ptr ds:[di].flags, RETURN_FAKE_BPB
|
|
; jnz CheckRet
|
|
;;Rev 3.30 Modification
|
|
call HasChange ;change line supported?
|
|
jz CheckRet ;No. Just return
|
|
;;End of Modification
|
|
call ChkOpCnt
|
|
jnz CheckROM
|
|
CheckRet:
|
|
ret
|
|
;
|
|
; Check for past ROM indications. If no ROM change indicated, then return OK.
|
|
;
|
|
public checkrom
|
|
CheckROM:
|
|
call CheckROMChange
|
|
jz CheckRet ; no change
|
|
;
|
|
; We now see that a change line has been seen in the past. Let's do the
|
|
; expensive verification.
|
|
;
|
|
Message fTest96,<"CheckROMChange says yes...",CR,LF>
|
|
call GETBP ; build BPB in current BDS
|
|
jc Ret_No_Error_Map ; GETBP has already called MapError
|
|
call Check_VID
|
|
jc CheckLatchRet ; disk error trying to read in.
|
|
or SI,SI ; Is changed for sure?
|
|
jns CheckRet
|
|
call ReturnVid
|
|
CheckLatchRet:
|
|
call MapError ; fix up AL for return to DOS
|
|
Ret_No_Error_Map:
|
|
stc ; indicate an error
|
|
pop si ; pop off return address
|
|
ret
|
|
|
|
|
|
|
|
;
|
|
; CheckFatVID:
|
|
;
|
|
; Check the FAT and the VID. Return in DI -1 or 0. Return with carry set
|
|
; ONLY if there was a disk error. Return that error code in AX.
|
|
;
|
|
public checkfatvid
|
|
CheckFATVID:
|
|
Message fTest96,<"Check FAT",CR,LF>
|
|
call FAT_Check
|
|
or SI,SI
|
|
js Changed_Drv
|
|
;
|
|
; The fat was the same. How about the volume ID?
|
|
;
|
|
Check_VID:
|
|
Message fTest96,<"Check VID",CR,LF>
|
|
call Read_volume_ID
|
|
jc CheckFatRet
|
|
call Check_Volume_id
|
|
or SI,SI
|
|
jnz Changed_Drv
|
|
Message fTest96,<"VID not changed",CR,LF>
|
|
call ResetChanged
|
|
CheckFatRet:
|
|
ret
|
|
Changed_Drv:
|
|
mov cs:[Tim_Drv],-1 ; Ensure that we ask ROM for media
|
|
ret ; check next time round
|
|
|
|
|
|
|
|
|
|
;
|
|
; CheckIO: At I/O time the rom-bios returned an error. We need to
|
|
; determine if the error is due to a media change. If error code is not
|
|
; change-line error (06h) we just return. We pop off the call and jmp to
|
|
; harderr if we see an error.
|
|
;
|
|
; On entry: AH contains error code returned from rom-bios.
|
|
;
|
|
|
|
public checkio
|
|
CheckIO:
|
|
cmp AH,06 ; change line error?
|
|
jnz CheckFatRet ; no - just return
|
|
call ChkOpCnt
|
|
jz CheckFATRet ; no open files
|
|
; If returning fake BPB then ignore disk changes
|
|
; test word ptr ds:[di].flags, RETURN_FAKE_BPB
|
|
; jnz IgnoreChange
|
|
call GETBP ; build up a new BPB in current BDS
|
|
jc No_Error_Map ; GETBP has already called MapError
|
|
call CheckFATVID
|
|
jc CheckIORet ; disk error trying to read in.
|
|
or SI,SI ; Is changed for sure?
|
|
js CheckIOErr ; yes changed
|
|
IgnoreChange:
|
|
inc BP ; allow a retry
|
|
ret
|
|
CheckIOErr:
|
|
call ReturnVid
|
|
CheckIORet:
|
|
stc ; make sure carry gets passed through
|
|
jmp HardErr
|
|
|
|
No_Error_Map:
|
|
jmp HardErr2
|
|
|
|
|
|
|
|
|
|
;
|
|
; Return VID sets up the VID for a return to DOS.
|
|
;
|
|
|
|
Public ReturnVID
|
|
ReturnVID:
|
|
Message fTest96,<"Return VID",cr,lf>
|
|
push DS ; save pointer to current BDS
|
|
push di
|
|
push cx
|
|
call init_vid_loop ; Sets ES:DI -> vid
|
|
lds BX,cs:[PTRSAV]
|
|
mov [BX.EXTRA],DI
|
|
mov [BX.EXTRA+2],ES
|
|
pop cx
|
|
pop di ; restore current BDS
|
|
pop DS
|
|
;; MOV AH,6 ; INVALID MEDIA CHANGE
|
|
mov AH, 0Fh ; set error as 'invalid media change'
|
|
stc ; indicate error by setting carry flag
|
|
ret
|
|
|
|
;
|
|
; Media_Set_VID:
|
|
;
|
|
; Moves the pointer to the volid for the drive into the original request packet
|
|
; On entry, DS:BX points to the original packet.
|
|
; No attempt is made to preserve registers.
|
|
;
|
|
|
|
MEDIA_SET_VID:
|
|
PUBLIC MEDIA_SET_VID ;;Rev 3.30 Modification
|
|
call init_vid_loop ; Sets ES:DI -> vid ;;End of Modification
|
|
lds bx,cs:[PtrSav] ; get pointer to packet
|
|
mov word ptr [BX.TRANS+1],DI
|
|
mov word ptr [BX.TRANS+3],ES
|
|
ret
|
|
|
|
|
|
;
|
|
; HiDensity - examine a drive/media descriptor to set the media type. If
|
|
; the media descriptor is NOT F9 (not 96tpi or 3 1/2), we return and let the
|
|
; caller do the rest. Otherwise, we pop off the return and jump to the tail
|
|
; of GETBP. For 3.5" media, we just return.
|
|
;
|
|
; Inputs: DS:DI point to correct BDS for this drive
|
|
; AH has media byte
|
|
;
|
|
; Outputs: Carry clear
|
|
; No registers modified
|
|
; Carry set
|
|
; AL = sectors/fat
|
|
; BH = number of root directory entries
|
|
; BL = sectors per track
|
|
; CX = number of sectors
|
|
; DH = sectors per allocation unit
|
|
; DL = number of heads
|
|
;
|
|
hidensity:
|
|
PUBLIC HIDENSITY ;;Rev 3.30 Modification
|
|
;;End of Modification
|
|
; Check for correct drive
|
|
;
|
|
test word ptr ds:[di].flags,fChangeline ; is it special?
|
|
jz DoFloppy ; no, do normal floppy test
|
|
;
|
|
; We have a media byte that is pretty complex. Examine drive information
|
|
; table to see what kind it is.
|
|
;
|
|
cmp byte ptr ds:[di].FormFactor,ffSmall; Is it single-media?
|
|
jz DoFloppy ; yes, use fatid...
|
|
;
|
|
; 96 tpi drive
|
|
;
|
|
cmp AH,0F9h
|
|
jnz DoFloppy
|
|
mov al,7 ; seven sectors / fat
|
|
mov bx,224*256+0fh ; 224 root dir entries & 0f sector max
|
|
mov cx,80*15*2 ; 80 tracks, 15 sectors/track, 2 sides
|
|
mov dx,01*256+2 ; sectors/allocation unit & head max
|
|
popr:
|
|
add SP,2 ; pop off return address
|
|
jmp has1_res ; return to tail of GETBP
|
|
|
|
|
|
DoFloppy:
|
|
ret
|
|
|
|
PATHSTART 001,TPI96 ;;Rev 3.30 Modification
|
|
;;End of Modification
|
|
;
|
|
; Certain poorly designed programs avoid DOS altogether and use INT 13 directly.
|
|
; These programs even retry operations and, thus, will ignore the disk change
|
|
; logic.
|
|
;
|
|
; We hook INT 13 and note all errors.
|
|
;
|
|
assume ds:nothing,es:nothing,ss:nothing
|
|
|
|
Public REAL13
|
|
Real13 dd ?
|
|
OldInt dd ?
|
|
dmy dw ?
|
|
|
|
PATHEND 001,TPI96 ;;Rev 3.30 Modification
|
|
;;End of Modification
|
|
Public Int13
|
|
Int13 proc FAR
|
|
pop word ptr OldInt
|
|
pop word ptr OldInt+2
|
|
pop DMY
|
|
MESSAGE FTEST13,<"*"> ;;Rev 3.30 Modification
|
|
pushf ;;End of Modification
|
|
call REAL13 ; simulate another INT 13
|
|
jc Err13 ; did an error occur?
|
|
jmp OldInt ; no, return and pop off flags
|
|
Err13:
|
|
MESSAGE FTEST13,<"INT 13 ERROR "> ;;Rev 3.30 Modification
|
|
MNUM FTEST13,AX
|
|
MESSAGE FTEST13,<CR,LF>
|
|
pushf ; save state
|
|
cmp AH,06h ; is error a 'change' error?
|
|
jz GOTERR ; yes, jump down
|
|
B: popf ; no, some other error, ignore it ;;End of Modification
|
|
jmp OldInt ; return and pop off flags
|
|
|
|
|
|
GotErr: or DL,DL ; is this for the hard disk?
|
|
js B ; yes, ignore
|
|
mov word ptr cs:[FlagBits],fChanged
|
|
call Set_Changed_DL
|
|
jmp B
|
|
INT13 endp
|
|
|
|
|
|
|
|
;
|
|
; Set_Changed_DL - Sets flag bits according to bits set in [FlagBits].
|
|
; Essentially used to indicate Changeline, or Format.
|
|
;
|
|
; Inputs: DL contains physical drive number
|
|
; [FlagBits] contains bits to set in the flag field in the BDSs
|
|
; Outputs: None
|
|
; Registers modified: Flags
|
|
;
|
|
|
|
Set_Changed_DL:
|
|
PUBLIC SET_CHANGED_DL ;;Rev 3.30 Modification
|
|
Message ftest96,<"Set Changed",cr,lf> ;;End of Modification
|
|
push BX
|
|
push DX
|
|
mov BL,DL
|
|
ALL_SET:
|
|
mov dx,cs:[FlagBits] ; get bits to set in flag field
|
|
xor BH,BH
|
|
;
|
|
; In the virtual drive system we *must* flag the other drives as being changed
|
|
;
|
|
; assume first BDS is in this segment
|
|
push ax
|
|
push ds ; save current BDS
|
|
push di
|
|
lds di,dword ptr cs:[Start_BDS]
|
|
Scan_BDS:
|
|
cmp di,-1
|
|
jz SkipSet
|
|
cmp byte ptr [di].DriveNum,bl
|
|
jnz Get_Next_BDS
|
|
;
|
|
; Someone may complain, but this *always* must be done when a disk change is
|
|
; noted. There are *no* other compromising circumstances.
|
|
;
|
|
SetChanged:
|
|
or word ptr ds:[di].flags,dx ; signal change on other drive
|
|
Get_Next_BDS:
|
|
mov ax,word ptr [di].link+2 ; go to next BDS
|
|
mov di,word ptr [di].link
|
|
mov ds,ax
|
|
jmp short Scan_BDS
|
|
SkipSet:
|
|
pop di ; restore current BDS
|
|
pop ds
|
|
pop ax
|
|
pop DX
|
|
pop BX
|
|
ret
|
|
|
|
|
|
|
|
;
|
|
; CheckROMChange - see if external program has diddled ROM change line.
|
|
;
|
|
; Inputs: DS:DI points to current BDS.
|
|
; Outputs: Zero set - no change
|
|
; Zero reset - change
|
|
; Registers modified: none
|
|
|
|
CheckROMChange:
|
|
MESSAGE FTEST13,<"CHECKROM "> ;;Rev 3.30 Modification
|
|
MNUM FTEST13
|
|
MESSAGE FTEST13,<CR,LF> ;;End of Modification
|
|
test word ptr [di].flags,fChanged
|
|
ret
|
|
|
|
|
|
|
|
|
|
;
|
|
; ResetChanged - restore value of change line
|
|
;
|
|
; Inputs: DS:DI points to current BDS
|
|
; Outputs: none
|
|
; Registers modified: none
|
|
|
|
ResetChanged:
|
|
MESSAGE FTEST13,<"RESETCHANGED "> ;;Rev 3.30 Modification
|
|
MNUM FTEST13
|
|
MESSAGE FTEST13,<CR,LF> ;;End of Modification
|
|
and word ptr ds:[di].flags,NOT fChanged
|
|
ret
|
|
|
|
|
|
|
|
;
|
|
; HasChange - see if drive can supply change line
|
|
;
|
|
; Inputs: DS:DI points to current BDS
|
|
; Outputs: Zero set - no change line available
|
|
; Zero reset - change line available
|
|
; Registers modified: none
|
|
|
|
PUBLIC HASCHANGE ;;Rev 3.30 Modification
|
|
HasChange:
|
|
MESSAGE FTEST13,<"HASCHANGE ">
|
|
MNUM FTEST13
|
|
MESSAGE FTEST13,<CR,LF> ;;End of Modification
|
|
test word ptr [di].flags,fChangeline
|
|
ret
|
|
|
|
ASSUME DS:CODE
|
|
|
|
include msvolid.inc
|
|
|
|
Public End96tpi
|
|
End96tpi Label Byte
|