about summary refs log tree commit diff stats
path: root/boot.subx
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-03-23 00:32:49 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-03-23 00:32:49 -0700
commit62a244211024a8367332541c571621883c05bcce (patch)
tree6bd560d3d44ef21b9c4eee5de7b644875652793b /boot.subx
parentbc79a190ec8366215d67110db08a25c7f8c8bf84 (diff)
downloadmu-62a244211024a8367332541c571621883c05bcce.tar.gz
writes to disk now working
Tested by inserting a call into the shell, but we can't leave it in because
every test ends up clobbering the disk. So it's now time to think about
a testable interface for the disk.
Diffstat (limited to 'boot.subx')
-rw-r--r--boot.subx89
1 files changed, 89 insertions, 0 deletions
diff --git a/boot.subx b/boot.subx
index 200f201a..028862ad 100644
--- a/boot.subx
+++ b/boot.subx
@@ -971,6 +971,91 @@ $load-first-sector-from-primary-bus-secondary-drive:end:
   5d/pop-to-ebp
   c3/return
 
+store-first-sector-to-primary-bus-secondary-drive:  # in: (addr stream byte)
+  # . prologue
+  55/push-ebp
+  89/<- %ebp 4/r32/esp
+  # . save registers
+  50/push-eax
+  51/push-ecx
+  52/push-edx
+  53/push-ebx
+  # check for drive
+  (secondary-drive-exists?)  # => eax
+  3d/compare-eax-and 0/imm32/false
+  0f 84/jump-if-= $store-first-sector-to-primary-bus-secondary-drive:end/disp32
+  # kick off write
+  (ata-drive-select 0xf0)  # primary bus, secondary drive; 4 LSBs contain 4 upper bits of LBA (here 0)
+  (clear-ata-error)
+  (ata-sector-count 1)
+  (ata-lba 0 0 0)  # lower 24 bits of LBA, all 0
+  (ata-command 0x30)  # write sectors with retries
+  # wait
+  (while-ata-busy)
+  (until-ata-ready-for-data)
+  # send data
+  ba/copy-to-edx 0x1f0/imm32
+  b9/copy-to-ecx 0x200/imm32  # 512 bytes per sector
+  # 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-first-sector-to-primary-bus-secondary-drive: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+8))  # => eax
+    3d/compare-eax-and 0/imm32/false
+    75/jump-if-!= break/disp8
+    # read byte from stream
+    (read-byte *(ebp+8))  # => 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-first-sector-to-primary-bus-secondary-drive:loop/disp8
+    }
+    # otherwise OR it with first-byte and write it out
+    c1/shift 4/subop/left %eax 8/imm8
+    09/or %eax 3/r32/ebx
+    66 ef/write-ax-into-port-dx
+    49/decrement-ecx
+    49/decrement-ecx
+    # reset first-byte
+    bb/copy-to-ebx 0xffff/imm32
+    eb/jump loop/disp8
+  }
+  # write out first-byte if necessary
+  81 7/subop/compare %ebx 0xff/imm32
+  {
+    7f/jump-if-> break/disp8
+    89/<- %eax 3/r32/ebx
+    66 ef/write-ax-into-port-dx
+    49/decrement-ecx
+    49/decrement-ecx
+  }
+  # pad zeroes
+  31/xor %eax 0/r32/eax
+  {
+    81 7/subop/compare %ecx 0/imm32
+    74/jump-if-= break/disp8
+    66 ef/write-ax-into-port-dx
+    49/decrement-ecx
+    49/decrement-ecx
+    eb/jump loop/disp8
+  }
+$store-first-sector-to-primary-bus-secondary-drive:end:
+  # . restore registers
+  5b/pop-to-ebx
+  5a/pop-to-edx
+  59/pop-to-ecx
+  58/pop-to-eax
+  # . epilogue
+  89/<- %esp 5/r32/ebp
+  5d/pop-to-ebp
+  c3/return
+
 secondary-drive-exists?:  # -> _/eax: boolean
   # . prologue
   55/push-ebp
@@ -1205,4 +1290,8 @@ $while-ata-busy:end:
   # . epilogue
   c3/return
 
+until-ata-ready-for-data:
+  (until-ata-data-available)
+  c3/return
+
 # vim:ft=subx