Root/userspace/nanonote/nand.ccp

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
28static unsigned *cache
29static bool dirty
30static unsigned current_block
31
32static 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
38static 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
51Iris::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

Archive Download this file

Branches:
master



interactive