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