OSDN Git Service

progress bar の更新頻度を定量化, front end -> script 実行形の構造体を統合
[unagi/old-svn-converted.git] / client / trunk / reader_kazzo.c
1 #include <assert.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <usb.h>
5 #include <kazzo_request.h>
6 #include <kazzo_task.h>
7 #include "memory_manage.h"
8 #include "reader_master.h"
9 #include "usb_device.h"
10 #include "reader_kazzo.h"
11 #include "widget.h"
12
13 static inline usb_dev_handle *device_open(void)
14 {
15         usb_dev_handle *handle = NULL;
16         const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID};
17         const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
18         char vendor[] = {USB_CFG_VENDOR_NAME, 0};
19         char product[] = {USB_CFG_DEVICE_NAME, 0};
20         int vid, pid;
21
22         /* compute VID/PID from usbconfig.h so that there is a central source of information */
23         vid = (rawVid[1] << 8) | rawVid[0];
24         pid = (rawPid[1] << 8) | rawPid[0];
25
26         if(usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) == 0){
27                 return handle;
28         }
29         return NULL;
30 }
31
32 static void kazzo_open(struct reader_handle *h)
33 {
34         h->handle = device_open();
35 }
36
37 static void kazzo_close(struct reader_handle *h)
38 {
39         usb_close(h->handle);
40 }
41 enum{
42         TIMEOUT = 4000
43 };
44 //-------- read sequence --------
45 static void device_read(usb_dev_handle *handle, enum request r, enum index index, long address, long length, uint8_t *data)
46 {
47         int cnt = usb_control_msg(
48                 handle, 
49                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, 
50                 r, address, 
51                 index, (char *) data, length, TIMEOUT
52         );
53         if(cnt != length){
54                 puts(__FUNCTION__);
55                 puts(usb_strerror());
56                 exit(1);
57         }
58 }
59 static void read_main(const struct reader_handle *d, const struct gauge *g, const enum request r, enum index index, long address, long length, uint8_t *data)
60 {
61         const int packet = READ_PACKET_SIZE;
62         while(length >= packet){
63                 device_read(
64                         (usb_dev_handle *) d->handle,
65                         r, index, address, packet, data
66                 );
67                 data += packet;
68                 address += packet;
69                 length -= packet;
70                 g->value_add(g->bar, g->label, packet);
71         }
72         if(length != 0){
73                 device_read(
74                         (usb_dev_handle *) d->handle, 
75                         r, index, address, length, data
76                 );
77                 g->value_add(g->bar, g->label, packet);
78         }
79 }
80 static void kazzo_cpu_read(const struct reader_handle *d, const struct gauge *g, long address, long length, uint8_t *data)
81 {
82         read_main(d, g, REQUEST_CPU_READ, INDEX_IMPLIED, address, length, data);
83 //      read_main(REQUEST_CPU_READ_6502, address, length, data);
84 }
85 static void kazzo_ppu_read(const struct reader_handle *d, const struct gauge *g, long address, long length, uint8_t *data)
86 {
87         read_main(d, g, REQUEST_PPU_READ, INDEX_IMPLIED, address, length, data);
88 }
89 //-------- write sequence --------
90 /*
91 When host send data that contains 0xff many times, v-usb losts some 
92 bits. To prevent losting bits, mask data xor 0xa5;
93 */
94 static void device_write(usb_dev_handle *handle, enum request w, enum index index, long address, long length, const uint8_t *data)
95 {
96         uint8_t *d = Malloc(length);
97         int i;
98         memcpy(d, data, length);
99         for(i = 0; i < length; i++){
100                 d[i] ^= 0xa5;
101         }
102         int cnt = usb_control_msg(
103                 handle, 
104                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
105                 w, address, 
106                 index, (char *) d, length, TIMEOUT
107         );
108         if(cnt != length){
109                 puts(__FUNCTION__);
110                 puts(usb_strerror());
111                 exit(1);
112         }
113         Free(d);
114 }
115
116 static void kazzo_init(const struct reader_handle *d)
117 {
118         device_write((usb_dev_handle *) d->handle, REQUEST_PHI2_INIT, INDEX_IMPLIED, 0, 0, NULL);
119 }
120
121 static void write_memory(const struct reader_handle *d, enum request r, long address, long length, const uint8_t *data)
122 {
123         while(length != 0){
124                 long l = length >= FLASH_PACKET_SIZE ? FLASH_PACKET_SIZE : length;
125                 device_write((usb_dev_handle *) d->handle, r, INDEX_IMPLIED, address, l, data);
126                 address += l;
127                 data += l;
128                 length -= l;
129         }
130 }
131 static void kazzo_cpu_write_6502(const struct reader_handle *d, long address, long length, const uint8_t *data)
132 {
133         write_memory(d, REQUEST_CPU_WRITE_6502, address, length, data);
134 }
135
136 static void kazzo_ppu_write(const struct reader_handle *d, long address, long length, const uint8_t *data)
137 {
138         write_memory(d, REQUEST_PPU_WRITE, address, length, data);
139 }
140
141 static inline void pack_short_le(long l, uint8_t *t)
142 {
143         t[0] = l & 0xff;
144         t[1] = (l >> 8) & 0xff;
145 }
146 static void flash_config(const struct reader_handle *d, enum request r, enum index index, long c000x, long c2aaa, long c5555, long unit, bool retry)
147 {
148         const int size = 2 * 4 + 1;
149         uint8_t buf[size];
150         uint8_t *t = buf;
151         assert(unit >= 1 && unit < 0x400);
152         pack_short_le(c000x, t);
153         t += sizeof(uint16_t);
154         pack_short_le(c2aaa, t);
155         t += sizeof(uint16_t);
156         pack_short_le(c5555, t);
157         t += sizeof(uint16_t);
158         pack_short_le(unit, t);
159         t += sizeof(uint16_t);
160         *t = retry == true ? 1 : 0;
161         device_write((usb_dev_handle *) d->handle, r, index, 0, size, buf);
162 }
163 static void kazzo_cpu_flash_config(const struct reader_handle *d, long c000x, long c2aaa, long c5555, long unit, bool retry)
164 {
165         flash_config(d, REQUEST_FLASH_CONFIG_SET, INDEX_CPU, c000x, c2aaa, c5555, unit, retry);
166 }
167 static void kazzo_ppu_flash_config(const struct reader_handle *d, long c000x, long c2aaa, long c5555, long unit, bool retry)
168 {
169         flash_config(d, REQUEST_FLASH_CONFIG_SET, INDEX_PPU, c000x, c2aaa, c5555, unit, retry);
170 }
171
172 static inline void flash_execute(const struct reader_handle *d, enum request p, enum request s, enum index index, long address, const uint8_t *data, int size, bool dowait, bool skip)
173 {
174         uint8_t status;
175         int filled = 1;
176         if(skip == true){
177                 uint8_t *filldata = Malloc(size);
178                 memset(filldata, 0xff, size);
179                 filled = memcmp(filldata, data, size);
180                 if(0){ //nesasm fill 0 to unused area. When this routine is enabled, programming will speed up and compare mode will not work.
181                         memset(filldata, 0, size);
182                         filled &= memcmp(filldata, data, size);
183                 }
184                 Free(filldata);
185         }
186         if(filled != 0){
187                 device_write((usb_dev_handle *) d->handle, p, index, address, size, data);
188         }
189         if(dowait == true){
190                 do{
191                         wait(10);
192                         device_read((usb_dev_handle *) d->handle, s, index, 0, 1, &status);
193                 }while(status != KAZZO_TASK_FLASH_IDLE);
194         }
195 }
196 static void kazzo_cpu_flash_erase(const struct reader_handle *d, long address, bool dowait)
197 {
198         flash_execute(d, REQUEST_FLASH_ERASE, REQUEST_FLASH_STATUS, INDEX_CPU, address, NULL, 0, dowait, false);
199 }
200 static void kazzo_ppu_flash_erase(const struct reader_handle *d, long address, bool dowait)
201 {
202         flash_execute(d, REQUEST_FLASH_ERASE, REQUEST_FLASH_STATUS, INDEX_PPU, address, NULL, 0, dowait, false);
203 }
204
205 static void dump(const uint8_t *w, const uint8_t *r, long length)
206 {
207         while(length != 0){
208                 if(memcmp(r, w, 0x10) != 0){
209                         int i;
210                         printf("* ");
211                         for(i = 0; i < 0x10; i+=4){
212                                 printf("%02x %02x %02x %02x-", w[i], w[i+1], w[i+2], w[i+3]);
213                         }
214                         puts("");
215                         printf("  ");
216                         for(i = 0; i < 0x10; i+=4){
217                                 printf("%02x %02x %02x %02x-", r[i], r[i+1], r[i+2], r[i+3]);
218                         }
219                         puts("");
220                 }
221                 w += 0x10;
222                 r += 0x10;
223                 length -= 0x10;
224         }
225 }
226 static long flash_program(const struct reader_handle *h, const struct gauge *g, enum index index, long address, long length, const uint8_t *data, bool dowait, bool skip)
227 {
228         enum request p = REQUEST_FLASH_PROGRAM;
229         enum request s = REQUEST_FLASH_STATUS;
230         if(dowait == false){
231                 flash_execute(h, p, s, index, address, data, FLASH_PACKET_SIZE, dowait, skip);
232                 g->value_add(g->bar, g->label, FLASH_PACKET_SIZE);
233                 return FLASH_PACKET_SIZE;
234         }
235         long count = 0;
236         uint8_t *d = Malloc(FLASH_PACKET_SIZE);
237         while(length >= FLASH_PACKET_SIZE){
238                 flash_execute(h, p, s, index, address, data, FLASH_PACKET_SIZE, dowait, skip);
239                 if(0){
240                         //device_read(handle, REQUEST_FLASH_BUFFER_GET, index, 0, FLASH_PACKET_SIZE, d);
241                         if(memcmp(d, data, FLASH_PACKET_SIZE) != 0){
242                                 puts("packet send error");
243                                 dump(data, d, FLASH_PACKET_SIZE);
244                         }
245                 }
246                 g->value_add(g->bar, g->label, FLASH_PACKET_SIZE);
247                 address += FLASH_PACKET_SIZE;
248                 data += FLASH_PACKET_SIZE;
249                 count += FLASH_PACKET_SIZE;
250                 length -= FLASH_PACKET_SIZE;
251         }
252         Free(d);
253         return count;
254 }
255 static long kazzo_cpu_flash_program(const struct reader_handle *d, const struct gauge *g, long address, long length, const uint8_t *data, bool dowait, bool skip)
256 {
257         return flash_program(d, g, INDEX_CPU, address, length, data, dowait, skip);
258 }
259 static long kazzo_ppu_flash_program(const struct reader_handle *d, const struct gauge *g, long address, long length, const uint8_t *data, bool dowait, bool skip)
260 {
261         return flash_program(d, g, INDEX_PPU, address, length, data, dowait, skip);
262 }
263
264 static void kazzo_flash_status(const struct reader_handle *d, uint8_t s[2])
265 {
266         read_main(d, &GAUGE_DUMMY, REQUEST_FLASH_STATUS, INDEX_BOTH, 0, 2, s);
267 }
268 static void kazzo_cpu_flash_device_get(const struct reader_handle *d, uint8_t s[2])
269 {
270         read_main(d, &GAUGE_DUMMY, REQUEST_FLASH_DEVICE, INDEX_CPU, 0, 2, s);
271 }
272 static void kazzo_ppu_flash_device_get(const struct reader_handle *d, uint8_t s[2])
273 {
274         read_main(d, &GAUGE_DUMMY, REQUEST_FLASH_DEVICE, INDEX_PPU, 0, 2, s);
275 }
276 static uint8_t kazzo_vram_connection(const struct reader_handle *d)
277 {
278         uint8_t s;
279         read_main(d, &GAUGE_DUMMY, REQUEST_VRAM_CONNECTION, INDEX_IMPLIED, 0, 1, &s);
280         return s;
281 }
282 const struct reader_driver DRIVER_KAZZO = {
283         .cpu = {
284                 .memory_read = kazzo_cpu_read, 
285                 .memory_write = kazzo_cpu_write_6502,
286                 .flash_config = kazzo_cpu_flash_config,
287                 .flash_erase = kazzo_cpu_flash_erase,
288                 .flash_program = kazzo_cpu_flash_program,
289                 .flash_device_get = kazzo_cpu_flash_device_get
290         }, .ppu = {
291                 .memory_read = kazzo_ppu_read,
292                 .memory_write = kazzo_ppu_write,
293                 .flash_config = kazzo_ppu_flash_config,
294                 .flash_erase = kazzo_ppu_flash_erase,
295                 .flash_program = kazzo_ppu_flash_program,
296                 .flash_device_get = kazzo_ppu_flash_device_get
297         }, .control  = {
298                 .name = "kazzo",
299                 .open = kazzo_open, .close = kazzo_close,
300                 .init = kazzo_init,
301                 .flash_status = kazzo_flash_status,
302                 .vram_connection = kazzo_vram_connection
303         }
304 };