2020-12-16 00:29:35 +01:00
|
|
|
; code for disk i/o
|
|
|
|
; from outside, only the following methods are meant to be called:
|
|
|
|
; - logdrv: select drive DL to operate on
|
|
|
|
; - map*: map sector DX:AX into dskbuf
|
|
|
|
; - dirty: inform that dskbuf has been written to
|
|
|
|
; access is done by accessing dskbuf directly
|
|
|
|
|
2020-08-15 23:15:31 +02:00
|
|
|
section .bss
|
|
|
|
|
2020-10-13 22:10:23 +02:00
|
|
|
; drive actually selected for I/O
|
2020-10-11 23:33:01 +02:00
|
|
|
dsknum: resb 1
|
2020-12-16 00:29:35 +01:00
|
|
|
|
|
|
|
; bios drive we end up using
|
|
|
|
biosnum: resb 1
|
|
|
|
|
2020-12-26 21:54:39 +01:00
|
|
|
dap: resw 2
|
|
|
|
.buf: resw 2
|
2020-10-11 23:33:01 +02:00
|
|
|
; current sector number
|
2020-12-16 00:29:35 +01:00
|
|
|
; absolute, ignores partition
|
2020-12-26 21:54:39 +01:00
|
|
|
dskseek: resd 2
|
2020-08-27 22:52:16 +02:00
|
|
|
|
2020-12-26 15:37:12 +01:00
|
|
|
; bit 0 (1) - dirty flag for dskbuf
|
|
|
|
; bit 1 (2) - controller configured
|
|
|
|
; bit 2 (4) - EBIOS supported
|
2020-12-16 00:29:35 +01:00
|
|
|
dskflag: resb 1
|
|
|
|
|
2020-08-27 22:52:16 +02:00
|
|
|
; disk buffer for I/O operations
|
2020-10-11 23:33:01 +02:00
|
|
|
dskbuf: resb 512
|
2020-08-27 22:52:16 +02:00
|
|
|
|
2020-10-25 00:50:23 +02:00
|
|
|
dpt: resb DPTSIZE
|
2020-10-30 10:29:22 +01:00
|
|
|
bpb: resb BPBSIZ4
|
2020-10-25 00:50:23 +02:00
|
|
|
|
2020-08-15 23:15:31 +02:00
|
|
|
section .text
|
|
|
|
|
2020-12-22 22:14:16 +01:00
|
|
|
; initial setup for disk i/o
|
|
|
|
dinit: ; copy previously set DPT to our data area
|
|
|
|
lds si, [4*0x1E]
|
|
|
|
mov di, dpt
|
|
|
|
mov cx, 11
|
|
|
|
rep movsb
|
|
|
|
; restore DS
|
|
|
|
xor ax, ax
|
|
|
|
mov ds, ax
|
|
|
|
; set vector
|
|
|
|
mov word [4*0x1E], dpt
|
|
|
|
mov word [4*0x1E+2], ds
|
2020-12-26 17:43:01 +01:00
|
|
|
; set to invalid drive
|
|
|
|
mov byte [dsknum], 0xFF
|
2020-12-22 22:14:16 +01:00
|
|
|
ret
|
|
|
|
|
2020-12-26 15:37:12 +01:00
|
|
|
; int 13 stub
|
|
|
|
; place reserved for stack switches
|
2020-12-26 17:03:15 +01:00
|
|
|
int13: ; debug output
|
2021-01-02 03:07:40 +01:00
|
|
|
;push bx
|
|
|
|
;push dx
|
|
|
|
;push cx
|
|
|
|
;push ax
|
|
|
|
;call printf
|
|
|
|
;db "int13 CALL AX=",2," CX=",2," DX=",2," BX=",2,0x0A,0x0D,0
|
2020-12-26 17:03:15 +01:00
|
|
|
; do the call
|
2020-12-26 15:37:12 +01:00
|
|
|
int 0x13
|
2021-01-02 03:07:40 +01:00
|
|
|
;jc .err
|
2020-12-26 15:37:12 +01:00
|
|
|
ret
|
2021-01-02 03:07:40 +01:00
|
|
|
.err: ;push ax
|
|
|
|
;call printf
|
|
|
|
;db "DISK ERR AX=",2,0x0A,0x0D,0
|
|
|
|
;stc
|
|
|
|
;ret
|
2020-12-26 15:37:12 +01:00
|
|
|
|
2020-12-26 18:44:48 +01:00
|
|
|
; get drive parameters
|
|
|
|
; read BIOS int13h/AH=8 values
|
|
|
|
; DPT data gets copied over our dpt
|
|
|
|
; CHS data gets inserted into our bpb
|
2020-12-26 21:54:39 +01:00
|
|
|
getprm: test byte [dskflag], 4
|
|
|
|
jnz .nodpt
|
|
|
|
; do the query
|
|
|
|
mov ah, 8
|
2020-12-26 18:44:48 +01:00
|
|
|
mov dl, [biosnum]
|
2020-12-26 17:43:01 +01:00
|
|
|
call int13
|
2020-12-26 18:44:48 +01:00
|
|
|
; bail out if error
|
|
|
|
jc .nodpt
|
|
|
|
; get and store sector number
|
|
|
|
and cx, 0x3F
|
|
|
|
mov word [bpb+BPBSPT], cx
|
|
|
|
; get and store number of heads
|
|
|
|
xchg dl, dh
|
|
|
|
and dx, 0xFF
|
|
|
|
inc dx
|
|
|
|
mov [bpb+BPBNOS], dx
|
|
|
|
; print geometry
|
|
|
|
push dx
|
|
|
|
push cx
|
|
|
|
call printf
|
|
|
|
db "getprm: ",2," sectors, ",2," heads",0x0A,0x0D,0
|
|
|
|
; test if DPT ptr is non-zero
|
|
|
|
.nochs: mov ax, es
|
2020-12-22 22:14:16 +01:00
|
|
|
or ax, di
|
|
|
|
test ax, ax
|
2020-12-26 18:44:48 +01:00
|
|
|
jz .nodpt
|
2020-12-22 22:14:16 +01:00
|
|
|
; DS:SI = ES:DI
|
|
|
|
mov ax, es
|
|
|
|
mov ds, ax
|
|
|
|
mov si, di
|
|
|
|
; ES:DI = dpt
|
|
|
|
xor ax, ax
|
|
|
|
mov es, ax
|
|
|
|
mov di, dpt
|
|
|
|
; do the copy
|
|
|
|
mov cx, 11
|
|
|
|
rep movsb
|
2020-12-26 18:44:48 +01:00
|
|
|
.nodpt: ; restore segment registers
|
2020-12-22 22:14:16 +01:00
|
|
|
xor ax, ax
|
|
|
|
mov ds, ax
|
2020-12-26 18:44:48 +01:00
|
|
|
mov es, ax
|
2020-12-22 22:14:16 +01:00
|
|
|
ret
|
|
|
|
|
2020-12-16 00:29:35 +01:00
|
|
|
; log in drive
|
|
|
|
; currently only supports 18 sectors 2 heads floppies
|
2020-08-27 22:52:16 +02:00
|
|
|
; IN dl drive number
|
2020-12-17 01:41:53 +01:00
|
|
|
logdrv: ; dont do anything if drive already selected
|
|
|
|
cmp dl, [dsknum]
|
2020-12-26 18:44:48 +01:00
|
|
|
je logfdd.ret
|
2020-12-17 01:41:53 +01:00
|
|
|
; clear out current contents
|
2020-12-26 17:43:01 +01:00
|
|
|
push dx
|
2020-12-17 01:41:53 +01:00
|
|
|
call flush
|
|
|
|
mov ax, 0xFFFF
|
|
|
|
mov [dskseek], ax
|
|
|
|
mov [dskseek+2], ax
|
|
|
|
mov byte [dskflag], 0
|
2020-12-17 01:10:02 +01:00
|
|
|
pop dx
|
2020-12-17 01:41:53 +01:00
|
|
|
; set current drive number
|
|
|
|
mov [dsknum], dl
|
2020-12-26 18:44:48 +01:00
|
|
|
; fork off if hdd
|
|
|
|
cmp dl, 2
|
|
|
|
jnc loghdd
|
|
|
|
|
|
|
|
logfdd: ; save info for bios
|
2020-12-17 01:10:02 +01:00
|
|
|
mov [biosnum], dl
|
2020-12-22 22:14:16 +01:00
|
|
|
; reset dpt to defaults
|
2020-12-26 18:44:48 +01:00
|
|
|
call getprm
|
2020-12-18 19:29:26 +01:00
|
|
|
; set default geometry (1.44 MB floppy)
|
|
|
|
mov word [bpb+BPBNOS], 2
|
|
|
|
mov word [bpb+BPBSPT], 18
|
2020-12-17 01:41:53 +01:00
|
|
|
; load boot sector
|
2020-12-16 00:29:35 +01:00
|
|
|
xor ax, ax
|
|
|
|
xor dx, dx
|
2020-12-17 01:10:02 +01:00
|
|
|
call mapabs
|
2020-12-16 00:29:35 +01:00
|
|
|
; copy bios parameter block
|
2020-12-22 22:14:16 +01:00
|
|
|
; TODO: guess from first byte of FAT if BPB invalid
|
|
|
|
mov si, dskbuf+BPBOFF
|
2020-12-16 00:29:35 +01:00
|
|
|
mov di, bpb
|
|
|
|
mov cx, BPBSIZ4
|
|
|
|
rep movsb
|
2020-12-22 22:14:16 +01:00
|
|
|
; copy SPT to DPT
|
|
|
|
mov al, [bpb+BPBSPT]
|
|
|
|
mov [dpt+4], al
|
2020-12-17 01:10:02 +01:00
|
|
|
; make sure partition offset is forced zero
|
2020-10-30 10:29:22 +01:00
|
|
|
xor ax, ax
|
2020-12-16 00:29:35 +01:00
|
|
|
mov [bpb+BPBHS], ax
|
|
|
|
mov [bpb+BPBHS+2], ax
|
2020-12-17 01:41:53 +01:00
|
|
|
.ret: ret
|
2020-10-30 10:29:22 +01:00
|
|
|
|
2020-12-26 18:44:48 +01:00
|
|
|
loghdd: sub dl, 2
|
|
|
|
cmp dl, 4
|
|
|
|
jnc logerr
|
|
|
|
push dx
|
2020-12-26 21:54:39 +01:00
|
|
|
mov dl, 0x80
|
|
|
|
mov byte [biosnum], dl
|
|
|
|
; test for ebios extensions
|
|
|
|
mov ah, 0x41
|
|
|
|
mov bx, 0x55AA
|
|
|
|
call int13
|
|
|
|
sbb bx, 0xAA55
|
|
|
|
jnz .chs
|
|
|
|
; enable ebios and assume controller is configured
|
|
|
|
or byte [dskflag], (2+4)
|
|
|
|
; initialize DAP
|
2020-12-26 21:58:51 +01:00
|
|
|
mov word [dap], 0x10
|
2020-12-26 21:54:39 +01:00
|
|
|
mov word [dap+2], 1
|
|
|
|
mov word [dap+4], dskbuf
|
|
|
|
xor ax, ax
|
|
|
|
mov word [dap+6], ax
|
|
|
|
mov word [dap+12], ax
|
|
|
|
mov word [dap+14], ax
|
2020-12-26 18:44:48 +01:00
|
|
|
; get chs data (needed or we cant load vbr)
|
2020-12-26 21:54:39 +01:00
|
|
|
.chs: call getprm
|
2020-12-26 18:44:48 +01:00
|
|
|
; read mbr
|
|
|
|
xor ax, ax
|
|
|
|
xor dx, dx
|
|
|
|
call mapabs
|
|
|
|
; get partition number
|
|
|
|
pop bx
|
|
|
|
xor bh, bh
|
|
|
|
mov cl, 4
|
|
|
|
sal bx, cl
|
|
|
|
; bail out if no partition
|
|
|
|
cmp byte [dskbuf+0x1be+bx+4], 0
|
|
|
|
je logerr
|
|
|
|
; load partition offset
|
|
|
|
mov ax, [dskbuf+0x1be+bx+8]
|
|
|
|
mov dx, [dskbuf+0x1be+bx+8+2]
|
|
|
|
; save to to stack
|
|
|
|
push dx
|
|
|
|
push ax
|
|
|
|
; load vbr
|
|
|
|
call mapabs
|
|
|
|
; copy bpb
|
|
|
|
mov si, dskbuf+BPBOFF
|
|
|
|
mov di, bpb
|
|
|
|
mov cx, BPBSIZ4
|
|
|
|
rep movsb
|
|
|
|
; fix CHS data
|
|
|
|
call getprm
|
|
|
|
; fix partition offset
|
|
|
|
pop ax
|
|
|
|
pop dx
|
|
|
|
mov [bpb+BPBHS], ax
|
|
|
|
mov [bpb+BPBHS+2], dx
|
|
|
|
ret
|
|
|
|
|
|
|
|
logerr: stc
|
|
|
|
ret
|
|
|
|
|
2020-12-16 00:29:35 +01:00
|
|
|
mapclu: ; counting from begin of cluster area
|
|
|
|
mov bx, [bpb+BPBRDE]
|
|
|
|
mov cl, 4
|
|
|
|
shr bx, cl ; 32 bytes per entry
|
|
|
|
add ax, bx
|
|
|
|
adc dx, 0
|
|
|
|
maprd: ; counting from beginning of dir
|
|
|
|
; add fat table sizes
|
|
|
|
xor ch, ch
|
|
|
|
mov cl, byte [bpb+BPBFN]
|
|
|
|
.loop: add ax, [bpb+BPBFS]
|
|
|
|
adc dx, 0
|
|
|
|
loop .loop
|
|
|
|
mapfat: ; counting from beginning of FAT
|
|
|
|
; add reserved sector count
|
|
|
|
add ax, [bpb+BPBRSC]
|
|
|
|
adc dx, 0
|
|
|
|
map: ; count from partition start
|
2020-12-17 01:10:02 +01:00
|
|
|
add ax, [bpb+BPBHS]
|
|
|
|
add dx, [bpb+BPBHS+2]
|
|
|
|
mapabs: ; absolute sector count
|
|
|
|
; skip doing a read if sector number matches
|
|
|
|
cmp ax, [dskseek]
|
|
|
|
jne read
|
|
|
|
cmp dx, [dskseek+2]
|
|
|
|
jne read
|
2020-08-27 22:52:16 +02:00
|
|
|
ret
|
|
|
|
|
2020-12-17 01:10:02 +01:00
|
|
|
read: push ax
|
2020-12-16 00:29:35 +01:00
|
|
|
push dx
|
|
|
|
call flush
|
|
|
|
pop dx
|
|
|
|
pop ax
|
|
|
|
; store the sector number
|
2020-10-11 23:33:01 +02:00
|
|
|
mov [dskseek], ax
|
2020-12-16 00:29:35 +01:00
|
|
|
mov [dskseek+2], dx
|
|
|
|
; do the actual read
|
2020-12-26 15:37:12 +01:00
|
|
|
|
2020-12-26 17:03:15 +01:00
|
|
|
; low level read and write
|
|
|
|
; call again to retry, no input registers
|
|
|
|
; read or write is configured in cx
|
2020-12-26 15:37:12 +01:00
|
|
|
_read: mov ch, 2
|
|
|
|
db 0x3D ; cmp ax, imm16: causes next instr to be skipped
|
|
|
|
_write: mov ch, 3
|
|
|
|
mov cl, 1 ; read len
|
2020-12-26 21:54:39 +01:00
|
|
|
; check if ebios supported
|
|
|
|
test byte [dskflag], 4
|
|
|
|
jz .l00
|
|
|
|
mov ax, cx
|
|
|
|
or ah, 0x40
|
|
|
|
mov si, dap
|
|
|
|
jmp .do
|
2020-12-26 15:37:12 +01:00
|
|
|
; check if we can skip controller reset
|
2020-12-26 21:54:39 +01:00
|
|
|
.l00: test byte [dskflag], 2
|
2020-12-26 15:37:12 +01:00
|
|
|
jnz .l01
|
|
|
|
; do controller reset
|
|
|
|
mov dl, [biosnum]
|
|
|
|
mov ah, 0
|
|
|
|
call int13
|
|
|
|
or byte [dskflag], 2
|
|
|
|
.l01: ; put sectors per cylinder into bx
|
|
|
|
mov ax, [bpb+BPBSPT]
|
|
|
|
mul word [bpb+BPBNOS]
|
|
|
|
mov bx, ax
|
|
|
|
; put linear sector num into dx:ax
|
|
|
|
mov ax, [dskseek]
|
|
|
|
mov dx, [dskseek+2]
|
|
|
|
; dx:ax = linear count, bx = sectors / cylinder
|
|
|
|
div bx
|
|
|
|
xchg ax, dx
|
|
|
|
; dx = cylinder, ax = head * spt + sector
|
|
|
|
mov bl, [bpb+BPBSPT]
|
|
|
|
div byte bl
|
|
|
|
; dx = cylinder, al = head, ah = sector
|
|
|
|
xchg dl, dh
|
|
|
|
ror dl, 1
|
|
|
|
ror dl, 1
|
|
|
|
or dl, ah
|
|
|
|
inc dx
|
|
|
|
; al: head number
|
|
|
|
; dh bit 0-7: cylinder bits 0-7
|
|
|
|
; dl bit 0-5: sector bits 0-5
|
|
|
|
; dl bit 6-7: cylinder bits 8-9
|
|
|
|
; shuffle values around for bios
|
|
|
|
xchg ax, cx
|
|
|
|
xchg cx, dx
|
|
|
|
xchg dh, dl
|
|
|
|
mov bx, dskbuf
|
2020-12-26 21:54:39 +01:00
|
|
|
.do: mov dl, [biosnum]
|
2020-12-26 15:37:12 +01:00
|
|
|
; ah: subfunction selected via cx previously
|
|
|
|
; al: 1 = reading 1 sector
|
|
|
|
; cx: sector and cylinder number
|
|
|
|
; dh: head number
|
|
|
|
; dl: drive number
|
|
|
|
; bx: offset to disk buffer
|
|
|
|
call int13
|
|
|
|
jc .err
|
|
|
|
; clear dirty flag on success
|
|
|
|
and byte [dskflag], 0xFE
|
|
|
|
clc
|
|
|
|
ret
|
|
|
|
.err: ; assume controller is misconfigured
|
|
|
|
and byte [dskflag], 0xFD
|
|
|
|
; exit with carry flag set
|
|
|
|
stc
|
2020-12-16 00:29:35 +01:00
|
|
|
ret
|
|
|
|
|
|
|
|
; mark dskbuf as containing unwritten changes
|
|
|
|
dirty: or byte [dskflag], 1 ; dirty
|
2020-08-27 22:52:16 +02:00
|
|
|
ret
|
|
|
|
|
2020-10-11 23:33:01 +02:00
|
|
|
; flush buffer if dirty
|
2020-12-16 00:29:35 +01:00
|
|
|
flush: test byte [dskflag], 1
|
|
|
|
jz .ret
|
|
|
|
; TODO: error handling & retries
|
2020-12-26 15:37:12 +01:00
|
|
|
jmp _write
|
2020-12-16 00:29:35 +01:00
|
|
|
.ret: ret
|