diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2018-05-24 09:19:44 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2018-05-24 09:19:44 -0400 |
commit | df782d398e5a13a25d8d938c18e52d1798a1cbce (patch) | |
tree | 2fd537d5aee3c7cdc53073c5d63d79c887de9976 | |
parent | a9445c3d852cab19b84b03066f62201389434c85 (diff) | |
download | minos-df782d398e5a13a25d8d938c18e52d1798a1cbce.tar.gz |
Overhauled
-rw-r--r-- | disk.asm | 260 |
1 files changed, 216 insertions, 44 deletions
@@ -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 |