| 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;
|
|
|
120 |
}
|