diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-08-26 21:48:49 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-08-26 21:48:49 +0000 |
commit | 62c4a2838eea24dc41a65e4fc567e386f07c32e4 (patch) | |
tree | 47bd1e837c3f3da5e9cd4156f2fff98526e5b90a /firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |
parent | 753350154ea04c8369225b9c1dc1840dc6fcd1d4 (diff) | |
download | rockbox-62c4a2838eea24dc41a65e4fc567e386f07c32e4.tar.gz rockbox-62c4a2838eea24dc41a65e4fc567e386f07c32e4.tar.bz2 rockbox-62c4a2838eea24dc41a65e4fc567e386f07c32e4.zip |
Onda VX747:
* Overall cleanup (still needs work)
* Add preliminary USB support
* Add power off support
* Add preliminary MMU handling
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18348 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 1037 |
1 files changed, 1037 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c new file mode 100644 index 0000000000..92a2f3b801 --- /dev/null +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -0,0 +1,1037 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Maurus Cuelenaere + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "system.h" +#include "usb_ch9.h" +#include "usb_drv.h" +#include "usb_core.h" +#include "jz4740.h" +#include "thread.h" + +#if 0 + +#define EP1_INTR_BIT 2 +#define EP_FIFO_NOEMPTY 2 + +#define GPIO_UDC_DETE_PIN (32 * 3 + 6) +#define GPIO_UDC_DETE GPIO_UDC_DETE_PIN +#define IRQ_GPIO_UDC_DETE (IRQ_GPIO_0 + GPIO_UDC_DETE) + +#define IS_CACHE(x) (x < 0xa0000000) + +bool usb_drv_connected(void) +{ + return (__gpio_get_pin(GPIO_UDC_DETE)==1); +} + +int usb_detect(void) +{ + if(__gpio_get_pin(GPIO_UDC_DETE)==1) + return USB_INSERTED; + else + return USB_EXTRACTED; +} + +void usb_init_device(void) +{ + system_enable_irq(IRQ_UDC); + __gpio_as_input(GPIO_UDC_DETE_PIN); + return; +} + +void usb_enable(bool on) +{ + if(on) + usb_core_init(); + else + usb_core_exit(); +} + +void usb_drv_init(void) +{ + /* Set this bit to allow the UDC entering low-power mode when + * there are no actions on the USB bus. + * UDC still works during this bit was set. + */ + //__cpm_stop_udc(); + + __cpm_start_udc(); + + /* Enable the USB PHY */ + REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; + + /* Disable interrupts */ + REG_USB_REG_INTRINE = 0; + REG_USB_REG_INTROUTE = 0; + REG_USB_REG_INTRUSBE = 0; + + /* Enable interrupts */ + REG_USB_REG_INTRINE |= USB_INTR_EP0; + REG_USB_REG_INTRUSBE |= USB_INTR_RESET; + + /* Enable SUSPEND */ + /* usb_setb(USB_REG_POWER, USB_POWER_SUSPENDM); */ + + /* Enable HS Mode */ + REG_USB_REG_POWER |= USB_POWER_HSENAB; + + /* Let host detect UDC: + * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this + * transistor on and pull the USBDP pin HIGH. + */ + REG_USB_REG_POWER |= USB_POWER_SOFTCONN; +} + +void usb_drv_exit(void) +{ + /* Disable interrupts */ + REG_USB_REG_INTRINE = 0; + REG_USB_REG_INTROUTE = 0; + REG_USB_REG_INTRUSBE = 0; + + /* Disable DMA */ + REG_USB_REG_CNTL1 = 0; + REG_USB_REG_CNTL2 = 0; + + /* Disconnect from usb */ + REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; + + /* Disable the USB PHY */ + REG_CPM_SCR &= ~CPM_SCR_USBPHY_ENABLE; + + __cpm_stop_udc(); +} + +void usb_drv_set_address(int address) +{ + REG_USB_REG_FADDR = address; +} + +/* Interrupt handler */ +void UDC(void) +{ + +} + +#else + +//------------------------------------------ +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef u32 +#define u32 unsigned int +#endif + +#ifndef s8 +#define s8 char +#endif + +#ifndef s16 +#define s16 short +#endif + +#ifndef s32 +#define s32 int +#endif + +extern int usbdebug; + +enum USB_ENDPOINT_TYPE +{ + ENDPOINT_TYPE_CONTROL, + /* Typically used to configure a device when attached to the host. + * It may also be used for other device specific purposes, including + * control of other pipes on the device. + */ + ENDPOINT_TYPE_ISOCHRONOUS, + /* Typically used for applications which need guaranteed speed. + * Isochronous transfer is fast but with possible data loss. A typical + * use is audio data which requires a constant data rate. + */ + ENDPOINT_TYPE_BULK, + /* Typically used by devices that generate or consume data in relatively + * large and bursty quantities. Bulk transfer has wide dynamic latitude + * in transmission constraints. It can use all remaining available bandwidth, + * but with no guarantees on bandwidth or latency. Since the USB bus is + * normally not very busy, there is typically 90% or more of the bandwidth + * available for USB transfers. + */ + ENDPOINT_TYPE_INTERRUPT + /* Typically used by devices that need guaranteed quick responses + * (bounded latency). + */ +}; + + +enum USB_STANDARD_REQUEST_CODE { + GET_STATUS, + CLEAR_FEATURE, + SET_FEATURE = 3, + SET_ADDRESS = 5, + GET_DESCRIPTOR, + SET_DESCRIPTOR, + GET_CONFIGURATION, + SET_CONFIGURATION, + GET_INTERFACE, + SET_INTERFACE, + SYNCH_FRAME +}; + + +enum USB_DESCRIPTOR_TYPE { + DEVICE_DESCRIPTOR = 1, + CONFIGURATION_DESCRIPTOR, + STRING_DESCRIPTOR, + INTERFACE_DESCRIPTOR, + ENDPOINT_DESCRIPTOR, + DEVICE_QUALIFIER_DESCRIPTOR, + OTHER_SPEED_CONFIGURATION_DESCRIPTOR, + INTERFACE_POWER1_DESCRIPTOR +}; + + +enum USB_FEATURE_SELECTOR { + ENDPOINT_HALT, + DEVICE_REMOTE_WAKEUP, + TEST_MODE +}; + +enum USB_CLASS_CODE { + CLASS_DEVICE, + CLASS_AUDIO, + CLASS_COMM_AND_CDC_CONTROL, + CLASS_HID, + CLASS_PHYSICAL = 0x05, + CLASS_STILL_IMAGING, + CLASS_PRINTER, + CLASS_MASS_STORAGE, + CLASS_HUB, + CLASS_CDC_DATA, + CLASS_SMART_CARD, + CLASS_CONTENT_SECURITY = 0x0d, + CLASS_VIDEO, + CLASS_DIAGNOSTIC_DEVICE = 0xdc, + CLASS_WIRELESS_CONTROLLER = 0xe0, + CLASS_MISCELLANEOUS = 0xef, + CLASS_APP_SPECIFIC = 0xfe, + CLASS_VENDOR_SPECIFIC = 0xff +}; + + +typedef struct { + u8 bmRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; +} __attribute__ ((packed)) USB_DeviceRequest; + + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize0; + u16 idVendor; + u16 idProduct; + u16 bcdDevice; + u8 iManufacturer; + u8 iProduct; + u8 iSerialNumber; + u8 bNumConfigurations; +} __attribute__ ((packed)) USB_DeviceDescriptor; + + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize0; + u8 bNumConfigurations; + u8 bReserved; +} __attribute__ ((packed)) USB_DeviceQualifierDescriptor; + + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 wTotalLength; + u8 bNumInterfaces; + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 MaxPower; +} __attribute__ ((packed)) USB_ConfigDescriptor; + + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 wTotalLength; + u8 bNumInterfaces; + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 bMaxPower; +} __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor; + + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndpoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; +} __attribute__ ((packed)) USB_InterfaceDescriptor; + + +typedef struct { + u8 bLegth; + u8 bDescriptorType; + u8 bEndpointAddress; + u8 bmAttributes; + u16 wMaxPacketSize; + u8 bInterval; +} __attribute__ ((packed)) USB_EndPointDescriptor; + + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 SomeDesriptor[1]; +} __attribute__ ((packed)) USB_StringDescriptor; +//------------------------------------------ +#define MAX_EP0_SIZE 64 +#define MAX_EP1_SIZE 512 + +#define USB_HS 0 +#define USB_FS 1 +#define USB_LS 2 + +//definitions of EP0 +#define USB_EP0_IDLE 0 +#define USB_EP0_RX 1 +#define USB_EP0_TX 2 +/* Define maximum packet size for endpoint 0 */ +#define M_EP0_MAXP 64 +/* Endpoint 0 status structure */ + +static __inline__ void usb_setb(u32 port, u8 val) +{ + volatile u8 *ioport = (volatile u8 *)(port); + *ioport = (*ioport) | val; +} + +static __inline__ void usb_clearb(u32 port, u8 val) +{ + volatile u8 *ioport = (volatile u8 *)(port); + *ioport = (*ioport) & ~val; +} + +static __inline__ void usb_setw(u32 port, u16 val) +{ + volatile u16 *ioport = (volatile u16 *)(port); + *ioport = (*ioport) | val; +} + +static __inline__ void usb_clearw(u32 port, u16 val) +{ + volatile u16 *ioport = (volatile u16 *)(port); + *ioport = (*ioport) & ~val; +} +//--------------------------------- +#define BULK_OUT_BUF_SIZE 0x20000 //buffer size : +#define BULK_IN_BUF_SIZE 0x20000 // too + +enum UDC_STATE +{ + IDLE, + BULK_IN, + BULK_OUT +}; + +enum USB_JZ4740_REQUEST //add for USB_BOOT +{ + VR_GET_CUP_INFO = 0, + VR_SET_DATA_ADDERSS, + VR_SET_DATA_LENGTH, + VR_FLUSH_CACHES, + VR_PROGRAM_START1, + VR_PROGRAM_START2, + VR_NOR_OPS, + VR_NAND_OPS, + VR_SDRAM_OPS, + VR_CONFIGRATION +}; + +enum NOR_OPS_TYPE +{ + NOR_INIT = 0, + NOR_QUERY, + NOR_WRITE, + NOR_ERASE_CHIP, + NOR_ERASE_SECTOR +}; + +enum NOR_FLASH_TYPE +{ + NOR_AM29 = 0, + NOR_SST28, + NOR_SST39x16, + NOR_SST39x8 +}; + +enum NAND_OPS_TYPE +{ + NAND_QUERY = 0, + NAND_INIT, + NAND_MARK_BAD, + NAND_READ_OOB, + NAND_READ_RAW, + NAND_ERASE, + NAND_READ, + NAND_PROGRAM, + NAND_READ_TO_RAM +}; + +enum SDRAM_OPS_TYPE +{ + SDRAM_LOAD, + +}; + +enum DATA_STRUCTURE_OB +{ + DS_flash_info , + DS_hand +}; + + +/*typedef enum _USB_BOOT_STATUS +{ + USB_NO_ERR =0 , + GET_CPU_INFO_ERR, + SET_DATA_ADDRESS_ERR, + SET_DATA_LENGTH_ERR, + FLUSH_CAHCES_ERR, + PROGRAM_START1_ERR, + PROGRAM_START2_ERR, + NOR_OPS_ERR, + NAND_OPS_ERR, + NOR_FLASHTYPE_ERR, + OPS_NOTSUPPORT_ERR +}USB_BOOT_STATUS;*/ + +enum OPTION +{ + OOB_ECC, + OOB_NO_ECC, + NO_OOB, +}; +//------------------------- +static inline void jz_writeb(u32 address, u8 value) +{ + *((volatile u8 *)address) = value; +} + +static inline void jz_writew(u32 address, u16 value) +{ + *((volatile u16 *)address) = value; +} + +static inline void jz_writel(u32 address, u32 value) +{ + *((volatile u32 *)address) = value; +} + +static inline u8 jz_readb(u32 address) +{ + return *((volatile u8 *)address); +} + +static inline u16 jz_readw(u32 address) +{ + return *((volatile u16 *)address); +} + +static inline u32 jz_readl(u32 address) +{ + return *((volatile u32 *)address); +} +//--------------------------- + +#define TXFIFOEP0 USB_FIFO_EP0 + +u32 Bulk_in_buf[BULK_IN_BUF_SIZE]; +u32 Bulk_out_buf[BULK_OUT_BUF_SIZE]; +u32 Bulk_in_size,Bulk_in_finish,Bulk_out_size; +u16 handshake_PKT[4]={0,0,0,0}; +u8 udc_state; + +static u32 rx_buf[32]; +static u32 tx_buf[32]; +static u32 tx_size, rx_size, finished,fifo; +static u8 ep0state,USB_Version; + +static u32 fifoaddr[] = +{ + TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8 +}; + +static u32 fifosize[] = { + MAX_EP0_SIZE, MAX_EP1_SIZE +}; + +static void udcReadFifo(u8 *ptr, int size) +{ + u32 *d = (u32 *)ptr; + int s; + s = (size + 3) >> 2; + while (s--) + *d++ = REG32(fifo); +} + +static void udcWriteFifo(u8 *ptr, int size) +{ + u32 *d = (u32 *)ptr; + u8 *c; + int s, q; + + if (size > 0) { + s = size >> 2; + while (s--) + REG32(fifo) = *d++; + q = size & 3; + if (q) { + c = (u8 *)d; + while (q--) + REG8(fifo) = *c++; + } + } +} + +void HW_SendPKT(int ep, const u8 *buf, int size) +{ + fifo = fifoaddr[ep]; + + if (ep!=0) + { + Bulk_in_size = size; + Bulk_in_finish = 0; + jz_writeb(USB_REG_INDEX, ep); + if (Bulk_in_size - Bulk_in_finish <= fifosize[ep]) + { + udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), + Bulk_in_size - Bulk_in_finish); + usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); + Bulk_in_finish = Bulk_in_size; + } else + { + udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish), + fifosize[ep]); + usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY); + Bulk_in_finish += fifosize[ep]; + } + } + else //EP0 + { + tx_size = size; + finished = 0; + memcpy((void *)tx_buf, buf, size); + ep0state = USB_EP0_TX; + } +} + +void HW_GetPKT(int ep, const u8 *buf, int size) +{ + memcpy((void *)buf, (u8 *)rx_buf, size); + fifo = fifoaddr[ep]; + if (rx_size > size) + rx_size -= size; + else { + size = rx_size; + rx_size = 0; + } + memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size); +} + +static USB_DeviceDescriptor devDesc = +{ + sizeof(USB_DeviceDescriptor), + DEVICE_DESCRIPTOR, //1 + 0x0200, //Version 2.0 + 0xff, //Vendor spec class + 0xff, + 0xff, + 64, /* Ep0 FIFO size */ + 0x601a, //vendor ID + 0xDEAD, //Product ID + 0xffff, + 0x00, + 0x00, + 0x00, + 0x01 +}; + +#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \ + sizeof(USB_InterfaceDescriptor) + \ + sizeof(USB_EndPointDescriptor) * 2) + +static struct { + USB_ConfigDescriptor configuration_descriptor; + USB_InterfaceDescriptor interface_descritor; + USB_EndPointDescriptor endpoint_descriptor[2]; +} __attribute__ ((packed)) confDesc = { + { + sizeof(USB_ConfigDescriptor), + CONFIGURATION_DESCRIPTOR, + CONFIG_DESCRIPTOR_LEN, + 0x01, + 0x01, + 0x00, + 0xc0, // Self Powered, no remote wakeup + 0x64 // Maximum power consumption 2000 mA + }, + { + sizeof(USB_InterfaceDescriptor), + INTERFACE_DESCRIPTOR, + 0x00, + 0x00, + 0x02, /* ep number */ + 0xff, + 0xff, + 0xff, + 0x00 + }, + { + { + sizeof(USB_EndPointDescriptor), + ENDPOINT_DESCRIPTOR, + (1 << 7) | 1,// endpoint 2 is IN endpoint + 2, /* bulk */ + 512, + 16 + }, + { + sizeof(USB_EndPointDescriptor), + ENDPOINT_DESCRIPTOR, + (0 << 7) | 1,// endpoint 5 is OUT endpoint + 2, /* bulk */ + 512, /* OUT EP FIFO size */ + 16 + } + } +}; + +void sendDevDescString(int size) +{ + u16 str_ret[13] = { + 0x031a,//0x1a=26 byte + 0x0041, + 0x0030, + 0x0030, + 0x0041, + 0x0030, + 0x0030, + 0x0041, + 0x0030, + 0x0030, + 0x0041, + 0x0030, + 0x0030 + }; + if(size >= 26) + size = 26; + str_ret[0] = (0x0300 | size); + HW_SendPKT(0, (u8 *)str_ret,size); +} + +void sendDevDesc(int size) +{ + switch (size) { + case 18: + HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc)); + break; + default: + HW_SendPKT(0, (u8 *)&devDesc, 8); + break; + } +} + +void sendConfDesc(int size) +{ + switch (size) { + case 9: + HW_SendPKT(0, (u8 *)&confDesc, 9); + break; + case 8: + HW_SendPKT(0, (u8 *)&confDesc, 8); + break; + default: + HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc)); + break; + } +} + +void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size) +{ + confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in; + confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size; + confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out; + confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size; +} + +static void udc_reset(void) +{ + //data init + ep0state = USB_EP0_IDLE; + Bulk_in_size = 0; + Bulk_in_finish = 0; + Bulk_out_size = 0; + udc_state = IDLE; + tx_size = 0; + rx_size = 0; + finished = 0; + /* Enable the USB PHY */ +// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; + /* Disable interrupts */ + jz_writew(USB_REG_INTRINE, 0); + jz_writew(USB_REG_INTROUTE, 0); + jz_writeb(USB_REG_INTRUSBE, 0); + jz_writeb(USB_REG_FADDR,0); + jz_writeb(USB_REG_POWER,0x60); //High speed + jz_writeb(USB_REG_INDEX,0); + jz_writeb(USB_REG_CSR0,0xc0); + jz_writeb(USB_REG_INDEX,1); + jz_writew(USB_REG_INMAXP,512); + jz_writew(USB_REG_INCSR,0x2048); + jz_writeb(USB_REG_INDEX,1); + jz_writew(USB_REG_OUTMAXP,512); + jz_writew(USB_REG_OUTCSR,0x0090); + jz_writew(USB_REG_INTRINE,0x3); //enable intr + jz_writew(USB_REG_INTROUTE,0x2); + jz_writeb(USB_REG_INTRUSBE,0x4); + + if ((jz_readb(USB_REG_POWER)&0x10)==0) + { + jz_writeb(USB_REG_INDEX,1); + jz_writew(USB_REG_INMAXP,64); + jz_writew(USB_REG_INCSR,0x2048); + jz_writeb(USB_REG_INDEX,1); + jz_writew(USB_REG_OUTMAXP,64); + jz_writew(USB_REG_OUTCSR,0x0090); + USB_Version=USB_FS; + fifosize[1]=64; + EP0_init(1,64,1,64); + } + else + { + jz_writeb(USB_REG_INDEX,1); + jz_writew(USB_REG_INMAXP,512); + jz_writew(USB_REG_INCSR,0x2048); + jz_writeb(USB_REG_INDEX,1); + jz_writew(USB_REG_OUTMAXP,512); + jz_writew(USB_REG_OUTCSR,0x0090); + USB_Version=USB_HS; + fifosize[1]=512; + EP0_init(1,512,1,512); + } + +} + +void usbHandleStandDevReq(u8 *buf) +{ + USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; + switch (dreq->bRequest) { + case GET_DESCRIPTOR: + if (dreq->bmRequestType == 0x80) /* Dev2Host */ + switch(dreq->wValue >> 8) + { + case DEVICE_DESCRIPTOR: + sendDevDesc(dreq->wLength); + break; + case CONFIGURATION_DESCRIPTOR: + sendConfDesc(dreq->wLength); + break; + case STRING_DESCRIPTOR: + if (dreq->wLength == 0x02) + HW_SendPKT(0, "\x04\x03", 2); + else + sendDevDescString(dreq->wLength); + //HW_SendPKT(0, "\x04\x03\x09\x04", 2); + break; + } + ep0state=USB_EP0_TX; + + break; + case SET_ADDRESS: + jz_writeb(USB_REG_FADDR,dreq->wValue); + break; + case GET_STATUS: + switch (dreq->bmRequestType) { + case 80: /* device */ + HW_SendPKT(0, "\x01\x00", 2); + break; + case 81: /* interface */ + case 82: /* ep */ + HW_SendPKT(0, "\x00\x00", 2); + break; + } + ep0state=USB_EP0_TX; + break; + case CLEAR_FEATURE: + case SET_CONFIGURATION: + case SET_INTERFACE: + case SET_FEATURE: + break; + } +} + +extern char printfbuf[256]; + +int GET_CUP_INFO_Handle() +{ + HW_SendPKT(0, printfbuf, 64); + udc_state = IDLE; + return 0; +} + +void usbHandleVendorReq(u8 *buf) +{ + int ret_state; + USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; + switch (dreq->bRequest) { + case 0xAB: + ret_state=GET_CUP_INFO_Handle(); + break; + case 0x12: + HW_SendPKT(0, "TEST", 4); + udc_state = IDLE; + break; + } +} + +void Handshake_PKT(void) +{ + if (udc_state!=IDLE) + { + HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT)); + udc_state = IDLE; + } +} + +void usbHandleDevReq(u8 *buf) +{ + switch ((buf[0] & (3 << 5)) >> 5) { + case 0: /* Standard request */ + usbHandleStandDevReq(buf); + break; + case 1: /* Class request */ + break; + case 2: /* Vendor request */ + usbHandleVendorReq(buf); + break; + } +} + +void EP0_Handler (void) +{ + u8 byCSR0; + +/* Read CSR0 */ + jz_writeb(USB_REG_INDEX, 0); + byCSR0 = jz_readb(USB_REG_CSR0); + +/* Check for SentStall + if sendtall is set ,clear the sendstall bit*/ + if (byCSR0 & USB_CSR0_SENTSTALL) + { + jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL)); + ep0state = USB_EP0_IDLE; + return; + } + +/* Check for SetupEnd */ + if (byCSR0 & USB_CSR0_SETUPEND) + { + jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND)); + ep0state = USB_EP0_IDLE; + return; + } +/* Call relevant routines for endpoint 0 state */ + if (ep0state == USB_EP0_IDLE) + { + if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo + { + USB_DeviceRequest *dreq; + fifo=fifoaddr[0]; + udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest)); + usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit + dreq = (USB_DeviceRequest *)rx_buf; + usbHandleDevReq((u8 *)rx_buf); + } + rx_size = 0; + } + + if (ep0state == USB_EP0_TX) + { + fifo=fifoaddr[0]; + if (tx_size - finished <= 64) + { + udcWriteFifo((u8 *)((u32)tx_buf+finished), + tx_size - finished); + finished = tx_size; + usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); + usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend! + ep0state=USB_EP0_IDLE; + } else + { + udcWriteFifo((u8 *)((u32)tx_buf+finished), 64); + usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY); + finished += 64; + } + } + return; +} + +void EPIN_Handler(u8 EP) +{ + jz_writeb(USB_REG_INDEX, EP); + fifo = fifoaddr[EP]; + + if (Bulk_in_size-Bulk_in_finish==0) + { + Handshake_PKT(); + return; + } + + if (Bulk_in_size - Bulk_in_finish <= fifosize[EP]) + { + udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), + Bulk_in_size - Bulk_in_finish); + usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); + Bulk_in_finish = Bulk_in_size; + } else + { + udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish), + fifosize[EP]); + usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY); + Bulk_in_finish += fifosize[EP]; + } +} + +void EPOUT_Handler(u8 EP) +{ + u32 size; + jz_writeb(USB_REG_INDEX, EP); + size = jz_readw(USB_REG_OUTCOUNT); + fifo = fifoaddr[EP]; + udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size); + usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY); + Bulk_out_size += size; +} + +void UDC(void) +{ + u8 IntrUSB; + u16 IntrIn; + u16 IntrOut; +/* Read interrupt registers */ + IntrUSB = jz_readb(USB_REG_INTRUSB); + IntrIn = jz_readw(USB_REG_INTRIN); + IntrOut = jz_readw(USB_REG_INTROUT); + + if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0) + return; + + if (IntrIn & 2) + { + EPIN_Handler(1); + } + if (IntrOut & 2) + { + EPOUT_Handler(1); + } + if (IntrUSB & USB_INTR_RESET) + { + udc_reset(); + } + +/* Check for endpoint 0 interrupt */ + if (IntrIn & USB_INTR_EP0) + { + EP0_Handler(); + } + + IntrIn = jz_readw(USB_REG_INTRIN); + return; +} + +void __udc_start(void) +{ + udc_reset(); + + ep0state = USB_EP0_IDLE; + Bulk_in_size = 0; + Bulk_in_finish = 0; + Bulk_out_size = 0; + udc_state = IDLE; + tx_size = 0; + rx_size = 0; + finished = 0; + + if ((jz_readb(USB_REG_POWER)&0x10)==0) + { + USB_Version=USB_FS; + fifosize[1]=64; + EP0_init(1,64,1,64); + } + else + { + USB_Version=USB_HS; + fifosize[1]=512; + EP0_init(1,512,1,512); + } + + USB_Version=USB_HS; + system_enable_irq(IRQ_UDC); +} + +void usb_init_device(void){} + +#endif |