Root/
| 1 | #pypp 0 |
| 2 | // Iris: micro-kernel for a capability-based operating system. |
| 3 | // boot-programs/nand.ccp: NAND driver. |
| 4 | // Copyright 2009 Bas Wijnen <wijnen@debian.org> |
| 5 | // |
| 6 | // This program is free software: you can redistribute it and/or modify |
| 7 | // it under the terms of the GNU General Public License as published by |
| 8 | // the Free Software Foundation, either version 3 of the License, or |
| 9 | // (at your option) any later version. |
| 10 | // |
| 11 | // This program is distributed in the hope that it will be useful, |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | // GNU General Public License for more details. |
| 15 | // |
| 16 | // You should have received a copy of the GNU General Public License |
| 17 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | |
| 19 | #include "devices.hh" |
| 20 | #define ARCH |
| 21 | #include "arch.hh" |
| 22 | |
| 23 | #define debug Iris::debug |
| 24 | #define DELAY Iris::schedule |
| 25 | #include "nand.hh" |
| 26 | #undef debug |
| 27 | |
| 28 | static unsigned *cache |
| 29 | static bool dirty |
| 30 | static unsigned current_block |
| 31 | |
| 32 | static void sync (): |
| 33 | //Iris::debug ("erasing %x\n", current_block << block_bits) |
| 34 | erase (current_block << block_bits) |
| 35 | for unsigned p = 0; p < 1 << (block_bits - page_bits); ++p: |
| 36 | write ((current_block << block_bits) + (p << page_bits), (char *)&cache[p << (page_bits - 2)]) |
| 37 | |
| 38 | static void read_block (unsigned b): |
| 39 | if b == current_block: |
| 40 | return |
| 41 | if current_block != ~0 && dirty: |
| 42 | sync () |
| 43 | current_block = b |
| 44 | //kdebug ("setting current block to ") |
| 45 | //kdebug_num (b) |
| 46 | //kdebug ("\n") |
| 47 | for unsigned p = 0; p < 1 << (block_bits - 9); ++p: |
| 48 | read ((b << block_bits) + (p << 9), (char *)&cache[p << (9 - 2)]) |
| 49 | dirty = false |
| 50 | |
| 51 | Iris::Num start (): |
| 52 | map_emc () |
| 53 | map_gpio () |
| 54 | |
| 55 | // Arbitrary addresses where the pages are mapped. |
| 56 | command = (volatile char *)0x15000 |
| 57 | address = (volatile char *)0x16000 |
| 58 | data = (volatile char *)0x17000 |
| 59 | |
| 60 | Iris::Page data_page = Iris::my_memory.create_page () |
| 61 | Iris::Page command_page = Iris::my_memory.create_page () |
| 62 | Iris::Page address_page = Iris::my_memory.create_page () |
| 63 | |
| 64 | unsigned base = 0x18000000 |
| 65 | data_page.alloc_physical (base, false, false) |
| 66 | command_page.alloc_physical (base + 0x8000, false, false) |
| 67 | address_page.alloc_physical (base + 0x10000, false, false) |
| 68 | |
| 69 | Iris::my_memory.map (data_page, (unsigned)data) |
| 70 | Iris::my_memory.map (command_page, (unsigned)command) |
| 71 | Iris::my_memory.map (address_page, (unsigned)address) |
| 72 | |
| 73 | Iris::free_cap (data_page) |
| 74 | Iris::free_cap (command_page) |
| 75 | Iris::free_cap (address_page) |
| 76 | |
| 77 | reset () |
| 78 | |
| 79 | current_block = ~0 |
| 80 | dirty = false |
| 81 | cache = (unsigned *)0x40000000 |
| 82 | for unsigned p = 0; p < 1 << (block_bits - PAGE_BITS); ++p: |
| 83 | Iris::Page page = Iris::my_memory.create_page () |
| 84 | page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME) |
| 85 | Iris::my_memory.map (page, (unsigned)cache + (p << PAGE_BITS)) |
| 86 | Iris::free_cap (page) |
| 87 | Iris::Page tmp = Iris::my_memory.create_page () |
| 88 | tmp.set_flags (Iris::Page::PAYING) |
| 89 | unsigned *tmp_addr = (unsigned *)0x3ffff000 |
| 90 | Iris::my_memory.map (tmp, (unsigned)tmp_addr) |
| 91 | |
| 92 | Iris::Cap cap = Iris::my_receiver.create_capability (0) |
| 93 | Iris::my_parent.provide_capability <Iris::WBlock> (cap.copy ()) |
| 94 | Iris::free_cap (cap) |
| 95 | |
| 96 | Iris::my_parent.init_done () |
| 97 | |
| 98 | while true: |
| 99 | Iris::wait () |
| 100 | switch Iris::recv.data[0].l: |
| 101 | case Iris::Block::GET_SIZE: |
| 102 | if size_bits > 32: |
| 103 | Iris::recv.reply.invoke (Iris::Num (0, 1 << (size_bits - 32))) |
| 104 | else: |
| 105 | Iris::recv.reply.invoke (1 << size_bits) |
| 106 | break |
| 107 | case Iris::Block::GET_ALIGN_BITS: |
| 108 | Iris::recv.reply.invoke (9) |
| 109 | break |
| 110 | case Iris::Block::GET_BLOCK: |
| 111 | unsigned row = Iris::recv.data[1].value () >> 9 |
| 112 | unsigned block = row >> (block_bits - 9) |
| 113 | row &= (1 << (block_bits - 9)) - 1 |
| 114 | unsigned offset = Iris::recv.data[0].h & 0xe00 |
| 115 | unsigned size = Iris::recv.data[0].h >> 16 |
| 116 | if size + offset >= 0x1000: |
| 117 | size = 0x1000 - offset |
| 118 | #if 0 |
| 119 | kdebug ("get ") |
| 120 | kdebug_num (block) |
| 121 | kdebug (":") |
| 122 | kdebug_num (row) |
| 123 | kdebug ("+") |
| 124 | kdebug_num (size) |
| 125 | kdebug ("@") |
| 126 | kdebug_num (offset) |
| 127 | kdebug ("\n") |
| 128 | #endif |
| 129 | read_block (block) |
| 130 | Iris::Cap reply = Iris::get_reply () |
| 131 | Iris::Page page = Iris::get_arg () |
| 132 | page.share (tmp) |
| 133 | tmp.set_flags (Iris::Page::FRAME) |
| 134 | for unsigned t = 0; t < size >> 2; ++t: |
| 135 | tmp_addr[(offset >> 2) + t] = cache[t + (row << (9 - 2))] |
| 136 | tmp.set_flags (0, Iris::Page::FRAME) |
| 137 | reply.invoke () |
| 138 | Iris::free_cap (reply) |
| 139 | Iris::free_cap (page) |
| 140 | break |
| 141 | case Iris::WBlock::SET_BLOCK: |
| 142 | unsigned row = Iris::recv.data[1].value () >> 9 |
| 143 | unsigned block = row >> (block_bits - 9) |
| 144 | row &= (1 << (block_bits - 9)) - 1 |
| 145 | unsigned offset = Iris::recv.data[0].h & 0xe00 |
| 146 | unsigned size = Iris::recv.data[0].h >> 16 |
| 147 | if size + offset >= 0x1000: |
| 148 | size = 0x1000 - offset |
| 149 | #if 0 |
| 150 | kdebug ("set ") |
| 151 | kdebug_num (block) |
| 152 | kdebug (":") |
| 153 | kdebug_num (row) |
| 154 | kdebug ("+") |
| 155 | kdebug_num (size) |
| 156 | kdebug ("@") |
| 157 | kdebug_num (offset) |
| 158 | kdebug ("\n") |
| 159 | #endif |
| 160 | //kdebug_num (current_block) |
| 161 | //kdebug ("/") |
| 162 | read_block (block) |
| 163 | Iris::Cap reply = Iris::get_reply () |
| 164 | Iris::Page page = Iris::get_arg () |
| 165 | page.share (tmp) |
| 166 | tmp.set_flags (Iris::Page::FRAME) |
| 167 | for unsigned t = 0; t < size; t += 4: |
| 168 | cache[(offset + t + (row << 9)) >> 2] = tmp_addr[(offset + t) >> 2] |
| 169 | tmp.set_flags (0, Iris::Page::FRAME) |
| 170 | reply.invoke () |
| 171 | Iris::free_cap (reply) |
| 172 | Iris::free_cap (page) |
| 173 | dirty = true |
| 174 | //kdebug_num (current_block) |
| 175 | //kdebug ("!") |
| 176 | break |
| 177 | case Iris::WBlock::TRUNCATE: |
| 178 | default: |
| 179 | Iris::recv.reply.invoke (Iris::ERR_INVALID_OPERATION) |
| 180 | break |
| 181 |
Branches:
master
