data.img now has more than one sector of data

This commit is contained in:
Kartik K. Agaram 2021-04-16 20:12:10 -07:00
parent cec0d9553b
commit 21a6f5539b
5 changed files with 88 additions and 42 deletions

4
400.mu
View File

@ -9,8 +9,8 @@ sig draw-cursor-on-real-screen g: grapheme
sig read-key kbd: (addr keyboard) -> _/eax: byte
# disk
sig load-sector disk: (addr disk), lba: int, out: (addr stream byte)
sig store-sector disk: (addr disk), lba: int, out: (addr stream byte)
sig load-sectors disk: (addr disk), lba: int, n: int, out: (addr stream byte)
sig store-sectors disk: (addr disk), lba: int, n: int, out: (addr stream byte)
# mouse
sig read-mouse-event -> _/eax: int, _/ecx: int

111
boot.subx
View File

@ -907,7 +907,7 @@ Primary-bus-secondary-drive:
== code
load-sector: # disk: (addr disk), lba: int, out: (addr stream byte)
load-sectors: # disk: (addr disk), lba: int, n: int, out: (addr stream byte)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
@ -918,35 +918,47 @@ load-sector: # disk: (addr disk), lba: int, out: (addr stream byte)
# check for drive
(drive-exists? *(ebp+8)) # => eax
3d/compare-eax-and 0/imm32/false
0f 84/jump-if-= $load-sector:end/disp32
0f 84/jump-if-= $load-sectors:end/disp32
# kick off read
(ata-drive-select *(ebp+8) *(ebp+0xc))
(clear-ata-error *(ebp+8))
(ata-sector-count *(ebp+8) 1)
(ata-sector-count *(ebp+8) *(ebp+0x10))
(ata-lba *(ebp+8) *(ebp+0xc))
(ata-command *(ebp+8) 0x20) # read sectors with retries
# poll for results
(while-ata-busy *(ebp+8))
(until-ata-data-available *(ebp+8))
# var data-port/edx = disk->data-port
8b/-> *(ebp+8) 0/r32/eax
8b/-> *(eax+0x24) 2/r32/edx
# emit results
31/xor %eax 0/r32/eax
b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector
# for each sector
{
81 7/subop/compare %ecx 0/imm32
74/jump-if-= break/disp8
66 ed/read-port-dx-into-ax
# write 2 bytes to stream one at a time
(append-byte *(ebp+0x10) %eax)
49/decrement-ecx
c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
(append-byte *(ebp+0x10) %eax)
49/decrement-ecx
eb/jump loop/disp8
# poll for results
#? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "waiting for sector.." 7 0)
(while-ata-busy *(ebp+8))
(until-ata-data-available *(ebp+8))
#? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "reading\n" 7 0)
# var data-port/edx = disk->data-port
8b/-> *(ebp+8) 0/r32/eax
8b/-> *(eax+0x24) 2/r32/edx
# emit results
31/xor %eax 0/r32/eax
b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector
{
81 7/subop/compare %ecx 0/imm32
74/jump-if-= break/disp8
66 ed/read-port-dx-into-ax
# write 2 bytes to stream one at a time
(append-byte *(ebp+0x14) %eax)
49/decrement-ecx
c1/shift 5/subop/right-padding-zeroes %eax 8/imm8
(append-byte *(ebp+0x14) %eax)
49/decrement-ecx
eb/jump loop/disp8
}
ff 1/subop/decrement *(ebp+0x10)
#? (draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x10) 0xc 0)
81 7/subop/compare *(ebp+0x10) 0/imm32
7e/jump-if-<= break/disp8
(wait-400ns *(ebp+8))
#? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "next sector\n" 7 0)
e9/jump loop/disp32
}
$load-sector:end:
$load-sectors:end:
# . restore registers
5a/pop-to-edx
59/pop-to-ecx
@ -956,7 +968,7 @@ $load-sector:end:
5d/pop-to-ebp
c3/return
store-sector: # disk: (addr disk), lba: int, in: (addr stream byte)
store-sectors: # disk: (addr disk), lba: int, n: int, in: (addr stream byte)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
@ -968,11 +980,11 @@ store-sector: # disk: (addr disk), lba: int, in: (addr stream byte)
# check for drive
(drive-exists? *(ebp+8)) # => eax
3d/compare-eax-and 0/imm32/false
0f 84/jump-if-= $store-sector:end/disp32
0f 84/jump-if-= $store-sectors:end/disp32
# kick off write
(ata-drive-select *(ebp+8) *(ebp+0xc))
(clear-ata-error *(ebp+8))
(ata-sector-count *(ebp+8) 1)
(ata-sector-count *(ebp+8) *(ebp+0x10))
(ata-lba *(ebp+8) *(ebp+0xc))
(ata-command *(ebp+8) 0x30) # write sectors with retries
# wait
@ -986,22 +998,22 @@ store-sector: # disk: (addr disk), lba: int, in: (addr stream byte)
# . var first-byte/ebx: byte
# . when it's more than 0xff, we're at an even-numbered byte
bb/copy-to-ebx 0xffff/imm32
$store-sector:loop:
$store-sectors:loop:
{
81 7/subop/compare %ecx 0/imm32
74/jump-if-= break/disp8
# this loop is slow, but the ATA spec also requires a small delay
(stream-empty? *(ebp+0x10)) # => eax
(stream-empty? *(ebp+0x14)) # => eax
3d/compare-eax-and 0/imm32/false
75/jump-if-!= break/disp8
# read byte from stream
(read-byte *(ebp+0x10)) # => eax
(read-byte *(ebp+0x14)) # => eax
# if we're at an odd-numbered byte, save it to first-byte
81 7/subop/compare %ebx 0xff/imm32
{
7e/jump-if-<= break/disp8
89/<- %ebx 0/r32/eax
eb/jump $store-sector:loop/disp8
eb/jump $store-sectors:loop/disp8
}
# otherwise OR it with first-byte and write it out
c1/shift 4/subop/left %eax 8/imm8
@ -1032,7 +1044,7 @@ $store-sector:loop:
49/decrement-ecx
eb/jump loop/disp8
}
$store-sector:end:
$store-sectors:end:
# . restore registers
5b/pop-to-ebx
5a/pop-to-edx
@ -1059,7 +1071,7 @@ drive-exists?: # disk: (addr disk) -> _/eax: boolean
3d/compare-eax-and 0xff/imm32
# if eax is 0xff, primary bus has no drives
b8/copy-to-eax 0/imm32/false
74/jump-if-= $drive-exists?:end/disp8
0f 84/jump-if-= $drive-exists?:end/disp32
}
# identify
(ata-drive-select *(ebp+8) 0)
@ -1266,7 +1278,7 @@ until-ata-data-available: # disk: (addr disk)
a8/test-bits-in-al 8/imm8/drq # set zf if bit 3 is not set
74/jump-if-zf-set-and-bit-3-not-set loop/disp8
}
$while-ata-busy:end:
$until-ata-data-available:end:
# . restore registers
5a/pop-to-edx
58/pop-to-eax
@ -1277,6 +1289,39 @@ until-ata-ready-for-data:
(until-ata-data-available)
c3/return
# https://wiki.osdev.org/index.php?title=ATA_PIO_Mode&oldid=25664#400ns_delays
wait-400ns: # disk: (addr disk)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
52/push-edx
#? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "waiting 400ns\n" 7 0)
# var status-port/edx = disk->status-port
8b/-> *(ebp+8) 0/r32/eax
8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset
#
b9/copy-to-ecx 0x10/imm32
{
81 7/subop/compare %ecx 0/imm32
74/jump-if-= break/disp8
#? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "." 7 0)
ec/read-port-dx-into-al
49/decrement-ecx
eb/jump loop/disp8
}
$wait-400ns:end:
# . restore registers
5a/pop-to-edx
59/pop-to-ecx
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
# }}}
## Controlling a PS/2 mouse

4
ex9.mu
View File

@ -18,14 +18,14 @@
fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
var text-storage: (stream byte 0x200)
var text/esi: (addr stream byte) <- address text-storage
load-sector data-disk, 0/lba, text
load-sectors data-disk, 0/lba, 1/num-sectors, text
var word-count/eax: int <- word-count text
var result-storage: (stream byte 0x10)
var result/edi: (addr stream byte) <- address result-storage
write-int32-decimal result, word-count
store-sector data-disk, 0/lba, result
store-sectors data-disk, 0/lba, 1/num-sectors, result
}
fn word-count in: (addr stream byte) -> _/eax: int {

View File

@ -394,7 +394,7 @@ fn push-bindings _params-ah: (addr handle cell), _args-ah: (addr handle cell), o
fn lookup-symbol sym: (addr cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
# trace sym
{
var stream-storage: (stream byte 0x100)
var stream-storage: (stream byte 0x200) # pessimistically sized just for the large alist loaded from disk in `main`
var stream/ecx: (addr stream byte) <- address stream-storage
write stream, "look up "
var sym2/eax: (addr cell) <- copy sym

View File

@ -30,9 +30,10 @@ fn load-state data-disk: (addr disk), _sandbox: (addr sandbox), globals: (addr g
var _data/eax: (addr gap-buffer) <- lookup *data-ah
var data/esi: (addr gap-buffer) <- copy _data
# data-disk -> stream
var s-storage: (stream byte 0x200)
var s-storage: (stream byte 0x400) # space for 2/sectors
var s/ebx: (addr stream byte) <- address s-storage
load-sector data-disk, 0/lba, s
load-sectors data-disk, 0/lba, 2/sectors, s
#? draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg, 0/bg
# stream -> gap-buffer
load-gap-buffer-from-stream data, s
clear-stream s
@ -93,11 +94,11 @@ fn store-state data-disk: (addr disk), sandbox: (addr sandbox), globals: (addr g
break-if-!=
return
}
var stream-storage: (stream byte 0x200)
var stream-storage: (stream byte 0x400) # space enough for 2/sectors
var stream/edi: (addr stream byte) <- address stream-storage
write stream, "(\n"
write-globals stream, globals
write-sandbox stream, sandbox
write stream, ")\n"
store-sector data-disk, 0/lba, stream
store-sectors data-disk, 0/lba, 2/sectors, stream
}