kolibrios-fun/trunk/blkdev/fdc.inc
ha d8e9ce1559 Kolibri 5 initial checkout
git-svn-id: svn://kolibrios.org@1 a494cfbc-eb01-0410-851d-a64ba20cac60
2005-10-06 17:56:22 +00:00

369 lines
9.0 KiB
PHP

;### fdc.inc ### Menuetos floppy stuff.
;Version 0.2: Write individual tracks. / Sync ramdisk <-> floppy
;Version 0.1: Write full ramdisk to floppy.
;£loppyright Tolle.
;depends on:
;restorefatchain
;memmove
;Int 6 (sys32.inc) should call fdc_irq func.
;The ramdisk should be at 0x100000
;Keeping track of the tracks.
iglobal
cylinder db 0
sector db 1
head db 0
;Memory and dma variables.
fdcmem dd 0x100000
cpymem dd 0x100000
dmamem dd 0x100000
endg
uglobal
dmasize db 0x0
dmamode db 0x0
endg
iglobal
;function pointers.
fdc_irq_func dd fdc_null
fdc_pump_func dd fdc_null
endg
uglobal
;General stuff
fdc_st0 db 0 ;status register 0 of last resultphase.
fdc_mutex db 0 ;wait in line. (Block calling app)
fdc_callspending db 0 ;mystery sauce
fdc_settings dd 0 ;bitfield.
endg
;Bit 0 enable direct file write [yes/no]
fdc_set: ;ebx: fdc_settings bitfield.
mov [fdc_settings],ebx
ret
fdc_get: ;returns fdc_settings in ecx
mov ecx, [fdc_settings]
ret
fdc_init: ;start with clean tracks.
mov edi,0xD201
mov al,0
mov ecx,160
rep stosb
ret
fdc_filesave: ;ebx: cluster to be saved.
pusha ;returns immediately. does not trigger a write.
mov eax,ebx
add eax,31
mov bl,18
div bl
mov ah,0
add eax,0xD201
mov [eax],byte 1 ;This track is now dirty.
popa
ret
fdc_writeramdisk: ;mark all tracks as dirty.
mov edi,0xD201
mov al,1
mov ecx,160
rep stosb
jmp fdc_commitflush
fdc_commitfile: ;flush dirty tracks to floppy
test [fdc_settings],1 ;...but only if this is really wanted by the user.
je fdc_commitend
fdc_commitflush:
cmp [fdc_callspending],5
je fdc_commitend
inc [fdc_callspending]
cmp [fdc_callspending],1
je fdc_commitonce
fdc_commitend:
ret
fdc_commitonce: ;One at a time.
.stall:
cli
cmp [fdc_mutex],0
jne .stallret
mov [fdc_mutex],1
jmp .goahead
.stallret:
sti
jmp .stall
.goahead:
sti
fdc_commitramdisk:
call restorefatchain
;Move the bootsector to a safe place.
mov eax,0x100000
mov ebx,0xD000
mov ecx,512
call memmove
;Always write the FAT table
mov eax,0xD201
mov [eax],byte 1
inc eax
mov [eax],byte 1
mov [dmamode],0x4A ;read from memory to floppy.
mov [dmasize],0x1 ;read 512 bytes sectors.
mov [fdc_irq_func],fdc_commitramdisk1
call fdc_floppy_on ;start floppy A: moter starts interruptflow.
ret
fdc_commitramdisk1:
mov [fdc_irq_func],fdc_recalibrate_result
mov [fdc_pump_func],fdc_commitramdisk2
call fdc_recalibrate ;retract the head to cylinder 0, sector 1
ret
fdc_commitramdisk2:
mov[head],0 ;set variables.
mov[cylinder],0
mov [sector],1
mov[cpymem],0x102400
mov [fdc_pump_func],fdc_fullpump
call fdc_write ;fdc_write will continue interruptflow
ret
fdc_fullpump:
add [dmamem],512
add [sector],1
cmp [sector],19
jne .clusterwrite
sub [dmamem],9216
mov eax,[cpymem]
mov ebx,[fdcmem]
mov ecx,9216
call memmove
add [cpymem],9216
cmp [head],0
je .nocylinderchange
add [cylinder],1
.nocylinderchange:
xor [head],1
cmp [cylinder],80
jne .noendofwrite
mov[fdc_irq_func],fdc_complete
call fdc_floppy_off
call fdc_init
jmp .end
.noendofwrite:
mov [sector],1
.clusterwrite:
xor eax,eax
mov al,[cylinder]
shl eax,1
add al,[head]
add eax,0xD201
mov bl,[eax]
cmp bl,1
jne fdc_fullpump
call fdc_write
.end:
ret
fdc_write:
call fdc_program_dma
call fdc_seek
ret
fdc_seek:
mov al, 0x0f
call fdc_write_reg
mov al,[head]
shl al,2
call fdc_write_reg
mov al,[cylinder]
call fdc_write_reg
mov [fdc_irq_func],fdc_seek_result
ret
fdc_seek_result:
call fdc_sensei
cmp al,[cylinder]
je .succes
call fdc_seek
jmp .end
.succes:
call fdc_write_sector
.end:
ret
fdc_write_sector:
mov al,0x45 ;write sector command
fdc_commandphase:
call fdc_write_reg
mov al,[head]
shl al,2
call fdc_write_reg
mov al,[cylinder]
call fdc_write_reg
mov al,[head]
call fdc_write_reg
mov al,[sector]
call fdc_write_reg
mov al,2 ;Sector size (2 ~> 512 bytes)
call fdc_write_reg
mov al,18 ;last sector on track.
call fdc_write_reg
mov al,27 ;length of GAP3
call fdc_write_reg
mov al,0xFF ;data length, ignored.
call fdc_write_reg
mov [fdc_irq_func],fdc_resultphase
ret
fdc_resultphase:
call fdc_read_reg
mov [fdc_st0],al
mov cx,6
.readresult:
call fdc_read_reg
loop .readresult
and [fdc_st0],11000000b
cmp [fdc_st0],byte 0
jz .succes
call fdc_seek
jmp .end
.succes:
call [fdc_pump_func]
.end:
ret
fdc_sensei:
mov al,0x08 ;get interrupt status command
call fdc_write_reg
call fdc_read_reg ;get result in al;
and al,0x80
cmp al,0x80
je fdc_sensei ;retry
call fdc_read_reg
ret
fdc_program_dma:
mov al,0
out 0x0c,al ; reset the flip-flop to a known state.
mov al,6 ; mask channel 2 so we can reprogram it.
out 0x0a,al
mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy
out 0x0b,al
mov al,0
out 0x0c,al ; reset the flip-flop to a known state.
mov eax,[dmamem]
out 0x04,al ; set the channel 2 starting address to 0
shr eax,8
out 0x04,al
shr eax,8
out 0x81,al
mov al,0
out 0x0c, al ; reset flip-flop
mov al, 0xff ;set count (actual size -1)
out 0x5, al
mov al, [dmasize] ;(0x1ff = 511 / 0x23ff =9215)
out 0x5,al
mov al,2
out 0xa,al
ret
fdc_recalibrate:
mov al,0x07 ;calibrate command
call fdc_write_reg
mov al,0 ;select drive 0
call fdc_write_reg
ret
fdc_recalibrate_result:
mov al,0x08 ;get interrupt status command
call fdc_write_reg ;send it
call fdc_read_reg ;get command in al;
cmp al,0x80
je fdc_recalibrate_result
mov ah,al
call fdc_read_reg
cmp ah,0x70
jne .end
call fdc_recalibrate
jmp .reallyend
.end:
call [fdc_pump_func]
.reallyend:
ret
fdc_busy:
.command_check:
mov dx,0x3F4
in al,dx
and al,0x10
cmp al,0x10
je .command_check
ret
fdc_read_reg:
status_check:
mov dx,0x3F4
in al,dx
and al,0xc0
cmp al,0xc0
jne status_check
mov dx, 0x3F5
in al, dx
ret
fdc_write_reg:
mov bl,al
.command_check:
mov dx,0x3F4
in al,dx
and al,0x80
cmp al,0x80
jne .command_check
mov al,bl
mov dx,0x3F5
out dx,al
ret
fdc_floppy_off:
mov al,0xC
mov dx,0x3f2
out dx,al
ret
fdc_floppy_on:
mov dx,0x3f2
mov al,0x0
out dx,al
mov al,0x1C
out dx,al
mov eax,50
call delay_hs
ret
fdc_complete:
mov eax,0xD000
mov ebx,0x100000
mov ecx,512
call memmove
mov [fdc_irq_func],fdc_null
mov [fdc_mutex],0
dec [fdc_callspending]
cmp [fdc_callspending],0
je .realyend
mov [fdc_mutex],1
call fdc_commitramdisk
.realyend:
ret
fdc_irq:
call [fdc_irq_func]
fdc_null:
ret