Hi there I am trying to format a 5.25" floppy via my own homebrew CPU and the loop is getting stuck trying to read the DRQ flag in the status register.
This is the WD1770 controller.
Could anyone PLEASE take a look at my code and tell me if you can see anything I am doing wrong?
Basically I issue the write track command, and then I am just waiting for DRQ in loops and when DRQ = 1 I write a byte to the data register. But it seems it never manages to read the DRQ == 1...
Here is my code. Please help
syscall_fdc_format:
mov [fdc_128_format_track], bl ; write track number to formatting data block
mov al, 1
mov [fdc_128_format_sect], al ; reset sector variable to 1
mov d, s_format_begin
call _puts
mov bl, [_FDC_WD_STAT_CMD] ; read status register to clear any errors
call print_u8x
call printnl
fdc_header_loop_start:
mov al, %11110110 ; Write Track Command: {1111, 0: Enable Spin-up Seq, 1: Settling Delay, 1: No Write Precompensation, 0}
mov [_FDC_WD_STAT_CMD], al
; write the first data block for formatting which is 40 bytes of 0xFF:
call fdc_wait_64us ; after issuing write track command, need to wait 64us before reading the status register
mov bl, [_FDC_WD_STAT_CMD] ; read status flag
call print_u8x
call printnl
mov cl, 40
fdc_drq_loop: ; for each byte, we need to wait for DRQ to be high
mov al, [_FDC_WD_STAT_CMD] ; read lost data flag
and al, $02 ; check drq bit
jz fdc_drq_loop
mov bl, $FF ; load format byte
mov [_FDC_WD_DATA], bl ; send data byte to wd1770
dec cl
jnz fdc_drq_loop
; start inner data block loop. this block is written 16 times
fdc_inner_loop:
mov si, fdc_128_format_inner
mov cl, 169 ; the inner format data block has 169 bytes total
mov ah, 1
fdc_drq_loop1:
mov al, [_FDC_WD_STAT_CMD] ; read lost data flag
and al, $02 ; check drq bit
jz fdc_drq_loop1
lodsb ; load format byte
mov [_FDC_WD_DATA], al ; send data byte to wd1770
dec cl
jnz fdc_drq_loop1 ; test whether entire data block was written
mov al, ah
inc al
mov [fdc_128_format_sect], al ; update the sector number variable in the format data block
cmp al, 17
jne fdc_inner_loop ; test whether data block was written 16 times
; here all the sectors have been written. now fill in remaining of the track until wd1770 interrupts out
fdc_format_footer:
mov a, $6500
syscall sys_io ; char in AH
fdc_footer_drq_loop:
mov al, [_FDC_WD_STAT_CMD] ; read lost data flag
and al, $02 ; check drq bit
jz fdc_footer_drq_loop
mov bl, $FF ; load format byte
mov [_FDC_WD_DATA], bl ; send data byte to wd1770
mov al, [_FDC_WD_STAT_CMD]
and al, $01 ; check busy bit
jnz fdc_format_footer ; if busy == 1, command is not finished, so loop again
fdc_format_done:
mov d, s_format_done
call _puts
mov al, %10000001 ; re-enable uart and fdc irqs
stomsk
sysret
This is the WD1770 controller.
Could anyone PLEASE take a look at my code and tell me if you can see anything I am doing wrong?
Basically I issue the write track command, and then I am just waiting for DRQ in loops and when DRQ = 1 I write a byte to the data register. But it seems it never manages to read the DRQ == 1...
Here is my code. Please help
syscall_fdc_format:
mov [fdc_128_format_track], bl ; write track number to formatting data block
mov al, 1
mov [fdc_128_format_sect], al ; reset sector variable to 1
mov d, s_format_begin
call _puts
mov bl, [_FDC_WD_STAT_CMD] ; read status register to clear any errors
call print_u8x
call printnl
fdc_header_loop_start:
mov al, %11110110 ; Write Track Command: {1111, 0: Enable Spin-up Seq, 1: Settling Delay, 1: No Write Precompensation, 0}
mov [_FDC_WD_STAT_CMD], al
; write the first data block for formatting which is 40 bytes of 0xFF:
call fdc_wait_64us ; after issuing write track command, need to wait 64us before reading the status register
mov bl, [_FDC_WD_STAT_CMD] ; read status flag
call print_u8x
call printnl
mov cl, 40
fdc_drq_loop: ; for each byte, we need to wait for DRQ to be high
mov al, [_FDC_WD_STAT_CMD] ; read lost data flag
and al, $02 ; check drq bit
jz fdc_drq_loop
mov bl, $FF ; load format byte
mov [_FDC_WD_DATA], bl ; send data byte to wd1770
dec cl
jnz fdc_drq_loop
; start inner data block loop. this block is written 16 times
fdc_inner_loop:
mov si, fdc_128_format_inner
mov cl, 169 ; the inner format data block has 169 bytes total
mov ah, 1
fdc_drq_loop1:
mov al, [_FDC_WD_STAT_CMD] ; read lost data flag
and al, $02 ; check drq bit
jz fdc_drq_loop1
lodsb ; load format byte
mov [_FDC_WD_DATA], al ; send data byte to wd1770
dec cl
jnz fdc_drq_loop1 ; test whether entire data block was written
mov al, ah
inc al
mov [fdc_128_format_sect], al ; update the sector number variable in the format data block
cmp al, 17
jne fdc_inner_loop ; test whether data block was written 16 times
; here all the sectors have been written. now fill in remaining of the track until wd1770 interrupts out
fdc_format_footer:
mov a, $6500
syscall sys_io ; char in AH
fdc_footer_drq_loop:
mov al, [_FDC_WD_STAT_CMD] ; read lost data flag
and al, $02 ; check drq bit
jz fdc_footer_drq_loop
mov bl, $FF ; load format byte
mov [_FDC_WD_DATA], bl ; send data byte to wd1770
mov al, [_FDC_WD_STAT_CMD]
and al, $01 ; check busy bit
jnz fdc_format_footer ; if busy == 1, command is not finished, so loop again
fdc_format_done:
mov d, s_format_done
call _puts
mov al, %10000001 ; re-enable uart and fdc irqs
stomsk
sysret