1 ; SCCSID = @(#)IOCTL.INC 1.15 85/09/05
2 TITLE IOCTL
- IOCTL system
call
14 ; Created: ARR 4 April 1983
16 ; GenericIOCTL added: KGS 22 April 1985
18 ; A000 version 4.00 Jan. 1988
24 ; get the appropriate segment definitions
28 CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
35 include ifssym
.inc ;AN000;
44 I_need RetryCount
,WORD
46 I_need EXTERR_LOCUS
,BYTE
50 I_need USER_IN_AX
,WORD ;AN000;
51 I_need Temp_Var2
,WORD ;AN000;
53 BREAK <IOCTL
- munge
on a handle to do device specific stuff
>
67 ; AH = 0 Return a combination of low byte of sf_flags and device driver
68 ; attribute word in DX, handle in BX:
69 ; DH = high word of device driver attributes
70 ; DL = low byte of sf_flags
71 ; 1 Set the bits contained in DX to sf_flags. DH MUST be 0. Handle
73 ; 2 Read CX bytes from the device control channel for handle in BX
74 ; into DS:DX. Return number read in AX.
75 ; 3 Write CX bytes to the device control channel for handle in BX from
76 ; DS:DX. Return bytes written in AX.
77 ; 4 Read CX bytes from the device control channel for drive in BX
78 ; into DS:DX. Return number read in AX.
79 ; 5 Write CX bytes to the device control channel for drive in BX from
80 ; DS:DX. Return bytes written in AX.
81 ; 6 Return input status of handle in BX. If a read will go to the
82 ; device, AL = 0FFh, otherwise 0.
83 ; 7 Return output status of handle in BX. If a write will go to the
84 ; device, AL = 0FFh, otherwise 0.
85 ; 8 Given a drive in BX, return 1 if the device contains non-
86 ; removable media, 0 otherwise.
87 ; 9 Return the contents of the device attribute word in DX for the
88 ; drive in BX. 0200h is the bit for shared. 1000h is the bit for
89 ; network. 8000h is the bit for local use.
90 ; A Return 8000h if the handle in BX is for the network or not.
91 ; B Change the retry delay and the retry count for the system. BX is
92 ; the count and CX is the delay.
95 ; AX = error_invalid_handle
96 ; = error_invalid_function
97 ; = error_invalid_data
99 ;-------------------------------------------------------------------------------
101 ; This is the documentation copied from DOS 4.0 it is much better
104 ; There are several basic forms of IOCTL calls:
107 ; ** Get/Set device information: **
109 ; ENTRY (AL) = function code
110 ; 0 - Get device information
111 ; 1 - Set device information
113 ; (DX) = info for "Set Device Information"
114 ; EXIT 'C' set if error
117 ; (DX) = info for "Get Device Information"
121 ; ** Read/Write Control Data From/To Handle **
123 ; ENTRY (AL) = function code
124 ; 2 - Read device control info
125 ; 3 - Write device control info
127 ; (CX) = transfer count
128 ; (DS:DX) = address for data
129 ; EXIT 'C' set if error
132 ; (AX) = count of bytes transfered
136 ; ** Read/Write Control Data From/To Block Device **
138 ; ENTRY (AL) = function code
139 ; 4 - Read device control info
140 ; 5 - Write device control info
141 ; (BL) = Drive number (0=default, 1='A', 2='B', etc)
142 ; (CX) = transfer count
143 ; (DS:DX) = address for data
144 ; EXIT 'C' set if error
147 ; (AX) = count of bytes transfered
151 ; ** Get Input/Output Status **
153 ; ENTRY (AL) = function code
154 ; 6 - Get Input status
155 ; 7 - Get Output Status
157 ; EXIT 'C' set if error
160 ; (AL) = 00 if not ready
165 ; ** Get Drive Information **
167 ; ENTRY (AL) = function code
168 ; 8 - Check for removable media
169 ; 9 - Get device attributes
170 ; (BL) = Drive number (0=default, 1='A', 2='B', etc)
171 ; EXIT 'C' set if error
174 ; (AX) = 0/1 media is removable/fixed (func. 8)
175 ; (DX) = device attribute word (func. 9)
179 ; ** Get Redirected bit **
181 ; ENTRY (AL) = function code
182 ; 0Ah - Network stuff
184 ; EXIT 'C' set if error
187 ; (DX) = SFT flags word, 8000h set if network file
191 ; ** Change sharer retry parameters **
193 ; ENTRY (AL) = function code
194 ; 0Bh - Set retry parameters
195 ; (CX) = retry loop count
196 ; (DX) = number of retries
197 ; EXIT 'C' set if error
203 ; =================================================================
205 ; ** New Standard Control **
207 ; ALL NEW IOCTL FACILITIES SHOULD USE THIS FORM. THE OTHER
208 ; FORMS ARE OBSOLETE.
210 ; =================================================================
212 ; ENTRY (AL) = function code
213 ; 0Ch - Control Function subcode
215 ; (CH) = Category Indicator
216 ; (CL) = Function within category
217 ; (DS:DX) = address for data, if any
218 ; (SI) = Passed to device as argument, use depends upon function
219 ; (DI) = Passed to device as argument, use depends upon function
220 ; EXIT 'C' set if error
223 ; (SI) = Return value, meaning is function dependent
224 ; (DI) = Return value, meaning is function dependent
225 ; (DS:DX) = Return address, use is function dependent
228 ; ============== Generic IOCTL Definitions for DOS 3.2 ============
229 ; (See dos/ioctl.mac for more info)
231 ; ENTRY (AL) = function code
232 ; 0Dh - Control Function subcode
233 ; (BL) = Drive Number (0 = Default, 1= 'A')
234 ; (CH) = Category Indicator
235 ; (CL) = Function within category
236 ; (DS:DX) = address for data, if any
237 ; (SI) = Passed to device as argument, use depends upon function
238 ; (DI) = Passed to device as argument, use depends upon function
240 ; EXIT 'C' set if error
243 ; (DS:DX) = Return address, use is function dependent
247 procedure $IOCTL
,NEAR
248 ASSUME
DS:NOTHING
,ES:NOTHING
249 MOV SI,DS ; Stash DS for calls 2,3,4 and 5
252 JBE ioctl_check_char
; char device
253 JMP ioctl_check_block
; Block device
255 invoke SFFromHandle
; ES:DI -> SFT
256 JNC ioctl_check_permissions
; have valid handle
258 error error_invalid_handle
260 ioctl_check_permissions:
262 JAE ioctl_control_string
264 MOV AL,BYTE PTR ES:[DI.sf_flags
]; Get low byte of flags
265 JZ ioctl_read
; read the byte
267 AND DH,0FEH ;AN000;MS.allow DH=01H
269 JZ ioctl_check_device
; can I set with this data?
270 error error_invalid_data
; no DH <> 0
276 TEST AL,devid_device
; can I set this handle?
277 JZ do_exception
; no, it is a file.
278 OR DL,devid_device
; Make sure user doesn't turn off the
279 ; device bit!! He can muck with the
281 MOV [EXTERR_LOCUS
],errLOC_SerDev
282 MOV BYTE PTR ES:[DI.sf_flags
],DL ;AC000;MS.; Set flags
284 OR BYTE PTR ES:[DI.sf_flags
+1],DH;AN000;MS.;set 100H bit for disk full
293 MOV [EXTERR_LOCUS
],errLOC_Disk
295 TEST AL,devid_device
; Should I set high byte
296 JZ ioctl_no_high
; no
297 MOV [EXTERR_LOCUS
],errLOC_SerDev
298 LES DI,ES:[DI.sf_devptr
] ; Get device pointer
299 MOV AH,BYTE PTR ES:[DI.SDEVATT
+1] ; Get high byte
302 invoke get_user_stack
306 ioctl_control_string:
307 TEST ES:[DI.sf_flags
],devid_device
; can I?
309 JMP ioctl_bad_fun
; No it is a file
311 TEST ES:[DI.sf_flags
],sf_isnet
;AN000;IFS.; IFS ?
312 JZ localrw
;AN000;IFS.; no
313 JMP callifs
;AN000;IFS.; call IFS
315 MOV [EXTERR_LOCUS
],errLOC_SerDev
316 LES DI,ES:[DI.sf_devptr
] ; Get device pointer
317 XOR BL,BL ; Unit number of char dev = 0
325 DEC AL ; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9
329 JAE ioctl_rem_media_check
340 JMP ioctl_bad_handle
; invalid SFT
351 ioctl_rem_media_check: ; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9
354 SUB AL,7 ; 9=0,10=1,11=2,12=3,13=4,14=5,15=6
366 DEC AL ; 10=0,11=1,12=2,13=3,14=4,15=5
368 Jmp Ioctl_Handle_redirj
371 DEC AL ; 11=0,12=1,13=2,14=3,15=4
372 JZ Set_Retry_Parameters
374 DEC AL ; 12=0,13=1,14=2,15=3
375 JZ GENERICIOCTLHANDLE
377 DEC AL ; 13=0,14=1,15=2
382 JMP ioctl_drive_owner
383 Set_Retry_Parameters:
384 MOV RetryLoop
,CX ; 0 retry loop count allowed
385 OR DX,DX ; zero retries not allowed
389 MOV RetryCount
,DX ; Set new retry count
391 transfer Sys_Ret_Ok
; Done
393 ; Generic IOCTL entry point.
394 ; here we invoke the Generic IOCTL using the IOCTL_Req structure.
395 ; SI:DX -> Users Device Parameter Table
396 ; IOCALL -> IOCTL_Req structure
398 invoke SFFromHandle
; Get SFT for device.
400 JMP ioctl_bad_handlej
402 ; test word ptr [DI.sf_flags],sf_isnet
403 CALL TEST_IFS_REMOTE
;AN000;;IFS. test if remote
404 JZ okokok
;AN000;;IFS.
405 jmp ioctl_bad_fun
; Cannot do this over net.
407 TEST [DI.sf_flags
],sf_isnet
;AN000;IFS.; local IFS
408 JNZ callifs
;AN000;IFS.; yes
411 mov [EXTERR_LOCUS
],ErrLOC_Serdev
412 les di,es:[di.sf_devptr
] ; Get pointer to device.
413 jmp short Do_GenIOCTL
416 mov [EXTERR_LOCUS
],ErrLOC_Disk
417 cmp ch,IOC_DC
; Only disk devices are allowed to use
418 jne ioctl_bad_fun
; no handles with Generic IOCTL.
419 CALL Check_If_Net
; ES:DI := Get_hdr_block of device in BL
420 JNZ ioctl_bad_fun
; There are no "net devices", and they
421 PUSH ES ; certainly don't know how to do this ;AN000;
423 LES DI,[THISCDS
] ;AN000;IFS. ;
424 TEST ES:[DI.curdir_flags
],curdir_isnet
;AN000;IFS. ; local IFS ?
427 JZ Do_GenIOCTL
;AN000;IFS. ; no
429 CMP byte ptr [User_In_AX
+1],69H
;AN000; ;IFS.
430 JNZ is44xx
;AN000; ;IFS.
431 MOV AX,440
DH ;AN000; ;IFS.
432 PUSH AX ;AN000; ;IFS.
433 JMP SHORT callrose
;AN000; ;IFS.
435 PUSH [User_In_AX
] ;AN000; ;IFS. call IFSFUNC
437 MOV DS,SI ;AN000; ;IFS.
438 MOV AX,(multNET
SHL 8) or 43 ;AN000; ;IFS.
439 INT 2FH
;AN000; ;IFS.
441 JNC doneok
;AN000; ;IFS.
442 MOV DI,AX ;AN000; ;IFS.
443 JMP device_err
;AN000; ;IFS.
445 test ES:[DI.SDEVATT
],DEV320
; Can device handle Generic IOCTL funcs
447 PUSH ES ; DEVIOCALL2 expects Device header block
449 ;set up Generic IOCTL Request Block
450 MOV byte ptr IOCALL
.ReqLen
,(size IOCTL_Req
)
451 MOV byte ptr IOCALL
.ReqFunc
,GENIOCTL
452 MOV byte ptr IOCALL
.ReqUnit
,BL
453 MOV byte ptr IOCALL
.MajorFunction
,CH
454 MOV byte ptr IOCALL
.MinorFunction
,CL
455 MOV word ptr IOCALL
.Reg_SI
,SI
456 MOV word ptr IOCALL
.Reg_DI
,DI
457 MOV word ptr IOCALL
.GenericIOCTL_Packet
,DX
458 MOV word ptr IOCALL
.GenericIOCTL_Packet
+ 2,SI
460 MOV BX,offset DOSGROUP
:IOCALL
465 ASSUME
DS:NOTHING
; DS:SI -> Device header.
468 jmp ioctl_do_IO
; Perform Call to device driver
471 JMP IOCTL_Handle_Redir
473 error error_invalid_function
481 JNZ ioctl_bad_fun
; There are no "net devices", and they
482 ; certainly don't know how to do this
484 TEST ES:[DI.SDEVATT
],DEVOPCL
; See if device can
485 JZ ioctl_bad_fun
; NO
486 MOV [IOCALL
.REQFUNC
],DEVRMD
488 MOV AH,BL ; Unit number
489 MOV WORD PTR [IOCALL
.REQLEN
],AX
491 MOV [IOCALL
.REQSTAT
],AX
495 MOV SI,DI ; DS:SI -> driver
498 MOV BX,OFFSET DOSGROUP
:IOCALL
; ES:BX -> Call header
502 MOV AX,[IOCALL
.REQSTAT
] ; Get Status word
503 AND AX,STBUI
; Mask to busy bit
505 SHR AX,CL ; Busy bit to bit 0
511 ;;;;; MOV AL,BL ;AC000;; Drive
512 ;;;;; invoke GETTHISDRV ;AC000;
514 ;;;;; JC ioctl_drv_err ; drive not valid
516 JC ioctl_drv_err
; drive not valid
517 MOV AX,[Temp_Var2
] ;AN000;IFS.
518 mov dx,word ptr es:[di.SDEVATT
] ; get device attribute word
519 MOV BL,AL ; Phys letter to BL (A=0)
521 ;;;;; TEST ES:[DI.curdir_flags],curdir_isnet
522 CALL TEST_IFS_REMOTE2
;AN000;IFS. test if remote
528 MOV SI,OFFSET DOSGROUP
:OPENBUF
531 MOV WORD PTR [SI+1],003AH ; ":",0
535 JNC ioctlLocal
; Not shared
536 OR DX,0200H ; Shared, bit 9
538 TEST ES:[DI].curdir_flags
,curdir_local
543 invoke get_user_stack
548 MOV AL,[DrvErr
] ;AN000;IFS. DrvErr is saved in GetThisDrv
549 transfer SYS_RET_ERR
;AN000;IFS.
553 invoke SFFromHandle
; ES:DI -> SFT
554 JNC ioctl_got_sft
; have valid handle
555 error error_invalid_handle
558 MOV DX,ES:[DI.sf_flags
] ; Get flags
565 DOSAssume
CS,<DS>,"IOCTL/IOCtl_Get_Dev"
567 JNZ ioctl_bad_funj
; There are no "net devices", and they
568 ; certainly don't know how to do this
571 TEST ES:[DI.SDEVATT
],DEVIOCTL
; See if device accepts control
572 JZ ioctl_bad_funj
; NO
575 JZ ioctl_control_read
576 MOV [IOCALL
.REQFUNC
],DEVWRIOCTL
577 JMP SHORT ioctl_control_call
579 MOV [IOCALL
.REQFUNC
],DEVRDIOCTL
583 MOV AH,BL ; Unit number
584 MOV WORD PTR [IOCALL
.REQLEN
],AX
586 MOV [IOCALL
.REQSTAT
],AX
589 MOV WORD PTR [IOXAD
],DX
590 MOV WORD PTR [IOXAD
+2],SI
594 MOV SI,DI ; DS:SI -> driver
597 MOV BX,OFFSET DOSGROUP
:IOCALL
; ES:BX -> Call header
600 TEST [IOCALL
.REQSTAT
],STERR
;Error?
602 MOV AX,[IOSCNT
] ; Get actual bytes transferred
606 MOV DI,[IOCALL
.REQSTAT
] ;Get Error
608 AND DI,STECODE
; mask out irrelevant bits
610 invoke SET_I24_EXTENDED_ERROR
615 DOSAssume
CS,<DS>,"Get_Driver_BL"
617 ; BL is drive number (0=default)
618 ; Returns pointer to device in ES:DI, unit number in BL if carry clear
624 JNC ioctl_goodrv
;AC000;IFS.
625 CMP AL,error_not_dos_disk
;AN000;IFS. if unknow media then
626 JZ ioctl_goodrv
;AN000;IFS. let it go
628 JMP SHORT ioctl_bad_drv
;AN000;IFS. error
630 XOR BL,BL ; Unit zero on Net device
631 MOV [EXTERR_LOCUS
],errLOC_Net
633 ; TEST ES:[DI.curdir_flags],curdir_isnet
634 CALL TEST_IFS_REMOTE2
;AN000;;IFS. test if remote
635 LES DI,ES:[DI.curdir_devptr
]; ES:DI -> Dpb or net dev
636 JNZ got_dev_ptr
; Is net
637 MOV [EXTERR_LOCUS
],errLOC_Disk
638 MOV BL,ES:[DI.dpb_UNIT
] ; Unit number
639 LES DI,ES:[DI.dpb_driver_addr
] ; Driver addr
642 MOV [Temp_Var2
],AX ;AN000;IFS.
648 ; Checks if the device is over the net or not. Returns result in ZERO flag.
649 ; If no device is found, the return address is popped off the stack, and a
650 ; jump is made to ioctl_drv_err.
653 ; Registers same as those for Get_Driver_BL
656 ; ZERO flag - set if not a net device
657 ; - reset if net device
658 ; ES:DI -> the device
662 JC ioctl_drv_err_pop
; invalid drive letter
663 entry TEST_IFS_REMOTE2
667 TEST ES:[DI.curdir_flags
],curdir_isnet
668 JZ belocal
;AN000; ;IFS.
669 LES DI,ES:[DI.curdir_ifs_hdr
] ;AN000; ;IFS. test if remote
671 TEST ES:[DI.ifs_attribute
],IFSREMOTE
;AN000; ;IFS.
678 pop ax ; pop off return address
687 ; Functions 14 and 15
690 JNZ ioctl_bad_funj3
; There are no "net devices", and they
691 ; certainly don't know how to do this
693 TEST ES:[DI.SDEVATT
],DEV320
; See if device can handle this
694 JZ ioctl_bad_funj3
; NO
697 MOV [IOCALL
.REQFUNC
],DEVSETOWN
698 jmp short ioctl_do_own
700 MOV [IOCALL
.REQFUNC
],DEVGETOWN
703 MOV AH,BL ; Unit number
704 MOV WORD PTR [IOCALL
.REQLEN
],AX
706 MOV [IOCALL
.REQSTAT
],AX
710 MOV SI,DI ; DS:SI -> driver
713 MOV BX,OFFSET DOSGROUP
:IOCALL
; ES:BX -> Call header
717 test [IOCALL
.REQSTAT
],STERR
718 jnz ioctl_string_errj
719 MOV AL,BYTE PTR [IOCALL
.REQUNIT
] ; Get owner returned by device
720 ; owner returned is 1-based.
727 ;Functions: test if a remote file
728 ;Output: Z flag set, local file
731 procedure TEST_IFS_REMOTE
,NEAR ;AN000;
732 ASSUME
DS:NOTHING
,ES:NOTHING
;AN000;
734 TEST ES:[DI.sf_flags
],sf_isnet
;AN000;;IFS. ifs ?
735 JZ nonifs
;AN000;;IFS. no
736 PUSH ES ;AN000;;IFS. save regs
738 LES DI,ES:[DI.sf_IFS_hdr
] ;AN000;;IFS. get ifs header
739 JMP TEST_REMOTE
;AN000;;IFS.
742 EndProc TEST_IFS_REMOTE
;AN000;