\ vandys \ ide.f \ Block I/O routines for IDE on the x86 drivers definitions \ Parameters SECSIZ constant SECSIZ SECWORDS constant SECWORDS BLKSECS constant BLKSECS \ IDE unit for current operation variable ideunit \ Offset into disk to address active partition \ Set up during bootup via boot-ide variable ideoff \ vandys \ I/O base ports $1F0 constant IDEBASE $206 constant IDECTLR \ IDE controller ports 0 constant IDE_DATA 1 constant IDE_ERROR 2 constant IDE_SCNT 3 constant IDE_SNUM 4 constant IDE_CYL0 5 constant IDE_CYL1 6 constant IDE_SDH 7 constant IDE_STATUS 7 constant IDE_CMD \ IDE status bits $01 constant IDES_ERROR $04 constant IDES_ECC $08 constant IDES_DRQ $80 constant IDES_BUSY \ IDE mode of operation--LBA/IBM $E0 constant IDE_MODE \ IDE commands $20 constant IDECMD_READ $30 constant IDECMD_WRITE \ vandys \ Return match of IDE status bit : ide_stat_check ( n -- bool ) IDEBASE IDE_STATUS + inb and 0= not ; \ Tell if controller indicates it's busy with a command : idebusy ( -- bool ) IDES_BUSY ide_stat_check ; \ Tell if controller has a data request : idedrq ( -- bool ) IDES_DRQ ide_stat_check ; \ vandys \ Make these CODE words when we get the assembler running \ Block I/O into buffer : repinsw ( a port count -- ) 2* rot swap over + swap do dup inw i w! 2 +loop drop ; : repoutsw ( a port count -- ) 2* rot swap over + swap do i w@ over outw 2 +loop drop ; \ code repinsw ( a port count -- ) ecx pop edx pop edi pop \ 16: rep ins next c; \ code repoutsw ( a port count -- ) esi eax mov \ ecx pop edx pop esi pop 16: rep outs \ eax esi mov next c; \ vandys : waitdrq ( -- ) begin idedrq 0= while pause repeat ; : ideio ( a blk op -- ) begin idebusy while pause repeat BLKSECS IDEBASE IDE_SCNT + outb -rot dup IDEBASE IDE_SNUM + outb dup 8 rshift IDEBASE IDE_CYL0 + outb dup 16 rshift IDEBASE IDE_CYL1 + outb 24 rshift IDE_MODE or ideunit @ 4 lshift or IDEBASE IDE_SDH + outb \ vandys swap dup IDEBASE IDE_CMD + outb IDECMD_WRITE = if BLKSECS 0 do waitdrq dup IDEBASE IDE_DATA + SECWORDS repoutsw SECSIZ + loop else BLKSECS 0 do waitdrq dup IDEBASE IDE_DATA + SECWORDS repinsw SECSIZ + loop then drop ; \ vandys \ Get block pointer, doing I/O if needed : iderdwt ( a blk rw -- err ) \ Convert block number to sector index swap BLKSECS * ideoff @ + swap \ Convert r/w argument to IDE read or write command; 0 means write, \ any other value means read if IDECMD_READ else IDECMD_WRITE then ideio 0 ; \ Disk partition parsing vandys 4 constant NFDISK 158 constant PT_FORTHOS : sec>parts ( a -- a' ) 446 + ; : part>type ( a -- a' ) 4 + ; : part>start ( a -- a' ) 2 cells + ; 16 constant part.size : partok? ( a -- ? ) 510 + @ $FFFF and $AA55 = ; : init-ideoff ( -- ) ideoff off align here dup 0 IDECMD_READ ideio ( a-sec0 ) dup partok? 0= if drop exit then sec>parts NFDISK 0 do dup part>type c@ PT_FORTHOS = if part>start @ ideoff ! unloop exit then part.size + loop drop ; \ Disk startup/initialization vandys also initialize definitions : boot-ide ( bool -- n | ) if ['] iderdwt 'rdwt ! init-ideoff else 1000 then ; only