;/* ; * Microsoft Confidential ; * Copyright (C) Microsoft Corporation 1991 ; * All Rights Reserved. ; */ ;=========================================================================== ; ; FILE: GLBLINIT.ASM ; ;=========================================================================== ;=========================================================================== ;Declaration of include files ;=========================================================================== ; ;--------------------------------------------------------------------------- ; ; M024 : B#5495. Added "Insufficient memory" message when FORMAT cannot ; allocate memory for FAT, Directory... etc ; ;--------------------------------------------------------------------------- ; debug equ 0 .xlist INCLUDE BPB.INC INCLUDE DOSEQUS.INC INCLUDE DOSMAC.INC INCLUDE SYSCALL.INC INCLUDE FOREQU.INC INCLUDE FORMACRO.INC INCLUDE IOCTL.INC INCLUDE FORSWTCH.INC INCLUDE SAFEDEF.INC INCLUDE SYSVAR.INC .list ;=========================================================================== ; Data segment ;=========================================================================== DATA SEGMENT PUBLIC PARA 'DATA' SECTORS_FOR_MIRROR EQU 7 ; # extra buffer sectors ; required by Mirror utility, ; apart from FAT & Root Dir ;=========================================================================== ; Declarations for all publics in other modules used by this module ;=========================================================================== ;Bytes EXTRN msgCrLF :BYTE EXTRN DriveToFormat :BYTE EXTRN ClustBound_Flag :BYTE EXTRN FileStat :BYTE EXTRN SystemDriveLetter :BYTE EXTRN SecPerClus :BYTE EXTRN CMCDDFlag :BYTE ;Words EXTRN SwitchMap :WORD EXTRN mSize :WORD EXTRN mStart :WORD EXTRN ClustBound_Buffer_Seg :WORD EXTRN Paras_per_fat :WORD ;Pointers and DWORDs EXTRN DirectorySector :DWORD EXTRN FatSpace :DWORD EXTRN FatSector :DWORD EXTRN DirBuf :DWORD EXTRN TotalClusters :DWORD ;Messages EXTRN msgFormatNotSupported :BYTE EXTRN msgCantZThisDrive :BYTE EXTRN msgCantZWithQ :BYTE EXTRN msgCantZFAT16 :BYTE EXTRN msgCantZFAT32 :BYTE EXTRN msgZFAT32Huge :BYTE EXTRN msgZFAT32TooHuge :BYTE EXTRN msgOutOfMemory :BYTE EXTRN msgInsufficientMemory :BYTE IFNDEF OPKBLD EXTRN msgNoSysSwitch :BYTE ENDIF ;OPKBLD ;Structures EXTRN SavedParams :BYTE EXTRN DeviceParameters :BYTE EXTRN IsExtRAWIODrv :BYTE EXTRN Bios :BYTE EXTRN dos :BYTE EXTRN Command :BYTE IFDEF DBLSPACE_HOOKS EXTRN DblSpaceBin :BYTE ENDIF PUBLIC FATNotAllInMem PUBLIC FATSecCntInMem FATNotAllInMem db 0 FATSecCntInMem dd 0 ifdef NEC_98 AllocSectorSize DW ? ; fixed #16585 endif DATA ENDS ;=========================================================================== ; Executable code segment ;=========================================================================== CODE SEGMENT PUBLIC PARA 'CODE' ASSUME CS:CODE, DS:DATA, ES:DATA ;=========================================================================== ; Declarations for all publics in other modules used by this module ;=========================================================================== ;Functions ;Labels EXTRN FatalExit :NEAR EXTRN ReadDos :NEAR EXTRN SysPrm :NEAR EXTRN exclusive_access_failed :NEAR EXTRN IsLockErr? :NEAR EXTRN Calc_Big32_Fat :NEAR EXTRN Calc_Big16_Fat :NEAR EXTRN GetTotalClusters :NEAR EXTRN Yes? :NEAR ;=========================================================================== ; Declarations for all publics in this module ;=========================================================================== PUBLIC Global_Init PUBLIC GetDeviceParameters PUBLIC ModifyDevPrmsForZSwich ; for debug PUBLIC Copy_Device_Parameters PUBLIC Alloc_Dir_Buf PUBLIC Alloc_Fat_Buf PUBLIC Alloc_Fat_Sec_Buf PUBLIC Alloc_DirBuf2 PUBLIC Alloc_Cluster_Buf IFDEF OPKBLD PUBLIC Do_Switch_S ENDIF ;OPKBLD ;=========================================================================== ; ; Global_Init : This procedure first gets the default drive parameters. ; It then allocates buffer space for the root directory ; sector, FAT,a fat sector, a file header and first ; root DIR sector based on these parameters. It ; then checks for the /s switch and if this is present, ; a buffer is allocated for the system files and these ; are read into memory. A prompt to insert the system ; disk will be given in the case of removable media. ; ;=========================================================================== Global_Init proc near lea DX, DeviceParameters ; Get the default drive parameters mov DeviceParameters.DP_SpecialFunctions, 0 .errnz EDP_SPECIALFUNCTIONS NE DP_SPECIALFUNCTIONS call GetDeviceParameters jnc GotDeviceParameters call IsLockErr? jnc @f jmp exclusive_access_failed @@: Message msgFormatNotSupported stc ; Let the jump to FatalExit be made ret ; in the main routine, upon returning GotDeviceParameters: ifdef NEC_98 ; fixed #16585 cmp DeviceParameters.DP_DeviceType,DEV_HARDDISK je @f cmp DeviceParameters.DP_DeviceType,DEV_OPTICAL je @f mov AllocSectorSize,0400h jmp short Set_ok @@: push bx mov bx, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector mov AllocSectorSize,bx pop bx Set_ok: endif ; fixed #16585 call Copy_Device_Parameters ; Save the device parameters ; for when we exit cmp SecPerClus,0 je NoZSwtch mov ax,1 ; Noisy version call ModifyDevPrmsForZSwich jc gi_err NoZSwtch: ifdef NEC_98 ; If 3.5"MO, allcate memory after updating default BPB cmp DeviceParameters.DP_DeviceType, DEV_HARDDISK ; Hard disk? .errnz EDP_DEVICETYPE NE DP_DEVICETYPE jne @F ; No test DeviceParameters.DP_DeviceAttributes, 1 ; Removable? .errnz EDP_DEVICEATTRIBUTES NE DP_DEVICEATTRIBUTES jz $$IF100 ; Yes @@: endif call Alloc_Dir_Buf ; Allocate root directory buffer jc gi_memerr call Alloc_Fat_Buf ; Allocate FAT buffer jc gi_memerr call Alloc_Fat_Sec_Buf ; Allocate fat sector buffer jc gi_memerr call Alloc_DirBuf2 ; Allocate 1-sector buffer DirBuf (general- ; purpose use) jc gi_memerr call Alloc_Cluster_Buf ; get room for retry buffer IFDEF OPKBLD call Do_Switch_S ; Load system files if needed ELSE test SwitchMap,SWITCH_S jz NoS1 ; Carry clear if jump Message msgNoSysSwitch jmp short gi_err NoS1: ENDIF ;OPKBLD ; carry flag determined by Do_Switch_S ifdef NEC_98 $$IF100: endif ret gi_memerr: Message msgInsufficientMemory gi_err: stc ret Global_Init endp ; ========================================================================= ; ; ModifyDevPrmsForZSwich: ; Modify the device parameters for a different sec/clus value ; ; Input: ; DeviceParameters set ; AX != 0 for noisy version (do the message thing) ; Output: ; carry set if problem. ; ; ========================================================================= ModifyDevPrmsForZSwich proc near push ax ; Save noisy switch on stack .386 movzx cx,SecPerClus .8086 or cx,cx jz MFZDoneJ ; Carry clear if jump cmp CMCDDFlag, Yes jne DrvOk1 DispErrMsg: mov dx,offset data:msgCantZThisDrive DispErrMsgSet: pop ax push ax or ax,ax jz MFZDoneErrJ call Display_Interface MFZDoneErrJ: stc MFZDoneJ: jmp MFZDone DrvOk1: ;; ;; This used to ignore things if you weren't actually making a change. ;; This is now out as it is important to poke Mr. User if he is making ;; a huge FAT drive. ;; ;; cmp cl,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster ;; je MFZDoneJ ; Carry clear if jump ;;;; mov dx,offset data:msgCantZWithQ test SwitchMap,SWITCH_Q ; Check for quick format jnz DispErrMsgSet mov DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster,cl cmp DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFAT,0 je IsFAT32 call Calc_Big16_Fat mov dx,0002h xor ax,ax ; DX:AX = 128k bytes mov cx,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector div cx ; AX = Sectors in 128k cmp ax,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFAT jb Bad16 .386 ja MFZDone ; Carry clear if jump .8086 call GetTotalClusters .386 cmp TotalClusters,0000FFF0h .8086 cmc ; Change "JB Is-OK" to "JNC Is-OK" jnc MFZDone Bad16: mov dx,offset data:msgCantZFAT16 jmp short DispErrMsgSet IsFAT32: call Calc_Big32_Fat call GetTotalClusters .386 cmp TotalClusters,65536-10 .8086 mov dx,offset data:msgCantZFAT32 jb DispErrMsgSet .386 mov eax,TotalClusters inc eax ; EAX now count including clus 0 and 1 ; ; GUI SCANDISK is a 16-bit windows app. GlobalAlloc in 16-bit windows is ; limited to 16Meg-64k per block. Check if we have made a drive with a huge FAT ; that may result in slow disk util perf. ; cmp eax, ((16 * 1024 * 1024) - (64 * 1024)) / 4 je short MFZDone ; carry clear if jump cmc ; Turn carry around so clear if below limit jnc short MFZDone .8086 pop ax push ax or ax,ax ; Noisy? jz MFZDone ; No, Carry clear if jump Message msgZFAT32Huge call Yes? ; Carry clear if YES, set if NO pushf Message msgCrlf popf MFZDone: pop ax ret ModifyDevPrmsForZSwich endp ; ========================================================================= ; ; GetDeviceParameters: ; Get the device parameters ; ; Input: ; DriveToFormat ; DX - pointer to device parameters ; ========================================================================= GetDeviceParameters proc near mov AX, (IOCTL shl 8) or GENERIC_IOCTL mov bl, DriveToFormat inc bl mov CX, (EXTRAWIO shl 8) or GET_DEVICE_PARAMETERS int 21H jc TryOldForm mov IsExtRAWIODrv,1 DoRet: jc realdoret push bx mov bx,dx cmp [bx.DP_BPB.oldBPB.BPB_TotalSectors],0 je realdoretP ; ; the WORD total sectors field is non-zero, make sure the DWORD ; total sectors field is 0. Having BigTotalSectors be a DWORD ; version of TotalSectors in this case is SUPPOSED to be perfectly ; ok but it turns out that several apps (mostly SETUP apps) get ; upset about this (on floppies in particular). ; mov [bx.DP_BPB.oldBPB.BPB_BigTotalSectors],0 mov [bx.DP_BPB.oldBPB.BPB_BigTotalSectors+2],0 realdoretP: pop bx clc realdoret: return TryOldForm: mov IsExtRAWIODrv,0 mov AX, (IOCTL shl 8) or GENERIC_IOCTL mov bl, DriveToFormat inc bl mov CX, (RAWIO shl 8) or GET_DEVICE_PARAMETERS int 21H jmp short DoRet GetDeviceParameters endp ;========================================================================== ; ; Copy_Device_Parameters : This procedure saves a copy of the original ; device parameters in the structure ; SavedParams. ; ;========================================================================== Copy_Device_Parameters proc near lea SI, DeviceParameters lea DI, SavedParams mov CX, size EA_DeviceParameters push DS pop ES rep movsb ret Copy_Device_Parameters endp ;========================================================================== ; ; Alloc_Dir_Buf : This procedure allocates a memory block for the root ; directory buffer, based on the device parameters only. ; ; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector ; Outputs : CY CLEAR - DirectorySector pointer to buffer ; CY SET - failure ; Modifies : AX, BX, DirectorySector ; ;========================================================================== Alloc_Dir_Buf proc near ; DirectorySector = ; malloc( Bytes Per Sector ) ifdef NEC_98 ; fixed #16585 mov BX, AllocSectorSize else mov BX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector endif .errnz EDP_BPB NE DP_BPB add BX, 0fH .386 shr bx, 4 ; Divide by 16 to get #paragraphs .8086 mov AH, Alloc int 21h jc Exit_Alloc_Dir_Buf ; Base address of newly allocated ; block is AX:0000 mov WORD PTR DirectorySector+2,AX xor AX,AX mov WORD PTR DirectorySector,AX Exit_Alloc_Dir_Buf: ret Alloc_Dir_Buf endp ;========================================================================== ; ; Alloc_Fat_Buf : This procedure allocates a memory block for the FAT ; buffer, based on the device parameters only. In order ; to ensure there is enough buffer space for the Mirror ; utility, the FatSpace buffer is initially allocated ; with size: ; FAT + RootDir + 6 sectors + 1 surplus sector ; which is all the buffer space required by Mirror. ; ; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector ; DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat ; DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat ; DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries ; ; Outputs : CY CLEAR - FatSpace pointer to buffer ; CY SET - failure ; ; Modifies : AX, BX, DX, FatSpace ; ;========================================================================== Alloc_Fat_Buf proc near xor ax,ax mov FATNotAllInMem,al ; Assume FAT will fit in mem .386 ifdef NEC_98 ; fixed #16585 cmp DeviceParameters.DP_DeviceType, DEV_3INCH1440KB jne short $$IF101 cmp DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors, 0 je short $$IF101 movzx EAX, AllocSectorSize jmp short $$EN101 $$IF101: movzx EAX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector $$EN101: else movzx EAX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector endif .errnz EDP_BPB NE DP_BPB add EAX, 0fH ; round up for next para shr eax, 4 ; convert to paras movzx ebx,DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerFat or bx,bx jnz short GotFSz mov ebx,dword ptr DeviceParameters.DP_BPB.BGBPB_BigSectorsPerFat GotFSz: mul ebx or edx,edx jz short NotHi GotBigFat: mov FATNotAllInMem,1 mov eax,128*1024 movzx ebx,DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector xor edx,edx div ebx mov FATSecCntInMem,eax mov ax,(128*1024)/16 jmp short SetRestFatBuf NotHi: cmp eax,(128*1024)/16 ; FAT bigger than 128k? ja short GotBigFat ; Yes SetRestFatBuf: .8086 mov BX,AX ; Save FAT size in paras in BX mov Paras_per_fat,BX ; Set paras_per_fat here, to ; avoid having to calculate it later ; Now add on root dir + extra sectors mov AX,DeviceParameters.DP_BPB.oldBPB.BPB_RootEntries ;; shl ax,5 ; * 32 bytes per dor entry ;; shr ax,4 ; / 16 bytes per para ;; Combine above two shifts.... shl AX,1 ; AX = para size of root dir add BX,AX ; BX = FAT + root dir ifdef NEC_98 ; fixed #16585 cmp DeviceParameters.DP_DeviceType, DEV_3INCH1440KB jne $$IF102 cmp DeviceParameters.DP_BPB.oldBPB.BPB_TotalSectors, 0 je $$IF102 mov AX, AllocSectorSize jmp short $$EN102 $$IF102: mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector $$EN102: else mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector endif add AX, 0fH ; round up for next para .386 shr AX, 4 ; convert to paras .8086 mov CX,SECTORS_FOR_MIRROR ; CX = # additional sectors needed by Mirror mul CX ; AX = total extra sector size in paras add BX,AX ; BX = FAT + root dir + extra sectors ; in paras mov AH,Alloc int 21h jc Exit_Alloc_Fat_Buf mov WORD PTR FatSpace+2,AX xor AX,AX mov WORD PTR FatSpace,AX Exit_Alloc_Fat_Buf: ret Alloc_Fat_Buf endp ;========================================================================== ; ; Alloc_Fat_Sec_Buf : This procedure allocates a memory block for the fat ; sector buffer which is used when copying chains from ; the old FAT to the new FAT. ; ; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector ; Outputs : CY CLEAR - FatSector pointer to buffer ; CY SET - failure ; Modifies : AX, BX, FatSector ; ;========================================================================== Alloc_Fat_Sec_Buf proc near ; FatSector = ; malloc( Bytes Per Sector ) ifdef NEC_98 ; fixed #16585 mov BX, AllocSectorSize else mov BX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector endif .errnz EDP_BPB NE DP_BPB add BX, 0fH .386 shr BX, 4 ; Divide by 16 to get #paragraphs .8086 mov AH, Alloc int 21h jc Exit_Alloc_Fat_Sec_Buf ; Base address of newly allocated ; block is AX:0000 mov WORD PTR FatSector+2,AX xor AX,AX mov WORD PTR FatSector,AX Exit_Alloc_Fat_Sec_Buf: ret Alloc_Fat_Sec_Buf endp ;========================================================================== ; ; Alloc_DirBuf2 : This procedure allocates a memory block for a 1-sector ; buffer. This buffer is used when reading in the boot ; sector in Phase1. ; ; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector ; Outputs : CY CLEAR - DirBuf pointer to buffer ; CY SET - failure ; Modifies : AX, BX, DirBuf ; ;========================================================================== Alloc_DirBuf2 proc near ; DirBuf = ; malloc( Bytes Per Sector ) ifdef NEC_98 ; fixed #16585 mov BX, AllocSectorSize else mov BX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector endif .errnz EDP_BPB NE DP_BPB add BX, 0fH .386 shr BX, 4 ; Divide by 16 to get #paragraphs .8086 mov AH, Alloc int 21h jc Exit_Alloc_DirBuf2 ; Base address of newly allocated ; block is AX:0000 mov WORD PTR DirBuf+2,AX xor AX,AX mov WORD PTR DirBuf,AX Exit_Alloc_DirBuf2: ret Alloc_DirBuf2 endp ;========================================================================= ; Alloc_Cluster_Buf : This routine will allocate a buffer ; based on a cluster's size. If enough ; space does not exist, a cluster will ; be redefined to a smaller size for ; purposes of sector retries. ; Note: This buffer is used only for bad ; tracks on hard disks. ; ; Inputs : DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector ; DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster ; ; Outputs : ClustBound_Flag - True (space available) ; False(not enough space) ; ClustBound_Buffer_Seg - Pointer to buffer ;========================================================================= Procedure Alloc_Cluster_Buf push AX ; Save regs push BX mov AX,(Alloc shl 8) ; Allocate memory mov BX,0ffffh ; Get available memory int 21h ifdef NEC_98 ; fixed #16585 mov AX, AllocSectorSize else mov AX, DeviceParameters.DP_BPB.oldBPB.BPB_BytesPerSector endif .errnz EDP_BPB NE DP_BPB add AX, 0fH .386 shr AX, 4 .8086 mul DeviceParameters.DP_BPB.oldBPB.BPB_SectorsPerCluster cmp BX,AX ; Enough room jna $$IF137 ; Yes mov BX,AX ; Allocate needed memory mov AX,(Alloc shl 8) int 21h mov ClustBound_Buffer_Seg,AX ; Save pointer to buffer mov ClustBound_Flag,True ; Signal space available jmp SHORT $$EN137 ; Not enough room $$IF137: mov ClustBound_Flag,False ; Signal not enough space $$EN137: pop BX ; Restore regs pop AX ret Alloc_Cluster_Buf ENDP IFDEF OPKBLD ;========================================================================= ; ; DO_SWITCH_S : This procedure will load the system files into ; memory (if there's space) if the /s switch is ; specified. ; ; CALLS : ReadDos ; SysPrm ; CALLED BY : Global_Init ; STRATEGY : The largest block of memory available is first ; determined. The program is aborted if this is zero. ; This block is then allocated, and the system files ; are read into it. A prompt for the system disk ; will be given if the system files are not found. ; ;========================================================================= Do_Switch_S proc near test SwitchMap,SWITCH_S .386 jz End_Do_Switch_S ; System files not required ; allocate memory for system files .8086 mov BX,0ffffh ; This call will actually fail mov AH,Alloc ; so that BX returns max block avlbl int 21h or BX,BX jz MemErr ; No memory mov [mSize],BX ; Now allocate the largest block mov AH,alloc int 21h jnc Mem_OK MemErr: mov AX, seg data ; Check for memory allocation error mov DS, AX Message msgOutOfMemory ; call PrintString stc ; Let the jump to FatalExit be made jmp End_Do_Switch_S ; in the main routine, upon returning Mem_OK: mov [mStart],AX ; Save the starting paragraph ; ========================================================================= ; This call to ReadDos may not be able to read in all of the DOS files if ; there is insufficient memory available. In that case the files will ; be read in after the disk is formatted. If the Drive being formatted is ; also the boot Drive this function will read the files from that ; Drive if there is enough memory. If there is insufficent memory it will ; force the files to be read from Drive A: if the Drive being formatted ; is also the boot Drive ; M011; Wrong: Try Boot, Then Default, Then sysprm (usually "A"). ; If not enough memory at boot time, we fail. ; ========================================================================= RdFrst: mov AH,GET_DEFAULT_Drive ; Find out default Drive int 21h push AX ; save default Drive mov ax, 3305h ; get startup drive int 21h mov al,dl add AL,40h ; Make it ASCII pop BX ; restore default Drive ifndef NEC_98 cmp AL,41h ; Q: Booted from Drive A? jnz go_get_Bios ; N: Not a special case cmp bl,1 ; Q: is B: current Drive jnz go_get_Bios ; N: Not a special case jmp short check_default ; check default Drive endif go_get_Bios: ; Here to check booted call Get_Host_Drive ; Translate to DblSpace host mov SystemDriveLetter,AL ; (if necessary) call ReadDos jnc CheckAllFilesIn check_default: ; Here to check default mov AH,GET_DEFAULT_Drive ; Find out default Drive int 21h add AL,41h ; Make it ASCII, 1 based call Get_Host_Drive ; Translate to DblSpace host mov SystemDriveLetter,AL TryThisOne: call ReadDos ; Read BIOS and DOS jnc CheckAllFilesIn ; Files read in OK NeedSys: call SysPrm ; Prompt for system disk jmp TryThisOne ; Try again CheckAllFilesIn: ; abort program here if all system files ; have not been read into memory, since ; program fails when trying to read them ; in after formatting is complete and FileStat,3fh ; zero out 2 msb cmp FileStat,22h ; BIOS and COMMAND in memory? jne MemErr ; no - abort program ; ; Now we have all of the files in memory, SETBLOCK the allocation ; block down to the amount required. ; .386 mov bx,[dos.fileStartSegment] mov eax,[dos.fileSizeInBytes] cmp bx,[bios.fileStartSegment] ja short Skip1 mov bx,[bios.fileStartSegment] mov eax,[bios.fileSizeInBytes] Skip1: cmp bx,[command.fileStartSegment] ja short Skip2 mov bx,[command.fileStartSegment] mov eax,[command.fileSizeInBytes] Skip2: IFDEF DBLSPACE_HOOKS cmp bx,[DblSpaceBin.fileStartSegment] ja short Skip3 mov bx,[DblSpaceBin.fileStartSegment] mov eax,[DblSpaceBin.fileSizeInBytes] Skip3: ENDIF add eax,15 shr eax,4 ; AX = # of paras from SEG BX .8086 add bx,ax ; SEG after end of sys files sub bx,[mStart] ; SIZE of sys area mov es,[mStart] mov AH,setblock int 21h clc ; yes End_Do_Switch_S: ret Do_Switch_S ENDP ;******************* START OF SPECIFICATIONS *********************************** ;Routine name: Get_Host_Drive ;******************************************************************************* ; ;Description: Given a drive letter in AL, check to see if it is a dblspace ; drive, and if so, translate the drive letter to the host ; drive letter. ; ;Called Procedures: None ; ;Input: ASCII drive letter in AL ; ;Output: drive letter in AL ; ;Change History: Created 11/21/92 MD ; Cut and paste from SYS command 12/07/92 JEM ; ;******************* END OF SPECIFICATIONS ************************************* public Get_Host_Drive Get_Host_Drive PROC NEAR push ax mov ax,4a11h ; DBLSPACE multiplex number xor bx,bx ; inquire version number int 2fh or ax,ax ; error? jnz not_dblspace cmp bx,'DM' ; stamp returned correctly? jnz not_dblspace ; DBLSPACE.BIN is loaded. At this time: ; ; (dx & 0x7fff) == driver internal version number ; high bit of DH set of driver has not yet been permanently placed ; cl == first disk letter reserved for DBLSPACE ; ch == number of disk letters reserved for DBLSPACE mov ax,4a11h ; DBLSPACE multiplex number mov bx,1 ; inquire drive map pop dx push dx sub dl, 'A' ; convert drv letter to 0 based drv number int 2fh test bl,80h ; COMPRESSED bit true? jz not_dblspace ; Drive is compressed. At this time: ; ; (bl & 0x7f) == host drive's CURRENT drive number ; bh == CVF extension number ; mov al,bl and al,7Fh add al, 'A' ; convert drv number to drv letter cbw pop dx push ax not_dblspace: pop ax ret Get_Host_Drive ENDP ENDIF ;OPKBLD CODE ENDS END