mirror of https://github.com/AR1972/DOS3.3
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.
1039 lines
30 KiB
1039 lines
30 KiB
include ioctl.inc
|
|
|
|
;
|
|
; Generic IOCTL dispatch tables
|
|
;
|
|
IOReadJumpTable db 2
|
|
dw offset GetDeviceParameters
|
|
dw offset ReadTrack
|
|
dw offset VerifyTrack
|
|
|
|
IOWriteJumpTable db 2
|
|
dw offset SetDeviceParameters
|
|
dw offset WriteTrack
|
|
dw offset FormatTrack
|
|
|
|
MAX_SECTORS_CURR_SUP EQU 63 ; CURRENT MAXIMUM SEC/TRK THAT ;3.30
|
|
; WE SUPPORT (Was 40 in DOS 3.2) ;3.30
|
|
;
|
|
; TrackTable is an area for saving information passwd by the set device
|
|
; parameter function for laster use my Read/Write/Format/Verify.
|
|
;
|
|
; Entries are 4-Tuples (C,H,R,N) where:
|
|
; C = Cylinder, H = Head, R = Sector, N = Bytes/Sector
|
|
;
|
|
; fixed for bug0016 - initialised table with values - sp
|
|
TrackTable db 0,0,1,2
|
|
db 0,0,2,2
|
|
db 0,0,3,2
|
|
db 0,0,4,2
|
|
db 0,0,5,2
|
|
db 0,0,6,2
|
|
db 0,0,7,2
|
|
db 0,0,8,2
|
|
db 0,0,9,2
|
|
db 0,0,10,2
|
|
db 0,0,11,2
|
|
db 0,0,12,2
|
|
db 0,0,13,2
|
|
db 0,0,14,2
|
|
db 0,0,15,2
|
|
db 0,0,16,2
|
|
db 0,0,17,2
|
|
db 0,0,18,2
|
|
db MAX_SECTORS_CURR_SUP * size a_SectorTable - ($-tracktable) dup (0)
|
|
|
|
sectorsPerTrack dw 15
|
|
|
|
|
|
; This is a real ugly place to put this
|
|
; it should really go in the BDS
|
|
mediaType db 0
|
|
|
|
Media_Set_For_Format db 0 ; 1 if we have done an Int 13 Set Media
|
|
; Type for Format call
|
|
; Rev 3.30 *****************************************************************
|
|
Had_Format_Error db 0 ; 1 if the previous format operation
|
|
; failed.
|
|
Dsk_time_out_Err equ 80h ; Time out error (No media present).
|
|
Dsk_change_line_Err equ 6h ; Change line error
|
|
Dsk_illegal_combination equ 0Ch ; Return code of ah=18h function.
|
|
; Rev 3.30 *****************************************************************
|
|
|
|
;
|
|
; TempDPT is a temporary place to hold a pointer to the original
|
|
; Disk Parameter Table while DPT is made to point to a table returned
|
|
; by a BIOS call. A value of -1 indicateds no value has been saved.
|
|
;
|
|
|
|
TempDPT DD -1
|
|
|
|
;
|
|
; Generic$IOCTL:
|
|
; Perform Generic IOCTL request
|
|
; Input:
|
|
; al - unit number
|
|
; Output:
|
|
; if carry set then al contains error code
|
|
;
|
|
Public Generic$IOCTL
|
|
Generic$IOCTL:
|
|
Message ftestdisk,<"Generic IOCTL",cr,lf>
|
|
les bx,cs:[PTRSAV] ; es:bx points to request header.
|
|
call SetDrive ; ds:di points to BDS for drive.
|
|
;
|
|
; At this point:
|
|
; es:bx - points to the Request Header
|
|
; ds:di points to the BDS for the drive
|
|
;
|
|
cmp es:[bx].MajorFunction, RAWIO
|
|
jne IOCTL_Func_Err
|
|
mov al, es:[bx].MinorFunction
|
|
mov si, offset IOReadJumpTable
|
|
test al, GEN_IOCTL_FN_TST ; Test of req. function
|
|
jnz NotGenericIoctlWrite ; function is a Read.
|
|
mov si, offset IOWriteJumpTable
|
|
NotGenericIoctlWrite:
|
|
and al, 0fH
|
|
cmp al, cs:[si]
|
|
ja IOCTL_Func_Err
|
|
cbw
|
|
shl ax, 1
|
|
inc si
|
|
add si,ax
|
|
les bx, es:[bx].GenericIOCTL_Packet
|
|
call cs:[si]
|
|
jc FailGeneric$IOCTL
|
|
jmp exit
|
|
|
|
FailGeneric$IOCTL:
|
|
jmp err$exit
|
|
|
|
IOCTL_Func_Err:
|
|
jmp CMDERR
|
|
|
|
|
|
|
|
|
|
|
|
;
|
|
; GetDeviceParameters:
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to device parameter packet
|
|
;
|
|
|
|
PUBLIC GETDEVICEPARAMETERS ;3.30
|
|
GetDeviceParameters proc near
|
|
; Copy info from BDS to the device parameters packet
|
|
mov al, byte ptr ds:[di].FormFactor
|
|
mov byte ptr es:[bx].DP_DeviceType, al
|
|
mov ax, word ptr ds:[di].Flags
|
|
and ax,fNon_Removable+fChangeline ; mask off other bits
|
|
mov word ptr es:[bx].DP_DeviceAttributes, ax
|
|
mov ax, word ptr ds:[di].cCyln
|
|
mov word ptr es:[bx].DP_Cylinders, ax
|
|
|
|
; Set media type to default
|
|
xor al, al
|
|
mov byte ptr es:[bx].DP_MediaType, al
|
|
|
|
; Copy recommended BPB
|
|
lea si, byte ptr [di].RBytePerSec
|
|
test byte ptr es:[bx].DP_SpecialFunctions, BUILD_DEVICE_BPB
|
|
jz use_BPB_present
|
|
; Get the correct disk in the drive
|
|
call CheckSingle
|
|
; Build the BPB from scratch
|
|
call GETBP
|
|
jc Get_Parm_Ret
|
|
lea si,byte ptr [di].BytePerSec
|
|
use_BPB_present:
|
|
lea di, byte ptr [bx].DP_BPB
|
|
mov cx, size BPB_Type ; for now use 'small' BPB
|
|
rep movsb
|
|
clc
|
|
Get_Parm_Ret:
|
|
ret
|
|
GetDeviceParameters endp
|
|
|
|
|
|
|
|
|
|
|
|
;
|
|
; SetDeviceParameters:
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to device parameter packet
|
|
;
|
|
|
|
PUBLIC SETDEVICEPARAMETERS ;3.30
|
|
SetDeviceParameters proc near
|
|
|
|
; Make sure the fChanged_By_Format flag gets set to kick DOS into looking at
|
|
; the BPB
|
|
or word ptr ds:[di].Flags, fChanged_By_Format or fChanged
|
|
test byte ptr es:[bx].DP_SpecialFunctions, ONLY_SET_TRACKLAYOUT
|
|
jz short SetDevParm_1
|
|
jmp SetTrackTable ; Originally TrackLayout
|
|
|
|
SetDevParm_1:
|
|
; Copy info from the device parameters packet to BDS
|
|
mov al, byte ptr es:[bx].DP_DeviceType
|
|
mov byte ptr ds:[di].FormFactor, al
|
|
|
|
mov ax, word ptr es:[bx].DP_Cylinders
|
|
mov word ptr ds:[di].cCyln, ax
|
|
|
|
; If change line is not loaded then ignore changeling flag
|
|
mov ax, word ptr es:[bx].DP_DeviceAttributes
|
|
cmp cs:[fHave96],0
|
|
jnz Have_Change
|
|
and ax,not fChangeline
|
|
Have_Change:
|
|
; ignore all bits except Non_removable and Changeline
|
|
and ax,fNon_Removable or fChangeline
|
|
mov cx, word ptr ds:[di].Flags
|
|
and cx, not (fNon_Removable or fChangeline or GOOD_TRACKLAYOUT)
|
|
or ax, cx
|
|
mov word ptr ds:[di].Flags, ax
|
|
|
|
; Set media type
|
|
mov al, byte ptr es:[bx].DP_MediaType
|
|
mov cs:mediaType, al
|
|
; the media changed (maybe) so we will have to do a SetDASD the next time
|
|
; we format a track
|
|
or word ptr ds:[di].Flags, SET_DASD_true
|
|
|
|
SaveReg <ds,di,es,bx>
|
|
; Figure out what we are supposed to do with the BPB
|
|
|
|
; Were we asked to install a fake BPB?
|
|
test byte ptr es:[bx].DP_SpecialFunctions, INSTALL_FAKE_BPB
|
|
jnz short InstallFakeBPB
|
|
|
|
; Were we returning a fake BPB when asked to build a BPB?
|
|
test word ptr ds:[di].Flags, RETURN_FAKE_BPB
|
|
jz short InstallRecommendedBPB
|
|
|
|
; We were returning a fake BPB but we can stop now
|
|
and word ptr ds:[di].Flags, not RETURN_FAKE_BPB
|
|
jmp DoneWithBPBstuff
|
|
|
|
InstallRecommendedBPB:
|
|
mov cx, size a_BPB
|
|
lea di, byte ptr [di].RBytePerSec
|
|
jmp short CopyTheBPB
|
|
|
|
InstallFakeBPB:
|
|
mov cx, size BPB_Type ; move 'smaller' BPB
|
|
lea di, byte ptr [di].BytePerSec
|
|
CopyTheBPB:
|
|
lea si, byte ptr [bx].DP_BPB
|
|
; exchange es and ds
|
|
push es
|
|
push ds
|
|
pop es
|
|
pop ds
|
|
|
|
rep movsb
|
|
|
|
DoneWithBPBstuff:
|
|
Call RestoreOldDPT
|
|
RestoreReg <bx,es,di,ds>
|
|
|
|
; Set up track table (if neccessary)
|
|
SetTrackTable:
|
|
mov cx, word ptr es:[bx].DP_TrackTableEntries
|
|
mov cs:sectorsPerTrack, cx
|
|
and word ptr ds:[di].Flags, not GOOD_TRACKLAYOUT
|
|
test byte ptr es:[bx].DP_SpecialFunctions, TRACKLAYOUT_IS_GOOD
|
|
jz UglyTrackLayout
|
|
or word ptr ds:[di].Flags, GOOD_TRACKLAYOUT
|
|
|
|
UglyTrackLayout:
|
|
cmp cx, MAX_SECTORS_IN_TRACK
|
|
ja TooManySectorsPerTrack
|
|
jcxz SectorInfoSaved ; if no value don't copy table
|
|
; save information in the track table
|
|
|
|
push BX ; get ES:BX to point to sector
|
|
add BX, DP_SectorTable ; table in Device param. struct
|
|
|
|
push DI
|
|
mov DI, offset TrackTable + 2 ; CS:DI now points to sector id
|
|
; of the first track table entry
|
|
push AX ; preserve AX value
|
|
|
|
; For MAX_SECTORS_IN_TRACK
|
|
TrackLoop: ; DO:
|
|
mov AX, word ptr ES:[BX] ; get sector number
|
|
mov byte ptr CS:[DI], AL ; save in track table
|
|
|
|
mov AX, word ptr ES:[BX]+2 ; get sector size
|
|
call SectorSizeToSectorIndex ; convert size to index number
|
|
mov byte ptr CS:[DI]+1, AL ; save size in track table
|
|
|
|
add BX, size a_sectorTable ; advance pointers to next
|
|
add DI, size a_sectorTable ; entries
|
|
loopnz TrackLoop ; End FOR
|
|
|
|
pop AX ; restore the saved values
|
|
pop DI
|
|
pop BX
|
|
|
|
SectorInfoSaved:
|
|
clc
|
|
ret
|
|
|
|
TooManySectorsPerTrack:
|
|
mov al, 0cH
|
|
stc
|
|
ret
|
|
|
|
SetDeviceParameters endp
|
|
|
|
|
|
;
|
|
; FormatTrack:
|
|
; If SpecialFunction byte is 1, then this is a status call to see if there is
|
|
; ROM support for the combination of sec/trk and # of cyln, and if the
|
|
; combination is legal. If SpecialFunction byte is 0, then format the track.
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to format packet
|
|
;
|
|
; Output:
|
|
; For status call:
|
|
; SpecialFunction byte set to:
|
|
; 0 - ROM support + legal combination
|
|
; 1 - No ROM support
|
|
; 2 - Illegal Combination
|
|
; 3 - no media present ;Rev 3.30
|
|
; Carry cleared.
|
|
;
|
|
; For format track:
|
|
; Carry set if error
|
|
;
|
|
;
|
|
; Flags also may be altered. All other registers preserved.
|
|
; If the call to ROM returns no error, then the current DPT is "replaced" by
|
|
; the one returned by the ROM. This is done by changing the pointer in [DPT]
|
|
; to the one returned. The original pointer to the disk base table is stored
|
|
; in TempDPT, until it is restored.
|
|
;
|
|
; This proc was changed to force a status for format call if we are on the
|
|
; new ROM.
|
|
;
|
|
;
|
|
FormatTrack proc near
|
|
test byte ptr es:[bx].DP_SpecialFunctions,Status_For_Format
|
|
jz SkipStatusOnly
|
|
|
|
Do_Status_Only:
|
|
call FormatStatus
|
|
mov byte ptr es:[bx].DP_SpecialFunctions,al
|
|
ret
|
|
|
|
SkipStatusOnly: ; for a hard disk only do the verify
|
|
cmp byte ptr ds:[di].FormFactor, DEV_HARDDISK
|
|
jnz SkipVerify
|
|
jmp DoVerifyTrack
|
|
SkipVerify:
|
|
SaveReg <ds,di,es,bx> ; Format a Track
|
|
call FormatStatus ; SetDASD checks media_set_for_format
|
|
cmp al,3 ; Check for time out
|
|
je Format_Failed ; Fail if time out
|
|
call SetDASD
|
|
;
|
|
; Store Cylinder,Head in track table
|
|
; ***** ASSUMPTION *******
|
|
; Since format requests on Fixed Media are converted to Verifies, we
|
|
; assume that we are formatting a floppy and hence have 255 or less
|
|
; tracks and heads. We therefore must change the Cylinder, Head data
|
|
; from the Request Packet Size to that of the TrackTable (see Int 13
|
|
; interface in IBM's Tech Ref.).
|
|
|
|
; Check to ensure correct disk is in drive
|
|
call CheckSingle
|
|
|
|
mov ax, word ptr es:[bx].FP_Cylinder
|
|
mov word ptr cs:[TRKNUM],ax
|
|
mov cx, word ptr es:[bx].FP_Head
|
|
mov byte ptr cs:[HDNUM],cl
|
|
mov ah,cl
|
|
; this next piece of code copies the correct head
|
|
; and cylinder numbers to the tracktable
|
|
push di ; preserve DI
|
|
mov di, offset TrackTable
|
|
mov CX, cs:SectorsPerTrack ; get number of sectors
|
|
jcxz EndSetUpTrackTable ; if nothing to do skip down
|
|
SetUpLoop:
|
|
mov cs:[di], AX ; set head and track value
|
|
add di, 4 ; move to next entry
|
|
loopnz SetUpLoop ; loop if not done yet
|
|
EndSetUpTrackTable:
|
|
pop di ; restore DI (BDS pointer)
|
|
mov cx, MAXERR ; Set up retry count
|
|
FormatRetry:
|
|
push cx
|
|
; set up registers for format call to TO_ROM
|
|
mov AX, word ptr CS:SectorsPerTrack ; set number of sectors
|
|
mov AH, ROMFormat
|
|
push cs ; set ES:BX to point to
|
|
pop es ; the track table
|
|
mov BX, offset TrackTable
|
|
; don't need to set CL on format
|
|
call to_rom
|
|
jnc FormatOk
|
|
pop cx
|
|
mov cs:[Had_Format_Error],1 ; Mark the error
|
|
push ax ;3.30
|
|
push cx ;3.30
|
|
push dx ;3.30
|
|
call ResetDisk
|
|
call FormatStatus ;3.30
|
|
cmp al, 1 ;3.30
|
|
jnz While_Err ;3.30
|
|
call SetDASD ;3.30
|
|
While_Err: ;3.30
|
|
pop dx ;3.30
|
|
pop cx ;3.30
|
|
pop ax ;3.30
|
|
loop FormatRetry
|
|
|
|
; Format failed
|
|
Format_Failed:
|
|
mov cs:[Had_Format_Error],1 ; Indicate a format error
|
|
cmp ah,Dsk_Change_Line_Err ; Convert change line to
|
|
jne Map_Err ; to time out.
|
|
mov ah,Dsk_Time_Out_Err
|
|
Map_Err:
|
|
call MapError
|
|
RestoreReg <bx,es,di,ds>
|
|
ret
|
|
|
|
FormatOk:
|
|
mov cs:[Had_Format_Error],0 ; Reset format error flag
|
|
pop cx ; clean up stack after bailing out
|
|
; of FormatRetry loop early
|
|
RestoreReg <bx,es,di,ds>
|
|
|
|
DoVerifyTrack:
|
|
call VerifyTrack ; Will reset DPT entries.
|
|
ret
|
|
|
|
FormatTrack endp
|
|
|
|
;
|
|
; FormatStatus:
|
|
; If SpecialFunction byte is 1, then this routine is called to see if there is
|
|
; ROM support for the combination of sec/trk and # of cyln, and if the
|
|
; combination is legal.
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to format packet
|
|
;
|
|
; Output:
|
|
; SpecialFunction byte set to:
|
|
; 0 - ROM support + legal combination
|
|
; 1 - No ROM support
|
|
; 2 - Illegal Combination
|
|
; 3 - No media present, ROM support exists but can't determine
|
|
; media
|
|
; Carry cleared.
|
|
;
|
|
; For format track:
|
|
; Carry set if error
|
|
;
|
|
;
|
|
; Flags also may be altered. All other registers preserved.
|
|
; If the call to ROM returns no error, then the current DPT is "replaced" by
|
|
; the one returned by the ROM. This is done by changing the pointer in [DPT]
|
|
; to the one returned. The original pointer to the disk base table is stored
|
|
; in TempDPT, until it is restored.
|
|
;
|
|
;
|
|
FormatStatus proc near
|
|
SaveReg <cx,dx>
|
|
cmp cs:[Had_Format_Error],1 ; Are we here because of a format err
|
|
je Fstat01
|
|
cmp byte ptr cs:[Media_Set_For_Format],1
|
|
jnz FStat03
|
|
jmp Stat_Ret
|
|
Fstat03:
|
|
mov byte ptr cs:[Media_Set_For_Format],0
|
|
;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; modification - sp001
|
|
;
|
|
; remove check for new rom from here. we shall just assume the
|
|
; prescence of the new rom and go ahead and issue the int13 call
|
|
; anyway. later on if there is an error we shall check this to
|
|
; see if it is there because of lack of rom support, in which
|
|
; case the appropriate error will be indicated by setting al to 1
|
|
;
|
|
; I would ideally like to see the new rom testing code shifted to
|
|
; msinit and this code reintroduced. however for this version we
|
|
; are aiming to stick close to the IBM variety.
|
|
;
|
|
; More changes to support this commenting out will follow. All
|
|
; will be marked as modification sp001
|
|
;
|
|
; mov al,1 ; No ROM support available error code
|
|
; test byte ptr cs:[New_ROM],1
|
|
; jnz FStat01
|
|
; jmp Stat_Ret
|
|
Fstat01:
|
|
SaveReg <ds,si>
|
|
|
|
xor ax,ax
|
|
mov ds,ax
|
|
lds si, dword ptr ds:[DskAdr] ; DS:SI := pDPT
|
|
|
|
mov word ptr cs:[DPT],si ; cs:[DPT] := pDPT
|
|
mov word ptr cs:[DPT + 2],ds
|
|
|
|
RestoreReg <si,ds>
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; modification sp001
|
|
;
|
|
; the following instruction introduced for the new rom modification
|
|
;
|
|
mov cs:[New_Rom],1 ; assume new rom
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
mov ax,word ptr [di].cCyln
|
|
mov cx,word ptr [di].Seclim
|
|
; set up registers for format status call
|
|
and AH, 03h ; 'and' out unneeded track bits
|
|
ror AH, 1 ; get track and sector values correct
|
|
ror AH, 1
|
|
or AH, CL ; set sector number
|
|
xchg AH, AL
|
|
mov CX, AX
|
|
dec CH
|
|
mov DL, byte ptr [DI].DriveNum ; get drive number
|
|
mov AH, 18h ; set command to "sec/trk supported?"
|
|
|
|
SaveReg <ES,DI,DS,SI>
|
|
int 13h ; call rom bios to see if supported
|
|
jc Format_Stat_Err ; if carry, combination is not supported
|
|
|
|
; ES:DI points to new Disk Base Table
|
|
; combination for this drive replace
|
|
; current (DskAdr) pointer with new one,
|
|
; saving the old one in TempDPT.
|
|
|
|
cmp cs:[Had_Format_Error],1 ; Are we here because of a format err
|
|
jnz Fstat02 ; Then skip the disk base setup
|
|
|
|
xor al,al ; Supported and OK
|
|
mov cs:[Had_Format_Error],al ; Clear format error
|
|
jmp Pop_Stat_Ret ; Back to work
|
|
|
|
Fstat02:
|
|
xor ax,ax
|
|
mov ds,ax
|
|
lds si, dword ptr ds:[DskAdr] ; DS:SI := pDPT
|
|
|
|
mov word ptr cs:[TempDPT],si
|
|
mov word ptr cs:[TempDPT + 2],ds ; Save pDPT
|
|
|
|
mov word ptr ds:[DskAdr],DI ; Setup New DPT returned by
|
|
mov word ptr ds:[DskAdr + 2],ES ; ROM
|
|
|
|
mov byte ptr cs:[Media_Set_For_Format],1 ; set flag
|
|
xor al,al ; Legal combination + ROM support code
|
|
jmp short Pop_Stat_Ret
|
|
|
|
Format_Stat_Err:
|
|
mov al,3 ; Assume a time out
|
|
cmp ah,Dsk_Time_Out_Err ; Was it a time out???
|
|
jz Pop_Stat_Ret ; Yes - then done
|
|
dec al ; Assume an illegal comb.
|
|
cmp ah,Dsk_illegal_combination ; Was it an illegal comb???
|
|
jz Pop_Stat_Ret ; Yes - then done
|
|
dec al ; Assume No ROM Support
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; modification sp001
|
|
;
|
|
; the following instruction was introduced for the new_rom modification
|
|
;
|
|
mov cs:[New_Rom],0 ; the old rom
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
; Return result of status call
|
|
Pop_Stat_Ret:
|
|
RestoreReg <SI,DS,DI,ES>
|
|
Stat_Ret:
|
|
clc
|
|
RestoreReg <dx,cx>
|
|
ret
|
|
FormatStatus endp
|
|
|
|
|
|
|
|
;
|
|
; VerifyTrack:
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to verify packet
|
|
;
|
|
PUBLIC VERIFYTRACK ;3.30
|
|
VerifyTrack proc near
|
|
mov cs:RFLAG, ROMverify
|
|
mov ax, word ptr es:[bx].VP_Cylinder
|
|
mov cs:curtrk, ax
|
|
mov ax, word ptr es:[bx].VP_Head
|
|
|
|
; ****** ASSUMPTION ******
|
|
; we assume that we have less than 256 heads, and that the Request
|
|
; Header Data Structure is unneccessarily big
|
|
mov cs:curhd, al
|
|
xor ax, ax
|
|
mov cx, cs:sectorsPerTrack
|
|
; Use 0:0 as the transfer address for verify
|
|
xor bx, bx
|
|
mov es, bx
|
|
call TrackIO
|
|
ret
|
|
VerifyTrack endp
|
|
|
|
;
|
|
; ReadTrack:
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to read packet
|
|
;
|
|
PUBLIC READTRACK ;3.30
|
|
ReadTrack:
|
|
mov cs:RFLAG, ROMread
|
|
jmp ReadWriteTrack
|
|
|
|
;
|
|
; WriteTrack:
|
|
;
|
|
; Input: DS:DI points to BDS for drive
|
|
; ES:BX points to write packet
|
|
;
|
|
PUBLIC WRITETRACK ;3.30
|
|
WriteTrack:
|
|
mov cs:RFLAG, ROMwrite
|
|
jmp ReadWriteTrack
|
|
;
|
|
; ReadWriteTrack:
|
|
;
|
|
; Input:
|
|
; DS:DI points to BDS for drive
|
|
; ES:BX points to write packet
|
|
; RFLAG - 2 for read, 3 for write
|
|
;
|
|
PUBLIC READWRITETRACK ;3.30
|
|
ReadWriteTrack proc near
|
|
mov ax, word ptr es:[bx].TRWP_Cylinder
|
|
mov cs:curtrk, ax
|
|
mov ax, word ptr es:[bx].TRWP_Head
|
|
|
|
; ****** ASSUMPTION ******
|
|
; we assume that we have less than 256 heads, and that the Request
|
|
; Header Data Structure is unneccessarily big
|
|
mov cs:curhd, al
|
|
mov ax, word ptr es:[bx].TRWP_FirstSector
|
|
mov cx, word ptr es:[bx].TRWP_SectorsToReadWrite
|
|
les bx, es:[bx].TRWP_TransferAddress
|
|
call TrackIO
|
|
ret
|
|
ReadWriteTrack endp
|
|
|
|
|
|
;
|
|
; TrackIO:
|
|
; Performs Track Read/Write/Verify
|
|
;
|
|
; Input:
|
|
; RFLAG - 2 = Read
|
|
; 3 = Write
|
|
; 4 = Verify
|
|
; ax - Index into track table of first sector to IO
|
|
; cx - number of sectors to IO
|
|
; es:bx - Transfer address
|
|
; ds:di - pointer to BDS
|
|
; curtrk - current cylinder
|
|
; curhd - current head
|
|
;
|
|
public trackio
|
|
TrackIO proc near
|
|
; procedure `disk' will pop stack to SPsav and return if error
|
|
mov cs:SPsav, sp
|
|
; Ensure correct disk is in drive
|
|
call CheckSingle
|
|
;
|
|
; Set up tables and variables for I/O
|
|
;
|
|
cmp byte ptr cs:[Media_Set_For_Format],1
|
|
jz DPTAlreadySet
|
|
|
|
; ;3.30
|
|
; SET UP TABLES AND VARIABLES FOR I/O ;3.30
|
|
; ;3.30
|
|
SaveReg <AX,CX>
|
|
call IOSetUp
|
|
RestoreReg <CX,AX>
|
|
;
|
|
; point si at the table entry of the first sector to be IO'd
|
|
;
|
|
DPTAlreadySet:
|
|
mov si, offset trackTable
|
|
shl ax, 1
|
|
shl ax, 1
|
|
add si, ax
|
|
;
|
|
; we want:
|
|
; cx to be the number of times we have to loop
|
|
; dx to be the number of sectors we read on each iteration
|
|
mov dx, 1
|
|
test word ptr ds:[di].Flags, GOOD_TRACKLAYOUT
|
|
jz IOnextSector
|
|
|
|
; Hey! we can read all the sectors in one blow
|
|
xchg dx, cx
|
|
|
|
IOnextSector:
|
|
push cx
|
|
push dx
|
|
; skip over the cylinder and head in the track table
|
|
inc si
|
|
inc si
|
|
|
|
; Get sector id from track table
|
|
mov AL, byte ptr cs:[si] ; get current sector value
|
|
mov cs:[cursec], AL ; save cursec value
|
|
|
|
;*** For a Fixed disk multi-track disk I/O - 4/14/86 ;3.30
|
|
;Assumptions: 1). In the input CX (# of sectors to go) to TRACKIO, only CL;3.30 is
|
|
;valid. 2). Sector size should be set to 512 bytes. 3). GOODTRACKLAYOUT. ;3.30
|
|
; ;3.30
|
|
test word ptr [di].Flags, fNon_Removable ;Fixed disk? - J.K;3.30 .
|
|
jz IOREMOVABLE ;no - ;3.30
|
|
mov cs:[seccnt], dx ;# of sectors to I;3.30 /O -
|
|
mov ax, dx ; ;3.30
|
|
call disk ; ;3.30
|
|
pop dx ; ;3.30
|
|
pop cx ; ;3.30
|
|
clc ; ;3.30
|
|
ret ; ;3.30
|
|
IOREMOVABLE: ; ;3.30
|
|
|
|
mov AL, byte ptr cs:[si]+1 ; get sector size index
|
|
|
|
; The next eight lines put sector size index in DPT
|
|
push ES ; save value while getting pointer
|
|
push SI ; to DPT
|
|
push AX
|
|
|
|
les SI, cs:DPT ; ES:SI points to DPT
|
|
; put size in DPT
|
|
mov byte ptr ES:[si].Disk_Sector_Siz, AL
|
|
mov AX, word ptr [di].seclim ; get number of sector/track
|
|
mov byte ptr ES:[si].Disk_EOT,AL ; patch in DPT
|
|
|
|
pop AX ; restore register values
|
|
pop SI
|
|
pop ES
|
|
; convert index to byte value
|
|
call SectorSizeIndexToSectorSize
|
|
push AX ; save number of bytes in sector
|
|
mov AX, DX ; get number of sector for I/0
|
|
|
|
DoTheIO:
|
|
mov cs:[SECCNT],ax ; set up the count of sectors to I/O
|
|
call disk
|
|
; advance buffer pointer by adding
|
|
; sector size
|
|
pop ax
|
|
add bx, ax
|
|
pop dx
|
|
pop cx
|
|
loop IOnextSector
|
|
call DONE ; Set time of last access, and reset
|
|
clc ; entries in DPT.
|
|
ret
|
|
|
|
TrackIO endp
|
|
;
|
|
; The sector size in bytes needs to be converted to an index value for the IBM
|
|
; ROM. (0=>128, 1=>256,2=>512,3=>1024). It is assumed that only these values
|
|
; are permissible.
|
|
; On Input AX contains sector size in bytes
|
|
; On Output AL contains index
|
|
;
|
|
public SectorSizeToSectorIndex
|
|
SectorSizeToSectorIndex proc near
|
|
and AH, 07h ; very simple error correction
|
|
mov AL, AH ; shift left 8 bits
|
|
cmp AL, 4 ; size 1024?
|
|
jnz SecToIndexRet ; no, then we are done
|
|
sub AL, 1 ; if 1024, adjust index to 3
|
|
SecToIndexRet:
|
|
ret
|
|
SectorSizeToSectorIndex endp
|
|
|
|
SectorSizeIndexToSectorSize proc near
|
|
; value in AH on entry is not important
|
|
push CX ; save CX value
|
|
mov CL, AL ; use index number as shift size
|
|
mov AX, 0080h ; set AX to 128
|
|
shl AX, CL ; shift by index to get proper value
|
|
pop CX ; restore CX value
|
|
ret
|
|
SectorSizeIndexToSectorSize endp
|
|
|
|
|
|
|
|
;
|
|
; Set up the ROM for formatting.
|
|
; we have to tell the ROM BIOS what type of disk is in the drive.
|
|
; On Input - DS:DI - points to BDS
|
|
;
|
|
SetDASD proc near
|
|
; See if we have new ROM and have issues Set Media Type For Format call
|
|
test byte ptr cs:[Media_Set_For_Format],1
|
|
jnz DasdHasBeenSet
|
|
; See if we have previously set DASD type
|
|
cmp cs:[Had_Format_Error],1
|
|
je DoSetDasd
|
|
test word ptr ds:[di].Flags, SET_DASD_true
|
|
jz DASDhasBeenSet
|
|
and word ptr ds:[di].Flags, not SET_DASD_true
|
|
; the next nine lines determine and put the DASD type in AL
|
|
DoSetDasd:
|
|
mov cs:[Had_Format_Error],0
|
|
mov cs:[GAP_PATCH], 50h ; assume 48tpi or 3.5" drive
|
|
cmp [di].FormFactor, ffSmall; is 3.5" drive?
|
|
jnz not35Drive ; no, skip down
|
|
mov AL, 04h ; yes set proper DASD value
|
|
jmp short Do_Set ; jump down
|
|
|
|
Not35Drive:
|
|
mov AL, 01h ;
|
|
cmp [di].FormFactor, ff96tpi; 96tpi disk drive?
|
|
jnz Do_Set ; no skip down to rom call
|
|
inc AL ; reflect 96tpi drive in DASD type
|
|
cmp [di].seclim, 15 ; 96tpi media in drive?
|
|
jnz Do_Set ; no, skip down to rom call
|
|
inc AL ; reflect 96tpi media in DASD type
|
|
mov cs:[GAP_PATCH], 54h ; and in the GAP_PATCH
|
|
Do_Set:
|
|
mov AH, 17h ; set command to Set DASD type
|
|
mov DL, [di].DriveNum ; set drive number
|
|
int 13h ; call rom-bios
|
|
DASDhasBeenSet:
|
|
mov ah,byte ptr [di].seclim
|
|
mov cs:[FORMT_EOT],ah
|
|
ret
|
|
SetDasd endp
|
|
|
|
|
|
;
|
|
; This routine is called if an error occurs while formatting or verifying.
|
|
; It resets the drive, and decrements the retry count.
|
|
; On Entry - DS:DI - points to BDS for the drive
|
|
; BP - contains retry count
|
|
; On Exit Flags indicate result of decrementing retry count
|
|
;
|
|
;
|
|
; There are some drives that "lose" the changeline indication if another
|
|
; floppy drive is accessed before the changeline is recorded by the device
|
|
; driver. In this situation, it is possible for the ROM to also not detect
|
|
; that the medium has changed. So, the end result is that we could have a
|
|
; diskette in the drive for which we can not even read the boot sector.
|
|
; We "fix" this by setting the byte at location DISK_STATE_MACHINE_DRV_0 (hex)
|
|
; for physical drive 0 (or DISK_STATE_MACHINE_DRV_1 for drive 1) to 0 (See
|
|
; IBM PC/AT "blessed" addresses Document for explanation) . This tells the ROM
|
|
; that the medium is 'unknown'. The ROM actually uses these locations for
|
|
; itself. Note that we do this only for internal drives; we do not do this for
|
|
; fixed disks or for physical drives > 1. We may end up corrupting some
|
|
; other bytes in memory that may be used for something else.
|
|
; NOTE: We do not stuff this byte if the last operation was a FORMAT because
|
|
; the ROM loses track of what it is trying to format!!
|
|
;
|
|
; This routine was changed to only stuff 61H when the drive indicated it
|
|
; supported changeline. The Phoenix ROM was taking a very long time
|
|
; to figure out what the media was which caused disk time outs to take
|
|
; forever
|
|
;
|
|
; We assume that DS:DI points to the current BDS for this drive.
|
|
; no registers should be touched
|
|
;
|
|
|
|
AGAIN:
|
|
call ResetDisk
|
|
dec bp ; decrement retry count
|
|
RET
|
|
|
|
PUBLIC RESETDISK
|
|
ResetDisk:
|
|
push ax
|
|
xor AH, AH ; set command to reset disk
|
|
int 13h ; call the rom-bios
|
|
pop ax
|
|
mov cs:[STEP_DRV],-1 ; zap up the speed
|
|
ret
|
|
|
|
;
|
|
; This routine sets up the Drive Parameter Table with the values needed for
|
|
; Format, does an Int 13. Values in DPT are restored after a VERIFY is done.
|
|
;
|
|
; On Entry - DS:DI - points to BDS for the drive
|
|
; ES:BX - points to TRKBUF
|
|
; AL - number of sectors
|
|
; AH - Int 13 function code
|
|
; CL - Sector number for verify
|
|
; On Exit - DS,DI,ES,BX remain unchanged.
|
|
; ax and flags are the results of the int 13
|
|
;
|
|
Public To_ROM
|
|
To_ROM:
|
|
SAVEREG <DS,DI,ES,BX,SI> ;3.30
|
|
|
|
; The below line was replaced because saving the DPT is predicated upon
|
|
; whether the functionality of the new ROM was used, not if it exists.
|
|
; test byte ptr cs:[New_ROM],1
|
|
|
|
test byte ptr cs:[Media_Set_For_Format],1
|
|
jnz Got_Valid_DPT
|
|
|
|
; Set up values in the DPT
|
|
; Set up motor start correctly for 3.5" drives.
|
|
push ax
|
|
push ds
|
|
|
|
xor ax,ax
|
|
mov ds,ax
|
|
lds si,dword ptr ds:[DskAdr] ; DS:SI := pDPT
|
|
|
|
mov word ptr cs:[DPT],si
|
|
mov word ptr cs:[DPT+2],ds ; Save pDPT
|
|
|
|
pop ds
|
|
push ES ; save value in ES
|
|
LES SI, CS:DPT
|
|
|
|
mov DX, [di].seclim ; set the sector per track in
|
|
mov es:[si].DISK_EOT, DL ; the Disk Parameter Table
|
|
cmp DX, 15 ; 96tip media?
|
|
jz To_ROM1 ; yes, skip down
|
|
; no - set Format Gap to 320/360 media value
|
|
mov CL, cs:[Gap_Patch]
|
|
mov byte ptr ES:[si].DISK_FORMT_GAP, CL
|
|
To_ROM1: ; 3.5" floppy drive?
|
|
cmp byte ptr [di].FormFactor, ffSmall
|
|
jnz To_ROM2 ; no, skip down
|
|
; yes - reset disk moter start value
|
|
mov byte ptr ES:[si].DISK_MOTOR_STRT, 4
|
|
To_ROM2:
|
|
pop ES ; restore ES value
|
|
pop ax
|
|
|
|
Got_Valid_DPT:
|
|
; now set up the registers
|
|
mov DL, [di].DriveNum ; set drive number
|
|
mov DH, CS:[HDNUM] ; set head number
|
|
mov CX, CS:[TRKNUM] ; set track number
|
|
ror CH,1
|
|
ror CH,1
|
|
xchg CH, CL
|
|
int 13h ; call the rom-bios disk routines
|
|
RestoreReg <si,bx,es,di,ds>
|
|
ret
|
|
|
|
|
|
;
|
|
; Get the owner of the physical drive represented by the logical drive in BL.
|
|
; The assumption is that we **ALWAYS** keep track of the owner of a drive!!
|
|
; If this is not the case, the system may hang, just following the linked list.
|
|
;
|
|
PUBLIC IOCTL$GETOWN
|
|
IOCTL$GETOWN:
|
|
call SetDrive
|
|
mov al,byte ptr [di].DriveNum ; Get physical drive number
|
|
push cs
|
|
pop ds
|
|
mov di,word ptr Start_BDS
|
|
Own_Loop:
|
|
cmp byte ptr [di].DriveNum,al
|
|
jne GetNextBDS
|
|
test word ptr [di].flags,fI_Own_Physical
|
|
jnz Done_GetOwn
|
|
GetNextBDS:
|
|
mov bx,word ptr [di].link+2
|
|
mov di,word ptr [di].link
|
|
mov ds,bx
|
|
jmp short Own_Loop
|
|
Done_GetOwn:
|
|
JMP SHORT EXIT_OWN
|
|
|
|
;
|
|
; Set the ownership of the physical drive represented by the logical drive in
|
|
; BL.
|
|
;
|
|
PUBLIC IOCTL$SETOWN
|
|
IOCTL$SETOWN:
|
|
call SetDrive
|
|
mov byte ptr cs:[fSetOwner],1 ; set flag for CheckSingle to
|
|
; look at.
|
|
call CheckSingle ; Set ownership of drive
|
|
mov byte ptr cs:[fSetOwner],0 ; reset flag
|
|
xor bx,bx
|
|
mov es,bx
|
|
mov cl,-1
|
|
mov byte ptr es:[LSTDRV],cl ; Set up SDSB as well
|
|
|
|
EXIT_OWN:
|
|
; If there is only one logical drive assigned to this physical drive, return
|
|
; 0 to user to indicate this.
|
|
xor cl,cl
|
|
test word ptr [di].flags,fI_Am_Mult
|
|
jz EXIT_NO_MULT
|
|
mov cl,byte ptr [di].DriveLet ; Get logical drive number
|
|
inc cl ; get it 1-based
|
|
EXIT_NO_MULT:
|
|
LDS BX,CS:[PtrSav]
|
|
mov byte ptr [BX].UNIT,CL
|
|
jmp EXIT
|
|
|
|
|
|
|
|
|
|
;
|
|
; Moves the old DPT that had been saved in TempDPT back to DPT. This is done
|
|
; only if the first byte of TempDPT is not -1.
|
|
; All registers (including flags) are preserved.
|
|
;
|
|
Public RestoreOldDPT
|
|
RestoreOldDPT:
|
|
; If we have already restored the disk base table earlier, do not do it
|
|
; again.
|
|
push ax
|
|
xor al,al
|
|
; Reset flag and get current flag setting
|
|
mov cs:[Had_Format_Error],al
|
|
xchg byte ptr cs:[Media_Set_For_Format],al
|
|
or al,al
|
|
jz DontRestore
|
|
SaveReg <si,ds,es>
|
|
LDS SI,CS:[TempDPT]
|
|
xor ax,ax
|
|
mov es,ax ; have ES -> segment 0
|
|
MOV WORD PTR ES:[DskAdr],SI
|
|
MOV WORD PTR ES:[DskAdr+2],DS
|
|
GotCurrentDPT:
|
|
RestoreReg <es,ds,si>
|
|
DontRestore:
|
|
pop ax
|
|
clc ; clear carry
|
|
ret ; (7/31/86)
|
|
|
|
;end of file msioctl.asm
|