]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - sw/app/rocon/appl_usb.c
IRC coprocesor, change to generic, index to user, usb commands update
[fpga/lx-cpu1/lx-rocon.git] / sw / app / rocon / appl_usb.c
1 #include <types.h>
2 #include <cpu_def.h>
3 #include <system_def.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <endian.h>
7 #include <usb/lpc.h>
8 #include <usb/usb.h>
9 #include <usb/usb_loader.h>
10 #include <usb/usbdebug.h>
11 #include <cmd_proc.h>
12 #include <hal_gpio.h>
13
14 #include "appl_defs.h"
15 #include "usb/usb_defs.h"
16 #include "appl_fpga.h"
17
18 #ifdef CONFIG_KEYVAL
19 #include <keyvalpb.h>
20 #include <lpciap.h>
21 #include <lpciap_kvpb.h>
22 #include <hal_machperiph.h>
23 #endif /*CONFIG_KEYVAL*/
24
25 #include <endian.h>
26 #if __BYTE_ORDER == __BIG_ENDIAN
27 #include <byteswap.h>
28 #define SWAP(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
29 #else /*__LITTLE_ENDIAN*/
30 #define SWAP(x) (x)
31 #endif
32
33 #define USB_VENDOR_TARGET_TUMBL        0x03
34
35 #define USB_CMD_FPGA_CONFIGURE         0xF000
36 #define USB_CMD_FPGA_MEASURE_READ      0xF001
37 #define USB_CMD_FPGA_MEASURE_WRITE     0xF002
38
39 #define USB_CMD_FPGA_IRC_SET_RESET     0xF010
40 #define USB_CMD_FPGA_IRC_DUMP          0xF011
41
42 #define USB_CMD_FPGA_TUMBL_SET_RESET   0xF100
43 #define USB_CMD_FPGA_TUMBL_SET_HALT    0xF101
44 #define USB_CMD_FPGA_TUMBL_SET_TRACE   0xF102
45 #define USB_CMD_FPGA_TUMBL_KICK_TRACE  0xF103
46 #define USB_CMD_FPGA_TUMBL_GET_PC      0xF104
47
48 #define USB_CMD_FPGA_TUMBL_DUMP_IMEM   0xF200
49 #define USB_CMD_FPGA_TUMBL_DUMP_DMEM   0xF201
50
51 #define USB_CMD_FPGA_RESET             0xFFFF
52
53 usb_device_t usb_device;
54 usb_ep_t eps[NUM_ENDPOINTS];
55
56 #define MASK_EP1RX 0x01
57 #define MASK_EP1TX 0x02
58
59 unsigned char ep1_rx_buff[USB_MAX_PACKET];
60 unsigned char ep1_tx_buff[USB_MAX_PACKET];
61 unsigned char ep0_buffer[USB_MAX_PACKET0];
62 int usb_active = 0;
63 int ep1_rx_index = 0, ep1_rx_ready = 1;
64 int ep1_tx_index = 0, ep1_tx_chars = 0;
65
66 #ifdef CONFIG_OC_CMDPROC
67
68 cmd_io_t cmd_io_usbcon_dev;
69
70 #define ED_LINE_CHARS 512
71
72 char ed_line_chars_usbcon_in[ED_LINE_CHARS + 1];
73 char ed_line_chars_usbcon_out[ED_LINE_CHARS + 1];
74
75 ed_line_buf_t ed_line_buf_usbcon_in =
76 {
77 flg:
78   FL_ELB_ECHO,
79   inbuf: 0,
80 alloc:
81   sizeof(ed_line_chars_usbcon_in),
82   maxlen: 0,
83   lastch: 0,
84 buf:
85   ed_line_chars_usbcon_in
86 };
87
88 ed_line_buf_t ed_line_buf_usbcon_out =
89 {
90 flg:
91   FL_ELB_NOCRLF,
92   inbuf: 0,
93 alloc:
94   sizeof(ed_line_chars_usbcon_out),
95   maxlen: 0,
96   lastch: 0,
97 buf:
98   ed_line_chars_usbcon_out
99 };
100
101 cmd_io_t cmd_io_usbcon =
102 {
103 putc:
104   cmd_io_line_putc,
105 getc:
106   NULL,
107 write:
108   cmd_io_write_bychar,
109 read:
110   NULL,
111 priv:
112   {
113   ed_line:
114     {
115     in:
116       &ed_line_buf_usbcon_in,
117     out:
118       &ed_line_buf_usbcon_out,
119     io_stack:
120       &cmd_io_usbcon_dev
121     }
122   }
123 };
124
125 #endif
126
127 static int usb_flash_pkt_wr(struct usb_ep_t *ep, int len, int code)
128 {
129   unsigned char *ptr = ep->ptr - len;
130
131 #ifdef CONFIG_KEYVAL
132   lpcisp_kvpb_copy(NULL, (void *)ep->user_data, ptr, len);
133 #endif /*CONFIG_KEYVAL*/
134
135   ep->user_data += len;
136   ep->ptr = ep0_buffer;
137   return USB_COMPLETE_OK;
138 }
139
140 static int usb_tumbl_pkt_wr(struct usb_ep_t *ep, int len, int code)
141 {
142   unsigned char *ptr = ep->ptr - len;
143   
144   appl_fpga_tumbl_write(ep->user_data, ptr, len);
145   
146   ep->user_data += len;
147   ep->ptr = ep0_buffer;
148   return USB_COMPLETE_OK;
149 }
150
151 static int usb_flash_erase(unsigned addr, unsigned len)
152 {
153 #ifdef CONFIG_KEYVAL
154   lpcisp_erase((void *)addr, len);
155 #endif /*CONFIG_KEYVAL*/
156   return 0;
157 }
158
159 static void usb_goto(unsigned address)
160 {
161 #ifdef CONFIG_KEYVAL
162   lpc_watchdog_init(1, 10);
163   lpc_watchdog_feed();
164
165   while (1)
166     {}
167
168 #endif /*CONFIG_KEYVAL*/
169 }
170
171 /* Not re-entrant */
172 uint16_t vendor_call_ret = 0xFFFF;
173
174 uint16_t appl_usb_vendor_call(uint16_t command, uint16_t argument)
175 {
176   int i, j;
177   
178   switch (command)
179   {
180     case USB_CMD_FPGA_CONFIGURE:
181       return appl_fpga_configure();
182
183     case USB_CMD_FPGA_MEASURE_READ:
184       return appl_fpga_measure_bus_read();
185
186     case USB_CMD_FPGA_MEASURE_WRITE:
187       return appl_fpga_measure_bus_write();
188
189     case USB_CMD_FPGA_IRC_SET_RESET:
190       /* When starting, zero out counters */
191       *irc_reset = argument & 0x0001;
192       return 0;
193
194     case USB_CMD_FPGA_IRC_DUMP:
195       printf("IRC1: count = %d, count index = %d, state = 0x%02x\n", (unsigned int) irc1->count, (unsigned int) irc1->count_index, (unsigned int)(*irc1_state));
196       printf("IRC2: count = %d, count index = %d, state = 0x%02x\n", (unsigned int) irc2->count, (unsigned int) irc2->count_index, (unsigned int)(*irc2_state));
197       printf("IRC3: count = %d, count index = %d, state = 0x%02x\n", (unsigned int) irc3->count, (unsigned int) irc3->count_index, (unsigned int)(*irc3_state));
198       printf("IRC4: count = %d, count index = %d, state = 0x%02x\n", (unsigned int) irc4->count, (unsigned int) irc4->count_index, (unsigned int)(*irc4_state));
199       return 0;
200       return 0;
201
202     case USB_CMD_FPGA_TUMBL_SET_RESET:
203       return appl_fpga_tumbl_set_reset(argument);
204     
205     case USB_CMD_FPGA_TUMBL_SET_HALT:
206       return appl_fpga_tumbl_set_halt(argument);
207     
208     case USB_CMD_FPGA_TUMBL_SET_TRACE:
209       return appl_fpga_tumbl_set_trace(argument);
210       
211     case USB_CMD_FPGA_TUMBL_KICK_TRACE:
212       return appl_fpga_tumbl_kick_trace();
213       
214     case USB_CMD_FPGA_TUMBL_GET_PC:
215       printf("Tubml PC: 0x%08X\n", (unsigned int) *tumbl_pc);
216       return 0;
217     
218     case USB_CMD_FPGA_TUMBL_DUMP_IMEM:
219       printf("TUMBL IMEM:\n");
220       for (i = 0; i < 64; i++)
221       {        
222         for (j = 0; j < 8; j++)
223           printf("%08X ", (unsigned int) tumbl_imem[i*8 + j]);
224           
225         printf("\n");
226       }
227       return 0;
228       
229     case USB_CMD_FPGA_TUMBL_DUMP_DMEM:
230       printf("TUMBL DMEM:\n");
231       for (i = 0; i < 128; i++)
232       {
233         for (j = 0; j < 8; j++)
234           printf("%08X ", (unsigned int) tumbl_dmem[i*8 + j]);
235           
236         printf("\n");
237       }
238       return 0;
239       
240     case USB_CMD_FPGA_RESET:
241       hal_gpio_direction_output(XC_INIT_PIN, 0);
242
243       for (i = 0; i < 128; i++)
244         {}
245
246       hal_gpio_direction_output(XC_INIT_PIN, 1);
247       return 0;
248   }
249
250   return 0xFFFF;
251 }
252
253 int appl_usb_vendor(usb_device_t *udev)
254 {
255   unsigned long addr;
256   unsigned len;
257   USB_DEVICE_REQUEST *dreq;
258
259   usb_active = 1;
260   dreq = &udev->request;
261
262 #ifdef CONFIG_KEYVAL
263
264   if (dreq->bRequest != (USB_VENDOR_GET_SET_MEMORY |
265                          USB_DATA_DIR_FROM_HOST | USB_VENDOR_TARGET_FLASH))
266     lpcisp_kvpb_flush(NULL);
267
268 #endif /*CONFIG_KEYVAL*/
269
270   switch (dreq->bRequest & USB_VENDOR_MASK)
271   {
272     case USB_VENDOR_GET_CAPABILITIES:
273       ep0_buffer[0] = 0xAA; // test
274       usb_send_control_data(udev, ep0_buffer, 1);
275       return 1;
276
277     case USB_VENDOR_RESET_DEVICE:
278       usb_send_control_data(udev, NULL, 0);
279 #ifdef CONFIG_KEYVAL
280       lpc_watchdog_init(1, 10);
281       lpc_watchdog_feed();
282
283       while (1)
284         {}
285
286 #endif /*CONFIG_KEYVAL*/
287       return 1;
288
289     case USB_VENDOR_GOTO:
290       usb_send_control_data(udev, NULL, 0);
291       usb_goto(dreq->wValue);
292       return 1;
293
294     case USB_VENDOR_ERASE_MEMORY:
295       usb_send_control_data(udev, NULL, 0);
296       usb_flash_erase(dreq->wValue, dreq->wIndex);
297       return 1;
298
299     case USB_VENDOR_ERASE_1KB_MEMORY:  /* erase memory for 1 KB */
300       usb_send_control_data(udev, NULL, 0);
301       usb_flash_erase((uint32_t)dreq->wValue << 10, dreq->wIndex << 10);
302       return 1;
303
304     case USB_VENDOR_CALL:
305       vendor_call_ret = SWAP(appl_usb_vendor_call(dreq->wIndex, dreq->wValue));
306       usb_send_control_data(udev, (unsigned char *) &vendor_call_ret, sizeof(uint16_t));
307       return 1;
308
309     case USB_VENDOR_GET_SET_MEMORY:
310       addr = (dreq->wValue & 0xffff) | (((unsigned long)dreq->wIndex & 0xffff) << 16);
311       len = dreq->wLength;
312
313       if ((dreq->bmRequestType & USB_DATA_DIR_MASK) == USB_DATA_DIR_FROM_HOST)
314       {
315         switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
316         {
317           case USB_VENDOR_TARGET_RAM:
318             udev->ep0.ptr = (void *)addr;
319             break;
320
321           case USB_VENDOR_TARGET_FLASH:
322             udev->ep0.next_pkt_fnc = usb_flash_pkt_wr;
323             udev->ep0.user_data = addr;
324             udev->ep0.ptr = ep0_buffer;
325             break;
326             
327           case USB_VENDOR_TARGET_TUMBL:
328             udev->ep0.next_pkt_fnc = usb_tumbl_pkt_wr;
329             udev->ep0.user_data = addr;
330             udev->ep0.ptr = ep0_buffer;
331             break;
332
333           default:
334             return -1;
335         }
336
337         if (len)
338           usb_set_control_endfnc(udev, usb_ack_setup);
339         else
340           usb_send_control_data(udev, NULL, 0);
341
342         return 1;
343       }
344       else
345       {
346         switch (dreq->bRequest & USB_VENDOR_TARGET_MASK)
347         {
348           case USB_VENDOR_TARGET_RAM:
349             usb_send_control_data(udev, (void *)addr, len);
350             break;
351
352           default:
353             return -1;
354         }
355
356         return 1;
357       }
358
359       break;
360   }
361
362   return 0;
363 }
364
365 int usb_app_fill_serial_number(uint32_t ul_sn)
366 {
367   char *p = usb_devdes_serial_number;
368   int len_max = sizeof(usb_devdes_serial_number);
369   char c;
370
371   while ((len_max -= 2) >= 2)
372   {
373     p += 2;
374     c = ((ul_sn >> (32 - 4)) & 0xf) + '0';
375     ul_sn <<= 4;
376
377     if (c > '9')
378       c += 'A' - '9' - 1;
379
380     *p = c;
381   }
382
383   return 0;
384 }
385
386 int usb_app_init(void)
387 {
388   memset(&usb_device, 0, sizeof(usb_device));
389
390   eps[0].max_packet_size = USB_MAX_PACKET;
391   eps[1].max_packet_size = USB_MAX_PACKET;
392   eps[0].epnum = 0x81;
393   eps[1].epnum = 0x01;
394   eps[0].event_mask = 0x08;
395   eps[1].event_mask = 0x04;
396   eps[0].udev = &usb_device;
397   eps[1].udev = &usb_device;
398
399   usb_device.id = 1;
400   usb_device.devdes_table = &usb_devdes_table;
401   usb_device.init = usb_lpc_init;
402   usb_debug_set_level(DEBUG_LEVEL_NONE);
403   usb_device.cntep = NUM_ENDPOINTS;
404   usb_device.ep = eps;
405   usb_device.vendor_fnc = appl_usb_vendor;
406
407   usb_init(&usb_device);
408   usb_connect(&usb_device);
409
410   return 0;
411 }
412
413 int usb_check_ep1()
414 {
415   if (usb_device.ep_events & MASK_EP1RX)
416   {
417     usb_device.ep_events &= ~MASK_EP1RX;
418     //TODO: Use some field in the structure, probably flags
419     ep1_rx_ready = 1;
420   }
421
422   /* Respond if there is something to send and RX is ready */
423   if (ep1_rx_ready && ep1_rx_index != 0)
424   {
425     usb_udev_write_endpoint(&eps[0], ep1_rx_buff, ep1_rx_index);
426     ep1_rx_index = 0;
427     ep1_rx_ready = 0;
428     hal_gpio_set_value(LED2_PIN, 0);
429     return 1;
430   }
431
432   return 0;
433 }
434
435 int usb_app_poll(void)
436 {
437   int active = usb_active;
438   usb_active = 0;
439
440   usb_check_events(&usb_device);
441   usb_control_response(&usb_device);
442
443   /* Check TX endpoint */
444   if (usb_device.ep_events & MASK_EP1TX)
445   {
446     ep1_tx_chars = usb_udev_read_endpoint(&eps[1], ep1_tx_buff, USB_MAX_PACKET);
447     ep1_tx_index = 0;
448     usb_device.ep_events &= ~MASK_EP1TX;
449     hal_gpio_set_value(LED2_PIN, 0);
450     usb_active = 1;
451   }
452
453   /* Check RX endpoint */
454   usb_active |= usb_check_ep1();
455
456   return active;
457 }
458
459 int usb_app_stop(void)
460 {
461   usb_disconnect(&usb_device);
462   return 0;
463 }
464
465 #ifdef CONFIG_OC_CMDPROC
466
467 int cmd_io_getc_usbcon(struct cmd_io *cmd_io)
468 {
469   if (ep1_tx_index >= ep1_tx_chars)
470     return -1;
471
472   return ep1_tx_buff[ep1_tx_index++];
473 }
474
475 int cmd_io_putc_usbcon(struct cmd_io *cmd_io, int ch)
476 {
477   if (ep1_rx_index >= USB_MAX_PACKET)
478   {
479     /* Check EP1 status and return -1 if unavailable */
480     usb_check_events(&usb_device);
481     usb_check_ep1();
482
483     /* Check again if it wasn't emptied */
484     if (ep1_rx_index >= USB_MAX_PACKET)
485       return -1;
486   }
487
488   ep1_rx_buff[ep1_rx_index++] = (unsigned char)ch;
489   return ch;
490 }
491
492 cmd_io_t cmd_io_usbcon_dev =
493 {
494   .putc = cmd_io_putc_usbcon,
495   .getc = cmd_io_getc_usbcon,
496   .write = cmd_io_write_bychar,
497   .read = cmd_io_read_bychar,
498   .priv.uart = { -1 }
499 };
500
501 #endif