;       SCCSID = @(#)i_devct8.asm	6.1 91/02/15
;	SCCSID = @(#)i_devct8.asm	6.2 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;***  i_devct8.asm - routines for category 8 IOCTL calls
;
;	Internal routines used by API IOCTL library routines
;	David Silverstein
;	Copyright MicroSoft Corporation, 1986
;	7-May-1986
;
;	This file contains support routines for disk control IOCTLs
;
;
;	04-May-87 (robertc): Install hooks for DOSErrorClass Support.
;	All int 21h errors are passed through api_get_extended to get the
;	extended errorcode and to provide the class, action, and locus for
;	the dynamic error FIFO queue.
;
;	10-Jun-87 (robertc): Fixed error logic. It was not checking carry
;	after int 21. (Ptm 5327)
;
;
;

include dos2equ.inc
include error.inc
include d_ioctl.inc
include i_devct8.inc


; The purpose of this segment is to share a reusable data area between api
; library routines. This is a win since it decreases the total api library
; overhead in the application's executable.

APIBUF	segment byte common 'CODE'

__api_buffer	db	40 dup(?)

APIBUF	ends


_TEXT	segment byte public 'CODE'
	assume	CS:_TEXT, DS:nothing

	PUBLIC	DISKCTRL

	EXTRN	_api_getvrsn :NEAR
	EXTRN	DosErrAdd:far
	EXTRN	api_get_extended:far

DISKCTRL	proc	near

	push	ds
	push	cx
	push	dx
	push	si
	push	di

	mov	cx, [Function]		; get block device function
	and	cx, NOT IGNORE_ERROR	; mask off error if unsupported bit

	mov	ax, error_invalid_function
	test	ch, ch			; high byte of function code should be 0
	jz	dctrl1			; function code ok
	jmp	NormalExit		; return with error
dctrl1:
	mov	bx, [DevHandle] 	; get passed device handle
	cmp	bh, 0ffh		; is this a fake handle?
	je	dctrl3

	; We have a real handle generated by the extended open call in
	; the 3xBox. We just send the ioctl to the driver.

	mov	ch, CATEGORY8
	lds	di, [ParmList]		; si:di <= parameter list pointer ;@@
	mov	ax, ds							  ;@@
	mov	si, ax							  ;@@
	lds	dx, [DataArea]		; ds:dx <= data packet pointer	  ;@@
	mov	ax, D2_IOCTL SHL 8 + D2_HANDLE_IOCTL
	int	21h			; call Dos 3.x IOCTL for handles
	jc	ErrorExit		; if this failed, get extended error
	xor	ax, ax
	jmp	short NormalExit	; go return sucessfull

dctrl3:
	not	bx			; translate to drive number here
	mov	ax, error_invalid_handle
	cmp	bx, 'Z'-'A' + 1 	; is this a valid drive number?
	ja	NormalExit		   ; no, return with error

	call	_api_getvrsn		; get Dos version
	cmp	ah, 10			; Are we running in the 3xBox?
	jae	dctrl10 		; just send it to the driver

	cmp	cx, D5_LockDrive	; lock drive
	jne	dctrl4
	call	LockDrive
	jmp	short NormalExit
dctrl4:
	cmp	cx, D5_UnlockDrive	; unlock drive
	jne	dctrl5
	call	UnlockDrive
	jmp	short NormalExit
dctrl5:
	cmp	cx, D5_RedetermineMedia ; redetermine media
	jne	dctrl6
	call	RedetermineMedia
	jc	ErrorExit
	jmp	short NormalExit
dctrl6:
	cmp	cx, D5_SetLogicalMap	; set logical map
	jne	dctrl7
	call	SetLogicalMap
	jc	ErrorExit
	jmp	short NormalExit
dctrl7:
	cmp	cx, D5_BlockRemovable	; block removable
	jne	dctrl8
	call	BlockRemovable
	jc	ErrorExit
	jmp	short NormalExit
dctrl8:
	cmp	cx, D5_GetLogicalMap	; get logical map
	jne	dctrl9
	call	GetLogicalMap
	jc	ErrorExit
	jmp	short NormalExit

	; If we are running Dos 3.2 or above, generic ioctls are supported.
	; An installed driver MAY support these. Just in case, we call the
	; driver through an int 21 call.
dctrl9:
	call	_api_getvrsn		; get Dos version
	cmp	ax, 314h		; is Dos 3.2 or above?
	jae	dctrl10 		; yes, driver may support this ioctl
	mov	ax, error_invalid_function
	jmp	short NormalExit

	; We are running Dos 3.2 or above.  The IOCTL info is passed to the
	; driver through an int 21 interface.
dctrl10:
	mov	ch, CATEGORY8
	lds	di, [ParmList]		; si:di <= parameter list pointer
	mov	ax, ds
	mov	si, ax
	lds	dx, [DataArea]		; ds:dx <= data packet pointer
	mov	ax, D2_IOCTL SHL 8 + D2_BLOCKDEVS; old style IOCTL block devs
	int	21h
	jc	ErrorExit		; an error occured, get extended error
	xor	ax, ax
	jmp	short NormalExit	   ; no error occured

	; get the extended error code - hopefully what the driver returned.
	; Because this code only runs in above 3.x, we don't have to worry about
	; Get Extended Error not being supported in Dos 2.x.

ErrorExit:
	call	api_get_extended
NormalExit:
	pop	di
	pop	si
	pop	dx
	pop	cx
	pop	ds
	ret


; ***** LockDrive, UnlockDrive
;
; Because the concept of locking and unlocking drives is meaningless in 2.x
; and 3.x DOS, they will always just return sucessfull.

LockDrive:
UnlockDrive:
	xor	ax, ax
	ret				; command complete


; ***** RedetermineMedia - Redetermine Media
;
; All this code does is make sure the BPB is compatible with the current
; hardware state (in case a disk has changed).
;
; ENTRY: bx = logical drive number

RedetermineMedia:
	mov	ax, D2_IOCTL SHL 8 + D2_BLOCKDEVS; old style IOCTL block devs
	mov	cx, CATEGORY8 SHL 8 + D2_GetDeviceParams
	mov	dx, SEG APIBUF		; get address of available memory area
	mov	ds, dx
	lea	dx, APIBUF:__api_buffer
	int	21h			; this should update the BPB
	jc	rdmed1
	xor	ax, ax
rdmed1:
	ret


; ***** GetLogicalMap - Get Logical Map
;

GetLogicalMap:
	mov	ax, D2_IOCTL SHL 8 + D2_GetLogicalMap ; Dos 2.x get logical map
	lds	si, [DataArea]
	mov	bl, byte ptr [si]
	int	21h
	jc	glm1			; exit with dos 2.x error codes
	mov	byte ptr [si], al
	xor	ax, ax
glm1:
	ret


; ***** SetLogicalMap - Set Logical Map
;

SetLogicalMap:
	mov	ax, D2_IOCTL SHL 8 + D2_SetLogicalMap ; Dos 2.x set logical map
	lds	si, [DataArea]
	mov	bl, byte ptr [si]		; logical drive number
	int	21h
	jc	slm1			; return with Dos 2.x error code
	mov	byte ptr [si], al
	xor	ax, ax
slm1:
	ret


; ***** BlockRemovable - Block Removable
;
; ENTRY: bx = logical drive number

BlockRemovable:
	mov	ax, D2_IOCTL SHL 8 + D2_Changeable ; is this device changeable?
	int	21h
	jc	blkrem1
	lds	si, [DataArea]		; get data area pointer
	mov	byte ptr [si], al	; load removable/nonremovable status
	xor	ax, ax
blkrem1:
	ret

DISKCTRL	endp
_TEXT		ends

		end
