; ATA/IDE Driver for Retro Native Forth
; -------------------------------------
; Works under Bochs, on a Dell Inspiron 3800, a Dell Precision 810, and a
; custom-build system
;
; As always, use of this is at your own risk!
; -------------------------------------
; This is not complete yet, the following limitations apply:
;  1) Supports CHS only
;  2) Only supports one drive
;  3) No autodetection of drive settings
;  4) Only supports single sector reads/writes
;  5) It's all manual.
;  6) If it kills your machine, don't ask me to fix it
;  7) DO NOT USE IT UNDER LINUX!
;  8) If you don't know what you're doing, don't mess with it!
; -------------------------------------

;#1 # This is an embedded script for adding ATA support to
;#1 # Retro Native Forth Release 6.
;#1 echo -e :: Installing ATA driver
;#1 cp ata source/drivers/native
;#1 echo -e :: Installation is complete

; ( Resolves the HEAD# into a combination drive+head )
; ( This is kind of inelegant, I'll fix it later )
$ata_select_head:
case 0, 0
case 1, 1
case 2, 2
case 3, 3
case 4, 4
case 5, 5
case 6, 6
case 7, 7
case 8, 8
case 9, 9
case 10, 10
case 11, 11
case 12, 12
case 13, 13
case 14, 14
case 15, 15
jmp .99
.0 mov eax, 10100000b
jmp short .99
.1 mov eax, 10101000b
jmp short .99
.2 mov eax, 10100100b
jmp short .99
.3 mov eax, 10101100b
jmp short .99
.4 mov eax, 10100010b
jmp short .99
.5 mov eax, 10101010b
jmp short .99
.6 mov eax, 10100110b
jmp short .99
.7 mov eax, 10101110b
jmp short .99
.8 mov eax, 10100001b
jmp short .99
.9 mov eax, 10101001b
jmp short .99
.10 mov eax, 10100101b
jmp short .99
.11 mov eax, 10101101b
jmp short .99
.12 mov eax, 10100011b
jmp short .99
.13 mov eax, 10101011b
jmp short .99
.14 mov eax, 10100111b
jmp short .99
.15 mov eax, 10101111b
.99 next

$ata_rw:
      swap
	mov     dx,1f6h         ;Drive and head port
	call	  $ata_select_head
	out     dx,al
      drop
push eax
push esi
	mov     dx,1f2h         ;Sector count port
	mov     al,1            ;Read one sector
	out     dx,al

pop esi
pop eax
	mov     dx,1f3h         ;Sector number port
	out     dx,al
	drop
	mov     dx,1f4h         ;Cylinder low port
	out     dx,al
	mov     dx,1f5h         ;Cylinder high port
	out     dx,al
      drop
next


; ( CYLINDER HEAD SECTOR -- )
code 'ata:read', ata_read
call ata_rw
push eax
	mov     dx,1f7h         ;Command port
	mov     al,20h          ;Read with retry.
	out     dx,al
.1
	in      al,dx
	test    al,8            ;This means the sector buffer requires
				;servicing.
	jz      .1     ;Don't continue until the sector buffer
				;is ready.

push edi
	mov     ecx,512/2        ;One sector /2
	mov     edi,ata_buffer
	mov     edx,1f0h         ;Data port - data comes in and out of here.
	rep     insw
pop edi
pop eax
next


; ( CYLINDER HEAD SECTOR -- )
code 'ata:write', ata_write
call ata_rw
push eax
	mov     dx,1f7h         ;Command port
	mov     al,30h          ;Read with retry.
	out     dx,al
.1
	in      al,dx
	test    al,8
	jz      .1     ;Don't continue until the sector buffer
				;is ready.
push esi
	mov     ecx,512/2        ;One sector /2
	mov     esi,ata_buffer
	mov     edx,1f0h         ;Data port - data comes in and out of here.
	rep     outsw
pop esi
pop eax
next


var 'ata:cyl', ata_cyl, 0
var 'ata:heads', ata_heads, 0
var 'ata:sect', ata_sect, 0

var 'ata:buffer', ata_buffer, 0
times 512 db 0
