+#include "logf.h" +#include "kernel.h" +#include #define UOG_USBCMD (*(volatile int *)0xc5000140) #define UOG_USBSTS (*(volatile int *)0xc5000144) @@ -554,6 +50,19 @@ #define MAX_PACKET_SIZE 64 +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define ERROR_TIMEOUT (-3) +#define ERROR_UNKNOWN (-7) + +#define PRIME_TIMER 100000 +#define TRANSFER_TIMER 1000000 +#define RESET_TIMER 5000000 + +#define OWN_VENDOR_ID 0x6666 +#define OWN_PRODUCT_ID 0xe200 +#define OWN_PRODUCT_REV 0x0001 + #define BUFFER_SIZE 4096 #define USB_BUS_RESET (UOG_USBSTS & (1 << 6)) @@ -562,6 +71,9 @@ #define TRANSFER_TIMER 1000000 #define RESET_TIMER 5000000 +/* forward declaration */ +void usb_handle_reset(); + struct dtd { unsigned int next_dtd; unsigned int dtd_token; @@ -698,14 +210,14 @@ .iface.bInterfaceProtocol = 0xff, }; -struct dtd dev_td[2] __attribute((aligned (32))); +struct dtd dev_td[2] __attribute((aligned (32))) __attribute__ ((section(".ibss"))); #define HOST2DEV 0 #define DEV2HOST 1 -struct dqh dev_qh[2] __attribute((aligned (1 << 11))); +struct dqh dev_qh[2] __attribute((aligned (1 << 11))) __attribute__ ((section(".ibss"))); -unsigned char buffer[BUFFER_SIZE] __attribute((aligned (1 << 12))); +unsigned char buffer[BUFFER_SIZE] __attribute((aligned (1 << 12))) __attribute__ ((section(".ibss"))); void dqh_init(int dir) @@ -738,32 +250,30 @@ int dtd_enqueue(int dir) { + + unsigned int timeout = PRIME_TIMER; const unsigned int mask = 1 << (dir * 16); struct dqh * const dqh = &dev_qh[dir]; struct dtd * const dtd = &dev_td[dir]; - struct timer t; dqh->dtd_ovrl.next_dtd = (unsigned int)dtd; dqh->dtd_ovrl.dtd_token &= ~0xc0; - //cache_flush(); - - timer_set(&t, PRIME_TIMER); - UOG_ENDPTPRIME |= mask; - while (UOG_ENDPTPRIME & mask) { + while ((UOG_ENDPTPRIME & mask) || (timeout--) > 0) { if (USB_BUS_RESET) { - longjmp(reset_env, 1); + usb_handle_reset(); } + } - if (timer_expired(&t)) { - exit(ERROR_TIMEOUT); - } + if ((timeout--) <= 0) { + logf("timeout->prime"); } if ((UOG_ENDPTSTAT & mask) == 0) { - exit(ERROR_HW); + logf("Endptstat 0x%x", UOG_ENDPTSTAT); + logf("HW_ERROR"); } return 0; @@ -773,14 +283,12 @@ dtd_wait(int dir) { const unsigned int mask = 1 << (dir * 16); + unsigned int timeout = TRANSFER_TIMER; struct dtd * const dtd = &dev_td[dir]; - struct timer t; - - timer_set(&t, TRANSFER_TIMER); for (;;) { if (USB_BUS_RESET) { - longjmp(reset_env, 1); + usb_handle_reset(); } if ((UOG_ENDPTCOMPLETE & mask) != 0) { @@ -791,9 +299,10 @@ return 0; } - if (timer_expired(&t)) { - return ERROR_TIMEOUT; + if ((timeout--) <= 0) { + return ERROR_TIMEOUT; } + } } @@ -820,7 +329,7 @@ do { if (USB_BUS_RESET) { - longjmp(reset_env, 1); + usb_handle_reset(); } todo = MIN(size, BUFFER_SIZE); @@ -853,7 +362,7 @@ do { if (USB_BUS_RESET) { - longjmp(reset_env, 1); + usb_handle_reset(); } todo = MIN(size, BUFFER_SIZE); @@ -881,7 +390,7 @@ usb_ack(struct spkt * s, int error) { if (USB_BUS_RESET) { - longjmp(reset_env, 1); + usb_handle_reset(); } if (error) { @@ -965,91 +474,8 @@ { int ret, error = 0; unsigned int val = 0; - struct timer t; - switch (s->bRequest) { - case REQ_NONE : - ret = 0; - break; - case REQ_SETPTR : - ret = usb_receive(&cur_addr, sizeof(cur_addr)); - break; - case REQ_WRITE : - ret = usb_receive(cur_addr, s->wLength); - cur_addr += ret; - break; - case REQ_READ : - ret = usb_send(cur_addr, s->wLength); - cur_addr += ret; - break; - case REQ_RUN : - ret = 0; - break; - case REQ_LOAD : - switch (s->wLength) { - case 1 : - val = *(volatile unsigned char *)cur_addr; - break; - case 2 : - val = *(volatile unsigned short *)cur_addr; - break; - case 4 : - val = *(volatile unsigned int *)cur_addr; - break; - default : - exit(ERROR_INVALID); - } - ret = usb_send(&val, s->wLength); - break; - case REQ_STORE : - ret = usb_receive(&val, s->wLength); - if (ret == s->wLength) { - switch (s->wLength) { - case 1 : - *(volatile unsigned char *)cur_addr = val; - break; - case 2 : - *(volatile unsigned short *)cur_addr = val; - break; - case 4 : - *(volatile unsigned int *)cur_addr = val; - break; - default : - exit(ERROR_INVALID); - } - } - break; - case REQ_I2C_READ : - if (s->wLength > TMPBUF_SIZE) { - ret = ERROR_INVALID; - } else { - ret = i2c_read(s->wIndex, tmpbuf, s->wLength); - if (ret >= 0) { - ret = usb_send(tmpbuf, ret); - } - } - break; - case REQ_I2C_WRITE : - ret = ERROR_INVALID; - if (s->wLength <= 4) { - ret = usb_receive(tmpbuf, s->wLength); - if (ret == s->wLength) { - timer_set(&t, s->wValue * 1000); - do { - ret = i2c_write(s->wIndex, tmpbuf, s->wLength); - } while (ret != s->wLength && !timer_expired(&t)); - } - } - break; - case REQ_I2C_PROGRAM : - ret = i2c_program(s->wIndex, cur_addr, s->wValue); - break; - case REQ_POWEROFF : - ret = 0; - break; - default : - ret = ERROR_UNKNOWN; - } + ret = 0; if (ret < 0) { error = ret; @@ -1059,14 +485,6 @@ usb_ack(s, error); - if (s->bRequest == REQ_RUN) { /* ack before jumping */ - longjmp(start_env, 2); - } - - if (s->bRequest == REQ_POWEROFF) { /* ack before power off */ - poweroff(); - } - return 0; } @@ -1080,8 +498,6 @@ return usb_handle_setup_dev_vnd(s); } - exit(ERROR_UNKNOWN); - return 0; } @@ -1133,88 +549,70 @@ return usb_handle_setup_ep(s); } - exit(ERROR_UNKNOWN); + logf("should never happen"); + return -1; } void -usb_handle_reset() +usb_handle_reset(void) { - struct timer t; - - timer_set(&t, RESET_TIMER); - + unsigned int timeout = RESET_TIMER; UOG_ENDPTSETUPSTAT = UOG_ENDPTSETUPSTAT; UOG_ENDPTCOMPLETE = UOG_ENDPTCOMPLETE; while (UOG_ENDPTPRIME) { /* prime and flush pending transfers */ - if (timer_expired(&t)) { - exit(ERROR_TIMEOUT); + if ((timeout--) <= 0) { + logf("TIMEOUT->p&f"); } } UOG_ENDPTFLUSH = ~0; if ((UOG_PORTSC0 & (1 << 8)) == 0) { - exit(ERROR_TIMEOUT); /* init too slow ! */ + logf("TIMEOUT->port"); } UOG_USBSTS = (1 << 6); while ((UOG_USBSTS & (1 << 2)) == 0) { /* wait for port change */ - if (timer_expired(&t)) { - exit(ERROR_TIMEOUT); + if ((timeout--) <= 0) { + logf("TIMEOUT->portchange"); } } UOG_USBSTS = (1 << 2); } -void -restart() -{ - UOG_USBCMD &= ~(1 << 0); /* stop */ +void usb_int() { + struct spkt spkt; - usleep(1000000); + if (USB_BUS_RESET) { + usb_handle_reset(); + } - cur_addr = (void *)_start; - longjmp(start_env, 2); + if ((UOG_ENDPTSETUPSTAT & 0x1) != 0) { + memcpy(&spkt, dev_qh[0].setup_buf, sizeof(spkt)); + UOG_ENDPTSETUPSTAT = UOG_ENDPTSETUPSTAT; + logf("recived packet"); + usb_handle_setup(&spkt); + } } -int -main() -{ - struct spkt spkt; - struct timer t; - int ret; - - i2c_init(); - - ret = setjmp(start_env); - - if (ret > 1) { - return 0; - } - - /* Reset the USB controller */ - - led_set(0); - - usleep(200000); +void arcotg_init() { + unsigned int timeout = RESET_TIMER; UOG_USBCMD &= ~(1 << 0); /* stop */ - usleep(500000); - - timer_set(&t, RESET_TIMER); + sleep(HZ/5); /* is this equal to usleep(50000)? */ UOG_USBCMD |= (1 << 1); /* reset */ - while (UOG_USBCMD & (1 << 1)) { - if (timer_expired(&t)) { - exit(ERROR_HW); - } + + while ((UOG_USBCMD & (1 << 1)) || (timeout--) > 0) { } - led_set(1); + if (timeout <= 0) { + logf("TIMEOUT->init"); + } /* Configure the controller */ @@ -1226,23 +624,12 @@ dqh_init(DEV2HOST); UOG_ENDPOINTLISTADDR = (unsigned int)dev_qh; +} +void dr_controller_run() { /* Start the device */ - UOG_USBCMD |= (1 << 0); /* run */ +} - setjmp(reset_env); - - for (;;) { - if (USB_BUS_RESET) { - usb_handle_reset(); - continue; - } - - if ((UOG_ENDPTSETUPSTAT & 0x1) != 0) { - memcpy(&spkt, dev_qh[0].setup_buf, sizeof(spkt)); - UOG_ENDPTSETUPSTAT = UOG_ENDPTSETUPSTAT; - usb_handle_setup(&spkt); - } - } +void dr_controller_stop() { }