Subversion Repositories freemyipod

Rev

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"
26
#include "usb/usbdrv.h"
27
#include "nand.h"
28
 
29
 
30
int usb_target_handle_request(uint32_t* buffer, int bufsize)
31
{
32
    int size = 0;
33
    switch (buffer[0])
34
    {
35
        case 0xffff0001:  // GET NAND INFO
36
        {
37
            int banks = 1;
38
            const struct nand_device_info_type* type = nand_get_device_type(0);
39
            for (; banks < 4; banks++)
40
                if (!nand_get_device_type(banks))
41
                    break;
42
            buffer[0] = 1;
43
            buffer[1] = type->id;
44
            buffer[2] = (banks << 16) | type->pagesperblock;
45
            buffer[3] = (type->blocks << 16) | type->userblocks;
46
            size = 16;
47
            break;
48
        }
49
        case 0xffff0002:  // READ NAND PAGES
50
        case 0xffff0003:  // WRITE NAND PAGES
51
        {
52
            int banks = 1;
53
            const struct nand_device_info_type* type = nand_get_device_type(0);
54
            for (; banks < 4; banks++)
55
                if (!nand_get_device_type(banks))
56
                    break;
57
            uint32_t pagecount = banks * type->blocks * type->pagesperblock;
58
            if (buffer[2] + buffer[3] > pagecount)
59
            {
60
                buffer[0] = 0xffff0001;
61
                size = 16;
62
                break;
63
            }
64
            int i;
65
            uint32_t database = buffer[1] & ~0xc0000000;
66
            uint32_t sparebase = database + buffer[3] * 2048;
67
            uint32_t resultbase = sparebase + buffer[3] * 64;
68
            int doecc = buffer[1] & 0x80000000;
69
            int checkempty = buffer[1] & 0x40000000;
70
            for (i = 0; i < buffer[3]; i++)
71
            {
72
                int lpage = buffer[2] + i;
73
                int bank = lpage % banks;
229 theseven 74
                int page = lpage / banks;
227 theseven 75
                int result;
76
                if (buffer[0] == 0xffff0002)
77
                    result = nand_read_page(bank, page, (void*)(database + i * 2048),
78
                                            (void*)(sparebase + i * 64), doecc, checkempty);
79
                else if (buffer[0] == 0xffff0003)
80
                    result = nand_write_page(bank, page, (void*)(database + i * 2048),
81
                                             (void*)(sparebase + i * 64), doecc);
82
                *((int*)(resultbase + i * 4)) = result;
83
            }
84
            buffer[0] = 1;
85
            size = 16;
86
            break;
87
        }
88
        case 0xffff0004:  // ERASE NAND PAGES
89
        {
90
            int banks = 1;
91
            const struct nand_device_info_type* type = nand_get_device_type(0);
92
            for (; banks < 4; banks++)
93
                if (!nand_get_device_type(banks))
94
                    break;
95
            uint32_t blockcount = banks * type->blocks;
96
            if (buffer[2] + buffer[3] > blockcount)
97
            {
98
                buffer[0] = 0xffff0001;
99
                size = 16;
100
                break;
101
            }
102
            int i;
103
            for (i = 0; i < buffer[3]; i++)
104
            {
105
                int lblock = buffer[2] + i;
106
                int bank = lblock % banks;
107
                int block = lblock / banks;
108
                int result = nand_block_erase(bank, block * type->pagesperblock); 
109
                *((int*)(buffer[1] + i * 4)) = result;
110
            }
111
            buffer[0] = 1;
112
            size = 16;
113
            break;
114
        }
115
        default:
116
            buffer[0] = 2;
117
            size = 16;
118
    }
119
    return size;
531 theseven 120
}