diff options
-rw-r--r-- | 400.mu | 4 | ||||
-rw-r--r-- | boot.subx | 111 | ||||
-rw-r--r-- | ex9.mu | 4 | ||||
-rw-r--r-- | shell/evaluate.mu | 2 | ||||
-rw-r--r-- | shell/main.mu | 9 |
5 files changed, 88 insertions, 42 deletions
diff --git a/400.mu b/400.mu index 7bef992a..a31edbb6 100644 --- a/400.mu +++ b/400.mu @@ -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 diff --git a/boot.subx b/boot.subx index e8c86682..78d553cc 100644 --- a/boot.subx +++ b/boot.subx @@ -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 diff --git a/ex9.mu b/ex9.mu index dc5dffd0..1b2cae5e 100644 --- a/ex9.mu +++ b/ex9.mu @@ -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 { diff --git a/shell/evaluate.mu b/shell/evaluate.mu index ebdbe486..36662d42 100644 --- a/shell/evaluate.mu +++ b/shell/evaluate.mu @@ -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 diff --git a/shell/main.mu b/shell/main.mu index 8abc6ed1..d8fa0963 100644 --- a/shell/main.mu +++ b/shell/main.mu @@ -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 } |