%OUT MS96TPI.INC...
;==============================================================================
;REVISION HISTORY:
;AN000 - New for DOS Version 4.00 - J.K.
;AC000 - Changed for DOS Version 4.00 - J.K.
;AN00x - PTM number for DOS Version 4.00 - J.K.
;==============================================================================
;AN001 - p2781 Changeline error behavior incompatibile with DOS 3.3 1/06/88 J.K.
;==============================================================================
;
;		DISK OPEN/CLOSE ROUTINES ARR 2.41
;

DSK$OPEN:				;ARR 2.41
	PUBLIC	DSK$OPEN

	MESSAGE FTESTDISK,<"DISK OPEN ">
	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			;ARR 2.41

DSK$CLOSE:				;ARR 2.41
	PUBLIC	DSK$CLOSE

	MESSAGE FTESTDISK,<"DISK CLOSE ">
	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  ARR 2.41
	DEC	WORD PTR DS:[DI].OPCNT
EXITJX:
	JMP	EXIT

; 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 ">
	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.
;
	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
;SB33001****************************************************************
	mov	DL, DS:[DI.drivenum] ;SB   ; set logical drive number	  ;3.30*
	mov	AH, 16h 	 ;SB	   ; get changeline status	  ;3.30*
	int	13h		 ;SB	   ; call rom diskette routine	  ;3.30*
;SB33001****************************************************************
	POP	DX
	POP	AX
	JC	MEDIADOVOLID
	MOV	SI,1			; 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
;
; 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
;
; 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.
;J.K. 9/16/86 For DOS 3.3, this will work only for the drive that has
;J.K. 9/16/86 changeline.
	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
;J.K. 9/16/86
;	call	HasChange		;change line supported?
;	jz	CheckRet		;No. Just return
	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
	POP	SI			; POP OFF RETURN ADDRESS
	RET

;
; 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:
;J.K. Now with the extended BOOT record, the logic should be enhanced.
;If it is the extended BOOT record, then we check the volume serial
;number instead of volume id. If it is different, then set SI to -1.
;If it is same, then SI= 1 (No change).
;If it is not the extended BOOT record, then just follows the old
;logic. DOS 4.00 will check if the # of FAT in the boot record BPB
;is not 0.  If it is 0 then it must be Non_FAT based system and
;should have already covered by extended boot structure checking.
;So, we will return "I don't know" by setting SI to 0.
;This routine assume the newest valid boot record is in CS:[DISKSECTOR].
;(This will be gauranteed by a successful GETBP call right before this
;routine.)
	MESSAGE FTEST96,<"CHECK VID",CR,LF>
;SB34MS96TPI001*********************************************************
;SB	check the EXT_Boot_Sig variable for the Extended boot signature
;SB	if it is set then go to do the extended ID check otherwise continue
;SB	with code below
;SB		2 LOCS

	cmp	cs:[Ext_Boot_Sig],Ext_Boot_Signature
	jz	Do_Ext_Check_Id
;SB34MS96TPI001*********************************************************
	call	HasChange			;AN000;
	jz	CheckRet			;AN000;

	xor	si,si				;AN000; assume I don't know.
	cmp	byte ptr cs:[SECPERCLUSINSECTOR]+3,0 ;AN000; Don't read vol id from
	je	CHECKFATRET			;AN000; the directory if not FAT system
	CALL	READ_VOLUME_ID
	JC	CHECKFATRET
	CALL	CHECK_VOLUME_ID
	OR	SI,SI
	JNZ	CHANGED_DRV
	MESSAGE FTEST96,<"VID NOT CHANGED",CR,LF>

VID_NO_Changed:
	CALL	RESETCHANGED
	clc					;AN000;
CHECKFATRET:
	RET
CHANGED_DRV:
	MOV	CS:[TIM_DRV],-1 		; ENSURE THAT WE ASK ROM FOR MEDIA
	RET					; CHECK NEXT TIME ROUND
   ;
   ; extended ID check
   ;
Do_Ext_Check_ID:				;AN000;
	push	ax				;AN000;
;SB34MS96TPI002**************************************************************
;SB	The code to check extended ID is basically a check to see if the
;Sb	volume serial number is still the same.  The volume serial number
;SB	previously read is in cs:[Boot_Serial_H] and cs:[Boot_Serial_L]
;SB	high and low words respectively.  DS:DI points to the BDS of the
;SB	drive under consideration.  The BDS has fields containing the 
;SB	high and low words of the volume serial number of the media in the
;SB	drive.  Compare these fields to the fields mentioned above.  If these
;SB	fields do not match the media has changed and so we should jump
;SB	to the code starting at Ext_Changed else return "I don't know" status
;SB	in the register used for the changeline status and continue executing
;SB     the code given below.  For temporary storage use the register which
;SB	has been saved and restored around this block.
;SB		7 LOCS
;SB	BDS fields in inc\msbds.inc

	mov	ax,cs:[Boot_Serial_L]
	cmp	ax,word ptr ds:[di+VOL_SERIAL]
	jnz	Ext_Changed
	mov	ax,cs:[Boot_Serial_H]
	cmp	ax,word ptr ds:[di+VOL_SERIAL+2]
	jnz	Ext_Changed
	xor	si,si			; don't know

;SB34MS96TPI002**************************************************************
	pop	ax				;AN000;
;	 jmp	 CheckFatRet			 ;AN000;
	jmp	VID_NO_Changed			;AN001;Reset the flag
Ext_Changed:					;AN000; Serial number is different!
	pop	ax				;AN000;
	mov	si, -1				;AN000; disk changed!
	clc					;AN000; clear carry. Only SI is meaningful here.
	jmp	Changed_Drv			;AN000;

;
; AT I/O TIME, WE DETECTED THE ERROR.  NOW WE NEED TO DETERMINE WHETHER THE
; MEDIA WAS TRULY CHANGED OR NOT.  WE RETURN NORMALLY IF MEDIA CHANGE UNKNOWN.
; AND WE POP OFF THE CALL AND JMP TO HARDERR IF WE SEE AN ERROR.
;
	PUBLIC CHECKIO
CHECKIO:
	CMP	AH,06
	JNZ	CHECKFATRET
	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:
;	POP	SI			; POP OFF RETURN
	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
	STC
	RET

;
; MUNGE THE TIME OF LAST SUCCESSFUL ACCESS FOR TWEEKED DRIVES
;
; DON'T NEED ANY MORE
; TWEEKCHECK:
;	  PUSH	  AX
;	  MOV	  AX,WORD PTR DS:[DI].FLAGS
;	  TEST	  AL,FCHANGED_BY_FORMAT
;	  JZ	  TWEEKDONE
;	  MOV	  CS:[TIM_DRV],-1
; TWEEKDONE:
;	  POP	  AX
;	  RET

;
; DRIVE IS THE LOGICAL DRIVE TO USE
;
; FORMAT_MEDIA_CHECK:			  ;ARR 2.42
;	  PUSH	  AX
;	  MOV	  AX,WORD PTR DS:[DI].FLAGS
;	  TEST	  AL,FCHANGED_BY_FORMAT
;	  JZ	  RETF1 		  ; MEDIA NOT CHANGED VIA FORMAT
;	  AND	  AL,NOT FCHANGED_BY_FORMAT
;	  MOV	  WORD PTR [DI].FLAGS,AX  ; RESET CHANGED_BY_FORMAT BIT
;	  MOV	  SI,-1 		  ; MEDIA CHANGED VIA FORMAT
; RETF1:
;	  POP	  AX
;	  RET

;
; 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:				; ARR 2.42
	PUBLIC MEDIA_SET_VID

	CALL	INIT_VID_LOOP		; SETS ES:DI -> VID
	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
;
; 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			; RETURN TO TAIL OF GETBP

DOFLOPPY:
	RET

	PATHSTART 001,TPI96

;
; CERTAIN BOGUS 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

	PUBLIC INT13
INT13	PROC	FAR
	POP	WORD PTR OLDINT
	POP	WORD PTR OLDINT+2
	POP	DMY
	MESSAGE FTEST13,<"*">
	PUSHF
	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 ">
	MNUM	FTEST13,AX
	MESSAGE FTEST13,<CR,LF>
	PUSHF				; SAVE STATE
	CMP	AH,06H			; DID I SEE A CHANGE EVENT?
	JZ	GOTERR			; YES
B:	POPF				; NO, SOME OTHER ERROR, IGNORE IT
	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

	MESSAGE FTEST96,<"SET CHANGED",CR,LF>
	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 ">
	MNUM	FTEST13
	MESSAGE FTEST13,<CR,LF>
	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

	public	ResetChanged
RESETCHANGED:
	MESSAGE FTEST13,<"RESETCHANGED ">
	MNUM	FTEST13
	MESSAGE FTEST13,<CR,LF>
	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
HASCHANGE:
	MESSAGE FTEST13,<"HASCHANGE ">
	MNUM	FTEST13
	MESSAGE FTEST13,<CR,LF>
	TEST	WORD PTR [DI].FLAGS,FCHANGELINE
	RET

	ASSUME	DS:CODE

	INCLUDE MSVOLID.INC

	PUBLIC END96TPI
END96TPI LABEL BYTE
