%TITLE          "Determine Current Drives - CHiPS bv 1997"
;**********************************************************************
;**                                                                  **
;**  Program   : DC_DRV                                              **
;**  Purpose   : Determine Current Drives                            **
;**                                                                  **
;**  Author    : B.F. Schreurs                                       **
;**              Computer High Performance Software (CHiPS) bv       **
;**  Date      : September 2nd, 1997                                 **
;**                                                                  **
;**  Calls     : [None]                                              **
;**                                                                  **
;**  Parameter : 1. Pass the address of the requested format.        **
;**                 The format specified how the data of the         **
;**                 available drives will be passed back.            **
;**                 Requested format size is 1 byte and may contain: **
;**                 "1" = Return data in format                      **
;**                       "ABCDE                     "               **
;**                 "2" = Return data in format                      **
;**                       "[A: Mydiskette ]"                         ** 
;**                       "[C: Harddisk_C ]"                         ** 
;**                       "[D: Harddisk_D ]"                         ** 
;**                       "[E: Cdrom_drive]"                         ** 
;**                       "                "                         ** 
;**                       "                "                         ** 
;**                       etc.                                       **    
;**                 "3" = Return data in format                      **
;**                       "[A: Mydiskette ]"                         ** 
;**                       "[C: Harddisk_C ]"                         ** 
;**                       "[E: Cdrom_drive]"                         ** 
;**                       "                "                         ** 
;**                       "                "                         ** 
;**                       "                "                         ** 
;**                       etc.                                       **    
;**                       using the drive list passed in parameter 2 **
;**                       which has the format of available_drives   **
;**  Parameter : 2. Pass the address of the table where the data     **
;**                 containing the drive information will be stored. **
;**                 Format "1": The table size should be  26 chars.  **
;**                 Format "2": The table size should be 416 chars.  **
;**                 Format "3": The table size should be 416 chars.  **
;**                             of which the first 26 characters of  **
;**                             the list is the available drives     **
;**                                                                  **
;**  Language  : Turbo Assembler                                     **
;**                                                                  **
;**********************************************************************
        IDEAL
        JUMPS

;----------------------------------------------------------------------
;--  Functions which can be called                                   --
;----------------------------------------------------------------------
        PUBLIC  DC_DRV

;----------------------------------------------------------------------
;--  Equates                                                         --
;----------------------------------------------------------------------
include ".\equ\sysdep.equ"
include ".\equ\equipmnt.equ"
include ".\equ\dos.equ"

DRIVE_AREA_STRUCTURE_SIZE   EQU  16

;**********************************************************************
SEGMENT SSeg Para Stack 'STACK'
;**********************************************************************

        db        64 dup (0)            ; Stack

ENDS    SSeg



;**********************************************************************
SEGMENT DSeg Word Public 'DATA'
;**********************************************************************

;----------------------------------------------------------------------
;--  Structures                                                      --
;----------------------------------------------------------------------

Struc   Drive_Area
  Letter                DB    3 dup (SPACE)
  Volume                DB   13 dup (SPACE)
ends

Struc   Media_Id
  MidInfoLevel          DW    1 dup (NULL)
  MidSerialNum          DW    2 dup (NULL)
  MidVolLabel           DB   11 dup (SPACE)
  MidFileSysType        DB    8 dup (SPACE)
ends

;----------------------------------------------------------------------
;--  Working Storage                                                 --
;----------------------------------------------------------------------
GLOBAL Return_Code:Byte:1

Parm_Format_ptr_es      DW    1 dup (NULL)      ; 1 = "ABCDEFGHIJKL    " etc.
Parm_Format_ptr_di      DW    1 dup (NULL)      ; 2 = "A: [Floppy     ]"
                                                ;     "C: [HARD_DRIVE ]" etc.
Parm_Drive_ptr_es       DW    1 dup (NULL)
Parm_Drive_ptr_di       DW    1 dup (NULL)

Available_Drives        DB  MAX_DRIVES dup (SPACE)

Buffer_Get_Media_Id     Media_Id <>
Buffer_Sense_Media_Type DW    1 dup (NULL)

ENDS    DSeg

;**********************************************************************
SEGMENT CSeg Word Public 'CODE'
;**********************************************************************

;**********************************************************************
PROC    DC_DRV
;**********************************************************************
        ASSUME  cs:CSeg
        ASSUME  ds:DSeg
        mov     ax, DSeg                    ; Initialize DS to address
        mov     ds, ax                      ; of data segment

        mov     bx, sp

;
; Parameter Drives
;
        mov     di, [ss:bx+2]
        mov     es, [ss:bx+4]

        mov     [Parm_Drive_ptr_es], es
        mov     [Parm_Drive_ptr_di], di

;
; Parameter Format
;
        mov     di, [ss:bx+6]
        mov     es, [ss:bx+8]

        mov     [Parm_Format_ptr_es], es
        mov     [Parm_Format_ptr_di], di

;
; Init Drive Map
;
        mov     cx, MAX_DRIVES              ; Maximum nr of drives possible
        mov     es, [Parm_Format_ptr_es]
        mov     di, [Parm_Format_ptr_di]
        cmp     [byte es:di], "1"           ; Requested Format = "ABCDE..."?
        je      @@10

        mov     ax, DRIVE_AREA_STRUCTURE_SIZE
        mul     cx
        mov     cx, ax

        mov     es, [Parm_Format_ptr_es]
        mov     di, [Parm_Format_ptr_di]
        cmp     [byte es:di], "2"           ; User specified drive list?
        je      @@10                        ; No
                                            ; Yes, so
        mov     si, offset Available_Drives

        push    ds si

        push    ds si
        mov     es, [Parm_Drive_ptr_es]
        mov     di, [Parm_Drive_ptr_di]
        push    es di
        mov     cx, MAX_DRIVES
        pop     si ds
        pop     di es
        rep     movsb

        pop     si ds

        jmp     @@70

@@10:
        mov     es, [Parm_Drive_ptr_es]
        mov     di, [Parm_Drive_ptr_di]

        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill character
        rep     stosb

        mov     si, offset Available_Drives
        push    ds si
        pop     di es

;
; Check available diskette drives A and B
;
        int     EQUIPMENT_SERVICE           ; Get equipment info
        mov     cx, ax
        and     cx, 00001h                  ; Check nr of floppy drives
        cmp     cl, 001h                    ; Floppy drives present?
        jne     @@30                        ; No
                                            ; Yes, so
        and     ax, 000C0h                  ; Check nr of floppy drives present
        cmp     al, 000h                    ; 1 floppy drive present?
        je      @@20                        ; Yes
                                            ; No, so
; 2 floppy drives present
        mov     [byte es:di], "A"           ; Add drive A to Drive Map
        inc     di
        mov     [byte es:di], "B"           ; Add drive B to Drive Map
        jmp     @@30

; Just 1 floppy drive present
@@20:
        push    es di
        mov     ax, 00050h
        mov     es, ax
        mov     di, 00004h
        mov     al, [byte es:di]            ; 0050:0004 shows which drive is
                                            ; emulated with 1 floppy drive
                                            ; 000h = drive A   0001h = drive B
        pop     di es

;
; Determine which floppy drive is being emulated, assume drive A
;
        mov     [byte es:di], "A"           ; Add drive A to Drive Map

        cmp     al, 000h                    ; Emulating drive A?
        je      @@30                        ; Yes
                                            ; No, so
        mov     [byte es:di], "B"           ; Add drive B to Drive Map

@@30:        
        inc     di
        xor     bx, bx                      ; Reset bx
        mov     bl, "C"                     ; Check Drive C thru Z

; Check drives C thru Z
@@40:
        mov     ax, DOS_SENSE_MEDIA_TYPE
        mov     cx, DOS_SENSE_MEDIA_TYPE_CX
        sub     bl, 64                      ; Turn drive into DOS drive
        mov     si, offset Buffer_Sense_Media_Type
        mov     dx, si
        int     DOS_SERVICE                 ; Check Drive Presence
        add     bl, 64                      ; Turn DOS drive into readable drive
        cmp     ax, DOS_DRIVE_NOT_AVAILABLE ; Drive available?
        je      @@50                        ; No
                                            ; Yes, so
        mov     [byte es:di], bl            ; Add drive to Drive Map
        inc     di                          ; Move to next drive

@@50:
        cmp     bl, "Z"                     ; Checked all drives?
        je      @@60                        ; Yes
                                            ; No, so
        inc     bl                          ; Get next drive
        jmp     @@40                        ; Check next drive

@@60:
        mov     es, [Parm_Format_ptr_es]
        mov     di, [Parm_Format_ptr_di]
        cmp     [byte es:di], "1"           ; Requested Format = "ABCDE..."?
        jne     @@70                        ; No
                                            ; Yes, so
;
; Pass available drives, format "ABCDE..."
;
        mov     si, offset Available_Drives
        mov     es, [Parm_Drive_ptr_es]
        mov     di, [Parm_Drive_ptr_di]
        mov     cx, MAX_DRIVES
        rep     movsb
        jmp     @@99

@@70:
;
; Retrieve Volume Names
;
        mov     si, offset Available_Drives
        mov     es, [Parm_Drive_ptr_es]
        mov     di, [Parm_Drive_ptr_di]
        mov     cx, MAX_DRIVES

@@80:
        cmp     [byte ds:si], SPACE         ; All drives processed?
        je      @@99                        ; Yes
                                            ; No, so
        xor     bx, bx
        mov     bl, [byte ds:si]            ; Remember drive letter
        movsb                               ; Move drive letter
        mov     [byte es:di], COLON         ; Drive is "A:", "C:", "D:", etc.
        inc     di                          ; Move over to space position
        mov     [byte es:di], SPACE         ; Specify the space
        inc     di                          ; Move to position of left hook
        mov     [byte es:di], "["           ; Left hook
        inc     di                          ; Move to position of volume name

        push    ds si es di

;
; Get volume name
;
        push    es di

        mov     si, offset Buffer_Get_Media_Id.MidVolLabel
        push    ds si
        pop     di es
        mov     cx, VOLUME_NAME_LENGTH
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Fill character
        rep     stosb

        pop     di es

        mov     ax, DOS_GET_MEDIA_ID
        mov     cx, DOS_GET_MEDIA_ID_CX
        sub     bl, 64                      ; Turn drive into DOS drive
        mov     si, offset Buffer_Get_Media_Id
        mov     dx, si
        int     DOS_SERVICE                 ; Check Drive Presence
        cmp     ax, DOS_DRIVE_NOT_AVAILABLE ; Drive available?
        je      @@90                        ; No
                                            ; Yes, so
        mov     si, offset Buffer_Get_Media_Id.MidVolLabel
        mov     cx, VOLUME_NAME_LENGTH
        rep     movsb

@@90:
        pop     di es si ds
        add     di, VOLUME_NAME_LENGTH      ; Move to position of right hook
        mov     [byte es:di], "]"           ; Right hook
        inc     di                          ; Move to next drive

        loop    @@80

@@99:
        mov     al, NULL
        mov     [Return_Code], al

        ret

ENDP    DC_DRV



ENDS    CSeg                                ; End of Code segment

END                                         ; End of Program
