about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--400.mu4
-rw-r--r--boot.subx111
-rw-r--r--ex9.mu4
-rw-r--r--shell/evaluate.mu2
-rw-r--r--shell/main.mu9
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
 }