mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1586 lines
35 KiB
1586 lines
35 KiB
;****************************************************************************
|
|
;* *
|
|
;* WFDISK.ASM - *
|
|
;* *
|
|
;* Format and Diskcopy utility routines *
|
|
;* *
|
|
;****************************************************************************
|
|
|
|
include winfile.inc
|
|
|
|
externFP GlobalDOSAlloc
|
|
externFP GlobalDOSFree
|
|
|
|
externFP GetDriveCapacity
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
createSeg _%SEGNAME, %SEGNAME, WORD, PUBLIC, CODE
|
|
|
|
sBegin DATA
|
|
Big32Sector dd ?
|
|
Big32Count dw ?
|
|
Big32BufPtr dd ?
|
|
sEnd
|
|
|
|
sBegin %SEGNAME
|
|
|
|
assumes CS,%SEGNAME
|
|
assumes DS,DATA
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* LongMult() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Death to the C-Runtimes!!!
|
|
|
|
cProc LongMult, <PUBLIC,FAR>
|
|
|
|
ParmW x
|
|
ParmW y
|
|
|
|
cBegin
|
|
mov ax,x
|
|
mov bx,y
|
|
mul bx
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* LongDiv() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Death to the C-Runtimes!!!
|
|
|
|
cProc LongDiv, <PUBLIC,FAR>
|
|
|
|
ParmD dwDivident
|
|
ParmW wDivisor
|
|
|
|
cBegin
|
|
mov ax,OFF_dwDivident
|
|
mov dx,SEG_dwDivident
|
|
mov bx,wDivisor
|
|
div bx
|
|
cEnd
|
|
|
|
|
|
cProc LongShift, <PUBLIC,FAR>
|
|
|
|
ParmD dwValue
|
|
ParmW wCount
|
|
|
|
cBegin
|
|
mov ax,OFF_dwValue
|
|
mov dx,SEG_dwValue
|
|
mov cx,wCount
|
|
LSLoop:
|
|
shr dx,1
|
|
rcr ax,1
|
|
loop LSLoop
|
|
cEnd
|
|
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* SetDASD() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
cProc SetDASD, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
parmW drive
|
|
parmB dasdvalue
|
|
|
|
cBegin
|
|
mov bx,drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
mov ah,17h
|
|
mov al,dasdvalue
|
|
int 13h
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* GetDBT() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
cProc GetDBT, <PUBLIC,FAR>
|
|
|
|
cBegin nogen
|
|
; Get Interrupt Vector 1E
|
|
mov ah,35h
|
|
mov al,1Eh
|
|
cCall DOS3Call
|
|
mov dx,es ; ES:BX contains the DISK BASE TABLE
|
|
mov ax,bx
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* GetDOSVersion() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
cProc GetDOSVersion, <PUBLIC,FAR>
|
|
|
|
cBegin nogen
|
|
mov ah,30h
|
|
cCall DOS3Call
|
|
xchg ah,al
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;*
|
|
;* int FAR PASCAL DeviceParameters(WORD, PDevPB, WORD);
|
|
;*
|
|
;* drive 0 based drive number
|
|
;* pDevPB pointer to device parameter block to set/get
|
|
;* wFunction 0x40 to Set, 0x60 to Get
|
|
;*
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
cProc DeviceParameters, <PUBLIC,FAR>
|
|
|
|
parmW drive
|
|
parmW pDevPB
|
|
parmW wFunction
|
|
|
|
cBegin
|
|
mov dx,pDevPB
|
|
mov ax,440Dh ; IOCTL: Generic I/O Control for Block Devices
|
|
mov bx,drive
|
|
inc bx ; 1-based drive numbers
|
|
mov ch,08h ; Minor Code
|
|
mov cl, byte ptr wFunction ; Get/Set Device Parameters
|
|
cCall DOS3Call
|
|
jc GDP_Error
|
|
xor ax, ax ; No error
|
|
GDP_Error: ;Error code in AX
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* DiskReset() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Flushes out the disk buffer.
|
|
|
|
cProc DiskReset, <PUBLIC,FAR>
|
|
|
|
cBegin nogen
|
|
mov ah,0Dh
|
|
cCall DOS3Call
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* GetDPB() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Returns the DPB for the specified drive.
|
|
|
|
cProc GetDPB, <PUBLIC,FAR>, <DS,SI,DI>
|
|
ParmW drive
|
|
ParmW pDPB
|
|
|
|
cBegin
|
|
push ds ; Save DS on stack
|
|
|
|
; DOS Function 32h is GetDPB() - Get the Drive Parameter Block
|
|
; Input : DL = Drive (1 = A, 2 = B, ...)
|
|
; Output: AL = 0, if successful and DS:BX points to the DPB.
|
|
; AL = -1, if invalid drive.
|
|
|
|
mov ah,32h ; GetDPB system call
|
|
mov dx,drive
|
|
inc dx ; 1-based drive numbers
|
|
int 21h
|
|
|
|
cbw ; Extend error into AX
|
|
or ax,ax ; Problems?
|
|
jnz gdpbdone ; Yup, return
|
|
|
|
mov si,bx
|
|
pop es ; Make ES = DS from stack;
|
|
mov di,pDPB
|
|
mov cx,SIZE DPB
|
|
cld
|
|
rep movsb
|
|
|
|
; Intensely stupid DOS 4.0 hack -
|
|
; IBM has changed the "FAT_size" field in the DPB structure from a
|
|
; byte to a word in DOS 4.0 causing us to misread any variables in
|
|
; the structure after this field. This super-sleazy hack rep moves
|
|
; the rest of the structure up one byte, effectively converting "FAT_
|
|
; size" back into a byte. ChipA 22-Jun-1988
|
|
|
|
push ax ; Preserve AX
|
|
|
|
call GetDOSVersion ; DOS 4.0 or greater?
|
|
cmp ax,0400h
|
|
jb gdpbdone
|
|
|
|
push es ; DS=ES
|
|
pop ds
|
|
mov si,pDPB ; Source at DPB.dpb_dir_sector
|
|
add si,17
|
|
mov di,si ; Destination up one
|
|
dec di
|
|
mov cx,16
|
|
rep movsb
|
|
|
|
gdpbdone:
|
|
pop ax
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* SetDPB() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Fakes up a DPB from the BPB on the disk in the specified drive.
|
|
|
|
cProc SetDPB, <PUBLIC,FAR>, <DS,SI,DI>
|
|
|
|
ParmW drive
|
|
ParmW pBPB
|
|
ParmW pDPB
|
|
|
|
cBegin
|
|
;
|
|
; What Follows is DOS function call 53h (SetDPB() - to Build a
|
|
; Drive Parameter Block given a Bios Parameter Block.
|
|
; Input: ES:BP points to the place where DPB is to be built
|
|
; DS:SI points to the given BPB
|
|
; Output: All registers except ES:BP and DS are destroyed;
|
|
; ES:BP points to the newly built DPB
|
|
|
|
; Inorder for this function to work correctly in protect mode,
|
|
; ES:BP must point to a DOS Addressable memory; To ensure that
|
|
; we allocate a GlobalDOSAlloc() and pass the ptr to it
|
|
|
|
xor ax,ax
|
|
push ax
|
|
mov ax,SIZE DPB
|
|
push ax
|
|
cCall GlobalDOSAlloc ; DX=Seg address; AX=HANDLE/Selector
|
|
or ax,ax
|
|
jz SDPB_Err
|
|
mov es,ax ; Selector address is in ES
|
|
mov si,pBPB ; DS:SI = BPB
|
|
|
|
mov cx,drive ; CX = drive
|
|
|
|
push bp ; Save BP
|
|
xor bp,bp ; ES:BP = global DPB
|
|
mov byte ptr es:[bp],cl ; Set the DPB drive number
|
|
mov ah,53h
|
|
;; win3.1 now has a C prolog on DOS3Call. this causes
|
|
;; BP to be trashed. since we won't be doing format on OS/2
|
|
;; just go ahead and
|
|
;; cCall DOS3Call
|
|
int 21h
|
|
xor si,si ; Save the pointer to DPB
|
|
pop bp ; Restore bp
|
|
push ax ; Save the return code
|
|
|
|
; Make a local copy of DPB from global DPB
|
|
mov di,pDPB
|
|
mov ax,es ; move tmp, es
|
|
push ds ; move es, ds
|
|
pop es
|
|
mov ds,ax ; mov ds, tmp
|
|
mov cx,SIZE DPB
|
|
rep movsb
|
|
|
|
; Now release the global memory allocated
|
|
push ds ; Handle to be freed is passed to GlobalDOSFree
|
|
;When GLobalDOSFree() returns, the handle stored in DS is freed and
|
|
;hence invalid; So, assign a valid selector to DS before the call.
|
|
push es
|
|
pop ds ; DS = ES
|
|
cCall GlobalDOSFree
|
|
|
|
; Intensely stupid DOS 4.0 hack -
|
|
; IBM has changed the "FAT_size" field in the DPB structure from a
|
|
; byte to a word in DOS 4.0 causing us to misread any variables in
|
|
; the structure after this field. This super-sleazy hack rep moves
|
|
; the rest of the structure up one byte, effectively converting "FAT_
|
|
; size" back into a byte. ChipA 22-Jun-1988
|
|
|
|
call GetDOSVersion ; DOS 4.0 or greater?
|
|
cmp ax,0400h
|
|
jb SDExit
|
|
|
|
push ds ; ES=DS
|
|
pop es
|
|
mov si,pDPB ; Source at DPB.dpb_dir_sector
|
|
add si,17
|
|
mov di,si ; Destination up one
|
|
dec di
|
|
mov cx,16
|
|
rep movsb
|
|
|
|
SDExit: pop ax ; Restore the return code
|
|
SDPB_Err:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* ModifyDPB() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Used for preparing diskettes for receiving the System files.
|
|
;
|
|
; This obtains the DPB and modifies the DPB_next_free field to contain
|
|
; a value of 2, because after deleting the SYS files in the destination
|
|
; disk, the newly copied files should occupy starting from Cluster 2.
|
|
|
|
cProc ModifyDPB, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
ParmW drive
|
|
|
|
cBegin
|
|
push ds ; Save DS on stack
|
|
|
|
; DOS Function 32h is GetDPB() - Get the Drive Parameter Block
|
|
; Input : DL = Drive (1 = A, 2 = B, ...)
|
|
; Output: AL = 0, if successful and DS:BX points to the DPB.
|
|
; AL = -1, if invalid drive.
|
|
|
|
mov ah,32h ; GetDPB system call
|
|
mov dx,drive
|
|
inc dx ; 1-based drive number
|
|
int 21h
|
|
|
|
cbw ; Extend error into AX
|
|
or ax,ax ; Problems?
|
|
jnz mdpbDone ; Yup, return
|
|
|
|
push ds ; Save ds:bx (pointer to DPB)
|
|
push bx
|
|
|
|
; Get Dos Version
|
|
cCall GetDOSVersion
|
|
pop bx ; Restore ds:bx (pointer to DPB)
|
|
pop ds
|
|
cmp ah,4 ; Are we dealing with quirky DOS 4?
|
|
jb mdpb_DOS3
|
|
mov ds:[bx].DPB_next_free+1,2 ; Yup, handle messed up structure
|
|
jmp short mdpb2
|
|
mdpb_DOS3:
|
|
mov ds:[bx].DPB_next_free,2 ; DOS 3.X
|
|
mdpb2:
|
|
xor ax,ax ; Success returns 0
|
|
mdpbDone:
|
|
pop ds ; Restore DS
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* MyInt25() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Performs a direct sector read from the specified drive.
|
|
; Returns 0 if successful otherwise it returns the DOS INT 25h error code.
|
|
|
|
; WARNING: INT 25h does NOT preserve registers. SI & DI must be preserved!
|
|
|
|
ParamBlockStruc struc
|
|
LO_sector dw ? ; Lo word of starting sector
|
|
HI_sector dw ? ; Hi word of starting sector
|
|
SecCount dw ? ; Number of sectors to read
|
|
BuffOff dw ? ; Offset of Buffer
|
|
BuffSeg dw ? ; Segment of Buffer
|
|
ParamBlockStruc ends
|
|
|
|
cProc MyInt25, <PUBLIC,FAR>, <DS,SI,DI>
|
|
|
|
ParmW drive ; 0-based drive number
|
|
ParmD buffer ; LPSTR
|
|
ParmW count ; # of sectors to read
|
|
ParmW sector ; Starting sector
|
|
|
|
LocalV ParamBlock, %(size ParamBlockStruc)
|
|
|
|
cBegin
|
|
mov ax,drive
|
|
lds bx,buffer
|
|
mov cx,count
|
|
mov dx,sector
|
|
push bp ; Save BP
|
|
int 25h
|
|
pop bx ; Remove flags from stack
|
|
pop bp ; Restore BP
|
|
jnc MyInt25_end
|
|
|
|
; If this has failed, it could be a partition > 32 Meg. So, try
|
|
; again assuming Partition size is > 32 Meg. If this also fails,
|
|
; this is really an error;
|
|
|
|
mov ax,drive
|
|
|
|
; Fill the parameter block with proper values
|
|
mov dx,sector
|
|
mov ParamBlock.LO_sector,dx ; Starting sector
|
|
|
|
; We get only 16 bit starting sector; So, hi word is made zero
|
|
mov ParamBlock.HI_sector,0
|
|
|
|
; The number of sectors to be read
|
|
mov dx,count
|
|
mov ParamBlock.SecCount,dx
|
|
|
|
; The address of the buffer to read into
|
|
mov dx,OFF_buffer
|
|
mov ParamBlock.BuffOff,dx
|
|
mov dx,SEG_buffer
|
|
mov ParamBlock.BuffSeg,dx
|
|
|
|
; Keep the address of ParamBlock is DS:BX
|
|
lea bx,ParamBlock
|
|
push ss
|
|
pop ds
|
|
mov cx,-1 ; > 32Meg partition
|
|
push bp ; Save BP
|
|
int 25h
|
|
pop bx ; Remove the flags on stack
|
|
pop bp ; Restore BP
|
|
|
|
MyInt25_end:
|
|
jc MyInt25_err
|
|
xor ax,ax ; Return 0 if successful
|
|
MyInt25_err:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* MyInt26() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Performs a direct sector write to the specified drive.
|
|
; Returns 0 if successful otherwise it returns the DOS INT 26h error code.
|
|
|
|
cProc MyInt26, <PUBLIC,FAR>, <DS,SI,DI>
|
|
|
|
ParmW drive
|
|
ParmD buffer
|
|
ParmW count
|
|
ParmW sector
|
|
|
|
cBegin
|
|
mov ax,drive
|
|
lds bx,buffer
|
|
mov cx,count
|
|
mov dx,sector
|
|
xor di, di
|
|
;; push bp ; Save BP
|
|
call DoINT26
|
|
;; int 26h
|
|
;; pop bx ; Pop of the flags on stack
|
|
;; pop bp ; Restore BP
|
|
jc MyInt26_err
|
|
xor ax,ax ; Return 0 if success
|
|
MyInt26_err: ; Return AX != 0 and Carry set on error
|
|
cEnd
|
|
|
|
|
|
|
|
if 1
|
|
|
|
;; this stuff stolen from spart
|
|
; This is the extension structure used on DOS 4.X INT 25/26 for large
|
|
; media. DS:BX -> this structure and CX = -1.
|
|
;ABS_32RW struc
|
|
; Big32Sector dd ?
|
|
; Big32Count dw ?
|
|
; Big32BufPtr dd ?
|
|
;ABS_32RW ends
|
|
|
|
; **
|
|
; DoINT26 -- Perform an abs disk write
|
|
;
|
|
; ENTRY:
|
|
; AL = Drive Number (A=0)
|
|
; CX is sector count
|
|
; DI:DX is start sector #
|
|
; DS:BX is transfer address
|
|
; SS = DATA
|
|
; EXIT:
|
|
; Carry Set
|
|
; AX = INT 26 Error code
|
|
; Carry Clear
|
|
; OK
|
|
; USES:
|
|
; All but DS,ES,BP
|
|
;
|
|
|
|
DoINT26 proc near
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
assumes ss,data
|
|
|
|
push bp
|
|
push ds
|
|
push es
|
|
|
|
push ax ; Save stuff
|
|
push dx
|
|
push di
|
|
push cx
|
|
push bx
|
|
int 26h
|
|
pop dx ; Flags
|
|
jnc NotRandoBigFoot2
|
|
cmp ax,0207h ; Rando MS-DOS BIGFOOT error?
|
|
jz MSDOSBF2 ; Yes, do like DOS 4.X
|
|
cmp ax,0408h ; Rando COMPAQ BIGFOOT error?
|
|
jnz Bad26P ; No ????????
|
|
pop bx
|
|
pop cx
|
|
pop di
|
|
pop dx
|
|
pop ax
|
|
or al,80h ; Set high bit of drive for randoBigFoot
|
|
jmp short Do261
|
|
|
|
Bad26P:
|
|
add sp,5*2 ; pop ax dx di cx bx
|
|
stc
|
|
jmp short Do261OK
|
|
|
|
NotRandoBigFoot2:
|
|
add sp,5*2
|
|
clc
|
|
jmp short Do261OK
|
|
|
|
MSDOSBF2:
|
|
pop bx
|
|
pop cx
|
|
pop di
|
|
pop dx
|
|
pop ax
|
|
|
|
DOS4Write1:
|
|
push bx
|
|
mov bx, dataOffset Big32Sector
|
|
pop word ptr ss:[Big32BufPtr]
|
|
mov word ptr ss:[Big32BufPtr + 2],ds
|
|
push ss
|
|
pop ds
|
|
mov [Big32Count],cx
|
|
mov cx,0FFFFh
|
|
mov word ptr [Big32Sector],dx
|
|
mov word ptr [Big32Sector + 2],di
|
|
Do261:
|
|
int 26h
|
|
pop dx ; Flags
|
|
Do261OK:
|
|
pop es
|
|
pop ds
|
|
pop bp
|
|
ret
|
|
|
|
DoINT26 endp
|
|
|
|
endif
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* IOCTL_Functions() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Uses IOCTL DOS functions to read/write/Format.
|
|
|
|
cProc IOCTL_Functions, <PUBLIC, FAR>, <SI,DI,DS>
|
|
|
|
ParmD lpParamBlock ; Parameter block
|
|
ParmW Function ; 61h for Read, 41h for Write, 42h for format
|
|
ParmW Drive ; 0 => A, 1 => B, ...
|
|
|
|
cBegin
|
|
mov ax, 440Dh
|
|
mov bl, byte ptr Drive
|
|
inc bl ; Make it 1 relative;
|
|
mov ch, 08h
|
|
mov cl, byte ptr Function
|
|
lds dx, lpParamBlock
|
|
cCall DOS3Call
|
|
jc DOS_RWS_Error
|
|
xor ax, ax ; Returns zero, if success;
|
|
jmp short DOS_RWS_End
|
|
DOS_RWS_Error: ; AX contains error code, if failure;
|
|
mov ah, 59h ; Get the extended error code;
|
|
xor bx, bx
|
|
cCall DOS3Call
|
|
DOS_RWS_End:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* MyReadWriteSector() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Uses INT 13h to read/write an absolute sector.
|
|
|
|
cProc MyReadWriteSector, <PUBLIC, FAR>, <SI,DI>
|
|
|
|
ParmD lpBuffer
|
|
ParmW Function ; 02 for Read and 03 for Write
|
|
ParmW Drive
|
|
ParmW Cylinder
|
|
ParmW Head
|
|
ParmW Count
|
|
|
|
LocalW wRetryCount
|
|
|
|
cBegin
|
|
; Retry this operation three times.
|
|
mov wRetryCount,4
|
|
|
|
MRWS_TryAgain:
|
|
mov ax,Count ; AL = Number of sectors
|
|
mov ah,byte ptr Function ; AH = Function #
|
|
mov ch,byte ptr Cylinder ; CH = Starting Cylinder
|
|
mov cl,1 ; CL = Starting Sector
|
|
|
|
mov bx,Drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx] ; DL = INT 13h drive designation
|
|
|
|
mov dh,byte ptr Head ; DH = Head #
|
|
les bx,lpBuffer ; ES:BX = Buffer
|
|
int 13h
|
|
|
|
jnc MRWS_End ; Problems?
|
|
dec wRetryCount ; Yup, retry
|
|
jz MRWS_End ; Are we out of retries?
|
|
|
|
xor ah,ah ; Nope, reset the disk
|
|
mov bx,Drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
int 13h
|
|
jmp short MRWS_TryAgain
|
|
MRWS_End:
|
|
xor al,al ; AH contains the error code, if any.
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* FormatTrackHead() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Formats and Verifies a diskette track. Stores the track table in the
|
|
; specified buffer.
|
|
|
|
cProc FormatTrackHead, <PUBLIC,FAR>, <DS,SI,DI>
|
|
|
|
ParmW drive
|
|
ParmW track
|
|
ParmW head
|
|
ParmW cSec
|
|
ParmD lpTrack
|
|
|
|
LocalD lpTrackTbl
|
|
LocalW retry
|
|
|
|
cBegin
|
|
les di,lpTrack ; ES:DI = Sector Buffer
|
|
cld
|
|
mov cx,cSec ; CX = Number of Sectors
|
|
|
|
; Build the Track Address table in the Sector Buffer.
|
|
mov OFF_lpTrackTbl,di ; lpTrackTbl = &Sector Buffer
|
|
mov SEG_lpTrackTbl,es
|
|
mov bx,0200h
|
|
mov ax,track
|
|
mov ah,byte ptr head
|
|
TrackBuildLoop:
|
|
stosw ; Store Track#, Head#
|
|
inc bl
|
|
xchg ax,bx
|
|
stosw ; Store Sector#, Bytes/Sector code
|
|
xchg ax,bx
|
|
loop TrackBuildLoop
|
|
|
|
; Format the track, retrying 4 times.
|
|
mov retry,4
|
|
FormatTrack:
|
|
mov ax,cSec
|
|
mov ah,5 ; Set up the INT 13h format call
|
|
mov ch,byte ptr track
|
|
mov cl,1
|
|
mov bx,drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
mov dh,byte ptr head
|
|
les bx,lpTrackTbl
|
|
int 13h
|
|
jc DecRetry ; Retry on error
|
|
|
|
; Verify the track.
|
|
mov ax,cSec
|
|
mov ah,4 ; Set up the INT 13h verify call
|
|
mov ch,byte ptr track
|
|
mov cl,1
|
|
mov bx,drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
mov dh,byte ptr head
|
|
les bx,lpTrackTbl
|
|
int 13h
|
|
jnc done ; Return if no errors
|
|
|
|
|
|
DecRetry:
|
|
; Check if it is the first attempt... If so, reset the disk.
|
|
cmp retry,4
|
|
jb just_retry
|
|
|
|
; Reset the disk
|
|
xor ah,ah
|
|
mov bx,drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
int 13h
|
|
|
|
just_retry:
|
|
dec retry
|
|
jnz FormatTrack
|
|
|
|
; Error code is in AH
|
|
Done:
|
|
xor al,al ; Error code, if any, is in AH
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* MyGetDriveType() - *
|
|
;* *
|
|
;* This function was used to be known as GetDriveType(); But now there *
|
|
;* is an exported function in Kernel with the same name; So, we have to *
|
|
;* chang the name to its present name. *
|
|
;* --SANKAR-- 10-17-89 *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Returns the type of drive supported by the ROM.
|
|
|
|
; Inputs: drive 0-based drive number for int 13
|
|
; Outputs: -1 if INT 13 returns carry
|
|
; 0 if changeline not supported
|
|
; 1 if changeline supported
|
|
; 2 if wacko returns from int 13
|
|
|
|
cProc MyGetDriveType, <PUBLIC,FAR>
|
|
|
|
ParmW drive
|
|
|
|
cBegin
|
|
mov bx,drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
mov ax,(15h shl 8) + 0FFh
|
|
int 13h
|
|
|
|
; Stupid IBM has documented INCORRECTLY the readdasdtype call to INT 13. The
|
|
; conditions at this point are:
|
|
;
|
|
; Carry flag unknown
|
|
; ah = 00 iff no diskette present => 2 (wacko)
|
|
; ah = 01 iff no changeline available => 0
|
|
; ah = 02 iff changeline available => 1
|
|
; ah = 03 iff hard disk => 2 (wacko)
|
|
; ah = 15 iff not on AT => 0
|
|
|
|
cmp ah,1
|
|
jb wacko
|
|
jz zero
|
|
cmp ah,3
|
|
jae wacko
|
|
|
|
; Changeline present. Put drive into high density mode.
|
|
GetDriveCall:
|
|
mov ah,17h
|
|
mov bx,drive
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
mov al,3
|
|
int 13h
|
|
|
|
; Doubly stupid IBM spins the drive for this call and potentially returns the
|
|
; disk change error (mumble). If we get carry set AND ah == 6, we retry the
|
|
; operation
|
|
|
|
jnc NoCarry
|
|
cmp ah,06h
|
|
jnz wacko
|
|
jmp GetDriveCall
|
|
NoCarry:
|
|
mov ax,1
|
|
jmp short doneDrive
|
|
wacko:
|
|
mov ax,2
|
|
jmp short doneDrive
|
|
zero:
|
|
mov ax,0
|
|
jmp short doneDrive
|
|
carry:
|
|
mov ax,-1
|
|
doneDrive:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* ReadSerialNumber() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; This reads and returns the serial number from the boot sector of the
|
|
; Diskette in the given drive.
|
|
;
|
|
; Returns:
|
|
; The serial number if the boot sector is that of DOS4.0 or above
|
|
; else returns 0L
|
|
|
|
cProc ReadSerialNumber, <FAR, PUBLIC>, <DI>
|
|
|
|
ParmW iDrive
|
|
ParmD lpBuff
|
|
|
|
cBegin
|
|
; Read the boot sector into the given drive
|
|
xor bx,bx
|
|
mov ax,1
|
|
cCall MyInt25,<iDrive,lpBuff,ax,bx>
|
|
or ax,ax
|
|
jnz RSN_RetZero
|
|
|
|
; Examine if it the version of boot sector is >= DOS 4.00
|
|
les di,lpBuff
|
|
mov al,byte ptr es:[di].BOOT_ExSignature_DOS4
|
|
cmp al,29h ; Signature for new BOOT record
|
|
je RSN_ReadIt
|
|
cmp al,28h ; Signature for new BOOT record
|
|
je RSN_ReadIt
|
|
RSN_RetZero:
|
|
xor ax,ax ; Return 0 if no serial no
|
|
xor dx,dx
|
|
jmp short RSN_End
|
|
RSN_ReadIt:
|
|
mov ax,word ptr es:[di].BOOT_SerialNo_DOS4
|
|
mov dx,word ptr es:[di].BOOT_SerialNo_DOS4+2
|
|
RSN_End:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* ModifyVolLabelInBootSec() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; This checks whether the given floppy contains a boot record of 4.00
|
|
; and if so, it overwrites the existing vol label with the given vol
|
|
; label and overwrites the existing serial # with the given serial #
|
|
;
|
|
; Returns: 0 if successful;
|
|
; -1 if error;
|
|
|
|
cProc ModifyVolLabelInBootSec, <FAR, PUBLIC>, <SI,DI,DS>
|
|
|
|
ParmW iDrive
|
|
ParmD lpszVolLabel
|
|
ParmD lSerialNo
|
|
ParmD lpBuff
|
|
|
|
cBegin
|
|
; Read the boot sector into the given drive
|
|
xor bx,bx
|
|
mov ax,1
|
|
cCall MyInt25,<iDrive,lpBuff,ax,bx>
|
|
or ax,ax
|
|
jnz MVLIBS_End
|
|
|
|
; Examine if it the version of boot sector is >= DOS 4.00
|
|
les di,lpBuff
|
|
mov al,byte ptr es:[di].BOOT_ExSignature_DOS4
|
|
cmp al,29h ; Signature for new BOOT record
|
|
je MVLIBS_Modify
|
|
cmp al,28h ; Signature for new BOOT record
|
|
je MVLIBS_Modify
|
|
xor ax,ax ; Return 0 if no error
|
|
jmp short MVLIBS_End
|
|
MVLIBS_Modify:
|
|
; Yup! Replace the existing vol label by the given one.
|
|
lea di,es:[di].BOOT_VolLabel_DOS4
|
|
lds si,lpszVolLabel
|
|
mov cx,11
|
|
mov ax,ds
|
|
or ax,si ; Check if the Vol Label is being removed
|
|
jz MVLIBS_PadBlanks ; Yup! Remove the label.
|
|
MVLIBS_Loop:
|
|
lodsb
|
|
or al,al
|
|
jz MVLIBS_PadBlanks
|
|
stosb
|
|
loop MVLIBS_Loop
|
|
MVLIBS_PadBlanks:
|
|
; Pad the Vol label with blanks
|
|
mov al,' '
|
|
rep stosb
|
|
; Modify the serial number
|
|
mov ax,OFF_lSerialNo
|
|
mov dx,SEG_lSerialNo
|
|
or ax,dx
|
|
jz MVLIBS_Write
|
|
les di,lpBuff
|
|
mov word ptr es:[di].BOOT_SerialNo_DOS4,ax
|
|
mov word ptr es:[di].BOOT_SerialNo_DOS4+2,dx
|
|
MVLIBS_Write:
|
|
; Go ahead and write the modified boot sector
|
|
xor ax,ax
|
|
mov bx,1
|
|
cCall MyInt26,<iDrive,lpBuff,bx,ax> ; Output correct boot sector
|
|
MVLIBS_End: ; Returns 0 if successful
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* WriteBootSector() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Copies the boot sector from one drive to another.
|
|
|
|
; Inputs: SrcDrive 0-based drive of source boot sector
|
|
; DstDrive 0-based drive of destination
|
|
; pBPB pointer to BPB for destination drive
|
|
; lpBuf long pointer to buffer large enough to
|
|
; contain boot sector.
|
|
; Returns: 0 if successfull
|
|
|
|
cProc WriteBootSector, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
parmW SrcDrive
|
|
parmW DstDrive
|
|
parmW pBPB
|
|
parmD lpBuf
|
|
|
|
cBegin
|
|
; Read boot sector from source drive
|
|
|
|
xor bx,bx
|
|
mov ax,1
|
|
cCall MyInt25,<SrcDrive,lpBuf,ax,bx>
|
|
or ax,ax
|
|
jz bsContinue
|
|
jmp bsDone
|
|
|
|
bsContinue:
|
|
mov si,pBPB
|
|
; if no BPB is passed, then pickup the correct one from bpbList
|
|
or si,si
|
|
jnz havebpb
|
|
mov ah,36h
|
|
mov dx,DstDrive
|
|
inc dl
|
|
cCall DOS3Call
|
|
inc ax
|
|
jz bsfail
|
|
mov si,dataOffset _bpbList ; Scan BPB list for match
|
|
mov bx,dataOffset _cCluster ; with associated cluster size
|
|
bsloop:
|
|
mov cx,word ptr [bx]
|
|
jcxz bsfail
|
|
cmp cx,dx
|
|
je havebpb
|
|
add si,SIZE BPB
|
|
inc bx
|
|
inc bx
|
|
jmp bsloop
|
|
|
|
bsfail:
|
|
mov ax,-1
|
|
jmp short bsdone
|
|
|
|
havebpb:
|
|
; Copy BPB appropriate for dest. drive into boot sector
|
|
les di,lpBuf
|
|
lea di,[di].BOOT_BPB
|
|
mov cx,SIZE BPB
|
|
cld
|
|
rep movsb
|
|
|
|
; Check if the Boot sector read belongs to DOS 4.0
|
|
mov di,OFF_lpBuf
|
|
cmp es:[di].BOOT_ExSignature_DOS4,29h
|
|
je WBS_Dos4
|
|
cmp es:[di].BOOT_ExSignature_DOS4,28h
|
|
je WBS_Dos4
|
|
|
|
; No, the Boot sector version is < 4.00
|
|
; Store a zero in BOOT_phydrv field
|
|
; (i.e. always assume A: is the boot drive
|
|
; so IBMBIO.COM will be happy)
|
|
xor ax,ax
|
|
mov es:[di].BOOT_phydrv,al ; 3.2 expects it here
|
|
mov es:[di].BOOT_bootdrive,al ; < 3.2 expects it here
|
|
jmp short WBS_Write
|
|
WBS_Dos4:
|
|
; It is DOS 4.0 or above
|
|
xor ax,ax
|
|
lea si,es:[di].BOOT_BPB_extension
|
|
; zero the high word of number of hidden sectors
|
|
mov es:[si].BPB_EX_cSecHidden_HiWord,ax
|
|
; Zero the total number of sectors, in the extended field
|
|
mov word ptr es:[si].BPB_EX_cTotalSectors,ax
|
|
mov word ptr es:[si].BPB_Ex_cTotalSectors+2,ax
|
|
|
|
; Make 'A' as the BOOT drive
|
|
mov es:[di].BOOT_phydrv_DOS4,al
|
|
|
|
; Get a serial number for this disk
|
|
push es
|
|
cCall <far ptr DreamUpSerialNumber>
|
|
pop es
|
|
mov word ptr es:[di].BOOT_SerialNo_DOS4,ax
|
|
mov word ptr es:[di].BOOT_SerialNo_DOS4+2,dx
|
|
|
|
;Overwrite "FAT16" with "FAT12" in the reserved area;
|
|
lea di,es:[di].BOOT_FATmarker_DOS4
|
|
lea si,_szReservedMarker
|
|
mov cx,8
|
|
rep movsb
|
|
WBS_Write:
|
|
; Go ahead and write the modified boot sector
|
|
xor ax,ax
|
|
mov bx,1
|
|
cCall MyInt26,<DstDrive,lpBuf,bx,ax> ; Output correct boot sector
|
|
bsdone: ; Returns 0 if successful
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* OpenFAT() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
cProc OpenFAT, <PUBLIC,FAR>
|
|
|
|
parmW mode
|
|
|
|
cBegin
|
|
mov [_wFATSector],-1
|
|
mov ax,mode
|
|
mov [_wFATMode],ax
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* FlushFAT() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Returns 0 if successful.
|
|
|
|
cProc FlushFAT, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
parmW pDPB
|
|
parmD lpBuf
|
|
|
|
cBegin
|
|
; Make sure that OpenFAT() has been called...
|
|
mov ax,[_wFATSector]
|
|
inc ax
|
|
jz FFDone
|
|
|
|
; ...and we are in WRITE mode.
|
|
test [_wFATMode],FAT_WRITE
|
|
jz FFDone
|
|
|
|
mov si,[_wFATSector] ; SI = Current FAT sector
|
|
mov bx,pDPB ; BX = pDPB
|
|
|
|
xor dx,dx
|
|
mov dl,[bx].DPB_drive
|
|
mov di,dx ; DI = Drive Number
|
|
|
|
; Write out the first copy of these two sectors.
|
|
mov dx,2
|
|
push bx ; Preserve BX
|
|
cCall MyInt26,<di,lpBuf,dx,si>
|
|
pop bx ; Restore BX
|
|
or ax,ax ; Problems?
|
|
jnz FFDone ; Yup, exit
|
|
|
|
push bx ; Preserve BX
|
|
|
|
; Did we just write out the first sector?
|
|
cmp si,1
|
|
jne FF2nd ; Nope, skip
|
|
|
|
; Yes, mark the media as invalid.
|
|
push ds ; Save DS on Stack
|
|
|
|
; DOS function 32h is Get_DPB() - to get the Drive Parameter Block
|
|
; Input : DL = Drive (1 = A, 2 = B, ...)
|
|
; Output: AL = 0, if successful and DS:BX points to the DPB.
|
|
; AL = -1, if invalid drive.
|
|
;
|
|
mov ah,32h ; Get DPB
|
|
mov dx,di
|
|
inc dx ; DX = 1-based drive number
|
|
int 21h
|
|
|
|
push ds ; ES = DS
|
|
pop es
|
|
|
|
pop ds ; Restore DS from Stack
|
|
|
|
cbw ; Extend error into AX
|
|
or ax,ax ; Problems?
|
|
jnz ff2nd ; Yup, return immediately
|
|
|
|
; ***** WARNING: 4.00 HACK *****
|
|
; es:bx now point to the DPB returned by DOS Function 32h. So, if
|
|
; it is DOS 4.X, then DPB_first_access is at one byte higher location.
|
|
; (Because, DPB_FAT_size field is one byte longer).
|
|
; Take care before assigning this field.
|
|
push es ; Save es:bx on stack -GetDosVersion spoils them
|
|
push bx
|
|
cCall GetDOSVersion
|
|
pop bx ; Restore es:bx from stack
|
|
pop es
|
|
cmp ah,4
|
|
jb ff_DOS3
|
|
mov es:[bx].DPB_first_access+1,-1 ; DOS 4.X
|
|
jmp short ff2nd
|
|
ff_DOS3:
|
|
mov es:[bx].DPB_first_access,-1 ; DOS 3.X
|
|
ff2nd:
|
|
; Write out the Second copy of two FAT sectors.
|
|
pop bx ; Restore BX (pDPB)
|
|
xor dx,dx
|
|
mov dl,[bx].DPB_FAT_size
|
|
add si,dx
|
|
mov dl,2
|
|
cCall MyInt26,<di,lpBuf,dx,si>; Returns 0 if successful
|
|
ffdone:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* SetIndexSector() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Determines the sector and offset-within-sector for a particular cluster entry.
|
|
|
|
; Inputs: DI = -> DPB block
|
|
; CX = clustor number
|
|
;
|
|
; Outputs: AX = sector number of fat sector containing fat entry
|
|
; DX = offset into fat sector of 1st bytes of fat entry for passed
|
|
; cluster number.
|
|
|
|
cProc SetIndexSector, <PUBLIC,NEAR>
|
|
|
|
cBegin nogen
|
|
xor dx,dx
|
|
mov ax,cx
|
|
|
|
; Are we using 12-bit fat entries?
|
|
cmp [di].DPB_max_cluster,4086
|
|
jb sis12bit ; Yes, go calculate sector/offset
|
|
|
|
; offset = (2*cluster) % pDPB->sector_size
|
|
; sector = pDPB->first_FAT + (2*cluster) / pDPB->sector_size
|
|
shl ax,1
|
|
div [di].DPB_sector_size ; No, 16 bit fat entries
|
|
jmp short sisdone
|
|
|
|
sis12bit:
|
|
; offset = (cluster + (cluster >> 1)) % pDPB->sector_size
|
|
; sector = pDPB->first_FAT + (cluster + (cluster >> 1)) / pDPB->sector_size
|
|
shr ax,1
|
|
add ax,cx
|
|
div [di].DPB_sector_size
|
|
|
|
sisdone:
|
|
add ax,[di].DPB_first_FAT
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* PackFAT() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Adds a specified value into the FAT entry which corresponds to the specified
|
|
; cluster.
|
|
|
|
; Inputs: pDPB pointer to DPB
|
|
; lpBuf pointer to a 2 sector buffer
|
|
; cluster cluster which needs the entry
|
|
; value value to be stuffed into cluster entry
|
|
;
|
|
; Returns 0 if successful.
|
|
|
|
cProc PackFAT, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
parmW pDPB
|
|
parmD lpBuf
|
|
parmW cluster
|
|
parmW value
|
|
|
|
cBegin
|
|
|
|
mov di,pDPB ; DI = pDPB
|
|
mov cx,cluster ; CX = Cluster #
|
|
cCall SetIndexSector
|
|
|
|
; AX = FAT Sector which contains the cluster entry
|
|
; DX = Offset within that sector for the cluster entry
|
|
|
|
mov si,dx ; SI = Entry Offset
|
|
|
|
; Are we currently modifying the proper FAT Sector?
|
|
cmp [_wFATSector],ax
|
|
je PFNoRead ; Yup, skip
|
|
|
|
; Nope, Flush this sector and read in the right one...
|
|
mov cx,ax ; CX = Desired sector
|
|
push cx ; Preserve CX
|
|
cCall FlushFAT,<di,lpBuf>
|
|
pop cx ; Restore CX
|
|
or ax,ax ; Problems?
|
|
jnz PFDone ; Yup, give up
|
|
|
|
mov al,[di].DPB_drive ; AL = Drive#
|
|
mov dx,2 ; DX =
|
|
push cx ; Preserve CX
|
|
cCall MyInt25,<ax,lpBuf,dx,cx>
|
|
pop cx ; Restore CX
|
|
or ax,ax ; Problems?
|
|
jnz PFDone ; Yup, give up
|
|
|
|
; Update the Current Sector variable.
|
|
mov [_wFATSector],cx
|
|
|
|
PFNoRead:
|
|
mov ax,value ; AX = FAT Entry Value
|
|
xor dx,dx ; DX = 0
|
|
|
|
; Does the DPB indicate more than 4086 clusters?
|
|
; i.e. Do we use 12-bit or 16-bit FAT entries?
|
|
cmp [di].DPB_max_cluster,4086
|
|
jae PF2 ; Use 16-bit entries
|
|
|
|
; Use 12-bit entries.
|
|
mov cl,4
|
|
mov dh,0F0h
|
|
test byte ptr cluster,1
|
|
jz PF1
|
|
rol dx,cl
|
|
shl ax,cl
|
|
jmp short PF2
|
|
PF1:
|
|
not dx
|
|
and ax,dx
|
|
not dx
|
|
PF2:
|
|
; Store the value at the proper offset.
|
|
les bx,lpBuf
|
|
and es:[bx+si],dx
|
|
or es:[bx+si],ax
|
|
xor ax,ax ; Return success
|
|
PFDone:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* UnpackFAT() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Inputs: pDPB drive parameter block for drive
|
|
; lpBuf pointer to a sector buffer
|
|
; cluster cluster whose FAT contents are to be returned
|
|
;
|
|
; this converts 12 bit FAT values to 16 bits values
|
|
;
|
|
; Returns:
|
|
; 0000 cluster available
|
|
; FFF0-FFF6 reserved
|
|
; FFF7 bad cluster
|
|
; FFFF-FFFF last cluster
|
|
; else next cluster in the chain
|
|
|
|
cProc UnpackFAT, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
parmW pDPB
|
|
parmD lpBuf
|
|
parmW cluster
|
|
|
|
cBegin
|
|
mov di,pDPB
|
|
mov cx,cluster
|
|
cCall SetIndexSector
|
|
mov si,dx
|
|
cmp [_wFATSector],ax
|
|
je upfnoread
|
|
push ax
|
|
cCall FlushFAT,<di,lpBuf>
|
|
pop cx
|
|
or ax,ax ;Did FlushFAT return error?
|
|
jnz upfError
|
|
mov al,[di].DPB_drive
|
|
mov dx,2
|
|
push cx
|
|
cCall MyInt25,<ax,lpBuf,dx,cx>
|
|
pop cx
|
|
or ax,ax ;Did MyInt25 return error?
|
|
jnz upfError
|
|
mov [_wFATSector],cx
|
|
upfnoread:
|
|
les bx,lpBuf
|
|
mov ax,es:[bx+si]
|
|
cmp [di].DPB_max_cluster,4096-10 ; 12 bit fat entries?
|
|
;; jae upfdone
|
|
jae upfexit
|
|
|
|
test byte ptr cluster,1 ;Is it an Odd or Even cluster
|
|
jz upf1
|
|
mov cl,4
|
|
shr ax,cl
|
|
upf1:
|
|
and ax,0FFFh ; keep only 12 bits
|
|
cmp ax,0FF0h ; is this a special cluster
|
|
jb upfexit ; no
|
|
or ax,0F000h ; extend the special clusters to 16 bits
|
|
jmp short upfexit ; done, get out
|
|
upfdone:
|
|
;; don't convert special end of chain and bad sectors
|
|
;; mov dx,ax
|
|
;; cmp [di].DPB_max_cluster,ax
|
|
;; jae upfexit
|
|
upfError:
|
|
mov ax,-1
|
|
upfexit:
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* IsHPMachine() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Attempts to detect HP Vectra machines.
|
|
|
|
cProc IsHPMachine,<PUBLIC,FAR>
|
|
|
|
cBegin nogen
|
|
push es
|
|
mov ax,__ROMBIOS ; To work in Protect mode
|
|
mov es,ax
|
|
mov ax,word ptr es:[00F8h]
|
|
pop es
|
|
cmp ax,'PH'
|
|
je IHMFoundIt
|
|
xor ax,ax
|
|
jmp short IHMDone
|
|
|
|
IHMFoundIt:
|
|
mov ax,1
|
|
IHMDone:
|
|
ret
|
|
cEnd nogen
|
|
|
|
ifdef 0
|
|
******************* COMMENTED OUT *****************************************
|
|
*** Look! Int13h Function 8 DOES NOT work in COMPAQ 386/16 machines ******
|
|
*** So, the following function is replaced by a GetDriveCapacity() ******
|
|
*** in WFFormat.c; Go and look at it. ******
|
|
*** This is a part of the Fix for Bug #5292 --SANKAR-- 10-17-89 ******
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* GetDriveCapacity() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Returns
|
|
; 0 if error
|
|
; 1 if 360KB floppy drive
|
|
; 2 if 1.2MB
|
|
; 3 if 720KB
|
|
; 4 if 1.44KB
|
|
|
|
cProc GetDriveCapacity, <PUBLIC,FAR>
|
|
|
|
ParmW nDriveId
|
|
|
|
cBegin
|
|
mov ah,08h ; Get drive parameters
|
|
mov bx,nDriveId
|
|
shl bx,1
|
|
mov dx,_rgiInt13Drive[bx]
|
|
int 13h
|
|
jc GDT_Error
|
|
mov al,bl ; Drive type
|
|
xor ah,ah
|
|
jmp short GDT_End
|
|
GDT_Error:
|
|
xor ax,ax ; returns 0 if error
|
|
GDT_End:
|
|
cEnd
|
|
************** COMMENTED OUT ****************************************
|
|
endif
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* DreamUpSerialNumber() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Returns a unique serial number for writing into the BOOT sector of DOS 4.0
|
|
; and above diskettes. The unique function is generated by hashing the
|
|
; system date and time.
|
|
|
|
cProc DreamUpSerialNumber, <PUBLIC, FAR>, <SI,DI>
|
|
|
|
cBegin
|
|
; Get the System Date
|
|
mov ah,2Ah
|
|
cCall DOS3Call; cx = Year, dh=month, dl=day
|
|
push cx
|
|
push dx ; Save them on the stack
|
|
|
|
; Get the System Time
|
|
mov ah,2Ch
|
|
cCall DOS3Call; ch=hours, cl=minutes, dh=seconds, dl=1/100th secs
|
|
|
|
; Low word of serial number = dx of time + dx of date
|
|
; High word of Serial number = cx of time + cx of date
|
|
pop ax
|
|
add ax,dx
|
|
pop dx
|
|
add dx,cx
|
|
cEnd
|
|
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* GetClusterInfo() - *
|
|
;* *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Returns the size of a sector in dx and sectors/cluster in ax for
|
|
; the specified drive
|
|
; Inputs: drive 0=>A, 1=>B
|
|
; Returns: 0 if unsuccessful, or AX= sectors/cluster and DX = size of sector in bytes;
|
|
|
|
cProc GetClusterInfo, <PUBLIC,FAR>, <SI,DI>
|
|
|
|
parmW drive
|
|
|
|
cBegin
|
|
mov ah,36h
|
|
mov dx,drive
|
|
inc dx ; make it 1 based.
|
|
cCall DOS3Call
|
|
inc ax ; if Error, ax = -1, else, ax = sectors/cluster
|
|
jz GCSdone ; Yup, Error. Return zero.
|
|
dec ax ; Get back sectors/cluster.
|
|
mov dx, cx ; cx = bytes/sector
|
|
GCSdone:
|
|
cEnd
|
|
|
|
if 0
|
|
|
|
;*--------------------------------------------------------------------------*
|
|
;* *
|
|
;* IsHighCapacityDrive() - *
|
|
;* This returns 0 if it is a low capacity drive (360KB or 720KB) *
|
|
;* returns >0 if it is a high capacity drive(1.2MB or 1.44MB) *
|
|
;* returns -1 if error occurred in reading the capacity *
|
|
;* *
|
|
;* This function is added as a Fix for Bug #4866 --SANKAR--09-28-89-- *
|
|
;*--------------------------------------------------------------------------*
|
|
|
|
; Flushes out the disk buffer.
|
|
|
|
cProc IsHighCapacityDrive, <PUBLIC,FAR>
|
|
|
|
ParmW iDrive
|
|
|
|
cBegin
|
|
cCall GetDriveCapacity, <iDrive>
|
|
cmp ax, 2
|
|
je IHCD_End ; Yup! It is a 1.2MB drive
|
|
cmp ax, 4
|
|
je IHCD_End ; Yup! It is a 1.44MB drive
|
|
or ax, ax
|
|
jnz IHCD_LowCap ; AX is 1 or 3 => Low capacity drive
|
|
dec ax ; Error in reading the capacity of drive;
|
|
js IHCD_End
|
|
IHCD_LowCap:
|
|
xor ax, ax
|
|
IHCD_End:
|
|
cEnd
|
|
|
|
endif
|
|
|
|
|
|
sEnd %SEGNAME
|
|
|
|
end
|