# Floppy boot segment

.org 0# actually 7c00
start:	jmp start0
	nop 

	.ascii "cmcf 1.0"
	.word 512# bytes/sector
	.byte 1# sector/cluster
	.word 1# sector reserved
	.byte 2# FATs
	.word 16 * 14# root directory entries
	.word 80 * 2 * 18# sectors
	.byte 0x0F0# media
	.word 9# sectors/FAT
	.word 18# sectors/track
	.word 2# heads
	.int 0# hidden sectors
	.int 80 * 2 * 18# sectors again
	.byte 0# drive
#    db 0
#    db 29h     ; signature
#    dd 44444444h     ; serial
#    db 'COLOR FORTH' ; label
#    db '        '

command:.byte 0
	.byte 0# head, drive
cylinder:
	.byte 0
	.byte 0# head
	.byte 1# sector
	.byte 2# 512 bytes/sector
	.byte 18# sectors/track
	.byte 0x1b# gap
	.byte 0x0ff
.balign 4
nc: 	.int 9# Forth+Icons+blocks 24-161
gdt: 	.word 0x17
	.int gdt0
.balign 8
gdt0: 	.word 0, 0, 0, 0
	.word 0x0FFFF, 0, 0x9A00, 0x0CF# code
	.word 0x0FFFF, 0, 0x9200, 0x0CF# data

# Code is compiled in Protected 32-bit mode.
# Hence  org $-2  to fix 16-bit words
# and 4 hand-assembled instructions.
# and EAX and AX exchanged
# This code is in Real 16-bit mode
.code16
start0:	mov $0x7c00, %ax
	mov %ax, %es
	mov $512, %di
	mov $0x4F01, %ax
	mov $vesa, %cx
	int $0x10
	mov $0x4F02, %ax# Video mode
	mov $vesa, %bx# hp*vp rgb: 565
	int $0x10
	mov %es:42(%di), %bp
	shl $16, %ebp
	mov %es:40(%di), %bp
	cli 
	xor %eax, %eax# Move code to 0
	mov %eax, %ebx
	mov %cs, %bx
	mov %bx, %ds
	mov %ax, %es
	movl %eax, %edi
	movl %eax, %esi
	call loc# Where are we? IP+4*CS
loc:	pop %si
	sub $loc - start, %si
	mov $512 / 4, %cx
	rep
	movsl 
	jmp  $0, $relocate

relocate:# This code is executed from 0
	mov %ax, %ds
	lgdt gdt
	movb $1, %al
	movl %eax, %cr0
	jmp  $8, $protected
.code32
protected:# Now in Protected 32-bit mode
	movb $0x10, %al
	mov %eax, %ds
	mov %eax, %es
	mov %eax, %ss
	movl $gods, %esp # setup return stack
	xorl %ecx, %ecx

a20:	movb $0x0d1, %al
	outb %al, $0x64
0:	inb $0x64, %al
	andb $2, %al
	jnz 0b
	movb $0x4b, %al
	outb %al, $0x60

cold:	movl $godd, %esi
	call spin
	call dma
	xorl %edi, %edi# Cylinder 0 on top of Address 0
	call read
	incb cylinder
	movb nc, %cl
0:	pushl %ecx
	call read
	popl %ecx
	loop 0b
	call stop
start2:	jmp start1

stop:	movb $0x0c, %cl# Motor off
onoff:	DUP_ 
	movb %cl, %al
	movw $0x3f2, %dx
	out %al, %dx
	outb %al, $0x0e1
	DROP 
	ret

.equ ms, 1000 * 1000 / 4 
spin:	movb $0x1c, %cl # tll
	call onoff
	movl $400 * ms, %ecx # (c4a)
0:	loop 0b
#	movb %cl, cylinder # calibrate       ; (c4a)
	movb $7, %al # recalibrate command
	movb $2, %cl
	jmp cmdi

ready:	movl $0x3F4, %edx
0:	in %dx, %al
	OUTb %al, $0x0E1 # tll     ; (c4a)
	shlb $1, %al
	jnc 0b
	leal 1(%edx), %edx
	ret 

cmd:	pushl %esi
	lea command, %esi# (c4a)
	movb %al, (%esi)
0:	call ready
	jns cmd0
	in %dx, %al # discard input
	OUTb %al, $0x0E1# tll ; (c4a)
	jmp 0b
cmd0:	lodsb
	out %al, %dx # write command
	pushl %ecx# (c4a)
	movl $0x001e, %ecx# (c4a)
cmd1:	outb %al, $0x0e1# (c4a)
	loop cmd1# (c4a)
	popl %ecx# (c4a)
	loop 0b
	popl %esi
	ret 

sense_:	movb $8, %al # sense interrupt status command
	movb $1, %cl
	call cmd
	call ready
	in %dx, %al
	OUTb %al, $0x0E1# tll         ; (c4a)
	cmpb $0x80, %al
	ret 

seek:	outb %al, $0x0b
0:	call sense_
	jnz 0b
	movb $0x0F, %al
	movb $3, %cl
cmdi:	call cmd
0:	call sense_
	jz 0b
	ret 

dma:	movw $0x2a1, command + 1# 2 6 16 ms (e 2)
	movb $3, %al# timing
	movb $3, %cl
	call cmd
	movw $0, command + 1
	movl $buffer * 4, %eax
	outb %al, $4
	movb %ah, %al
	outb %al, $4
	shrl $16, %eax
	outb %al, $0x81
	movl $512 * 18 * 2 - 1, %eax# DMA 2
	outb %al, $5
	movb %ah, %al
	outb %al, $5
	movb $0x0b, %al
	outb %al, $0x0f
	ret 

transfer:
	movb $9, %cl
	call cmd
	incb cylinder
0:	call ready
	jns 0b
	ret 

read:	movb $0x16, %al# Read DMA 2
	call seek
	movb $0x0e6, %al
	call transfer
	pushl %esi
	movl $buffer * 4, %esi
	movl $512 * 18 * 2 / 4, %ecx
	rep
	movsl 
	popl %esi
	ret
		
.org 0x1FE# End boot sector
	.byte 0x55, 0x0AA

write:	movl $buffer * 4, %edi
	movl $512 * 18 * 2 / 4, %ecx
	rep
	movsl 
	movb $0x1a, %al# Write DMA 2
	call seek
	movb $0x0c5, %al
	jmp transfer

flop:	movb %al, cylinder# c-cx
	DUP_ 
	movw $0x3f2, %dx
	in %dx, %al
	outb %al, $0x0e1
	testb $0x10, %al
	jnz 0f
	jmp spin
0:	ret

readf:	call flop# ac-ac
	pushl %edi
	movl 4(%esi), %edi
	shll $2, %edi
	call read
	popl %edi
readf1:	DROP 
	incl %eax
	addl $0x1200, (%esi)
	ret 

writef:	call flop# ac-ac
	pushl %esi
	movl 4(%esi), %esi
	shll $2, %esi
	call write
	popl %esi
	jmp readf1