; =============================================================================
;
; Litos - Block device
;
; =============================================================================
CODE_SECTION 32
; -----------------------------------------------------------------------------
; Read sectors from track
; -----------------------------------------------------------------------------
; INPUT: EAX = start sector number (1...)
; EBX = floppy disk device parameter block FLOPPY
; ECX = number of sectors
; EDX = data buffer
; ESI = head
; EDI = cylinder
; OUTPUT: EAX = sectors OK read
; CY = error
; -----------------------------------------------------------------------------
DiskReadTrk: DRVFNC ebx,DISKF_ReadTrk
; -----------------------------------------------------------------------------
; Write sectors to track
; -----------------------------------------------------------------------------
; INPUT: EAX = start sector number (1...)
; EBX = floppy disk device parameter block FLOPPY
; ECX = number of sectors
; EDX = data buffer
; ESI = head
; EDI = cylinder
; OUTPUT: EAX = sectors OK written
; CY = error
; -----------------------------------------------------------------------------
DiskWriteTrk: DRVFNC ebx,DISKF_WriteTrk
; -----------------------------------------------------------------------------
; Verify sectors from track
; -----------------------------------------------------------------------------
; INPUT: EAX = start sector number (1...)
; EBX = floppy disk device parameter block FLOPPY
; ECX = number of sectors
; ESI = head
; EDI = cylinder
; OUTPUT: EAX = sectors OK verified
; CY = error
; -----------------------------------------------------------------------------
DiskVerifyTrk: DRVFNC ebx,DISKF_VerifyTrk
; -----------------------------------------------------------------------------
; Compare sectors from track
; -----------------------------------------------------------------------------
; INPUT: EAX = start sector number (1...)
; EBX = floppy disk device parameter block FLOPPY
; ECX = number of sectors
; EDX = data buffer
; ESI = head
; EDI = cylinder
; OUTPUT: EAX = sectors OK compared
; CY = error
; -----------------------------------------------------------------------------
DiskCompTrk: DRVFNC ebx,DISKF_CompTrk
; -----------------------------------------------------------------------------
; Format track (without verify)
; -----------------------------------------------------------------------------
; INPUT: AL = formatting filler byte
; EBX = floppy disk device parameter block FLOPPY
; ESI = head
; EDI = cylinder
; OUTPUT: CY = error
; -----------------------------------------------------------------------------
DiskFormatTrk: DRVFNC ebx,DISKF_FormatTrk
; -----------------------------------------------------------------------------
; Calculate media size
; -----------------------------------------------------------------------------
; INPUT: EBX = block device DISK
; NOTES: Input parameters are cylinders, heads and sectors per track.
; -----------------------------------------------------------------------------
; ------------- Push registers
DiskCalcMedia: push eax ; push EAX
push ecx ; push ECX
push edx ; push EDX
push esi ; push ESI
; ------------- Calculate total number of tracks (heads*cylinders -> EDX:EAX)
mov eax,[ebx+DISK_Heads] ; EAX <- number of heads
mul dword [ebx+DISK_Tracks] ; EDX:EAX <- total tracks
; ------------- Calculate total number of sectors (-> ESI:EAX)
mov ecx,[ebx+DISK_TrackSect] ; ECX <- sectors per track
xchg eax,esi ; ESI <- tracks LOW
xchg eax,edx ; EAX <- tracks HIGH
mul ecx ; EAX <- sectors HIGH
xchg eax,esi ; ESI <- sectors HIGH,EAX <- tracks LOW
mul ecx ; EDX:EAX <- sectors LOW
add edx,esi ; EDX <- sectors HIGH
mov [ebx+DISK_SectNum],eax ; store sectors LOW
mov [ebx+DISK_SectNum+4],edx ; store sectors HIGH
; ------------- Calculate media size in bytes
mov cl,[ebx+DDEV_GranBits] ; CL <- granularity bits
shld edx,eax,cl ; rotate EDX:EAX << CL
shl eax,cl ; rotate EAX << CL
mov [ebx+DDEV_Size],eax ; set total size LOW
mov [ebx+DDEV_Size+4],edx ; set total size HIGH
; ------------- Pop registers
pop esi ; pop ESI
pop edx ; pop EDX
pop ecx ; pop ECX
pop eax ; pop EAX
ret
; -----------------------------------------------------------------------------
; Prepare parameters for operation
; -----------------------------------------------------------------------------
; INPUT: EDX:EAX = data offset
; EBX = block device DISK
; ECX = data length (bytes)
; ESI = data buffer
; OUTPUT: EAX = starting sector on track (1...)
; ECX = number of sectors
; EDX = data buffer
; ESI = head
; EDI = cylinder
; CY = invalid disk parameters (TrackSect or Heads is zero)
; -----------------------------------------------------------------------------
; ------------- Push registers
DiskPrepPar: push esi ; push ESI (data buffer)
push ebp ; push EBP
; ------------- Check disk parameters
cmp dword [ebx+DISK_TrackSect],byte 1 ; sectors per track
jb DiskPrepPar8 ; invalid parameter
cmp dword [ebx+DISK_Heads],byte 1 ; number of heads
jb DiskPrepPar8 ; invalid parameter
; ------------- Prepare starting sector (-> ESI:EDI)
push ecx ; push ECX (data length)
xchg eax,edi ; EDI <- current position LOW
mov esi,edx ; ESI <- current position HIGH
mov cl,[ebx+DDEV_GranBits] ; CL <- granularity bits
shrd edi,esi,cl ; rotate position >> CL
shr esi,cl ; rotate position HIGH
pop eax ; pop EAX (data length)
; ------------- Prepare number of sectors (-> EAX)
shr eax,cl ; EAX <- number of sectors
; ------------- Get sector on track (-> EBP) and track (-> ESI:EDI)
xor edx,edx ; EDX <- 0
xchg eax,esi ; EAX <- sector HIGH, ESI <- sectors
mov ecx,[ebx+DISK_TrackSect] ; ECX <- sectors per track
div ecx ; EAX <- track number HIGH, EDX <- rest
xchg eax,esi ; ESI <- track number HIGH,EAX<-sectors
xchg eax,edi ; EAX <- sector number LOW,EDI<-sectors
div ecx ; EAX <- track number LOW,EDX <- sector
inc edx ; EDX <- sector + 1
xchg eax,edi ; EDI <- track number LOW, EAX<-sectors
mov ebp,edx ; EBP <- sector number (1...)
; ------------- Get head (-> ESI) and cylinder (-> EDI)
xor edx,edx ; EDX <- 0
xchg eax,esi ; EAX <- track HIGH, ESI <- sectors
mov ecx,[ebx+DISK_Heads] ; ECX <- number of heads
div ecx ; EAX <- cylinder HIGH, EDX <- rest
xchg eax,esi ; ESI <- cylinder HIGH, EAX <- sectors
xchg eax,edi ; EAX <- track LOW, EDI <- sectors
div ecx ; EAX <- cylinder LOW, EDX <- head
xchg eax,edi ; EDI <- cylinder LOW, EAX <- sectors
xchg eax,ecx ; ECX <- number of sectors
xchg eax,ebp ; EAX <- sector number (1...)
xchg edx,esi ; EDX <- cylinder HIGH, ESI <- head
; ------------- Limit cylinder number on overflow (it clears CF)
or edx,edx ; cylinder overflow?
jz DiskPrepPar8 ; no overflow
xor edi,edi ; EDI <- 0
dec edi ; EDI <- -1, max. cylinder on overflow
; ------------- Pop registers
DiskPrepPar8: pop ebp ; pop EBP
pop edx ; pop EDX (data buffer)
ret
; -----------------------------------------------------------------------------
; Limit number of sectors
; -----------------------------------------------------------------------------
; INPUT: EAX = starting sector on track (1...)
; EBX = block device DISK
; ECX = number of sectors
; OUTPUT: ECX = limited number of sectors
; -----------------------------------------------------------------------------
DiskLimitSect: push edx ; push EDX
mov edx,[ebx+DISK_TrackSect] ; EDX <- sectors per track
inc edx ; EDX <- sectors per track + 1
sub edx,eax ; EDX <- remaining sectors
cmp edx,ecx ; check number of sectors
ja DiskLimitSect4 ; number of sectors is OK
mov ecx,edx ; ECX <- limit number of sectors
DiskLimitSect4: pop edx ; pop EDX
ret
; -----------------------------------------------------------------------------
; Shift to next sectors
; -----------------------------------------------------------------------------
; INPUT: EAX = sectors OK
; EBX = block device DISK
; ECX = number of sectors
; EDX = data buffer
; ESI = head
; EDI = cylinder
; OUTPUT: CY = continue with next track, NC = end of operation
; EAX = 1, new first sector on track
; ECX = new number of sectors
; EDX = new data buffer
; ESI = new head
; EDI = new cylinder
; -----------------------------------------------------------------------------
; ------------- Shift remaining sectors
DiskShiftNext: sub ecx,eax ; shift remaining sectors
jbe DiskShiftNext8 ; no other data required
; ------------- Shift address
push ecx ; push ECX
mov cl,[ebx+DDEV_GranBits] ; CL <- granularity bits
shl eax,cl ; EAX <- convert sectors to bytes
add edx,eax ; EDX <- shift address
pop ecx ; pop ECX
; ------------- Prepare new first sector on track (-> EAX)
xor eax,eax ; EAX <- 0
inc eax ; EAX <- 1, new first sector on track
; ------------- Shift head and track
inc esi ; increase head number
cmp esi,[ebx+DISK_Heads] ; check head number
jb DiskShiftNext6 ; head number is OK
xor esi,esi ; ESI <- 0, head on next cylinder
inc edi ; increase cylinder number
; ------------- Continue
DiskShiftNext6: stc ; flag to continue
ret
; ------------- End of operation
DiskShiftNext8: clc ; end of operation
ret
; -----------------------------------------------------------------------------
; Get result of operation
; -----------------------------------------------------------------------------
; INPUT: EBP = sectors OK
; EBX = block device DISK
; OUTPUT: EAX = bytes OK
; DESTROYS: EBP, ECX
; NOTES: It saves flags
; -----------------------------------------------------------------------------
DiskGetResult: pushf ; push flags
xchg eax,ebp ; EAX <- number of sectors
mov cl,[ebx+DDEV_GranBits] ; CL <- granularity bits
shl eax,cl ; EAX <- convert sectors to bytes
popf ; pop flags
ret
; -----------------------------------------------------------------------------
; Read data from disk
; -----------------------------------------------------------------------------
; INPUT: EDX:EAX = data offset
; EBX = block device DISK
; ECX = data length (bytes)
; ESI = data buffer
; OUTPUT: EAX = bytes OK read
; CY = error
; -----------------------------------------------------------------------------
; ------------- Push registers
DiskRead: push ecx ; push ECX
push edx ; push EDX
push esi ; push ESI
push edi ; push EDI
push ebp ; push EBP
; ------------- Prepare parameters
xor ebp,ebp ; EBP <- 0, data counter
call DiskPrepPar ; prepare parameters
jc short DiskWrite9 ; disk parameters error
; ------------- Check cylinder number
DiskRead2: cmp edi,[ebx+DISK_Tracks] ; check cylinder number
jae short DiskWrite9 ; invalid cylinder number
; ------------- Limit number of sectors (-> ECX)
push ecx ; push ECX
call DiskLimitSect ; limit number of sectors
; ------------- Read sectors from track
call DiskReadTrk ; read sectors from track
pop ecx ; pop ECX
; ------------- Shift sector counter
pushf ; push flags
add ebp,eax ; add sector number
popf ; pop flags
jc short DiskWrite9 ; error
; ------------- Shift to next sector
call DiskShiftNext ; shift to next sector
jc short DiskRead2 ; next track
jmp short DiskWrite9
; -----------------------------------------------------------------------------
; Write data to disk
; -----------------------------------------------------------------------------
; INPUT: EDX:EAX = data offset
; EBX = block device DISK
; ECX = data length (bytes)
; ESI = data buffer
; OUTPUT: EAX = bytes OK written
; CY = error
; -----------------------------------------------------------------------------
; ------------- Push registers
DiskWrite: push ecx ; push ECX
push edx ; push EDX
push esi ; push ESI
push edi ; push EDI
push ebp ; push EBP
; ------------- Prepare parameters
xor ebp,ebp ; EBP <- 0, data counter
call DiskPrepPar ; prepare parameters
jc short DiskWrite9 ; disk parameters error
; ------------- Check cylinder number
DiskWrite2: cmp edi,[ebx+DISK_Tracks] ; check cylinder number
jae short DiskWrite9 ; invalid cylinder number
; ------------- Limit number of sectors (-> ECX)
push ecx ; push ECX
call DiskLimitSect ; limit number of sectors
; ------------- Write sectors to track
call DiskWriteTrk ; write sectors to track
pop ecx ; pop ECX
; ------------- Shift sector counter
pushf ; push flags
add ebp,eax ; add sector number
popf ; pop flags
jc short DiskWrite9 ; error
; ------------- Shift to next sector
call DiskShiftNext ; shift to next sector
jc short DiskWrite2 ; next track
; ------------- Get mumber of bytes
DiskWrite9: call DiskGetResult ; get result of operation
; ------------- Pop registers
pop ebp ; pop EBP
pop edi ; pop EDI
pop esi ; pop ESI
pop edx ; pop EDX
pop ecx ; pop ECX
ret
; -----------------------------------------------------------------------------
; Verify data from disk
; -----------------------------------------------------------------------------
; INPUT: EDX:EAX = data offset
; EBX = block device DISK
; ECX = data length (bytes)
; OUTPUT: EAX = bytes OK verified
; CY = error
; -----------------------------------------------------------------------------
; ------------- Push registers
DiskVerify: push ecx ; push ECX
push edx ; push EDX
push esi ; push ESI
push edi ; push EDI
push ebp ; push EBP
; ------------- Prepare parameters
xor ebp,ebp ; EBP <- 0, data counter
call DiskPrepPar ; prepare parameters
jc short DiskWrite9 ; disk parameters error
; ------------- Check cylinder number
DiskVerify2: cmp edi,[ebx+DISK_Tracks] ; check cylinder number
jae short DiskWrite9 ; invalid cylinder number
; ------------- Limit number of sectors (-> ECX)
push ecx ; push ECX
call DiskLimitSect ; limit number of sectors
; ------------- Verify sectors from track
call DiskVerifyTrk ; verify sectors from track
pop ecx ; pop ECX
; ------------- Shift sector counter
pushf ; push flags
add ebp,eax ; add sector number
popf ; pop flags
jc short DiskWrite9 ; error
; ------------- Shift to next sector
call DiskShiftNext ; shift to next sector
jc short DiskVerify2 ; next track
jmp short DiskWrite9
; -----------------------------------------------------------------------------
; Compare data from disk
; -----------------------------------------------------------------------------
; INPUT: EDX:EAX = data offset
; EBX = block device DISK
; ECX = data length (bytes)
; ESI = data buffer
; OUTPUT: EAX = bytes OK compared
; CY = error
; -----------------------------------------------------------------------------
; ------------- Push registers
DiskCompare: push ecx ; push ECX
push edx ; push EDX
push esi ; push ESI
push edi ; push EDI
push ebp ; push EBP
; ------------- Prepare parameters
xor ebp,ebp ; EBP <- 0, data counter
call DiskPrepPar ; prepare parameters
jc short DiskWrite9 ; disk parameters error
; ------------- Check cylinder number
DiskCompare2: cmp edi,[ebx+DISK_Tracks] ; check cylinder number
jae short DiskWrite9 ; invalid cylinder number
; ------------- Limit number of sectors (-> ECX)
push ecx ; push ECX
call DiskLimitSect ; limit number of sectors
; ------------- Compare sectors from track
call DiskCompTrk ; compare sectors from track
pop ecx ; pop ECX
; ------------- Shift sector counter
pushf ; push flags
add ebp,eax ; add sector number
popf ; pop flags
jc short DiskWrite9 ; error
; ------------- Shift to next sector
call DiskShiftNext ; shift to next sector
jc short DiskCompare2 ; next track
jmp short DiskWrite9
; -----------------------------------------------------------------------------
; Data
; -----------------------------------------------------------------------------
DATA_SECTION
|