Root/userspace/nanonote/sdmmc.ccp

1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// source/sd+mmc.ccp: sd+mmc 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
23class Mmc:
24    public:
25    enum Response_type:
26        NONE = MSC_CMDAT_RESPONSE_NONE
27        RD_DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ
28        WR_DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE
29        R1 = MSC_CMDAT_RESPONSE_R1
30        R1B = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_BUSY
31        R2 = MSC_CMDAT_RESPONSE_R2
32        R3 = MSC_CMDAT_RESPONSE_R3
33        R4 = MSC_CMDAT_RESPONSE_R4
34        R5 = MSC_CMDAT_RESPONSE_R5
35        R6 = MSC_CMDAT_RESPONSE_R6
36        R7 = MSC_CMDAT_RESPONSE_R7
37    static unsigned const POWER_PORT = 3
38    static unsigned const POWER_PIN = 2
39    struct CID:
40        unsigned mid
41        char oid[2]
42        char pnm[5]
43        unsigned prv
44        unsigned psn
45        unsigned year
46        unsigned month
47    struct CSD:
48        unsigned c_size
49        unsigned c_size_mult
50        unsigned read_bl_len, write_bl_len
51        bool copy
52        bool perm_write_protect
53        bool tmp_write_protect
54    bool send (unsigned cmd, unsigned arg, Response_type response_type, unsigned *response = NULL)
55    void check_sd ()
56    void check_sdmem ()
57    void check_mmc ()
58    public:
59    void reset ()
60    void detect ()
61    void release ()
62    void interrupt ()
63    CID const &get_cid ():
64        return cid
65    unsigned get_num_blocks ():
66        return num_blocks
67    unsigned get_read_block_size ():
68        return read_block_size
69    unsigned get_block_bits ():
70        return hc ? 9 : csd.read_bl_len > csd.write_bl_len ? csd.read_bl_len : csd.write_bl_len
71    void write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
72    void read_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset)
73    void wait_write ()
74    void add_cb (Iris::Listitem item):
75        cb_list.add_item (item)
76    private:
77    void set_block (unsigned block)
78    unsigned current_block_num
79    bool dirty
80    unsigned *current_block
81    unsigned rca
82    bool have_sdmem, have_io
83    bool hc
84    CID cid
85    CSD csd
86    unsigned num_blocks, read_block_size
87    Iris::Page buffer_page
88    Iris::List cb_list
89    static unsigned const buffer = 0x15000
90
91bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigned *response):
92    MSC_CMD = cmd
93    MSC_ARG = arg
94    MSC_CMDAT = response_type
95    MSC_IMASK = ~MSC_IMASK_END_CMD_RES
96    Iris::register_interrupt (IRQ_MSC)
97    msc_start_op ()
98    Iris::wait_for_interrupt ()
99    MSC_IMASK = ~0
100    //kdebug ("cmd: ")
101    //kdebug_num (cmd)
102    unsigned stat = MSC_STAT
103    //kdebug (", stat: ")
104    //kdebug_num (stat)
105    //kdebug ("\n")
106    if stat & MSC_STAT_CRC_RES_ERR:
107        Iris::panic (0, "crc error in mmc response")
108        return false
109    if stat & MSC_STAT_TIME_OUT_RES:
110        kdebug ("time out waiting for mmc response\n")
111        MSC_IREG = MSC_IREG_END_CMD_RES
112        return false
113    if response_type == R2:
114        unsigned d = MSC_RES
115        if d >> 8 != 0x3f:
116            Iris::panic (d, "invalid r2 response")
117        if cmd == 3:
118            // Read out result.
119            cid.mid = d & 0xff
120            d = MSC_RES
121            cid.oid[0] = d >> 8
122            cid.oid[1] = d & 0xff
123            d = MSC_RES
124            cid.pnm[0] = d >> 8
125            cid.pnm[1] = d & 0xff
126            d = MSC_RES
127            cid.pnm[2] = d >> 8
128            cid.pnm[3] = d & 0xff
129            d = MSC_RES
130            cid.pnm[4] = d >> 8
131            cid.prv = d & 0xff
132            d = MSC_RES
133            cid.psn = d << 16
134            d = MSC_RES
135            cid.psn |= d
136            d = MSC_RES
137            cid.year = 2000 + (d >> 4 & 0xff)
138            cid.month = d & 0xf
139            #if 1
140            Iris::debug ("CID: mid=%x, oid=%x %x, pnm=%x %x %x %x %x, prv=%x, psn=%x, year=%x, month=%x\n", cid.mid, cid.oid[0], cid.oid[1], cid.pnm[0], cid.pnm[1], cid.pnm[2], cid.pnm[3], cid.pnm[4], cid.prv, cid.psn, cid.year, cid.month)
141            #endif
142        else:
143            // Header (8) 1.0 1.0
144            // Read out csd.
145            // Ignore csd_structure. 2 (+ 6) 1.0 2.0 ***
146            d = MSC_RES
147            // Ignore taac and nsac. 8 + 8 2.0 4.0 ***
148            d = MSC_RES
149            // Ignore tran_speed, ccc. 8 + 8/12 2.0 6.0 ***
150            d = MSC_RES
151            // Ignore rest of ccc. 4/12 0.4 6.4
152            // 4 0.4 7.0
153            csd.read_bl_len = (d >> 8) & 0xf
154            // Ignore read_bl_partial, write_blk_misalign, read_blk_misalign, dsr_imp. 1 + 1 + 1 + 1 (+ 2) 0.6 7.6
155            // 2/12 0.2 8.0 ***
156            csd.c_size = (d & 0x0003) << 10
157            d = MSC_RES
158            // 10/12 1.2 9.2
159            csd.c_size |= d >> 6
160            // Ignore vdd_r_cur_min, vdd_r_cur_max. 3 + 3 0.6 10.0 ***
161            d = MSC_RES
162            // Ignore vdd_w_cur_min, vdd_w_cur_max. 3 + 3 0.6 10.6
163            // 3 0.3 11.1
164            csd.c_size_mult = (d >> 7) & 0x7
165            // Ignore erase_blk_enable, sector_size. 1 + 6/7 0.7 12.0 ***
166            d = MSC_RES
167            // Ignore rest of sector_size, wp_grp_size, wp_grp_enable, r2w_factor. 1/7 + 7 + 1 (+ 2) + 3 1.6 13.6
168            // 2/4 0.4 14.0 ***
169            csd.write_bl_len = (d << 2) & 0xc
170            d = MSC_RES
171            // 2/4 0.2 14.2
172            csd.write_bl_len |= (d >> 14) & 0x3
173            // Ignore write_bl_partial, file_format_grp. 1 (+ 5) + 1 0.7 15.1
174            // 1 0.1 15.2
175            csd.copy = d & 0x40
176            // 1 0.1 15.3
177            csd.perm_write_protect = d & 0x20
178            // 1 0.1 15.4
179            csd.tmp_write_protect = d & 0x10
180            // Ignore file_format. 2 (+ 2) 0.4 16.0 ***
181            read_block_size = hc ? 512 : 1 << csd.read_bl_len
182            num_blocks = (csd.c_size + 1) << (csd.c_size_mult + 2)
183            if hc:
184                if csd.read_bl_len < 9:
185                    num_blocks >>= 9 - csd.read_bl_len
186                else:
187                    num_blocks <<= csd.read_bl_len - 9
188            #if 1
189            Iris::debug ("CSD: size=%x<<%x, r/w len=%x/%x, %s, %s, %s\n", csd.c_size, csd.c_size_mult, csd.read_bl_len, csd.write_bl_len, csd.copy ? "copy" : "no copy", csd.perm_write_protect ? "fixed write protect" : "no fixed write protect", csd.tmp_write_protect ? "write protect" : "no write protect")
190            #endif
191        unsigned c_size
192        unsigned c_size_mult
193        unsigned read_bl_len, write_bl_len
194        bool copy
195        bool perm_write_protect
196        bool tmp_write_protect
197    else if response_type != NONE:
198        unsigned r = MSC_RES
199        if response_type == R3:
200            if r >> 8 != 0x3f:
201                Iris::panic (r, "r3 response was not 3f")
202        else if r >> 8 != cmd:
203            kdebug ("stat: ")
204            kdebug_num (MSC_STAT)
205            kdebug ("; response: ")
206            kdebug_num (r)
207            kdebug ("; cmd: ")
208            kdebug_num (cmd)
209            Iris::panic (r, "response doesn't match command")
210        r <<= 24
211        r |= MSC_RES << 8
212        r |= MSC_RES & 0xff
213        if response:
214            *response = r
215    else:
216    //kdebug ("extra response fifo read: ")
217    //for unsigned i = 0; i < 9; ++i:
218        //kdebug (" ")
219        //kdebug_num (MSC_RES, 4)
220    //kdebug ("\n")
221    MSC_IREG = MSC_IREG_END_CMD_RES
222    return true
223
224void Mmc::reset ():
225    current_block_num = ~0
226    dirty = false
227    cb_list = Iris::my_memory.create_list ()
228    current_block = (unsigned *)(buffer + PAGE_SIZE)
229    // Create a buffer to use for data transfer.
230    buffer_page = Iris::my_memory.create_page ()
231    Iris::my_memory.map (buffer_page, buffer)
232    // Reset all state, by faking a release event.
233    release ()
234    // Enable 25 MHz clock to msc.
235    CPM_MSCCDR = 13
236    cpm_start_msc ()
237    // Enable msc pins.
238    gpio_as_msc ()
239    // Disable power to card.
240    gpio_as_gpio (POWER_PORT, 1 << POWER_PIN)
241    gpio_as_output (POWER_PORT, 1 << POWER_PIN)
242    gpio_disable_pull (POWER_PORT, 1 << POWER_PIN)
243    gpio_set (POWER_PORT, 1 << POWER_PIN)
244
245    // Stop the clock.
246    MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP
247    while MSC_STAT & MSC_STAT_CLK_EN:
248        //kdebug (",")
249        Iris::sleep (1)
250
251    // Reset controller and inserted devices.
252    MSC_STRPCL = MSC_STRPCL_RESET
253    while MSC_STAT & MSC_STAT_IS_RESETTING:
254        //kdebug (":")
255        Iris::sleep (1)
256
257    // Initialize registers.
258    MSC_CLKRT = MSC_CLKRT_CLK_RATE_DIV_1
259    MSC_RESTO = 64
260    MSC_RDTO = ~0
261    MSC_BLKLEN = 0x200
262    MSC_NOB = 0
263    MSC_IREG = ~0
264    MSC_IMASK = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_RXFIFO_RD_REQ)
265    MSC_ARG = 0
266
267    // Start the clock.
268    MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START
269    // Set cards, if any, to idle.
270    send (0, 0, NONE)
271
272    // Reset SDIO device, if any. Don't do this, because it breaks for some reason.
273    //send (52, 0x88000c08, R5)
274
275void Mmc::check_mmc ():
276    //kdebug ("checking mmc\n")
277    // 1. SEND CMD1 (SEND_OP_CMD) TO VALIDATE VOLTAGE (THE GENERAL OCR VALUE IS 0X00FF88000).
278    // 2. IF THE RESPONSE IS CORRECT, THEN CONTINUE, ELSE GOTO 9.
279    // 3. IF THE INITIALIZATION HAS FINISHED, GO TO 5. (THE RESPONSE IS THE OCR REGISTER AND IT INCLUDES A STATUS INFORMATION BIT (BIT [31]). THIS STATUS BIT IS SET IF THE CARD POWER UP PROCEDURE HAS BEEN FINISHED. AS LONG AS THE CARD IS BUSY, THE CORRESPONDING BIT[31] IS SET TO LOW.)
280    // 4. Send CMD1 (SEND_OP_CMD) to validate voltage, and then go to 3.
281    // 5. Send CMD2 (ALL_SEND_CID) to get the card CID.
282    // 6. If the response timeout occurs, goto 9.
283    // 7. Send CMD3 (SET_RELATIVE_ADDR) to assign the card a RCA.
284
285void Mmc::check_sdmem ():
286    kdebug ("checking sdmem\n")
287    // 2. Send CMD55. Here the default RCA 0x0000 is used for CMD55.
288    // 3. If the response is correct (CMD55 has response), then continue, else go to check MMC.
289    unsigned code
290    hc = false
291    if send (8, 0x1aa, R7, &code) && (code & 0xff) == 0xaa:
292        kdebug ("hc\n")
293        hc = true
294    if !send (55, 0, R1, &code):
295        check_mmc ()
296        return
297    // 4. Send ACMD41 (SD_SEND_OP_CMD) to validate voltage (the general OCR value is 0x00FF8000).
298    if !send (41, hc ? 0x40800000 : 0x00800000, R3, &code):
299        check_mmc ()
300        return
301    // 5. If the initialization has finished, go to 7. (The response is the OCR register and it includes a status information bit (bit [31]). This status bit is set if the card power up procedure has been finished. As long as the card is busy, the corresponding bit[31] is set to LOW.)
302    // 6. Send CMD55 and ACMD41 to validate voltage, and then go to 5.
303    unsigned retries = 100
304    while !(code & (1 << 31)) && --retries:
305        if !send (55, 0, R1, &code):
306            return
307        if !send (41, hc ? 0x40800000 : 0x00800000, R3, &code):
308            return
309        Iris::sleep (1)
310    if !(code & (1 << 31)):
311        Iris::panic (code, "card fails to finish setting up")
312    // 7. Send CMD2 (ALL_SEND_CID) to get the card CID.
313    if !send (2, 0, R2):
314        Iris::panic (0, "card failed to send CID")
315    // 8. Send CMD3 (SET_RELATIVE_ADDR) to let card publish a RCA. The RCA is returned from the response.
316    // 9. If do not accept the new RCA, go to 8, else record the new RCA.
317    rca = 0
318    while !rca:
319        if !send (3, 0, R6, &rca):
320            Iris::panic (0, "card failed to provide rca")
321        rca &= 0xffff0000
322    kdebug ("received rca ")
323    kdebug_num (rca >> 16, 4)
324    kdebug ("\n")
325    have_sdmem = true
326
327void Mmc::check_sd ():
328    //kdebug ("checking sdio\n")
329    if !send (0, 0, NONE):
330        Iris::panic (0, "unable to reset cards?")
331    // 2. Send CMD5 (IO_SEND_OP_CMD) to validate voltage.
332    // 3. If the response is correct and the number of IO functions > 0, then continue, else go to check SDMEM.
333    unsigned code
334    if !send (5, 1 << 20, R4, &code) || !(code & (7 << 28)):
335        check_sdmem ()
336        return
337    // 4. If C-bit in the response is ready (the initialization has finished), go to 6.
338    // 5. Send CMD5 (IO_SEND_OP_CMD) to validate voltage, then go to 4.
339    while !(code & (1 << 31)):
340        if !send (5, 1 << 20, R4, &code):
341            Iris::panic (0, "invalid response to cmd 5")
342    // 6. If memory-present-bit in the response is true, then it is a combo card (SDIO + Memory), else it is only a SDIO card.
343    // 7. If it is a combo card, go to check SDMEM to initialize the memory part.
344    have_io = true
345    if code & (1 << 27):
346        check_sdmem ()
347        return
348    // 8. Send CMD3 (SET_RELATIVE_ADDR) to let the card publish a RCA. The RCA is returned from the response.
349    // 9. If do not accept the new RCA, go to 8, else record the new RCA.
350    rca = 0
351    while rca == 0:
352        if !send (3, 0, R6, &rca):
353            Iris::panic (0, "unable to set rca")
354        rca &= 0xffff0000
355    check_mmc ()
356
357void Mmc::detect ():
358    kdebug ("mmc detect\n")
359    gpio_clear (POWER_PORT, 1 << POWER_PIN)
360    check_sd ()
361    check_mmc ()
362    if have_sdmem:
363        if !send (9, rca, R2):
364            Iris::panic (0, "unable to request csd")
365        if !send (7, rca, R1B):
366            Iris::panic (0, "unable to select sdmem")
367        kdebug ("found device; size = ")
368        kdebug_num (num_blocks)
369        kdebug (" * ")
370        kdebug_num (read_block_size)
371        kdebug (" = ")
372        kdebug_num (num_blocks * read_block_size)
373        kdebug ("\n")
374        // Set up buffer memory.
375        for unsigned i = 0; i < 1 << csd.write_bl_len; i += PAGE_SIZE:
376            Iris::Page p = Iris::my_memory.create_page ()
377            p.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
378            Iris::my_memory.map (p, (unsigned)current_block + i)
379            Iris::free_cap (p)
380        Iris::Listitem item = cb_list.get_next ()
381        while item.code != Iris::Cap ().code:
382            Iris::Cap c = cb_list.get_cap (item)
383            c.invoke (0, ~0)
384            Iris::free_cap (c)
385            Iris::Listitem nextitem = cb_list.get_next (item);
386            Iris::free_cap (item)
387            item = nextitem
388
389void Mmc::release ():
390    kdebug ("mmc release\n")
391    gpio_set (POWER_PORT, 1 << POWER_PIN)
392    have_sdmem = false
393    have_io = false
394    read_block_size = 0
395    if num_blocks != 0:
396        for unsigned i = 0; i < 1 << csd.write_bl_len; i += PAGE_SIZE:
397            Iris::Page p = Iris::my_memory.mapping ((void *)((unsigned)current_block + i))
398            Iris::my_memory.destroy (p)
399            Iris::free_cap (p)
400        if dirty:
401            Iris::debug ("Warning: sd/mmc card removed before data was written to it")
402        current_block_num = ~0
403        dirty = false
404    num_blocks = 0
405    Iris::Listitem item = cb_list.get_next ()
406    while item.code != Iris::Cap ().code:
407        Iris::Cap c = cb_list.get_cap (item)
408        c.invoke (0, ~0)
409        Iris::free_cap (c)
410        Iris::Listitem nextitem = cb_list.get_next (item);
411        Iris::free_cap (item)
412        item = nextitem
413
414void Mmc::interrupt ():
415    kdebug ("mmc interrupt\n")
416
417void Mmc::set_block (unsigned block):
418    if current_block_num == block:
419        return
420    if dirty && current_block_num != ~0:
421        MSC_NOB = 1
422        MSC_BLKLEN = 1 << csd.write_bl_len
423        if !send (24, (current_block_num << csd.write_bl_len), WR_DATA):
424            Iris::panic (0, "unable to send data")
425        MSC_IMASK = ~MSC_IMASK_TXFIFO_WR_REQ
426        for unsigned a = 0; a < 1 << csd.write_bl_len; a += 4:
427            while MSC_STAT & MSC_STAT_DATA_FIFO_FULL:
428                Iris::register_interrupt (IRQ_MSC)
429                Iris::wait_for_interrupt ()
430            MSC_TXFIFO = current_block[a >> 2]
431        MSC_IMASK = ~0
432        MSC_IREG = MSC_IREG_DATA_TRAN_DONE
433        //kdebug ("done writing page\n")
434    current_block_num = block
435    dirty = false
436    MSC_NOB = 1
437    MSC_BLKLEN = 1 << 9
438    for unsigned a = 0; a < 1 << csd.write_bl_len; a += 1 << 9:
439        if !send (17, (block << csd.write_bl_len) + a, RD_DATA):
440            Iris::panic (0, "unable to request data")
441        MSC_IMASK = ~MSC_IMASK_RXFIFO_RD_REQ
442        for unsigned aa = 0; aa < 1 << 9; aa += 4:
443            while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY:
444                Iris::register_interrupt (IRQ_MSC)
445                Iris::wait_for_interrupt ()
446            current_block[(a + aa) >> 2] = MSC_RXFIFO
447        MSC_IMASK = ~0
448        MSC_IREG = MSC_IREG_DATA_TRAN_DONE
449    //kdebug ("done filling page\n")
450
451void Mmc::read_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
452    if address.value () >> (csd.write_bl_len + 32):
453        Iris::panic (address.h, "page too high: not supported")
454    unsigned block = address.value () >> csd.write_bl_len
455    unsigned start_pos = address.l & (1 << csd.write_bl_len) - 1
456    set_block (block)
457    unsigned blockmask = ~((1 << 9) - 1)
458    size &= blockmask
459    offset &= ~PAGE_MASK & ~3
460    if size + offset > PAGE_SIZE:
461        size = PAGE_SIZE - offset
462    page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
463    page.share (buffer_page)
464    buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
465    page.set_flags (0, Iris::Page::PAYING)
466    for unsigned i = 0; i < size; i += 4:
467        ((unsigned *)buffer)[(offset + i) >> 2] = current_block[(start_pos + i) >> 2]
468
469void Mmc::write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset):
470    if address.value () >> (csd.write_bl_len + 32):
471        Iris::panic (address.h, "page too high: not supported")
472    unsigned block = address.value () >> csd.write_bl_len
473    unsigned start_pos = address.l & (1 << csd.write_bl_len) - 1
474    set_block (block)
475    unsigned blockmask = ~((1 << 9) - 1)
476    size &= blockmask
477    offset &= ~PAGE_MASK & ~3
478    if size + offset > PAGE_SIZE:
479        size = PAGE_SIZE - offset
480    page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
481    page.share (buffer_page)
482    buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
483    page.set_flags (0, Iris::Page::PAYING)
484    for unsigned i = 0; i < size; i += 4:
485        current_block[(start_pos + i) >> 2] = ((unsigned *)buffer)[(offset + i) >> 2]
486    dirty = true
487
488void Mmc::wait_write ():
489    MSC_IMASK = ~MSC_IMASK_PRG_DONE
490    while !MSC_STAT & MSC_STAT_PRG_DONE:
491        Iris::register_interrupt (IRQ_MSC)
492        Iris::wait_for_interrupt ()
493    MSC_IREG = MSC_IREG_PRG_DONE
494
495static Mmc mmc
496
497enum types:
498    DETECT = 1
499    REQUEST
500
501Iris::Num start ():
502    map_msc ()
503    map_gpio ()
504    map_cpm ()
505
506    mmc.reset ()
507
508    Iris::Event detect = Iris::my_parent.get_capability <Iris::Event> ()
509    Iris::Cap cap = Iris::my_receiver.create_capability (DETECT)
510    detect.set_cb (cap.copy ())
511    cap.invoke (~0)
512    Iris::free_cap (cap)
513
514    // Get a message from the queue. This is either the "there is no card" message, or the message we just sent.
515    Iris::wait ()
516    if Iris::recv.data[0].l != ~0:
517        // If it was "there is no card", the message we sent is still in the queue.
518        Iris::wait ()
519    else:
520        // Otherwise, there is a card.
521        mmc.detect ()
522
523    cap = Iris::my_receiver.create_capability (REQUEST)
524    Iris::my_parent.provide_capability <Iris::WBlock> (cap.copy ())
525    Iris::free_cap (cap)
526
527    Iris::my_parent.init_done ()
528
529    while true:
530        Iris::wait ()
531        switch Iris::recv.protected_data.l:
532            case 0:
533                mmc.interrupt ()
534                break
535            case DETECT:
536                if Iris::recv.data[0].l:
537                    mmc.detect ()
538                else:
539                    mmc.release ()
540                break
541            case REQUEST:
542                //kdebug ("sd+mmc request ")
543                //kdebug_num (Iris::recv.data[0].l)
544                //kdebug ("\n")
545                switch Iris::recv.data[0].l:
546                    case Iris::Block::GET_SIZE:
547                        Iris::debug ("get size\n")
548                        unsigned long long size = mmc.get_num_blocks () * mmc.get_read_block_size ()
549                        Iris::recv.reply.invoke (size)
550                        break
551                    case Iris::Block::GET_ALIGN_BITS:
552                        Iris::debug ("get align bits\n")
553                        Iris::recv.reply.invoke (9)
554                        break
555                    case Iris::Block::GET_BLOCK:
556                        //Iris::debug ("get block\n")
557                        Iris::Cap reply = Iris::get_reply ()
558                        Iris::Page page = Iris::get_arg ()
559                        mmc.read_page (page, Iris::recv.data[1], Iris::recv.data[0].h >> 16, Iris::recv.data[0].h & 0xffff)
560                        reply.invoke ()
561                        Iris::free_cap (page)
562                        Iris::free_cap (reply)
563                        break
564                    case Iris::WBlock::SET_BLOCK:
565                        Iris::debug ("set block\n")
566                        Iris::Cap reply = Iris::get_reply ()
567                        Iris::Page page = Iris::get_arg ()
568                        mmc.write_page (page, Iris::recv.data[1], Iris::recv.data[0].h >> 16, Iris::recv.data[0].h & 0xffff)
569                        reply.invoke ()
570                        Iris::free_cap (page)
571                        Iris::free_cap (reply)
572                        mmc.wait_write ()
573                        break
574                    case Iris::Block::SET_CHANGE_CB:
575                        Iris::debug ("set change cb\n")
576                        Iris::Listitem item = Iris::get_arg ()
577                        Iris::Cap reply = Iris::get_reply ()
578                        mmc.add_cb (item)
579                        reply.invoke ()
580                        Iris::free_cap (item)
581                        Iris::free_cap (reply)
582                        break
583                    case Iris::WBlock::TRUNCATE:
584                        Iris::debug ("truncate\n")
585                        // Fall through: don't support resizing.
586                    default:
587                        Iris::panic (0, "unexpected event for sd+mmc")
588                break
589            default:
590                Iris::panic (0, "unexpected request source for sd+mmc")
591

Archive Download this file

Branches:
master



interactive