Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
427 farthen 6
//    This file is part of emCORE.
227 theseven 7
//
427 farthen 8
//    emCORE is free software: you can redistribute it and/or
227 theseven 9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
427 farthen 13
//    emCORE is distributed in the hope that it will be useful,
227 theseven 14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
427 farthen 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
227 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "usb/usbtarget.h"
891 theseven 26
#include "usb/usb.h"
227 theseven 27
#include "nand.h"
28
 
29
 
891 theseven 30
int usb_target_handle_request(uint32_t* buf, int bufsize, void** addr)
227 theseven 31
{
891 theseven 32
    int len = 0;
33
    switch (buf[0])
227 theseven 34
    {
35
        case 0xffff0001:  // GET NAND INFO
36
        {
891 theseven 37
            int banks;
227 theseven 38
            const struct nand_device_info_type* type = nand_get_device_type(0);
891 theseven 39
            for (banks = 1; banks < 4; banks++)
227 theseven 40
                if (!nand_get_device_type(banks))
41
                    break;
891 theseven 42
            buf[0] = 1;
43
            buf[1] = type->id;
44
            buf[2] = (banks << 16) | type->pagesperblock;
45
            buf[3] = (type->blocks << 16) | type->userblocks;
227 theseven 46
            break;
47
        }
48
        case 0xffff0002:  // READ NAND PAGES
49
        case 0xffff0003:  // WRITE NAND PAGES
50
        {
891 theseven 51
            int banks;
227 theseven 52
            const struct nand_device_info_type* type = nand_get_device_type(0);
891 theseven 53
            for (banks = 1; banks < 4; banks++)
227 theseven 54
                if (!nand_get_device_type(banks))
55
                    break;
56
            uint32_t pagecount = banks * type->blocks * type->pagesperblock;
891 theseven 57
            if (buf[2] + buf[3] > pagecount)
227 theseven 58
            {
891 theseven 59
                buf[0] = 0xffff0001;
227 theseven 60
                break;
61
            }
62
            int i;
891 theseven 63
            uint32_t database = buf[1] & ~0xc0000000;
64
            uint32_t sparebase = database + buf[3] * 2048;
65
            uint32_t resultbase = sparebase + buf[3] * 64;
66
            int doecc = buf[1] & 0x80000000;
67
            int checkempty = buf[1] & 0x40000000;
68
            for (i = 0; i < buf[3]; i++)
227 theseven 69
            {
891 theseven 70
                int lpage = buf[2] + i;
227 theseven 71
                int bank = lpage % banks;
229 theseven 72
                int page = lpage / banks;
227 theseven 73
                int result;
891 theseven 74
                if (buf[0] == 0xffff0002)
227 theseven 75
                    result = nand_read_page(bank, page, (void*)(database + i * 2048),
76
                                            (void*)(sparebase + i * 64), doecc, checkempty);
891 theseven 77
                else if (buf[0] == 0xffff0003)
227 theseven 78
                    result = nand_write_page(bank, page, (void*)(database + i * 2048),
79
                                             (void*)(sparebase + i * 64), doecc);
80
                *((int*)(resultbase + i * 4)) = result;
81
            }
891 theseven 82
            buf[0] = 1;
227 theseven 83
            break;
84
        }
85
        case 0xffff0004:  // ERASE NAND PAGES
86
        {
891 theseven 87
            int banks;
227 theseven 88
            const struct nand_device_info_type* type = nand_get_device_type(0);
891 theseven 89
            for (banks = 1; banks < 4; banks++)
227 theseven 90
                if (!nand_get_device_type(banks))
91
                    break;
92
            uint32_t blockcount = banks * type->blocks;
891 theseven 93
            if (buf[2] + buf[3] > blockcount)
227 theseven 94
            {
891 theseven 95
                buf[0] = 0xffff0001;
227 theseven 96
                break;
97
            }
98
            int i;
891 theseven 99
            for (i = 0; i < buf[3]; i++)
227 theseven 100
            {
891 theseven 101
                int lblock = buf[2] + i;
227 theseven 102
                int bank = lblock % banks;
103
                int block = lblock / banks;
104
                int result = nand_block_erase(bank, block * type->pagesperblock); 
891 theseven 105
                *((int*)(buf[1] + i * 4)) = result;
227 theseven 106
            }
891 theseven 107
            buf[0] = 1;
227 theseven 108
            break;
109
        }
932 theseven 110
        default:
111
            buf[0] = 2;
112
            break;
227 theseven 113
    }
891 theseven 114
    return len;
531 theseven 115
}