blob: 34c5db1faa896e7971cb86e98aa9b5f6796dd9b3 [file] [log] [blame]
Maurus Cuelenaere95167e02008-04-24 20:08:28 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Tomasz Malesinski
11 * Copyright (C) 2008 by Maurus Cuelenaere
12 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000013 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
Maurus Cuelenaere95167e02008-04-24 20:08:28 +000017 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
Maurus Cuelenaere95167e02008-04-24 20:08:28 +000024#include "usb_ch9.h"
25#include "usb_drv.h"
26#include "usb_core.h"
27#include "isp1583.h"
28#include "thread.h"
Maurus Cuelenaere88455332008-04-24 21:07:43 +000029#include "logf.h"
Maurus Cuelenaereed5f1ed2008-05-03 14:43:43 +000030#include <stdio.h>
Maurus Cuelenaere95167e02008-04-24 20:08:28 +000031
32#define DIR_RX 0
33#define DIR_TX 1
Maurus Cuelenaere95167e02008-04-24 20:08:28 +000034
35struct usb_endpoint
36{
37 unsigned char *out_buf;
38 short out_len;
39 short out_ptr;
40 void (*out_done)(int, unsigned char *, int);
41 unsigned char out_in_progress;
42
43 unsigned char *in_buf;
44 short in_min_len;
45 short in_max_len;
46 short in_ptr;
47 void (*in_done)(int, unsigned char *, int);
48 unsigned char in_ack;
49
50 unsigned char halt[2];
51 unsigned char enabled[2];
52 short max_pkt_size[2];
53 short type;
54};
55
56static unsigned char setup_pkt_buf[8];
57static struct usb_endpoint endpoints[NUM_ENDPOINTS];
58
59static bool high_speed_mode = false;
60
61static inline void or_int_value(volatile unsigned short *a, volatile unsigned short *b, unsigned long r, unsigned long value)
62{
63 set_int_value(*a, *b, (r | value));
64}
65static inline void bc_int_value(volatile unsigned short *a, volatile unsigned short *b, unsigned long r, unsigned long value)
66{
67 set_int_value(*a, *b, (r & ~value));
68}
69
70static inline void nop_f(void)
71{
72 yield();
73}
74
75#define NOP asm volatile("nop\n");
76
77static inline int ep_index(int n, bool dir)
78{
79 return (n << 1) | dir;
80}
81
82static inline bool epidx_dir(int idx)
83{
84 return idx & 1;
85}
86
87static inline int epidx_n(int idx)
88{
89 return idx >> 1;
90}
91
92static inline void usb_select_endpoint(int idx)
93{
94 /* Select the endpoint */
95 ISP1583_DFLOW_EPINDEX = idx;
96 /* The delay time from the Write Endpoint Index register to the Read Data Port register must be at least 190 ns.
97 * The delay time from the Write Endpoint Index register to the Write Data Port register must be at least 100 ns.
98 */
99 NOP;
100}
101
102static inline void usb_select_setup_endpoint(void)
103{
104 /* Select the endpoint */
105 ISP1583_DFLOW_EPINDEX = DFLOW_EPINDEX_EP0SETUP;
106 /* The delay time from the Write Endpoint Index register to the Read Data Port register must be at least 190 ns.
107 * The delay time from the Write Endpoint Index register to the Write Data Port register must be at least 100 ns.
108 */
109 NOP;
110}
111
112static void usb_setup_endpoint(int idx, int max_pkt_size, int type)
113{
114 if(epidx_n(idx)!=0)
115 {
116 usb_select_endpoint(idx);
117 ISP1583_DFLOW_MAXPKSZ = max_pkt_size & 0x7FF;
118 ISP1583_DFLOW_EPTYPE = (DFLOW_EPTYPE_NOEMPKT | DFLOW_EPTYPE_DBLBUF | (type & 0x3));
119
120 /* clear buffer ... */
121 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_CLBUF;
122 /* ... twice because of double buffering */
123 usb_select_endpoint(idx);
124 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_CLBUF;
125 }
126
127 struct usb_endpoint *ep;
128 ep = &(endpoints[epidx_n(idx)]);
129 ep->halt[epidx_dir(idx)] = 0;
130 ep->enabled[epidx_dir(idx)] = 0;
131 ep->out_in_progress = 0;
132 ep->in_min_len = -1;
133 ep->in_ack = 0;
134 ep->type = type;
135 ep->max_pkt_size[epidx_dir(idx)] = max_pkt_size;
136}
137
138static void usb_enable_endpoint(int idx)
139{
140 if(epidx_n(idx)!=0)
141 {
142 usb_select_endpoint(idx);
143 /* Enable interrupt */
144 or_int_value(&ISP1583_INIT_INTEN_A, &ISP1583_INIT_INTEN_B, ISP1583_INIT_INTEN_READ, 1 << (10 + idx));
145 /* Enable endpoint */
146 ISP1583_DFLOW_EPTYPE |= DFLOW_EPTYPE_ENABLE;
147 }
148
149 endpoints[epidx_n(idx)].enabled[epidx_dir(idx)] = 1;
150}
Maurus Cuelenaereed5f1ed2008-05-03 14:43:43 +0000151/*
Maurus Cuelenaere95167e02008-04-24 20:08:28 +0000152static void usb_disable_endpoint(int idx, bool set_struct)
153{
154 usb_select_endpoint(idx);
155 ISP1583_DFLOW_EPTYPE &= ~DFLOW_EPTYPE_ENABLE;
156 bc_int_value(&ISP1583_INIT_INTEN_A, &ISP1583_INIT_INTEN_B, ISP1583_INIT_INTEN_READ, 1 << (10 + idx));
157
158 if(set_struct)
159 endpoints[epidx_n(idx)].enabled[epidx_dir(idx)] = 0;
160}
Maurus Cuelenaereed5f1ed2008-05-03 14:43:43 +0000161*/
Maurus Cuelenaere95167e02008-04-24 20:08:28 +0000162static int usb_get_packet(unsigned char *buf, int max_len)
163{
164 int len, i;
165 len = ISP1583_DFLOW_BUFLEN;
166
167 if (max_len < 0 || max_len > len)
168 max_len = len;
169
170 i = 0;
171 while (i < len)
172 {
173 unsigned short d = ISP1583_DFLOW_DATA;
174 if (i < max_len)
175 buf[i] = d & 0xff;
176 i++;
177 if (i < max_len)
178 buf[i] = (d >> 8) & 0xff;
179 i++;
180 }
181 return max_len;
182}
183
184static int usb_receive(int n)
185{
186 logf("usb_receive(%d)", n);
187 int len;
188
189 if (endpoints[n].halt[DIR_RX]
190 || !endpoints[n].enabled[DIR_RX]
191 || endpoints[n].in_min_len < 0
192 || !endpoints[n].in_ack)
193 return -1;
194
195 endpoints[n].in_ack = 0;
196
197 usb_select_endpoint(ep_index(n, DIR_RX));
198
199 len = usb_get_packet(endpoints[n].in_buf + endpoints[n].in_ptr,
200 endpoints[n].in_max_len - endpoints[n].in_ptr);
201 endpoints[n].in_ptr += len;
202 if (endpoints[n].in_ptr >= endpoints[n].in_min_len) {
203 endpoints[n].in_min_len = -1;
204 if (endpoints[n].in_done)
205 (*(endpoints[n].in_done))(n, endpoints[n].in_buf,
206 endpoints[n].in_ptr);
207 }
208 logf("receive_end");
209 return 0;
210}
211
212static bool usb_out_buffer_full(int ep)
213{
214 usb_select_endpoint(ep_index(ep, DIR_TX));
215 if (ISP1583_DFLOW_EPTYPE & 4) /* Check if type=bulk and double buffering is set */
216 return (ISP1583_DFLOW_BUFSTAT & 3) == 3; /* Return true if both buffers are filled */
217 else
218 return (ISP1583_DFLOW_BUFSTAT & 3) != 0; /* Return true if one of the buffers are filled */
219}
220
221static int usb_send(int n)
222{
223 logf("usb_send(%d)", n);
224 int max_pkt_size, len;
225 int i;
226 unsigned char *p;
227
228 if (endpoints[n].halt[DIR_TX]
229 || !endpoints[n].enabled[DIR_TX]
230 || !endpoints[n].out_in_progress)
231 {
232 logf("NOT SEND TO EP!");
233 return -1;
234 }
235
236 if (endpoints[n].out_ptr < 0)
237 {
238 endpoints[n].out_in_progress = 0;
239 if (endpoints[n].out_done)
240 (*(endpoints[n].out_done))(n, endpoints[n].out_buf,
241 endpoints[n].out_len);
242 logf("ALREADY SENT TO EP!");
243 return -1;
244 }
245
246 if (usb_out_buffer_full(n))
247 {
248 logf("BUFFER FULL!");
249 return -1;
250 }
251
252 usb_select_endpoint(ep_index(n, DIR_TX));
253 max_pkt_size = endpoints[n].max_pkt_size[DIR_TX];
254 len = endpoints[n].out_len - endpoints[n].out_ptr;
255 if (len > max_pkt_size)
256 len = max_pkt_size;
257
258 if(len < max_pkt_size)
259 ISP1583_DFLOW_BUFLEN = len;
260
261 p = endpoints[n].out_buf + endpoints[n].out_ptr;
262 i = 0;
263 while (len - i >= 2) {
264 ISP1583_DFLOW_DATA = p[i] | (p[i + 1] << 8);
265 i += 2;
266 }
267 if (i < len)
268 ISP1583_DFLOW_DATA = p[i];
269
270 endpoints[n].out_ptr += len;
271
272/*
273 if (endpoints[n].out_ptr == endpoints[n].out_len
274 && len < max_pkt_size)
275*/
276 if (endpoints[n].out_ptr == endpoints[n].out_len)
277 endpoints[n].out_ptr = -1;
278
279 logf("send_end");
280 return 0;
281}
282
283static void usb_stall_endpoint(int idx)
284{
285 usb_select_endpoint(idx);
286 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_STALL;
287 endpoints[epidx_n(idx)].halt[epidx_dir(idx)] = 1;
288}
289
290static void usb_unstall_endpoint(int idx)
291{
292 usb_select_endpoint(idx);
293 ISP1583_DFLOW_CTRLFUN &= ~DFLOW_CTRLFUN_STALL;
294 ISP1583_DFLOW_EPTYPE &= ~DFLOW_EPTYPE_ENABLE;
295 ISP1583_DFLOW_EPTYPE |= DFLOW_EPTYPE_ENABLE;
296 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_CLBUF;
297 if (epidx_dir(idx) == DIR_TX)
298 endpoints[epidx_n(idx)].out_in_progress = 0;
299 else
300 {
301 endpoints[epidx_n(idx)].in_min_len = -1;
302 endpoints[epidx_n(idx)].in_ack = 0;
303 }
304 endpoints[epidx_n(idx)].halt[epidx_dir(idx)] = 0;
305}
306
307static void usb_status_ack(int ep, int dir)
308{
309 logf("usb_status_ack(%d)", dir);
310 usb_select_endpoint(ep_index(ep, dir));
311 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_STATUS;
312}
313
314static void usb_data_stage_enable(int ep, int dir)
315{
316 logf("usb_data_stage_enable(%d)", dir);
317 usb_select_endpoint(ep_index(ep, dir));
318 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_DSEN;
319}
320
321static void usb_handle_setup_rx(void)
322{
323 int len;
324 usb_select_setup_endpoint();
325 len = usb_get_packet(setup_pkt_buf, 8);
326
327 if (len == 8)
328 usb_core_control_request((struct usb_ctrlrequest*)setup_pkt_buf);
329 else
330 {
331 usb_drv_stall(0, true, false);
332 usb_drv_stall(0, true, true);
333 logf("usb_handle_setup_rx() failed");
334 return;
335 }
336
337 logf("usb_handle_setup_rx(): %02x %02x %02x %02x %02x %02x %02x %02x", setup_pkt_buf[0], setup_pkt_buf[1], setup_pkt_buf[2], setup_pkt_buf[3], setup_pkt_buf[4], setup_pkt_buf[5], setup_pkt_buf[6], setup_pkt_buf[7]);
338}
339
340static void usb_handle_data_int(int ep, int dir)
341{
342 int len;
343 if (dir == DIR_TX)
344 len = usb_send(ep);
345 else
346 {
347 len = usb_receive(ep);
348 endpoints[ep].in_ack = 1;
349 }
350 logf("usb_handle_data_int(%d, %d) finished", ep, dir);
351}
352
353bool usb_drv_powered(void)
354{
355#if 0
356 return (ISP1583_INIT_OTG & INIT_OTG_BSESS_VALID) ? true : false;
357#else
358 return (ISP1583_INIT_MODE & INIT_MODE_VBUSSTAT) ? true : false;
359#endif
360}
361
362static void setup_endpoints(void)
363{
364 usb_setup_endpoint(ep_index(0, DIR_RX), 64, 0);
365 usb_setup_endpoint(ep_index(0, DIR_TX), 64, 0);
366
367 int i;
368 for(i = 1; i < NUM_ENDPOINTS-1; i++)
369 {
370 usb_setup_endpoint(ep_index(i, DIR_RX), (high_speed_mode ? 512 : 64), 2); /* 2 = TYPE_BULK */
371 usb_setup_endpoint(ep_index(i, DIR_TX), (high_speed_mode ? 512 : 64), 2);
372 }
373
374 usb_enable_endpoint(ep_index(0, DIR_RX));
375 usb_enable_endpoint(ep_index(0, DIR_TX));
376
377 for (i = 1; i < NUM_ENDPOINTS-1; i++)
378 {
379 usb_enable_endpoint(ep_index(i, DIR_RX));
380 usb_enable_endpoint(ep_index(i, DIR_TX));
381 }
382
383 ZVM_SPECIFIC;
384}
385
386void usb_helper(void)
387{
388 if(ISP1583_GEN_INT_READ & ISP1583_INIT_INTEN_READ)
389 {
390 #ifdef DEBUG
Maurus Cuelenaereed5f1ed2008-05-03 14:43:43 +0000391 logf("Helper detected interrupt... [%d]", current_tick);
Maurus Cuelenaere95167e02008-04-24 20:08:28 +0000392 #endif
393 usb_drv_int();
394 }
395 return;
396}
397
398void usb_drv_init(void)
399{
400 /* Disable interrupt at CPU level */
401 DIS_INT_CPU_TARGET;
402
403 /* Unlock the device's registers */
404 ISP1583_GEN_UNLCKDEV = ISP1583_UNLOCK_CODE;
405
406 /* Soft reset the device */
407 ISP1583_INIT_MODE = INIT_MODE_SFRESET;
408 sleep(10);
409 /* Enable CLKAON & GLINTENA */
410 ISP1583_INIT_MODE = STANDARD_INIT_MODE;
411
412 /* Disable all OTG functions */
413 ISP1583_INIT_OTG = 0;
414
415#if 0
416 #ifdef USE_HIGH_SPEED
417 /* Force device to high speed */
418 ISP1583_GEN_TSTMOD = GEN_TSTMOD_FORCEHS;
419 high_speed_mode = true;
420 #endif
421#endif
422
423 #ifdef DEBUG
424 logf("BUS_CONF/DA0:%d MODE0/DA1: %d MODE1: %d", (bool)(ISP1583_INIT_MODE & INIT_MODE_TEST0), (bool)(ISP1583_INIT_MODE & INIT_MODE_TEST1), (bool)(ISP1583_INIT_MODE & INIT_MODE_TEST2));
425 logf("Chip ID: 0x%x", ISP1583_GEN_CHIPID);
426 //logf("INV0: 0x% IRQEDGE: 0x%x IRQPORT: 0x%x", IO_GIO_INV0, IO_GIO_IRQEDGE, IO_GIO_IRQPORT);
427 #endif
428
429 /*Set interrupt generation to target-specific mode +
430 * Set the control pipe to ACK only interrupt +
431 * Set the IN pipe to ACK only interrupt +
432 * Set OUT pipe to ACK and NYET interrupt
433 */
434
435 ISP1583_INIT_INTCONF = 0x54 | INT_CONF_TARGET;
436 /* Clear all interrupts */
437 set_int_value(ISP1583_GEN_INT_A, ISP1583_GEN_INT_B, 0xFFFFFFFF);
438 /* Enable USB interrupts */
439 set_int_value(ISP1583_INIT_INTEN_A, ISP1583_INIT_INTEN_B, STANDARD_INTEN);
440
441 ZVM_SPECIFIC;
442
443 /* Enable interrupt at CPU level */
444 EN_INT_CPU_TARGET;
445
446 setup_endpoints();
447
448 /* Clear device address and disable it */
449 ISP1583_INIT_ADDRESS = 0;
450
451 /* Turn SoftConnect on */
452 ISP1583_INIT_MODE |= INIT_MODE_SOFTCT;
453
454 ZVM_SPECIFIC;
455
456 tick_add_task(usb_helper);
457
458 logf("usb_init_device() finished");
459}
460
461int usb_drv_port_speed(void)
462{
463 return (int)high_speed_mode;
464}
465
466void usb_drv_exit(void)
467{
468 logf("usb_drv_exit()");
469
470 /* Disable device */
471 ISP1583_INIT_MODE &= ~INIT_MODE_SOFTCT;
472 ISP1583_INIT_ADDRESS = 0;
473
474 /* Disable interrupts */
475 set_int_value(ISP1583_INIT_INTEN_A, ISP1583_INIT_INTEN_B, 0);
476 /* and the CPU's one... */
477 DIS_INT_CPU_TARGET;
478
479
480 /* Send usb controller to suspend mode */
481 ISP1583_INIT_MODE = INIT_MODE_GOSUSP;
482 ISP1583_INIT_MODE = 0;
483
484 tick_remove_task(usb_helper);
485
486 ZVM_SPECIFIC;
487}
488
489void usb_drv_stall(int endpoint, bool stall, bool in)
490{
491 logf("%sstall EP%d %s", (stall ? "" : "un"), endpoint, (in ? "RX" : "TX" ));
492 if (stall)
493 usb_stall_endpoint(ep_index(endpoint, (int)in));
494 else
495 usb_unstall_endpoint(ep_index(endpoint, (int)in));
496}
497
498bool usb_drv_stalled(int endpoint, bool in)
499{
500 return (endpoints[endpoint].halt[(int)in] == 1);
501}
502
503static void out_callback(int ep, unsigned char *buf, int len)
504{
505 (void)buf;
506 logf("out_callback(%d, 0x%x, %d)", ep, &buf, len);
507 usb_status_ack(ep, DIR_RX);
508 usb_core_transfer_complete(ep, true, 0, len); /* 0=>status succeeded, haven't worked out status failed yet... */
509}
510
511static void in_callback(int ep, unsigned char *buf, int len)
512{
513 (void)buf;
514 logf("in_callback(%d, 0x%x, %d)", ep, &buf, len);
515 usb_status_ack(ep, DIR_TX);
516 usb_core_transfer_complete(ep, false, 0, len);
517}
518
519int usb_drv_recv(int ep, void* ptr, int length)
520{
521 logf("usb_drv_recv(%d, 0x%x, %d)", ep, &ptr, length);
522 if(ep == 0 && length == 0 && ptr == NULL)
523 {
524 usb_status_ack(ep, DIR_TX);
525 return 0;
526 }
527 endpoints[ep].in_done = in_callback;
528 endpoints[ep].in_buf = ptr;
529 endpoints[ep].in_max_len = length;
530 endpoints[ep].in_min_len = length;
531 endpoints[ep].in_ptr = 0;
532 if(ep == 0)
533 {
534 usb_data_stage_enable(ep, DIR_RX);
535 return usb_receive(ep);
536 }
537 else
538 return usb_receive(ep);
539}
540
541int usb_drv_send_nonblocking(int ep, void* ptr, int length)
542{
543 /* First implement DMA... */
544 return usb_drv_send(ep, ptr, length);
545}
546
547int usb_drv_send(int ep, void* ptr, int length)
548{
549 logf("usb_drv_send_nb(%d, 0x%x, %d)", ep, &ptr, length);
550 if(ep == 0 && length == 0 && ptr == NULL)
551 {
552 usb_status_ack(ep, DIR_RX);
553 return 0;
554 }
555 if(endpoints[ep].out_in_progress == 1)
556 return -1;
557 endpoints[ep].out_done = out_callback;
558 endpoints[ep].out_buf = ptr;
559 endpoints[ep].out_len = length;
560 endpoints[ep].out_ptr = 0;
561 endpoints[ep].out_in_progress = 1;
562 if(ep == 0)
563 {
564 int rc = usb_send(ep);
565 usb_data_stage_enable(ep, DIR_TX);
566 usb_drv_wait(ep, DIR_TX);
567 return rc;
568 }
569 else
570 return usb_send(ep);
571}
572
573void usb_drv_reset_endpoint(int ep, bool send)
574{
575 logf("reset endpoint(%d, %d)", ep, send);
576 usb_setup_endpoint(ep_index(ep, (int)send), endpoints[ep].max_pkt_size[(int)send], endpoints[ep].type);
577 usb_enable_endpoint(ep_index(ep, (int)send));
578}
579
580void usb_drv_wait(int ep, bool send)
581{
582 logf("usb_drv_wait(%d, %d)", ep, send);
583 if(send)
584 {
585 while (endpoints[ep].out_in_progress)
586 nop_f();
587 }
588 else
589 {
590 while (endpoints[ep].in_ack)
591 nop_f();
592 }
593}
594
595void usb_drv_cancel_all_transfers(void)
596{
597 logf("usb_drv_cancel_all_tranfers()");
598 int i;
599
600 for(i=0;i<NUM_ENDPOINTS-1;i++)
601 endpoints[i].halt[0] = endpoints[i].halt[1] = 1;
602}
603
604static void bus_reset(void)
605{
606 /* Enable CLKAON & GLINTENA */
607 ISP1583_INIT_MODE = STANDARD_INIT_MODE;
608 /* Enable USB interrupts */
609 ISP1583_INIT_INTCONF = 0x54 | INT_CONF_TARGET;
610 set_int_value(ISP1583_INIT_INTEN_A, ISP1583_INIT_INTEN_B, STANDARD_INTEN);
611
612 /* Disable all OTG functions */
613 ISP1583_INIT_OTG = 0;
614
615 /* Clear device address and enable it */
616 ISP1583_INIT_ADDRESS = INIT_ADDRESS_DEVEN;
617
618 ZVM_SPECIFIC;
619
620 /* Reset endpoints to default */
621 setup_endpoints();
622
623 logf("bus reset->done");
624}
625
626/* Method for handling interrupts, must be called from usb-<target>.c */
Maurus Cuelenaere7a8fc3f2008-05-16 21:05:18 +0000627void IRAM_ATTR usb_drv_int(void)
Maurus Cuelenaere95167e02008-04-24 20:08:28 +0000628{
629 unsigned long ints;
630 ints = ISP1583_GEN_INT_READ & ISP1583_INIT_INTEN_READ;
631
632 if(!ints)
633 return;
634
635 /* Unlock the device's registers */
636 ISP1583_GEN_UNLCKDEV = ISP1583_UNLOCK_CODE;
637
638 #if 0
639 logf(" handling int [0x%x & 0x%x = 0x%x]", ISP1583_GEN_INT_READ, ISP1583_INIT_INTEN_READ, ints);
640 #endif
641
642 if(ints & INT_IEBRST) /* Bus reset */
643 {
644 logf("BRESET");
645 high_speed_mode = false;
646 bus_reset();
647 usb_core_bus_reset();
648 /* Mask bus reset interrupt */
649 set_int_value(ISP1583_GEN_INT_A, ISP1583_GEN_INT_B, INT_IEBRST);
650 return;
651 }
652 if(ints & INT_IEP0SETUP) /* EP0SETUP interrupt */
653 {
654 logf("EP0SETUP");
655 usb_handle_setup_rx();
656 }
657 if(ints & INT_IEHS_STA) /* change from full-speed to high-speed mode -> endpoints need to get reconfigured!! */
658 {
659 logf("HS_STA");
660 high_speed_mode = true;
661 setup_endpoints();
662 }
663 if(ints & INT_EP_MASK) /* Endpoints interrupt */
664 {
665 unsigned long ep_event;
666 unsigned short i = 10;
667 ep_event = ints & INT_EP_MASK;
668 while(ep_event)
669 {
670 if(i>25)
671 break;
672
673 if(ep_event & (1 << i))
674 {
675 logf("EP%d %s interrupt", (i - 10) / 2, i % 2 ? "RX" : "TX");
676 usb_handle_data_int((i - 10) / 2, i % 2);
677 ep_event &= ~(1 << i);
678 }
679 i++;
680 }
681 }
682 if(ints & INT_IERESM && !(ints & INT_IESUSP)) /* Resume status: status change from suspend to resume (active) */
683 {
684 logf("RESM");
685 }
686 if(ints & INT_IESUSP && !(ints & INT_IERESM)) /* Suspend status: status change from active to suspend */
687 {
688 logf("SUSP");
689 }
690 if(ints & INT_IEDMA) /* change in the DMA Interrupt Reason register */
691 {
692 logf("DMA");
693 }
694 if(ints & INT_IEVBUS) /* transition from LOW to HIGH on VBUS */
695 {
696 logf("VBUS");
697 }
698 /* Mask all (enabled) interrupts */
699 set_int_value(ISP1583_GEN_INT_A, ISP1583_GEN_INT_B, ints);
700
701 ZVM_SPECIFIC;
702}
703
704void usb_drv_set_address(int address)
705{
706 logf("usb_drv_set_address(0x%x)", address);
707 ISP1583_INIT_ADDRESS = (address & 0x7F) | INIT_ADDRESS_DEVEN;
708
709 ZVM_SPECIFIC;
710
711 usb_status_ack(0, DIR_TX);
712}
713
Maurus Cuelenaereed5f1ed2008-05-03 14:43:43 +0000714int dbg_usb_num_items(void)
715{
716 return 2+NUM_ENDPOINTS*2;
717}
718
719char* dbg_usb_item(int selected_item, void *data, char *buffer, size_t buffer_len)
720{
721 if(selected_item < 2)
722 {
723 switch(selected_item)
724 {
725 case 0:
726 snprintf(buffer, buffer_len, "USB connected: %s", (usb_drv_connected() ? "Yes" : "No"));
727 return buffer;
728 case 1:
729 snprintf(buffer, buffer_len, "HS mode: %s", (high_speed_mode ? "Yes" : "No"));
730 return buffer;
731 }
732 }
733 else
734 {
735 int n = ep_index((selected_item - 2) / 2, (selected_item - 2) % 2);
736 if(endpoints[n].enabled == false)
737 snprintf(buffer, buffer_len, "EP%d[%s]: DISABLED", epidx_n(n), (epidx_dir(n) ? "TX" : "RX"));
738 else
739 {
740 if(epidx_dir(n))
741 {
742 if(endpoints[n].out_in_progress)
743 snprintf(buffer, buffer_len, "EP%d[TX]: TRANSFERRING DATA -> %d bytes/%d bytes", epidx_n(n), (endpoints[n].out_len - endpoints[n].out_ptr), endpoints[n].out_len);
744 else
745 snprintf(buffer, buffer_len, "EP%d[TX]: STANDBY", epidx_n(n));
746 }
747 else
748 {
749 if(endpoints[n].in_buf && !endpoints[n].in_ack)
750 snprintf(buffer, buffer_len, "EP%d[RX]: RECEIVING DATA -> %d bytes/%d bytes", epidx_n(n), endpoints[n].in_ptr, endpoints[n].in_max_len);
751 else
752 snprintf(buffer, buffer_len, "EP%d[RX]: STANDBY", epidx_n(n));
753 }
754 }
755 return buffer;
756 }
757 return NULL;
758 (void)data;
759}
760
Maurus Cuelenaere95167e02008-04-24 20:08:28 +0000761void usb_drv_set_test_mode(int mode)
762{
763 logf("usb_drv_set_test_mode(%d)", mode);
764 switch(mode){
765 case 0:
766 ISP1583_GEN_TSTMOD = 0;
767 /* Power cycle... */
768 break;
769 case 1:
770 ISP1583_GEN_TSTMOD = GEN_TSTMOD_JSTATE;
771 break;
772 case 2:
773 ISP1583_GEN_TSTMOD = GEN_TSTMOD_KSTATE;
774 break;
775 case 3:
776 ISP1583_GEN_TSTMOD = GEN_TSTMOD_SE0_NAK;
777 break;
778 case 4:
779 //REG_PORTSC1 |= PORTSCX_PTC_PACKET;
780 break;
781 case 5:
782 //REG_PORTSC1 |= PORTSCX_PTC_FORCE_EN;
783 break;
784 }
785}