\ 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
: waitdrq Wait for IDE DRQ to indicate "ready", pause'ing in between
: ideio Actual operation of IDE controller
Wait for drive ready--this can happen unexepectedly
due to power management spinning down the drive.
I/O size--always a full block
Program block #, using LBA addressing
Send command
For write command, send data as controller asks
For read command, pull data as data available
Drop buffer address... all done!
# of FDISK entries in sector 0 of a disk
Partition type for ForthOS storage
Words to access the needed fields in a partition; array of partitions
Partition type
starting sector #
overall size of one partition entry
: partok? Tell if magic # is OK for partition sector
: init-ideoff Read fdisk label, find our partition and set ideoff to
make this the start of our blocks. If can't find partition, clear
ideoff to make "block" see the whole raw disk.
: boot-ide Hook to system init to set up IDE driver
Actual initialization call
Connect our services to the rdwt vector, also find beginning
of our partition
Return index for order in which we'd like to be run