OSDN Git Service

c64894ac4f4e785f010af18a13dbdecc67f4636b
[unagi/old-svn-converted.git] / client / tag / 0.6.2 / 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
12 static usb_dev_handle *device_open(void)
13 {
14         usb_dev_handle *handle = NULL;
15         const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID};
16         const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
17         char vendor[] = {USB_CFG_VENDOR_NAME, 0};
18         char product[] = {USB_CFG_DEVICE_NAME, 0};
19         int vid, pid;
20
21         /* compute VID/PID from usbconfig.h so that there is a central source of information */
22         vid = (rawVid[1] << 8) | rawVid[0];
23         pid = (rawPid[1] << 8) | rawPid[0];
24
25         if(usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) == 0){
26                 return handle;
27         }
28         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
29         return NULL;
30 }
31 static usb_dev_handle *handle = NULL;
32 static int kazzo_open_close(enum reader_control oc)
33 {
34         switch(oc){
35         case READER_OPEN:
36                 handle = device_open();
37                 return handle == NULL ? NG : OK;
38         case READER_CLOSE:
39                 usb_close(handle);
40                 handle = NULL;
41                 return OK;
42         }
43         return NG;
44 }
45 enum{
46         TIMEOUT = 4000
47 };
48 //-------- read sequence --------
49 static void device_read(usb_dev_handle *handle, enum request r, enum index index, long address, long length, uint8_t *data)
50 {
51         int cnt = usb_control_msg(
52                 handle, 
53                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, 
54                 r, address, 
55                 index, (char *) data, length, TIMEOUT
56         );
57         if(cnt != length){
58                 puts(__FUNCTION__);
59                 puts(usb_strerror());
60                 exit(1);
61         }
62 }
63 static void read_main(const enum request r, enum index index, long address, long length, uint8_t *data)
64 {
65         const int packet = READ_PACKET_SIZE;
66         while(length >= packet){
67                 device_read(handle, r, index, address, packet, data);
68                 data += packet;
69                 address += packet;
70                 length -= packet;
71         }
72         if(length != 0){
73                 device_read(handle, r, index, address, length, data);
74         }
75 }
76 static void kazzo_cpu_read(long address, long length, uint8_t *data)
77 {
78         read_main(REQUEST_CPU_READ, INDEX_IMPLIED, address, length, data);
79 //      read_main(REQUEST_CPU_READ_6502, address, length, data);
80 }
81 static void kazzo_ppu_read(long address, long length, uint8_t *data)
82 {
83         read_main(REQUEST_PPU_READ, INDEX_IMPLIED, address, length, data);
84 }
85 //-------- write sequence --------
86 /*
87 When host send data that contains 0xff many times, v-usb losts some 
88 bits. To prevent losting bits, mask data xor 0xa5;
89 */
90 static void device_write(usb_dev_handle *handle, enum request w, enum index index, long address, long length, const uint8_t *data)
91 {
92         uint8_t *d = Malloc(length);
93         int i;
94         memcpy(d, data, length);
95         for(i = 0; i < length; i++){
96                 d[i] ^= 0xa5;
97         }
98         int cnt = usb_control_msg(
99                 handle, 
100                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
101                 w, address, 
102                 index, (char *) d, length, TIMEOUT
103         );
104         if(cnt != length){
105                 puts(__FUNCTION__);
106                 puts(usb_strerror());
107                 exit(1);
108         }
109         Free(d);
110 }
111
112 static void kazzo_init(void)
113 {
114         device_write(handle, REQUEST_PHI2_INIT, INDEX_IMPLIED, 0, 0, NULL);
115 }
116
117 static void write_memory(enum request r, long address, long length, const uint8_t *data)
118 {
119         while(length != 0){
120                 long l = length >= FLASH_PACKET_SIZE ? FLASH_PACKET_SIZE : length;
121                 device_write(handle, r, INDEX_IMPLIED, address, l, data);
122                 address += l;
123                 data += l;
124                 length -= l;
125         }
126 }
127 static void kazzo_cpu_write_6502(long address, long length, const uint8_t *data)
128 {
129         write_memory(REQUEST_CPU_WRITE_6502, address, length, data);
130 }
131 /*static void kazzo_cpu_write_flash(long address, long data)
132 {
133         uint8_t d = (uint8_t) (data & 0xff);
134         device_write(handle, REQUEST_CPU_WRITE_FLASH, address, 1, &d);
135 }*/
136 static void kazzo_ppu_write(long address, long length, const uint8_t *data)
137 {
138         write_memory(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(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(handle, r, index, 0, size, buf);
162 }
163 static void kazzo_cpu_flash_config(long c000x, long c2aaa, long c5555, long unit, bool retry)
164 {
165         flash_config(REQUEST_FLASH_CONFIG_SET, INDEX_CPU, c000x, c2aaa, c5555, unit, retry);
166 }
167 static void kazzo_ppu_flash_config(long c000x, long c2aaa, long c5555, long unit, bool retry)
168 {
169         flash_config(REQUEST_FLASH_CONFIG_SET, INDEX_PPU, c000x, c2aaa, c5555, unit, retry);
170 }
171
172 static inline void flash_execute(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(handle, p, index, address, size, data);
188         }
189         if(dowait == true){
190                 do{
191                         wait(10);
192                         device_read(handle, s, index, 0, 1, &status);
193                 }while(status != KAZZO_TASK_FLASH_IDLE);
194         }
195 }
196 static void kazzo_cpu_flash_erase(long address, bool dowait)
197 {
198         flash_execute(REQUEST_FLASH_ERASE, REQUEST_FLASH_STATUS, INDEX_CPU, address, NULL, 0, dowait, false);
199 }
200 static void kazzo_ppu_flash_erase(long address, bool dowait)
201 {
202         flash_execute(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(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(p, s, index, address, data, FLASH_PACKET_SIZE, dowait, skip);
232                 return FLASH_PACKET_SIZE;
233         }
234         long count = 0;
235         uint8_t *d = Malloc(FLASH_PACKET_SIZE);
236         while(length >= FLASH_PACKET_SIZE){
237                 flash_execute(p, s, index, address, data, FLASH_PACKET_SIZE, dowait, skip);
238                 if(0){
239                         //device_read(handle, REQUEST_FLASH_BUFFER_GET, index, 0, FLASH_PACKET_SIZE, d);
240                         if(memcmp(d, data, FLASH_PACKET_SIZE) != 0){
241                                 puts("packet send error");
242                                 dump(data, d, FLASH_PACKET_SIZE);
243                         }
244                 }
245                 address += FLASH_PACKET_SIZE;
246                 data += FLASH_PACKET_SIZE;
247                 count += FLASH_PACKET_SIZE;
248                 length -= FLASH_PACKET_SIZE;
249         }
250         Free(d);
251         return count;
252 }
253 static long kazzo_cpu_flash_program(long address, long length, const uint8_t *data, bool dowait, bool skip)
254 {
255         return flash_program(INDEX_CPU, address, length, data, dowait, skip);
256 }
257 static long kazzo_ppu_flash_program(long address, long length, const uint8_t *data, bool dowait, bool skip)
258 {
259         return flash_program(INDEX_PPU, address, length, data, dowait, skip);
260 }
261
262 static void kazzo_flash_status(uint8_t s[2])
263 {
264         read_main(REQUEST_FLASH_STATUS, INDEX_BOTH, 0, 2, s);
265 }
266 static void kazzo_cpu_flash_device_get(uint8_t s[2])
267 {
268         read_main(REQUEST_FLASH_DEVICE, INDEX_CPU, 0, 2, s);
269 }
270 static void kazzo_ppu_flash_device_get(uint8_t s[2])
271 {
272         read_main(REQUEST_FLASH_DEVICE, INDEX_PPU, 0, 2, s);
273 }
274 static uint8_t kazzo_vram_connection(void)
275 {
276         uint8_t s;
277         read_main(REQUEST_VRAM_CONNECTION, INDEX_IMPLIED, 0, 1, &s);
278         return s;
279 }
280 const struct reader_driver DRIVER_KAZZO = {
281         .name = "kazzo",
282         .open_or_close = kazzo_open_close,
283         .init = kazzo_init,
284         .cpu_read = kazzo_cpu_read, .ppu_read = kazzo_ppu_read,
285         .cpu_write_6502 = kazzo_cpu_write_6502,
286         .flash_support = true,
287         .ppu_write = kazzo_ppu_write,
288         .cpu_flash_config = kazzo_cpu_flash_config,
289         .cpu_flash_erase = kazzo_cpu_flash_erase,
290         .cpu_flash_program = kazzo_cpu_flash_program,
291         .cpu_flash_device_get = kazzo_cpu_flash_device_get,
292         .ppu_flash_config = kazzo_ppu_flash_config,
293         .ppu_flash_erase = kazzo_ppu_flash_erase,
294         .ppu_flash_program = kazzo_ppu_flash_program,
295         .ppu_flash_device_get = kazzo_ppu_flash_device_get,
296         .flash_status = kazzo_flash_status,
297         .vram_connection = kazzo_vram_connection
298 };