;       SCCSID = @(#)d_qcdisk.asm	6.1 91/02/15
;      SCCSID = @(#)d_qcdisk.asm	6.2 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;***  d_qcdisk.asm - API stub routine DosQCurDisk
;
;	Member of API library
;	Bill Mershon
;	Copyright MicroSoft Corporation, 1986
;	27-Feb-1986
;
;	library routine for API simulator
;
;	Called from dos 2.x,3.x compatible dos 5.x applications
;
;	Special Information
;		none
;
;	Modification History
;	10-May-1986 (WFM)  as per DCR 259 (D0000259 P	DCR) submitted by miro
;	(SUBMITTED: 04/17/86 by Felix Miro (MIRO)), we now use a standard
;	mapping of 'a:' to 1, 'b:' to 2, etc.
;
;	06-Jan-87 (billme): Replace initial pushes and final pops
;	with calls to __api_begin and __api_end resp.  This will
;	reduce the size of FAPI and allow support for signals.
;
; @@	24-Feb-87 (GAA) fix ptm P2066 - to prevent interruption
; @@	during the GetDisk/SetDisk process of generating the
; @@	bit map, we set Ctrl-Break state OFF. The original setting
; @@	is restored on exit.
;
; @@	25-Feb-87 (GAA) fix loops to loop til CX=0 and
; @@	load map for drives Q-Z into DI.
;
; @@	06-Aug-87 (GAA) Moved ctrl-break off/on setting to
; @@	external routines api_ctrlbreak_off/_reset (in i_versio.asm).
;

include dos2equ.inc

	EXTRN	__api_begin:near
	EXTRN	__api_end:near
	EXTRN	api_ctrlbreak_off:near		; @@ ctrl-break checking on/off
	EXTRN	api_ctrlbreak_reset:near	; @@ support

;***	DOSQCURDISK - stub to emulate DOSQCURDISK function call
;
;	simulates dos 5.0 DOSQCURDISK using int 21, function 047h
;
;	errorcode = unsigned far pascal
;	DosQCurDisk (DriveNumber,LogicalDriveMap)
;
;	ENTRY:
;		DriveNumber - drive number (0=default, 1=A, etc)
;		LogicalDriveMap - drive map area
;
;	RETURN:
;		AX = 0 if no error, else error code (see DOS 5 spec)
;
;	EXIT:
;		@DriveNumber contains current drive number
;		@LogicalDriveMap contains current drive map
;
;	USES:
;		AX
;
;	Pseudo Code:
;		save registers
;		use BP as pointer to stack parameters
; @@		if ctrl-brk chk = ON then set ctrl-brk OFF
;		save the current disk
;		begin building the drive map
;		make sure the current drive is in the map
;		use functions 0eh (set default drive) and 019h
;			(get default drive) to find the currently
;			accessable drives (if a given drive exists
;			the get following a set yield the new drive number -
;			if the drive does not exist, the set will have
;			no effect).
;		execute above in in loop looking for drives A to Z
;		restore the disk that was current upon entry
; @@		restore original state of ctrl-brk check
;		restore registers
;		return
;
;	WARNING:
;		may return error code from Dos 2.x, 3.x (see dos manuals)
;
;	EFFECTS:
;		none
;

	title	DOSQCURDISK - stub to emulate DOSQCURDISK function call
;
;	EXTRN	DOSQCURDISK:FAR
;
;	PUSH	@ WORD DriveNumber
;	PUSH	@ DWORD Logical Drive Map
;	CALL	DOSQCURDISK
;


_TEXT	segment byte public 'CODE'

	assume	CS:_TEXT,DS:NOTHING


	public	DOSQCURDISK

DriveNumber	equ	[BP+10]
LogicalDriveMap equ	[BP+6]

DOSQCURDISK	proc	far

	call	__api_begin	; init bp and save bp,ds,bx,cx,dx,si,di,es
				; required to save: bp,ds,bx,cx,dx,si,di + es

	call	api_ctrlbreak_off	; @@ turn off ctrl-break checking

	; save current disk ... to build drive map, we will need to
	; select each disk in the full range of possible disks so
	; we save the current disk so we can restore it after we build map
	mov	ah,D2_CurDisk
	int	21h
					; AL contains current disk
	mov	ah,bl			; BL contains ctrl-brk state	; @@
	mov	es,ax			; save current disk and		; @@
					; original ctrl-brk state in ES ; @@
	lds	bx,[DriveNumber]
	xor	ah,ah
	inc	ax			; standardize 'a:' = 1, etc
					; (see modification history)
	mov	ds:[bx],ax		; store drive number
	dec	ax			; reset from standard (for DOS 2)

; initialize for disk drive query
	mov	dh,al		; DH will contain current valid drive
	mov	bx,1		; initialize mask

; make sure the current drive is mapped
	xor	si,si		; SI will contain low portion of mask
	xor	di,di		; DI will contain high portion of mask
	mov	cl,dh
	cmp	cl,16
	jge	dqcd_1
	rol	bx,cl		; shift if drive is < 16 (A: - O:)
	or	si,bx
	jmp	dqcd_2
dqcd_1:
	sub	cl,16
	rol	bx,cl		; shift if drive is >= 16 (P: - Z:)
	or	di,bx
dqcd_2:

; load map for drives A-P into SI
	xor	dl,dl		; DL will contain current target drive
	mov	bx,1		; initialize mask
	mov	cx,16
dqcd_3:
	mov	ah,D2_SelectDisk
	int	21h
	mov	ah,D2_CurDisk
	int	21h
	cmp	al,dh		; recall - DH contains current valid drive
	jz	dqcd_4		; target is not valid
	mov	dh,al
	or	si,bx
dqcd_4:
	inc	dl		; increment target drive number
	rol	bx,1		; point mask to next drive
	loop	dqcd_3		; @@ loop til all drives (A-P) processed

; load map for drives Q-Z into DI
	mov	bx,1		; initialize mask
	mov	cx,10
dqcd_5:
	mov	ah,D2_SelectDisk
	int	21h
	mov	ah,D2_CurDisk
	int	21h
	cmp	al,dh		; recall - DH contains current valid drive
	jz	dqcd_6		; target is not valid
	mov	dh,al
	or	di,bx		; @@ set map bit in DI !!
dqcd_6:
	inc	dl		; increment target drive number
	rol	bx,1		; point mask to next drive
	loop	dqcd_5		; @@ loop til all drives (Q-Z) processed

	lds	bx,[LogicalDriveMap]
	mov	ds:[bx],si
	mov	ds:[bx+2],di

; ES contains in hi byte: original ctrl-brk state			; @@
;	      in lo byte: saved current disk				; @@

	mov	ax,es		; AL <- saved current disk
	mov	bl,ah		; AH <- saved original ctrl-brk state	; @@

	mov	dl,al		; select disk that was current on entry
	mov	ah,D2_SelectDisk
	int	21h
ErrorExit:

	call	api_ctrlbreak_reset	; @@ restore ctrl-break checking

	xor	ax,ax		; set "no error"
	call	__api_end	; check sigs & restore es,di,si,dx,cx,bx,ds,bp

	ret	8		; clear stack of entry parameters (bytes)
DOSQCURDISK	endp

_TEXT	ends

	end

