     1                                  ;	SCCSID = @(#)IOCTL.INC	1.15 85/09/05
     2                                  ;TITLE	IOCTL - IOCTL system call
     3                                  ;NAME	IOCTL
     4                                  
     5                                  ;
     6                                  ;
     7                                  ; IOCTL system call.
     8                                  ;
     9                                  ;
    10                                  ; $IOCTL
    11                                  ;
    12                                  ;   Revision history:
    13                                  ;
    14                                  ;	Created: ARR 4 April 1983
    15                                  ;
    16                                  ;	GenericIOCTL added:		KGS	22 April 1985
    17                                  ;
    18                                  ;	A000	version 4.00	Jan. 1988
    19                                  
    20                                  
    21                                  
    22                                  [list -]
    22          ******************       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
    27                                  
    28                                  [list +]
    29                                  section DOSCODECODE
    30                                  [list -]
    30          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    30          ******************       warning: out: BPB.INC... [-w+user]
    30          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    30          ******************       warning: out: DEVSYM.INC... [-w+user]
    30          ******************       warning: out: IOCTL.INC... [-w+user]
    30          ******************       warning: out: BPB.INC... [-w+user]
    39                                  
    40                                  	i_need	THISCDS,DWORD
    41                                  	i_need	IOCALL,BYTE
    42                                  	i_need	IOMED,BYTE
    43                                  	i_need	IOSCNT,WORD
    44                                  	i_need	IOXAD,DWORD
    45                                  	I_need	RetryCount,WORD
    46                                  	I_need	RetryLoop,WORD
    47                                  	I_need	EXTERR_LOCUS,BYTE
    48                                  	I_need	OPENBUF,BYTE
    49                                  	I_need	ExtErr,WORD
    50                                  	I_need	DrvErr,BYTE
    51                                  	I_need	USER_IN_AX,WORD 		;AN000;
    52                                  	I_need	Temp_Var2,WORD			;AN000;
    53                                  
    54                                   assume nocheck, ss:DOSGROUP
    55                                  
    56                                  BREAK <IOCTL - munge on a handle to do device specific stuff>
    57                                  
    58                                  ;
    59                                  ;   Assembler usage:
    60                                  ;	    MOV     BX, Handle
    61                                  ;	    MOV     DX, Data
    62                                  ;
    63                                  ;	(or LDS     DX,BUF
    64                                  ;	    MOV     CX,COUNT)
    65                                  ;
    66                                  ;	    MOV     AH, Ioctl
    67                                  ;	    MOV     AL, Request
    68                                  ;	    INT     21h
    69                                  ;
    70                                  ;   AH = 0  Return a combination of low byte of sf_flags and device driver
    71                                  ;	    attribute word in DX, handle in BX:
    72                                  ;	    DH = high word of device driver attributes
    73                                  ;	    DL = low byte of sf_flags
    74                                  ;	 1  Set the bits contained in DX to sf_flags.  DH MUST be 0.  Handle
    75                                  ;	    in BX.
    76                                  ;	 2  Read CX bytes from the device control channel for handle in BX
    77                                  ;	    into DS:DX.  Return number read in AX.
    78                                  ;	 3  Write CX bytes to the device control channel for handle in BX from
    79                                  ;	    DS:DX.  Return bytes written in AX.
    80                                  ;	 4  Read CX bytes from the device control channel for drive in BX
    81                                  ;	    into DS:DX.  Return number read in AX.
    82                                  ;	 5  Write CX bytes to the device control channel for drive in BX from
    83                                  ;	    DS:DX.  Return bytes written in AX.
    84                                  ;	 6  Return input status of handle in BX. If a read will go to the
    85                                  ;	    device, AL = 0FFh, otherwise 0.
    86                                  ;	 7  Return output status of handle in BX. If a write will go to the
    87                                  ;	    device, AL = 0FFh, otherwise 0.
    88                                  ;	 8  Given a drive in BX, return 1 if the device contains non-
    89                                  ;	    removable media, 0 otherwise.
    90                                  ;	 9  Return the contents of the device attribute word in DX for the
    91                                  ;	    drive in BX.  0200h is the bit for shared.	1000h is the bit for
    92                                  ;	    network. 8000h is the bit for local use.
    93                                  ;	 A  Return 8000h if the handle in BX is for the network or not.
    94                                  ;	 B  Change the retry delay and the retry count for the system. BX is
    95                                  ;	    the count and CX is the delay.
    96                                  ;
    97                                  ;   Error returns:
    98                                  ;	    AX = error_invalid_handle
    99                                  ;	       = error_invalid_function
   100                                  ;	       = error_invalid_data
   101                                  ;
   102                                  ;-------------------------------------------------------------------------------
   103                                  ;
   104                                  ;   This is the documentation copied from DOS 4.0 it is much better
   105                                  ;   than the above
   106                                  ;
   107                                  ;	There are several basic forms of IOCTL calls:
   108                                  ;
   109                                  ;
   110                                  ;	** Get/Set device information:	**
   111                                  ;
   112                                  ;	ENTRY	(AL) = function code
   113                                  ;		  0 - Get device information
   114                                  ;		  1 - Set device information
   115                                  ;		(BX) = file handle
   116                                  ;		(DX) = info for "Set Device Information"
   117                                  ;	EXIT	'C' set if error
   118                                  ;		  (AX) = error code
   119                                  ;		'C' clear if OK
   120                                  ;		  (DX) = info for "Get Device Information"
   121                                  ;	USES	ALL
   122                                  ;
   123                                  ;
   124                                  ;	**  Read/Write Control Data From/To Handle  **
   125                                  ;
   126                                  ;	ENTRY	(AL) = function code
   127                                  ;		  2 - Read device control info
   128                                  ;		  3 - Write device control info
   129                                  ;		(BX) = file handle
   130                                  ;		(CX) = transfer count
   131                                  ;		(DS:DX) = address for data
   132                                  ;	EXIT	'C' set if error
   133                                  ;		  (AX) = error code
   134                                  ;		'C' clear if OK
   135                                  ;		  (AX) = count of bytes transfered
   136                                  ;	USES	ALL
   137                                  ;
   138                                  ;
   139                                  ;	**  Read/Write Control Data From/To Block Device  **
   140                                  ;
   141                                  ;	ENTRY	(AL) = function code
   142                                  ;		  4 - Read device control info
   143                                  ;		  5 - Write device control info
   144                                  ;		(BL) = Drive number (0=default, 1='A', 2='B', etc)
   145                                  ;		(CX) = transfer count
   146                                  ;		(DS:DX) = address for data
   147                                  ;	EXIT	'C' set if error
   148                                  ;		  (AX) = error code
   149                                  ;		'C' clear if OK
   150                                  ;		  (AX) = count of bytes transfered
   151                                  ;	USES	ALL
   152                                  ;
   153                                  ;
   154                                  ;	**  Get Input/Output Status  **
   155                                  ;
   156                                  ;	ENTRY	(AL) = function code
   157                                  ;		  6 - Get Input status
   158                                  ;		  7 - Get Output Status
   159                                  ;		(BX) = file handle
   160                                  ;	EXIT	'C' set if error
   161                                  ;		  (AX) = error code
   162                                  ;		'C' clear if OK
   163                                  ;		  (AL) = 00 if not ready
   164                                  ;		  (AL) = FF if ready
   165                                  ;	USES	ALL
   166                                  ;
   167                                  ;
   168                                  ;	**  Get Drive Information  **
   169                                  ;
   170                                  ;	ENTRY	(AL) = function code
   171                                  ;		  8 - Check for removable media
   172                                  ;		  9 - Get device attributes
   173                                  ;		(BL) = Drive number (0=default, 1='A', 2='B', etc)
   174                                  ;	EXIT	'C' set if error
   175                                  ;		  (AX) = error code
   176                                  ;		'C' clear if OK
   177                                  ;		  (AX) = 0/1 media is removable/fixed (func. 8)
   178                                  ;		  (DX) = device attribute word (func. 9)
   179                                  ;	USES	ALL
   180                                  ;
   181                                  ;
   182                                  ;	**  Get Redirected bit	**
   183                                  ;
   184                                  ;	ENTRY	(AL) = function code
   185                                  ;		  0Ah - Network stuff
   186                                  ;		(BX) = file handle
   187                                  ;	EXIT	'C' set if error
   188                                  ;		  (AX) = error code
   189                                  ;		'C' clear if OK
   190                                  ;		  (DX) = SFT flags word, 8000h set if network file
   191                                  ;	USES	ALL
   192                                  ;
   193                                  ;
   194                                  ;	**  Change sharer retry parameters  **
   195                                  ;
   196                                  ;	ENTRY	(AL) = function code
   197                                  ;		  0Bh - Set retry parameters
   198                                  ;		(CX) = retry loop count
   199                                  ;		(DX) = number of retries
   200                                  ;	EXIT	'C' set if error
   201                                  ;		  (AX) = error code
   202                                  ;		'C' clear if OK
   203                                  ;	USES	ALL
   204                                  ;
   205                                  ;
   206                                  ;   =================================================================
   207                                  ;
   208                                  ;	**  New Standard Control  **
   209                                  ;
   210                                  ;	ALL NEW IOCTL FACILITIES SHOULD USE THIS FORM.	THE OTHER
   211                                  ;	FORMS ARE OBSOLETE.
   212                                  ;
   213                                  ;   =================================================================
   214                                  ;
   215                                  ;	ENTRY	(AL) = function code
   216                                  ;		  0Ch - Control Function subcode
   217                                  ;		(BX) = File Handle
   218                                  ;		(CH) = Category Indicator
   219                                  ;		(CL) = Function within category
   220                                  ;		(DS:DX) = address for data, if any
   221                                  ;		(SI) = Passed to device as argument, use depends upon function
   222                                  ;		(DI) = Passed to device as argument, use depends upon function
   223                                  ;	EXIT	'C' set if error
   224                                  ;		  (AX) = error code
   225                                  ;		'C' clear if OK
   226                                  ;		  (SI) = Return value, meaning is function dependent
   227                                  ;		  (DI) = Return value, meaning is function dependent
   228                                  ;		  (DS:DX) = Return address, use is function dependent
   229                                  ;	USES	ALL
   230                                  ;
   231                                  ;    ============== Generic IOCTL Definitions for DOS 3.2 ============
   232                                  ;     (See dos/ioctl.mac for more info)
   233                                  ;
   234                                  ;	ENTRY	(AL) = function code
   235                                  ;		  0Dh - Control Function subcode
   236                                  ;		(BL) = Drive Number (0 = Default, 1= 'A')
   237                                  ;		(CH) = Category Indicator
   238                                  ;		(CL) = Function within category
   239                                  ;		(DS:DX) = address for data, if any
   240                                  ;		(SI) = Passed to device as argument, use depends upon function
   241                                  ;		(DI) = Passed to device as argument, use depends upon function
   242                                  ;
   243                                  ;	EXIT	'C' set if error
   244                                  ;		  (AX) = error code
   245                                  ;		'C' clear if OK
   246                                  ;		  (DS:DX) = Return address, use is function dependent
   247                                  ;	USES	ALL
   248                                  ;
   249                                  
   250                                  	procedure   D_IOCTL,NEAR
   250          ******************       warning: proc D_IOCTL... [-w+user]
   251                                  	ASSUME	DS:NOTHING,ES:NOTHING
   252 00000000 8CDE                    	MOV	SI,DS			; Stash DS for calls 2,3,4 and 5
   253 00000002 161F                    	context DS
   254 00000004 3C03                    	CMP	AL,3
   255 00000006 7603                    	JBE	ioctl_check_char	; char	device
   256 00000008 E98400                  	JMP	ioctl_check_block	; Block device
   257                                  ioctl_check_char:
   258 0000000B E8(0000)                	invoke	SFFromHandle		; ES:DI -> SFT
   259 0000000E 7305                    	JNC	ioctl_check_permissions ; have valid handle
   260                                  ioctl_bad_handle:
   261 00000010 B006E9(0000)            	error	error_invalid_handle
   262                                  
   263                                  ioctl_check_permissions:
   264 00000015 3C02                    	CMP	AL,2
   265 00000017 734F                    	JAE	ioctl_control_string
   266 00000019 3C00                    	CMP	AL,0
   267 0000001B 268A4505                	MOV	AL,BYTE PTR [ES:DI + sf_flags]; Get low byte of flags
   268 0000001F 7425                    	JZ	ioctl_read		; read the byte
   269 00000021 52                      	PUSH	DX			;AN000;MS.
   270 00000022 80E6FE                  	AND	DH,0FEH 		;AN000;MS.allow DH=01H
   271 00000025 5A                      	POP	DX			;AN000;MS.
   272 00000026 7407                    	JZ	ioctl_check_device	; can I set with this data?
   273 00000028 B00DEBE6                	error	error_invalid_data	; no DH <> 0
   274                                  
   275                                  ioctl_bad_funj2:
   276 0000002C E98C01                  	JMP	ioctl_bad_fun
   277                                  
   278                                  ioctl_check_device:
   279 0000002F A880                    	TEST	AL,devid_device 	; can I set this handle?
   280 00000031 740C                    	JZ	do_exception		; no, it is a file.
   281 00000033 80CA80                  	OR	DL,devid_device 	; Make sure user doesn't turn off the
   282                                  					;   device bit!! He can muck with the
   283                                  					;   others at will.
   284 00000036 C606[0000]04            	MOV	byte [EXTERR_LOCUS],errLOC_SerDev
   285 0000003B 26885505                	MOV	BYTE PTR [ES:DI + sf_flags],DL  ;AC000;MS.; Set flags
   286                                  do_exception:
   287 0000003F 26087506                	OR	BYTE PTR [ES:DI + sf_flags+1],DH;AN000;MS.;set 100H bit for disk full
   288                                  
   289 00000043 E9(0000)                	transfer    SYS_RET_OK
   290                                  
   291                                  
   292                                  ioctl_read:
   293 00000046 C606[0000]02            	MOV	byte [EXTERR_LOCUS],errLOC_Disk
   294 0000004B 30E4                    	XOR	AH,AH
   295 0000004D A880                    	TEST	AL,devid_device 	; Should I set high byte
   296 0000004F 740D                    	JZ	ioctl_no_high		; no
   297 00000051 C606[0000]04            	MOV	byte [EXTERR_LOCUS],errLOC_SerDev
   298 00000056 26C47D07                	LES	DI,[ES:DI + sf_devptr]	; Get device pointer
   299 0000005A 268A6505                	MOV	AH,BYTE PTR [ES:DI + SDEVATT+1]	; Get high byte
   300                                  ioctl_no_high:
   301 0000005E 89C2                    	MOV	DX,AX
   302 00000060 E8(0000)                	invoke	get_user_stack
   303 00000063 895406                  	MOV	[SI + user_DX],DX
   304 00000066 EBDB                    	transfer    SYS_RET_OK
   305                                  
   306                                  ioctl_control_string:
   307 00000068 26F745058000            	TEST	word [ES:DI + sf_flags],devid_device	; can I?
   308 0000006E 7503                    	JNZ	ioctl_ctl_str_1
   309 00000070 E94801                  	JMP	ioctl_bad_fun			; No it is a file
   310                                  ioctl_ctl_str_1:
   311 00000073 26F745050080            	TEST	word [ES:DI + sf_flags],sf_isnet	;AN000;IFS.; IFS ?
   312 00000079 7403                    	JZ	localrw 			;AN000;IFS.; no
   313 0000007B E9C700                  	JMP	callifs 			;AN000;IFS.; call IFS
   314                                  localrw:
   315 0000007E C606[0000]04            	MOV	byte [EXTERR_LOCUS],errLOC_SerDev
   316 00000083 26C47D07                	LES	DI,[ES:DI + sf_devptr]	; Get device pointer
   317 00000087 30DB                    	XOR	BL,BL			; Unit number of char dev = 0
   318 00000089 E9DF01                  	JMP	ioctl_do_string
   319                                  
   320                                  ioctl_get_devj:
   321 0000008C E9D701                  	JMP	ioctl_get_dev
   322                                  
   323                                  ioctl_check_block:
   324 0000008F FEC8                    	DEC	AL
   325 00000091 FEC8                    	DEC	AL			; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9
   326 00000093 3C03                    	CMP	AL,3
   327 00000095 76F5                    	JBE	ioctl_get_devj
   328 00000097 3C06                    	CMP	AL,6
   329 00000099 731F                    	JAE	ioctl_rem_media_check
   330                                  
   331 0000009B B401                    	MOV	AH,1
   332 0000009D 2C04                    	SUB	AL,4			; 6=0,7=1
   333 0000009F 7402                    	JZ	ioctl_get_status
   334 000000A1 B403                    	MOV	AH,3
   335                                  ioctl_get_status:
   336 000000A3 50                      	PUSH	AX
   337 000000A4 E8(0000)                	invoke	GET_IO_SFT
   338 000000A7 58                      	POP	AX
   339 000000A8 7303                    	JNC	DO_IOFUNC
   340 000000AA E963FF                  	JMP	ioctl_bad_handle	; invalid SFT
   341                                  
   342                                  DO_IOFUNC:
   343 000000AD E8(0000)                	invoke	IOFUNC
   344 000000B0 88C4                    	MOV	AH,AL
   345 000000B2 B0FF                    	MOV	AL,0FFH
   346 000000B4 7502                    	JNZ	ioctl_status_ret
   347 000000B6 FEC0                    	INC	AL
   348                                  ioctl_status_ret:
   349 000000B8 EBAC                    	transfer SYS_RET_OK
   350                                  
   351                                  ioctl_rem_media_check:			; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9
   352 000000BA 7407                    	JE	ioctl_rem_mediaj
   353                                  
   354 000000BC 2C07                    	SUB	AL,7			; 9=0,10=1,11=2,12=3,13=4,14=5,15=6
   355 000000BE 7509                    	JNZ	Rem_med_chk_1
   356 000000C0 E93E01                  	JMP	Ioctl_Drive_attr
   357                                  
   358                                  ioctl_rem_mediaj:
   359 000000C3 E9FD00                  	jmp	ioctl_rem_media
   360                                  
   361                                  ioctl_bad_funj4:
   362 000000C6 E9F200                  	jmp	ioctl_bad_fun
   363                                  
   364                                  Rem_med_chk_1:
   365                                  
   366 000000C9 FEC8                    	DEC	AL			; 10=0,11=1,12=2,13=3,14=4,15=5
   367 000000CB 7503                    	jnz	Set_Retry_chk
   368                                  Ioctl_Handle_redirj equ IOCtl_Handle_RedirJ	; NASM port label
   369 000000CD E9E800                  	Jmp	Ioctl_Handle_redirj
   370                                  
   371                                  Set_Retry_chk:
   372 000000D0 FEC8                    	DEC	AL			; 11=0,12=1,13=2,14=3,15=4
   373 000000D2 7415                    	JZ	Set_Retry_Parameters
   374                                  
   375 000000D4 FEC8                    	DEC	AL			; 12=0,13=1,14=2,15=3
   376 000000D6 7422                    	JZ	GENERICIOCTLHANDLE
   377                                  
   378 000000D8 FEC8                    	DEC	AL			; 13=0,14=1,15=2
   379 000000DA 7440                    	JZ	GENERICIOCTL
   380                                  		; 14/0Eh = 1, 15/0Fh = 2, 16/10h = 3, 17/11h = 4
   381                                  
   382 000000DC 3C04                    	CMP	AL,4
   383 000000DE 77E6                    	JA	ioctl_bad_funj4
   384 000000E0 3C03                    	cmp al, 3
   385 000000E2 7738                    	ja	GENERICIOCTL
   386 000000E4 7414                    	je	GENERICIOCTLHANDLE
   387 000000E6 E94502                  	JMP	ioctl_drive_owner
   388                                  Set_Retry_Parameters:
   389 000000E9 890E[0000]              	MOV	[RetryLoop],CX		; 0 retry loop count allowed
   390 000000ED 09D2                    	OR	DX,DX			; zero retries not allowed
   391 000000EF 7503                    	JNZ	goodtr
   392                                  IoCtl_Bad_Fun equ ioctl_bad_fun	; NASM port label
   393 000000F1 E9C700                  	JMP	IoCtl_Bad_Fun
   394                                  goodtr:
   395 000000F4 8916[0000]              	MOV	[RetryCount],DX		; Set new retry count
   396                                  doneok:
   397 000000F8 EBBE                    	transfer	Sys_Ret_Ok	; Done
   398                                  
   399                                  ; Generic IOCTL entry point.
   400                                  ;	here we invoke the Generic IOCTL using the IOCTL_Req structure.
   401                                  ;	SI:DX -> Users Device Parameter Table
   402                                  ;	IOCALL -> IOCTL_Req structure
   403                                  ;	INP:	al = nonzero for query only (4410h)
   404                                  GENERICIOCTLHANDLE:
   405 000000FA E8(0000)                	invoke	SFFromHandle		; Get SFT for device.
   406 000000FD 7303                    	jnc	goodh
   407 000000FF E9BE00                  	JMP	ioctl_bad_handlej
   408                                  goodh:
   409                                  ;	test	word ptr [DI.sf_flags],sf_isnet
   410 00000102 E87202                  	CALL	TEST_IFS_REMOTE 	;AN000;;IFS. test if remote
   411 00000105 7403                    	JZ	okokok			;AN000;;IFS.
   412 00000107 E9B100                  	jmp	ioctl_bad_fun		; Cannot do this over net.
   413                                  okokok:
   414 0000010A F745050080              	TEST	word [DI + sf_flags],sf_isnet	;AN000;IFS.; local IFS
   415 0000010F 7530                    	JNZ	callifs_no_query	;AN000;IFS.; yes
   416                                  
   417                                  ErrLOC_Serdev equ errLOC_SerDev	; NASM port equate
   418 00000111 C606[0000]04            	mov	byte [EXTERR_LOCUS],ErrLOC_Serdev
   419 00000116 26C47D07                	les	di,[es:di + sf_devptr]	; Get pointer to device.
   420 0000011A EB49                    	jmp	short Do_GenIOCTL
   421                                  
   422                                  GENERICIOCTL:
   423                                  ;	INP:	al = nonzero for query only (4411h)
   424                                  ErrLOC_Disk equ errLOC_Disk	; NASM port equate
   425 0000011C C606[0000]02            	mov	byte [EXTERR_LOCUS],ErrLOC_Disk
   426 00000121 80FD08                  	cmp	ch,IOC_DC		; Only disk devices are allowed to use
   427 00000124 7403E99200              	jne	ioctl_bad_fun		; no handles with Generic IOCTL.
   428 00000129 E8D901                  	CALL	Check_If_Net		; ES:DI := Get_hdr_block of device in BL
   429                                   assume es:nothing
   430 0000012C 7403E98A00              	JNZ	ioctl_bad_fun		; There are no "net devices", and they
   431                                   assume es:nothing	; device header
   432 00000131 06                      	PUSH	ES			;   certainly don't know how to do this ;AN000;
   433 00000132 57                      	PUSH	DI				 ;AN000;IFS.
   434 00000133 C43E[0000]              	LES	DI,[THISCDS]			 ;AN000;IFS.	 ;
   435                                   assume es:nothing
   436 00000137 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet;AN000;IFS.	 ; local IFS ?
   437 0000013D 5F                      	POP	DI				 ;AN000;IFS.
   438 0000013E 07                      	POP	ES				 ;AN000;IFS.
   439                                   assume es:nothing
   440 0000013F 7424                    	JZ	Do_GenIOCTL			 ;AN000;IFS.	 ; no
   441                                  callifs_no_query:
   442 00000141 84C0                    	test al, al
   443 00000143 7576                    	jnz ioctl_bad_fun
   444                                  callifs:
   445                                  User_In_AX equ USER_IN_AX	; NASM port label
   446 00000145 803E[0100]69            	CMP	byte ptr [User_In_AX+1],69H  ;AN000;	     ;IFS.
   447 0000014A 7506                    	JNZ	is44xx			     ;AN000;	     ;IFS.
   448 0000014C B80D44                  	MOV	AX,440DH		     ;AN000;	     ;IFS.
   449 0000014F 50                      	PUSH	AX			     ;AN000;	     ;IFS.
   450 00000150 EB04                    	JMP	SHORT callrose		     ;AN000;	     ;IFS.
   451                                  is44xx:
   452 00000152 FF36[0000]              	PUSH	word [User_In_AX]		     ;AN000;	     ;IFS. call IFSFUNC
   453                                  callrose:
   454 00000156 8EDE                    	MOV	DS,SI			     ;AN000;	     ;IFS.
   455                                   assume ds:nothing
   456                                  multNET equ MultNET	; NASM port equate
   457 00000158 B82B11                  	MOV	AX,(multNET << 8) |  43    ;AN000;	     ;IFS.
   458 0000015B CD2F                    	INT	2FH			     ;AN000;	     ;IFS.
   459 0000015D 5B                      	POP	BX			     ;AN000;	     ;IFS.
   460 0000015E 7398                    	JNC	doneok			     ;AN000;	     ;IFS.
   461 00000160 89C7                    	MOV	DI,AX			     ;AN000;	     ;IFS.
   462 00000162 E95B01                  	JMP	device_err		     ;AN000;	     ;IFS.
   463                                  Do_GenIOCTL:
   464                                   assume ds:DOSGROUP
   465 00000165 26F745044000            	test	word [ES:DI + SDEVATT],DEV320	; Can device handle Generic IOCTL funcs
   466 0000016B 744E                    	jz	ioctl_bad_fun
   467 0000016D 06                      	PUSH	ES			; DEVIOCALL2 expects Device header block
   468 0000016E 57                      	PUSH	DI			; in DS:SI
   469                                  	;set up Generic IOCTL Request Block
   470                                  IOCTL_Req_struc_size equ IOCTL_REQ_struc_size	; NASM port equate
   471                                  ReqLen equ REQLEN	; NASM port equate
   472 0000016F C606[0000]17            	MOV	byte [IOCALL + ReqLen],(IOCTL_Req_struc_size)
   473                                  ReqFunc equ REQFUNC	; NASM port equate
   474 00000174 C606[0200]13            	MOV	byte [IOCALL + ReqFunc],GENIOCTL
   475 00000179 84C0                    	test al, al
   476 0000017B 7405                    	jz @F
   477 0000017D C606[0200]19            	MOV	byte [IOCALL + ReqFunc], QUERYGENIOCTL
   478                                  @@:
   479                                  ReqUnit equ REQUNIT	; NASM port equate
   480 00000182 881E[0100]              	MOV	byte ptr [IOCALL + ReqUnit],BL
   481                                  MajorFunction equ MAJORFUNCTION	; NASM port equate
   482 00000186 882E[0D00]              	MOV	byte ptr [IOCALL + MajorFunction],CH
   483                                  MinorFunction equ MINORFUNCTION	; NASM port equate
   484 0000018A 880E[0E00]              	MOV	byte ptr [IOCALL + MinorFunction],CL
   485                                  Reg_SI equ REG_SI	; NASM port equate
   486 0000018E 8936[0F00]              	MOV	word ptr [IOCALL + Reg_SI],SI
   487                                  Reg_DI equ REG_DI	; NASM port equate
   488 00000192 893E[1100]              	MOV	word ptr [IOCALL + Reg_DI],DI
   489                                  GenericIOCTL_Packet equ GENERICIOCTL_PACKET	; NASM port equate
   490 00000196 8916[1300]              	MOV	word ptr [IOCALL + GenericIOCTL_Packet],DX
   491 0000019A 8936[1500]              	MOV	word ptr [IOCALL + GenericIOCTL_Packet + 2],SI
   492                                  
   493 0000019E BB[0000]                	MOV	BX,offset IOCALL wrt DOSGROUP
   494                                  
   495 000001A1 16                      	PUSH	SS
   496 000001A2 07                      	POP	ES
   497                                   assume es:DOSGROUP
   498                                  
   499 000001A3 5E                      	POP	SI
   500 000001A4 1F                      	POP	DS
   501                                  ASSUME DS:NOTHING			; DS:SI -> Device header.
   502                                  	; jmp	ioctl_do_IO		; Perform Call to device driver
   503                                  ; ioctl_do_IO:
   504 000001A5 E8(0000)                	invoke	DEVIOCALL2
   505 000001A8 36F606[0400]80          	testopt [ss:IOCALL + REQSTAT], STERR	; Error?
   506 000001AE 7403E90801              	JNZ	Ioctl_string_err
   507 000001B3 31C0                    	xor ax, ax			; lDOS: return ax = 0 on success
   508 000001B5 E9(0000)                	transfer    SYS_RET_OK
   509                                  
   510                                  IOCtl_Handle_RedirJ:
   511                                  IOCTL_Handle_Redir equ Ioctl_Handle_redir	; NASM port label
   512 000001B8 E99900                  	JMP	IOCTL_Handle_Redir
   513                                  ioctl_bad_fun:
   514 000001BB B001E9(0000)            	error	error_invalid_function
   515                                  
   516                                  ioctl_bad_handlej:
   517 000001C0 E94DFE                  	jmp	ioctl_bad_handle
   518                                  
   519                                  ; Function 8
   520                                  ioctl_rem_media:
   521 000001C3 E83F01                  	CALL	Check_If_Net
   522                                   assume es:nothing
   523 000001C6 75F3                    	JNZ	ioctl_bad_fun		; There are no "net devices", and they
   524                                  					;   certainly don't know how to do this
   525                                  					;   call.
   526                                   assume es:nothing	; device header
   527 000001C8 26F745040008            	TEST	word [ES:DI + SDEVATT],DEVOPCL ; See if device can
   528 000001CE 74EB                    	JZ	ioctl_bad_fun		; NO
   529 000001D0 36C606[0200]0F          	MOV	byte [ss:IOCALL + REQFUNC],DEVRMD
   530 000001D6 B00D                    	MOV	AL,REMHL
   531 000001D8 88DC                    	MOV	AH,BL			; Unit number
   532 000001DA 36A3[0000]              	MOV	WORD PTR [ss:IOCALL + REQLEN],AX
   533 000001DE 31C0                    	XOR	AX,AX
   534 000001E0 36A3[0300]              	MOV	[ss:IOCALL + REQSTAT],AX
   535 000001E4 06                      	PUSH	ES
   536 000001E5 1F                      	POP	DS
   537                                  ASSUME	DS:NOTHING
   538 000001E6 89FE                    	MOV	SI,DI			; DS:SI -> driver
   539 000001E8 16                      	PUSH	SS
   540 000001E9 07                      	POP	ES
   541                                   assume es:DOSGROUP
   542 000001EA BB[0000]                	MOV	BX,OFFSET IOCALL wrt DOSGROUP   ; ES:BX -> Call header
   543 000001ED 1E56                    	SaveReg <DS,SI>
   544 000001EF E8(0000)                	invoke	DEVIOCALL2
   545 000001F2 5E1F                    	RestoreReg <SI,DS>
   546 000001F4 36A1[0300]              	MOV	AX,[ss:IOCALL + REQSTAT]	; Get Status word
   547 000001F8 250002                  	AND	AX,STBUI		; Mask to busy bit
   548 000001FB B109                    	MOV	CL,9
   549 000001FD D3E8                    	SHR	AX,CL			; Busy bit to bit 0
   550 000001FF EBB4                    	transfer    SYS_RET_OK
   551                                  
   552                                  ; Function 9
   553                                  Ioctl_Drive_attr:
   554                                  
   555                                  ;;;;;	MOV	AL,BL			;AC000;; Drive
   556                                  ;;;;;	invoke	GETTHISDRV		;AC000;
   557                                  ;;;;;					;AC000;
   558                                  ;;;;;	JC	ioctl_drv_err		; drive not valid
   559 00000201 E8CB00                  	call	Get_Driver_BL
   560                                   assume es:nothing
   561 00000204 7247                    	JC	ioctl_drv_err		; drive not valid
   562                                   assume es:nothing	; device header
   563 00000206 36A1[0000]              	MOV	AX,[ss:Temp_Var2]		;AN000;IFS.
   564 0000020A 268B5504                	mov	dx,word ptr [es:di + SDEVATT]	; get device attribute word
   565 0000020E 88C3                    	MOV	BL,AL			; Phys letter to BL (A=0)
   566 00000210 36C43E[0000]            	LES	DI,[ss:THISCDS]
   567                                  ;;;;;	TEST	[ES:DI.curdir_flags],curdir_isnet
   568 00000215 E8F200                  	CALL	TEST_IFS_REMOTE2	;AN000;IFS. test if remote
   569 00000218 7404                    	JZ	IOCTLShare
   570 0000021A 81CA0010                	OR	DX,1000h
   571                                  IOCTLShare:
   572 0000021E 161F                    	Context DS
   573                                  ASSUME	DS:NOTHING
   574 00000220 BE[0000]                	MOV	SI,OFFSET OPENBUF wrt DOSGROUP
   575 00000223 80C341                  	ADD	BL,"A"
   576 00000226 881C                    	MOV	[SI],BL
   577 00000228 C744013A00              	MOV	WORD PTR [SI+1],003AH	; ":",0
   578 0000022D B80003                  	MOV	AX,0300H
   579 00000230 F8                      	CLC
   580 00000231 CD2A                    	INT	int_IBM
   581                                  ioctlLocal equ IOCTLLocal	; NASM port label
   582 00000233 7304                    	JNC	ioctlLocal		; Not shared
   583 00000235 81CA0002                	OR	DX,0200H		; Shared, bit 9
   584                                  IOCTLLocal:
   585 00000239 26F745430010            	TEST	word [ES:DI + curdir_flags],curdir_local
   586                                  ioctl_set_dx equ ioctl_set_DX	; NASM port label
   587 0000023F 7404                    	JZ	ioctl_set_dx
   588 00000241 81CA0080                	OR	DX,8000h
   589                                  
   590                                  ioctl_set_DX:
   591 00000245 E8(0000)                	invoke	get_user_stack
   592 00000248 895406                  	MOV	[SI + user_DX],DX
   593 0000024B EBB2                    	transfer    SYS_RET_OK
   594                                  
   595                                  ioctl_drv_err:
   596 0000024D 36A0[0000]              	MOV	AL,[ss:DrvErr]		;AN000;IFS. DrvErr is saved in GetThisDrv
   597 00000251 E9(0000)                	transfer SYS_RET_ERR		;AN000;IFS.
   598                                  
   599                                  ; Function 10
   600                                  Ioctl_Handle_redir:
   601 00000254 E8(0000)                	invoke	SFFromHandle		; ES:DI -> SFT
   602 00000257 7304                    	JNC	ioctl_got_sft		; have valid handle
   603 00000259 B006EBF4                	error	error_invalid_handle
   604                                  
   605                                  ioctl_got_sft:
   606 0000025D 268B5505                	MOV	DX,[ES:DI + sf_flags]	; Get flags
   607 00000261 EBE2                    	JMP	ioctl_set_DX
   608                                  
   609                                  ioctl_bad_funj:
   610 00000263 E955FF                  	JMP	ioctl_bad_fun
   611                                  
   612                                  ioctl_get_dev:
   613                                  	DOSAssume   CS,<DS>,"IOCTL/IOCtl_Get_Dev"
   614 00000266 E89C00                  	CALL	Check_If_Net
   615                                   assume es:nothing
   616 00000269 75F8                    	JNZ	ioctl_bad_funj		; There are no "net devices", and they
   617                                  					;   certainly don't know how to do this
   618                                  					;   call.
   619                                   assume es:nothing	; device header
   620                                  
   621                                  ioctl_do_string:
   622 0000026B 26F745040040            	TEST	word [ES:DI + SDEVATT],DEVIOCTL; See if device accepts control
   623 00000271 74F0                    	JZ	ioctl_bad_funj		; NO
   624 00000273 FEC8                    	DEC	AL
   625 00000275 FEC8                    	DEC	AL
   626 00000277 7407                    	JZ	ioctl_control_read
   627 00000279 C606[0200]0C            	MOV	byte [IOCALL + REQFUNC],DEVWRIOCTL
   628 0000027E EB05                    	JMP	SHORT ioctl_control_call
   629                                  ioctl_control_read:
   630                                   assume es:nothing	; device header
   631 00000280 C606[0200]03            	MOV	byte [IOCALL + REQFUNC],DEVRDIOCTL
   632                                  ioctl_control_call:
   633                                   assume es:nothing	; device header
   634 00000285 B016                    	MOV	AL,DRDWRHL
   635                                  ioctl_setup_pkt:
   636                                   assume es:nothing	; device header
   637 00000287 88DC                    	MOV	AH,BL			; Unit number
   638 00000289 A3[0000]                	MOV	WORD PTR [IOCALL + REQLEN],AX
   639 0000028C 31C0                    	XOR	AX,AX
   640 0000028E A3[0300]                	MOV	[IOCALL + REQSTAT],AX
   641 00000291 A2[0000]                	MOV	[IOMED],AL
   642 00000294 890E[0000]              	MOV	[IOSCNT],CX
   643 00000298 8916[0000]              	MOV	WORD PTR [IOXAD],DX
   644 0000029C 8936[0200]              	MOV	WORD PTR [IOXAD+2],SI
   645 000002A0 06                      	PUSH	ES
   646 000002A1 1F                      	POP	DS
   647                                  ASSUME	DS:NOTHING
   648 000002A2 89FE                    	MOV	SI,DI			; DS:SI -> driver
   649 000002A4 16                      	PUSH	SS
   650 000002A5 07                      	POP	ES
   651                                   assume es:DOSGROUP
   652 000002A6 BB[0000]                	MOV	BX,OFFSET IOCALL wrt DOSGROUP   ; ES:BX -> Call header
   653                                  ioctl_do_IO:
   654 000002A9 E8(0000)                	invoke	DEVIOCALL2
   655 000002AC 36F706[0300]0080        	TEST	word [ss:IOCALL + REQSTAT],STERR	    ;Error?
   656 000002B3 7506                    	JNZ	Ioctl_string_err
   657 000002B5 36A1[0000]              	MOV	AX,[ss:IOSCNT]		; Get actual bytes transferred
   658 000002B9 EB90                    	transfer    SYS_RET_OK
   659                                  
   660                                  Ioctl_string_err:
   661 000002BB 368B3E[0300]            	MOV	DI,[ss:IOCALL + REQSTAT]	;Get Error
   662                                  device_err:
   663 000002C0 81E7FF00                	AND	DI,STECODE		; mask out irrelevant bits
   664 000002C4 89F8                    	MOV	AX,DI
   665 000002C6 E8(0000)                	invoke	SET_I24_EXTENDED_ERROR
   666                                  extErr equ ExtErr	; NASM port label
   667 000002C9 36A1[0000]              	mov	ax, [ss:extErr]
   668 000002CD EB8C                    	transfer    SYS_RET_ERR
   669                                  
   670                                  Get_Driver_BL:
   671                                  	DOSAssume   CS,<DS>,"Get_Driver_BL"
   672                                  	ASSUME	ES:NOTHING
   673                                  ; BL is drive number (0=default)
   674                                  ; Returns pointer to device in ES:DI, unit number in BL if carry clear
   675                                  ; No regs modified
   676                                  
   677 000002CF 50                      	PUSH	AX
   678 000002D0 88D8                    	MOV	AL,BL			; Drive
   679 000002D2 E8(0000)                	invoke	GETTHISDRV
   680 000002D5 7307                    	JNC	ioctl_goodrv		;AC000;IFS.
   681                                  error_not_dos_disk equ error_not_DOS_disk	; NASM port equate
   682 000002D7 3C1A                    	CMP	AL,error_not_dos_disk	;AN000;IFS.   if unknow media then
   683 000002D9 7403                    	JZ	ioctl_goodrv		;AN000;IFS.	 let it go
   684 000002DB F9                      	STC				;AN000;IFS.   else
   685 000002DC EB25                    	JMP	SHORT ioctl_bad_drv	;AN000;IFS.	 error
   686                                  ioctl_goodrv:
   687 000002DE 30DB                    	XOR	BL,BL			; Unit zero on Net device
   688 000002E0 C606[0000]03            	MOV	byte [EXTERR_LOCUS],errLOC_Net
   689 000002E5 C43E[0000]              	LES	DI,[THISCDS]
   690                                   assume es:nothing	; CDS
   691                                  ;	TEST	[ES:DI.curdir_flags],curdir_isnet
   692 000002E9 E81E00                  	CALL	TEST_IFS_REMOTE2	;AN000;;IFS. test if remote
   693 000002EC 26C47D45                	LES	DI,[ES:DI + curdir_devptr]; ES:DI -> Dpb or net dev
   694 000002F0 750D                    	JNZ	got_dev_ptr		; Is net
   695                                   assume es:DPB
   696 000002F2 C606[0000]02            	MOV	byte [EXTERR_LOCUS],errLOC_Disk
   697 000002F7 268A5D01                	MOV	BL,[ES:DI + dpb_UNIT]	; Unit number
   698 000002FB 26C47D13                	LES	DI,[ES:DI + dpb_driver_addr]  ; Driver addr
   699                                   assume es:nothing	; device header
   700                                  got_dev_ptr:
   701 000002FF F8                      	CLC
   702 00000300 A3[0000]                	MOV	[Temp_Var2],AX		     ;AN000;IFS.
   703                                  ioctl_bad_drv:
   704 00000303 58                      	POP	AX
   705 00000304 C3                      	return
   706                                  
   707                                  ;
   708                                  ; Checks if the device is over the net or not. Returns result in ZERO flag.
   709                                  ; If no device is found, the return address is popped off the stack, and a
   710                                  ; jump is made to ioctl_drv_err.
   711                                  ;
   712                                  ; On Entry:
   713                                  ; Registers same as those for Get_Driver_BL
   714                                  ;
   715                                  ; On Exit:
   716                                  ; ZERO flag	- set if not a net device
   717                                  ;		- reset if net device
   718                                  ; ES:DI -> the device
   719                                  ;
   720                                  Check_If_Net:
   721 00000305 E8C7FF                  	CALL	Get_Driver_BL
   722                                   assume es:nothing
   723 00000308 721B                    	JC	ioctl_drv_err_pop	; invalid drive letter
   724                                  entry TEST_IFS_REMOTE2
   725 0000030A 06                      	PUSH	ES
   726 0000030B 57                      	PUSH	DI
   727 0000030C C43E[0000]              	LES	DI,[THISCDS]
   728                                   assume es:nothing	; CDS
   729 00000310 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet
   730 00000316 740A                    	JZ	belocal 		       ;AN000;	 ;IFS.
   731 00000318 26C47D52                	LES	DI,[ES:DI + curdir_ifs_hdr]      ;AN000;	 ;IFS.	test if remote
   732                                  TEST_REMOTE:				       ;AN000;
   733                                  ifs_attribute equ IFS_ATTRIBUTE	; NASM port equate
   734 0000031C 26F7450C0008            	TEST	word [ES:DI + ifs_attribute],IFSREMOTE;AN000;	 ;IFS.
   735                                  belocal:
   736 00000322 5F                      	POP	DI
   737 00000323 07                      	POP	ES
   738                                   assume es:nothing
   739 00000324 C3                      	ret
   740                                  
   741                                  ioctl_drv_err_pop:
   742 00000325 58                      	pop	ax			; pop off return address
   743 00000326 E924FF                  	jmp	ioctl_drv_err
   744                                  
   745                                  ioctl_bad_funj3:
   746 00000329 E98FFE                  	jmp	ioctl_bad_fun
   747                                  
   748                                  ioctl_string_errj:
   749                                  ioctl_string_err equ Ioctl_string_err	; NASM port label
   750 0000032C EB8D                    	jmp	ioctl_string_err
   751                                  
   752                                  ; Functions 14 and 15
   753                                  ioctl_drive_owner:
   754 0000032E E8D4FF                  	Call	Check_If_Net
   755                                   assume es:nothing
   756 00000331 75F6                    	JNZ	ioctl_bad_funj3 	; There are no "net devices", and they
   757                                  					;   certainly don't know how to do this
   758                                  					;   call.
   759                                   assume es:nothing	; device header
   760 00000333 26F745044000            	TEST	word [ES:DI + SDEVATT],DEV320	; See if device can handle this
   761 00000339 74EE                    	JZ	ioctl_bad_funj3 	; NO
   762 0000033B FEC8                    	dec	al
   763 0000033D 7407                    	jz	GetOwner
   764 0000033F C606[0200]18            	MOV	byte [IOCALL + REQFUNC],DEVSETOWN
   765 00000344 EB05                    	jmp	short ioctl_do_own
   766                                  GetOwner:
   767 00000346 C606[0200]17            	MOV	byte [IOCALL + REQFUNC],DEVGETOWN
   768                                  ioctl_do_own:
   769 0000034B B00D                    	MOV	AL,OWNHL
   770 0000034D 88DC                    	MOV	AH,BL			; Unit number
   771 0000034F A3[0000]                	MOV	WORD PTR [IOCALL + REQLEN],AX
   772 00000352 31C0                    	XOR	AX,AX
   773 00000354 A3[0300]                	MOV	[IOCALL + REQSTAT],AX
   774 00000357 06                      	PUSH	ES
   775 00000358 1F                      	POP	DS
   776                                  ASSUME	DS:NOTHING
   777 00000359 89FE                    	MOV	SI,DI			; DS:SI -> driver
   778 0000035B 16                      	PUSH	SS
   779 0000035C 07                      	POP	ES
   780                                   assume es:DOSGROUP
   781 0000035D BB[0000]                	MOV	BX,OFFSET IOCALL wrt DOSGROUP   ; ES:BX -> Call header
   782 00000360 1E56                    	SaveReg <DS,SI>
   783 00000362 E8(0000)                	invoke	DEVIOCALL2
   784 00000365 5E1F                    	RestoreReg <SI,DS>
   785 00000367 36F706[0300]0080        	test	word [ss:IOCALL + REQSTAT],STERR
   786 0000036E 75BC                    	jnz	ioctl_string_errj
   787 00000370 36A0[0100]              	MOV	AL,BYTE PTR [ss:IOCALL + REQUNIT]	; Get owner returned by device
   788                                  						; owner returned is 1-based.
   789 00000374 E9(0000)                	transfer    SYS_RET_OK
   790                                  
   791                                  EndProc D_IOCTL
   792                                  
   793                                  
   794                                  ;Input: ES:DI -> SFT
   795                                  ;Functions: test if a remote file
   796                                  ;Output: Z flag set, local file
   797                                  ;
   798                                  
   799                                  	procedure   TEST_IFS_REMOTE,NEAR  ;AN000;
   799          ******************       warning: proc TEST_IFS_REMOTE... [-w+user]
   800                                  	ASSUME	DS:NOTHING,ES:NOTHING	  ;AN000;
   801                                  
   802 00000377 26F745050080            	TEST	word [ES:DI + sf_flags],sf_isnet ;AN000;;IFS.	ifs ?
   803 0000037D 7408                    	JZ	nonifs			  ;AN000;;IFS.	no
   804 0000037F 06                      	PUSH	ES		       ;AN000;;IFS. save regs
   805 00000380 57                      	PUSH	DI		       ;AN000;;IFS.
   806                                  sf_IFS_hdr equ sf_IFS_HDR	; NASM port equate
   807 00000381 26C47D37                	LES	DI,[ES:DI + sf_IFS_hdr]  ;AN000;;IFS. get ifs header
   808 00000385 EB95                    	JMP	TEST_REMOTE	       ;AN000;;IFS.
   809                                  nonifs: 			       ;AN000;
   810 00000387 C3                      	return			       ;AN000;;IFS.
   811                                  EndProc TEST_IFS_REMOTE 	       ;AN000;
   812                                  
   813                                  END
