     1                                  ;	SCCSID = @(#)fcbio2.asm 1.2 85/07/23
     2                                  ;	SCCSID = @(#)fcbio2.asm 1.2 85/07/23
     3                                  ;TITLE	FCBIO2 - FCB system calls
     4                                  ;NAME	FCBIO2
     5                                  
     6                                  ;
     7                                  ; Ancient 1.0 1.1 FCB system calls
     8                                  ;				    regen   save
     9                                  ;   GetRR
    10                                  ;   GetExtent
    11                                  ;   SetExtent
    12                                  ;   GetExtended
    13                                  ;   GetRecSize
    14                                  ;   FCBIO
    15                                  ;   $FCB_OPEN		    written ACC     ACC
    16                                  ;   $FCB_CREATE 	    written ACC     ACC
    17                                  ;   $FCB_RANDOM_WRITE_BLOCK written fcbio   fcbio
    18                                  ;   $FCB_RANDOM_READ_BLOCK  written fcbio   fcbio
    19                                  ;   $FCB_SEQ_READ	    written fcbio   fcbio
    20                                  ;   $FCB_SEQ_WRITE	    written fcbio   fcbio
    21                                  ;   $FCB_RANDOM_READ	    written fcbio   fcbio
    22                                  ;   $FCB_RANDOM_WRITE	    written fcbio   fcbio
    23                                  ;
    24                                  ;   Revision history:
    25                                  ;
    26                                  ;	Created: ARR 4 April 1983
    27                                  ;		 MZ  6 June  1983 completion of functions
    28                                  ;		 MZ 15 Dec   1983 Brain damaged programs close FCBs multiple
    29                                  ;				  times.  Change so successive closes work by
    30                                  ;				  always returning OK.	Also, detect I/O to
    31                                  ;				  already closed FCB and return EOF.
    32                                  ;		 MZ 16 Jan   1984 More braindamage.  Need to separate info
    33                                  ;				  out of sft into FCB for reconnection
    34                                  ;
    35                                  ;	A000	version 4.00  Jan. 1988
    36                                  ;
    37                                  [list -]
    37          ******************       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
    42                                  
    43                                  [list +]
    44                                  section DOSCODECODE
    45                                  [list -]
    45          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    45          ******************       warning: out: BPB.INC... [-w+user]
    45          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    45          ******************       warning: out: DEVSYM.INC... [-w+user]
    45          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    53                                  
    54                                  	EXTRN	DOS_Read:NEAR, DOS_Write:NEAR
    55                                  	EXTRN	DOS_Open:NEAR, DOS_Create:NEAR
    56                                  
    57                                  	I_need	DMAAdd,DWORD		; current user's DMA address
    58                                  	I_need	OpenBuf,128		; buffer for translating paths
    59                                  	I_need	ThisSFT,DWORD		; SFT in use
    60                                  	I_need	sftFCB,DWORD		; pointer to SFTs for FCB cache
    61                                  	I_need	FCBLRU,WORD		; least recently used count
    62                                  	I_need	DISK_FULL,BYTE		; flag for disk full
    63                                  %if debug
    64                                  	I_need	BugLev,WORD
    65                                  	I_need	BugTyp,WORD
    66                                  	%include "bugtyp.nas"
    67                                  %endif
    68                                  
    69                                  %ifndef BUF2
    70                                  %IF	BUFFERFLAG
    71                                  	I_need	BUF_EMS_MODE,BYTE
    72                                  	I_need	BUF_EMS_LAST_PAGE,DWORD
    73                                  	I_need	BUF_EMS_FIRST_PAGE,DWORD
    74                                  	I_need	BUF_EMS_SAFE_FLAG,BYTE
    75                                  	I_need	BUF_EMS_NPA640,WORD
    76                                  	I_need	BUF_EMS_PAGE_FRAME,WORD
    77                                  	I_need	BUF_EMS_PFRAME,WORD
    78                                  	I_need	LASTBUFFER,DWORD
    79                                  
    80                                  	extrn	restore_user_map:near
    81                                  	extrn	Setup_EMS_Buffers:near
    82                                  %ENDIF
    83                                  %endif
    84                                  
    85                                  ; Defintions for FCBOp flags
    86                                  
    87                                  Random	equ   2				; random operation
    88                                  FCBRead equ   4				; doing a read
    89                                  Block	equ   8				; doing a block I/O
    90                                  
    91                                  Break <GetRR - return the random record field in DX:AX>
    92                                  
    93                                  ;
    94                                  ;   GetRR - correctly load DX:AX with the random record field (3 or 4 bytes)
    95                                  ;	from the FCB pointed to by DS:SI
    96                                  ;
    97                                  ;   Inputs:	DS:SI point to an FCB
    98                                  ;		BX has record size
    99                                  ;   Outputs:	DX:AX contain the contents of the random record field
   100                                  ;   Registers modified: none
   101                                  
   102                                  Procedure   GetRR,NEAR
   102          ******************       warning: proc GetRR... [-w+user]
   103                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   104                                  FCB_RR equ fcb_RR	; NASM port label
   105 00000000 8B4421                  	MOV	AX,WORD PTR [SI + FCB_RR] ; get low order part
   106 00000003 8B5423                  	MOV	DX,WORD PTR [SI + FCB_RR+2]   ; get high order part
   107 00000006 83FB40                  	CMP	BX,64			; ignore MSB of RR if recsiz > 64
   108 00000009 7202                    	JB	GetRRBye
   109 0000000B 30F6                    	XOR	DH,DH
   110                                  GetRRBye:
   111 0000000D C3                      	return
   112                                  EndProc GetRR
   113                                  
   114                                  Break <GetExtent - retrieve next location for sequential IO>
   115                                  
   116                                  ;
   117                                  ;   GetExtent - Construct the next record to perform I/O from the EXTENT and
   118                                  ;	NR fields in the FCB.
   119                                  ;
   120                                  ;   Inputs:	DS:SI - point to FCB
   121                                  ;   Outputs:	DX:AX contain the contents of the random record field
   122                                  ;   Registers modified: none
   123                                  
   124                                  Procedure   GetExtent,NEAR
   124          ******************       warning: proc GetExtent... [-w+user]
   125                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   126 0000000E 8A4420                  	MOV	AL,[SI + fcb_NR]		; get low order piece
   127 00000011 8B540C                  	MOV	DX,[SI + fcb_EXTENT]	; get high order piece
   128 00000014 D0E0                    	SHL	AL,1
   129 00000016 D1EA                    	SHR	DX,1
   130 00000018 D0D8                    	RCR	AL,1			; move low order bit of DL to high order of AH
   131 0000001A 88D4                    	MOV	AH,DL
   132 0000001C 88F2                    	MOV	DL,DH
   133 0000001E 30F6                    	XOR	DH,DH
   134 00000020 C3                      	return
   135                                  EndProc GetExtent
   136                                  
   137                                  Break <SetExtent - update the extent/NR field>
   138                                  
   139                                  ;
   140                                  ;   SetExtent - change the position of an FCB by filling in the extent/NR
   141                                  ;	fields
   142                                  ;
   143                                  ;   Inputs:	DS:SI point to FCB
   144                                  ;		DX:AX is a record location in file
   145                                  ;   Outputs:	Extent/NR fields are filled in
   146                                  ;   Registers modified: CX
   147                                  
   148                                  Procedure SetExtent,NEAR
   148          ******************       warning: proc SetExtent... [-w+user]
   149                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   150 00000021 5052                    	SaveReg <AX,DX>
   151 00000023 89C1                    	MOV	CX,AX
   152 00000025 247F                    	AND	AL,7FH			; next rec field
   153 00000027 884420                  	MOV	[SI + fcb_NR],AL
   154 0000002A 80E180                  	AND	CL,80H			; save upper bit
   155 0000002D D1E1                    	SHL	CX,1
   156 0000002F D1D2                    	RCL	DX,1			; move high bit of CX to low bit of DX
   157 00000031 88E8                    	MOV	AL,CH
   158 00000033 88D4                    	MOV	AH,DL
   159 00000035 89440C                  	MOV	[SI + fcb_EXTENT],AX	; all done
   160 00000038 5A58                    	RestoreReg  <DX,AX>
   161 0000003A C3                      	return
   162                                  EndProc SetExtent
   163                                  
   164                                  Break <GetExtended - find FCB in potential extended fcb>
   165                                  
   166                                  ;
   167                                  ;   GetExtended - Make DS:SI point to FCB from DS:DX
   168                                  ;
   169                                  ;   Inputs:	DS:DX point to a possible extended FCB
   170                                  ;   Outputs:	DS:SI point to the FCB part
   171                                  ;		zeroflag set if not extended fcb
   172                                  ;   Registers modified: SI
   173                                  
   174                                  Procedure   GetExtended,NEAR
   174          ******************       warning: proc GetExtended... [-w+user]
   175                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   176 0000003B 89D6                    	MOV	SI,DX			; point to Something
   177 0000003D 803CFF                  	CMP	BYTE PTR [SI],-1	; look for extention
   178 00000040 7503                    	JNZ	GetBye			; not there
   179 00000042 83C607                  	ADD	SI,7			; point to FCB
   180                                  GetBye:
   181 00000045 39D6                    	CMP	SI,DX			; set condition codes
   182 00000047 C3                      	return
   183                                  EndProc GetExtended
   184                                  
   185                                  Break <GetRecSize - return in BX the FCB record size>
   186                                  
   187                                  ;
   188                                  ;   GetRecSize - return in BX the record size from the FCB at DS:SI
   189                                  ;
   190                                  ;   Inputs:	DS:SI point to a non-extended FCB
   191                                  ;   Outputs:	BX contains the record size
   192                                  ;   Registers modified: None
   193                                  
   194                                  Procedure   GetRecSize,NEAR
   194          ******************       warning: proc GetRecSize... [-w+user]
   195                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   196 00000048 8B5C0E                  	MOV	BX,[SI + fcb_RECSIZ]	; get his record size
   197 0000004B 09DB                    	OR	BX,BX			; is it nul?
   198 0000004D 75F8                    	retnz
   199 0000004F BB8000                  	MOV	BX,128			; use default size
   200 00000052 895C0E                  	MOV	[SI + fcb_RECSIZ],BX	; stuff it back
   201 00000055 C3                      	return
   202                                  EndProc GetRecSize
   203                                  
   204                                  BREAK <FCBIO - do internal FCB I/O>
   205                                  
   206                                  ;
   207                                  ;   FCBIO - look at FCBOP and merge all FCB operations into a single routine.
   208                                  ;
   209                                  ;   Inputs:	FCBOP flags which operations need to be performed
   210                                  ;		DS:DX point to FCB
   211                                  ;		CX may have count of number of records to xfer
   212                                  ;   Outputs:	AL has error code
   213                                  ;   Registers modified: all
   214                                  
   215                                  Procedure   FCBIO,NEAR
   215          ******************       warning: proc FCBIO... [-w+user]
   216                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   217                                  PUBLIC FCBIO001S,FCBIO001E
   218                                  FCBIO001S:
   219                                  	LocalVar    FCBErr,BYTE
   220                                  	LocalVar    cRec,WORD
   221                                  	LocalVar    RecPos,DWORD
   222                                  	LocalVar    RecSize,WORD
   223                                  	LocalVar    bPos,DWORD
   224                                  	LocalVar    cByte,WORD
   225                                  	LocalVar    cResult,WORD
   226                                  	LocalVar    cRecRes,WORD
   227                                  	LocalVar    FCBOp,BYTE
   228                                  FCBIO001E:
   229 00000056 5589E583EC14            	Enter
   230                                  
   231                                  FEOF	EQU	1
   232                                  FTRIM	EQU	2
   233 0000005C 8846EC                  	MOV	[FCBOp],AL
   234 0000005F C646FF00                	MOV	byte [FCBErr],0		;   FCBErr = 0;
   235 00000063 E8D5FF                  	invoke	GetExtended		;   FCB = GetExtended ();
   236                                  BLOCK equ Block	; NASM port equate
   237 00000066 F646EC08                	TEST	byte [FCBOp],BLOCK		;   if ((OP&BLOCK) == 0)
   238 0000006A 7503                    	JNZ	GetPos
   239 0000006C B90100                  	MOV	CX,1			;	cRec = 1;
   240                                  GetPos:
   241 0000006F 894EFD                  	MOV	[cRec],CX 		;*Tail coalesce
   242 00000072 E899FF                  	invoke	GetExtent		;   RecPos = GetExtent ();
   243 00000075 E8D0FF                  	invoke	GetRecSize		;   RecSize = GetRecSize ();
   244 00000078 895EF7                  	MOV	[RecSize],BX
   245                                  RANDOM equ Random	; NASM port equate
   246 0000007B F646EC02                	TEST	byte [FCBOp],RANDOM		;   if ((OP&RANDOM) <> 0)
   247 0000007F 7403                    	JZ	GetRec
   248 00000081 E87CFF                  	invoke	GetRR			;	RecPos = GetRR ();
   249                                  GetRec:
   250 00000084 8946F9                  	MOV	[RecPosL],AX		;*Tail coalesce
   251 00000087 8956FB                  	MOV	[RecPosH],DX
   252 0000008A E894FF                  	invoke	SetExtent		;   SetExtent (RecPos);
   253 0000008D 8B46FB                  	MOV	AX,[RecPosH]		;   bPos = RecPos * RecSize;
   254 00000090 F7E3                    	MUL	BX
   255 00000092 89C7                    	MOV	DI,AX
   256 00000094 8B46F9                  	MOV	AX,[RecPosL]
   257 00000097 F7E3                    	MUL	BX
   258 00000099 01FA                    	ADD	DX,DI
   259 0000009B 8946F3                  	MOV	[bPosL],AX
   260 0000009E 8956F5                  	MOV	[bPosH],DX
   261 000000A1 8B46FD                  	MOV	AX,[cRec] 		;   cByte = cRec * RecSize;
   262 000000A4 F7E3                    	MUL	BX
   263 000000A6 8946F1                  	MOV	[cByte],AX
   264 000000A9 360306[0000]            	ADD	AX,WORD PTR [ss:DMAAdd]	;   if (cByte+DMA > 64K) {
   265 000000AE 83D200                  	ADC	DX,0
   266 000000B1 7419                    	JZ	DoOper
   267 000000B3 C646FF02                	MOV	byte [FCBErr],FTRIM		;	FCBErr = FTRIM;
   268 000000B7 36A1[0000]              	MOV	AX,WORD PTR [ss:DMAAdd]	;	cRec = (64K-DMA)/RecSize;
   269 000000BB F7D8                    	NEG	AX
   270 000000BD 7501                    	JNZ	DoDiv
   271 000000BF 48                      	DEC	AX
   272                                  DoDiv:
   273 000000C0 31D2                    	XOR	DX,DX
   274 000000C2 F7F3                    	DIV	BX
   275 000000C4 8946FD                  	MOV	[cRec],AX
   276 000000C7 F7E3                    	MUL	BX			;	cByte = cRec * RecSize;
   277 000000C9 8946F1                  	MOV	[cByte],AX		;	}
   278                                  DoOper:
   279 000000CC 31DB                    	XOR	BX,BX
   280 000000CE 895EEF                  	MOV	[cResult],BX		;   cResult = 0;
   281 000000D1 395EF1                  	CMP	[cByte],BX		;   if (cByte <> 0 ||
   282 000000D4 7508                    	JNZ	DoGetExt
   283 000000D6 F646FF02                	TEST	byte [FCBErr],FTRIM		;	(FCBErr&FTRIM) == 0) {
   284                                  %IF debug
   285                                  	JZ	DoGetExt
   286                                  	JMP	SkipOp
   287                                  %ELSE
   288 000000DA 7402                    	JZ	SKP_SkipOp
   289 000000DC EB76                    	JMP	SkipOp
   290                                  SKP_SkipOp:
   291                                  %ENDIF
   292                                  DoGetExt:
   293 000000DE E8(0000)                	invoke	SFTFromFCB		;	if (!SFTFromFCB (SFT,FCB))
   294 000000E1 730F                    	JNC	ContinueOp
   295                                  FCBDeath:
   296 000000E3 E8(0000)                	invoke	FCB_Ret_Err		; signal error, map for extended
   297 000000E6 C746ED0000              	MOV	word [cRecRes],0		; no bytes transferred
   298 000000EB C646FF01                	MOV	byte [FCBErr],FEOF		;	    return FTRIM;
   299 000000EF E9F000                  	JMP	FCBSave 		; bam!
   300                                  ContinueOp:
   301                                  	Assert	ISSFT,<ES,DI>,"ContinueOP"
   302                                  fcb_filsiz equ fcb_FILSIZ	; NASM port label
   303 000000F2 8B4410                  	MOV	AX,WORD PTR [SI + fcb_filsiz]
   304 000000F5 26894511                	MOV	WORD PTR [ES:DI + sf_size],AX
   305 000000F9 8B4412                  	MOV	AX,WORD PTR [SI + fcb_filsiz + 2]
   306 000000FC 26894513                	MOV	WORD PTR [ES:DI + sf_size + 2],AX
   307 00000100 8B46F3                  	MOV	AX,[bPosL]
   308 00000103 8B56F5                  	MOV	DX,[bPosH]
   309 00000106 26894515                	MOV	WORD PTR [ES:DI + sf_position],AX
   310 0000010A 26875517                	XCHG	WORD PTR [ES:DI + sf_position+2],DX
   311 0000010E 52                      	PUSH	DX			; save away Open age.
   312 0000010F 8B4EF1                  	MOV	CX,[cByte]		;	cResult =
   313                                  
   314                                  ;	int	3
   315                                  
   316                                  DOSGroup equ DOSGROUP	; NASM port equate
   317 00000112 BF[0000]                	MOV	DI,OFFSET DOS_Read	;	    *(OP&FCBRead ? DOS_Read
   318 00000115 F646EC04                	TEST	byte [FCBOp],FCBRead	;			 : DOS_Write)(cRec);
   319 00000119 7503                    	JNZ	DoContext
   320 0000011B BF[0000]                	MOV	DI,OFFSET DOS_Write
   321                                  DoContext:
   322 0000011E 551E56                  	SaveReg <BP,DS,SI>
   323 00000121 161F                    	Context DS
   324                                  ;; Fix for disk full
   325 00000123 FFD7                    	CALL	DI
   326 00000125 5E1F5D                  	RestoreReg  <SI,DS,BP>
   327                                  	ASSUME	DS:NOTHING
   328                                  
   329                                  %ifndef BUF2
   330                                  %IF	BUFFERFLAG
   331                                  	pushf
   332                                  	push	ax
   333                                  	push	bx
   334                                  
   335                                  	cmp	byte [ss:BUF_EMS_MODE], -1
   336                                  	jz	dos_fcb_call_done
   337                                  	call	restore_user_map
   338                                  	mov	ax, word ptr [ss:BUF_EMS_LAST_PAGE]
   339                                  	cmp	[ss:BUF_EMS_PFRAME], ax
   340                                  	je	dos_fcb_call_done
   341                                  	mov	word ptr [ss:LASTBUFFER], -1
   342                                  	mov	[ss:BUF_EMS_PFRAME], ax
   343                                  	mov	ax, word ptr [ss:BUF_EMS_LAST_PAGE+2]
   344                                  	mov	[ss:BUF_EMS_PAGE_FRAME], ax
   345                                  	mov	byte [ss:BUF_EMS_SAFE_FLAG], 1
   346                                  	call	Setup_EMS_Buffers
   347                                  
   348                                  dos_fcb_call_done:
   349                                  	pop	bx
   350                                  	pop	ax
   351                                  	popf
   352                                  %ENDIF
   353                                  %endif
   354                                  
   355 00000128 72B9                    	JC	FCBDeath
   356                                  
   357 0000012A 36803E[0000]00          	CMP	BYTE PTR [ss:DISK_FULL],0	; treat disk full as error
   358 00000130 740A                    	JZ	NODSKFULL
   359 00000132 36C606[0000]00          	MOV	BYTE PTR [ss:DISK_FULL],0	; clear the flag
   360 00000138 C646FF01                	MOV	byte [FCBerr],FEOF		; set disk full flag
   361                                  NODSKFULL:
   362                                  ;; Fix for disk full
   363 0000013C 894EEF                  	MOV	[cResult],CX
   364 0000013F E8(0000)                	invoke	SaveFCBInfo		;	SaveFCBInfo (FCB);
   365                                  	Assert	ISSFT,<ES,DI>,"FCBIO/SaveFCBInfo"
   366                                  %warning out: WARNING!!! Make sure sf_position+2 is OpenAGE
   366          ******************       warning: out: WARNING!!! Make sure sf_position+2 is OpenAGE [-w+user]
   367                                  sf_Position equ sf_position	; NASM port label
   368 00000142 268F4517                	POP	WORD PTR [ES:DI + sf_Position + 2]	; restore open age
   369 00000146 268B4511                	MOV	AX,WORD PTR [ES:DI + sf_size]
   370 0000014A 894410                  	MOV	WORD PTR [SI + fcb_filsiz],AX
   371 0000014D 268B4513                	MOV	AX,WORD PTR [ES:DI + sf_size + 2]
   372 00000151 894412                  	MOV	WORD PTR [SI + fcb_filsiz + 2],AX
   373                                  					;	}
   374                                  SkipOp:
   375 00000154 8B46EF                  	MOV	AX,[cResult]		;   cRecRes = cResult / RecSize;
   376 00000157 31D2                    	XOR	DX,DX
   377 00000159 F776F7                  	DIV	word [RecSize]
   378 0000015C 8946ED                  	MOV	[cRecRes],AX
   379 0000015F 0146F9                  	ADD	[RecPosL],AX		;   RecPos += cRecResult;
   380 00000162 8356FB00                	ADC	word [RecPosH],0
   381                                  ;
   382                                  ; If we have not gotten the expected number of records, we signal an EOF
   383                                  ; condition.  On input, this is EOF.  On output this is usually disk full.
   384                                  ; BUT...  Under 2.0 and before, all device output IGNORED this condition.  So
   385                                  ; do we.
   386                                  ;
   387 00000166 3B46FD                  	CMP	AX,[cRec] 		;   if (cRecRes <> cRec)
   388 00000169 7412                    	JZ	TryBlank
   389 0000016B F646EC04                	TEST	byte [FCBOp],FCBRead		;	if (OP&FCBRead || !DEVICE)
   390 0000016F 7508                    	JNZ	SetEOF
   391 00000171 26F745058000            	TEST	word [ES:DI + sf_flags],devid_device
   392 00000177 7504                    	JNZ	TryBlank
   393                                  SetEOF:
   394 00000179 C646FF01                	MOV	byte [FCBErr],FEOF		;	FCBErr = FEOF;
   395                                  TryBlank:				;
   396 0000017D 09D2                    	OR	DX,DX			;   if (cResult%RecSize <> 0) {
   397 0000017F 7426                    	JZ	SetExt
   398 00000181 8346F901                	ADD	word [RecPosL],1		;	RecPos++;
   399 00000185 8356FB00                	ADC	word [RecPosH],0
   400 00000189 F646EC04                	TEST	byte [FCBOp],FCBRead		;	if(OP&FCBRead) <> 0) {
   401 0000018D 7418                    	JZ	SetExt
   402 0000018F FF46ED                  	INC	word [cRecRes] 		;	cRecRes++;
   403 00000192 C646FF03                	MOV	byte [FCBErr],FTRIM + FEOF	;	FCBErr = FTRIM | FEOF;
   404 00000196 8B4EF7                  	MOV	CX,[RecSize]		;	Blank (RecSize-cResult%RecSize,
   405 00000199 29D1                    	SUB	CX,DX			;	       DMA+cResult);
   406 0000019B 30C0                    	XOR	AL,AL
   407 0000019D 36C43E[0000]            	LES	DI,[ss:DMAAdd]
   408 000001A2 037EEF                  	ADD	DI,[cResult]
   409 000001A5 F3AA                    	REP	STOSB			;   }	}
   410                                  SetExt:
   411 000001A7 8B56FB                  	MOV	DX,[RecPosH]
   412 000001AA 8B46F9                  	MOV	AX,[RecPosL]
   413 000001AD F646EC02                	TEST	byte [FCBOp],RANDOM		;   if ((OP&Random) == 0 ||
   414 000001B1 7406                    	JZ	DoSetExt
   415 000001B3 F646EC08                	TEST	byte [FCBOp],BLOCK		;	(OP&BLOCK) <> 0)
   416 000001B7 7403                    	JZ	TrySetRR
   417                                  DoSetExt:
   418 000001B9 E865FE                  	invoke	SetExtent		;	SetExtent (RecPos, FCB);
   419                                  TrySetRR:
   420 000001BC F646EC08                	TEST	byte [FCBOp],BLOCK		;   if ((op&BLOCK) <> 0)
   421 000001C0 740F                    	JZ	TryReturn
   422 000001C2 894421                  	MOV	WORD PTR [SI + FCB_RR],AX ;	FCB->RR = RecPos;
   423 000001C5 885423                  	MOV	BYTE PTR [SI + FCB_RR+2],DL
   424 000001C8 837C0E40                	CMP	word [SI + fcb_RECSIZ],64
   425 000001CC 7303                    	JAE	TryReturn
   426 000001CE 887424                  	MOV	[SI+fcb_RR+2+1],DH	; Set 4th byte only if record size < 64
   427                                  TryReturn:
   428 000001D1 F646EC04                	TEST	byte [FCBOP],FCBRead		;   if (!(FCBOP & FCBREAD)) {
   429 000001D5 750B                    	JNZ	FCBSave
   430 000001D7 1E                      	SaveReg <DS>			;	FCB->FDate = date;
   431 000001D8 E8(0000)                	Invoke	Date16			;	FCB->FTime = time;
   432 000001DB 1F                      	RestoreReg  <DS>
   433                                  FCB_FDate equ fcb_FDATE	; NASM port label
   434 000001DC 894414                  	MOV	[SI + FCB_FDate],AX
   435                                  FCB_FTime equ fcb_FTIME	; NASM port label
   436 000001DF 895416                  	MOV	[SI + FCB_FTime],DX	;	}
   437                                  FCBSave:
   438 000001E2 F646EC08                	TEST	byte [FCBOp],BLOCK		;   if ((op&BLOCK) <> 0)
   439 000001E6 7409                    	JZ	DoReturn
   440 000001E8 8B4EED                  	MOV	CX,[cRecRes]		;	user_CX = cRecRes;
   441 000001EB E8(0000)                	invoke	Get_User_Stack
   442                                  User_CX equ user_CX	; NASM port label
   443 000001EE 894C04                  	MOV	[SI + User_CX],CX
   444                                  DoReturn:
   445 000001F1 8A46FF                  	MOV	AL,[FCBErr]		;   return (FCBERR);
   446 000001F4 89EC5D                  	Leave
   447 000001F7 C3                      	return
   448                                  EndProc FCBIO
   449                                  
   450                                  Break <$FCB_Open - open an old-style FCB>
   451                                  
   452                                  ;
   453                                  ;   $FCB_Open - CPM compatability file open.  The user has formatted an FCB
   454                                  ;	for us and asked to have the rest filled in.
   455                                  ;
   456                                  ;   Inputs:	DS:DX point to an unopenned FCB
   457                                  ;   Outputs:	AL indicates status 0 is ok FF is error
   458                                  ;		FCB has the following fields filled in:
   459                                  ;		    Time/Date Extent/NR Size
   460                                  
   461                                  Procedure D_FCB_Open,NEAR
   461          ******************       warning: proc D_FCB_Open... [-w+user]
   462                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP
   463                                  sharing_Compat equ sharing_compat	; NASM port equate
   464                                  Open_For_Both equ open_for_both	; NASM port equate
   465 000001F8 B80200                  	MOV	AX,sharing_Compat+Open_For_Both
   466 000001FB B9[0000]                	MOV	CX,OFFSET DOS_Open
   467                                  ;
   468                                  ; The following is common code for Creation and openning of FCBs.  AX is
   469                                  ; either attributes (for create) or open mode (for open)...  DS:DX points to
   470                                  ; the FCB
   471                                  ;
   472                                  DoAccess:
   473 000001FE 1E525150                	SaveReg <DS,DX,CX,AX>		; save FCB pointer away
   474 00000202 BF[0000]                	MOV	DI,OFFSET OpenBuf wrt DOSGroup
   475 00000205 E8(0000)                	invoke	TransFCB		; crunch the fcb
   476 00000208 58595A1F                	RestoreReg  <AX,CX,DX,DS>	; get fcb
   477 0000020C 7303                    	JNC	FindFCB 		; everything seems ok
   478                                  FCBOpenErr:
   479                                  ;
   480                                  ; AL has error code
   481                                  ;
   482 0000020E E9(0000)                	transfer    FCB_Ret_Err
   483                                  FindFCB:
   484 00000211 E827FE                  	invoke	GetExtended		; DS:SI will point to FCB
   485 00000214 E8(0000)                	invoke	LRUFCB			; get a sft entry (no error)
   486 00000217 722A                    	JC	HardMessage
   487                                  	ASSUME	ES:NOTHING
   488                                  
   489                                  ;	Message 1,"Entering "
   490                                  ;	MessageNum  ES
   491                                  ;	Message 1,":"
   492                                  ;	MessageNum  DI
   493                                  ;	Message 1,<13,10>
   494                                  
   495                                  sf_ISFCB equ sf_isfcb	; NASM port equate
   496 00000219 26C745020080            	MOV	word [ES:DI + sf_mode],sf_ISFCB
   497 0000021F 1E5653                  	SaveReg <DS,SI,BX>		; save fcb pointer
   498 00000222 89CE                    	MOV	SI,CX
   499 00000224 161F                    	Context DS			; let DOS_Open see variables
   500 00000226 FFD6                    	CALL	SI			; go open the file
   501 00000228 5B5E1F                  	RestoreReg  <BX,SI,DS>		; get fcb
   502                                  	ASSUME	DS:NOTHING
   503 0000022B 36C43E[0000]            	LES	DI,[ss:ThisSFT]		; get sf pointer
   504 00000230 7318                    	JNC	FCBOK			; operation succeeded
   505                                  	Assert	ISSFT,<ES,DI>,"DeadFCB"
   506                                  failopen:
   507 00000232 50                      	PUSH	AX
   508 00000233 B052                    	MOV	AL,"R"                  ; clear out field (free sft)
   509 00000235 E8(0000)                	invoke	BlastSFT
   510 00000238 58                      	POP	AX
   511 00000239 83F804                  	CMP	AX,error_too_many_open_files
   512 0000023C 7405                    	JZ	HardMessage
   513 0000023E 83F824                  	CMP	AX,error_sharing_buffer_exceeded
   514 00000241 7505                    	jnz	DeadFCB
   515                                  HardMessage:
   516 00000243 50                      	PUSH	AX
   517 00000244 E8(0000)                	invoke	FCBHardErr
   518 00000247 58                      	POP	AX
   519                                  DeadFCB:
   520 00000248 EBC4                    	transfer    FCB_Ret_Err
   521                                  FCBOK:
   522 0000024A E8(0000)                	invoke	IsSFTNet		       ;AN007;F.C. >32mb  Non Fat file?
   523 0000024D 7511                    	JNZ	FCBOK2			       ;AN007;F.C. >32mb  yes
   524 0000024F E8(0000)                	invoke	CheckShare		       ;AN000;F.C. >32mb  share around?
   525 00000252 750C                    	JNZ	FCBOK2			       ;AN000;F.C. >32mb  yes
   526 00000254 26837D1D00              	CMP	WORD PTR [ES:DI + sf_dirsec + 2],0 ;AN000;F.C. >32mb  if dirsec >32mb
   527 00000259 7405                    	JZ	FCBOK2			       ;AN000;F.C. >32mb    then error
   528 0000025B B85A00                  	MOV	AX,error_sys_comp_not_loaded   ;AN000;F.C. >32mb
   529 0000025E EBD2                    	JMP	failopen		       ;AN000;F.C. >32mb
   530                                  FCBOK2:
   531                                  
   532 00000260 26FF05                  	INC	word [ES:DI + sf_ref_count]	; increment reference count
   533 00000263 E8(0000)                	invoke	SaveFCBInfo
   534                                  	Assert	ISSFT,<ES,DI>,"FCBOK"
   535 00000266 E8(0000)                	invoke	SetOpenAge
   536                                  	Assert	ISSFT,<ES,DI>,"FCBOK/SetOpenAge"
   537 00000269 26F745058000            	TEST	word [ES:DI + sf_flags],devid_device
   538 0000026F 7509                    	JNZ	FCBNoDrive		; do not munge drive on devices
   539 00000271 8A04                    	MOV	AL,[SI]		; get drive byte
   540 00000273 E8(0000)                	invoke	GetThisDrv		; convert
   541 00000276 FEC0                    	INC	AL
   542 00000278 8804                    	MOV	[SI],AL		; stash in good drive letter
   543                                  FCBNoDrive:
   544                                  FCB_RecSiz equ fcb_RECSIZ	; NASM port label
   545 0000027A C7440E8000              	MOV	word [SI + FCB_RecSiz],80h	; stuff in default record size
   546                                  SF_Time equ sf_time	; NASM port label
   547 0000027F 268B450D                	MOV	AX,[ES:DI + SF_Time]	; set time
   548 00000283 894416                  	MOV	[SI + FCB_FTime],AX
   549                                  SF_Date equ sf_date	; NASM port label
   550 00000286 268B450F                	MOV	AX,[ES:DI + SF_Date]	; set date
   551 0000028A 894414                  	MOV	[SI + FCB_FDate],AX
   552                                  SF_Size equ sf_size	; NASM port label
   553 0000028D 268B4511                	MOV	AX,WORD PTR [ES:DI + SF_Size] ; set sizes
   554                                  FCB_FILSIZ equ fcb_FILSIZ	; NASM port label
   555 00000291 894410                  	MOV	[SI + FCB_FILSIZ],AX
   556 00000294 268B4513                	MOV	AX,WORD PTR [ES:DI + SF_Size + 2]
   557 00000298 894412                  	MOV	[SI + FCB_FILSIZ + 2],AX
   558 0000029B 31C0                    	XOR	AX,AX			; convenient zero
   559                                  FCB_Extent equ fcb_EXTENT	; NASM port label
   560 0000029D 89440C                  	MOV	[SI + FCB_Extent],AX	; point to beginning of file
   561                                  ;
   562                                  ; We must scan the set of FCB SFTs for one that appears to match the current
   563                                  ; one.	We cheat and use CheckFCB to match the FCBs.
   564                                  ;
   565                                  SFTFCB equ sftFCB	; NASM port label
   566 000002A0 36C43E[0000]            	LES	DI,[ss:SFTFCB]		; get the pointer to head of the list
   567                                  sfCount equ SFCount	; NASM port label
   568 000002A5 268A6504                	MOV	AH,BYTE PTR [ES:DI + sfCount] ; get number of SFTs to scan
   569                                  OpenScan:
   570 000002A9 3A4418                  	CMP	AL,[SI + fcb_sfn] 	; don't compare ourselves
   571 000002AC 7407                    	JZ	SkipCheck
   572 000002AE 50                      	SaveReg <AX>			; preserve count
   573 000002AF E8(0000)                	invoke	CheckFCB		; do they match
   574 000002B2 58                      	RestoreReg  <AX>		; get count back
   575 000002B3 7309                    	JNC	OpenFound		; found a match!
   576                                  SkipCheck:
   577 000002B5 FEC0                    	INC	AL			; advance to next FCB
   578 000002B7 38E0                    	CMP	AL,AH			; table full?
   579 000002B9 75EE                    	JNZ	OpenScan		; no, go for more
   580                                  OpenDone:
   581 000002BB 30C0                    	xor	al,al			; return success
   582 000002BD C3                      	return
   583                                  ;
   584                                  ; The SFT at ES:DI is the one that is already in use for this FCB.  We set the
   585                                  ; FCB to use this one.	We increment its ref count.  We do NOT close it at all.
   586                                  ; Consider:
   587                                  ;
   588                                  ;   open (foo)	delete (foo) open (bar)
   589                                  ;
   590                                  ; This causes us to recycle (potentially) bar through the same local SFT as
   591                                  ; foo even though foo is no longer needed; this is due to the server closing
   592                                  ; foo for us when we delete it.  Unfortunately, we cannot see this closure.
   593                                  ; If we were to CLOSE bar, the server would then close the only reference to
   594                                  ; bar and subsequent I/O would be lost to the redirector.
   595                                  ;
   596                                  ; This gets solved by NOT closing the sft, but zeroing the ref count
   597                                  ; (effectively freeing the SFT) and informing the sharer (if relevant) that
   598                                  ; the SFT is no longer in use.	Note that the SHARER MUST keep its ref counts
   599                                  ; around.  This will allow us to access the same file through multiple network
   600                                  ; connections and NOT prematurely terminate when the ref count on one
   601                                  ; connection goes to zero.
   602                                  ;
   603                                  OpenFound:
   604 000002BE 884418                  	MOV	[SI + fcb_SFN],AL 	; assign with this
   605 000002C1 26FF05                  	INC	word [ES:DI + sf_ref_count]	; remember this new invocation
   606 000002C4 36A1[0000]              	MOV	AX,[ss:FCBLRU]		; update LRU counts
   607 000002C8 26894515                	MOV	[ES:DI + sf_LRU],AX
   608                                  ;
   609                                  ; We have an FCB sft that is now of no use.  We release sharing info and then
   610                                  ; blast it to prevent other reuse.
   611                                  ;
   612 000002CC 161F                    	context DS
   613 000002CE C43E[0000]              	LES	DI,[ThisSFT]
   614 000002D2 26FF0D                  	DEC	word [ES:DI + sf_ref_count]	; free the newly allocated SFT
   615 000002D5 E8(0000)                	invoke	ShareEnd
   616                                  	Assert	ISSFT,<ES,DI>,"Open blasting"
   617 000002D8 B043                    	MOV	AL,'C'
   618 000002DA E8(0000)                	invoke	BlastSFT
   619 000002DD EBDC                    	JMP	OpenDone
   620                                  EndProc D_FCB_Open
   621                                  
   622                                  BREAK	<$FCB_Create - create a new directory entry>
   623                                  
   624                                  ;
   625                                  ;   $FCB_Create - CPM compatability file create.  The user has formatted an
   626                                  ;	FCB for us and asked to have the rest filled in.
   627                                  ;
   628                                  ;   Inputs:	DS:DX point to an unopenned FCB
   629                                  ;   Outputs:	AL indicates status 0 is ok FF is error
   630                                  ;		FCB has the following fields filled in:
   631                                  ;		    Time/Date Extent/NR Size
   632                                  
   633                                  Procedure D_FCB_Create,NEAR
   633          ******************       warning: proc D_FCB_Create... [-w+user]
   634                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   635 000002DF B9[0000]                	MOV	CX,OFFSET DOS_Create	; routine to call
   636 000002E2 31C0                    	XOR	AX,AX			; attributes to create
   637 000002E4 E854FD                  	invoke	GetExtended		; get extended FCB
   638 000002E7 7403                    	JZ	DoAccessJ		; not an extended FCB
   639 000002E9 8A44FF                  	MOV	AL,[SI-1]		; get attributes
   640                                  DoAccessJ:
   641 000002EC E90FFF                  	JMP	DoAccess		; do dirty work
   642                                  EndProc D_FCB_Create
   643                                  
   644                                  BREAK <$FCB_Random_write_Block - write a block of records to a file >
   645                                  
   646                                  ;
   647                                  ;   $FCB_Random_Write_Block - retrieve a location from the FCB, seek to it
   648                                  ;	and write a number of blocks from it.
   649                                  ;
   650                                  ;   Inputs:	DS:DX point to an FCB
   651                                  ;   Outputs:	AL = 0 write was successful and the FCB position is updated
   652                                  ;		AL <> 0 Not enough room on disk for the output
   653                                  ;
   654                                  
   655                                  Procedure D_FCB_Random_Write_Block,NEAR
   655          ******************       warning: proc D_FCB_Random_Write_Block... [-w+user]
   656                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   657 000002EF B00A                    	MOV	AL,Random+Block
   658 000002F1 E962FD                  	JMP	FCBIO
   659                                  EndProc D_FCB_Random_Write_Block
   660                                  
   661                                  BREAK <$FCB_Random_Read_Block - read a block of records to a file >
   662                                  
   663                                  ;
   664                                  ;   $FCB_Random_Read_Block - retrieve a location from the FCB, seek to it
   665                                  ;	and read a number of blocks from it.
   666                                  ;
   667                                  ;   Inputs:	DS:DX point to an FCB
   668                                  ;   Outputs:	AL = error codes defined above
   669                                  ;
   670                                  
   671                                  Procedure D_FCB_Random_Read_Block,NEAR
   671          ******************       warning: proc D_FCB_Random_Read_Block... [-w+user]
   672                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   673 000002F4 B00E                    	MOV	AL,Random+FCBRead+Block
   674 000002F6 E95DFD                  	JMP	FCBIO
   675                                  EndProc D_FCB_Random_Read_Block
   676                                  
   677                                  BREAK <$FCB_Seq_Read - read the next record from a file >
   678                                  
   679                                  ;
   680                                  ;   $FCB_Seq_Read - retrieve the next record from an FCB and read it into
   681                                  ;	memory
   682                                  ;
   683                                  ;   Inputs:	DS:DX point to an FCB
   684                                  ;   Outputs:	AL = error codes defined above
   685                                  ;
   686                                  
   687                                  Procedure D_FCB_Seq_Read,NEAR
   687          ******************       warning: proc D_FCB_Seq_Read... [-w+user]
   688                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   689 000002F9 B004                    	MOV	AL,FCBRead
   690 000002FB E958FD                  	JMP	FCBIO
   691                                  EndProc D_FCB_Seq_Read
   692                                  
   693                                  BREAK <$FCB_Seq_Write - write the next record to a file >
   694                                  
   695                                  ;
   696                                  ;   $FCB_Seq_Write - retrieve the next record from an FCB and write it to the
   697                                  ;	file
   698                                  ;
   699                                  ;   Inputs:	DS:DX point to an FCB
   700                                  ;   Outputs:	AL = error codes defined above
   701                                  ;
   702                                  
   703                                  Procedure D_FCB_Seq_Write,NEAR
   703          ******************       warning: proc D_FCB_Seq_Write... [-w+user]
   704                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   705 000002FE B000                    	MOV	AL,0
   706 00000300 E953FD                  	jmp	FCBIO
   707                                  EndProc D_FCB_SEQ_WRITE
   708                                  
   709                                  BREAK <$FCB_Random_Read - Read a single record from a file >
   710                                  
   711                                  ;
   712                                  ;   $FCB_Random_Read - retrieve a location from the FCB, seek to it and read a
   713                                  ;	record from it.
   714                                  ;
   715                                  ;   Inputs:	DS:DX point to an FCB
   716                                  ;   Outputs:	AL = error codes defined above
   717                                  ;
   718                                  
   719                                  Procedure D_FCB_Random_Read,NEAR
   719          ******************       warning: proc D_FCB_Random_Read... [-w+user]
   720                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   721 00000303 B006                    	MOV	AL,Random+FCBRead
   722 00000305 E94EFD                  	jmp	FCBIO			; single block
   723                                  EndProc D_FCB_RANDOM_READ
   724                                  
   725                                  BREAK <$FCB_Random_Write - write a single record to a file >
   726                                  
   727                                  ;
   728                                  ;   $FCB_Random_Write - retrieve a location from the FCB, seek to it and write
   729                                  ;	a record to it.
   730                                  ;
   731                                  ;   Inputs:	DS:DX point to an FCB
   732                                  ;   Outputs:	AL = error codes defined above
   733                                  ;
   734                                  
   735                                  Procedure D_FCB_Random_Write,NEAR
   735          ******************       warning: proc D_FCB_Random_Write... [-w+user]
   736                                   ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGroup
   737 00000308 B002                    	MOV	AL,Random
   738 0000030A E949FD                  	jmp	FCBIO
   739                                  EndProc D_FCB_RANDOM_WRITE
   740                                  
   741                                  END
   742                                  
   743                                  
   744                                  
   745                                  
