| iris.hhp |
| 591 | 591 | #ifndef __KERNEL__ |
| 592 | 592 | #if 1 |
| 593 | 593 | // Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. |
| 594 | | #define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0) |
| 594 | #define kdebug_char(_c) do { unsigned _d = (_c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(_d) : "a0", "a1", "memory"); } while (0) |
| 595 | 595 | #else |
| 596 | | #define kdebug_char(c) do {} while (0) |
| 596 | #define kdebug_char(_c) do {} while (0) |
| 597 | 597 | #endif |
| 598 | 598 | #define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0) |
| 599 | 599 | #define __stringify2(x) #x |
| ... | ... | |
| 602 | 602 | |
| 603 | 603 | static void kdebug_num (unsigned n, unsigned digits = 8): |
| 604 | 604 | unsigned i |
| 605 | | const char *encode = "0123456789abcdef" |
| 605 | char const *encode = "0123456789abcdef" |
| 606 | 606 | for i = 0; i < digits; ++i: |
| 607 | 607 | kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf]) |
| 608 | 608 | |
| ... | ... | |
| 620 | 620 | while true: |
| 621 | 621 | wait () |
| 622 | 622 | |
| 623 | inline void debug_num (unsigned num, unsigned base): |
| 624 | char const *encode = "0123456789abcdef" |
| 625 | unsigned digits = 1 |
| 626 | unsigned power = base |
| 627 | while power <= num: |
| 628 | power *= base |
| 629 | ++digits |
| 630 | for unsigned i = 0; i < digits; ++i: |
| 631 | power /= base |
| 632 | unsigned d = num / power |
| 633 | kdebug_char (encode[d]) |
| 634 | num -= d * power |
| 635 | |
| 636 | inline void debug (const char *f, ...): |
| 637 | unsigned *last = (unsigned *)&f |
| 638 | while *f: |
| 639 | if *f == '%': |
| 640 | ++f |
| 641 | switch *f: |
| 642 | case '%': |
| 643 | kdebug_char ('%') |
| 644 | break |
| 645 | case 'd': |
| 646 | ++last |
| 647 | debug_num (*last, 10) |
| 648 | break |
| 649 | case 'x': |
| 650 | ++last |
| 651 | debug_num (*last, 0x10) |
| 652 | break |
| 653 | case 's': |
| 654 | ++last |
| 655 | kdebug ((char *)*last) |
| 656 | break |
| 657 | default: |
| 658 | panic (*f, "invalid character in dbg format string") |
| 659 | else: |
| 660 | kdebug_char (*f) |
| 661 | ++f |
| 662 | |
| 623 | 663 | #endif |
| 624 | 664 | #endif |
| mips/nanonote/Makefile.arch |
| 15 | 15 | # You should have received a copy of the GNU General Public License |
| 16 | 16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | 17 | |
| 18 | start_load = 0xa0600000 |
| 18 | 19 | load = 0x80000000 |
| 19 | | #UDC_BOOT = set |
| 20 | #UDC_BOOT = comment this out for nand boot |
| 20 | 21 | |
| 21 | 22 | ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL |
| 22 | 23 | CROSS = mipsel-linux-gnu- |
| 23 | 24 | OBJDUMP = $(CROSS)objdump |
| 24 | 25 | junk = mdebug.abi32 reginfo comment pdr |
| 25 | 26 | OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk)) |
| 26 | | LDFLAGS = --omagic -Ttext $(load) |
| 27 | iris.elf: LDFLAGS = --omagic -Ttext $(load) |
| 28 | mips/start.elf: LDFLAGS = --omagic -Ttext $(start_load) |
| 27 | 29 | |
| 28 | 30 | arch_iris_sources = mips/interrupts.cc mips/arch.cc |
| 29 | 31 | boot_sources = mips/init.cc mips/nanonote/board.cc |
| ... | ... | |
| 44 | 46 | threadlist = mips/nanonote/threadlist-sd |
| 45 | 47 | ARCH_CXXFLAGS = -DNUM_THREADS=4 |
| 46 | 48 | all: iris-sd.tar |
| 47 | | iris-sd.tar: $(addprefix fs/,$(addsuffix .elf,$(programs))) iris.raw fs/init.config |
| 48 | | mkimage -A mips -T kernel -a $(load) -e a$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') -n Iris -d iris.raw fs/uimage | sed -e 's/:/;/g' |
| 49 | iris-sd.tar: $(addprefix fs/,$(addsuffix .elf,$(programs))) mips/start.raw.gz fs/init.config |
| 50 | mkimage -A mips -T kernel -a $(start_load) -e a$(shell /bin/sh -c '$(OBJDUMP) -t mips/start.elf | grep __start$$ | cut -b2-8') -n Iris -d mips/start.raw.gz fs/uimage | sed -e 's/:/;/g' |
| 49 | 51 | cd fs && tar cvf ../$@ uimage init.config $(addsuffix .elf,$(programs)) --dereference |
| 50 | 52 | endif |
| 51 | 53 | |
| 52 | | test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config |
| 53 | | echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050 |
| 54 | mips/start.o:mips/start.S Makefile Makefile.arch iris.raw |
| 55 | $(CC) $(CPPFLAGS) -DSTART=0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') -c $< -o $@ |
| 56 | |
| 57 | test: mips/start.raw mips/start.elf mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config |
| 58 | echo "reboot $(start_load) 0xa$(shell /bin/sh -c '$(OBJDUMP) -t mips/start.elf | grep __start$$ | cut -b2-8') $<" | nc localhost 5050 |
| 54 | 59 | |
| 55 | 60 | mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac devices.hh |
| 56 | 61 | $(MAKE) -C mips/nanonote/server |
| ... | ... | |
| 63 | 68 | %.raw: %.elf |
| 64 | 69 | $(OBJCOPY) -S $(OBJCOPYFLAGS) -Obinary $< $@ |
| 65 | 70 | |
| 71 | %.raw.gz: %.raw |
| 72 | gzip < $< > $@ |
| 73 | |
| 66 | 74 | nanonote-boot: mips/nanonote/nanonote-boot.cc mips/nanonote/sdram-setup.raw |
| 67 | 75 | g++ `pkg-config --cflags --libs shevek` $< -o $@ -D'STAGE1="$<"' -lusb |
| 68 | 76 | |
| ... | ... | |
| 84 | 92 | $< > $@ |
| 85 | 93 | |
| 86 | 94 | %.o:%.S Makefile Makefile.arch mips/arch.hh |
| 87 | | $(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@ |
| 95 | $(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x1000 -c $< -o $@ |
| 88 | 96 | |
| 89 | 97 | # entry.o must be the first file. threadlist.o must be the first of the init objects (which can be freed after loading). |
| 90 | 98 | iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) $(threadlist).o mips/boot.o $(subst .cc,.o,$(boot_sources)) |
| 91 | 99 | $(LD) $(LDFLAGS) $^ -o $@ |
| 92 | 100 | |
| 101 | mips/start.elf: mips/start.o |
| 102 | $(LD) $(LDFLAGS) $^ -o $@ |
| 103 | |
| 93 | 104 | server: |
| 94 | 105 | while mips/nanonote/server/usb-server ; do : ; done |
| 95 | 106 | |
| ... | ... | |
| 100 | 111 | x-terminal-emulator -e make debug & |
| 101 | 112 | x-terminal-emulator -e make servers & |
| 102 | 113 | |
| 103 | | ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o source/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw |
| 114 | ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o source/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw mips/start.elf mips/start.raw |
| 104 | 115 | |
| 105 | 116 | .PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh |
| 106 | 117 | .PHONY: test all monitor server servers setup |
| mips/nanonote/server/usb-server.ccp |
| 40 | 40 | static int const run_vendor = 0xfffe |
| 41 | 41 | static int const run_product = 0x0002 |
| 42 | 42 | static unsigned const timeout = 10000 |
| 43 | | void boot (unsigned entry) |
| 43 | void boot (std::string const &filename, unsigned load, unsigned entry) |
| 44 | 44 | data (std::string const &port): |
| 45 | 45 | handle = NULL |
| 46 | 46 | server = shevek::server <client, data *>::create () |
| ... | ... | |
| 49 | 49 | |
| 50 | 50 | private: |
| 51 | 51 | static unsigned const STAGE1_LOAD = 0x80002000 |
| 52 | | static unsigned const STAGE2_LOAD = 0x80000000 |
| 53 | 52 | static unsigned const STAGE1_ENTRY = STAGE1_LOAD |
| 54 | 53 | enum requests: |
| 55 | 54 | VR_GET_CPU_INFO = 0 |
| ... | ... | |
| 212 | 211 | keep = is_stdio |
| 213 | 212 | void read (std::string const &line): |
| 214 | 213 | shevek::istring l (line) |
| 215 | | unsigned entry |
| 216 | | if l ("reboot %x%", entry): |
| 217 | | get_server ()->data ()->boot (entry) |
| 214 | unsigned load, entry |
| 215 | std::string filename |
| 216 | if l ("reboot %x %x %r%", load, entry, filename): |
| 217 | get_server ()->data ()->boot (filename, load, entry) |
| 218 | 218 | else if l ("shutdown%"): |
| 219 | 219 | std::cerr << "shutting down\n" |
| 220 | 220 | shevek::end_loop () |
| ... | ... | |
| 266 | 266 | sleep (1) |
| 267 | 267 | std::cerr << shevek::ostring ("giving up finding device %04x:%04x\n", vendor, product) |
| 268 | 268 | |
| 269 | | void data::boot (unsigned entry): |
| 270 | | std::cerr << "booting " << shevek::ostring ("%x", entry) << "\n" |
| 269 | void data::boot (std::string const &filename, unsigned load, unsigned entry): |
| 270 | std::cerr << "booting " << shevek::ostring ("%s from %x@%x", Glib::ustring (filename), load, entry) << "\n" |
| 271 | 271 | if handle: |
| 272 | 272 | usb_release_interface (handle, 0) |
| 273 | 273 | usb_close (handle) |
| ... | ... | |
| 294 | 294 | std::ostringstream stage2 |
| 295 | 295 | usb_release_interface (handle, 0) |
| 296 | 296 | file.close () |
| 297 | | file.open (STAGE2_FILE) |
| 297 | file.open (filename.c_str ()) |
| 298 | 298 | stage2 << file.rdbuf () |
| 299 | | std::cerr << "sending Iris\n" |
| 300 | | send_file (STAGE2_LOAD, stage2.str ().size (), stage2.str ().data ()) |
| 299 | std::cerr << shevek::ostring ("sending Iris (size 0x%x)\n", stage2.str ().size ()) |
| 300 | send_file (load, stage2.str ().size (), stage2.str ().data ()) |
| 301 | 301 | std::cerr << "flushing caches\n" |
| 302 | 302 | request (VR_FLUSH_CACHES) |
| 303 | 303 | std::cerr << "running Iris\n" |
| mips/start.S |
| 1 | // Iris: micro-kernel for a capability-based operating system. |
| 2 | // mips/start.S: kernel starter at high address. |
| 3 | // Copyright 2009 Bas Wijnen <wijnen@debian.org> |
| 4 | // |
| 5 | // This program is free software: you can redistribute it and/or modify |
| 6 | // it under the terms of the GNU General Public License as published by |
| 7 | // the Free Software Foundation, either version 3 of the License, or |
| 8 | // (at your option) any later version. |
| 9 | // |
| 10 | // This program is distributed in the hope that it will be useful, |
| 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | // GNU General Public License for more details. |
| 14 | // |
| 15 | // You should have received a copy of the GNU General Public License |
| 16 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | |
| 18 | .globl __start |
| 19 | .set noreorder |
| 20 | |
| 21 | __start: |
| 22 | bal 1f |
| 23 | // For some reason the disassembler considers everything |
| 24 | // after __start non-code until the next label. So I add a label. |
| 25 | start_hack_for_disassembler: |
| 26 | nop |
| 27 | .word _gp |
| 28 | 1: lw $gp, 0($ra) |
| 29 | |
| 30 | li $a0, 0xa0000000 |
| 31 | la $a1, image |
| 32 | la $a2, image_end |
| 33 | |
| 34 | 1: lw $a3, 0($a1) |
| 35 | sw $a3, 0($a0) |
| 36 | addiu $a1, 4 |
| 37 | bne $a1, $a2, 1b |
| 38 | addiu $a0, 4 |
| 39 | |
| 40 | li $t9, START |
| 41 | jr $t9 |
| 42 | nop |
| 43 | |
| 44 | image: |
| 45 | .incbin "iris.raw" |
| 46 | image_end: |
| source/nand.ccp |
| 80 | 80 | static void unbusy (): |
| 81 | 81 | while !(gpio_get_port (2) & (1 << 30)): |
| 82 | 82 | Iris::schedule () |
| 83 | Iris::schedule () |
| 84 | |
| 85 | static void addr (unsigned d): |
| 86 | unbusy () |
| 87 | *address = d |
| 88 | unbusy () |
| 89 | |
| 90 | static void cmd (unsigned d): |
| 91 | unbusy () |
| 92 | *command = d |
| 93 | unbusy () |
| 94 | |
| 95 | static void wdata (unsigned d): |
| 96 | unbusy () |
| 97 | *data = d |
| 98 | unbusy () |
| 99 | |
| 100 | static unsigned rdata (): |
| 101 | unbusy () |
| 102 | unsigned ret = *data |
| 103 | unbusy () |
| 104 | return ret |
| 83 | 105 | |
| 84 | 106 | static void reset (): |
| 85 | 107 | Iris::Page data_page = Iris::my_memory.create_page () |
| ... | ... | |
| 104 | 126 | EMC_NFCSR = EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1 |
| 105 | 127 | |
| 106 | 128 | // Reset nand. |
| 107 | | *command = CMD_RESET |
| 108 | | unbusy () |
| 129 | cmd (CMD_RESET) |
| 109 | 130 | |
| 110 | | *command = CMD_READID |
| 111 | | *address = 0 |
| 112 | | unsigned d = *data |
| 131 | cmd (CMD_READID) |
| 132 | addr (0) |
| 133 | unsigned d = rdata () |
| 113 | 134 | //unsigned maker = d |
| 114 | | d = *data |
| 135 | d = rdata () |
| 115 | 136 | //unsigned device = d |
| 116 | | d = *data |
| 137 | d = rdata () |
| 117 | 138 | //unsigned internal_chip_number = 1 << (d & 0x3) |
| 118 | 139 | //unsigned cell_type = 2 << ((d >> 2) & 0x3) |
| 119 | 140 | //unsigned simultaneously_programmed_pages = 1 << ((d >> 4) & 0x3) |
| 120 | 141 | //bool can_interleave_program_between_chips = d & 0x40 |
| 121 | 142 | //bool can_cache_program = d & 0x80 |
| 122 | | d = *data |
| 143 | d = rdata () |
| 123 | 144 | page_bits = 10 + (d & 3) |
| 124 | | kdebug ("page bits: ") |
| 125 | | kdebug_num (page_bits) |
| 126 | | kdebug ("\n") |
| 145 | Iris::debug ("page bits: %d\n", page_bits) |
| 127 | 146 | redundant_bits = (d & 4 ? 4 : 3) |
| 128 | | block_bits = 64 + ((d >> 4) & 3) |
| 147 | Iris::debug ("redundant bits: %d\n", redundant_bits) |
| 148 | block_bits = 16 + ((d >> 4) & 3) |
| 149 | Iris::debug ("block bits: %d\n", block_bits) |
| 129 | 150 | word_size = (d & 0x40 ? 16 : 8) |
| 151 | Iris::debug ("word size: %d\n", word_size) |
| 130 | 152 | //unsigned serial_access_minimum = (d & 0x80 ? 25 : 50) |
| 131 | | d = *data |
| 153 | d = rdata () |
| 132 | 154 | //unsigned num_planes = 1 << ((d >> 2) & 3) |
| 133 | 155 | //unsigned plane_bits = 26 + ((d >> 4) & 7) |
| 134 | 156 | |
| 135 | 157 | static void read (unsigned a, char *buffer): |
| 136 | 158 | unsigned column = a & ((1 << page_bits) - 1) |
| 137 | 159 | unsigned row = a >> page_bits |
| 138 | | kdebug ("reading: ") |
| 139 | | kdebug_num (a) |
| 140 | | kdebug ("/") |
| 141 | | kdebug_num (row) |
| 142 | | kdebug ("/") |
| 143 | | kdebug_num (column) |
| 144 | | kdebug (": ") |
| 145 | | *command = CMD_READ0 |
| 146 | | *address = column |
| 147 | | *address = column >> 8 |
| 148 | | *address = row |
| 149 | | *address = row >> 8 |
| 150 | | *address = row >> 16 |
| 151 | | *command = CMD_READSTART |
| 160 | //Iris::debug ("reading: %x/%x/%x: ", a, row, column) |
| 161 | cmd (CMD_READ0) |
| 162 | addr (column) |
| 163 | addr (column >> 8) |
| 164 | addr (row) |
| 165 | addr (row >> 8) |
| 166 | addr (row >> 16) |
| 167 | cmd (CMD_READSTART) |
| 152 | 168 | EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_ERST |
| 153 | | // Wait for nand to be ready. |
| 154 | | unbusy () |
| 155 | 169 | for unsigned t = 0; t < 0x200; ++t: |
| 156 | | buffer[t] = *data |
| 170 | buffer[t] = rdata () |
| 157 | 171 | char error[9] |
| 158 | | unsigned errcol = (1 << page_bits) + (column >> 5) |
| 159 | | *command = CMD_RNDOUT |
| 160 | | *address = errcol |
| 161 | | *address = errcol >> 8 |
| 162 | | *command = CMD_RNDOUTSTART |
| 172 | // Spare space (starts at 1 << page_bits) |
| 173 | // 0: unused |
| 174 | // 2: detect valid data (at least 1 byte == 0 means valid) |
| 175 | // 5: unused |
| 176 | // 6: 9-byte ecc of 1st 512 bytes |
| 177 | // 15: 9-byte ecc of 2nd 512 bytes |
| 178 | // 24: 9-byte ecc of 3rd 512 bytes |
| 179 | // 33: 9-byte ecc of 4th 512 bytes |
| 180 | // 42: unused |
| 181 | // 64: end of space |
| 182 | unsigned errcol = (1 << page_bits) + (column >> 9) * 9 + 6 |
| 183 | cmd (CMD_RNDOUT) |
| 184 | addr (errcol) |
| 185 | addr (errcol >> 8) |
| 186 | cmd (CMD_RNDOUTSTART) |
| 163 | 187 | for unsigned t = 0; t < 9; ++t: |
| 164 | | error[t] = *data |
| 188 | error[t] = rdata () |
| 165 | 189 | EMC_NFPAR (0) = ((unsigned *)error)[0] |
| 166 | 190 | EMC_NFPAR (1) = ((unsigned *)error)[1] |
| 167 | 191 | EMC_NFPAR (2) = error[9] |
| 168 | 192 | EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY |
| 169 | 193 | while !(EMC_NFINTS & EMC_NFINTS_DECF): |
| 170 | 194 | Iris::schedule () |
| 171 | | // delay... |
| 172 | | //Iris::schedule () |
| 173 | 195 | unsigned errs = (EMC_NFINTS & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT |
| 196 | for unsigned i = 0; i < errs; ++i: |
| 197 | Iris::debug ("correcting %x on %x\n", EMC_NFERR (i) & 0xff, EMC_NFERR (i) >> 16) |
| 198 | buffer[EMC_NFERR (i) >> 16] ^= EMC_NFERR (i) & 0xff |
| 199 | |
| 200 | static void write (unsigned a, char *buffer): |
| 201 | unsigned row = a >> page_bits |
| 202 | //Iris::debug ("writing: %x/%x: ", a, row) |
| 203 | cmd (CMD_SEQIN) |
| 204 | addr (0) |
| 205 | addr (0) |
| 206 | addr (row) |
| 207 | addr (row >> 8) |
| 208 | addr (row >> 16) |
| 209 | char ecc[4][9] |
| 210 | for unsigned i = 0; i < 0x4; ++i: |
| 211 | EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING | EMC_NFECR_ERST |
| 212 | for unsigned j = 0; j < 0x200; ++j: |
| 213 | wdata (buffer[i * 0x200 + j]) |
| 214 | while !(EMC_NFINTS & EMC_NFINTS_ENCF): |
| 215 | Iris::schedule () |
| 216 | ((unsigned *)ecc[i])[0] = EMC_NFPAR (0) |
| 217 | ((unsigned *)ecc[i])[1] = EMC_NFPAR (1) |
| 218 | ecc[i][9] = EMC_NFPAR (2) |
| 219 | // Spare space (starts at 1 << page_bits) |
| 220 | // 0: unused |
| 221 | // 2: detect valid data (at least 1 byte == 0 means valid) |
| 222 | // 5: unused |
| 223 | // 6: 9-byte ecc of 1st 512 bytes |
| 224 | // 15: 9-byte ecc of 2nd 512 bytes |
| 225 | // 24: 9-byte ecc of 3rd 512 bytes |
| 226 | // 33: 9-byte ecc of 4th 512 bytes |
| 227 | // 42: unused |
| 228 | // 64: end of space |
| 229 | for unsigned i = 0; i < 6; ++i: |
| 230 | wdata (0) |
| 231 | for unsigned i = 0; i < 4; ++i: |
| 232 | for unsigned j = 0; j < 9; ++j: |
| 233 | wdata (ecc[i][j]) |
| 234 | cmd (CMD_PAGEPROG) |
| 235 | Iris::debug ("nand program %d done\n", a) |
| 236 | |
| 237 | static void erase (unsigned a): |
| 238 | unsigned row = a >> page_bits |
| 239 | cmd (CMD_ERASE1) |
| 240 | addr (row) |
| 241 | addr (row >> 8) |
| 242 | addr (row >> 16) |
| 243 | cmd (CMD_ERASE2) |
| 244 | Iris::debug ("nand erase %d done\n", a) |
| 174 | 245 | |
| 175 | 246 | Iris::Num start (): |
| 176 | | kdebug ("reading nand in 10 seconds\n") |
| 247 | kdebug ("starting nand operation in 10 seconds\n") |
| 177 | 248 | Iris::sleep (10 * HZ) |
| 178 | 249 | map_emc () |
| 179 | 250 | map_gpio () |
| 180 | 251 | |
| 252 | // Arbitrary addresses where the pages are mapped. |
| 181 | 253 | command = (volatile char *)0x15000 |
| 182 | 254 | address = (volatile char *)0x16000 |
| 183 | 255 | data = (volatile char *)0x17000 |
| 184 | 256 | |
| 185 | 257 | reset () |
| 186 | 258 | |
| 187 | | char buffer[0x200] |
| 259 | char buffer[0x800] |
| 260 | |
| 261 | //erase (0) |
| 188 | 262 | |
| 189 | 263 | // Send nand contents to serial port. |
| 190 | 264 | for unsigned a = 0; a < 0x4000; a += 0x200: |
| 191 | 265 | read (a, buffer) |
| 192 | | //for unsigned s = 0; s < 0x10; ++s: |
| 193 | | for unsigned t = 0; t < 0x10; ++t: |
| 266 | for unsigned s = 0; s < 0x10; ++s: |
| 267 | for unsigned t = 0; t < 0x20; ++t: |
| 194 | 268 | kdebug (" ") |
| 195 | | kdebug_num (buffer[0 * 0x20 + t], 2) |
| 269 | kdebug_num (buffer[s * 0x20 + t], 2) |
| 196 | 270 | kdebug ("\n") |
| 197 | | //kdebug ("\n") |
| 271 | kdebug ("\n") |
| 198 | 272 | // Exit. |
| 199 | 273 | return 0 |