summaryrefslogtreecommitdiff
path: root/disk.asm
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2018-05-24 09:19:44 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2018-05-24 09:19:44 -0400
commitdf782d398e5a13a25d8d938c18e52d1798a1cbce (patch)
tree2fd537d5aee3c7cdc53073c5d63d79c887de9976 /disk.asm
parenta9445c3d852cab19b84b03066f62201389434c85 (diff)
downloadminos-df782d398e5a13a25d8d938c18e52d1798a1cbce.tar.gz
Overhauled
Diffstat (limited to 'disk.asm')
-rw-r--r--disk.asm260
1 files changed, 216 insertions, 44 deletions
diff --git a/disk.asm b/disk.asm
index 1843fca..2e001f8 100644
--- a/disk.asm
+++ b/disk.asm
@@ -2,34 +2,130 @@
%define _DISK_ASM
%include "stdio.asm"
+SECTORS_PER_TRACK equ 12h
disk_info:
push bp
mov bp, sp
+ pusha
+
+ mov ax, 0
+ mov es, ax
+ mov di, 0
+
+ mov ah, 08h
+ mov si, disk_info_fmt
+ mov dx, [bp + 4] ; load drive number
+ ; {diskette=00h..03h, hdd=80h-81h}
+ cmp dx, 80h
+ jge .is_disk
+
+ .is_diskette:
+ mov si, diskette_info_fmt
+
+ .is_disk:
+ int 13h
+ jc .error
+
+ and word [bp + 4], 07fh ; mask off bit 7
+
+ push cx
+ push dx
+ push ax
+ push word [bp + 4] ; drive number
+ push si ; format string
+ call printf
+ add sp, 2 * 5
+
+ jmp .return
+
+ .error:
+ stc
+ .return:
+ popa
+ mov sp, bp
+ pop bp
+ ret
+
+disk_info_ext:
+ push bp
+ mov bp, sp
+ pusha
+
+ sub sp, 2 ; bit-field temp storage
xor dx, dx
mov ah, 41h
mov bx, 55aah
mov dl, [bp + 4] ; drive number {80h..ffh}
int 13h
- jc .return
+ jc .return ; carry is set on failure
+ mov word [bp - 2], cx ; store bit-field
+
+ and dx, 07fh ; mask off bit 7
+
+ xchg ah, al ; extension version
+ and ax, 00ffh ; mask off high byte
- shr ax, 8
- push dx
push cx
push ax
- push disk_info_fmt
+ push dx
+ push disk_info_ext_fmt
call printf
- add sp, 6
+ add sp, 2 * 4
+
+ mov dx, word [bp - 2] ; load bit-field
+ mov cx, 0000h ; set counter
+
+ .do_flag:
+ mov bx, dx ; load BX with bit-field
+ shr bx, cl ; shift bit-field by count
+ and bx, 01h ; Is the bit set?
+ je .no_flag ; non-zero = YES
+
+ push cx ; push count
+ call disk_info_ext_print_flag ; display flag
+ add sp, 2 ; clean up
+ .no_flag:
+ inc cx ; next bit
+ cmp cx, 0fh ; 16 bits in bit field
+ jne .do_flag
.return:
+ add sp, 2
+ popa
mov sp, bp
pop bp
ret
+
+disk_info_ext_print_flag:
+ push bp
+ mov bp, sp
+ pusha
+
+ mov cx, [bp + 4]
+
+ imul cx, cx, 2 ; compute WORD offset
+ lea bx, [disk_info_ext_table] ; load array address
+ add bx, cx ; compute string pointer offset
+
+ push word [bx] ; load address of string pointer
+ push .fmt ; load format string
+ call printf
+ add sp, 2 * 2
+.return:
+ popa
+ mov sp, bp
+ pop bp
+ ret
+ .fmt db " - %s", ASCII_LF, 0
+
+
disk_last_status:
push bp
mov bp, sp
+ clc ; clear carry flag
; DL = drive number
mov ah, 01h ; BIOS get status of last drive operation
int 13h ; BIOS disk service
@@ -129,7 +225,7 @@ disk_convert_status:
push ax ; error code
push error_msg_disk_status_fmt
call printf ; Print error message
- add sp, 8 ; Clean up stack
+ add sp, 2 * 4 ; Clean up stack
.return:
popa
@@ -138,15 +234,6 @@ disk_convert_status:
ret
-disk_lba_chs:
- push bp
- mov bp, sp
-
- mov ax, word [bp - 2] ; LBA
-
- mov sp, bp
- pop bp
- ret
disk_reset:
push bp
@@ -154,10 +241,10 @@ disk_reset:
pusha
mov ah, 00h ; reset disk
- mov dl, [bp + 4] ; disk number
+ mov dl, byte [bp + 4] ; disk number
int 13h ; BIOS disk service
jnc .success
-
+ stc
.success:
popa
mov sp, bp
@@ -165,27 +252,77 @@ disk_reset:
ret
-disk_read:
+disk_lba_chs:
push bp
mov bp, sp
-
- push di
- mov di, 3 ; retry counter
-.readloop:
push ax
push bx
- push cx
push dx
+ sub sp, 2 * 3 ; -2 = HEAD
+ ; -4 = TRACK
+ ; -6 = SECTOR
- ; AL = Sectors to read
- ; ES:BX = Buffer address
- ; CH = Cylinder (10 bits [6 & 7 of CL are MSB])
- ; CL = Sector (5 lower bits)
- ; DH = Head
- ; DL = Drive
- mov ah, 02h ; BIOS - read disk sectors
- int 13h ; BIOS disk service
+ mov si, [bp + 4] ; Linear Block Address
+
+ ; compute HEAD
+ mov cx, SECTORS_PER_TRACK
+ shl cx, 1 ; SPT * 2
+ xor dx, dx ; initialize quotient
+ mov ax, si ; LBA %
+ mov bx, cx ; (SPT * 2)
+ div bx
+
+ mov ax, dx ; use quotient as next dividend
+ xor dx, dx
+ mov bx, SECTORS_PER_TRACK ; / SPT
+ div bx
+ mov [bp - 2], ax ; store HEAD (remainder)
+
+ ; compute TRACK
+ xor dx, dx ; initialize quotient
+ mov ax, si ; LBA %
+ mov bx, cx ; (SPT * 2)
+ div bx
+ mov [bp - 4], ax ; store TRACK (remainder)
+
+ ; compute SECTOR
+ xor dx, dx
+ mov ax, si
+ mov bx, SECTORS_PER_TRACK
+ div bx
+ add dx, 1
+ mov [bp - 6], dx ; store SECTOR (quotient)
+
+ pop dx
+ pop bx
+ pop ax
+ ; assemble return values
+ mov dh, byte [bp - 2] ; load HEAD
+ mov ch, byte [bp - 4] ; load TRACK
+ mov cl, byte [bp - 6] ; load SECTOR
+
+ add sp, 2 * 3
+ mov sp, bp
+ pop bp
+ ret
+
+
+disk_read:
+ push bp
+ mov bp, sp
+
+ mov si, [bp + 4] ; LBA
+
+ push si
+ call disk_lba_chs ; convert LBA to CHS
+ add sp, 2
+
+ mov ah, 02h
+ mov dl, byte [bp + 6] ; drive number
+ mov al, byte [bp + 8] ; number of sectors to read
+ mov bx, [bp + 10] ; data destination address [es:bx]
+ int 13h
jnc .success
call disk_convert_status
@@ -193,19 +330,37 @@ disk_read:
push dx
call disk_reset
add sp, 2
+ stc
+.success:
+ mov sp, bp
+ pop bp
+ ret
- pop dx
- pop cx
- pop bx
- pop ax
+disk_write:
+ push bp
+ mov bp, sp
+
+ mov si, [bp + 4] ; LBA
+ push si
+ call disk_lba_chs ; convert LBA to CHS
+ add sp, 2
+
+ mov ah, 03h
+ mov dl, byte [bp + 6] ; drive number
+ mov al, byte [bp + 8] ; number of sectors to read
+ mov bx, [bp + 10] ; data destination address [es:bx]
+ int 13h
+ jnc .success
- dec di
- jnz .readloop
+ call disk_convert_status
+ push dx
+ call disk_reset
+ add sp, 2
+ stc
.success:
- pop di
mov sp, bp
pop bp
ret
@@ -215,14 +370,31 @@ disk_read:
align 2
drive0: dw 0
-msg_disk_reset: db "Drive reset successful.", ASCII_CR, 0
-msg_disk_read: db "Sector read successful.", ASCII_CR, 0
+msg_disk_reset: db "Drive reset successful.", ASCII_LF, 0
+msg_disk_read: db "Sector read successful.", ASCII_LF, 0
+
+error_msg_disk_reset: db "Drive reset failed!", ASCII_LF, 0
+error_msg_disk_read: db "Drive read failed!", ASCII_LF, 0
+
+diskette_info_fmt: db 'FDD(%x): status=%x head_max=%x cyl_max=%x', ASCII_LF, 0
+
+disk_info_fmt: db 'HDD(%x): status=%x head_max=%x cyl_max=%x', ASCII_LF, 0
+disk_info_ext_fmt: db 'HDD(%x): IBM/MS INT 13 Extensions v%x [%x]', ASCII_LF, 0
+
+disk_info_ext_flags:
+ .bit_0: db "Extended disk access support", 0
+ .bit_1: db "Removable drive controller support", 0
+ .bit_2: db "Enhanced disk drive support", 0
+ .reserved: db "Reserved", 0
-error_msg_disk_reset: db "Drive reset failed!", ASCII_CR, 0
-error_msg_disk_read: db "Drive read failed!", ASCII_CR, 0
+disk_info_ext_table:
+ dw disk_info_ext_flags.bit_0
+ dw disk_info_ext_flags.bit_1
+ dw disk_info_ext_flags.bit_2
+ .reserved: times(15-3) dw disk_info_ext_flags.reserved
+ dw 0000h ; END of disk_info_ext_table
-disk_info_fmt: db 'HDD(%c): INT 13h Ext: %x (%x)', ASCII_CR, 0
-error_msg_disk_status_fmt: db 'ERROR %x: Drive %x: %s', ASCII_CR, 0
+error_msg_disk_status_fmt: db 'ERROR %x: Drive %x: %s', ASCII_LF, 0
error_msg_disk:
eds_success: db "Success", 0 ; 00h
eds_invalid_command: db "Invalid command", 0