     1                                  ;	SCCSID = @(#)disk.asm	1.1 85/04/10
     2                                  ;	SCCSID = @(#)disk.asm	1.1 85/04/10
     3                                  ;TITLE	DISK - Disk utility routines
     4                                  ;NAME	Disk
     5                                  ; Low level Read and write routines for local SFT I/O on files and devs
     6                                  ;
     7                                  ;   SWAPCON
     8                                  ;   SWAPBACK
     9                                  ;   DOS_READ
    10                                  ;   DOS_WRITE
    11                                  ;   get_io_sft
    12                                  ;   DirRead
    13                                  ;   FIRSTCLUSTER
    14                                  ;   SET_BUF_AS_DIR
    15                                  ;   FATSecRd
    16                                  ;   DREAD
    17                                  ;   CHECK_WRITE_LOCK
    18                                  ;   CHECK_READ_LOCK
    19                                  ;
    20                                  ;   Revision history:
    21                                  ;
    22                                  ;	A000   version 4.00  Jan. 1988
    23                                  ;
    24                                  
    25                                  ;
    26                                  ; get the appropriate segment definitions
    27                                  ;
    28                                  [list -]
    28          ******************       warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <4> [list -]
    14                              <3> [list -]
     3                              <2> 
     4                              <2> addsection DOSSTART, align=16 PUBLIC class=DOSSTART
     5                              <2> ; (no prior section) ; DOSSTART		ENDS
     6                              <2> 
     7                              <2> addsection DOSSTARTJUMP, align=1 PUBLIC class=START
     8                              <2> ; (no prior section) ; DOSSTARTJUMP		ENDS
     9                              <2> 
    10                              <2> addsection CONSTANTS, align=2 PUBLIC class=CONST
    11                              <2> ; (no prior section) ; CONSTANTS	ENDS
    12                              <2> 
    13                              <2> addsection DATA, align=2 PUBLIC class=DATA
    14                              <2> ; (no prior section) ; DATA		ENDS
    15                              <2> 
    16                              <2> addsection TABLE, align=2 PUBLIC class=TABLE
    17                              <2> ; (no prior section) ; TABLE		ENDS
    18                              <2> 
    19                              <2> addsection DOSDATATABLE, align=2 PUBLIC class=DOSDATACODE
    20                              <2> ; (no prior section) ; DOSDATATABLE		ENDS
    21                              <2> 
    22                              <2> addsection DOSDATACODE, align=1 PUBLIC class=DOSDATACODE
    23                              <2> ; (no prior section) ; DOSDATACODE		ENDS
    24                              <2> 
    25                              <2> addsection DOSBIODATA, align=2 PUBLIC class=DOSBIODATA
    26                              <2> 
    27                              <2> addsection LAST, align=16 PUBLIC class=LAST
    28                              <2> ; (no prior section) ; LAST		ENDS
    29                              <2> 
    30                              <2> group DOSGROUP DOSSTART DOSSTARTJUMP CONSTANTS DATA TABLE DOSDATATABLE DOSDATACODE DOSBIODATA LAST
     8                              <1> 
     9                              <1> %include "dcodeseg.nas"
     1                              <2> 
     2                              <2> %ifndef DCODESEGNAS
     3                              <2> %assign DCODESEGNAS 1
     4                              <2> 
     5                              <2> section DOSCODETABLE align=2 PUBLIC class=DOSCODE
     6                              <2> ; (no prior section) ; DOSCODETABLE		ENDS
     7                              <2> section DOSCODECODE align=1 PUBLIC class=DOSCODE
     8                              <2> ; (no prior section) ; DOSCODECODE		ENDS
     9                              <2> section DOSBIOCODE align=2 PUBLIC class=DOSCODE
    10                              <2> section BIOCODE	align=2 PUBLIC class=DOSCODE
    11                              <2> 
    12                              <2> %ifnidni DOSENTRYGROUP, DOSCODEGROUP
    13                              <2>  group DOSCODEGROUP DOSCODETABLE DOSCODECODE DOSBIOCODE BIOCODE
    14                              <2> %endif
    15                              <2> 
    16                              <2> %endif
    10                              <1> 
    11                              <1> section LAST
    12                              <1> ; (no prior section) ; LAST		ENDS
    30                                  %include "fastseek.mac"				;AN000;
     1                              <1> ;
     2                              <1> ;Equates for FASTSEEK.
     3                              <1> ;
     4                              <1> ;FASTSEEK flags
     5                              <1> ;
     6                              <1> FS_begin      equ    00000001B
     7                              <1> FS_end	      equ    11111110B
     8                              <1> FS_insert     equ    00000010B
     9                              <1> FS_no_insert  equ    11111101B
    10                              <1> 
    11                              <1> ;FASTSEEK EXTENT CACHING Subfunctions
    12                              <1> FSEC_open	equ	11
    13                              <1> FSEC_close	equ	12
    14                              <1> FSEC_delete	equ	13
    15                              <1> FSEC_lookup	equ	14
    16                              <1> FSEC_insert	equ	15
    17                              <1> FSEC_truncate	equ	16
    18                              <1> ;
    19                              <1> ;Equates used in DOS.
    20                              <1> 
    21                              <1> 
    22                              <1> ;
    31                                  %include "fastxxxx.mac"				;AN000;
     1                              <1> ; Fastxxx equates
     2                              <1> FastOpen_ID	   equ	   1
     3                              <1> FastSeek_ID	   equ	   2
     4                              <1> Fast_yes	   equ	   10000000B	 ; fastxxx flag
     5                              <1> 
     6                              <1> ;Structure definitions
     7                              <1> ;
     8                              <1> Fasttable_Entry  struc			 ; Fastxxx  Entry pointer in DOS
     9 00000000 ????                <1> Fast_Entry_Num	    dw	    ?		 ; number of entries
    10 00000002 ????????            <1> FastOpen_Seek	    dd	    ?		 ; fastopen & fastseek entry address
    11                              <1> Fasttable_Entry  ends
    12                              <1> ;
    32                                  
    33                                  [list +]
    34                                  section DOSCODECODE
    35                                  [list -]
    35          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    35          ******************       warning: out: BPB.INC... [-w+user]
    35          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    35          ******************       warning: out: DEVSYM.INC... [-w+user]
    35          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    43                                  
    44                                  %iassign Installed TRUE
    45                                  
    46                                  	I_need	DirStart,WORD
    47                                  	I_Need	CONSft,DWORD		; SFT for swapped console In/Out
    48                                  	i_need	CONSWAP,BYTE
    49                                  	i_need	IDLEINT,BYTE
    50                                  	i_need	THISSFT,DWORD
    51                                  	i_need	DMAADD,DWORD
    52                                  	i_need	DEVCALL,BYTE
    53                                  	i_need	CALLSCNT,WORD
    54                                  	i_need	CALLXAD,DWORD
    55                                  	i_need	CONTPOS,WORD
    56                                  	i_need	NEXTADD,WORD
    57                                  	i_need	CONBUF,BYTE
    58                                  	i_need	ClusFac,BYTE
    59                                  	i_need	Cluster_Factor_EDR,WORD
    60                                  	i_need	SecClusPos,BYTE
    61                                  	i_need	DirSec,DWORD		     ;AN000;
    62                                  	i_need	ClusNum,WORD
    63                                  	i_need	NxtClusNum,WORD
    64                                  	i_need	ReadOp,BYTE
    65                                  	i_need	CURBUF,DWORD
    66                                  	i_need	ALLOWED,BYTE
    67                                  	i_need	EXTERR_LOCUS,BYTE
    68                                  	i_need	FastSeekflg,BYTE	     ;AN000;
    69                                  	i_need	HIGH_SECTOR,WORD	     ;AN000;
    70                                  	I_need	JShare,DWORD		     ;AN000;
    71                                  	i_need	DOS34_FLAG,WORD 	     ;AN000;
    72                                  
    73                                  %ifndef BUF2
    74                                  %IF	BUFFERFLAG
    75                                  	i_need	BUF_EMS_MODE,BYTE
    76                                  	i_need  BUF_EMS_LAST_PAGE,BYTE
    77                                  	I_need	BUF_EMS_FIRST_PAGE,DWORD
    78                                  	I_need	BUF_EMS_SAFE_FLAG,BYTE
    79                                  	I_need	BUF_EMS_NPA640,WORD
    80                                  	I_need	BUF_EMS_PAGE_FRAME,WORD
    81                                  	I_need	BUF_EMS_PFRAME,WORD
    82                                  	I_need	LASTBUFFER,DWORD
    83                                  
    84                                  	extrn	save_user_map:near
    85                                  	extrn	restore_user_map:near
    86                                  	extrn	Setup_EMS_Buffers:near
    87                                  %ENDIF
    88                                  %endif
    89                                  
    90                                   assume nocheck, ss:DOSGROUP
    91                                  
    92                                  Break	<SwapCon, Swap Back - Old-style I/O to files>
    93                                  ; * * * * Drivers for file input from devices * * * *
    94                                  
    95                                  ;   Indicate that ther is no more I/O occurring through another SFT outside of
    96                                  ;   handles 0 and 1
    97                                  ;
    98                                  ;   Inputs:	DS is DOSGroup
    99                                  ;   Outputs:	CONSWAP is set to false.
   100                                  ;   Registers modified: none
   101                                  
   102                                  	procedure   SWAPBACK,NEAR
   102          ******************       warning: proc SWAPBACK... [-w+user]
   103                                  	DOSAssume   CS,<DS>,"SwapBack"
   104                                  	ASSUME	ES:NOTHING
   105 00000000 C606[0000]00            	MOV	BYTE PTR [CONSWAP],0	; signal no conswaps
   106 00000005 C3                      	return
   107                                  EndProc SWAPBACK
   108                                  
   109                                  ;   Copy ThisSFT to CONSFT for use by the 1-12 primitives.
   110                                  ;
   111                                  ;   Inputs:	ThisSFT as the sft of the desired file
   112                                  ;		DS is DOSGroup
   113                                  ;   Outputs:	CONSWAP is set.  CONSFT = ThisSFT.
   114                                  ;   Registers modified: none
   115                                  	procedure   SWAPCON,NEAR
   115          ******************       warning: proc SWAPCON... [-w+user]
   116                                  	DOSAssume   CS,<DS>,"SwapCon"
   117                                  	ASSUME	ES:NOTHING
   118 00000006 0657                    	SaveReg <ES,DI>
   119 00000008 C606[0000]01            	MOV	BYTE PTR [CONSWAP],1	;   CONSwap = TRUE;
   120                                  ThisSFT equ THISSFT	; NASM port label
   121 0000000D C43E[0000]              	LES	DI,[ThisSFT]
   122                                  	Assert	ISSFT,<ES,DI>,"SwapCon"
   123                                  CONSFT equ CONSft	; NASM port label
   124 00000011 893E[0000]              	MOV	WORD PTR [CONSFT],DI
   125 00000015 8C06[0200]              	MOV	WORD PTR [CONSFT+2],ES
   126 00000019 5F07                    	RestoreReg  <DI,ES>
   127 0000001B C3                      	return
   128                                  EndProc SWAPCON
   129                                  
   130                                  Break	<DOS_READ -- MAIN READ ROUTINE AND DEVICE IN ROUTINES>
   131                                  
   132                                  ;
   133                                  ; Inputs:
   134                                  ;	[THISSFT] set to the SFT for the file being used
   135                                  ;	[DMAADD] contains transfer address
   136                                  ;	CX = No. of bytes to read
   137                                  ; Function:
   138                                  ;	Perform read operation
   139                                  ; Outputs:
   140                                  ;    Carry clear
   141                                  ;	SFT Position and cluster pointers updated
   142                                  ;	CX = No. of bytes read
   143                                  ;	ES:DI point to SFT
   144                                  ;    Carry set
   145                                  ;	AX is error code
   146                                  ;	CX = 0
   147                                  ;	ES:DI point to SFT
   148                                  ; DS preserved, all other registers destroyed
   149                                  
   150                                  	procedure   DOS_READ,NEAR
   150          ******************       warning: proc DOS_READ... [-w+user]
   151                                  	DOSAssume   CS,<DS>,"DOS_Read"
   152                                  	ASSUME	ES:NOTHING
   153                                  
   154                                  %ifndef BUF2
   155                                  %IF	BUFFERFLAG
   156                                  	cmp	byte [BUF_EMS_MODE], -1
   157                                  	jz	dos_rd_call
   158                                  	call	choose_buf_page
   159                                  	jnc	sav_map_rd_hndl
   160                                  	return
   161                                  sav_map_rd_hndl:
   162                                  ;	call	save_user_map
   163                                  dos_rd_call:
   164                                  %ENDIF
   165                                  %endif	
   166                                  
   167 0000001C C43E[0000]              	LES	DI,[THISSFT]
   168                                  	Assert	ISSFT,<ES,DI>,"DOS_Read"
   169                                  ;
   170                                  ; Verify that the sft has been opened in a mode that allows reading.
   171                                  ;
   172 00000020 268A4502                	MOV	AL,BYTE PTR [ES:DI + sf_mode]
   173 00000024 240F                    	AND	AL,access_mask
   174 00000026 3C01                    	CMP	AL,open_for_write
   175 00000028 7503                    	JNE	READ_NO_MODE		;Is read or both
   176 0000002A E9(0000)                	transfer   SET_ACC_ERR
   177                                  
   178                                  READ_NO_MODE:
   179 0000002D E8(0000)                	invoke	SETUP
   180 00000030 E30B                    	JCXZ	NoIORet 		; no bytes to read - fast return
   181 00000032 E8(0000)                	invoke	IsSFTNet
   182 00000035 7408                    	JZ	LOCAL_READ
   183                                  
   184                                  ;	invoke	OWN_SHARE		;AN000;;IFS. IFS owns share ?
   185                                  ;	JZ	IFS_HAS_SHARE		;AN000;;IFS. yes
   186                                  ;	EnterCrit   critDisk		;AN000;;IFS. enter critical section
   187                                  ;	CALL	CHECK_READ_LOCK 	;AN000;;IFS. check read lock
   188                                  ;	JNC	READ_OK2		;AN000;;IFS. lock check ok
   189                                  ;	JMP	SHORT critexit		;AN000;;IFS. fail
   190                                  READ_OK2:				;AN000;
   191                                  ;	LeaveCrit   critDisk		;AN000;;IFS. leave critical section
   192                                  IFS_HAS_SHARE:				;AN000;
   193                                  
   194                                  %IFN Installed
   195                                  	transfer NET_READ
   196                                  %ELSE
   197                                  multNET equ MultNET	; NASM port equate
   198 00000037 B80811                  	MOV	AX,(multNET << 8) | 8
   199 0000003A CD2F                    	INT	2FH
   200 0000003C C3                      	return
   201                                  %ENDIF
   202                                  
   203                                  ;
   204                                  ; The user ended up requesting 0 bytes of input.  We do nothing for this case
   205                                  ; except return immediately.
   206                                  ;
   207                                  NoIORet:
   208 0000003D F8                      	CLC
   209 0000003E C3                      	return
   210                                  
   211                                  LOCAL_READ:
   212 0000003F 26F745058000            	TEST	word [ES:DI + sf_flags],devid_device  ; Check for named device I/O
   213 00000045 7523                    	JNZ	READDEV
   214 00000047 C606[0000]02            	MOV	byte [EXTERR_LOCUS],errLOC_Disk
   215 0000004C E8(0000)                	EnterCrit   critDisk
   216 0000004F F606[0000]80            	TEST	byte [FastSeekflg],Fast_yes	       ; FastSeek installed ?
   217 00000054 7405                    	JZ	FS_no			       ; no
   218 00000056 800E[0000]01            	OR	byte [FastSeekflg],FS_begin	       ; set fastseek mode
   219                                  FS_no:
   220 0000005B E8(0000)                	invoke	DISKREAD
   221 0000005E 9C                      	PUSHF				      ; save flag
   222 0000005F 368026[0000]FE          	AND	byte [ss:FastSeekflg],FS_end       ; reset fastseek mode
   223 00000065 9D                      	POPF				      ; retore flag
   224                                  critexit:
   225 00000066 E8(0000)                	LeaveCrit   critDisk
   226 00000069 C3                      	return
   227                                  
   228                                  ;
   229                                  ; We are reading from a device.  Examine the status of the device to see if we
   230                                  ; can short-circuit the I/O.  If the device in the EOF state or if it is the
   231                                  ; null device, we can safely indicate no transfer.
   232                                  ;
   233                                  READDEV:
   234                                  	DOSAssume   CS,<DS>,"DISK/ReadDev"
   235                                  	ASSUME	ES:NOTHING
   236 0000006A C606[0000]04            	MOV	byte [EXTERR_LOCUS],errLOC_SerDev
   237 0000006F 268A5D05                	MOV	BL,BYTE PTR [ES:DI + sf_flags]
   238 00000073 C43E[0000]              	LES	DI,[DMAADD]
   239 00000077 F6C340                  	TEST	BL,devid_device_EOF	; End of file?
   240 0000007A 7407                    	JZ	ENDRDDEVJ3
   241 0000007C F6C304                  	TEST	BL,devid_device_null	; NUL device?
   242 0000007F 7405                    	JZ	TESTRAW 		; NO
   243 00000081 30C0                    	XOR	AL,AL			; Indicate EOF by setting zero
   244                                  ENDRDDEVJ3:
   245 00000083 E9C000                  	JMP	ENDRDDEVJ2
   246                                  
   247                                  ;
   248                                  ; We need to hit the device.  Figure out if we do a raw read or we do the
   249                                  ; bizarre std_con_string_input.
   250                                  ;
   251                                  TESTRAW:
   252 00000086 F6C320                  	TEST	BL,devid_device_raw	; Raw mode?
   253 00000089 7508                    	JNZ	DVRDRAW 		; Yes, let the device do all local editing
   254 0000008B F6C301                  	TEST	BL,devid_device_con_in	; Is it console device?
   255 0000008E 7449                    	JZ	NOTRDCON
   256 00000090 E9E900                  	JMP	READCON
   257                                  
   258                                  DVRDRAW:
   259                                  	DOSAssume   CS,<DS>,"DISK/DvRdRaw"
   260 00000093 06                      	PUSH	ES
   261 00000094 1F                      	POP	DS			; Xaddr to DS:DI
   262                                  ASSUME	DS:NOTHING
   263                                  ReadRawRetry:
   264 00000095 89FB                    	MOV	BX,DI			; DS:BX transfer addr
   265 00000097 31C0                    	XOR	AX,AX			; Media Byte, unit = 0
   266 00000099 89C2                    	MOV	DX,AX			; Start at 0
   267 0000009B E8(0000)                	invoke	SETREAD
   268 0000009E 1E                      	PUSH	DS			; Save Seg part of Xaddr
   269 0000009F 36C536[0000]            	LDS	SI,[ss:THISSFT]
   270                                   assume ds:nothing
   271                                  	Assert	ISSFT,<DS,SI>,"DOS_Read/DvRdRawR"
   272 000000A4 E8(0000)                	invoke	DEVIOCALL
   273 000000A7 89FA                    	MOV	DX,DI			; DS:DX is preserved by INT 24
   274 000000A9 B486                    	MOV	AH,86H			; Read error
   275 000000AB 368B3E[0300]            	MOV	DI,[ss:DEVCALL + REQSTAT]
   276 000000B0 F7C70080                	TEST	DI,STERR
   277 000000B4 7419                    	JZ	CRDROK			; No errors
   278 000000B6 E8(0000)                	invoke	CHARHARD
   279 000000B9 89D7                    	MOV	DI,DX			; DS:DI is Xaddr
   280 000000BB 08C0                    	OR	AL,AL
   281 000000BD 7410                    	JZ	CRDROK			; Ignore
   282 000000BF 3C03                    	CMP	AL,3
   283 000000C1 7403                    	JZ	CRDFERR 		; fail.
   284 000000C3 1F                      	POP	DS			; Recover saved seg part of Xaddr
   285                                   assume ds:nothing
   286 000000C4 EBCF                    	JMP	ReadRawRetry		; Retry
   287                                  
   288                                  ;
   289                                  ; We have encountered a device-driver error.  We have informed the user of it
   290                                  ; and he has said for us to fail the system call.
   291                                  ;
   292                                  CRDFERR:
   293 000000C6 5F                      	POP	DI			; Clean stack
   294                                  DEVIOFERR:
   295 000000C7 36C43E[0000]            	LES	DI,[ss:THISSFT]
   296                                  	Assert	ISSFT,<ES,DI>,"DOS_Read/DEVIOFERR"
   297 000000CC E9(0000)                	transfer    SET_ACC_ERR_DS
   298                                  
   299                                  CRDROK:
   300 000000CF 5F                      	POP	DI			; Chuck saved seg of Xaddr
   301 000000D0 89D7                    	MOV	DI,DX
   302 000000D2 36033E[0000]            	ADD	DI,[ss:CALLSCNT]		; Amount transferred
   303 000000D7 EBAA                    	JMP	SHORT ENDRDDEVJ3
   304                                  
   305                                  ; We are going to do a cooked read on some character device.  There is a
   306                                  ; problem here, what does the data look like?  Is it a terminal device, line
   307                                  ; CR line CR line CR, or is it file data, line CR LF line CR LF?  Does it have
   308                                  ; a ^Z at the end which is data, or is the ^Z not data?  In any event we're
   309                                  ; going to do this:  Read in pieces up to CR (CRs included in data) or ^z (^z
   310                                  ; included in data).  this "simulates" the way con works in cooked mode
   311                                  ; reading one line at a time.  With file data, however, the lines will look
   312                                  ; like, LF line CR.  This is a little weird.
   313                                  
   314                                  NOTRDCON:
   315 000000D9 8CC0                    	MOV	AX,ES
   316 000000DB 8ED8                    	MOV	DS,AX
   317                                  ASSUME	DS:NOTHING
   318 000000DD 89FB                    	MOV	BX,DI
   319 000000DF 31D2                    	XOR	DX,DX
   320 000000E1 89D0                    	MOV	AX,DX
   321 000000E3 51                      	PUSH	CX
   322 000000E4 B90100                  	MOV	CX,1
   323 000000E7 E8(0000)                	invoke	SETREAD
   324 000000EA 59                      	POP	CX
   325 000000EB 36C536[0000]            	LDS	SI,[ss:THISSFT]
   326                                  	Assert	ISSFT,<DS,SI>,"DOS_Read/NotRdCon"
   327 000000F0 C57407                  	LDS	SI,[SI + sf_devptr]
   328                                  DVRDLP:
   329 000000F3 E8(0000)                	invoke	DSKSTATCHK
   330 000000F6 E8(0000)                	invoke	DEVIOCALL2
   331 000000F9 57                      	PUSH	DI		; Save "count" done
   332 000000FA B486                    	MOV	AH,86H
   333 000000FC 368B3E[0300]            	MOV	DI,[ss:DEVCALL + REQSTAT]
   334 00000101 F7C70080                	TEST	DI,STERR
   335 00000105 7417                    	JZ	CRDOK
   336 00000107 E8(0000)                	invoke	CHARHARD
   337 0000010A 5F                      	POP	DI
   338 0000010B 36C706[0000]0100        	MOV	word [ss:CALLSCNT],1
   339 00000112 3C01                    	CMP	AL,1
   340 00000114 74DD                    	JZ	DVRDLP			;Retry
   341 00000116 3C03                    	CMP	AL,3
   342 00000118 74AD                    	JZ	DEVIOFERR		; FAIL
   343 0000011A 30C0                    	XOR	AL,AL			; Ignore, Pick some random character
   344 0000011C EB12                    	JMP	SHORT DVRDIGN
   345                                  
   346                                  CRDOK:
   347 0000011E 5F                      	POP	DI
   348 0000011F 36833E[0000]01          	CMP	word [ss:CALLSCNT],1
   349 00000125 751F                    	JNZ	ENDRDDEVJ2
   350 00000127 1E                      	PUSH	DS
   351 00000128 368E1E[0200]            	MOV	DS,WORD PTR [ss:CALLXAD+2]
   352                                   assume ds:nothing
   353 0000012D 8A05                    	MOV	AL,BYTE PTR [DI]	; Get the character we just read
   354 0000012F 1F                      	POP	DS
   355                                   assume ds:nothing	; device
   356                                  DVRDIGN:
   357 00000130 36FF06[0000]            	INC	WORD PTR [ss:CALLXAD]	; Next character
   358 00000135 36C706[0300]0000        	MOV	word [ss:DEVCALL + REQSTAT],0
   359 0000013C 47                      	INC	DI			; Next character
   360 0000013D 3C1A                    	CMP	AL,1AH			; ^Z?
   361 0000013F 7405                    	JZ	ENDRDDEVJ2		; Yes, done zero set (EOF)
   362 00000141 3C0D                    	CMP	AL,c_CR 		; CR?
   363 00000143 E0AE                    	LOOPNZ	DVRDLP			; Loop if no, else done
   364 00000145 40                      	INC	AX			; Resets zero flag so NOT EOF, unless
   365                                  					;  AX=FFFF which is not likely
   366                                  ENDRDDEVJ2:
   367 00000146 EB1F                    	JMP	SHORT ENDRDDEV
   368                                  
   369                                  ASSUME	DS:NOTHING,ES:NOTHING
   370                                  
   371                                  TRANBUF:
   372 00000148 AC                      	LODSB
   373 00000149 AA                      	STOSB
   374 0000014A 3C0D                    	CMP	AL,c_CR 	; Check for carriage return
   375 0000014C 7503                    	JNZ	NORMCH
   376 0000014E C6040A                  	MOV	BYTE PTR [SI],c_LF
   377                                  NORMCH:
   378 00000151 3C0A                    	CMP	AL,c_LF
   379 00000153 E0F3                    	LOOPNZ	TRANBUF
   380 00000155 7507                    	JNZ	ENDRDCON
   381 00000157 31F6                    	XOR	SI,SI		; Cause a new buffer to be read
   382 00000159 E8(0000)                	invoke	OUTT		; Transmit linefeed
   383 0000015C 0C01                    	OR	AL,1		; Clear zero flag--not end of file
   384                                  ENDRDCON:
   385 0000015E 161F                    	Context DS
   386 00000160 E89DFE                  	CALL	SWAPBACK
   387 00000163 8936[0000]              	MOV	[CONTPOS],SI
   388                                  ENDRDDEV:
   389 00000167 161F                    	Context DS
   390 00000169 893E[0000]              	MOV	[NEXTADD],DI
   391 0000016D 7509                    	JNZ	SETSFTC 	; Zero set if Ctrl-Z found in input
   392 0000016F C43E[0000]              	LES	DI,[THISSFT]
   393                                  	Assert	ISSFT,<ES,DI>,"DOS_Read/EndRdDev"
   394 00000173 26806505BF              	AND	BYTE PTR [ES:DI + sf_flags],~ devid_device_EOF ; Mark as no more data available
   395                                  SETSFTC:
   396 00000178 E8(0000)                	invoke	SETSFT
   397 0000017B C3                      	return
   398                                  
   399                                  ASSUME	DS:NOTHING,ES:NOTHING
   400                                  
   401                                  READCON:
   402                                  	DOSAssume   CS,<DS>,"ReadCon"
   403 0000017C E887FE                  	CALL	SWAPCON
   404 0000017F 8B36[0000]              	MOV	SI,[CONTPOS]
   405 00000183 09F6                    	OR	SI,SI
   406 00000185 75C1                    	JNZ	TRANBUF
   407 00000187 803E[0000]80            	CMP	BYTE PTR [CONBUF],128
   408 0000018C 7406                    	JZ	GETBUF
   409 0000018E C706[0000]80FF          	MOV	WORD PTR [CONBUF],0FF80H	; Set up 128-byte buffer with no template
   410                                  GETBUF:
   411 00000194 51                      	PUSH	CX
   412 00000195 06                      	PUSH	ES
   413 00000196 57                      	PUSH	DI
   414 00000197 BA[0000]                	MOV	DX,OFFSET CONBUF wrt DOSGROUP
   415 0000019A E8(0000)                	invoke	D_STD_CON_STRING_INPUT		; Get input buffer
   416 0000019D 5F                      	POP	DI
   417 0000019E 07                      	POP	ES
   418                                   assume es:nothing
   419 0000019F 59                      	POP	CX
   420 000001A0 BE[0200]                	MOV	SI,2 + OFFSET CONBUF wrt DOSGROUP
   421 000001A3 803C1A                  	CMP	BYTE PTR [SI],1AH	; Check for Ctrl-Z in first character
   422 000001A6 75A0                    	JNZ	TRANBUF
   423 000001A8 B01A                    	MOV	AL,1AH
   424 000001AA AA                      	STOSB
   425 000001AB 4F                      	DEC	DI
   426 000001AC B00A                    	MOV	AL,c_LF
   427 000001AE E8(0000)                	invoke	OUTT		; Send linefeed
   428 000001B1 31F6                    	XOR	SI,SI
   429 000001B3 EBA9                    	JMP	ENDRDCON
   430                                  
   431                                  EndProc DOS_READ
   432                                  
   433                                  Break	<DOS_WRITE -- MAIN WRITE ROUTINE AND DEVICE OUT ROUTINES>
   434                                  
   435                                  ;
   436                                  ; Inputs:
   437                                  ;	[THISSFT] set to the SFT for the file being used
   438                                  ;	[DMAADD] contains transfer address
   439                                  ;	CX = No. of bytes to write
   440                                  ; Function:
   441                                  ;	Perform write operation
   442                                  ;	NOTE: If CX = 0 on input, file is truncated or grown
   443                                  ;		to current sf_position
   444                                  ; Outputs:
   445                                  ;    Carry clear
   446                                  ;	SFT Position and cluster pointers updated
   447                                  ;	CX = No. of bytes written
   448                                  ;	ES:DI point to SFT
   449                                  ;    Carry set
   450                                  ;	AX is error code
   451                                  ;	CX = 0
   452                                  ;	ES:DI point to SFT
   453                                  ; DS preserved, all other registers destroyed
   454                                  
   455                                  	procedure   DOS_WRITE,NEAR
   455          ******************       warning: proc DOS_WRITE... [-w+user]
   456                                  	DOSAssume   CS,<DS>,"DOS_Write"
   457                                  	ASSUME	ES:NOTHING
   458                                  
   459                                  %ifndef BUF2
   460                                  %IF	BUFFERFLAG
   461                                  	cmp	byte [BUF_EMS_MODE], -1
   462                                  	jz	dos_wrt_call
   463                                  	call	choose_buf_page
   464                                  	jnc	sav_map_wrt_hndl
   465                                  	return
   466                                  sav_map_wrt_hndl:
   467                                  ;	call	save_user_map
   468                                  dos_wrt_call:
   469                                  %ENDIF
   470                                  %endif
   471                                  
   472 000001B5 C43E[0000]              	LES	DI,[THISSFT]
   473                                  	Assert	ISSFT,<ES,DI>,"DosWrite"
   474 000001B9 268A4502                	MOV	AL,BYTE PTR [ES:DI + sf_mode]
   475 000001BD 240F                    	AND	AL,access_mask
   476 000001BF 3C00                    	CMP	AL,open_for_read
   477 000001C1 7503                    	JNE	Check_FCB_RO		 ;Is write or both
   478                                  BadMode:
   479 000001C3 E9(0000)                	transfer    SET_ACC_ERR
   480                                  
   481                                  ;
   482                                  ; NOTE: The following check for writting to a Read Only File is performed
   483                                  ;	    ONLY on FCBs!!!!
   484                                  ;	We ALLOW writes to Read Only files via handles to allow a CREATE
   485                                  ;	    of a read only file which can then be written to.
   486                                  ;	This is OK because we are NOT ALLOWED to OPEN a RO file via handles
   487                                  ;	    for writting, or RE-CREATE an EXISTING RO file via handles. Thus,
   488                                  ;	    CREATing a NEW RO file, or RE-CREATing an existing file which
   489                                  ;	    is NOT RO to be RO, via handles are the only times we can write
   490                                  ;	    to a read-only file.
   491                                  ;
   492                                  Check_FCB_RO:
   493 000001C6 26F745020080            	TEST	word [ES:DI + sf_mode],sf_isfcb
   494 000001CC 7407                    	JZ	WRITE_NO_MODE		; Not an FCB
   495 000001CE 26F6450401              	TEST	byte [ES:DI + sf_attr],attr_read_only
   496 000001D3 75EE                    	JNZ	BadMode 		; Can't write to Read_Only files via FCB
   497                                  WRITE_NO_MODE:
   498 000001D5 E8(0000)                	invoke	SETUP
   499 000001D8 E8(0000)                	invoke	IsSFTNet
   500 000001DB 7406                    	JZ	LOCAL_WRITE
   501                                  
   502                                  ;	invoke	OWN_SHARE		;AN000;;IFS. IFS owns share ?
   503                                  ;	JZ	IFS_HAS_SHARE2		;AN000;;IFS. yes
   504                                  ;	EnterCrit   critDisk		;AN000;;IFS. enter critical section
   505                                  ;	CALL	CHECK_WRITE_LOCK	;AN000;;IFS. check write lock
   506                                  ;	JC	nocommit		;AN000;;IFS. lock error
   507                                  ;
   508                                  ;	LeaveCrit   critDisk		;AN000;;IFS. leave critical section
   509                                  IFS_HAS_SHARE2: 			;AN000;
   510                                  
   511                                  
   512                                  %IFN Installed
   513                                  	transfer NET_WRITE
   514                                  %ELSE
   515 000001DD B80911                  	MOV	AX,(multNET << 8) | 9
   516 000001E0 CD2F                    	INT	2FH
   517                                  ;	JC	nomore		       ;AN000;;IFS. error
   518                                  ;	invoke	OWN_SHARE	       ;AN000;;IFS. IFS owns share ?
   519                                  ;	JZ	nomore		       ;AN000;;IFS. yes
   520                                  ;
   521                                  ;	MOV	AX,1		       ;AN000;;IFS. update all SFT for new size
   522                                  ;	call	JShare + 14 * 4        ;AN000;;IFS. call ShSu
   523                                  
   524                                  nomore: 			       ;AN000;
   525 000001E2 C3                      	return
   526                                  %ENDIF
   527                                  
   528                                  
   529                                  LOCAL_WRITE:
   530 000001E3 26F745058000            	TEST	word [ES:DI + sf_flags],devid_device  ; Check for named device I/O
   531 000001E9 757B                    	JNZ	WRTDEV
   532 000001EB C606[0000]02            	MOV	byte [EXTERR_LOCUS],errLOC_Disk
   533 000001F0 E8(0000)                	EnterCrit   critDisk
   534 000001F3 F606[0000]80            	TEST	byte [FastSeekflg],Fast_yes	       ;AN000;FO. FastSeek installed ?
   535 000001F8 7405                    	JZ	FS_no2			       ;AN000;FO. no
   536 000001FA 800E[0000]01            	OR	byte [FastSeekflg],FS_begin	       ;AN000;FO. set fastseek mode
   537                                  FS_no2: 				       ;AN000;
   538 000001FF E8(0000)                	invoke	DISKWRITE
   539 00000202 9C                      	PUSHF				       ;AN000;FO. save flag
   540 00000203 368026[0000]FE          	AND	byte [ss:FastSeekflg],FS_end        ;AN000;FO. reset fastseek mode
   541 00000209 9D                      	POPF				       ;AN000;FO. restore flag
   542                                  ;; Extended Open
   543 0000020A 7211                    	JC	nocommit		       ;AN000;EO.
   544 0000020C C43E[0000]              	LES	DI,[THISSFT]		       ;AN000;EO.
   545 00000210 26F745020040            	TEST	word [ES:DI + sf_mode],auto_commit_write ;AN000;EO.
   546 00000216 7405                    	JZ	nocommit		       ;AN000;EO.
   547 00000218 51                      	PUSH	CX			       ;AN000;EO.
   548 00000219 E8(0000)                	invoke	DOS_COMMIT		       ;AN000;EO.
   549 0000021C 59                      	POP	CX			       ;AN000;EO.
   550                                  nocommit:				       ;AN000;
   551                                  ;; Extended Open
   552 0000021D E8(0000)                	LeaveCrit   critDisk
   553 00000220 C3                      	return
   554                                  
   555                                  DVWRTRAW:
   556                                  ASSUME	DS:NOTHING
   557 00000221 31C0                    	XOR	AX,AX			; Media Byte, unit = 0
   558 00000223 E8(0000)                	invoke	SETWRITE
   559 00000226 1E                      	PUSH	DS			; Save seg of transfer
   560 00000227 36C536[0000]            	LDS	SI,[ss:THISSFT]
   561                                   assume ds:nothing
   562                                  	Assert	ISSFT,<DS,SI>,"DosWrite/DvWrtRaw"
   563 0000022C E8(0000)                	invoke	DEVIOCALL		; DS:SI -> DEVICE
   564 0000022F 89FA                    	MOV	DX,DI			; Offset part of Xaddr saved in DX
   565 00000231 B487                    	MOV	AH,87H
   566 00000233 368B3E[0300]            	MOV	DI,[ss:DEVCALL + REQSTAT]
   567 00000238 F7C70080                	TEST	DI,STERR
   568 0000023C 7414                    	JZ	CWRTROK
   569 0000023E E8(0000)                	invoke	CHARHARD
   570 00000241 89D3                    	MOV	BX,DX			; Recall transfer addr
   571 00000243 08C0                    	OR	AL,AL
   572 00000245 740B                    	JZ	CWRTROK 		; Ignore
   573 00000247 3C03                    	CMP	AL,3
   574 00000249 7403                    	JZ	CWRFERR
   575 0000024B 1F                      	POP	DS			; Recover saved seg of transfer
   576                                   assume ds:nothing
   577 0000024C EBD3                    	JMP	DVWRTRAW		; Try again
   578                                  
   579                                  CWRFERR:
   580 0000024E 58                      	POP	AX			; Chuck saved seg of transfer
   581 0000024F E974FE                  	JMP	CRDFERR 		; Will pop one more stack element
   582                                  
   583                                  CWRTROK:
   584 00000252 58                      	POP	AX			; Chuck saved seg of transfer
   585 00000253 1F                      	POP	DS
   586                                  	DOSAssume   CS,<DS>,"DISK/CWrtOK"
   587 00000254 A1[0000]                	MOV	AX,[CALLSCNT]		; Get actual number of bytes transferred
   588                                  ENDWRDEV:
   589 00000257 C43E[0000]              	LES	DI,[THISSFT]
   590                                  	Assert	ISSFT,<ES,DI>,"DosWrite/EndWrDev"
   591 0000025B 89C1                    	MOV	CX,AX
   592 0000025D E8(0000)                	invoke	ADDREC
   593 00000260 C3                      	return
   594                                  
   595                                  WRTNUL:
   596 00000261 89CA                    	MOV	DX,CX			;Entire transfer done
   597                                  WrtCookJ:
   598 00000263 E99D00                  	JMP	WRTCOOKDONE
   599                                  
   600                                  WRTDEV:
   601                                  	DOSAssume   CS,<DS>,"DISK/WrtDev"
   602 00000266 C606[0000]04            	MOV	byte [EXTERR_LOCUS],errLOC_SerDev
   603 0000026B 26804D0540              	OR	BYTE PTR [ES:DI + sf_flags],devid_device_EOF  ; Reset EOF for input
   604 00000270 268A5D05                	MOV	BL,BYTE PTR [ES:DI + sf_flags]
   605 00000274 31C0                    	XOR	AX,AX
   606 00000276 E3DF                    	JCXZ	ENDWRDEV		; problem of creating on a device.
   607 00000278 1E                      	PUSH	DS
   608 00000279 88D8                    	MOV	AL,BL
   609 0000027B C51E[0000]              	LDS	BX,[DMAADD]		; Xaddr to DS:BX
   610                                  ASSUME	DS:NOTHING
   611 0000027F 89DF                    	MOV	DI,BX			; Xaddr to DS:DI
   612 00000281 31D2                    	XOR	DX,DX			; Set starting point
   613 00000283 A820                    	TEST	AL,devid_device_raw	; Raw?
   614 00000285 7402                    	JZ	TEST_DEV_CON
   615 00000287 EB98                    	JMP	DVWRTRAW
   616                                  
   617                                  TEST_DEV_CON:
   618 00000289 A802                    	TEST	AL,devid_device_con_out ; Console output device?
   619 0000028B 757C                    	JNZ	WRITECON
   620 0000028D A804                    	TEST	AL,devid_device_null
   621 0000028F 75D0                    	JNZ	WRTNUL
   622 00000291 89D0                    	MOV	AX,DX
   623 00000293 803F1A                  	CMP	BYTE PTR [BX],1AH	; ^Z?
   624                                  WRTCOOKJ equ WrtCookJ	; NASM port label
   625 00000296 74CB                    	JZ	WRTCOOKJ		; Yes, transfer nothing
   626 00000298 51                      	PUSH	CX
   627 00000299 B90100                  	MOV	CX,1
   628 0000029C E8(0000)                	invoke	SETWRITE
   629 0000029F 59                      	POP	CX
   630 000002A0 36C536[0000]            	LDS	SI,[ss:THISSFT]
   631                                  X25_Special equ X25_special	; NASM port equate
   632 000002A5 36810E[0000]0008        	OR	word [ss:DOS34_FLAG],X25_Special;AN000;;PTM. bad x25 driver
   633 000002AC B403                    	MOV	AH,3			;AN000;;PTM. prompt critical error ASAP
   634 000002AE E8(0000)                	invoke	IOFUNC			;AN000;;PTM.
   635                                  	Assert	ISSFT,<DS,SI>,"DosWrite/TestDevCon"
   636 000002B1 C57407                  	LDS	SI,[SI + sf_devptr]
   637                                  DVWRTLP:
   638 000002B4 E8(0000)                	invoke	DSKSTATCHK
   639 000002B7 E8(0000)                	invoke	DEVIOCALL2
   640 000002BA 57                      	PUSH	DI
   641 000002BB B487                    	MOV	AH,87H
   642 000002BD 368B3E[0300]            	MOV	DI,[ss:DEVCALL + REQSTAT]
   643 000002C2 F7C70080                	TEST	DI,STERR
   644 000002C6 7416                    	JZ	CWROK
   645 000002C8 E8(0000)                	invoke	CHARHARD
   646 000002CB 5F                      	POP	DI
   647 000002CC 36C706[0000]0100        	MOV	word [ss:CALLSCNT],1
   648 000002D3 3C01                    	CMP	AL,1
   649 000002D5 74DD                    	JZ	DVWRTLP 	; Retry
   650 000002D7 08C0                    	OR	AL,AL
   651 000002D9 740C                    	JZ	DVWRTIGN	; Ignore
   652 000002DB E9E8FD                  	JMP	CRDFERR 	; Fail, pops one stack element
   653                                  
   654                                  CWROK:
   655 000002DE 5F                      	POP	DI
   656 000002DF 36833E[0000]00          	CMP	word [ss:CALLSCNT],0
   657 000002E5 741C                    	JZ	WRTCOOKDONE
   658                                  DVWRTIGN:
   659 000002E7 42                      	INC	DX
   660 000002E8 36FF06[0000]            	INC	WORD PTR [ss:CALLXAD]
   661 000002ED 47                      	INC	DI
   662 000002EE 1E                      	PUSH	DS
   663 000002EF 368E1E[0200]            	MOV	DS,WORD PTR [ss:CALLXAD+2]
   664                                   assume ds:nothing
   665 000002F4 803D1A                  	CMP	BYTE PTR [DI],1AH	; ^Z?
   666 000002F7 1F                      	POP	DS
   667                                   assume ds:nothing
   668 000002F8 7409                    	JZ	WRTCOOKDONE
   669 000002FA 36C706[0300]0000        	MOV	word [ss:DEVCALL + REQSTAT],0
   670 00000301 E2B1                    	LOOP	DVWRTLP
   671                                  WRTCOOKDONE:
   672 00000303 89D0                    	MOV	AX,DX
   673 00000305 1F                      	POP	DS
   674                                   assume ds:nothing
   675 00000306 E94EFF                  	JMP	ENDWRDEV
   676                                  
   677                                  WRITECON:
   678 00000309 1E                      	PUSH	DS
   679 0000030A 161F                    	Context DS
   680 0000030C E8F7FC                  	CALL	SWAPCON
   681 0000030F 1F                      	POP	DS
   682                                  ASSUME	DS:NOTHING
   683 00000310 89DE                    	MOV	SI,BX
   684 00000312 51                      	PUSH	CX
   685                                  WRCONLP:
   686 00000313 AC                      	LODSB
   687 00000314 3C1A                    	CMP	AL,1AH		; ^Z?
   688 00000316 7405                    	JZ	CONEOF
   689 00000318 E8(0000)                	invoke	OUTT
   690 0000031B E2F6                    	LOOP	WRCONLP
   691                                  CONEOF:
   692 0000031D 58                      	POP	AX			; Count
   693 0000031E 29C8                    	SUB	AX,CX			; Amount actually written
   694 00000320 1F                      	POP	DS
   695                                  	DOSAssume   CS,<DS>,"DISK/ConEOF"
   696 00000321 E8DCFC                  	CALL	SWAPBACK
   697 00000324 E930FF                  	JMP	ENDWRDEV
   698                                  EndProc DOS_WRITE
   699                                  
   700                                  ;   Convert JFN number in BX to sf_entry in DS:SI We get the normal SFT if
   701                                  ;   CONSWAP is FALSE or if the handle desired is 2 or more.  Otherwise, we
   702                                  ;   retrieve the sft from ConSFT which is set by SwapCon.
   703                                  
   704                                  	procedure   get_io_sft,near
   704          ******************       warning: proc get_io_sft... [-w+user]
   705                                  ASSUME	DS:NOTHING,ES:NOTHING
   706                                  ConSwap equ CONSWAP	; NASM port label
   707 00000327 36F606[0000]FF          	TEST	byte [ss:ConSwap],-1
   708 0000032D 7512                    	JNZ	GetRedir
   709                                  GetNormal:
   710 0000032F 161F                    	Context DS
   711 00000331 06                      	PUSH	ES
   712 00000332 57                      	PUSH	DI
   713 00000333 E8(0000)                	invoke	SFFromHandle
   714 00000336 7206                    	JC	RET44P
   715 00000338 8CC6                    	MOV	SI,ES
   716 0000033A 8EDE                    	MOV	DS,SI
   717                                  ASSUME	DS:NOTHING
   718 0000033C 89FE                    	MOV	SI,DI
   719                                  RET44P:
   720 0000033E 5F                      	POP	DI
   721 0000033F 07                      	POP	ES
   722                                   assume es:nothing
   723 00000340 C3                      	return
   724                                  GetRedir:
   725 00000341 83FB01                  	CMP	BX,1
   726 00000344 77E9                    	JA	GetNormal
   727                                  ConSFT equ CONSft	; NASM port label
   728 00000346 36C536[0000]            	LDS	SI,[ss:ConSFT]
   729                                  	Assert	ISSFT,<DS,SI>,"GetIOSft"
   730 0000034B F8                      	CLC
   731 0000034C C3                      	return
   732                                  EndProc get_io_sft
   733                                  
   734                                  Break	<DIRREAD -- READ A DIRECTORY SECTOR>
   735                                  
   736                                  ; Inputs:
   737                                  ;	AX = Directory block number (relative to first block of directory)
   738                                  ;	ES:BP = Base of drive parameters
   739                                  ;	[DIRSEC] = First sector of first cluster of directory
   740                                  ;	[CLUSNUM] = Next cluster
   741                                  ;	[CLUSFAC] = Sectors/Cluster
   742                                  ; Function:
   743                                  ;	Read the directory block into [CURBUF].
   744                                  ; Outputs:
   745                                  ;	[NXTCLUSNUM] = Next cluster (after the one skipped to)
   746                                  ;	[SECCLUSPOS] Set
   747                                  ;	ES:BP unchanged
   748                                  ;	[CURBUF] Points to Buffer with dir sector
   749                                  ;	Carry set if error (user said FAIL to I 24)
   750                                  ; DS preserved, all other registers destroyed.
   751                                  
   752                                  	procedure   DirRead,NEAR
   752          ******************       warning: proc DirRead... [-w+user]
   753                                  	DOSAssume   CS,<DS>,"DirRead"
   754                                  	ASSUME	ES:NOTHING
   755                                  	Assert	    ISDPB,<ES,BP>,"DirRead"
   756                                  
   757                                  ;
   758                                  ; Note that ClusFac is is the sectors per cluster.  This is NOT necessarily
   759                                  ; the same as what is in the DPB!  In the case of the root directory, we have
   760                                  ; ClusFac = # sectors in the root directory.  The root directory is detected
   761                                  ; by DIRStart = 0.
   762                                  ;
   763 0000034D 31D2                    	XOR	DX,DX
   764 0000034F 833E[0000]00            	CMP	word [DirStart],0
   765 00000354 7504                    	jnz	SubDir
   766 00000356 92                      	XCHG	AX,DX
   767 00000357 EB0D                    	JMP	DoRead
   768 00000359 90                      	nop	; identicalise
   769                                  ;
   770                                  ; Convert the sector number in AX into cluster and sector-within-cluster pair
   771                                  ;
   772                                  SubDir:
   773 0000035A 88C2                    	MOV	DL,AL
   774 0000035C 26225604                	AND	DL,[ES:BP + dpb_cluster_mask]
   775                                  ;
   776                                  ; DX is the sector-in-cluster
   777                                  ;
   778 00000360 268A4E05                	MOV	CL,[ES:BP + dpb_cluster_shift]
   779 00000364 D3E8                    	SHR	AX,CL
   780                                  ;
   781                                  ; DX is position in cluster
   782                                  ; AX is number of clusters to skip
   783                                  ;
   784                                  DoRead:
   785                                  SECCLUSPOS equ SecClusPos	; NASM port label
   786 00000366 8816[0000]              	MOV	[SECCLUSPOS],DL
   787 0000036A 89C1                    	MOV	CX,AX
   788 0000036C 88D4                    	MOV	AH,DL
   789                                  ;
   790                                  ; CX is number of clusters to skip.
   791                                  ; AH is remainder
   792                                  ;
   793                                  DIRSEC equ DirSec	; NASM port label
   794 0000036E 8B16[0200]              	MOV	DX,WORD PTR [DIRSEC+2]	     ;AN000;>32mb
   795 00000372 8916[0000]              	MOV	[HIGH_SECTOR],DX	     ;AN000;>32mb
   796 00000376 8B16[0000]              	MOV	DX,WORD PTR [DIRSEC]
   797 0000037A 00E2                    	ADD	DL,AH
   798 0000037C 80D600                  	ADC	DH,0
   799 0000037F 8316[0000]00            	ADC	word [HIGH_SECTOR],0 	     ;AN000;>32mb
   800                                  
   801                                  CLUSNUM equ ClusNum	; NASM port label
   802 00000384 8B1E[0000]              	MOV	BX,[CLUSNUM]
   803                                  NXTCLUSNUM equ NxtClusNum	; NASM port label
   804 00000388 891E[0000]              	MOV	[NXTCLUSNUM],BX
   805 0000038C E319                    	JCXZ	FIRSTCLUSTER
   806                                  SKPCLLP:
   807 0000038E E8(0000)                	invoke	UNPACK
   808 00000391 72B9                    	retc
   809 00000393 87DF                    	XCHG	BX,DI
   810 00000395 E8(0000)                	invoke	IsEOF			; test for eof based on fat size
   811 00000398 7302                    	JAE	HAVESKIPPED
   812 0000039A E2F2                    	LOOP	SKPCLLP
   813                                  HAVESKIPPED:
   814 0000039C 891E[0000]              	MOV	[NXTCLUSNUM],BX
   815 000003A0 89FA                    	MOV	DX,DI
   816 000003A2 88E3                    	MOV	BL,AH
   817 000003A4 E8(0000)                	invoke	FIGREC
   818                                  
   819                                  	entry	FIRSTCLUSTER
   820                                  
   821                                  allowed_RETRY equ Allowed_RETRY	; NASM port equate
   822                                  allowed_FAIL equ Allowed_FAIL	; NASM port equate
   823 000003A7 C606[0000]18            	MOV	byte [ALLOWED],allowed_RETRY + allowed_FAIL
   824 000003AC 30C0                    	XOR	AL,AL		; Indicate pre-read
   825 000003AE E8(0000)                	invoke	GETBUFFR
   826 000003B1 7299                    	retc
   827                                  
   828                                  	entry	SET_BUF_AS_DIR
   829                                  	DOSAssume   CS,<DS>,"SET_BUF_AS_DIR"
   830                                  	ASSUME	ES:NOTHING
   831                                  ; Set the type of CURBUF to be a directory sector.
   832                                  ; Only flags are modified.
   833                                  
   834 000003B3 1E                      	PUSH	DS
   835 000003B4 56                      	PUSH	SI
   836 000003B5 C536[0000]              	LDS	SI,[CURBUF]
   837                                   assume ds:nothing
   838                                  	Assert	ISBUF,<DS,SI>,"SetBufAsDir"
   839 000003B9 804C0504                	OR	byte [SI + buf_flags],buf_isDIR	; Clears carry
   840 000003BD 5E                      	POP	SI
   841 000003BE 1F                      	POP	DS
   842                                   assume ds:DOSGROUP
   843 000003BF C3                      	return
   844                                  EndProc DirRead
   845                                  
   846                                  Break	<FATSECRD -- READ A FAT SECTOR>
   847                                  
   848                                  ; Inputs:
   849                                  ;	Same as DREAD
   850                                  ;	DS:BX = Transfer address
   851                                  ;	CX = Number of sectors
   852                                  ;	DX = Absolute record number
   853                                  ;	ES:BP = Base of drive parameters
   854                                  ; Function:
   855                                  ;	Calls BIOS to perform FAT read.
   856                                  ; Outputs:
   857                                  ;	Same as DREAD
   858                                  
   859                                  	procedure   FATSecRd,NEAR
   859          ******************       warning: proc FATSecRd... [-w+user]
   860                                  ASSUME	DS:NOTHING,ES:NOTHING
   861                                  
   862                                  	Assert	    ISDPB,<ES,BP>,"FATSecRd"
   863 000003C0 36C606[0000]18          	MOV	byte [ss:ALLOWED],allowed_RETRY + allowed_FAIL
   864 000003C6 89CF                    	MOV	DI,CX
   865 000003C8 268A4E08                	MOV	CL,[ES:BP + dpb_FAT_count]
   866 000003CC 268B460F                	MOV	AX,[ES:BP + dpb_FAT_size] 	;AN000;>32mb
   867                                  ;	XOR	AH,AH
   868 000003D0 30ED                    	XOR	CH,CH				;AN000;>32mb
   869 000003D2 52                      	PUSH	DX
   870                                  NXTFAT:
   871 000003D3 36C706[0000]0000        	MOV	word [ss:HIGH_SECTOR],0       ;AN000;>32mb FAT sectors cannot exceed
   872 000003DA 51                      	PUSH	CX		      ;AN000;>32mb
   873 000003DB 50                      	PUSH	AX
   874 000003DC 89F9                    	MOV	CX,DI
   875 000003DE E8(0000)                	invoke	DSKREAD
   876 000003E1 58                      	POP	AX
   877 000003E2 59                      	POP	CX
   878 000003E3 7420                    	JZ	RET41P		; Carry clear
   879 000003E5 01C2                    	ADD	DX,AX
   880 000003E7 E2EA                    	LOOP	NXTFAT
   881 000003E9 5A                      	POP	DX
   882 000003EA 89F9                    	MOV	CX,DI
   883                                  
   884                                  ; NOTE FALL THROUGH
   885                                  
   886                                  Break	<DREAD -- DO A DISK READ>
   887                                  
   888                                  ; Inputs:
   889                                  ;	DS:BX = Transfer address
   890                                  ;	CX = Number of sectors
   891                                  ;	DX = Absolute record number	      (LOW)
   892                                  ;	[HIGH_SECTOR]= Absolute record number (HIGH)
   893                                  ;	ES:BP = Base of drive parameters
   894                                  ;	[ALLOWED] must be set in case call to HARDERR_DOS needed
   895                                  ; Function:
   896                                  ;	Calls BIOS to perform disk read. If BIOS reports
   897                                  ;	errors, will call HARDERRRW for further action.
   898                                  ; Outputs:
   899                                  ;	Carry set if error (currently user FAILED to INT 24)
   900                                  ; DS,ES:BP preserved. All other registers destroyed.
   901                                  
   902                                  	entry	DREAD
   903                                  ASSUME	DS:NOTHING,ES:NOTHING
   904                                  
   905                                  	Assert	ISDPB,<ES,BP>,"DREAD"
   906 000003EC E8(0000)                	invoke	DSKREAD
   907 000003EF 74CE                    	retz			; Carry clear
   908                                  READOP equ ReadOp	; NASM port label
   909 000003F1 36C606[0000]00          	MOV	BYTE PTR [ss:READOP],0
   910 000003F7 E8(0000)                	invoke	HARDERRRW
   911 000003FA 3C01                    	CMP	AL,1		; Check for retry
   912 000003FC 74EE                    	JZ	DREAD
   913 000003FE 3C03                    	CMP	AL,3		; Check for FAIL
   914 00000400 F8                      	CLC
   915 00000401 7501                    	JNZ	NO_CAR		; Ignore
   916 00000403 F9                      	STC
   917                                  NO_CAR:
   918 00000404 C3                      	return
   919                                  
   920 00000405 5A                      RET41P: POP	DX
   921 00000406 C3                      	return
   922                                  EndProc FATSecRd
   923                                  
   924                                  
   925                                  Break	<CHECK_WRITE_LOCK>
   926                                  
   927                                  ; Inputs:
   928                                  ;	output of SETUP
   929                                  ;	ES:DI -> SFT
   930                                  ; Function:
   931                                  ;	check write lock
   932                                  ; Outputs:
   933                                  ;	Carry set if error
   934                                  ;	Carry clear if ok
   935                                  
   936                                  	procedure   CHECK_WRITE_LOCK,NEAR      ;AN000;
   936          ******************       warning: proc CHECK_WRITE_LOCK... [-w+user]
   937                                  ASSUME	DS:NOTHING,ES:NOTHING		       ;AN000;
   938                                  
   939 00000407 26F6450408              	TEST	byte [ES:DI + sf_attr],attr_volume_id ;AN000;;MS.  volume id
   940 0000040C 7404                    	JZ	write_cont		       ;AN000;;MS.  no
   941 0000040E E8(0000)                	invoke	SET_ACC_ERR_DS		       ;AN000;;MS.
   942 00000411 C3                      	return				;AN000;;MS.
   943                                  write_cont:				;AN000;
   944 00000412 51                      	PUSH	CX			;AN000;;MS. save reg
   945 00000413 09C9                    	OR	CX,CX			;AN000;;MS.
   946 00000415 7503                    	JNZ	Not_Truncate		;AN000;;MS.
   947 00000417 B9FFFF                  	MOV	CX,0FFFFH		;AN000;;MS. check for lock on whole file
   948                                  Not_Truncate:				;AN000;
   949 0000041A B080                    	MOV	AL,80H			;AN000;;MS. check write access
   950 0000041C E8(0000)                	invoke	LOCK_CHECK		;AN000;;MS. check lock
   951 0000041F 59                      	POP	CX			;AN000;;MS. restore reg
   952 00000420 7305                    	JNC	WRITE_OK		;AN000;;MS. lock ok
   953 00000422 E8(0000)                	invoke	WRITE_LOCK_VIOLATION	;AN000;;MS. issue I24
   954 00000425 73E0                    	JNC	CHECK_WRITE_LOCK	;AN000;;MS. retry
   955                                  WRITE_OK:				;AN000;
   956 00000427 C3                      	return				;AN000;;MS.
   957                                  EndProc CHECK_WRITE_LOCK		;AN000;
   958                                  
   959                                  
   960                                  Break	<CHECK_READ_LOCK>
   961                                  
   962                                  ; Inputs:
   963                                  ;	ES:DI -> SFT
   964                                  ;	output of SETUP
   965                                  ; Function:
   966                                  ;	check read lock
   967                                  ; Outputs:
   968                                  ;	Carry set if error
   969                                  ;	Carry clear if ok
   970                                  
   971                                  	procedure   CHECK_READ_LOCK,NEAR       ;AN000;
   971          ******************       warning: proc CHECK_READ_LOCK... [-w+user]
   972                                  ASSUME	DS:NOTHING,ES:NOTHING		       ;AN000;
   973                                  
   974 00000428 26F6450408              	TEST	byte [ES:DI + sf_attr],attr_volume_id ;AN000;;MS.  volume id
   975 0000042D 7404                    	JZ	do_retry		       ;AN000;;MS.  no
   976 0000042F E8(0000)                	invoke	SET_ACC_ERR		       ;AN000;;MS.
   977 00000432 C3                      	return				       ;AN000;;MS.
   978                                  do_retry:				;AN000;
   979 00000433 B000                    	MOV	AL,0			;AN000;;MS. check read access
   980 00000435 E8(0000)                	invoke	LOCK_CHECK		;AN000;;MS. check lock
   981 00000438 7305                    	JNC	READ_OK 		;AN000;;MS. lock ok
   982 0000043A E8(0000)                	invoke	READ_LOCK_VIOLATION	;AN000;;MS. issue I24
   983 0000043D 73E9                    	JNC	CHECK_READ_LOCK 	;AN000;;MS. retry
   984                                  READ_OK:				;AN000; MS.
   985 0000043F C3                      	return				;AN000;;MS.
   986                                  EndProc CHECK_READ_LOCK 		;AN000;
   987                                  
   988                                  %ifndef BUF2
   989                                  %IF BUFFERFLAG
   990                                  
   991                                  ;-------------------------------------------------------------------------
   992                                  ;	Function name	: 	choose_buf_page
   993                                  ;	Inputs		:	DMAADD = Xaddr
   994                                  ;				cx = # of bytes to transfer
   995                                  ;	Outputs		:	if NC
   996                                  ;
   997                                  ;				SAFE_FLAG - 0 ==> page is safe. no need to
   998                                  ;						  detect collision between
   999                                  ;						  user & system buffer.
  1000                                  ;				SAFE_FLAG - 1 ==> page is unsafe. Must check
  1001                                  ;						  for collision
  1002                                  ;
  1003                                  ;				CY - error
  1004                                  ;
  1005                                  ;
  1006                                  ;	High Level Alogrithm:
  1007                                  ;
  1008                                  ;	1. If Xaddr. is above the first physical page above 640K
  1009                                  ;	   2. choose that page
  1010                                  ;	   3. set safe flag
  1011                                  ;	4. else
  1012                                  ;	   5. choose highest page above 640K
  1013                                  ;	   6. If 6 or more pages above 640k
  1014                                  ;	      7. Set safe flag				
  1015                                  ;	   8. else
  1016                                  ;	      9. if Xaddr. + # of bytes to transfer does not spill into the
  1017                                  ;	     	 chosen page
  1018                                  ;		 10. set safe flag
  1019                                  ;	      11.else
  1020                                  ;		 12. clear safe flag
  1021                                  ;	      13.endif
  1022                                  ;	   14.endif
  1023                                  ;	15.endif
  1024                                  ;
  1025                                  ;----------------------------------------------------------------------------
  1026                                  Procedure 	choose_buf_page,near
  1027                                  
  1028                                   assume ds:nothing, es:nothing, ss:dosgroup
  1029                                  
  1030                                  	push	cx
  1031                                  	push	bx
  1032                                  	push	dx
  1033                                  	push	si
  1034                                  	push	ds
  1035                                  	push	ax
  1036                                  
  1037                                  	mov	ax, word ptr [ss:DMAADD+2]
  1038                                  	and	ax, 0fc00h  	; page segment of transfer segment
  1039                                  
  1040                                  	cmp	ax, word ptr [ss:BUF_EMS_FIRST_PAGE]
  1041                                  	ja	pick_first
  1042                                  	
  1043                                  	cmp	word [ss:BUF_EMS_NPA640], 6
  1044                                  	jae	safe_pick_last
  1045                                  
  1046                                  	add	cx, word ptr [ss:DMAADD]	; get final offset 
  1047                                  	mov	bx, cx
  1048                                  
  1049                                  	mov	cl, 4
  1050                                  	shr	bx, cl		; get # of paragraphs
  1051                                  	mov	ax, word ptr [ss:DMAADD+2]	; get initial segment
  1052                                  	add	ax, bx		; get final segment
  1053                                  
  1054                                  	and	ax, 0fc00h
  1055                                  	cmp	ax, word ptr [ss:BUF_EMS_LAST_PAGE]
  1056                                  	jne	safe_pick_last
  1057                                  
  1058                                  	mov	byte [ss:BUF_EMS_SAFE_FLAG], 0
  1059                                  	jmp	fin_choose_page
  1060                                  	nop	; identicalise
  1061                                  
  1062                                  safe_pick_last:
  1063                                  	mov	byte [ss:BUF_EMS_SAFE_FLAG], 1
  1064                                  	jmp	fin_choose_page
  1065                                  	nop	; identicalise
  1066                                  
  1067                                  ;pick_last:
  1068                                  ;	mov	ax, word ptr [BUF_EMS_LAST_PAGE]
  1069                                  ;	mov	[BUF_EMS_PFRAME], ax
  1070                                  ;	mov	ax, word ptr [BUF_EMS_LAST_PAGE+2]
  1071                                  ;	mov	[BUF_EMS_PAGE_FRAME], ax
  1072                                  ;	xor	ax, ax
  1073                                  ;	jmp	fin_choose_page
  1074                                  
  1075                                  pick_first:
  1076                                  	mov	ax, word ptr [ss:BUF_EMS_FIRST_PAGE]
  1077                                  	cmp	[ss:BUF_EMS_PFRAME], ax
  1078                                  	je	fin_choose_page
  1079                                  	call	restore_user_map
  1080                                  	mov	word ptr [ss:LASTBUFFER], -1
  1081                                  	mov	[ss:BUF_EMS_PFRAME], ax
  1082                                  	mov	ax, word ptr [ss:BUF_EMS_FIRST_PAGE+2]
  1083                                  	mov	[ss:BUF_EMS_PAGE_FRAME], ax
  1084                                  	mov	byte [ss:BUF_EMS_SAFE_FLAG], 1
  1085                                  	call	Setup_EMS_Buffers
  1086                                  	call	save_user_map
  1087                                  	jmp	fin_choose_page
  1088                                  	nop	; identicalise
  1089                                  
  1090                                  err_choose_page:
  1091                                  	stc
  1092                                  
  1093                                  fin_choose_page:
  1094                                  	clc
  1095                                  
  1096                                  	pop	ax
  1097                                  	pop	ds
  1098                                  	pop	si
  1099                                  	pop	dx
  1100                                  	pop	bx
  1101                                  	pop	cx
  1102                                  	return
  1103                                  
  1104                                  EndProc	choose_buf_page	
  1105                                  
  1106                                  %ENDIF
  1107                                  %endif
  1108                                  
  1109                                      END
  1110                                  
  1111                                  
  1112                                  
