     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 E98501                  	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 E94101                  	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 E9C000                  	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 E9D701                  	JMP	ioctl_do_string
   319                                  
   320                                  ioctl_get_devj:
   321 0000008C E9CF01                  	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 E93701                  	JMP	Ioctl_Drive_attr
   357                                  
   358                                  ioctl_rem_mediaj:
   359 000000C3 E9F600                  	jmp	ioctl_rem_media
   360                                  
   361                                  ioctl_bad_funj4:
   362 000000C6 E9EB00                  	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 E9E100                  	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 7439                    	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 7731                    	ja	GENERICIOCTL
   386 000000E4 7414                    	je	GENERICIOCTLHANDLE
   387 000000E6 E93102                  	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 E9C000                  	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 E9B700                  	JMP	ioctl_bad_handlej
   408                                  goodh:
   409                                  ;	test	word ptr [DI.sf_flags],sf_isnet
   410 00000102 E85E02                  	CALL	TEST_IFS_REMOTE 	;AN000;;IFS. test if remote
   411 00000105 7403                    	JZ	okokok			;AN000;;IFS.
   412 00000107 E9AA00                  	jmp	ioctl_bad_fun		; Cannot do this over net.
   413                                  okokok:
   414                                  ErrLOC_Serdev equ errLOC_SerDev	; NASM port equate
   415 0000010A C606[0000]04            	mov	byte [EXTERR_LOCUS],ErrLOC_Serdev
   416 0000010F 26C47D07                	les	di,[es:di + sf_devptr]	; Get pointer to device.
   417 00000113 EB49                    	jmp	short Do_GenIOCTL
   418                                  
   419                                  GENERICIOCTL:
   420                                  ;	INP:	al = nonzero for query only (4411h)
   421                                  ErrLOC_Disk equ errLOC_Disk	; NASM port equate
   422 00000115 C606[0000]02            	mov	byte [EXTERR_LOCUS],ErrLOC_Disk
   423 0000011A 80FD08                  	cmp	ch,IOC_DC		; Only disk devices are allowed to use
   424 0000011D 7403E99200              	jne	ioctl_bad_fun		; no handles with Generic IOCTL.
   425 00000122 E8D801                  	CALL	Check_If_Net		; ES:DI := Get_hdr_block of device in BL
   426                                   assume es:nothing
   427 00000125 7403E98A00              	JNZ	ioctl_bad_fun		; There are no "net devices", and they
   428                                   assume es:nothing	; device header
   429 0000012A 06                      	PUSH	ES			;   certainly don't know how to do this ;AN000;
   430 0000012B 57                      	PUSH	DI				 ;AN000;IFS.
   431 0000012C C43E[0000]              	LES	DI,[THISCDS]			 ;AN000;IFS.	 ;
   432                                   assume es:nothing
   433 00000130 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet;AN000;IFS.	 ; local IFS ?
   434 00000136 5F                      	POP	DI				 ;AN000;IFS.
   435 00000137 07                      	POP	ES				 ;AN000;IFS.
   436                                   assume es:nothing
   437 00000138 7424                    	JZ	Do_GenIOCTL			 ;AN000;IFS.	 ; no
   438                                  callifs_no_query:
   439 0000013A 84C0                    	test al, al
   440 0000013C 7576                    	jnz ioctl_bad_fun
   441                                  callifs:
   442                                  User_In_AX equ USER_IN_AX	; NASM port label
   443 0000013E 803E[0100]69            	CMP	byte ptr [User_In_AX+1],69H  ;AN000;	     ;IFS.
   444 00000143 7506                    	JNZ	is44xx			     ;AN000;	     ;IFS.
   445 00000145 B80D44                  	MOV	AX,440DH		     ;AN000;	     ;IFS.
   446 00000148 50                      	PUSH	AX			     ;AN000;	     ;IFS.
   447 00000149 EB04                    	JMP	SHORT callrose		     ;AN000;	     ;IFS.
   448                                  is44xx:
   449 0000014B FF36[0000]              	PUSH	word [User_In_AX]		     ;AN000;	     ;IFS. call IFSFUNC
   450                                  callrose:
   451 0000014F 8EDE                    	MOV	DS,SI			     ;AN000;	     ;IFS.
   452                                   assume ds:nothing
   453                                  multNET equ MultNET	; NASM port equate
   454 00000151 B82B11                  	MOV	AX,(multNET << 8) |  43    ;AN000;	     ;IFS.
   455 00000154 CD2F                    	INT	2FH			     ;AN000;	     ;IFS.
   456 00000156 5B                      	POP	BX			     ;AN000;	     ;IFS.
   457 00000157 739F                    	JNC	doneok			     ;AN000;	     ;IFS.
   458 00000159 89C7                    	MOV	DI,AX			     ;AN000;	     ;IFS.
   459 0000015B E95A01                  	JMP	device_err		     ;AN000;	     ;IFS.
   460                                  Do_GenIOCTL:
   461                                   assume ds:DOSGROUP
   462 0000015E 26F745044000            	test	word [ES:DI + SDEVATT],DEV320	; Can device handle Generic IOCTL funcs
   463 00000164 744E                    	jz	ioctl_bad_fun
   464 00000166 06                      	PUSH	ES			; DEVIOCALL2 expects Device header block
   465 00000167 57                      	PUSH	DI			; in DS:SI
   466                                  	;set up Generic IOCTL Request Block
   467                                  IOCTL_Req_struc_size equ IOCTL_REQ_struc_size	; NASM port equate
   468                                  ReqLen equ REQLEN	; NASM port equate
   469 00000168 C606[0000]17            	MOV	byte [IOCALL + ReqLen],(IOCTL_Req_struc_size)
   470                                  ReqFunc equ REQFUNC	; NASM port equate
   471 0000016D C606[0200]13            	MOV	byte [IOCALL + ReqFunc],GENIOCTL
   472 00000172 84C0                    	test al, al
   473 00000174 7405                    	jz @F
   474 00000176 C606[0200]19            	MOV	byte [IOCALL + ReqFunc], QUERYGENIOCTL
   475                                  @@:
   476                                  ReqUnit equ REQUNIT	; NASM port equate
   477 0000017B 881E[0100]              	MOV	byte ptr [IOCALL + ReqUnit],BL
   478                                  MajorFunction equ MAJORFUNCTION	; NASM port equate
   479 0000017F 882E[0D00]              	MOV	byte ptr [IOCALL + MajorFunction],CH
   480                                  MinorFunction equ MINORFUNCTION	; NASM port equate
   481 00000183 880E[0E00]              	MOV	byte ptr [IOCALL + MinorFunction],CL
   482                                  Reg_SI equ REG_SI	; NASM port equate
   483 00000187 8936[0F00]              	MOV	word ptr [IOCALL + Reg_SI],SI
   484                                  Reg_DI equ REG_DI	; NASM port equate
   485 0000018B 893E[1100]              	MOV	word ptr [IOCALL + Reg_DI],DI
   486                                  GenericIOCTL_Packet equ GENERICIOCTL_PACKET	; NASM port equate
   487 0000018F 8916[1300]              	MOV	word ptr [IOCALL + GenericIOCTL_Packet],DX
   488 00000193 8936[1500]              	MOV	word ptr [IOCALL + GenericIOCTL_Packet + 2],SI
   489                                  
   490 00000197 BB[0000]                	MOV	BX,offset IOCALL wrt DOSGROUP
   491                                  
   492 0000019A 16                      	PUSH	SS
   493 0000019B 07                      	POP	ES
   494                                   assume es:DOSGROUP
   495                                  
   496 0000019C 5E                      	POP	SI
   497 0000019D 1F                      	POP	DS
   498                                  ASSUME DS:NOTHING			; DS:SI -> Device header.
   499                                  	; jmp	ioctl_do_IO		; Perform Call to device driver
   500                                  ; ioctl_do_IO:
   501 0000019E E8(0000)                	invoke	DEVIOCALL2
   502 000001A1 36F606[0400]80          	testopt [ss:IOCALL + REQSTAT], STERR	; Error?
   503 000001A7 7403E90701              	JNZ	Ioctl_string_err
   504 000001AC 31C0                    	xor ax, ax			; lDOS: return ax = 0 on success
   505 000001AE E9(0000)                	transfer    SYS_RET_OK
   506                                  
   507                                  IOCtl_Handle_RedirJ:
   508                                  IOCTL_Handle_Redir equ Ioctl_Handle_redir	; NASM port label
   509 000001B1 E99800                  	JMP	IOCTL_Handle_Redir
   510                                  ioctl_bad_fun:
   511 000001B4 B001E9(0000)            	error	error_invalid_function
   512                                  
   513                                  ioctl_bad_handlej:
   514 000001B9 E954FE                  	jmp	ioctl_bad_handle
   515                                  
   516                                  ; Function 8
   517                                  ioctl_rem_media:
   518 000001BC E83E01                  	CALL	Check_If_Net
   519                                   assume es:nothing
   520 000001BF 75F3                    	JNZ	ioctl_bad_fun		; There are no "net devices", and they
   521                                  					;   certainly don't know how to do this
   522                                  					;   call.
   523                                   assume es:nothing	; device header
   524 000001C1 26F745040008            	TEST	word [ES:DI + SDEVATT],DEVOPCL ; See if device can
   525 000001C7 74EB                    	JZ	ioctl_bad_fun		; NO
   526 000001C9 36C606[0200]0F          	MOV	byte [ss:IOCALL + REQFUNC],DEVRMD
   527 000001CF B00D                    	MOV	AL,REMHL
   528 000001D1 88DC                    	MOV	AH,BL			; Unit number
   529 000001D3 36A3[0000]              	MOV	WORD PTR [ss:IOCALL + REQLEN],AX
   530 000001D7 31C0                    	XOR	AX,AX
   531 000001D9 36A3[0300]              	MOV	[ss:IOCALL + REQSTAT],AX
   532 000001DD 06                      	PUSH	ES
   533 000001DE 1F                      	POP	DS
   534                                  ASSUME	DS:NOTHING
   535 000001DF 89FE                    	MOV	SI,DI			; DS:SI -> driver
   536 000001E1 16                      	PUSH	SS
   537 000001E2 07                      	POP	ES
   538                                   assume es:DOSGROUP
   539 000001E3 BB[0000]                	MOV	BX,OFFSET IOCALL wrt DOSGROUP   ; ES:BX -> Call header
   540 000001E6 1E56                    	SaveReg <DS,SI>
   541 000001E8 E8(0000)                	invoke	DEVIOCALL2
   542 000001EB 5E1F                    	RestoreReg <SI,DS>
   543 000001ED 36A1[0300]              	MOV	AX,[ss:IOCALL + REQSTAT]	; Get Status word
   544 000001F1 250002                  	AND	AX,STBUI		; Mask to busy bit
   545 000001F4 B109                    	MOV	CL,9
   546 000001F6 D3E8                    	SHR	AX,CL			; Busy bit to bit 0
   547 000001F8 EBB4                    	transfer    SYS_RET_OK
   548                                  
   549                                  ; Function 9
   550                                  Ioctl_Drive_attr:
   551                                  
   552                                  ;;;;;	MOV	AL,BL			;AC000;; Drive
   553                                  ;;;;;	invoke	GETTHISDRV		;AC000;
   554                                  ;;;;;					;AC000;
   555                                  ;;;;;	JC	ioctl_drv_err		; drive not valid
   556 000001FA E8CA00                  	call	Get_Driver_BL
   557                                   assume es:nothing
   558 000001FD 7246                    	JC	ioctl_drv_err		; drive not valid
   559                                   assume es:nothing	; device header
   560 000001FF 36A1[0000]              	MOV	AX,[ss:Temp_Var2]		;AN000;IFS.
   561 00000203 88C3                    	MOV	BL,AL			; Phys letter to BL (A=0)
   562 00000205 BA0010                  	mov dx, 1000h			; this is like MS-DOS v5 if remote
   563 00000208 E8F700                  	CALL	TEST_IFS_REMOTE2	;AN000;IFS. test if remote
   564 0000020B 7504                    	jnz @F				; if remote, skip device read -->
   565                                  		; (only read es:di if local)
   566 0000020D 268B5504                	mov	dx,word ptr [es:di + SDEVATT]	; get device attribute word
   567                                  @@:
   568 00000211 36C43E[0000]            	LES	DI,[ss:THISCDS]
   569                                  IOCTLShare:
   570 00000216 161F                    	Context DS
   571                                  ASSUME	DS:NOTHING
   572 00000218 BE[0000]                	MOV	SI,OFFSET OPENBUF wrt DOSGROUP
   573 0000021B 80C341                  	ADD	BL,"A"
   574 0000021E 881C                    	MOV	[SI],BL
   575 00000220 C744013A00              	MOV	WORD PTR [SI+1],003AH	; ":",0
   576 00000225 B80003                  	MOV	AX,0300H
   577 00000228 F8                      	CLC
   578 00000229 CD2A                    	INT	int_IBM
   579                                  ioctlLocal equ IOCTLLocal	; NASM port label
   580 0000022B 7304                    	JNC	ioctlLocal		; Not shared
   581 0000022D 81CA0002                	OR	DX,0200H		; Shared, bit 9
   582                                  IOCTLLocal:
   583 00000231 26F745430010            	TEST	word [ES:DI + curdir_flags],curdir_local
   584                                  ioctl_set_dx equ ioctl_set_DX	; NASM port label
   585 00000237 7404                    	JZ	ioctl_set_dx
   586 00000239 81CA0080                	OR	DX,8000h
   587                                  
   588                                  ioctl_set_DX:
   589 0000023D E8(0000)                	invoke	get_user_stack
   590 00000240 895406                  	MOV	[SI + user_DX],DX
   591 00000243 EBB3                    	transfer    SYS_RET_OK
   592                                  
   593                                  ioctl_drv_err:
   594 00000245 36A0[0000]              	MOV	AL,[ss:DrvErr]		;AN000;IFS. DrvErr is saved in GetThisDrv
   595 00000249 E9(0000)                	transfer SYS_RET_ERR		;AN000;IFS.
   596                                  
   597                                  ; Function 10
   598                                  Ioctl_Handle_redir:
   599 0000024C E8(0000)                	invoke	SFFromHandle		; ES:DI -> SFT
   600 0000024F 7304                    	JNC	ioctl_got_sft		; have valid handle
   601 00000251 B006EBF4                	error	error_invalid_handle
   602                                  
   603                                  ioctl_got_sft:
   604 00000255 268B5505                	MOV	DX,[ES:DI + sf_flags]	; Get flags
   605 00000259 EBE2                    	JMP	ioctl_set_DX
   606                                  
   607                                  ioctl_bad_funj:
   608 0000025B E956FF                  	JMP	ioctl_bad_fun
   609                                  
   610                                  ioctl_get_dev:
   611                                  	DOSAssume   CS,<DS>,"IOCTL/IOCtl_Get_Dev"
   612 0000025E E89C00                  	CALL	Check_If_Net
   613                                   assume es:nothing
   614 00000261 75F8                    	JNZ	ioctl_bad_funj		; There are no "net devices", and they
   615                                  					;   certainly don't know how to do this
   616                                  					;   call.
   617                                   assume es:nothing	; device header
   618                                  
   619                                  ioctl_do_string:
   620 00000263 26F745040040            	TEST	word [ES:DI + SDEVATT],DEVIOCTL; See if device accepts control
   621 00000269 74F0                    	JZ	ioctl_bad_funj		; NO
   622 0000026B FEC8                    	DEC	AL
   623 0000026D FEC8                    	DEC	AL
   624 0000026F 7407                    	JZ	ioctl_control_read
   625 00000271 C606[0200]0C            	MOV	byte [IOCALL + REQFUNC],DEVWRIOCTL
   626 00000276 EB05                    	JMP	SHORT ioctl_control_call
   627                                  ioctl_control_read:
   628                                   assume es:nothing	; device header
   629 00000278 C606[0200]03            	MOV	byte [IOCALL + REQFUNC],DEVRDIOCTL
   630                                  ioctl_control_call:
   631                                   assume es:nothing	; device header
   632 0000027D B016                    	MOV	AL,DRDWRHL
   633                                  ioctl_setup_pkt:
   634                                   assume es:nothing	; device header
   635 0000027F 88DC                    	MOV	AH,BL			; Unit number
   636 00000281 A3[0000]                	MOV	WORD PTR [IOCALL + REQLEN],AX
   637 00000284 31C0                    	XOR	AX,AX
   638 00000286 A3[0300]                	MOV	[IOCALL + REQSTAT],AX
   639 00000289 A2[0000]                	MOV	[IOMED],AL
   640 0000028C 890E[0000]              	MOV	[IOSCNT],CX
   641 00000290 8916[0000]              	MOV	WORD PTR [IOXAD],DX
   642 00000294 8936[0200]              	MOV	WORD PTR [IOXAD+2],SI
   643 00000298 06                      	PUSH	ES
   644 00000299 1F                      	POP	DS
   645                                  ASSUME	DS:NOTHING
   646 0000029A 89FE                    	MOV	SI,DI			; DS:SI -> driver
   647 0000029C 16                      	PUSH	SS
   648 0000029D 07                      	POP	ES
   649                                   assume es:DOSGROUP
   650 0000029E BB[0000]                	MOV	BX,OFFSET IOCALL wrt DOSGROUP   ; ES:BX -> Call header
   651                                  ioctl_do_IO:
   652 000002A1 E8(0000)                	invoke	DEVIOCALL2
   653 000002A4 36F706[0300]0080        	TEST	word [ss:IOCALL + REQSTAT],STERR	    ;Error?
   654 000002AB 7506                    	JNZ	Ioctl_string_err
   655 000002AD 36A1[0000]              	MOV	AX,[ss:IOSCNT]		; Get actual bytes transferred
   656 000002B1 EB90                    	transfer    SYS_RET_OK
   657                                  
   658                                  Ioctl_string_err:
   659 000002B3 368B3E[0300]            	MOV	DI,[ss:IOCALL + REQSTAT]	;Get Error
   660                                  device_err:
   661 000002B8 81E7FF00                	AND	DI,STECODE		; mask out irrelevant bits
   662 000002BC 89F8                    	MOV	AX,DI
   663 000002BE E8(0000)                	invoke	SET_I24_EXTENDED_ERROR
   664                                  extErr equ ExtErr	; NASM port label
   665 000002C1 36A1[0000]              	mov	ax, [ss:extErr]
   666 000002C5 EB8C                    	transfer    SYS_RET_ERR
   667                                  
   668                                  Get_Driver_BL:
   669                                  	DOSAssume   CS,<DS>,"Get_Driver_BL"
   670                                  	ASSUME	ES:NOTHING
   671                                  ; BL is drive number (0=default)
   672                                  ; Returns pointer to device in ES:DI, unit number in BL if carry clear
   673                                  ; No regs modified
   674                                  
   675 000002C7 50                      	PUSH	AX
   676 000002C8 88D8                    	MOV	AL,BL			; Drive
   677 000002CA E8(0000)                	invoke	GETTHISDRV
   678 000002CD 7307                    	JNC	ioctl_goodrv		;AC000;IFS.
   679                                  error_not_dos_disk equ error_not_DOS_disk	; NASM port equate
   680 000002CF 3C1A                    	CMP	AL,error_not_dos_disk	;AN000;IFS.   if unknow media then
   681 000002D1 7403                    	JZ	ioctl_goodrv		;AN000;IFS.	 let it go
   682 000002D3 F9                      	STC				;AN000;IFS.   else
   683 000002D4 EB25                    	JMP	SHORT ioctl_bad_drv	;AN000;IFS.	 error
   684                                  ioctl_goodrv:
   685 000002D6 30DB                    	XOR	BL,BL			; Unit zero on Net device
   686 000002D8 C606[0000]03            	MOV	byte [EXTERR_LOCUS],errLOC_Net
   687 000002DD C43E[0000]              	LES	DI,[THISCDS]
   688                                   assume es:nothing	; CDS
   689                                  ;	TEST	[ES:DI.curdir_flags],curdir_isnet
   690 000002E1 E81E00                  	CALL	TEST_IFS_REMOTE2	;AN000;;IFS. test if remote
   691 000002E4 26C47D45                	LES	DI,[ES:DI + curdir_devptr]; ES:DI -> Dpb or net dev
   692 000002E8 750D                    	JNZ	got_dev_ptr		; Is net
   693                                   assume es:DPB
   694 000002EA C606[0000]02            	MOV	byte [EXTERR_LOCUS],errLOC_Disk
   695 000002EF 268A5D01                	MOV	BL,[ES:DI + dpb_UNIT]	; Unit number
   696 000002F3 26C47D13                	LES	DI,[ES:DI + dpb_driver_addr]  ; Driver addr
   697                                   assume es:nothing	; device header
   698                                  got_dev_ptr:
   699 000002F7 F8                      	CLC
   700 000002F8 A3[0000]                	MOV	[Temp_Var2],AX		     ;AN000;IFS.
   701                                  ioctl_bad_drv:
   702 000002FB 58                      	POP	AX
   703 000002FC C3                      	return
   704                                  
   705                                  ;
   706                                  ; Checks if the device is over the net or not. Returns result in ZERO flag.
   707                                  ; If no device is found, the return address is popped off the stack, and a
   708                                  ; jump is made to ioctl_drv_err.
   709                                  ;
   710                                  ; On Entry:
   711                                  ; Registers same as those for Get_Driver_BL
   712                                  ;
   713                                  ; On Exit:
   714                                  ; ZERO flag	- set if not a net device
   715                                  ;		- reset if net device
   716                                  ; ES:DI -> the device
   717                                  ;
   718                                  Check_If_Net:
   719 000002FD E8C7FF                  	CALL	Get_Driver_BL
   720                                   assume es:nothing
   721 00000300 720F                    	JC	ioctl_drv_err_pop	; invalid drive letter
   722                                  entry TEST_IFS_REMOTE2
   723 00000302 06                      	PUSH	ES
   724 00000303 57                      	PUSH	DI
   725 00000304 C43E[0000]              	LES	DI,[THISCDS]
   726                                   assume es:nothing	; CDS
   727 00000308 26F745430080            	TEST	word [ES:DI + curdir_flags],curdir_isnet
   728 0000030E 5F                      	POP	DI
   729 0000030F 07                      	POP	ES
   730                                   assume es:nothing
   731 00000310 C3                      	ret
   732                                  
   733                                  ioctl_drv_err_pop:
   734 00000311 58                      	pop	ax			; pop off return address
   735 00000312 E930FF                  	jmp	ioctl_drv_err
   736                                  
   737                                  ioctl_bad_funj3:
   738 00000315 E99CFE                  	jmp	ioctl_bad_fun
   739                                  
   740                                  ioctl_string_errj:
   741                                  ioctl_string_err equ Ioctl_string_err	; NASM port label
   742 00000318 EB99                    	jmp	ioctl_string_err
   743                                  
   744                                  ; Functions 14 and 15
   745                                  ioctl_drive_owner:
   746 0000031A E8E0FF                  	Call	Check_If_Net
   747                                   assume es:nothing
   748 0000031D 75F6                    	JNZ	ioctl_bad_funj3 	; There are no "net devices", and they
   749                                  					;   certainly don't know how to do this
   750                                  					;   call.
   751                                   assume es:nothing	; device header
   752 0000031F 26F745044000            	TEST	word [ES:DI + SDEVATT],DEV320	; See if device can handle this
   753 00000325 74EE                    	JZ	ioctl_bad_funj3 	; NO
   754 00000327 FEC8                    	dec	al
   755 00000329 7407                    	jz	GetOwner
   756 0000032B C606[0200]18            	MOV	byte [IOCALL + REQFUNC],DEVSETOWN
   757 00000330 EB05                    	jmp	short ioctl_do_own
   758                                  GetOwner:
   759 00000332 C606[0200]17            	MOV	byte [IOCALL + REQFUNC],DEVGETOWN
   760                                  ioctl_do_own:
   761 00000337 B00D                    	MOV	AL,OWNHL
   762 00000339 88DC                    	MOV	AH,BL			; Unit number
   763 0000033B A3[0000]                	MOV	WORD PTR [IOCALL + REQLEN],AX
   764 0000033E 31C0                    	XOR	AX,AX
   765 00000340 A3[0300]                	MOV	[IOCALL + REQSTAT],AX
   766 00000343 06                      	PUSH	ES
   767 00000344 1F                      	POP	DS
   768                                  ASSUME	DS:NOTHING
   769 00000345 89FE                    	MOV	SI,DI			; DS:SI -> driver
   770 00000347 16                      	PUSH	SS
   771 00000348 07                      	POP	ES
   772                                   assume es:DOSGROUP
   773 00000349 BB[0000]                	MOV	BX,OFFSET IOCALL wrt DOSGROUP   ; ES:BX -> Call header
   774 0000034C 1E56                    	SaveReg <DS,SI>
   775 0000034E E8(0000)                	invoke	DEVIOCALL2
   776 00000351 5E1F                    	RestoreReg <SI,DS>
   777 00000353 36F706[0300]0080        	test	word [ss:IOCALL + REQSTAT],STERR
   778 0000035A 75BC                    	jnz	ioctl_string_errj
   779 0000035C 36A0[0100]              	MOV	AL,BYTE PTR [ss:IOCALL + REQUNIT]	; Get owner returned by device
   780                                  						; owner returned is 1-based.
   781 00000360 E9(0000)                	transfer    SYS_RET_OK
   782                                  
   783                                  EndProc D_IOCTL
   784                                  
   785                                  
   786                                  ;Input: ES:DI -> SFT
   787                                  ;Functions: test if a remote file
   788                                  ;Output: Z flag set, local file
   789                                  ;
   790                                  
   791                                  	procedure   TEST_IFS_REMOTE,NEAR  ;AN000;
   791          ******************       warning: proc TEST_IFS_REMOTE... [-w+user]
   792                                  	ASSUME	DS:NOTHING,ES:NOTHING	  ;AN000;
   793                                  
   794 00000363 26F745050080            	TEST	word [ES:DI + sf_flags],sf_isnet ;AN000;;IFS.	ifs ?
   795 00000369 C3                      	return			       ;AN000;;IFS.
   796                                  EndProc TEST_IFS_REMOTE 	       ;AN000;
   797                                  
   798                                  END
