/kernelide.txt
\                                                                    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