From 41282e2b6929cc5571efc4af8db83f9a92344819 Mon Sep 17 00:00:00 2001 From: Shakti Bhatnagar Date: Wed, 16 Jul 2014 15:33:59 +0530 Subject: [PATCH] usbps_v2_2: Deprecated v2_1 added new version v2_2 Added new version of usbps driver v2_2 Signed-off-by: Shakti Bhatnagar Acked-by: Srikanth Vemula --- .../drivers/usbps/data/usbps.mdd | 42 + .../drivers/usbps/data/usbps.tcl | 52 + .../drivers/usbps/examples/index.html | 20 + .../drivers/usbps/examples/xusbps_ch9.c | 641 ++++++++ .../drivers/usbps/examples/xusbps_ch9.h | 199 +++ .../usbps/examples/xusbps_ch9_storage.c | 368 +++++ .../usbps/examples/xusbps_ch9_storage.h | 90 + .../usbps/examples/xusbps_class_storage.c | 362 +++++ .../usbps/examples/xusbps_class_storage.h | 174 ++ .../usbps/examples/xusbps_intr_example.c | 574 +++++++ .../drivers/usbps/src/Makefile | 41 + .../drivers/usbps/src/xusbps.c | 361 ++++ .../drivers/usbps/src/xusbps.h | 1082 ++++++++++++ .../drivers/usbps/src/xusbps_endpoint.c | 1446 +++++++++++++++++ .../drivers/usbps/src/xusbps_endpoint.h | 512 ++++++ .../drivers/usbps/src/xusbps_g.c | 77 + .../drivers/usbps/src/xusbps_hw.c | 119 ++ .../drivers/usbps/src/xusbps_hw.h | 523 ++++++ .../drivers/usbps/src/xusbps_intr.c | 467 ++++++ .../drivers/usbps/src/xusbps_sinit.c | 96 ++ 20 files changed, 7246 insertions(+) create mode 100755 XilinxProcessorIPLib/drivers/usbps/data/usbps.mdd create mode 100755 XilinxProcessorIPLib/drivers/usbps/data/usbps.tcl create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/index.html create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.h create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.h create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.h create mode 100755 XilinxProcessorIPLib/drivers/usbps/examples/xusbps_intr_example.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/Makefile create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps.h create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.h create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_g.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.h create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_intr.c create mode 100755 XilinxProcessorIPLib/drivers/usbps/src/xusbps_sinit.c diff --git a/XilinxProcessorIPLib/drivers/usbps/data/usbps.mdd b/XilinxProcessorIPLib/drivers/usbps/data/usbps.mdd new file mode 100755 index 00000000..c804b88f --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/data/usbps.mdd @@ -0,0 +1,42 @@ +############################################################################### +# +# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +OPTION psf_version = 2.1; + +BEGIN driver usbps + + OPTION supported_peripherals = (ps7_usb); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 2.2; + OPTION NAME = usbps; + +END driver diff --git a/XilinxProcessorIPLib/drivers/usbps/data/usbps.tcl b/XilinxProcessorIPLib/drivers/usbps/data/usbps.tcl new file mode 100755 index 00000000..284e1acb --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/data/usbps.tcl @@ -0,0 +1,52 @@ +############################################################################### +# +# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +############################################################################## +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 1.00a sdm 11/22/11 Created +# +############################################################################## + +#uses "xillib.tcl" + +proc generate {drv_handle} { + xdefine_zynq_include_file $drv_handle "xparameters.h" "XUsbPs" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" + + xdefine_zynq_config_file $drv_handle "xusbps_g.c" "XUsbPs" "DEVICE_ID" "C_S_AXI_BASEADDR" + + xdefine_zynq_canonical_xpars $drv_handle "xparameters.h" "XUsbPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" + +} + diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/index.html b/XilinxProcessorIPLib/drivers/usbps/examples/index.html new file mode 100755 index 00000000..e770b790 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/index.html @@ -0,0 +1,20 @@ + + + + + +Driver example applications + + + +

Example Applications for the driver usbps_v2_1

+
+ +

Copyright � 2010-2014 Xilinx, Inc. All rights reserved.

+ + diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.c b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.c new file mode 100755 index 00000000..5e5c4d11 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.c @@ -0,0 +1,641 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xusbps_ch9.c + * + * This file contains the implementation of the chapter 9 code for the example. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ---------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 1.04a nm  02/05/13 Fixed CR# 696550.
+ *		      Added template code for Vendor request.
+ * 1.04a nm  03/04/13 Fixed CR# 704022. Implemented TEST_MODE Feature.
+ * 1.06a kpc 11/11/13 Always use global memory for dma operations
+ * 2.1   kpc 4/29/14  Align dma buffers to cache line boundary
+ *
+ ******************************************************************************/ + +/***************************** Include Files *********************************/ + + +#include "xparameters.h" /* XPAR parameters */ +#include "xusbps.h" /* USB controller driver */ +#include "xusbps_hw.h" /* USB controller driver */ + +#include "xusbps_ch9.h" +#include "xil_printf.h" +#include "xil_cache.h" + +/*default class is storage class */ +#include "xusbps_class_storage.h" +#include "sleep.h" + +/* #define CH9_DEBUG */ + +#ifdef CH9_DEBUG +#include +#define printf xil_printf +#endif + +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static void XUsbPs_StdDevReq(XUsbPs *InstancePtr, + XUsbPs_SetupData *SetupData); + +static int XUsbPs_HandleVendorReq(XUsbPs *InstancePtr, + XUsbPs_SetupData *SetupData); + +/************************** Variable Definitions *****************************/ + +static u8 Response ALIGNMENT_CACHELINE; + +/*****************************************************************************/ +/** +* This function handles a Setup Data packet from the host. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param SetupData is the structure containing the setup request. +* +* @return +* - XST_SUCCESS if the function is successful. +* - XST_FAILURE if an Error occured. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_Ch9HandleSetupPacket(XUsbPs *InstancePtr, + XUsbPs_SetupData *SetupData) +{ + int Status = XST_SUCCESS; + +#ifdef CH9_DEBUG + printf("Handle setup packet\n"); +#endif + + switch (SetupData->bmRequestType & XUSBPS_REQ_TYPE_MASK) { + case XUSBPS_CMD_STDREQ: + XUsbPs_StdDevReq(InstancePtr, SetupData); + break; + + case XUSBPS_CMD_CLASSREQ: + XUsbPs_ClassReq(InstancePtr, SetupData); + break; + + case XUSBPS_CMD_VENDREQ: + +#ifdef CH9_DEBUG + printf("vendor request %x\n", SetupData->bRequest); +#endif + Status = XUsbPs_HandleVendorReq(InstancePtr, SetupData); + break; + + default: + /* Stall on Endpoint 0 */ +#ifdef CH9_DEBUG + printf("unknown class req, stall 0 in out\n"); +#endif + XUsbPs_EpStall(InstancePtr, 0, XUSBPS_EP_DIRECTION_IN | + XUSBPS_EP_DIRECTION_OUT); + break; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function handles a standard device request. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param SetupData is a pointer to the data structure containing the +* setup request. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XUsbPs_StdDevReq(XUsbPs *InstancePtr, + XUsbPs_SetupData *SetupData) +{ + int Status; + int Error = 0; + + XUsbPs_Local *UsbLocalPtr; + + int ReplyLen; + static u8 Reply[XUSBPS_REQ_REPLY_LEN] ALIGNMENT_CACHELINE; + + /* Check that the requested reply length is not bigger than our reply + * buffer. This should never happen... + */ + if (SetupData->wLength > XUSBPS_REQ_REPLY_LEN) { + return; + } + + UsbLocalPtr = (XUsbPs_Local *) InstancePtr->UserDataPtr; + +#ifdef CH9_DEBUG + printf("std dev req %d\n", SetupData->bRequest); +#endif + + switch (SetupData->bRequest) { + + case XUSBPS_REQ_GET_STATUS: + + switch(SetupData->bmRequestType & XUSBPS_STATUS_MASK) { + case XUSBPS_STATUS_DEVICE: + /* It seems we do not have to worry about zeroing out the rest + * of the reply buffer even though we are only using the first + * two bytes. + */ + *((u16 *) &Reply[0]) = 0x0100; /* Self powered */ + break; + + case XUSBPS_STATUS_INTERFACE: + *((u16 *) &Reply[0]) = 0x0; + break; + + case XUSBPS_STATUS_ENDPOINT: + { + u32 Status; + int EpNum = SetupData->wIndex; + + Status = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCRn_OFFSET(EpNum & 0xF)); + + if(EpNum & 0x80) { /* In EP */ + if(Status & XUSBPS_EPCR_TXS_MASK) { + *((u16 *) &Reply[0]) = 0x0100; + }else { + *((u16 *) &Reply[0]) = 0x0000; + } + } else { /* Out EP */ + if(Status & XUSBPS_EPCR_RXS_MASK) { + *((u16 *) &Reply[0]) = 0x0100; + }else { + *((u16 *) &Reply[0]) = 0x0000; + } + } + break; + } + + default: + ; +#ifdef CH9_DEBUG + printf("unknown request for status %x\n", SetupData->bmRequestType); +#endif + } + XUsbPs_EpBufferSend(InstancePtr, 0, Reply, SetupData->wLength); + break; + + case XUSBPS_REQ_SET_ADDRESS: + + /* With bit 24 set the address value is held in a shadow + * register until the status phase is acked. At which point it + * address value is written into the address register. + */ + XUsbPs_SetDeviceAddress(InstancePtr, SetupData->wValue); +#ifdef CH9_DEBUG + printf("Set address %d\n", SetupData->wValue); +#endif + /* There is no data phase so ack the transaction by sending a + * zero length packet. + */ + XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + break; + + case XUSBPS_REQ_GET_INTERFACE: +#ifdef CH9_DEBUG + printf("Get interface %d/%d/%d\n", + SetupData->wIndex, SetupData->wLength, + InstancePtr->CurrentAltSetting); +#endif + Response = (u8)InstancePtr->CurrentAltSetting; + + /* Ack the host */ + XUsbPs_EpBufferSend(InstancePtr, 0, &Response, 1); + + break; + + case XUSBPS_REQ_GET_DESCRIPTOR: +#ifdef CH9_DEBUG + printf("Get desc %x/%d\n", (SetupData->wValue >> 8) & 0xff, + SetupData->wLength); +#endif + + /* Get descriptor type. */ + switch ((SetupData->wValue >> 8) & 0xff) { + + case XUSBPS_TYPE_DEVICE_DESC: + case XUSBPS_TYPE_DEVICE_QUALIFIER: + + /* Set up the reply buffer with the device descriptor + * data. + */ + ReplyLen = XUsbPs_Ch9SetupDevDescReply( + Reply, XUSBPS_REQ_REPLY_LEN); + + ReplyLen = ReplyLen > SetupData->wLength ? + SetupData->wLength : ReplyLen; + + if(((SetupData->wValue >> 8) & 0xff) == + XUSBPS_TYPE_DEVICE_QUALIFIER) { + Reply[0] = (u8)ReplyLen; + Reply[1] = (u8)0x6; + Reply[2] = (u8)0x0; + Reply[3] = (u8)0x2; + Reply[4] = (u8)0xFF; + Reply[5] = (u8)0x00; + Reply[6] = (u8)0x0; + Reply[7] = (u8)0x10; + Reply[8] = (u8)0; + Reply[9] = (u8)0x0; + } + Status = XUsbPs_EpBufferSend(InstancePtr, 0, + Reply, ReplyLen); + if (XST_SUCCESS != Status) { + /* Failure case needs to be handled */ + for (;;); + } + break; + + case XUSBPS_TYPE_CONFIG_DESC: + + /* Set up the reply buffer with the configuration + * descriptor data. + */ + ReplyLen = XUsbPs_Ch9SetupCfgDescReply( + Reply, XUSBPS_REQ_REPLY_LEN); + +#ifdef CH9_DEBUG + printf("get config %d/%d\n", ReplyLen, SetupData->wLength); +#endif + + ReplyLen = ReplyLen > SetupData->wLength ? + SetupData->wLength : ReplyLen; + + Status = XUsbPs_EpBufferSend(InstancePtr, 0, + Reply, ReplyLen); + if (XST_SUCCESS != Status) { + /* Failure case needs to be handled */ + for (;;); + } + break; + + + case XUSBPS_TYPE_STRING_DESC: + + /* Set up the reply buffer with the string descriptor + * data. + */ + ReplyLen = XUsbPs_Ch9SetupStrDescReply( + Reply, XUSBPS_REQ_REPLY_LEN, + SetupData->wValue & 0xFF); + + ReplyLen = ReplyLen > SetupData->wLength ? + SetupData->wLength : ReplyLen; + + Status = XUsbPs_EpBufferSend(InstancePtr, 0, + Reply, ReplyLen); + if (XST_SUCCESS != Status) { + /* Failure case needs to be handled */ + for (;;); + } + break; + +#ifdef MOUSE_SIMULATION + case XUSBPS_TYPE_HID_DESC: + + /* Set up the reply buffer with the HID descriptor + * data. + */ + ReplyLen = XUsbPs_Ch9SetupHidDescReply( + Reply, XUSBPS_REQ_REPLY_LEN); + + ReplyLen = ReplyLen > SetupData->wLength ? + SetupData->wLength : ReplyLen; + + Status = XUsbPs_EpBufferSend(InstancePtr, 0, + Reply, ReplyLen); + if (XST_SUCCESS != Status) { + /* Failure case needs to be handled */ + for (;;); + } + break; + + case XUSBPS_TYPE_REPORT_DESC: + + /* Set up the reply buffer with the report descriptor + * data. + */ + ReplyLen = XUsbPs_Ch9SetupReportDescReply( + Reply, XUSBPS_REQ_REPLY_LEN); +#ifdef CH9_DEBUG + printf("report desc len %d\n", ReplyLen); +#endif + + ReplyLen = ReplyLen > SetupData->wLength ? + SetupData->wLength : ReplyLen; + + Status = XUsbPs_EpBufferSend(InstancePtr, 0, + Reply, ReplyLen); + if (XST_SUCCESS != Status) { + /* Failure case needs to be handled */ + for (;;); + } + break; +#endif /* MOUSE_SIMULATION */ + + default: + Error = 1; + break; + } + break; + + + case XUSBPS_REQ_SET_CONFIGURATION: + + /* + * Only allow configuration index 1 as this is the only one we + * have. + */ + if ((SetupData->wValue & 0xff) != 1) { + Error = 1; + break; + } + + UsbLocalPtr->CurrentConfig = SetupData->wValue & 0xff; + + + /* Call the application specific configuration function to + * apply the configuration with the given configuration index. + */ + XUsbPs_SetConfiguration(InstancePtr, + UsbLocalPtr->CurrentConfig); + + /* There is no data phase so ack the transaction by sending a + * zero length packet. + */ + XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + break; + + + case XUSBPS_REQ_GET_CONFIGURATION: + Response = (u8)InstancePtr->CurrentAltSetting; + XUsbPs_EpBufferSend(InstancePtr, 0, + &Response, 1); + break; + + + case XUSBPS_REQ_CLEAR_FEATURE: + switch(SetupData->bmRequestType & XUSBPS_STATUS_MASK) { + case XUSBPS_STATUS_ENDPOINT: + if(SetupData->wValue == XUSBPS_ENDPOINT_HALT) { + int EpNum = SetupData->wIndex; + + if(EpNum & 0x80) { /* In ep */ + XUsbPs_ClrBits(InstancePtr, + XUSBPS_EPCRn_OFFSET(EpNum & 0xF), + XUSBPS_EPCR_TXS_MASK); + }else { /* Out ep */ + XUsbPs_ClrBits(InstancePtr, + XUSBPS_EPCRn_OFFSET(EpNum), + XUSBPS_EPCR_RXS_MASK); + } + } + /* Ack the host ? */ + XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + break; + + default: + Error = 1; + break; + } + + break; + + case XUSBPS_REQ_SET_FEATURE: + switch(SetupData->bmRequestType & XUSBPS_STATUS_MASK) { + case XUSBPS_STATUS_ENDPOINT: + if(SetupData->wValue == XUSBPS_ENDPOINT_HALT) { + int EpNum = SetupData->wIndex; + + if(EpNum & 0x80) { /* In ep */ + XUsbPs_SetBits(InstancePtr, + XUSBPS_EPCRn_OFFSET(EpNum & 0xF), + XUSBPS_EPCR_TXS_MASK); + + }else { /* Out ep */ + XUsbPs_SetBits(InstancePtr, + XUSBPS_EPCRn_OFFSET(EpNum), + XUSBPS_EPCR_RXS_MASK); + } + } + /* Ack the host ? */ + XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + + break; + case XUSBPS_STATUS_DEVICE: + if (SetupData->wValue == XUSBPS_TEST_MODE) { + int TestSel = (SetupData->wIndex >> 8) & 0xFF; + + /* Ack the host, the transition must happen + after status stage and < 3ms */ + XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + usleep(1000); + + switch (TestSel) { + case XUSBPS_TEST_J: + case XUSBPS_TEST_K: + case XUSBPS_TEST_SE0_NAK: + case XUSBPS_TEST_PACKET: + case XUSBPS_TEST_FORCE_ENABLE: + XUsbPs_SetBits(InstancePtr, \ + XUSBPS_PORTSCR1_OFFSET, \ + TestSel << 16); + break; + default: + /* Unsupported test selector */ + break; + } + break; + } + + default: + Error = 1; + break; + } + + break; + + + /* For set interface, check the alt setting host wants */ + case XUSBPS_REQ_SET_INTERFACE: + +#ifdef CH9_DEBUG + printf("set interface %d/%d\n", SetupData->wValue, SetupData->wIndex); +#endif + /* Not supported */ + /* XUsbPs_SetInterface(InstancePtr, SetupData->wValue, SetupData->wIndex); */ + + /* Ack the host after device finishes the operation */ + Error = XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + if(Error) { +#ifdef CH9_DEBUG + printf("EpBufferSend failed %d\n", Error); +#endif + } + break; + + default: + Error = 1; + break; + } + + /* Set the send stall bit if there was an error */ + if (Error) { +#ifdef CH9_DEBUG + printf("std dev req %d/%d error, stall 0 in out\n", + SetupData->bRequest, (SetupData->wValue >> 8) & 0xff); +#endif + XUsbPs_EpStall(InstancePtr, 0, XUSBPS_EP_DIRECTION_IN | + XUSBPS_EP_DIRECTION_OUT); + } +} + +/*****************************************************************************/ +/** +* This function handles a vendor request. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param SetupData is a pointer to the data structure containing the +* setup request. +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if an Error occured. +* +* @note +* This function is a template to handle vendor request for control +* IN and control OUT endpoints. The control OUT endpoint can +* receive only 64 bytes of data per dTD. For receiving more than +* 64 bytes of vendor data on control OUT endpoint, change the +* buffer size of the control OUT endpoint. Otherwise the results +* are unexpected. +* +******************************************************************************/ +static int XUsbPs_HandleVendorReq(XUsbPs *InstancePtr, + XUsbPs_SetupData *SetupData) +{ + u8 *BufferPtr; + u32 BufferLen; + u32 Handle; + u32 Reg; + const static u8 Reply[8] ALIGNMENT_CACHELINE = + {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}; + u8 EpNum = 0; + int Status; + int Direction; + int Timeout; + + /* Check the direction, USB 2.0 section 9.3 */ + Direction = SetupData->bmRequestType & (1 << 7); + + if (!Direction) { + /* Control OUT vendor request */ + if (SetupData->wLength > 0) { + /* Re-Prime the endpoint to receive Setup DATA */ + XUsbPs_EpPrime(InstancePtr, 0, XUSBPS_EP_DIRECTION_OUT); + + /* Check whether EP prime is successful or not */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + do { + Reg = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET); + } while(((Reg & (1 << EpNum)) == 1) && --Timeout); + + if (!Timeout) { + return XST_FAILURE; + } + + /* Get the Setup DATA, don't wait for the interrupt */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + do { + Status = XUsbPs_EpBufferReceive(InstancePtr, + EpNum, &BufferPtr, &BufferLen, &Handle); + } while((Status != XST_SUCCESS) && --Timeout); + + if (!Timeout) { + return XST_FAILURE; + } + + Xil_DCacheInvalidateRange((unsigned int)BufferPtr, + BufferLen); +#ifdef CH9_DEBUG + int Len; + xil_printf("Vendor data:\r\n"); + for(Len = 0;Len < BufferLen;Len++) + xil_printf("%02x ",BufferPtr[Len]); +#endif + + if (Status == XST_SUCCESS) { + /* Zero length ACK */ + Status = XUsbPs_EpBufferSend(InstancePtr, EpNum, + NULL, 0); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + } + } else { + if (SetupData->wLength > 0) { + /* Control IN vendor request */ + Status = XUsbPs_EpBufferSend(InstancePtr, EpNum, Reply, + SetupData->wLength); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + } + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.h b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.h new file mode 100755 index 00000000..982df493 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9.h @@ -0,0 +1,199 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xusbps_ch9.h + * + * This file contains definitions used in the chapter 9 code. + * + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.04a nm   03/04/13 Fixed CR# 704022. Implemented TEST_MODE Feature.
+ * 2.1   kpc  04/28/14 Added macros secific to cache operations
+ * 
+ * + ******************************************************************************/ + +#ifndef XUSBPS_CH9_H +#define XUSBPS_CH9_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xusbps_hw.h" +#include "xil_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/* + * Simulation type switch, default type is storage. + */ + +/** + * @name Request types + * @{ + */ +#define XUSBPS_REQ_TYPE_MASK 0x60 /**< Mask for request opcode */ + +#define XUSBPS_CMD_STDREQ 0x00 /**< */ +#define XUSBPS_CMD_CLASSREQ 0x20 /**< */ +#define XUSBPS_CMD_VENDREQ 0x40 /**< */ + +#define XUSBPS_REQ_REPLY_LEN 1024 /**< Max size of reply buffer. */ +/* @} */ + +/** + * @name Request Values + * @{ + */ +#define XUSBPS_REQ_GET_STATUS 0x00 +#define XUSBPS_REQ_CLEAR_FEATURE 0x01 +#define XUSBPS_REQ_SET_FEATURE 0x03 +#define XUSBPS_REQ_SET_ADDRESS 0x05 +#define XUSBPS_REQ_GET_DESCRIPTOR 0x06 +#define XUSBPS_REQ_SET_DESCRIPTOR 0x07 +#define XUSBPS_REQ_GET_CONFIGURATION 0x08 +#define XUSBPS_REQ_SET_CONFIGURATION 0x09 +#define XUSBPS_REQ_GET_INTERFACE 0x0a +#define XUSBPS_REQ_SET_INTERFACE 0x0b +#define XUSBPS_REQ_SYNC_FRAME 0x0c +/* @} */ + +/** + * @name Feature Selectors + * @{ + */ +#define XUSBPS_ENDPOINT_HALT 0x00 +#define XUSBPS_DEVICE_REMOTE_WAKEUP 0x01 +#define XUSBPS_TEST_MODE 0x02 +/* @} */ + +/** + * @name Descriptor Types + * @{ + */ +#define XUSBPS_TYPE_DEVICE_DESC 0x01 +#define XUSBPS_TYPE_CONFIG_DESC 0x02 +#define XUSBPS_TYPE_STRING_DESC 0x03 +#define XUSBPS_TYPE_IF_CFG_DESC 0x04 +#define XUSBPS_TYPE_ENDPOINT_CFG_DESC 0x05 +#define XUSBPS_TYPE_DEVICE_QUALIFIER 0x06 +#define XUSBPS_TYPE_HID_DESC 0x21 + +#define XUSBPS_TYPE_REPORT_DESC 0x22 +/* @} */ + + +/** + * @name USB Device States + * @{ + */ +#define XUSBPS_DEVICE_ATTACHED 0x00 +#define XUSBPS_DEVICE_POWERED 0x01 +#define XUSBPS_DEVICE_DEFAULT 0x02 +#define XUSBPS_DEVICE_ADDRESSED 0x03 +#define XUSBPS_DEVICE_CONFIGURED 0x04 +#define XUSBPS_DEVICE_SUSPENDED 0x05 +/* @} */ + +/** + * @name Status type + * @{ + */ +#define XUSBPS_STATUS_MASK 0x3 +#define XUSBPS_STATUS_DEVICE 0x0 +#define XUSBPS_STATUS_INTERFACE 0x1 +#define XUSBPS_STATUS_ENDPOINT 0x2 +/* @} */ + +/** + * @name EP Types + * @{ + */ +#define XUSBPS_EP_CONTROL 0 +#define XUSBPS_EP_ISOCHRONOUS 1 +#define XUSBPS_EP_BULK 2 +#define XUSBPS_EP_INTERRUPT 3 +/* @} */ + + +/** + * @name Device Classes + * @{ + */ +#define XUSBPS_CLASS_HID 0x03 +#define XUSBPS_CLASS_STORAGE 0x08 +#define XUSBPS_CLASS_VENDOR 0xFF +/* @} */ + +/** + * @name Test Mode Selectors + * @{ + */ +#define XUSBPS_TEST_J 0x01 +#define XUSBPS_TEST_K 0x02 +#define XUSBPS_TEST_SE0_NAK 0x03 +#define XUSBPS_TEST_PACKET 0x04 +#define XUSBPS_TEST_FORCE_ENABLE 0x05 +/* @} */ + +/**************************** Type Definitions *******************************/ + +typedef struct { + u8 CurrentConfig; /* Configuration used by Ch9 code. */ +} XUsbPs_Local; + +/***************** Macros (Inline Functions) Definitions *********************/ +#define ALIGNMENT_CACHELINE __attribute__ ((aligned (32))) +#define DCACHE_INVALIDATE_SIZE(a) ((a) % 32) ? ((((a) / 32) * 32) + 32) : (a) + +/************************** Function Prototypes ******************************/ + +int XUsbPs_Ch9HandleSetupPacket(XUsbPs *InstancePtr, + XUsbPs_SetupData *SetupData); + + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_CH9_H */ diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.c b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.c new file mode 100755 index 00000000..71ccc76e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.c @@ -0,0 +1,368 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xusbps_ch9_storage.c + * + * This file contains the implementation of the storage specific chapter 9 code + * for the example. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ---------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ *
+ ******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include + +#include "xparameters.h" /* XPAR parameters */ +#include "xusbps.h" /* USB controller driver */ + +#include "xusbps_ch9.h" +#include "xusbps_ch9_storage.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +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_STD_DEV_DESC; + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 wTotalLength; + u8 bNumInterfaces; + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 bMaxPower; +}__attribute__((__packed__))USB_STD_CFG_DESC; + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndPoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; +}__attribute__((__packed__))USB_STD_IF_DESC; + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u8 bEndpointAddress; + u8 bmAttributes; + u16 wMaxPacketSize; + u8 bInterval; +}__attribute__((__packed__))USB_STD_EP_DESC; + +typedef struct { + u8 bLength; + u8 bDescriptorType; + u16 wLANGID[1]; +}__attribute__((__packed__))USB_STD_STRING_DESC; + +typedef struct { + USB_STD_CFG_DESC stdCfg; + USB_STD_IF_DESC ifCfg; + USB_STD_EP_DESC epCfg1; + USB_STD_EP_DESC epCfg2; +}__attribute__((__packed__))USB_CONFIG; + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +#define USB_ENDPOINT0_MAXP 0x40 + +#define USB_BULKIN_EP 1 +#define USB_BULKOUT_EP 1 + +#define USB_DEVICE_DESC 0x01 +#define USB_CONFIG_DESC 0x02 +#define USB_STRING_DESC 0x03 +#define USB_INTERFACE_CFG_DESC 0x04 +#define USB_ENDPOINT_CFG_DESC 0x05 + + +/*****************************************************************************/ +/** +* +* This function returns the device descriptor for the device. +* +* @param BufPtr is pointer to the buffer that is to be filled +* with the descriptor. +* @param BufLen is the size of the provided buffer. +* +* @return Length of the descriptor in the buffer on success. +* 0 on error. +* +******************************************************************************/ +u32 XUsbPs_Ch9SetupDevDescReply(u8 *BufPtr, u32 BufLen) +{ + USB_STD_DEV_DESC deviceDesc = { + sizeof(USB_STD_DEV_DESC), /* bLength */ + USB_DEVICE_DESC, /* bDescriptorType */ + be2les(0x0200), /* bcdUSB 2.0 */ + 0x00, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + USB_ENDPOINT0_MAXP, /* bMaxPackedSize0 */ + be2les(0x0d7d), /* idVendor */ + be2les(0x0100), /* idProduct */ + be2les(0x0100), /* bcdDevice */ + 0x01, /* iManufacturer */ + 0x02, /* iProduct */ + 0x03, /* iSerialNumber */ + 0x01 /* bNumConfigurations */ + }; + + /* Check buffer pointer is there and buffer is big enough. */ + if (!BufPtr) { + return 0; + } + + if (BufLen < sizeof(USB_STD_DEV_DESC)) { + return 0; + } + + memcpy(BufPtr, &deviceDesc, sizeof(USB_STD_DEV_DESC)); + + return sizeof(USB_STD_DEV_DESC); +} + + +/*****************************************************************************/ +/** +* +* This function returns the configuration descriptor for the device. +* +* @param BufPtr is the pointer to the buffer that is to be filled with +* the descriptor. +* @param BufLen is the size of the provided buffer. +* +* @return Length of the descriptor in the buffer on success. +* 0 on error. +* +******************************************************************************/ +u32 XUsbPs_Ch9SetupCfgDescReply(u8 *BufPtr, u32 BufLen) +{ + USB_CONFIG config = { + /* Std Config */ + {sizeof(USB_STD_CFG_DESC), /* bLength */ + USB_CONFIG_DESC, /* bDescriptorType */ + be2les(sizeof(USB_CONFIG)), /* wTotalLength */ + 0x01, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x04, /* iConfiguration */ + 0xc0, /* bmAttribute */ + 0x00}, /* bMaxPower */ + + /* Interface Config */ + {sizeof(USB_STD_IF_DESC), /* bLength */ + USB_INTERFACE_CFG_DESC, /* bDescriptorType */ + 0x00, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x02, /* bNumEndPoints */ + 0x08, /* bInterfaceClass */ + 0x06, /* bInterfaceSubClass */ + 0x50, /* bInterfaceProtocol */ + 0x05}, /* iInterface */ + + /* Bulk Out Endpoint Config */ + {sizeof(USB_STD_EP_DESC), /* bLength */ + USB_ENDPOINT_CFG_DESC, /* bDescriptorType */ + 0x00 | USB_BULKOUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttribute */ + be2les(0x200), /* wMaxPacketSize */ + 0x00}, /* bInterval */ + + /* Bulk In Endpoint Config */ + {sizeof(USB_STD_EP_DESC), /* bLength */ + USB_ENDPOINT_CFG_DESC, /* bDescriptorType */ + 0x80 | USB_BULKIN_EP, /* bEndpointAddress */ + 0x02, /* bmAttribute */ + be2les(0x200), /* wMaxPacketSize */ + 0x00} /* bInterval */ + }; + + /* Check buffer pointer is OK and buffer is big enough. */ + if (!BufPtr) { + return 0; + } + + if (BufLen < sizeof(USB_STD_DEV_DESC)) { + return 0; + } + + memcpy(BufPtr, &config, sizeof(USB_CONFIG)); + + return sizeof(USB_CONFIG); +} + + +/*****************************************************************************/ +/** +* +* This function returns a string descriptor for the given index. +* +* @param BufPtr is a pointer to the buffer that is to be filled with +* the descriptor. +* @param BufLen is the size of the provided buffer. +* @param Index is the index of the string for which the descriptor +* is requested. +* +* @return Length of the descriptor in the buffer on success. +* 0 on error. +* +******************************************************************************/ +u32 XUsbPs_Ch9SetupStrDescReply(u8 *BufPtr, u32 BufLen, u8 Index) +{ + int i; + + static char *StringList[] = { + "UNUSED", + "Xilinx", + "EPB USB Flash Drive Disk Emulation", + "2A49876D9CC1AA4", + "Default Configuration", + "Default Interface", + }; + char *String; + u32 StringLen; + u32 DescLen; + u8 TmpBuf[128]; + + USB_STD_STRING_DESC *StringDesc; + + if (!BufPtr) { + return 0; + } + + if (Index >= sizeof(StringList) / sizeof(char *)) { + return 0; + } + + String = StringList[Index]; + StringLen = strlen(String); + + StringDesc = (USB_STD_STRING_DESC *) TmpBuf; + + /* Index 0 is special as we can not represent the string required in + * the table above. Therefore we handle index 0 as a special case. + */ + if (0 == Index) { + StringDesc->bLength = 4; + StringDesc->bDescriptorType = USB_STRING_DESC; + StringDesc->wLANGID[0] = be2les(0x0409); + } + /* All other strings can be pulled from the table above. */ + else { + StringDesc->bLength = StringLen * 2 + 2; + StringDesc->bDescriptorType = USB_STRING_DESC; + + for (i = 0; i < StringLen; i++) { + StringDesc->wLANGID[i] = be2les((u16) String[i]); + } + } + DescLen = StringDesc->bLength; + + /* Check if the provided buffer is big enough to hold the descriptor. */ + if (DescLen > BufLen) { + return 0; + } + + memcpy(BufPtr, StringDesc, DescLen); + + return DescLen; +} + + +/*****************************************************************************/ +/** +* This function handles a "set configuration" request. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param ConfigIdx is the Index of the desired configuration. +* +* @return None +* +******************************************************************************/ +void XUsbPs_SetConfiguration(XUsbPs *InstancePtr, int ConfigIdx) +{ + Xil_AssertVoid(InstancePtr != NULL); + + /* We only have one configuration. Its index is 1. Ignore anything + * else. + */ + if (1 != ConfigIdx) { + return; + } + + XUsbPs_EpEnable(InstancePtr, 1, XUSBPS_EP_DIRECTION_OUT); + XUsbPs_EpEnable(InstancePtr, 1, XUSBPS_EP_DIRECTION_IN); + + /* Set BULK mode for both directions. */ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCR1_OFFSET, + XUSBPS_EPCR_TXT_BULK_MASK | + XUSBPS_EPCR_RXT_BULK_MASK | + XUSBPS_EPCR_TXR_MASK | + XUSBPS_EPCR_RXR_MASK); + + /* Prime the OUT endpoint. */ + XUsbPs_EpPrime(InstancePtr, 1, XUSBPS_EP_DIRECTION_OUT); +} diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.h b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.h new file mode 100755 index 00000000..156f5a06 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_ch9_storage.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xusbps_ch9_storage.h + * + * This file contains definitions used in the chapter 9 code. + * + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 
+ * + ******************************************************************************/ + +#ifndef XUSBPS_CH9_STORAGE_H +#define XUSBPS_CH9_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xusbps_hw.h" +#include "xil_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* Check where these defines need to go */ +#define be2le(val) (u32)(val) +#define be2les(x) (u16) (x) +#define htonl(val) ((((u32)(val) & 0x000000FF)<<24) | \ + (((u32)(val) & 0x0000FF00)<<8) | \ + (((u32)(val) & 0x00FF0000)>>8) | \ + (((u32)(val) & 0xFF000000)>>24)) + +#define htons(x) (u16) ((((u16)(x))<<8) | (((u16)(x))>>8)) + +/************************** Function Prototypes ******************************/ + +u32 XUsbPs_Ch9SetupDevDescReply(u8 *BufPtr, u32 BufLen); +u32 XUsbPs_Ch9SetupCfgDescReply(u8 *BufPtr, u32 BufLen); +u32 XUsbPs_Ch9SetupStrDescReply(u8 *BufPtr, u32 BufLen, u8 Index); +void XUsbPs_SetConfiguration(XUsbPs *InstancePtr, int ConfigIdx); + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_CH9_STORAGE_H */ diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.c b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.c new file mode 100755 index 00000000..cdb69e41 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.c @@ -0,0 +1,362 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xusbps_class_storage.c + * + * This file contains the implementation of the storage class code for the + * example. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ---------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 2.1   kpc  4/28/14  Align DMA buffers to cache line boundary
+ *
+ ******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include + +#include "xusbps.h" /* USB controller driver */ + +#include "xusbps_ch9_storage.h" +#include "xusbps_ch9.h" +#include "xusbps_class_storage.h" +#include "xil_printf.h" + +/* #define CLASS_STORAGE_DEBUG */ + +#ifdef CLASS_STORAGE_DEBUG +#define printf xil_printf +#endif + +/************************** Constant Definitions *****************************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/* Pre-manufactured response to the SCSI Inquirey command. + */ +const static SCSI_INQUIRY scsiInquiry ALIGNMENT_CACHELINE = { + 0x00, + 0x80, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x00, + {"Xilinx "}, /* Vendor ID: must be 8 characters long. */ + {"PS USB VirtDisk"}, /* Product ID: must be 16 characters long. */ + {"1.00"} /* Revision: must be 4 characters long. */ +}; +static u8 MaxLUN ALIGNMENT_CACHELINE = 0; +/* Buffer for virtual flash disk space. */ +static u8 VirtFlash[VFLASH_SIZE] ALIGNMENT_CACHELINE; + +static USB_CBW lastCBW ALIGNMENT_CACHELINE; + +/* Local transmit buffer for simple replies. */ +static u8 txBuffer[128] ALIGNMENT_CACHELINE; + +/*****************************************************************************/ +/** +* This function handles Reduced Block Command (RBC) requests from the host. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint on which the RBC was received. +* @param BufferPtr is the data buffer containing the RBC or data. +* @param BufferLen is the length of the data buffer. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUsbPs_HandleStorageReq(XUsbPs *InstancePtr, u8 EpNum, + u8 *BufferPtr, u32 BufferLen) +{ + USB_CBW *CBW; + u32 Offset; + static u8 *VirtFlashWritePointer = VirtFlash; + /* Static variables used for data transfers.*/ + static int rxBytesLeft; + + /* Current SCSI machine state. */ + static int phase = USB_EP_STATE_COMMAND; + + /* COMMAND phase. */ + if (USB_EP_STATE_COMMAND == phase) { + CBW = (USB_CBW *) BufferPtr; + + switch (CBW->CBWCB[0]) { + case USB_RBC_INQUIRY: +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: INQUIRY\n"); +#endif + XUsbPs_EpBufferSend(InstancePtr, 1, + (void *) &scsiInquiry, + sizeof(scsiInquiry)); + /* Send Success Status */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = 0; + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, (void *) CBW, 13); + break; + + + case USB_UFI_GET_CAP_LIST: + { + SCSI_CAP_LIST *CapList; + + CapList = (SCSI_CAP_LIST *) txBuffer; +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: CAPLIST\n"); +#endif + CapList->listLength = 8; + CapList->descCode = 3; + CapList->numBlocks = htonl(VFLASH_NUM_BLOCKS); + CapList->blockLength = htons(VFLASH_BLOCK_SIZE); + XUsbPs_EpBufferSend(InstancePtr, 1, txBuffer, + sizeof(SCSI_CAP_LIST)); + /* Send Success Status + */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = + be2le(be2le(CBW->dCBWDataTransferLength) - + sizeof(SCSI_CAP_LIST)); + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, (u8 *) CBW, 13); + break; + } + + case USB_RBC_READ_CAP: + { + SCSI_READ_CAPACITY *Cap; + + Cap = (SCSI_READ_CAPACITY *) txBuffer; +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: READCAP\n"); +#endif + Cap->numBlocks = htonl(VFLASH_NUM_BLOCKS - 1); + Cap->blockSize = htonl(VFLASH_BLOCK_SIZE); + XUsbPs_EpBufferSend(InstancePtr, 1, txBuffer, + sizeof(SCSI_READ_CAPACITY)); + /* Send Success Status */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = 0; + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, (u8 *) CBW, 13); + break; + } + + case USB_RBC_READ: + Offset = htonl(((SCSI_READ_WRITE *) CBW->CBWCB)-> + block) * VFLASH_BLOCK_SIZE; +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: READ Offset 0x%08x\n", (int) Offset); +#endif + XUsbPs_EpBufferSend(InstancePtr, 1, &VirtFlash[Offset], + htons(((SCSI_READ_WRITE *) CBW->CBWCB)-> + length) * VFLASH_BLOCK_SIZE); + /* Send Success Status */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = 0; + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, (u8 *) CBW, 13); + break; + + case USB_RBC_MODE_SENSE: +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: MODE SENSE\n"); +#endif + XUsbPs_EpBufferSend(InstancePtr, 1, + (u8 *) "\003\000\000\000", 4); + + /* Send Success Status */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = + be2le(be2le(CBW->dCBWDataTransferLength) - 4); + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, (u8 *) CBW, 13); + break; + + + case USB_RBC_TEST_UNIT_READY: + case USB_RBC_MEDIUM_REMOVAL: + case USB_RBC_VERIFY: +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: TEST UNIT READY\n"); +#endif + /* Send Success Status */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = 0; + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, (u8 *) CBW, 13); + break; + + + case USB_RBC_WRITE: + Offset = htonl(((SCSI_READ_WRITE *) CBW->CBWCB)-> + block) * VFLASH_BLOCK_SIZE; +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: WRITE Offset 0x%08x\n", (int) Offset); +#endif + VirtFlashWritePointer = &VirtFlash[Offset]; + /* Save the CBW for the DATA and STATUS phases. */ + lastCBW = *CBW; + rxBytesLeft = + htons(((SCSI_READ_WRITE *) CBW->CBWCB)->length) + * VFLASH_BLOCK_SIZE; + + phase = USB_EP_STATE_DATA; + break; + + + case USB_RBC_STARTSTOP_UNIT: + { + u8 immed; + + immed = ((SCSI_START_STOP *) CBW->CBWCB)->immed; +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: START/STOP unit: immed %02x\n", immed); +#endif + /* If the immediate bit is 0 we are supposed to send + * a success status. + */ + if (0 == (immed & 0x01)) { + /* Send Success Status */ + CBW->dCBWSignature = 0x55534253; + CBW->dCBWDataTransferLength = 0; + CBW->bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, + (u8 *) CBW, 13); + } + break; + } + + + /* Commands that we do not support for this example. */ + case 0x04: /* Format Unit */ + case 0x15: /* Mode Select */ + case 0x5e: /* Persistent Reserve In */ + case 0x5f: /* Persistent Reserve Out */ + case 0x17: /* Release */ + case 0x03: /* Request Sense */ + case 0x16: /* Reserve */ + case 0x35: /* Sync Cache */ + case 0x3b: /* Write Buffer */ +#ifdef CLASS_STORAGE_DEBUG + printf("SCSI: Got unhandled command %02x\n", CBW->CBWCB[0]); +#endif + default: + break; + } + } + /* DATA phase. + */ + else if (USB_EP_STATE_DATA == phase) { + switch (lastCBW.CBWCB[0]) { + case USB_RBC_WRITE: + /* Copy the data we just read into the VirtFlash buffer. */ + memcpy(VirtFlashWritePointer, BufferPtr, BufferLen); + VirtFlashWritePointer += BufferLen; + + rxBytesLeft -= BufferLen; + + if (rxBytesLeft <= 0) { + /* Send Success Status */ + lastCBW.dCBWSignature = 0x55534253; + lastCBW.dCBWDataTransferLength = 0; + lastCBW.bmCBWFlags = 0; + + XUsbPs_EpBufferSend(InstancePtr, 1, + (void *) &lastCBW, 13); + + phase = USB_EP_STATE_COMMAND; + } + break; + } + } +} + + +/*****************************************************************************/ +/** +* This function handles a Storage Class Setup request from the host. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param SetupData is the setup data structure containing the setup +* request. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUsbPs_ClassReq(XUsbPs *InstancePtr, XUsbPs_SetupData *SetupData) +{ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(SetupData != NULL); + + + switch (SetupData->bRequest) { + + case XUSBPS_CLASSREQ_MASS_STORAGE_RESET: + XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); + break; + + case XUSBPS_CLASSREQ_GET_MAX_LUN: + XUsbPs_EpBufferSend(InstancePtr, 0, &MaxLUN, 1); + break; + + default: + XUsbPs_EpStall(InstancePtr, 0, XUSBPS_EP_DIRECTION_IN); + break; + } +} + + diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.h b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.h new file mode 100755 index 00000000..ddf38bc6 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_class_storage.h @@ -0,0 +1,174 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xusbps_ch9_storage.h + * + * This file contains definitions used in the chapter 9 code. + * + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 
+ * + ******************************************************************************/ + +#ifndef XUSBPS_CLASS_STORAGE_H +#define XUSBPS_CLASS_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xusbps_ch9_storage.h" + +/************************** Constant Definitions *****************************/ + +/* Mass storage opcodes. + */ +#define USB_RBC_FORMAT 0x04 +#define USB_RBC_INQUIRY 0x12 +#define USB_RBC_MODE_SEL 0x15 +#define USB_RBC_MODE_SENSE 0x1a +#define USB_RBC_READ 0x28 +#define USB_RBC_READ_CAP 0x25 +#define USB_RBC_VERIFY 0x2f +#define USB_RBC_WRITE 0x2a +#define USB_RBC_STARTSTOP_UNIT 0x1b +#define USB_RBC_TEST_UNIT_READY 0x00 +#define USB_RBC_MEDIUM_REMOVAL 0x1e +#define USB_UFI_GET_CAP_LIST 0x23 + + +/* Virtual Flash memory related definitions. + */ +#define VFLASH_SIZE 0x100000 /* 1MB space */ +#define VFLASH_BLOCK_SIZE 0x200 +#define VFLASH_NUM_BLOCKS (VFLASH_SIZE/VFLASH_BLOCK_SIZE) + + +/* Class request opcodes. + */ +#define XUSBPS_CLASSREQ_MASS_STORAGE_RESET 0xFF +#define XUSBPS_CLASSREQ_GET_MAX_LUN 0xFE + + +/* SCSI machine states + */ +#define USB_EP_STATE_COMMAND 0 +#define USB_EP_STATE_DATA 1 +#define USB_EP_STATE_STATUS 2 + + +/**************************** Type Definitions *******************************/ + +/* The following structures define USB storage class requests. The details of + * the contents of those structures are not important in the context of this + * example. + */ +typedef struct { + u32 dCBWSignature; + u32 dCBWTag; + u32 dCBWDataTransferLength; + u8 bmCBWFlags; + u8 cCBWLUN; + u8 bCBWCBLength; + u8 CBWCB[16]; +} __attribute__((__packed__))USB_CBW; + +typedef struct { + u8 deviceType; + u8 rmb; + u8 version; + u8 blah; + u8 additionalLength; + u8 sccs; + u8 info0; + u8 info1; + u8 vendorID[8]; + u8 productID[16]; + u8 revision[4]; +} __attribute__((__packed__))SCSI_INQUIRY; + +typedef struct { + u8 reserved[3]; + u8 listLength; + u32 numBlocks; + u8 descCode; + u8 blockLengthMSB; + u16 blockLength; +} __attribute__((__packed__))SCSI_CAP_LIST; + +typedef struct { + u32 numBlocks; + u32 blockSize; +} __attribute__((__packed__))SCSI_READ_CAPACITY; + +typedef struct { + u8 opCode; + u8 reserved1; + u32 block; + u8 reserved2; + u16 length; + u8 control; +} __attribute__((__packed__))SCSI_READ_WRITE; + +typedef struct { + u8 opCode; + u8 immed; + u8 reserved1; + u8 reserved2; + u8 start; + u8 control; +} __attribute__((__packed__))SCSI_START_STOP; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +void XUsbPs_HandleStorageReq(XUsbPs *InstancePtr, u8 EpNum, + u8 *BufferPtr, u32 BufferLen); +void XUsbPs_ClassReq(XUsbPs *InstancePtr, XUsbPs_SetupData *SetupData); + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_CLASS_STORAGE_H */ diff --git a/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_intr_example.c b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_intr_example.c new file mode 100755 index 00000000..e3ade510 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/examples/xusbps_intr_example.c @@ -0,0 +1,574 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xusbps_intr_example.c +* +* This file contains an example of how to use the USB driver with the USB +* controller in DEVICE mode. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- ----------------------------------------------------
+* 1.00a wgr/nm  10/09/10 First release
+* 1.01a nm      03/05/10 Included xpseudo_asm.h instead of xpseudo_asm_gcc.h
+* 1.04a nm      02/05/13 Fixed CR# 696550.
+*		         Added template code for Vendor request.
+* 1.06a kpc		11/11/13 Fixed CR#759458, cacheInvalidate size should be
+*				 ailgned to ccahe line size.
+* 2.1   kpc    04/28/14 Cleanup and removed unused functions
+*
+******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" /* XPAR parameters */ +#include "xusbps.h" /* USB controller driver */ +#include "xscugic.h" +#include "xusbps_ch9.h" /* Generic Chapter 9 handling code */ +#include "xusbps_class_storage.h" /* Storage class handling code */ +#include "xil_exception.h" +#include "xpseudo_asm.h" +#include "xreg_cortexa9.h" +#include "xil_cache.h" +#include +#include +#include + +/************************** Constant Definitions *****************************/ +#define MEMORY_SIZE (64 * 1024) +u8 Buffer[MEMORY_SIZE] ALIGNMENT_CACHELINE; + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static int UsbIntrExample(XScuGic *IntcInstancePtr, XUsbPs *UsbInstancePtr, + u16 UsbDeviceId, u16 UsbIntrId); + +static void UsbIntrHandler(void *CallBackRef, u32 Mask); +static void XUsbPs_Ep0EventHandler(void *CallBackRef, u8 EpNum, + u8 EventType, void *Data); +static void XUsbPs_Ep1EventHandler(void *CallBackRef, u8 EpNum, + u8 EventType, void *Data); +static int UsbSetupIntrSystem(XScuGic *IntcInstancePtr, + XUsbPs *UsbInstancePtr, u16 UsbIntrId); +static void UsbDisableIntrSystem(XScuGic *IntcInstancePtr, u16 UsbIntrId); + + +/************************** Variable Definitions *****************************/ + +/* The instances to support the device drivers are global such that the + * are initialized to zero each time the program runs. + */ +static XScuGic IntcInstance; /* The instance of the IRQ Controller */ +static XUsbPs UsbInstance; /* The instance of the USB Controller */ + +static volatile int NumIrqs = 0; +static volatile int NumReceivedFrames = 0; + + +/*****************************************************************************/ +/** + * + * Main function to call the USB interrupt example. + * + * @param None + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE on error + * + ******************************************************************************/ + +int main(void) +{ + int Status; + + /* Run the USB Interrupt example.*/ + Status = UsbIntrExample(&IntcInstance, &UsbInstance, + XPAR_XUSBPS_0_DEVICE_ID, XPAR_XUSBPS_0_INTR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * + * This function does a minimal DEVICE mode setup on the USB device and driver + * as a design example. The purpose of this function is to illustrate how to + * set up a USB flash disk emulation system. + * + * + * @param IntcInstancePtr is a pointer to the instance of the INTC driver. + * @param UsbInstancePtr is a pointer to the instance of USB driver. + * @param UsbDeviceId is the Device ID of the USB Controller and is the + * XPAR__DEVICE_ID value from xparameters.h. + * @param UsbIntrId is the Interrupt Id and is typically + * XPAR___IP2INTC_IRPT_INTR value + * from xparameters.h. + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE on error + * + ******************************************************************************/ +static int UsbIntrExample(XScuGic *IntcInstancePtr, XUsbPs *UsbInstancePtr, + u16 UsbDeviceId, u16 UsbIntrId) +{ + int Status; + u8 *MemPtr = NULL; + int ReturnStatus = XST_FAILURE; + + /* For this example we only configure 2 endpoints: + * Endpoint 0 (default control endpoint) + * Endpoint 1 (BULK data endpoint) + */ + const u8 NumEndpoints = 2; + + XUsbPs_Config *UsbConfigPtr; + XUsbPs_DeviceConfig DeviceConfig; + + /* Initialize the USB driver so that it's ready to use, + * specify the controller ID that is generated in xparameters.h + */ + UsbConfigPtr = XUsbPs_LookupConfig(UsbDeviceId); + if (NULL == UsbConfigPtr) { + goto out; + } + + + /* We are passing the physical base address as the third argument + * because the physical and virtual base address are the same in our + * example. For systems that support virtual memory, the third + * argument needs to be the virtual base address. + */ + Status = XUsbPs_CfgInitialize(UsbInstancePtr, + UsbConfigPtr, + UsbConfigPtr->BaseAddress); + if (XST_SUCCESS != Status) { + goto out; + } + + /* Set up the interrupt subsystem. + */ + Status = UsbSetupIntrSystem(IntcInstancePtr, + UsbInstancePtr, + UsbIntrId); + if (XST_SUCCESS != Status) + { + goto out; + } + + /* Configuration of the DEVICE side of the controller happens in + * multiple stages. + * + * 1) The user configures the desired endpoint configuration using the + * XUsbPs_DeviceConfig data structure. This includes the number of + * endpoints, the number of Transfer Descriptors for each endpoint + * (each endpoint can have a different number of Transfer Descriptors) + * and the buffer size for the OUT (receive) endpoints. Each endpoint + * can have different buffer sizes. + * + * 2) Request the required size of DMAable memory from the driver using + * the XUsbPs_DeviceMemRequired() call. + * + * 3) Allocate the DMAable memory and set up the DMAMemVirt and + * DMAMemPhys members in the XUsbPs_DeviceConfig data structure. + * + * 4) Configure the DEVICE side of the controller by calling the + * XUsbPs_ConfigureDevice() function. + */ + + /* + * For this example we only configure Endpoint 0 and Endpoint 1. + * + * Bufsize = 0 indicates that there is no buffer allocated for OUT + * (receive) endpoint 0. Endpoint 0 is a control endpoint and we only + * receive control packets on that endpoint. Control packets are 8 + * bytes in size and are received into the Queue Head's Setup Buffer. + * Therefore, no additional buffer space is needed. + */ + DeviceConfig.EpCfg[0].Out.Type = XUSBPS_EP_TYPE_CONTROL; + DeviceConfig.EpCfg[0].Out.NumBufs = 2; + DeviceConfig.EpCfg[0].Out.BufSize = 64; + DeviceConfig.EpCfg[0].Out.MaxPacketSize = 64; + DeviceConfig.EpCfg[0].In.Type = XUSBPS_EP_TYPE_CONTROL; + DeviceConfig.EpCfg[0].In.NumBufs = 2; + DeviceConfig.EpCfg[0].In.MaxPacketSize = 64; + + DeviceConfig.EpCfg[1].Out.Type = XUSBPS_EP_TYPE_BULK; + DeviceConfig.EpCfg[1].Out.NumBufs = 16; + DeviceConfig.EpCfg[1].Out.BufSize = 512; + DeviceConfig.EpCfg[1].Out.MaxPacketSize = 512; + DeviceConfig.EpCfg[1].In.Type = XUSBPS_EP_TYPE_BULK; + DeviceConfig.EpCfg[1].In.NumBufs = 16; + DeviceConfig.EpCfg[1].In.MaxPacketSize = 512; + + DeviceConfig.NumEndpoints = NumEndpoints; + + MemPtr = (u8 *)&Buffer[0]; + memset(MemPtr,0,MEMORY_SIZE); + Xil_DCacheFlushRange((unsigned int)MemPtr, MEMORY_SIZE); + + /* Finish the configuration of the DeviceConfig structure and configure + * the DEVICE side of the controller. + */ + DeviceConfig.DMAMemPhys = (u32) MemPtr; + + Status = XUsbPs_ConfigureDevice(UsbInstancePtr, &DeviceConfig); + if (XST_SUCCESS != Status) { + goto out; + } + + /* Set the handler for receiving frames. */ + Status = XUsbPs_IntrSetHandler(UsbInstancePtr, UsbIntrHandler, NULL, + XUSBPS_IXR_UE_MASK); + if (XST_SUCCESS != Status) { + goto out; + } + + /* Set the handler for handling endpoint 0 events. This is where we + * will receive and handle the Setup packet from the host. + */ + Status = XUsbPs_EpSetHandler(UsbInstancePtr, 0, + XUSBPS_EP_DIRECTION_OUT, + XUsbPs_Ep0EventHandler, UsbInstancePtr); + + /* Set the handler for handling endpoint 1 events. + * + * Note that for this example we do not need to register a handler for + * TX complete events as we only send data using static data buffers + * that do not need to be free()d or returned to the OS after they have + * been sent. + */ + Status = XUsbPs_EpSetHandler(UsbInstancePtr, 1, + XUSBPS_EP_DIRECTION_OUT, + XUsbPs_Ep1EventHandler, UsbInstancePtr); + + /* Enable the interrupts. */ + XUsbPs_IntrEnable(UsbInstancePtr, XUSBPS_IXR_UR_MASK | + XUSBPS_IXR_UI_MASK); + + + /* Start the USB engine */ + XUsbPs_Start(UsbInstancePtr); + + /* At this point we wait for the user to plug in the usb plug. This + * will cause the host to send USB packets. Once we received something, + * we clean up and stop the controller. + * + * This will not really work if we want to use the USB storage + * example. What can we do instead? + */ + while (NumReceivedFrames < 1) { + /* NOP */ + } + + + /* Set return code to indicate success and fall through to clean-up + * code. + */ + ReturnStatus = XST_SUCCESS; + +out: + /* Clean up. It's always safe to disable interrupts and clear the + * handlers, even if they have not been enabled/set. The same is true + * for disabling the interrupt subsystem. + */ + XUsbPs_Stop(UsbInstancePtr); + XUsbPs_IntrDisable(UsbInstancePtr, XUSBPS_IXR_ALL); + (int) XUsbPs_IntrSetHandler(UsbInstancePtr, NULL, NULL, 0); + + UsbDisableIntrSystem(IntcInstancePtr, UsbIntrId); + + /* Free allocated memory. + */ + if (NULL != UsbInstancePtr->UserDataPtr) { + free(UsbInstancePtr->UserDataPtr); + } + return ReturnStatus; +} + +/*****************************************************************************/ +/** + * + * This function is the handler which performs processing for the USB driver. + * It is called from an interrupt context such that the amount of processing + * performed should be minimized. + * + * This handler provides an example of how to handle USB interrupts and + * is application specific. + * + * @param CallBackRef is the Upper layer callback reference passed back + * when the callback function is invoked. + * @param Mask is the Interrupt Mask. + * @param CallBackRef is the User data reference. + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE on error + * + * @note None. + * + ******************************************************************************/ +static void UsbIntrHandler(void *CallBackRef, u32 Mask) +{ + NumIrqs++; +} + + +/*****************************************************************************/ +/** +* This funtion is registered to handle callbacks for endpoint 0 (Control). +* +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. +* +* +* @param CallBackRef is the reference passed in when the function +* was registered. +* @param EpNum is the Number of the endpoint on which the event occured. +* @param EventType is type of the event that occured. +* +* @return None. +* +******************************************************************************/ +static void XUsbPs_Ep0EventHandler(void *CallBackRef, u8 EpNum, + u8 EventType, void *Data) +{ + XUsbPs *InstancePtr; + int Status; + XUsbPs_SetupData SetupData; + u8 *BufferPtr; + u32 BufferLen; + u32 Handle; + + + Xil_AssertVoid(NULL != CallBackRef); + + InstancePtr = (XUsbPs *) CallBackRef; + + switch (EventType) { + + /* Handle the Setup Packets received on Endpoint 0. */ + case XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED: + Status = XUsbPs_EpGetSetupData(InstancePtr, EpNum, &SetupData); + if (XST_SUCCESS == Status) { + /* Handle the setup packet. */ + (int) XUsbPs_Ch9HandleSetupPacket(InstancePtr, + &SetupData); + } + break; + + /* We get data RX events for 0 length packets on endpoint 0. We receive + * and immediately release them again here, but there's no action to be + * taken. + */ + case XUSBPS_EP_EVENT_DATA_RX: + /* Get the data buffer. */ + Status = XUsbPs_EpBufferReceive(InstancePtr, EpNum, + &BufferPtr, &BufferLen, &Handle); + if (XST_SUCCESS == Status) { + /* Return the buffer. */ + XUsbPs_EpBufferRelease(Handle); + } + break; + + default: + /* Unhandled event. Ignore. */ + break; + } +} + + +/*****************************************************************************/ +/** +* This funtion is registered to handle callbacks for endpoint 1 (Bulk data). +* +* It is called from an interrupt context such that the amount of processing +* performed should be minimized. +* +* +* @param CallBackRef is the reference passed in when the function was +* registered. +* @param EpNum is the Number of the endpoint on which the event occured. +* @param EventType is type of the event that occured. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XUsbPs_Ep1EventHandler(void *CallBackRef, u8 EpNum, + u8 EventType, void *Data) +{ + XUsbPs *InstancePtr; + int Status; + u8 *BufferPtr; + u32 BufferLen; + u32 InavalidateLen; + u32 Handle; + + + Xil_AssertVoid(NULL != CallBackRef); + + InstancePtr = (XUsbPs *) CallBackRef; + + switch (EventType) { + case XUSBPS_EP_EVENT_DATA_RX: + /* Get the data buffer.*/ + Status = XUsbPs_EpBufferReceive(InstancePtr, EpNum, + &BufferPtr, &BufferLen, &Handle); + /* Invalidate the Buffer Pointer */ + InavalidateLen = BufferLen; + if (BufferLen % 32) { + InavalidateLen = (BufferLen/32) * 32 + 32; + } + + Xil_DCacheInvalidateRange((unsigned int)BufferPtr, + InavalidateLen); + if (XST_SUCCESS == Status) { + /* Handle the storage class request. */ + XUsbPs_HandleStorageReq(InstancePtr, EpNum, + BufferPtr, BufferLen); + /* Release the buffer. */ + XUsbPs_EpBufferRelease(Handle); + } + break; + + default: + /* Unhandled event. Ignore. */ + break; + } +} + +/*****************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur for +* the USB controller. This function is application specific since the actual +* system may or may not have an interrupt controller. The USB controller could +* be directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param IntcInstancePtr is a pointer to instance of the Intc controller. +* @param UsbInstancePtr is a pointer to instance of the USB controller. +* @param UsbIntrId is the Interrupt Id and is typically +* XPAR___VEC_ID value +* from xparameters.h +* +* @return +* - XST_SUCCESS if successful +* - XST_FAILURE on error +* +******************************************************************************/ +static int UsbSetupIntrSystem(XScuGic *IntcInstancePtr, + XUsbPs *UsbInstancePtr, u16 UsbIntrId) +{ + int Status; + XScuGic_Config *IntcConfig; + + /* + * Initialize the interrupt controller driver so that it is ready to + * use. + */ + IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); + if (NULL == IntcConfig) { + return XST_FAILURE; + } + Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Xil_ExceptionInit(); + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + IntcInstancePtr); + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + Status = XScuGic_Connect(IntcInstancePtr, UsbIntrId, + (Xil_ExceptionHandler)XUsbPs_IntrHandler, + (void *)UsbInstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + /* + * Enable the interrupt for the device. + */ + XScuGic_Enable(IntcInstancePtr, UsbIntrId); + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function disables the interrupts that occur for the USB controller. +* +* @param IntcInstancePtr is a pointer to instance of the INTC driver. +* @param UsbIntrId is the Interrupt Id and is typically +* XPAR___VEC_ID value +* from xparameters.h +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void UsbDisableIntrSystem(XScuGic *IntcInstancePtr, u16 UsbIntrId) +{ + /* Disconnect and disable the interrupt for the USB controller. */ + XScuGic_Disconnect(IntcInstancePtr, UsbIntrId); +} diff --git a/XilinxProcessorIPLib/drivers/usbps/src/Makefile b/XilinxProcessorIPLib/drivers/usbps/src/Makefile new file mode 100755 index 00000000..7cf97e2f --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/Makefile @@ -0,0 +1,41 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xusbps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling usbps" + +xusbps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xusbps_includes + +xusbps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} + diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps.c b/XilinxProcessorIPLib/drivers/usbps/src/xusbps.c new file mode 100755 index 00000000..7f723a92 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps.c @@ -0,0 +1,361 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** + * @file xusbps.c + * + * The XUsbPs driver. Functions in this file are the minimum required + * functions for this driver. See xusbps.h for a detailed description of the + * driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 2.1   kpc 04/28/14 Removed ununsed functions
+ * 
+ ******************************************************************************/ + +/***************************** Include Files **********************************/ +#include +#include "xusbps.h" + +/************************** Constant Definitions ******************************/ + +/**************************** Type Definitions ********************************/ + +/***************** Macros (Inline Functions) Definitions **********************/ + +/************************** Variable Definitions ******************************/ + +/************************** Function Prototypes *******************************/ + +/*****************************************************************************/ +/** +* +* This function initializes a XUsbPs instance/driver. +* +* The initialization entails: +* - Initialize all members of the XUsbPs structure. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param ConfigPtr is a pointer to a XUsbPs_Config configuration +* structure. This structure will contain the requested +* configuration for the device. Typically, this is a local +* structure and the content of which will be copied into the +* configuration structure within XUsbPs. +* @param VirtBaseAddress is the base address of the device. For systems +* with virtual memory, this address must be the virtual address +* of the device. +* For systems that do not support virtual memory this address +* should be the physical address of the device. For backwards +* compatibilty NULL may be passed in systems that do not support +* virtual memory (deprecated). +* +* @return +* - XST_SUCCESS no errors occured. +* - XST_FAILURE an error occured during initialization. +* +* @note +* After calling XUsbPs_CfgInitialize() the controller +* IS NOT READY for use. Before the controller can be used its +* DEVICE parameters must be configured. See xusbps.h +* for details. +* +******************************************************************************/ +int XUsbPs_CfgInitialize(XUsbPs *InstancePtr, + const XUsbPs_Config *ConfigPtr, u32 VirtBaseAddress) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* Copy the config structure. */ + InstancePtr->Config = *ConfigPtr; + + /* Check if the user provided a non-NULL base address. If so, we have + * to overwrite the base address in the configuration structure. + */ + if (0 != VirtBaseAddress) { + InstancePtr->Config.BaseAddress = VirtBaseAddress; + } + + /* Initialize the XUsbPs structure to default values. */ + InstancePtr->CurrentAltSetting = XUSBPS_DEFAULT_ALT_SETTING; + + InstancePtr->HandlerFunc = NULL; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function performs device reset, device is stopped at the end. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XUsbPs_DeviceReset(XUsbPs *InstancePtr) +{ + int Timeout; + + /* Clear all setup token semaphores by reading the + * XUSBPS_EPSTAT_OFFSET register and writing its value back to + * itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET)); + + /* Clear all the endpoint complete status bits by reading the + * XUSBPS_EPCOMPL_OFFSET register and writings its value back + * to itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET)); + + /* Cancel all endpoint prime status by waiting until all bits + * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF + * to XUSBPS_EPFLUSH_OFFSET. + * + * Avoid hanging here by using a Timeout counter... + */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET) & + XUSBPS_EP_ALL_MASK) && --Timeout) { + /* NOP */ + } + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); + + XUsbPs_Stop(InstancePtr); + + /* Write to CR register for controller reset */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET) | XUSBPS_CMD_RST_MASK); + + /* Wait for reset to finish, hardware clears the reset bit once done */ + Timeout = 1000000; + while((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET) & + XUSBPS_CMD_RST_MASK) && --Timeout) { + /* NOP */ + } +} +/*****************************************************************************/ +/** +* +* This function resets the USB device. All the configuration registers are +* reset to their default values. The function waits until the reset operation +* is complete or for a certain duration within which the reset operation is +* expected to be completed. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - XST_SUCCESS Reset operation completed successfully. +* - XST_FAILURE Reset operation timed out. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_Reset(XUsbPs *InstancePtr) +{ + int Timeout; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Write a 1 to the RESET bit. The RESET bit is cleared by HW once the + * RESET is complete. + * + * We are going to wait for the RESET bit to clear before we return + * from this function. Unfortunately we do not have timers available at + * this point to determine when we should report a Timeout. + * + * However, by using a large number for the poll loop we can assume + * that the polling operation will take longer than the expected time + * the HW needs to RESET. If the poll loop expires we can assume a + * Timeout. The drawback is that on a slow system (and even on a fast + * system) this can lead to _very_ long Timeout periods. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET, XUSBPS_CMD_RST_MASK); + + + /* Wait for the RESET bit to be cleared by HW. */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_CMD_OFFSET) & + XUSBPS_CMD_RST_MASK) && --Timeout) { + /* NOP */ + } + + if (0 == Timeout) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * USB Suspend + * + * In order to conserve power, USB devices automatically enter the suspended + * state when the device has observed no bus traffic for a specified period. + * When suspended, the USB device maintains any internal status, including its + * address and configuration. Attached devices must be prepared to suspend at + * any time they are powered, regardless of if they have been assigned a + * non-default address, are configured, or neither. Bus activity may cease due + * to the host entering a suspend mode of its own. In addition, a USB device + * shall also enter the suspended state when the hub port it is attached to is + * disabled. + * + * A USB device exits suspend mode when there is bus activity. A USB device may + * also request the host to exit suspend mode or selective suspend by using + * electrical signaling to indicate remote wakeup. The ability of a device to + * signal remote wakeup is optional. If the USB device is capable of remote + * wakeup signaling, the device must support the ability of the host to enable + * and disable this capability. When the device is reset, remote wakeup + * signaling must be disabled. + * + * @param InstancePtr is a pointer to XUsbPs instance of the controller. + * + * @return + * - XST_SUCCESS if the USB device has entered Suspend mode + * successfully + * - XST_FAILURE on any error + * + * @note None. + * + ******************************************************************************/ +int XUsbPs_Suspend(const XUsbPs *InstancePtr) +{ + (void) InstancePtr; + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* USB Resume +* + If the USB controller is suspended, its operation is resumed when any +* non-idle signaling is received on its upstream facing port. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - XST_SUCCESS if the USB device has Resumed successfully +* - XST_FAILURE on any error +* +* @note None. +* +******************************************************************************/ +int XUsbPs_Resume(const XUsbPs *InstancePtr) +{ + (void) InstancePtr; + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* USB Assert Resume +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - XST_SUCCESS if the USB device has Resumed successfully +* - XST_FAILURE on any error +* +* @note None. +* +******************************************************************************/ + +int XUsbPs_RequestHostResume(const XUsbPs *InstancePtr) +{ + (void) InstancePtr; + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* This functions sets the controller's DEVICE address. It also sets the +* advance bit so the controller will wait for the next IN-ACK before the new +* address takes effect. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param Address is the Address of the device. +* +* @return +* - XST_SUCCESS: Address set successfully. +* - XST_FAILURE: An error occured. +* - XST_INVALID_PARAM: Invalid parameter passed, e.g. address +* value too big. +* +* @note None. +* +*****************************************************************************/ +int XUsbPs_SetDeviceAddress(XUsbPs *InstancePtr, u8 Address) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check address range validity. */ + if (Address > XUSBPS_DEVICEADDR_MAX) { + return XST_INVALID_PARAM; + } + + /* Set the address register with the Address value provided. Also set + * the Address Advance Bit. This will cause the address to be set only + * after an IN occured and has been ACKed on the endpoint. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_DEVICEADDR_OFFSET, + (Address << XUSBPS_DEVICEADDR_ADDR_SHIFT) | + XUSBPS_DEVICEADDR_DEVICEAADV_MASK); + + return XST_SUCCESS; +} + diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps.h b/XilinxProcessorIPLib/drivers/usbps/src/xusbps.h new file mode 100755 index 00000000..ace093a7 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps.h @@ -0,0 +1,1082 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xusbps.h + * + * This file contains the implementation of the XUsbPs driver. It is the + * driver for an USB controller in DEVICE or HOST mode. + * + *

Introduction

+ * + * The Spartan-3AF Embedded Peripheral Block contains a USB controller for + * communication with serial peripherals or hosts. The USB controller supports + * Host, Device and On the Go (OTG) applications. + * + *

USB Controller Features

+ * + * - Supports Low Speed USB 1.1 (1.5Mbps), Full Speed USB 1.1 (12Mbps), and + * High Speed USB 2.0 (480Mbps) data speeds + * - Supports Device, Host and OTG operational modes + * - ULPI transceiver interface for USB 2.0 operation + * - Integrated USB Full and Low speed serial transceiver interfaces for lowest + * cost connections + * + *

Initialization & Configuration

+ * + * The configuration of the USB driver happens in multiple stages: + * + * - (a) Configuration of the basic parameters: + * In this stage the basic parameters for the driver are configured, + * including the base address and the controller ID. + * + * - (b) Configuration of the DEVICE endpoints (if applicable): + * If DEVICE mode is desired, the endpoints of the controller need to be + * configured using the XUsbPs_DeviceConfig data structure. Once the + * endpoint configuration is set up in the data structure, The user then + * needs to allocate the required amount of DMAable memory and + * finalize the configuration of the XUsbPs_DeviceConfig data structure, + * e.g. setting the DMAMemVirt and DMAMemPhys members. + * + * - (c) Configuration of the DEVICE modes: + * In the second stage the parameters for DEVICE are configured. + * The caller only needs to configure the modes that are + * actually used. Configuration is done with the: + * XUsbPs_ConfigureDevice() + * Configuration parameters are defined and passed + * into these functions using the: + * XUsbPs_DeviceConfig data structures. + * + * + *

USB Device Endpoints

+ * + * The USB core supports up to 4 endpoints. Each endpoint has two directions, + * an OUT (RX) and an IN (TX) direction. Note that the direction is viewed from + * the host's perspective. Endpoint 0 defaults to be the control endpoint and + * does not need to be set up. Other endpoints need to be configured and set up + * depending on the application. Only endpoints that are actuelly used by the + * application need to be initialized. + * See the example code (xusbps_intr_example.c) for more information. + * + * + *

Interrupt Handling

+ * + * The USB core uses one interrupt line to report interrupts to the CPU. + * Interrupts are handled by the driver's interrupt handler function + * XUsbPs_IntrHandler(). + * It has to be registered with the OS's interrupt subsystem. The driver's + * interrupt handler divides incoming interrupts into two categories: + * + * - General device interrupts + * - Endopint related interrupts + * + * The user (typically the adapter layer) can register general interrupt + * handler fucntions and endpoint specific interrupt handler functions with the + * driver to receive those interrupts by calling the + * XUsbPs_IntrSetHandler() + * and + * XUsbPs_EpSetHandler() + * functions respectively. Calling these functions with a NULL pointer as the + * argument for the function pointer will "clear" the handler function. + * + * The user can register one handler function for the generic interrupts and + * two handler functions for each endpoint, one for the RX (OUT) and one for + * the TX (IN) direction. For some applications it may be useful to register a + * single endpoint handler function for muliple endpoints/directions. + * + * When a callback function is called by the driver, parameters identifying the + * type of the interrupt will be passed into the handler functions. For general + * interrupts the interrupt mask will be passed into the handler function. For + * endpoint interrupts the parameters include the number of the endpoint, the + * direction (OUT/IN) and the type of the interrupt. + * + * + *

Data buffer handling

+ * + * Data buffers are sent to and received from endpoint using the + * XUsbPs_EpBufferSend(), XUsbPs_EpBufferSendWithZLT() + * and + * XUsbPs_EpBufferReceive() + * functions. + * + * User data buffer size is limited to 16 Kbytes. If the user wants to send a + * data buffer that is bigger than this limit it needs to break down the data + * buffer into multiple fragments and send the fragments individually. + * + * From the controller perspective Data buffers can be aligned at any boundary. + * if the buffers are from cache region then the buffer and buffer size should + * be aligned to cache line aligned + * + * + *

Zero copy

+ * + * The driver uses a zero copy mechanism which imposes certain restrictions to + * the way the user can handle the data buffers. + * + * One restriction is that the user needs to release a buffer after it is done + * processing the data in the buffer. + * + * Similarly, when the user sends a data buffer it MUST not re-use the buffer + * until it is notified by the driver that the buffer has been transmitted. The + * driver will notify the user via the registered endpoint interrupt handling + * function by sending a XUSBPS_EP_EVENT_DATA_TX event. + * + * + *

DMA

+ * + * The driver uses DMA internally to move data from/to memory. This behaviour + * is transparent to the user. Keeping the DMA handling hidden from the user + * has the advantage that the same API can be used with USB cores that do not + * support DMA. + * + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ----------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.02a wgr  05/16/12 Removed comments as they are showing up in SDK
+ *		       Tabs for CR 657898
+ * 1.03a nm   09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 1.04a nm   10/23/12 Fixed CR# 679106.
+ *	      11/02/12 Fixed CR# 683931. Mult bits are set properly in dQH.
+ * 2.00a kpc 04/03/14 Fixed CR#777763. Corrected the setup tripwire macro val.
+ * 2.1   kpc 04/28/14 Removed unused function prototypes
+ * 
+ * + ******************************************************************************/ + +#ifndef XUSBPS_H +#define XUSBPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xusbps_hw.h" +#include "xil_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/** + * @name System hang prevention Timeout counter value. + * + * This value is used throughout the code to initialize a Timeout counter that + * is used when hard polling a register. The ides is to initialize the Timeout + * counter to a value that is longer than any expected Timeout but short enough + * so the system will continue to work and report an error while the user is + * still paying attention. A reasonable Timeout time would be about 10 seconds. + * The XUSBPS_TIMEOUT_COUNTER value should be chosen so a polling loop would + * run about 10 seconds before a Timeout is detected. For example: + * + * int Timeout = XUSBPS_TIMEOUT_COUNTER; + * while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + * XUSBPS_CMD_OFFSET) & + * XUSBPS_CMD_RST_MASK) && --Timeout) { + * ; + * } + * if (0 == Timeout) { + * return XST_FAILURE; + * } + * + */ +#define XUSBPS_TIMEOUT_COUNTER 1000000 + + +/** + * @name Endpoint Direction (bitmask) + * Definitions to be used with Endpoint related function that require a + * 'Direction' parameter. + * + * NOTE: + * The direction is always defined from the perspective of the HOST! This + * means that an IN endpoint on the controller is used for sending data while + * the OUT endpoint on the controller is used for receiving data. + * @{ + */ +#define XUSBPS_EP_DIRECTION_IN 0x01 /**< Endpoint direction IN. */ +#define XUSBPS_EP_DIRECTION_OUT 0x02 /**< Endpoint direction OUT. */ +/* @} */ + + +/** + * @name Endpoint Type + * Definitions to be used with Endpoint related functions that require a 'Type' + * parameter. + * @{ + */ +#define XUSBPS_EP_TYPE_NONE 0 /**< Endpoint is not used. */ +#define XUSBPS_EP_TYPE_CONTROL 1 /**< Endpoint for Control Transfers */ +#define XUSBPS_EP_TYPE_ISOCHRONOUS 2 /**< Endpoint for isochronous data */ +#define XUSBPS_EP_TYPE_BULK 3 /**< Endpoint for BULK Transfers. */ +#define XUSBPS_EP_TYPE_INTERRUPT 4 /**< Endpoint for interrupt Transfers */ +/* @} */ + +/** + * Endpoint Max Packet Length in DeviceConfig is a coded value, ch9.6.6. + * + * @{ + */ +#define ENDPOINT_MAXP_LENGTH 0x400 +#define ENDPOINT_MAXP_MULT_MASK 0xC00 +#define ENDPOINT_MAXP_MULT_SHIFT 10 +/* @} */ + +/** + * @name Field names for status retrieval + * Definitions for the XUsbPs_GetStatus() function call 'StatusType' + * parameter. + * @{ + */ +#define XUSBPS_EP_STS_ADDRESS 1 /**< Address of controller. */ +#define XUSBPS_EP_STS_CONTROLLER_STATE 2 /**< Current controller state. */ +/* @} */ + + + +/** + * @name USB Default alternate setting + * + * @{ + */ +#define XUSBPS_DEFAULT_ALT_SETTING 0 /**< The default alternate setting is 0 */ +/* @} */ + +/** + * @name Endpoint event types + * Definitions that are used to identify events that occur on endpoints. Passed + * to the endpoint event handler functions registered with + * XUsbPs_EpSetHandler(). + * @{ + */ +#define XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED 0x01 + /**< Setup data has been received on the enpoint. */ +#define XUSBPS_EP_EVENT_DATA_RX 0x02 + /**< Data frame has been received on the endpoint. */ +#define XUSBPS_EP_EVENT_DATA_TX 0x03 + /**< Data frame has been sent on the endpoint. */ +/* @} */ + + +/* + * Maximum packet size for endpoint, 1024 + * @{ + */ +#define XUSBPS_MAX_PACKET_SIZE 1024 + /**< Maximum value can be put into the queue head */ +/* @} */ +/**************************** Type Definitions *******************************/ + +/****************************************************************************** + * This data type defines the callback function to be used for Endpoint + * handlers. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param EpNum is the Number of the endpoint that caused the event. + * @param EventType is the type of the event that occured on the endpoint. + * @param Data is a pointer to user data pointer specified when callback + * was registered. + */ +typedef void (*XUsbPs_EpHandlerFunc)(void *CallBackRef, + u8 EpNum, u8 EventType, void *Data); + + +/****************************************************************************** + * This data type defines the callback function to be used for the general + * interrupt handler. + * + * @param CallBackRef is the Callback reference passed in by the upper + * layer when setting the handler, and is passed back to the upper + * layer when the handler is called. + * @param IrqMask is the Content of the interrupt status register. This + * value can be used by the callback function to distinguish the + * individual interrupt types. + */ +typedef void (*XUsbPs_IntrHandlerFunc)(void *CallBackRef, u32 IrqMask); + + +/******************************************************************************/ + +/* The following type definitions are used for referencing Queue Heads and + * Transfer Descriptors. The structures themselves are not used, however, the + * types are used in the API to avoid using (void *) pointers. + */ +typedef u8 XUsbPs_dQH[XUSBPS_dQH_ALIGN]; +typedef u8 XUsbPs_dTD[XUSBPS_dTD_ALIGN]; + + +/** + * The following data structures are used internally by the L0/L1 driver. + * Their contents MUST NOT be changed by the upper layers. + */ + +/** + * The following data structure represents OUT endpoint. + */ +typedef struct { + XUsbPs_dQH *dQH; + /**< Pointer to the Queue Head structure of the endpoint. */ + + XUsbPs_dTD *dTDs; + /**< Pointer to the first dTD of the dTD list for this + * endpoint. */ + + XUsbPs_dTD *dTDCurr; + /**< Buffer to the currently processed descriptor. */ + + u8 *dTDBufs; + /**< Pointer to the first buffer of the buffer list for this + * endpoint. */ + + XUsbPs_EpHandlerFunc HandlerFunc; + /**< Handler function for this endpoint. */ + void *HandlerRef; + /**< User data reference for the handler. */ +} XUsbPs_EpOut; + + +/** + * The following data structure represents IN endpoint. + */ +typedef struct { + XUsbPs_dQH *dQH; + /**< Pointer to the Queue Head structure of the endpoint. */ + + XUsbPs_dTD *dTDs; + /**< List of pointers to the Transfer Descriptors of the + * endpoint. */ + + XUsbPs_dTD *dTDHead; + /**< Buffer to the next available descriptor in the list. */ + + XUsbPs_dTD *dTDTail; + /**< Buffer to the last unsent descriptor in the list*/ + + XUsbPs_EpHandlerFunc HandlerFunc; + /**< Handler function for this endpoint. */ + void *HandlerRef; + /**< User data reference for the handler. */ +} XUsbPs_EpIn; + + +/** + * The following data structure represents an endpoint used internally + * by the L0/L1 driver. + */ +typedef struct { + /* Each endpoint has an OUT and an IN component. + */ + XUsbPs_EpOut Out; /**< OUT endpoint structure */ + XUsbPs_EpIn In; /**< IN endpoint structure */ +} XUsbPs_Endpoint; + + + +/** + * The following structure is used by the user to receive Setup Data from an + * endpoint. Using this structure simplifies the process of interpreting the + * setup data in the core's data fields. + * + * The naming scheme for the members of this structure is different from the + * naming scheme found elsewhere in the code. The members of this structure are + * defined in the Chapter 9 USB reference guide. Using this naming scheme makes + * it easier for people familiar with the standard to read the code. + */ +typedef struct { + u8 bmRequestType; /**< bmRequestType in setup data */ + u8 bRequest; /**< bRequest in setup data */ + u16 wValue; /**< wValue in setup data */ + u16 wIndex; /**< wIndex in setup data */ + u16 wLength; /**< wLength in setup data */ +} +XUsbPs_SetupData; + + +/** + * Data structures used to configure endpoints. + */ +typedef struct { + u32 Type; + /**< Endpoint type: + - XUSBPS_EP_TYPE_CONTROL + - XUSBPS_EP_TYPE_ISOCHRONOUS + - XUSBPS_EP_TYPE_BULK + - XUSBPS_EP_TYPE_INTERRUPT */ + + u32 NumBufs; + /**< Number of buffers to be handled by this endpoint. */ + u32 BufSize; + /**< Buffer size. Only relevant for OUT (receive) Endpoints. */ + + u16 MaxPacketSize; + /**< Maximum packet size for this endpoint. This number will + * define the maximum number of bytes sent on the wire per + * transaction. Range: 0..1024 */ +} XUsbPs_EpSetup; + + +/** + * Endpoint configuration structure. + */ +typedef struct { + XUsbPs_EpSetup Out; /**< OUT component of endpoint. */ + XUsbPs_EpSetup In; /**< IN component of endpoint. */ +} XUsbPs_EpConfig; + + +/** + * The XUsbPs_DeviceConfig structure contains the configuration information to + * configure the USB controller for DEVICE mode. This data structure is used + * with the XUsbPs_ConfigureDevice() function call. + */ +typedef struct { + u8 NumEndpoints; /**< Number of Endpoints for the controller. + This number depends on the runtime + configuration of driver. The driver may + configure fewer endpoints than are available + in the core. */ + + XUsbPs_EpConfig EpCfg[XUSBPS_MAX_ENDPOINTS]; + /**< List of endpoint configurations. */ + + + u32 DMAMemPhys; /**< Physical base address of DMAable memory + allocated for the driver. */ + + /* The following members are used internally by the L0/L1 driver. They + * MUST NOT be accesses and/or modified in any way by the upper layers. + * + * The reason for having these members is that we generally try to + * avoid allocating memory in the L0/L1 driver as we want to be OS + * independent. In order to avoid allocating memory for this data + * structure wihin L0/L1 we put it into the XUsbPs_DeviceConfig + * structure which is allocated by the caller. + */ + XUsbPs_Endpoint Ep[XUSBPS_MAX_ENDPOINTS]; + /**< List of endpoint metadata structures. */ + + u32 PhysAligned; /**< 64 byte aligned base address of the DMA + memory block. Will be computed and set by + the L0/L1 driver. */ +} XUsbPs_DeviceConfig; + + +/** + * The XUsbPs_Config structure contains configuration information for the USB + * controller. + * + * This structure only contains the basic configuration for the controller. The + * caller also needs to initialize the controller for the DEVICE mode + * using the XUsbPs_DeviceConfig data structures with the + * XUsbPs_ConfigureDevice() function call + */ +typedef struct { + u16 DeviceID; /**< Unique ID of controller. */ + u32 BaseAddress; /**< Core register base address. */ +} XUsbPs_Config; + + +/** + * The XUsbPs driver instance data. The user is required to allocate a + * variable of this type for every USB controller in the system. A pointer to a + * variable of this type is then passed to the driver API functions. + */ +typedef struct { + XUsbPs_Config Config; /**< Configuration structure */ + + int CurrentAltSetting; /**< Current alternative setting of interface */ + + void *UserDataPtr; /**< Data pointer to be used by upper layers to + store application dependent data structures. + The upper layers are responsible to allocated + and free the memory. The driver will not + mofidy this data pointer. */ + + /** + * The following structures hold the configuration for DEVICE mode + * of the controller. They are initialized using the + * XUsbPs_ConfigureDevice() function call. + */ + XUsbPs_DeviceConfig DeviceConfig; + /**< Configuration for the DEVICE mode. */ + + XUsbPs_IntrHandlerFunc HandlerFunc; + /**< Handler function for the controller. */ + void *HandlerRef; + /**< User data reference for the handler. */ + u32 HandlerMask; + /**< User interrupt mask. Defines which interrupts will cause + * the callback to be called. */ +} XUsbPs; + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************** + * + * USB CONTROLLER RELATED MACROS + * + ******************************************************************************/ +/*****************************************************************************/ +/** + * This macro returns the current frame number. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @return The current frame number. + * + * @note C-style signature: + * u32 XUsbPs_GetFrameNum(const XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_GetFrameNum(InstancePtr) \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, XUSBPS_FRAME_OFFSET) + + +/*****************************************************************************/ +/** + * This macro starts the USB engine. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_Start(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_Start(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RS_MASK) + + +/*****************************************************************************/ +/** + * This macro stops the USB engine. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_Stop(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_Stop(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RS_MASK) + + +/*****************************************************************************/ +/** + * This macro forces the USB engine to be in Full Speed (FS) mode. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * + * @note C-style signature: + * void XUsbPs_ForceFS(XUsbPs *InstancePtr) + * + ******************************************************************************/ +#define XUsbPs_ForceFS(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_PORTSCR1_OFFSET, \ + XUSBPS_PORTSCR_PFSC_MASK) + + +/*****************************************************************************/ +/** + * This macro starts the USB Timer 0, with repeat option for period of + * one second. + * + * @param InstancePtr is a pointer to XUsbPs instance of the controller. + * @param Interval is the interval for Timer0 to generate an interrupt + * + * @note C-style signature: + * void XUsbPs_StartTimer0(XUsbPs *InstancePtr, u32 Interval) + * + ******************************************************************************/ +#define XUsbPs_StartTimer0(InstancePtr, Interval) \ +{ \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_TIMER0_LD_OFFSET, (Interval)); \ + XUsbPs_SetBits(InstancePtr, XUSBPS_TIMER0_CTL_OFFSET, \ + XUSBPS_TIMER_RUN_MASK | \ + XUSBPS_TIMER_RESET_MASK | \ + XUSBPS_TIMER_REPEAT_MASK); \ +} \ + + +/*****************************************************************************/ +/** +* This macro stops Timer 0. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_StopTimer0(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_StopTimer0(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_TIMER0_CTL_OFFSET, \ + XUSBPS_TIMER_RUN_MASK) + + +/*****************************************************************************/ +/** +* This macro reads Timer 0. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_ReadTimer0(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_ReadTimer0(InstancePtr) \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_TIMER0_CTL_OFFSET) & \ + XUSBPS_TIMER_COUNTER_MASK + + +/*****************************************************************************/ +/** +* This macro force remote wakeup on host +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_RemoteWakeup(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_RemoteWakeup(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_PORTSCR1_OFFSET, \ + XUSBPS_PORTSCR_FPR_MASK) + + +/****************************************************************************** + * + * ENDPOINT RELATED MACROS + * + ******************************************************************************/ +/*****************************************************************************/ +/** +* This macro enables the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is number of the endpoint to enable. +* @param Dir is direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpEnable(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpEnable(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXE_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXE_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro disables the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to disable. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpDisable(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpDisable(InstancePtr, EpNum, Dir) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXE_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXE_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro stalls the given endpoint for the given direction, and flush +* the buffers. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is number of the endpoint to stall. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpStall(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpStall(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXS_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXS_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro unstalls the given endpoint for the given direction. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the Number of the endpoint to unstall. +* @param Dir is the Direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpUnStall(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpUnStall(InstancePtr, EpNum, Dir) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), \ + ((Dir) & XUSBPS_EP_DIRECTION_OUT ? XUSBPS_EPCR_RXS_MASK : 0) | \ + ((Dir) & XUSBPS_EP_DIRECTION_IN ? XUSBPS_EPCR_TXS_MASK : 0)) + + +/*****************************************************************************/ +/** +* This macro flush an endpoint upon interface disable +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to flush. +* @param Dir is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @note C-style signature: +* void XUsbPs_EpFlush(XUsbPs *InstancePtr, u8 EpNum, u8 Dir) +* +******************************************************************************/ +#define XUsbPs_EpFlush(InstancePtr, EpNum, Dir) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPFLUSH_OFFSET, \ + EpNum << ((Dir) & XUSBPS_EP_DIRECTION_OUT ? \ + XUSBPS_EPFLUSH_RX_SHIFT:XUSBPS_EPFLUSH_TX_SHIFT)) \ + +/*****************************************************************************/ +/** +* This macro enables the interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param IntrMask is the Bit mask of interrupts to be enabled. +* +* @note C-style signature: +* void XUsbPs_IntrEnable(XUsbPs *InstancePtr, u32 IntrMask) +* +******************************************************************************/ +#define XUsbPs_IntrEnable(InstancePtr, IntrMask) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_IER_OFFSET, IntrMask) + + +/*****************************************************************************/ +/** +* This function disables the interrupts defined by the bit mask. +* +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param IntrMask is a Bit mask of interrupts to be disabled. +* +* @note C-style signature: +* void XUsbPs_IntrDisable(XUsbPs *InstancePtr, u32 IntrMask) +* +******************************************************************************/ +#define XUsbPs_IntrDisable(InstancePtr, IntrMask) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_IER_OFFSET, IntrMask) + + +/*****************************************************************************/ +/** +* This macro enables the endpoint NAK interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is the Bit mask of endpoint NAK interrupts to be +* enabled. +* @note C-style signature: +* void XUsbPs_NakIntrEnable(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrEnable(InstancePtr, NakIntrMask) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_EPNAKIER_OFFSET, NakIntrMask) + + +/*****************************************************************************/ +/** +* This macro disables the endpoint NAK interrupts defined by the bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is a Bit mask of endpoint NAK interrupts to be +* disabled. +* +* @note +* C-style signature: +* void XUsbPs_NakIntrDisable(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrDisable(InstancePtr, NakIntrMask) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_EPNAKIER_OFFSET, NakIntrMask) + + +/*****************************************************************************/ +/** +* This function clears the endpoint NAK interrupts status defined by the +* bit mask. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param NakIntrMask is the Bit mask of endpoint NAK interrupts to be cleared. +* +* @note C-style signature: +* void XUsbPs_NakIntrClear(XUsbPs *InstancePtr, u32 NakIntrMask) +* +******************************************************************************/ +#define XUsbPs_NakIntrClear(InstancePtr, NakIntrMask) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_EPNAKISR_OFFSET, NakIntrMask) + + + +/*****************************************************************************/ +/** +* This macro sets the Interrupt Threshold value in the control register +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param Threshold is the Interrupt threshold to be set. +* Allowed values: +* - XUSBPS_CMD_ITHRESHOLD_0 - Immediate interrupt +* - XUSBPS_CMD_ITHRESHOLD_1 - 1 Frame +* - XUSBPS_CMD_ITHRESHOLD_2 - 2 Frames +* - XUSBPS_CMD_ITHRESHOLD_4 - 4 Frames +* - XUSBPS_CMD_ITHRESHOLD_8 - 8 Frames +* - XUSBPS_CMD_ITHRESHOLD_16 - 16 Frames +* - XUSBPS_CMD_ITHRESHOLD_32 - 32 Frames +* - XUSBPS_CMD_ITHRESHOLD_64 - 64 Frames +* +* @note +* C-style signature: +* void XUsbPs_SetIntrThreshold(XUsbPs *InstancePtr, u8 Threshold) +* +******************************************************************************/ +#define XUsbPs_SetIntrThreshold(InstancePtr, Threshold) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_CMD_OFFSET, (Threshold))\ + + +/*****************************************************************************/ +/** +* This macro sets the Tripwire bit in the USB command register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_SetTripwire(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_SetSetupTripwire(InstancePtr) \ + XUsbPs_SetBits(InstancePtr, XUSBPS_CMD_OFFSET, \ + XUSBPS_CMD_SUTW_MASK) + + +/*****************************************************************************/ +/** +* This macro clears the Tripwire bit in the USB command register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @note C-style signature: +* void XUsbPs_ClrTripwire(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_ClrSetupTripwire(InstancePtr) \ + XUsbPs_ClrBits(InstancePtr, XUSBPS_CMD_OFFSET, \ + XUSBPS_CMD_SUTW_MASK) + + +/*****************************************************************************/ +/** +* This macro checks if the Tripwire bit in the USB command register is set. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* +* @return +* - TRUE: The tripwire bit is still set. +* - FALSE: The tripwire bit has been cleared. +* +* @note C-style signature: +* int XUsbPs_TripwireIsSet(XUsbPs *InstancePtr) +* +******************************************************************************/ +#define XUsbPs_SetupTripwireIsSet(InstancePtr) \ + (XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + XUSBPS_CMD_OFFSET) & \ + XUSBPS_CMD_SUTW_MASK ? TRUE : FALSE) + + +/****************************************************************************** +* +* GENERAL REGISTER / BIT MANIPULATION MACROS +* +******************************************************************************/ +/****************************************************************************/ +/** +* This macro sets the given bit mask in the register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param RegOffset is the register offset to be written. +* @param Bits is the Bits to be set in the register +* +* @return None. +* +* @note C-style signature: +* void XUsbPs_SetBits(u32 BaseAddress, u32 RegOffset, u32 Bits) +* +*****************************************************************************/ +#define XUsbPs_SetBits(InstancePtr, RegOffset, Bits) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, RegOffset, \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + RegOffset) | (Bits)); + + +/****************************************************************************/ +/** +* +* This macro clears the given bits in the register. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param RegOffset is the register offset to be written. +* @param Bits are the bits to be cleared in the register +* +* @return None. +* +* @note +* C-style signature: +* void XUsbPs_ClrBits(u32 BaseAddress, u32 RegOffset, u32 Bits) +* +*****************************************************************************/ +#define XUsbPs_ClrBits(InstancePtr, RegOffset, Bits) \ + XUsbPs_WriteReg((InstancePtr)->Config.BaseAddress, RegOffset, \ + XUsbPs_ReadReg((InstancePtr)->Config.BaseAddress, \ + RegOffset) & ~(Bits)); + + +/************************** Function Prototypes ******************************/ + +/** + * Setup / Initialize functions. + * + * Implemented in file xusbps.c + */ +int XUsbPs_CfgInitialize(XUsbPs *InstancePtr, + const XUsbPs_Config *ConfigPtr, u32 BaseAddress); + +int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr, + const XUsbPs_DeviceConfig *CfgPtr); + +/** + * Common functions used for DEVICE/HOST mode. + */ +int XUsbPs_Reset(XUsbPs *InstancePtr); + +/** + * DEVICE mode specific functions. + */ +int XUsbPs_BusReset(XUsbPs *InstancePtr); +int XUsbPs_SetDeviceAddress(XUsbPs *InstancePtr, u8 Address); + + +/** + * Handling Suspend and Resume. + * + * Implemented in xusbps.c + */ +int XUsbPs_Suspend(const XUsbPs *InstancePtr); +int XUsbPs_Resume(const XUsbPs *InstancePtr); +int XUsbPs_RequestHostResume(const XUsbPs *InstancePtr); + + +/* + * Functions for managing Endpoints / Transfers + * + * Implemented in file xusbps_endpoint.c + */ +int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen); +int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen); +int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle); +void XUsbPs_EpBufferRelease(u32 Handle); + +int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpHandlerFunc CallBackFunc, + void *CallBackRef); +int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum, + XUsbPs_SetupData *SetupDataPtr); + +int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction); + +int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr, + int EpNum, unsigned short NewDirection, int DirectionChanged); + +/* + * Interrupt handling functions + * + * Implemented in file xusbps_intr.c + */ +void XUsbPs_IntrHandler(void *InstancePtr); + +int XUsbPs_IntrSetHandler(XUsbPs *InstancePtr, + XUsbPs_IntrHandlerFunc CallBackFunc, + void *CallBackRef, u32 Mask); +/* + * Helper functions for static configuration. + * Implemented in xusbps_sinit.c + */ +XUsbPs_Config *XUsbPs_LookupConfig(u16 DeviceId); + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_H */ diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.c b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.c new file mode 100755 index 00000000..77862ed2 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.c @@ -0,0 +1,1446 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** + * @file xusbps_endpoint.c + * + * Endpoint specific function implementations. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 1.03a nm  09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 1.04a nm  11/02/12 Fixed CR#683931. Mult bits are set properly in dQH.
+ * 2.00a kpc 04/03/14 Fixed CR#777763. Updated the macro names 
+ * 2.1   kpc 04/28/14 Added XUsbPs_EpBufferSendWithZLT api and merged common
+ *		      code to XUsbPs_EpQueueRequest.
+ * 
+ ******************************************************************************/ + +/***************************** Include Files **********************************/ + +#include /* for bzero() */ +#include + +#include "xusbps.h" +#include "xusbps_endpoint.h" + +/************************** Constant Definitions ******************************/ + +/**************************** Type Definitions ********************************/ + +/************************** Variable Definitions ******************************/ + +/************************** Function Prototypes ******************************/ + +static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr); +static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr); +static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr); +static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr, + const u8 *BufferPtr, u32 BufferLen); + +static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len); + +/* Functions to reconfigure endpoint upon host's set alternate interface + * request. + */ +static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, + int EpNum, unsigned short NewDirection); +static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, + int EpNum, unsigned short NewDirection); +static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen, u8 ReqZero); + +/******************************* Functions ************************************/ + +/*****************************************************************************/ +/** + * + * This function configures the DEVICE side of the controller. The caller needs + * to pass in the desired configuration (e.g. number of endpoints) and a + * DMAable buffer that will hold the Queue Head List and the Transfer + * Descriptors. The required size for this buffer can be obtained by the caller + * using the: XUsbPs_DeviceMemRequired() macro. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param CfgPtr is a pointer to the configuration structure that contains + * the desired DEVICE side configuration. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occured. + * + * @note + * The caller may configure the controller for both, DEVICE and + * HOST side. + * + ******************************************************************************/ +int XUsbPs_ConfigureDevice(XUsbPs *InstancePtr, + const XUsbPs_DeviceConfig *CfgPtr) +{ + int Status; + u32 ModeValue = 0x0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Copy the configuration data over into the local instance structure */ + InstancePtr->DeviceConfig = *CfgPtr; + + + /* Align the buffer to a 2048 byte (XUSBPS_dQH_BASE_ALIGN) boundary.*/ + InstancePtr->DeviceConfig.PhysAligned = + (InstancePtr->DeviceConfig.DMAMemPhys + + XUSBPS_dQH_BASE_ALIGN) & + ~(XUSBPS_dQH_BASE_ALIGN -1); + + /* Initialize the endpoint pointer list data structure. */ + XUsbPs_EpListInit(&InstancePtr->DeviceConfig); + + + /* Initialize the Queue Head structures in DMA memory. */ + XUsbPs_dQHInit(&InstancePtr->DeviceConfig); + + + /* Initialize the Transfer Descriptors in DMA memory.*/ + Status = XUsbPs_dTDInit(&InstancePtr->DeviceConfig); + if (XST_SUCCESS != Status) { + return XST_FAILURE; + } + + /* Changing the DEVICE mode requires a controller RESET. */ + if (XST_SUCCESS != XUsbPs_Reset(InstancePtr)) { + return XST_FAILURE; + } + + /* Set the Queue Head List address. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPLISTADDR_OFFSET, + InstancePtr->DeviceConfig.PhysAligned); + + /* Set the USB mode register to configure DEVICE mode. + * + * XUSBPS_MODE_SLOM_MASK note: + * Disable Setup Lockout. Setup Lockout is not required as we + * will be using the tripwire mechanism when handling setup + * packets. + */ + ModeValue = XUSBPS_MODE_CM_DEVICE_MASK | XUSBPS_MODE_SLOM_MASK; + + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_MODE_OFFSET, ModeValue); + + XUsbPs_SetBits(InstancePtr, XUSBPS_OTGCSR_OFFSET, + XUSBPS_OTGSC_OT_MASK); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function sends a given data buffer. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param BufferPtr is a pointer to the buffer to send. +* @param BufferLen is the Buffer length. +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occured. +* - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). +* - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. +* +******************************************************************************/ +int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr, + BufferLen, FALSE); +} + +/*****************************************************************************/ +/** +* This function sends a given data buffer and also zero length packet if the +* Bufferlen is in multiples of endpoint max packet size. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param BufferPtr is a pointer to the buffer to send. +* @param BufferLen is the Buffer length. +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occured. +* - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). +* - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. +* +******************************************************************************/ +int XUsbPs_EpBufferSendWithZLT(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen) +{ + u8 ReqZero = FALSE; + XUsbPs_EpSetup *Ep; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.EpCfg[EpNum].In; + + if ((BufferLen >= Ep->MaxPacketSize) && + (BufferLen % Ep->MaxPacketSize == 0)) { + ReqZero = TRUE; + } + + return XUsbPs_EpQueueRequest(InstancePtr, EpNum, BufferPtr, + BufferLen, ReqZero); +} + +/*****************************************************************************/ +/** +* This function sends a given data buffer and also sends ZLT packet if it is +* requested. +* +* @param InstancePtr is a pointer to XUsbPs instance of the controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param BufferPtr is a pointer to the buffer to send. +* @param BufferLen is the Buffer length. +* @param ReqZero is the +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occured. +* - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). +* - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. +* +******************************************************************************/ +static int XUsbPs_EpQueueRequest(XUsbPs *InstancePtr, u8 EpNum, + const u8 *BufferPtr, u32 BufferLen, u8 ReqZero) +{ + int Status; + u32 Token; + XUsbPs_EpIn *Ep; + XUsbPs_dTD *DescPtr; + u32 Length; + u32 PipeEmpty = 1; + u32 Mask = 0x00010000; + u32 BitMask = Mask << EpNum; + u32 RegValue; + u32 Temp; + u32 exit = 1; + + + /* Locate the next available buffer in the ring. A buffer is available + * if its descriptor is not active. + */ + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In; + + Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen); + + if(Ep->dTDTail != Ep->dTDHead) { + PipeEmpty = 0; + } + XUsbPs_dTDInvalidateCache(Ep->dTDHead); + + /* Tell the caller if we do not have any descriptors available. */ + if (XUsbPs_dTDIsActive(Ep->dTDHead)) { + return XST_USB_NO_DESC_AVAILABLE; + } + + /* Remember the current head. */ + DescPtr = Ep->dTDHead; + + do { + Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen; + /* Attach the provided buffer to the current descriptor.*/ + Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length); + if (XST_SUCCESS != Status) { + return XST_FAILURE; + } + BufferLen -= Length; + BufferPtr += Length; + + XUsbPs_dTDSetActive(Ep->dTDHead); + if (BufferLen == 0 && (ReqZero == FALSE)) { + XUsbPs_dTDSetIOC(Ep->dTDHead); + exit = 0; + } + XUsbPs_dTDClrTerminate(Ep->dTDHead); + XUsbPs_dTDFlushCache(Ep->dTDHead); + + /* Advance the head descriptor pointer to the next descriptor. */ + Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead); + /* Terminate the next descriptor and flush the cache.*/ + XUsbPs_dTDInvalidateCache(Ep->dTDHead); + /* Tell the caller if we do not have any descriptors available. */ + if (XUsbPs_dTDIsActive(Ep->dTDHead)) { + return XST_USB_NO_DESC_AVAILABLE; + } + + if (ReqZero && BufferLen == 0) { + ReqZero = FALSE; + } + + } while(BufferLen || exit); + + XUsbPs_dTDSetTerminate(Ep->dTDHead); + XUsbPs_dTDFlushCache(Ep->dTDHead); + + if(!PipeEmpty) { + /* Read the endpoint prime register. */ + RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET); + if(RegValue & BitMask) { + return XST_SUCCESS; + } + + do { + RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET); + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, + RegValue | XUSBPS_CMD_ATDTW_MASK); + Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET) + & BitMask; + } while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) & + XUSBPS_CMD_ATDTW_MASK)); + + RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET); + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, + RegValue & ~XUSBPS_CMD_ATDTW_MASK); + + if(Temp) { + return XST_SUCCESS; + } + } + + /* Check, if the DMA engine is still running. If it is running, we do + * not clear Queue Head fields. + * + * Same cache rule as for the Transfer Descriptor applies for the Queue + * Head. + */ + XUsbPs_dQHInvalidateCache(Ep->dQH); + /* Add the dTD to the dQH */ + XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr); + Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN); + Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK); + XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token); + + XUsbPs_dQHFlushCache(Ep->dQH); + + Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN); + + return Status; +} + +/*****************************************************************************/ +/** + * This function receives a data buffer from the endpoint of the given endpoint + * number. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param BufferPtr (OUT param) is a pointer to the buffer pointer to hold + * the reference of the data buffer. + * @param BufferLenPtr (OUT param) is a pointer to the integer that will + * hold the buffer length. + * @param Handle is the opaque handle to be used when the buffer is + * released. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occured. + * - XST_USB_NO_BUF: No buffer available. + * + * @note + * After handling the data in the buffer, the user MUST release + * the buffer using the Handle by calling the + * XUsbPs_EpBufferRelease() function. + * + ******************************************************************************/ +int XUsbPs_EpBufferReceive(XUsbPs *InstancePtr, u8 EpNum, + u8 **BufferPtr, u32 *BufferLenPtr, u32 *Handle) +{ + XUsbPs_EpOut *Ep; + XUsbPs_EpSetup *EpSetup; + u32 length = 0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(BufferPtr != NULL); + Xil_AssertNonvoid(BufferLenPtr != NULL); + Xil_AssertNonvoid(Handle != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + /* Locate the next available buffer in the ring. A buffer is available + * if its descriptor is not active. + */ + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; + + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + if (XUsbPs_dTDIsActive(Ep->dTDCurr)) { + return XST_USB_NO_BUF; + } + + /* The buffer is not active which means that it has been processed by + * the DMA engine and contains valid data. + */ + EpSetup = &InstancePtr->DeviceConfig.EpCfg[EpNum].Out; + + + /* Use the buffer pointer stored in the "user data" field of the + * Transfer Descriptor. + */ + *BufferPtr = (u8 *) XUsbPs_ReaddTD(Ep->dTDCurr, + XUSBPS_dTDUSERDATA); + + length = EpSetup->BufSize - + XUsbPs_dTDGetTransferLen(Ep->dTDCurr); + + if(length > 0) { + *BufferLenPtr = length; + }else { + *BufferLenPtr = 0; + } + + *Handle = (u32) Ep->dTDCurr; + + + /* Reset the descriptor's BufferPointer0 and Transfer Length fields to + * their original value. Note that we can not yet re-activate the + * descriptor as the caller will be using the attached buffer. Once the + * caller releases the buffer by calling XUsbPs_EpBufferRelease(), we + * can re-activate the descriptor. + */ + XUsbPs_WritedTD(Ep->dTDCurr, XUSBPS_dTDBPTR0, *BufferPtr); + XUsbPs_dTDSetTransferLen(Ep->dTDCurr, EpSetup->BufSize); + + XUsbPs_dTDFlushCache(Ep->dTDCurr); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function returns a previously received data buffer to the driver. +* +* @param Handle is a pointer to the buffer that is returned. +* +* @return None. +* +******************************************************************************/ +void XUsbPs_EpBufferRelease(u32 Handle) +{ + XUsbPs_dTD *dTDPtr; + + /* Perform sanity check on Handle.*/ + Xil_AssertVoid((0 != Handle) && (0 == (Handle % XUSBPS_dTD_ALIGN))); + + /* Activate the descriptor and clear the Terminate bit. Make sure to do + * the proper cache handling. + */ + dTDPtr = (XUsbPs_dTD *) Handle; + + XUsbPs_dTDInvalidateCache(dTDPtr); + + XUsbPs_dTDClrTerminate(dTDPtr); + XUsbPs_dTDSetActive(dTDPtr); + XUsbPs_dTDSetIOC(dTDPtr); + + XUsbPs_dTDFlushCache(dTDPtr); + +} + + +/*****************************************************************************/ +/** + * This function sets the handler for endpoint events. + * + * @param InstancePtr is a pointer to the XUsbPs instance of the + * controller. + * @param EpNum is the number of the endpoint to receive data from. + * @param Direction is the direction of the endpoint (bitfield): + * - XUSBPS_EP_DIRECTION_OUT + * - XUSBPS_EP_DIRECTION_IN + * @param CallBackFunc is the Handler callback function. + * Can be NULL if the user wants to disable the handler entry. + * @param CallBackRef is the user definable data pointer that will be + * passed back if the handler is called. May be NULL. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occured. + * - XST_INVALID_PARAM: Invalid parameter passed. + * + * @note + * The user can disable a handler by setting the callback function + * pointer to NULL. + * + ******************************************************************************/ +int XUsbPs_EpSetHandler(XUsbPs *InstancePtr, u8 EpNum, u8 Direction, + XUsbPs_EpHandlerFunc CallBackFunc, + void *CallBackRef) +{ + XUsbPs_Endpoint *Ep; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CallBackFunc != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.Ep[EpNum]; + + if(Direction & XUSBPS_EP_DIRECTION_OUT) { + Ep->Out.HandlerFunc = CallBackFunc; + Ep->Out.HandlerRef = CallBackRef; + } + + if(Direction & XUSBPS_EP_DIRECTION_IN) { + Ep->In.HandlerFunc = CallBackFunc; + Ep->In.HandlerRef = CallBackRef; + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function primes an endpoint. +* +* @param InstancePtr is pointer to the XUsbPs instance. +* @param EpNum is the number of the endpoint to receive data from. +* @param Direction is the direction of the endpoint (bitfield): +* - XUSBPS_EP_DIRECTION_OUT +* - XUSBPS_EP_DIRECTION_IN +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occured. +* - XST_INVALID_PARAM: Invalid parameter passed. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_EpPrime(XUsbPs *InstancePtr, u8 EpNum, u8 Direction) +{ + u32 Mask; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + /* Get the right bit mask for the endpoint direction. */ + switch (Direction) { + + case XUSBPS_EP_DIRECTION_OUT: + Mask = 0x00000001; + break; + + case XUSBPS_EP_DIRECTION_IN: + Mask = 0x00010000; + break; + + default: + return XST_INVALID_PARAM; + } + + /* Write the endpoint prime register. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET, Mask << EpNum); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function extracts the Setup Data from a given endpoint. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpNum is the number of the endpoint to receive data from. +* @param SetupDataPtr is a pointer to the setup data structure to be +* filled. +* +* @return +* - XST_SUCCESS: The operation completed successfully. +* - XST_FAILURE: An error occured. +* +* @note None. +******************************************************************************/ +int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum, + XUsbPs_SetupData *SetupDataPtr) +{ + XUsbPs_EpOut *Ep; + + u32 Data[2]; + u8 *p; + + int Timeout; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SetupDataPtr != NULL); + Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); + + Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; + + + /* Get the data from the Queue Heads Setup buffer into local variables + * so we can extract the setup data values. + */ + do { + /* Arm the tripwire. The tripwire will tell us if a new setup + * packet arrived (in which case the tripwire bit will be + * cleared) while we were reading the buffer. If a new setup + * packet arrived the buffer is corrupted and we continue + * reading. + */ + XUsbPs_SetSetupTripwire(InstancePtr); + + XUsbPs_dQHInvalidateCache(Ep->dQH); + + Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0); + Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1); + } while (FALSE == XUsbPs_SetupTripwireIsSet(InstancePtr)); + + /* Clear the pending endpoint setup stat bit. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET, 1 << EpNum); + + /* Clear the Tripwire bit and continue. + */ + XUsbPs_ClrSetupTripwire(InstancePtr); + + + /* Data in the setup buffer is being converted by the core to big + * endian format. We have to take care of proper byte swapping when + * reading the setup data values. + * + * Need to check if there is a smarter way to do this and take the + * processor/memory-controller endianess into account? + */ + p = (u8 *) Data; + + SetupDataPtr->bmRequestType = p[0]; + SetupDataPtr->bRequest = p[1]; + SetupDataPtr->wValue = (p[3] << 8) | p[2]; + SetupDataPtr->wIndex = (p[5] << 8) | p[4]; + SetupDataPtr->wLength = (p[7] << 8) | p[6]; + + /* Before we leave we need to make sure that the endpoint setup bit has + * cleared. It needs to be 0 before the endpoint can be re-primed. + * + * Note: According to the documentation this endpoint setup bit should + * clear within 1-2us after it has been written above. This means that + * we should never catch it being 1 here. However, we still need to + * poll it to make sure. Just in case, we use a counter 'Timeout' so we + * won't hang here if the bit is stuck for some reason. + */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET) & + (1 << EpNum)) && --Timeout) { + /* NOP */ + } + if (0 == Timeout) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* This function initializes the endpoint pointer data structure. +* +* The function sets up the local data structure with the aligned addresses for +* the Queue Head and Transfer Descriptors. +* +* @param DevCfgPtr is pointer to the XUsbPs DEVICE configuration +* structure. +* +* @return none +* +* @note +* Endpoints of type XUSBPS_EP_TYPE_NONE are not used in the +* system. Therefore no memory is reserved for them. +* +******************************************************************************/ +static void XUsbPs_EpListInit(XUsbPs_DeviceConfig *DevCfgPtr) +{ + int EpNum; + u8 *p; + + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Set up the XUsbPs_Endpoint array. This array is used to define the + * location of the Queue Head list and the Transfer Descriptors in the + * block of DMA memory that has been passed into the driver. + * + * 'p' is used to set the pointers in the local data structure. + * Initially 'p' is pointed to the beginning of the DMAable memory + * block. As pointers are assigned, 'p' is incremented by the size of + * the respective object. + */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + /* Start off with 'p' pointing to the (aligned) beginning of the DMA + * buffer. + */ + p = (u8 *) DevCfgPtr->PhysAligned; + + + /* Initialize the Queue Head pointer list. + * + * Each endpoint has two Queue Heads. One for the OUT direction and one + * for the IN direction. An OUT Queue Head is always followed by an IN + * Queue Head. + * + * Queue Head alignment is XUSBPS_dQH_ALIGN. + * + * Note that we have to reserve space here for unused endpoints. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + /* OUT Queue Head */ + Ep[EpNum].Out.dQH = (XUsbPs_dQH *) p; + p += XUSBPS_dQH_ALIGN; + + /* IN Queue Head */ + Ep[EpNum].In.dQH = (XUsbPs_dQH *) p; + p += XUSBPS_dQH_ALIGN; + } + + + /* 'p' now points to the first address after the Queue Head list. The + * Transfer Descriptors start here. + * + * Each endpoint has a variable number of Transfer Descriptors + * depending on user configuration. + * + * Transfer Descriptor alignment is XUSBPS_dTD_ALIGN. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + /* OUT Descriptors. + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + Ep[EpNum].Out.dTDs = (XUsbPs_dTD *) p; + Ep[EpNum].Out.dTDCurr = (XUsbPs_dTD *) p; + p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs; + } + + /* IN Descriptors. + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) { + Ep[EpNum].In.dTDs = (XUsbPs_dTD *) p; + Ep[EpNum].In.dTDHead = (XUsbPs_dTD *) p; + Ep[EpNum].In.dTDTail = (XUsbPs_dTD *) p; + p += XUSBPS_dTD_ALIGN * EpCfg[EpNum].In.NumBufs; + } + } + + + /* 'p' now points to the first address after the Transfer Descriptors. + * The data buffers for the OUT Transfer Desciptors start here. + * + * Note that IN (TX) Transfer Descriptors are not assigned buffers at + * this point. Buffers will be assigned when the user calls the send() + * function. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + /* If BufSize for this endpoint is set to 0 it means + * that we do not need to attach a buffer to this + * descriptor. We also initialize it's buffer pointer + * to NULL. + */ + if (0 == EpCfg[EpNum].Out.BufSize) { + Ep[EpNum].Out.dTDBufs = NULL; + continue; + } + + Ep[EpNum].Out.dTDBufs = p; + p += EpCfg[EpNum].Out.BufSize * EpCfg[EpNum].Out.NumBufs; + } + } + + + /* Initialize the endpoint event handlers to NULL. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + Ep[EpNum].Out.HandlerFunc = NULL; + Ep[EpNum].In.HandlerFunc = NULL; + } +} + + +/*****************************************************************************/ +/** +* +* This function initializes the Queue Head List in memory. +* +* @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration +* structure. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XUsbPs_dQHInit(XUsbPs_DeviceConfig *DevCfgPtr) +{ + int EpNum; + + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Setup pointers for simpler access. */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + /* Go through the list of Queue Head entries and: + * + * - Set Transfer Descriptor addresses + * - Set Maximum Packet Size + * - Disable Zero Length Termination (ZLT) for non-isochronous transfers + * - Enable Interrupt On Setup (IOS) + * + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + + /* OUT Queue Heads.*/ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs); + + /* For isochronous, ep max packet size translates to different + * values in queue head than other types. + * Also enable ZLT for isochronous. + */ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH); + } + + /* Only control OUT needs this */ + if(XUSBPS_EP_TYPE_CONTROL == EpCfg[EpNum].Out.Type) { + XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH); + } + + /* Set up the overlay next dTD pointer. */ + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs); + + XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH); + } + + + /* IN Queue Heads. */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) { + XUsbPs_WritedQH(Ep[EpNum].In.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs); + + + /* Isochronous ep packet size can be larger than 1024.*/ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH); + } + + XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH); + } + } +} + + +/*****************************************************************************/ +/** + * + * This function initializes the Transfer Descriptors lists in memory. + * + * @param DevCfgPtr is a pointer to the XUsbPs DEVICE configuration + * structure. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occured. + * + ******************************************************************************/ +static int XUsbPs_dTDInit(XUsbPs_DeviceConfig *DevCfgPtr) +{ + int EpNum; + + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Setup pointers for simpler access. */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + /* Walk through the list of endpoints and initialize their Transfer + * Descriptors. + */ + for (EpNum = 0; EpNum < DevCfgPtr->NumEndpoints; ++EpNum) { + int Td; + int NumdTD; + + XUsbPs_EpOut *Out = &Ep[EpNum].Out; + XUsbPs_EpIn *In = &Ep[EpNum].In; + + + /* OUT Descriptors + * =============== + * + * + Set the next link pointer + * + Set the interrupt complete and the active bit + * + Attach the buffer to the dTD + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].Out.Type) { + NumdTD = EpCfg[EpNum].Out.NumBufs; + } + else { + NumdTD = 0; + } + + for (Td = 0; Td < NumdTD; ++Td) { + int Status; + + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]); + + /* Set NEXT link pointer. */ + XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP, + &Out->dTDs[NextTd]); + + /* Set the OUT descriptor ACTIVE and enable the + * interrupt on complete. + */ + XUsbPs_dTDSetActive(&Out->dTDs[Td]); + XUsbPs_dTDSetIOC(&Out->dTDs[Td]); + + + /* Set up the data buffer with the descriptor. If the + * buffer pointer is NULL it means that we do not need + * to attach a buffer to this descriptor. + */ + if (NULL == Out->dTDBufs) { + XUsbPs_dTDFlushCache(&Out->dTDs[Td]); + continue; + } + + Status = XUsbPs_dTDAttachBuffer( + &Out->dTDs[Td], + Out->dTDBufs + + (Td * EpCfg[EpNum].Out.BufSize), + EpCfg[EpNum].Out.BufSize); + if (XST_SUCCESS != Status) { + return XST_FAILURE; + } + + XUsbPs_dTDFlushCache(&Out->dTDs[Td]); + } + + + /* IN Descriptors + * ============== + * + * + Set the next link pointer + * + Set the Terminate bit to mark it available + */ + if (XUSBPS_EP_TYPE_NONE != EpCfg[EpNum].In.Type) { + NumdTD = EpCfg[EpNum].In.NumBufs; + } + else { + NumdTD = 0; + } + + for (Td = 0; Td < NumdTD; ++Td) { + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&In->dTDs[Td]); + + /* Set NEXT link pointer. */ + XUsbPs_WritedTD(In->dTDs[Td], XUSBPS_dTDNLP, + In->dTDs[NextTd]); + + /* Set the IN descriptor's TERMINATE bits. */ + XUsbPs_dTDSetTerminate(In->dTDs[Td]); + + XUsbPs_dTDFlushCache(&In->dTDs[Td]); + } + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * + * This function associates a buffer with a Transfer Descriptor. The function + * will take care of splitting the buffer into multiple 4kB aligned segments if + * the buffer happens to span one or more 4kB pages. + * + * @param dTDIndex is a pointer to the Transfer Descriptor + * @param BufferPtr is pointer to the buffer to link to the descriptor. + * @param BufferLen is the length of the buffer. + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occured. + * - XST_USB_BUF_TOO_BIG: The provided buffer is bigger than tha + * maximum allowed buffer size (16k). + * + * @note + * Cache invalidation and flushing needs to be handler by the + * caller of this function. + * + ******************************************************************************/ +static int XUsbPs_dTDAttachBuffer(XUsbPs_dTD *dTDPtr, + const u8 *BufferPtr, u32 BufferLen) +{ + u32 BufAddr; + u32 BufEnd; + u32 PtrNum; + + Xil_AssertNonvoid(dTDPtr != NULL); + + /* Check if the buffer is smaller than 16kB. */ + if (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) { + return XST_USB_BUF_TOO_BIG; + } + + /* Get a u32 of the buffer pointer to avoid casting in the following + * logic operations. + */ + BufAddr = (u32) BufferPtr; + + + /* Set the buffer pointer 0. Buffer pointer 0 can point to any location + * in memory. It does not need to be 4kB aligned. However, if the + * provided buffer spans one or more 4kB boundaries, we need to set up + * the subsequent buffer pointers which must be 4kB aligned. + */ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(0), BufAddr); + + /* Check if the buffer spans a 4kB boundary. + * + * Only do this check, if we are not sending a 0-length buffer. + */ + if (BufferLen > 0) { + BufEnd = BufAddr + BufferLen -1; + PtrNum = 1; + + while ((BufAddr & 0xFFFFF000) != (BufEnd & 0xFFFFF000)) { + /* The buffer spans at least one boundary, let's set + * the next buffer pointer and repeat the procedure + * until the end of the buffer and the pointer written + * are in the same 4kB page. + */ + BufAddr = (BufAddr + 0x1000) & 0xFFFFF000; + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDBPTR(PtrNum), + BufAddr); + PtrNum++; + } + } + + /* Set the length of the buffer. */ + XUsbPs_dTDSetTransferLen(dTDPtr, BufferLen); + + + /* We remember the buffer pointer in the user data field (reserved + * field in the dTD). This makes it easier to reset the buffer pointer + * after a buffer has been received on the endpoint. The buffer pointer + * needs to be reset because the DMA engine modifies the buffer pointer + * while receiving. + */ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDUSERDATA, BufferPtr); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * This function set the Max PacketLen for the queue head for isochronous EP. + * + * If the max packet length is greater than XUSBPS_MAX_PACKET_SIZE, then + * Mult bits are set to reflect that. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Len is the Length to be set. + * + ******************************************************************************/ +static void XUsbPs_dQHSetMaxPacketLenISO(XUsbPs_dQH *dQHPtr, u32 Len) +{ + u32 Mult = (Len & ENDPOINT_MAXP_MULT_MASK) >> ENDPOINT_MAXP_MULT_SHIFT; + u32 MaxPktSize = (Mult > 1) ? ENDPOINT_MAXP_LENGTH : Len; + + if (MaxPktSize > XUSBPS_MAX_PACKET_SIZE) { + return; + } + + if (Mult > 3) { + return; + } + + /* Set Max packet size */ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & + ~XUSBPS_dQHCFG_MPL_MASK) | + (MaxPktSize << XUSBPS_dQHCFG_MPL_SHIFT)); + + /* Set Mult to tell hardware how many transactions in each microframe */ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & + ~XUSBPS_dQHCFG_MULT_MASK) | + (Mult << XUSBPS_dQHCFG_MULT_SHIFT)); + +} + +/*****************************************************************************/ +/** +* This function reconfigures one Ep corresponding to host's request of setting +* alternate interface. The endpoint has been disabled before this call. +* +* Both QH and dTDs are updated for the new configuration. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param CfgPtr +* Pointer to the updated XUsbPs DEVICE configuration structure. +* +* @param EpNum +* The endpoint to be reconfigured. +* +* @param NewDirection +* The new transfer direction the endpoint. +* +* @param DirectionChanged +* A boolean value indicate whether the transfer direction has changed. +* +* @return +* XST_SUCCESS upon success, XST_FAILURE otherwise. +* +******************************************************************************/ +int XUsbPs_ReconfigureEp(XUsbPs *InstancePtr, XUsbPs_DeviceConfig *CfgPtr, + int EpNum, unsigned short NewDirection, + int DirectionChanged) { + + int Status = XST_SUCCESS; + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + Ep = CfgPtr->Ep; + EpCfg = CfgPtr->EpCfg; + + /* If transfer direction changes, dTDs has to be reset + * Number of buffers are preset and should not to be changed. + */ + if(DirectionChanged) { + if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + u8 *p; + + /* Swap the pointer to the dTDs. + */ + Ep[EpNum].Out.dTDs = Ep[EpNum].In.dTDs; + p = (u8 *)(Ep[EpNum].Out.dTDs + XUSBPS_dTD_ALIGN * EpCfg[EpNum].Out.NumBufs); + + /* Set the OUT buffer if buffer size is not zero + */ + if(EpCfg[EpNum].Out.BufSize > 0) { + Ep[EpNum].Out.dTDBufs = p; + } + } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + Ep[EpNum].In.dTDs = Ep[EpNum].Out.dTDs; + } + } + + /* Reset dTD progress tracking pointers + */ + if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + Ep[EpNum].In.dTDHead = Ep[EpNum].In.dTDTail = Ep[EpNum].In.dTDs; + } else if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + Ep[EpNum].Out.dTDCurr = Ep[EpNum].Out.dTDs; + } + + /* Reinitialize information in QH + */ + XUsbPs_dQHReinitEp(CfgPtr, EpNum, NewDirection); + + /* Reinitialize the dTD linked list, and flush the cache + */ + Status = XUsbPs_dTDReinitEp(CfgPtr, EpNum, NewDirection); + if(Status != XST_SUCCESS) { + return Status; + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * This function re-initializes the Queue Head List in memory. + * The endpoint 1 has been disabled before this call. + * + * @param DevCfgPtr + * Pointer to the updated XUsbPs DEVICE configuration structure. + * + * @param EpNum + * The endpoint to be reconfigured. + * + * @param NewDirection + * The new transfer direction of endpoint 1 + * + * @return none + * + ******************************************************************************/ +static void XUsbPs_dQHReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, +int EpNum, unsigned short NewDirection) +{ + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + + /* Setup pointers for simpler access. + */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + /* Go through the list of Queue Head entries and: + * + * - Set Transfer Descriptor addresses + * - Set Maximum Packet Size + * - Disable Zero Length Termination (ZLT) for non-isochronous transfers + * - Enable Interrupt On Setup (IOS) + * + */ + if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + /* OUT Queue Heads. + */ + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].Out.dTDs); + + /* For isochronous, ep max packet size translates to different + * values in queue head than other types. + * Also enable ZLT for isochronous. + */ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].Out.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].Out.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].Out.dQH, + EpCfg[EpNum].Out.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].Out.dQH); + } + + XUsbPs_dQHSetIOS(Ep[EpNum].Out.dQH); + + /* Set up the overlay next dTD pointer. + */ + XUsbPs_WritedQH(Ep[EpNum].Out.dQH, + XUSBPS_dQHdTDNLP, Ep[EpNum].Out.dTDs); + + XUsbPs_dQHFlushCache(Ep[EpNum].Out.dQH); + + } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + + /* IN Queue Heads. + */ + XUsbPs_WritedQH(Ep[EpNum].In.dQH, + XUSBPS_dQHCPTR, Ep[EpNum].In.dTDs); + + /* Isochronous ep packet size can be larger than 1024. */ + if(XUSBPS_EP_TYPE_ISOCHRONOUS == EpCfg[EpNum].In.Type) { + XUsbPs_dQHSetMaxPacketLenISO(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHEnableZLT(Ep[EpNum].In.dQH); + }else { + XUsbPs_dQHSetMaxPacketLen(Ep[EpNum].In.dQH, + EpCfg[EpNum].In.MaxPacketSize); + XUsbPs_dQHDisableZLT(Ep[EpNum].In.dQH); + } + + XUsbPs_dQHSetIOS(Ep[EpNum].In.dQH); + + XUsbPs_dQHFlushCache(Ep[EpNum].In.dQH); + } + +} + +/*****************************************************************************/ +/** + * + * This function re-initializes the Transfer Descriptors lists in memory. + * The endpoint has been disabled before the call. The transfer descriptors + * list pointer has been initialized too. + * + * @param DevCfgPtr + * Pointer to the XUsbPs DEVICE configuration structure. + * + * @param EpNum + * The endpoint to be reconfigured. + * + * @param NewDirection + * The new transfer direction of endpoint 1 + * + * @return + * - XST_SUCCESS: The operation completed successfully. + * - XST_FAILURE: An error occured. + * + ******************************************************************************/ +static int XUsbPs_dTDReinitEp(XUsbPs_DeviceConfig *DevCfgPtr, +int EpNum, unsigned short NewDirection) +{ + XUsbPs_Endpoint *Ep; + XUsbPs_EpConfig *EpCfg; + int Td; + int NumdTD; + + + /* Setup pointers for simpler access. + */ + Ep = DevCfgPtr->Ep; + EpCfg = DevCfgPtr->EpCfg; + + + if(NewDirection == XUSBPS_EP_DIRECTION_OUT) { + XUsbPs_EpOut *Out = &Ep[EpNum].Out; + + /* OUT Descriptors + * =============== + * + * + Set the next link pointer + * + Set the interrupt complete and the active bit + * + Attach the buffer to the dTD + */ + NumdTD = EpCfg[EpNum].Out.NumBufs; + + for (Td = 0; Td < NumdTD; ++Td) { + int Status; + + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&Out->dTDs[Td]); + + /* Set NEXT link pointer. + */ + XUsbPs_WritedTD(&Out->dTDs[Td], XUSBPS_dTDNLP, + &Out->dTDs[NextTd]); + + /* Set the OUT descriptor ACTIVE and enable the + * interrupt on complete. + */ + XUsbPs_dTDSetActive(&Out->dTDs[Td]); + XUsbPs_dTDSetIOC(&Out->dTDs[Td]); + + /* Set up the data buffer with the descriptor. If the + * buffer pointer is NULL it means that we do not need + * to attach a buffer to this descriptor. + */ + if (Out->dTDBufs != NULL) { + + Status = XUsbPs_dTDAttachBuffer( + &Out->dTDs[Td], + Out->dTDBufs + + (Td * EpCfg[EpNum].Out.BufSize), + EpCfg[EpNum].Out.BufSize); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + XUsbPs_dTDFlushCache(&Out->dTDs[Td]); + } + } else if(NewDirection == XUSBPS_EP_DIRECTION_IN) { + XUsbPs_EpIn *In = &Ep[EpNum].In; + + /* IN Descriptors + * ============== + * + * + Set the next link pointer + * + Set the Terminate bit to mark it available + */ + NumdTD = EpCfg[EpNum].In.NumBufs; + + for (Td = 0; Td < NumdTD; ++Td) { + int NextTd = (Td + 1) % NumdTD; + + XUsbPs_dTDInvalidateCache(&In->dTDs[Td]); + + /* Set NEXT link pointer. + */ + XUsbPs_WritedTD(&In->dTDs[Td], XUSBPS_dTDNLP, + &In->dTDs[NextTd]); + + /* Set the IN descriptor's TERMINATE bits. + */ + XUsbPs_dTDSetTerminate(&In->dTDs[Td]); + + XUsbPs_dTDFlushCache(&In->dTDs[Td]); + } + } + + return XST_SUCCESS; +} + diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.h b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.h new file mode 100755 index 00000000..9dec125e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_endpoint.h @@ -0,0 +1,512 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xusbps_endpoint.h + * + * This is an internal file containung the definitions for endpoints. It is + * included by the xusbps_endpoint.c which is implementing the endpoint + * functions and by xusbps_intr.c. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- --------------------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 
+ * + ******************************************************************************/ +#ifndef XUSBPS_ENDPOINT_H +#define XUSBPS_ENDPOINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xusbps.h" +#include "xil_types.h" + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + + +/** + * Endpoint Device Transfer Descriptor + * + * The dTD describes to the device controller the location and quantity of data + * to be sent/received for given transfer. The driver does not attempt to + * modify any field in an active dTD except the Next Link Pointer. + */ +#define XUSBPS_dTDNLP 0x00 /**< Pointer to the next descriptor */ +#define XUSBPS_dTDTOKEN 0x04 /**< Descriptor Token */ +#define XUSBPS_dTDBPTR0 0x08 /**< Buffer Pointer 0 */ +#define XUSBPS_dTDBPTR1 0x0C /**< Buffer Pointer 1 */ +#define XUSBPS_dTDBPTR2 0x10 /**< Buffer Pointer 2 */ +#define XUSBPS_dTDBPTR3 0x14 /**< Buffer Pointer 3 */ +#define XUSBPS_dTDBPTR4 0x18 /**< Buffer Pointer 4 */ +#define XUSBPS_dTDBPTR(n) (XUSBPS_dTDBPTR0 + (n) * 0x04) +#define XUSBPS_dTDRSRVD 0x1C /**< Reserved field */ + +/* We use the reserved field in the dTD to store user data. */ +#define XUSBPS_dTDUSERDATA XUSBPS_dTDRSRVD /**< Reserved field */ + + +/** @name dTD Next Link Pointer (dTDNLP) bit positions. + * @{ + */ +#define XUSBPS_dTDNLP_T_MASK 0x00000001 + /**< USB dTD Next Link Pointer Terminate Bit */ +#define XUSBPS_dTDNLP_ADDR_MASK 0xFFFFFFE0 + /**< USB dTD Next Link Pointer Address [31:5] */ +/* @} */ + + +/** @name dTD Token (dTDTOKEN) bit positions. + * @{ + */ +#define XUSBPS_dTDTOKEN_XERR_MASK 0x00000008 /**< dTD Transaction Error */ +#define XUSBPS_dTDTOKEN_BUFERR_MASK 0x00000020 /**< dTD Data Buffer Error */ +#define XUSBPS_dTDTOKEN_HALT_MASK 0x00000040 /**< dTD Halted Flag */ +#define XUSBPS_dTDTOKEN_ACTIVE_MASK 0x00000080 /**< dTD Active Bit */ +#define XUSBPS_dTDTOKEN_MULTO_MASK 0x00000C00 /**< Multiplier Override Field [1:0] */ +#define XUSBPS_dTDTOKEN_IOC_MASK 0x00008000 /**< Interrupt on Complete Bit */ +#define XUSBPS_dTDTOKEN_LEN_MASK 0x7FFF0000 /**< Transfer Length Field */ +/* @} */ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** + * + * IMPORTANT NOTE: + * =============== + * + * Many of the following macros modify Device Queue Head (dQH) data structures + * and Device Transfer Descriptor (dTD) data structures. Those structures can + * potentially reside in CACHED memory. Therefore, it's the callers + * responsibility to ensure cache coherency by using provided + * + * XUsbPs_dQHInvalidateCache() + * XUsbPs_dQHFlushCache() + * XUsbPs_dTDInvalidateCache() + * XUsbPs_dTDFlushCache() + * + * function calls. + * + ******************************************************************************/ +#define XUsbPs_dTDInvalidateCache(dTDPtr) \ + Xil_DCacheInvalidateRange((unsigned int)dTDPtr, sizeof(XUsbPs_dTD)) + +#define XUsbPs_dTDFlushCache(dTDPtr) \ + Xil_DCacheFlushRange((unsigned int)dTDPtr, sizeof(XUsbPs_dTD)) + +#define XUsbPs_dQHInvalidateCache(dQHPtr) \ + Xil_DCacheInvalidateRange((unsigned int)dQHPtr, sizeof(XUsbPs_dQH)) + +#define XUsbPs_dQHFlushCache(dQHPtr) \ + Xil_DCacheFlushRange((unsigned int)dQHPtr, sizeof(XUsbPs_dQH)) + +/*****************************************************************************/ +/** + * + * This macro sets the Transfer Length for the given Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * @param Len is the length to be set. Range: 0..16384 + * + * @note C-style signature: + * void XUsbPs_dTDSetTransferLen(u32 dTDPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dTDSetTransferLen(dTDPtr, Len) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + ~XUSBPS_dTDTOKEN_LEN_MASK) | ((Len) << 16)) + + +/*****************************************************************************/ +/** + * + * This macro gets the Next Link pointer of the given Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * + * @return TransferLength field of the descriptor. + * + * @note C-style signature: + * u32 XUsbPs_dTDGetTransferLen(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDGetNLP(dTDPtr) \ + (XUsbPs_dTD *) ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP)\ + & XUSBPS_dTDNLP_ADDR_MASK)) + + +/*****************************************************************************/ +/** + * + * This macro sets the Next Link pointer of the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param NLP is the Next Link Pointer + * + * @note C-style signature: + * void XUsbPs_dTDSetTransferLen(u32 dTDPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dTDSetNLP(dTDPtr, NLP) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + (XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) & \ + ~XUSBPS_dTDNLP_ADDR_MASK) | \ + ((NLP) & XUSBPS_dTDNLP_ADDR_MASK)) + + +/*****************************************************************************/ +/** + * + * This macro gets the Transfer Length for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @return TransferLength field of the descriptor. + * + * @note C-style signature: + * u32 XUsbPs_dTDGetTransferLen(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDGetTransferLen(dTDPtr) \ + (u32) ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) \ + & XUSBPS_dTDTOKEN_LEN_MASK) >> 16) + + +/*****************************************************************************/ +/** + * + * This macro sets the Interrupt On Complete (IOC) bit for the given Transfer + * Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetIOC(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetIOC(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) | \ + XUSBPS_dTDTOKEN_IOC_MASK) + + +/*****************************************************************************/ +/** + * + * This macro sets the Terminate bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetTerminate(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetTerminate(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) | \ + XUSBPS_dTDNLP_T_MASK) + + +/*****************************************************************************/ +/** + * + * This macro clears the Terminate bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDClrTerminate(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDClrTerminate(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDNLP, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDNLP) & \ + ~XUSBPS_dTDNLP_T_MASK) + + +/*****************************************************************************/ +/** + * + * This macro checks if the given descriptor is active. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @return + * - TRUE: The buffer is active. + * - FALSE: The buffer is not active. + * + * @note C-style signature: + * int XUsbPs_dTDIsActive(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDIsActive(dTDPtr) \ + ((XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) & \ + XUSBPS_dTDTOKEN_ACTIVE_MASK) ? TRUE : FALSE) + + +/*****************************************************************************/ +/** + * + * This macro sets the Active bit for the given Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * + * @note C-style signature: + * void XUsbPs_dTDSetActive(u32 dTDPtr) + * + ******************************************************************************/ +#define XUsbPs_dTDSetActive(dTDPtr) \ + XUsbPs_WritedTD(dTDPtr, XUSBPS_dTDTOKEN, \ + XUsbPs_ReaddTD(dTDPtr, XUSBPS_dTDTOKEN) | \ + XUSBPS_dTDTOKEN_ACTIVE_MASK) + + +/*****************************************************************************/ +/** + * + * This macro reads the content of a field in a Transfer Descriptor. + * + * @param dTDPtr is a pointer to the dTD element. + * @param Id is the field ID inside the dTD element to read. + * + * @note C-style signature: + * u32 XUsbPs_ReaddTD(u32 dTDPtr, u32 Id) + * + ******************************************************************************/ +#define XUsbPs_ReaddTD(dTDPtr, Id) (*(u32 *)((u32)(dTDPtr) + (u32)(Id))) + +/*****************************************************************************/ +/** + * + * This macro writes a value to a field in a Transfer Descriptor. + * + * @param dTDPtr is pointer to the dTD element. + * @param Id is the field ID inside the dTD element to read. + * @param Val is the value to write to the field. + * + * @note C-style signature: + * u32 XUsbPs_WritedTD(u32 dTDPtr, u32 Id, u32 Val) + * + ******************************************************************************/ +#define XUsbPs_WritedTD(dTDPtr, Id, Val) \ + (*(u32 *) ((u32)(dTDPtr) + (u32)(Id)) = (u32)(Val)) + + +/******************************************************************************/ +/** + * Endpoint Device Queue Head + * + * Device queue heads are arranged in an array in a continuous area of memory + * pointed to by the ENDPOINTLISTADDR pointer. The device controller will index + * into this array based upon the endpoint number received from the USB bus. + * All information necessary to respond to transactions for all primed + * transfers is contained in this list so the Device Controller can readily + * respond to incoming requests without having to traverse a linked list. + * + * The device Endpoint Queue Head (dQH) is where all transfers are managed. The + * dQH is a 48-byte data structure, but must be aligned on a 64-byte boundary. + * During priming of an endpoint, the dTD (device transfer descriptor) is + * copied into the overlay area of the dQH, which starts at the nextTD pointer + * DWord and continues through the end of the buffer pointers DWords. After a + * transfer is complete, the dTD status DWord is updated in the dTD pointed to + * by the currentTD pointer. While a packet is in progress, the overlay area of + * the dQH is used as a staging area for the dTD so that the Device Controller + * can access needed information with little minimal latency. + * + * @note + * Software must ensure that no interface data structure reachable by the + * Device Controller spans a 4K-page boundary. The first element of the + * Endpoint Queue Head List must be aligned on a 4K boundary. + */ +#define XUSBPS_dQHCFG 0x00 /**< dQH Configuration */ +#define XUSBPS_dQHCPTR 0x04 /**< dQH Current dTD Pointer */ +#define XUSBPS_dQHdTDNLP 0x08 /**< dTD Next Link Ptr in dQH + overlay */ +#define XUSBPS_dQHdTDTOKEN 0x0C /**< dTD Token in dQH overlay */ +#define XUSBPS_dQHSUB0 0x28 /**< USB dQH Setup Buffer 0 */ +#define XUSBPS_dQHSUB1 0x2C /**< USB dQH Setup Buffer 1 */ + + +/** @name dQH Configuration (dQHCFG) bit positions. + * @{ + */ +#define XUSBPS_dQHCFG_IOS_MASK 0x00008000 + /**< USB dQH Interrupt on Setup Bit */ +#define XUSBPS_dQHCFG_MPL_MASK 0x07FF0000 + /**< USB dQH Maximum Packet Length + * Field [10:0] */ +#define XUSBPS_dQHCFG_MPL_SHIFT 16 +#define XUSBPS_dQHCFG_ZLT_MASK 0x20000000 + /**< USB dQH Zero Length Termination + * Select Bit */ +#define XUSBPS_dQHCFG_MULT_MASK 0xC0000000 + /* USB dQH Number of Transactions Field + * [1:0] */ +#define XUSBPS_dQHCFG_MULT_SHIFT 30 +/* @} */ + + +/*****************************************************************************/ +/** + * + * This macro sets the Maximum Packet Length field of the give Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Len is the length to be set. + * + * @note C-style signature: + * void XUsbPs_dQHSetMaxPacketLen(u32 dQHPtr, u32 Len) + * + ******************************************************************************/ +#define XUsbPs_dQHSetMaxPacketLen(dQHPtr, Len) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + (XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_MPL_MASK) | ((Len) << 16)) + +/*****************************************************************************/ +/** + * + * This macro sets the Interrupt On Setup (IOS) bit for an endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHSetIOS(u32 dQHPtr) + * + ******************************************************************************/ +#define XUsbPs_dQHSetIOS(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) | \ + XUSBPS_dQHCFG_IOS_MASK) + +/*****************************************************************************/ +/** + * + * This macro clears the Interrupt On Setup (IOS) bit for an endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHClrIOS(u32 dQHPtr) + * + ******************************************************************************/ +#define XUsbPs_dQHClrIOS(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_IOS_MASK) + +/*****************************************************************************/ +/** + * + * This macro enables Zero Length Termination for the endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHEnableZLT(u32 dQHPtr) + * + * + ******************************************************************************/ +#define XUsbPs_dQHEnableZLT(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) & \ + ~XUSBPS_dQHCFG_ZLT_MASK) + + +/*****************************************************************************/ +/** + * + * This macro disables Zero Length Termination for the endpoint. + * + * @param dQHPtr is a pointer to the dQH element. + * + * @note C-style signature: + * void XUsbPs_dQHDisableZLT(u32 dQHPtr) + * + * + ******************************************************************************/ +#define XUsbPs_dQHDisableZLT(dQHPtr) \ + XUsbPs_WritedQH(dQHPtr, XUSBPS_dQHCFG, \ + XUsbPs_ReaddQH(dQHPtr, XUSBPS_dQHCFG) | \ + XUSBPS_dQHCFG_ZLT_MASK) + +/*****************************************************************************/ +/** + * + * This macro reads the content of a field in a Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Id is the Field ID inside the dQH element to read. + * + * @note C-style signature: + * u32 XUsbPs_ReaddQH(u32 dQHPtr, u32 Id) + * + ******************************************************************************/ +#define XUsbPs_ReaddQH(dQHPtr, Id) (*(u32 *)((u32)(dQHPtr) + (u32) (Id))) + +/*****************************************************************************/ +/** + * + * This macro writes a value to a field in a Queue Head. + * + * @param dQHPtr is a pointer to the dQH element. + * @param Id is the Field ID inside the dQH element to read. + * @param Val is the Value to write to the field. + * + * @note C-style signature: + * u32 XUsbPs_WritedQH(u32 dQHPtr, u32 Id, u32 Val) + * + ******************************************************************************/ +#define XUsbPs_WritedQH(dQHPtr, Id, Val) \ + (*(u32 *) ((u32)(dQHPtr) + (u32)(Id)) = (u32)(Val)) + + + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_ENDPOINT_H */ diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_g.c b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_g.c new file mode 100755 index 00000000..3a051e5a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_g.c @@ -0,0 +1,77 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** + * + * @file xusbps_g.c + * This file contains a configuration table where each entry is a configuration + * structure for an XUsbPs device in the system. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 2.00  hk   22/01/14 Added check to select second instance.
+ * 
+ * + *****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xusbps.h" +#include "xparameters.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +/** + * Each XUsbPs device in the system has an entry in this table. + */ + +XUsbPs_Config XUsbPs_ConfigTable[] = { + { + 0, + XPAR_XUSBPS_0_BASEADDR + }, +#ifdef XPAR_XUSBPS_1_BASEADDR + { + 1, + XPAR_XUSBPS_1_BASEADDR + } +#endif +}; diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.c b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.c new file mode 100755 index 00000000..55ca9d03 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.c @@ -0,0 +1,119 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** + * + * @file xusbps_hw.c + * + * The implementation of the XUsbPs interface reset functionality + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.05a kpc  10/10/10 first version
+ * 
+ * + *****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xusbps.h" +#include "xparameters.h" + + +/************************** Constant Definitions ****************************/ +#define XUSBPS_RESET_TIMEOUT 0xFFFFF +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + + +/************************** Function Prototypes *****************************/ + + +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given usbps interface by +* configuring the appropriate control bits in the usbps specifc registers. +* the usbps reset sequence involves the below steps +* Disbale the interrupts +* Clear the status registers +* Apply the reset command and wait for reset complete status +* Update the relevant control registers with reset values +* @param BaseAddress of the interface +* +* @return N/A. +* +* @note None. +* +******************************************************************************/ +void XUsbPs_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + u32 Timeout = 0; + + /* Host and device mode */ + /* Disable the interrupts */ + XUsbPs_WriteReg(BaseAddress,XUSBPS_IER_OFFSET,0x0); + /* Clear the interuupt status */ + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_ISR_OFFSET); + XUsbPs_WriteReg(BaseAddress,XUSBPS_ISR_OFFSET,RegVal); + + /* Perform the reset operation using USB CMD register */ + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); + RegVal = RegVal | XUSBPS_CMD_RST_MASK; + XUsbPs_WriteReg(BaseAddress,XUSBPS_CMD_OFFSET,RegVal); + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); + /* Wait till the reset operation returns success */ + /* + * FIX ME: right now no indication to the caller or user about + * timeout overflow + */ + while ((RegVal & XUSBPS_CMD_RST_MASK) && (Timeout < XUSBPS_RESET_TIMEOUT)) + { + RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); + Timeout++; + } + /* Update periodic list base address register with reset value */ + XUsbPs_WriteReg(BaseAddress,XUSBPS_LISTBASE_OFFSET,0x0); + /* Update async/endpoint list base address register with reset value */ + XUsbPs_WriteReg(BaseAddress,XUSBPS_ASYNCLISTADDR_OFFSET,0x0); + +} + + + diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.h b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.h new file mode 100755 index 00000000..6d877510 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_hw.h @@ -0,0 +1,523 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * + * @file xusbps_hw.h + * + * This header file contains identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xusbps.h. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 1.04a nm   10/23/12 Fixed CR# 679106.
+ * 1.05a kpc  07/03/13 Added XUsbPs_ResetHw function prototype
+ * 2.00a kpc  04/03/14 Fixed CR#777764. Corrected max endpoint vale and masks 
+ * 
+ * + ******************************************************************************/ +#ifndef XUSBPS_HW_H +#define XUSBPS_HW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + + +#define XUSBPS_REG_SPACING 4 + +/** @name Timer 0 Register offsets + * + * @{ + */ +#define XUSBPS_TIMER0_LD_OFFSET 0x00000080 +#define XUSBPS_TIMER0_CTL_OFFSET 0x00000084 +/* @} */ + +/** @name Timer Control Register bit mask + * + * @{ + */ +#define XUSBPS_TIMER_RUN_MASK 0x80000000 +#define XUSBPS_TIMER_STOP_MASK 0x80000000 +#define XUSBPS_TIMER_RESET_MASK 0x40000000 +#define XUSBPS_TIMER_REPEAT_MASK 0x01000000 +/* @} */ + +/** @name Timer Control Register bit mask + * + * @{ + */ +#define XUSBPS_TIMER_COUNTER_MASK 0x00FFFFFF +/* @} */ + +/** @name Device Hardware Parameters + * + * @{ + */ +#define XUSBPS_HWDEVICE_OFFSET 0x0000000C + +#define XUSBPS_EP_NUM_MASK 0x3E +#define XUSBPS_EP_NUM_SHIFT 1 +/* @} */ + +/** @name Capability Regsiter offsets + */ +#define XUSBPS_HCSPARAMS_OFFSET 0x00000104 + +/** @name Operational Register offsets. + * Register comments are tagged with "H:" and "D:" for Host and Device modes, + * respectively. + * Tags are only present for registers that have a different meaning DEVICE and + * HOST modes. Most registers are only valid for either DEVICE or HOST mode. + * Those registers don't have tags. + * @{ + */ +#define XUSBPS_CMD_OFFSET 0x00000140 /**< Configuration */ +#define XUSBPS_ISR_OFFSET 0x00000144 /**< Interrupt Status */ +#define XUSBPS_IER_OFFSET 0x00000148 /**< Interrupt Enable */ +#define XUSBPS_FRAME_OFFSET 0x0000014C /**< USB Frame Index */ +#define XUSBPS_LISTBASE_OFFSET 0x00000154 /**< H: Periodic List Base Address */ +#define XUSBPS_DEVICEADDR_OFFSET 0x00000154 /**< D: Device Address */ +#define XUSBPS_ASYNCLISTADDR_OFFSET 0x00000158 /**< H: Async List Address */ +#define XUSBPS_EPLISTADDR_OFFSET 0x00000158 /**< D: Endpoint List Addr */ +#define XUSBPS_TTCTRL_OFFSET 0x0000015C /**< TT Control */ +#define XUSBPS_BURSTSIZE_OFFSET 0x00000160 /**< Burst Size */ +#define XUSBPS_TXFILL_OFFSET 0x00000164 /**< Tx Fill Tuning */ +#define XUSBPS_ULPIVIEW_OFFSET 0x00000170 /**< ULPI Viewport */ +#define XUSBPS_EPNAKISR_OFFSET 0x00000178 /**< Endpoint NAK IRQ Status */ +#define XUSBPS_EPNAKIER_OFFSET 0x0000017C /**< Endpoint NAK IRQ Enable */ +#define XUSBPS_PORTSCR1_OFFSET 0x00000184 /**< Port Control/Status 1 */ + +/* NOTE: The Port Control / Status Register index is 1-based. */ +#define XUSBPS_PORTSCRn_OFFSET(n) \ + (XUSBPS_PORTSCR1_OFFSET + (((n)-1) * XUSBPS_REG_SPACING)) + + +#define XUSBPS_OTGCSR_OFFSET 0x000001A4 /**< OTG Status and Control */ +#define XUSBPS_MODE_OFFSET 0x000001A8 /**< USB Mode */ +#define XUSBPS_EPSTAT_OFFSET 0x000001AC /**< Endpoint Setup Status */ +#define XUSBPS_EPPRIME_OFFSET 0x000001B0 /**< Endpoint Prime */ +#define XUSBPS_EPFLUSH_OFFSET 0x000001B4 /**< Endpoint Flush */ +#define XUSBPS_EPRDY_OFFSET 0x000001B8 /**< Endpoint Ready */ +#define XUSBPS_EPCOMPL_OFFSET 0x000001BC /**< Endpoint Complete */ +#define XUSBPS_EPCR0_OFFSET 0x000001C0 /**< Endpoint Control 0 */ +#define XUSBPS_EPCR1_OFFSET 0x000001C4 /**< Endpoint Control 1 */ +#define XUSBPS_EPCR2_OFFSET 0x000001C8 /**< Endpoint Control 2 */ +#define XUSBPS_EPCR3_OFFSET 0x000001CC /**< Endpoint Control 3 */ +#define XUSBPS_EPCR4_OFFSET 0x000001D0 /**< Endpoint Control 4 */ + +#define XUSBPS_MAX_ENDPOINTS 12 /**< Number of supported Endpoints in + * this core. */ +#define XUSBPS_EP_OUT_MASK 0x00000FFF /**< OUR (RX) endpoint mask */ +#define XUSBPS_EP_IN_MASK 0x0FFF0000 /**< IN (TX) endpoint mask */ +#define XUSBPS_EP_ALL_MASK 0x0FFF0FFF /**< Mask used for endpoint control + * registers */ +#define XUSBPS_EPCRn_OFFSET(n) \ + (XUSBPS_EPCR0_OFFSET + ((n) * XUSBPS_REG_SPACING)) + +#define XUSBPS_EPFLUSH_RX_SHIFT 0 +#define XUSBPS_EPFLUSH_TX_SHIFT 16 + +/* @} */ + + + +/** @name Endpoint Control Register (EPCR) bit positions. + * @{ + */ + +/* Definitions for TX Endpoint bits */ +#define XUSBPS_EPCR_TXT_CONTROL_MASK 0x00000000 /**< Control Endpoint - TX */ +#define XUSBPS_EPCR_TXT_ISO_MASK 0x00040000 /**< Isochronous. Endpoint */ +#define XUSBPS_EPCR_TXT_BULK_MASK 0x00080000 /**< Bulk Endpoint - TX */ +#define XUSBPS_EPCR_TXT_INTR_MASK 0x000C0000 /**< Interrupt Endpoint */ +#define XUSBPS_EPCR_TXS_MASK 0x00010000 /**< Stall TX endpoint */ +#define XUSBPS_EPCR_TXE_MASK 0x00800000 /**< Transmit enable - TX */ +#define XUSBPS_EPCR_TXR_MASK 0x00400000 /**< Data Toggle Reset Bit */ + + +/* Definitions for RX Endpoint bits */ +#define XUSBPS_EPCR_RXT_CONTROL_MASK 0x00000000 /**< Control Endpoint - RX */ +#define XUSBPS_EPCR_RXT_ISO_MASK 0x00000004 /**< Isochronous Endpoint */ +#define XUSBPS_EPCR_RXT_BULK_MASK 0x00000008 /**< Bulk Endpoint - RX */ +#define XUSBPS_EPCR_RXT_INTR_MASK 0x0000000C /**< Interrupt Endpoint */ +#define XUSBPS_EPCR_RXS_MASK 0x00000001 /**< Stall RX endpoint. */ +#define XUSBPS_EPCR_RXE_MASK 0x00000080 /**< Transmit enable. - RX */ +#define XUSBPS_EPCR_RXR_MASK 0x00000040 /**< Data Toggle Reset Bit */ +/* @} */ + + +/** @name USB Command Register (CR) bit positions. + * @{ + */ +#define XUSBPS_CMD_RS_MASK 0x00000001 /**< Run/Stop */ +#define XUSBPS_CMD_RST_MASK 0x00000002 /**< Controller RESET */ +#define XUSBPS_CMD_FS01_MASK 0x0000000C /**< Frame List Size bit 0,1 */ +#define XUSBPS_CMD_PSE_MASK 0x00000010 /**< Periodic Sched Enable */ +#define XUSBPS_CMD_ASE_MASK 0x00000020 /**< Async Sched Enable */ +#define XUSBPS_CMD_IAA_MASK 0x00000040 /**< IRQ Async Advance Doorbell */ +#define XUSBPS_CMD_ASP_MASK 0x00000300 /**< Async Sched Park Mode Cnt */ +#define XUSBPS_CMD_ASPE_MASK 0x00000800 /**< Async Sched Park Mode Enbl */ +#define XUSBPS_CMD_SUTW_MASK 0x00002000 /**< Setup TripWire */ +#define XUSBPS_CMD_ATDTW_MASK 0x00004000 /**< Add dTD TripWire */ +#define XUSBPS_CMD_FS2_MASK 0x00008000 /**< Frame List Size bit 2 */ +#define XUSBPS_CMD_ITC_MASK 0x00FF0000 /**< IRQ Threshold Control */ +/* @} */ + + +/** + * @name Interrupt Threshold + * These definitions are used by software to set the maximum rate at which the + * USB controller will generate interrupt requests. The interrupt interval is + * given in number of micro-frames. + * + * USB defines a full-speed 1 ms frame time indicated by a Start Of Frame (SOF) + * packet each and every 1ms. USB also defines a high-speed micro-frame with a + * 125us frame time. For each micro-frame a SOF (Start Of Frame) packet is + * generated. Data is sent in between the SOF packets. The interrupt threshold + * defines how many micro-frames the controller waits before issuing an + * interrupt after data has been received. + * + * For a threshold of 0 the controller will issue an interrupt immediately + * after the last byte of the data has been received. For a threshold n>0 the + * controller will wait for n micro-frames before issuing an interrupt. + * + * Therefore, a setting of 8 micro-frames (default) means that the controller + * will issue at most 1 interrupt per millisecond. + * + * @{ + */ +#define XUSBPS_CMD_ITHRESHOLD_0 0x00 /**< Immediate interrupt. */ +#define XUSBPS_CMD_ITHRESHOLD_1 0x01 /**< 1 micro-frame */ +#define XUSBPS_CMD_ITHRESHOLD_2 0x02 /**< 2 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_4 0x04 /**< 4 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_8 0x08 /**< 8 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_16 0x10 /**< 16 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_32 0x20 /**< 32 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_64 0x40 /**< 64 micro-frames */ +#define XUSBPS_CMD_ITHRESHOLD_MAX XUSBPS_CMD_ITHRESHOLD_64 +#define XUSBPS_CMD_ITHRESHOLD_DEFAULT XUSBPS_CMD_ITHRESHOLD_8 +/* @} */ + + + +/** @name USB Interrupt Status Register (ISR) / Interrupt Enable Register (IER) + * bit positions. + * @{ + */ +#define XUSBPS_IXR_UI_MASK 0x00000001 /**< USB Transaction Complete */ +#define XUSBPS_IXR_UE_MASK 0x00000002 /**< Transaction Error */ +#define XUSBPS_IXR_PC_MASK 0x00000004 /**< Port Change Detect */ +#define XUSBPS_IXR_FRE_MASK 0x00000008 /**< Frame List Rollover */ +#define XUSBPS_IXR_AA_MASK 0x00000020 /**< Async Advance */ +#define XUSBPS_IXR_UR_MASK 0x00000040 /**< RESET Received */ +#define XUSBPS_IXR_SR_MASK 0x00000080 /**< Start of Frame */ +#define XUSBPS_IXR_SLE_MASK 0x00000100 /**< Device Controller Suspend */ +#define XUSBPS_IXR_ULPI_MASK 0x00000400 /**< ULPI IRQ */ +#define XUSBPS_IXR_HCH_MASK 0x00001000 /**< Host Controller Halted + * Read Only */ +#define XUSBPS_IXR_RCL_MASK 0x00002000 /**< USB Reclamation Read Only */ +#define XUSBPS_IXR_PS_MASK 0x00004000 /**< Periodic Sched Status + * Read Only */ +#define XUSBPS_IXR_AS_MASK 0x00008000 /**< Async Sched Status Read only */ +#define XUSBPS_IXR_NAK_MASK 0x00010000 /**< NAK IRQ */ +#define XUSBPS_IXR_UA_MASK 0x00040000 /**< USB Host Async IRQ */ +#define XUSBPS_IXR_UP_MASK 0x00080000 /**< USB Host Periodic IRQ */ +#define XUSBPS_IXR_TI0_MASK 0x01000000 /**< Timer 0 Interrupt */ +#define XUSBPS_IXR_TI1_MASK 0x02000000 /**< Timer 1 Interrupt */ + +#define XUSBPS_IXR_ALL (XUSBPS_IXR_UI_MASK | \ + XUSBPS_IXR_UE_MASK | \ + XUSBPS_IXR_PC_MASK | \ + XUSBPS_IXR_FRE_MASK | \ + XUSBPS_IXR_AA_MASK | \ + XUSBPS_IXR_UR_MASK | \ + XUSBPS_IXR_SR_MASK | \ + XUSBPS_IXR_SLE_MASK | \ + XUSBPS_IXR_ULPI_MASK | \ + XUSBPS_IXR_HCH_MASK | \ + XUSBPS_IXR_RCL_MASK | \ + XUSBPS_IXR_PS_MASK | \ + XUSBPS_IXR_AS_MASK | \ + XUSBPS_IXR_NAK_MASK | \ + XUSBPS_IXR_UA_MASK | \ + XUSBPS_IXR_UP_MASK | \ + XUSBPS_IXR_TI0_MASK | \ + XUSBPS_IXR_TI1_MASK) + /**< Mask for ALL IRQ types */ +/* @} */ + + +/** @name USB Mode Register (MODE) bit positions. + * @{ + */ +#define XUSBPS_MODE_CM_MASK 0x00000003 /**< Controller Mode Select */ +#define XUSBPS_MODE_CM_IDLE_MASK 0x00000000 +#define XUSBPS_MODE_CM_DEVICE_MASK 0x00000002 +#define XUSBPS_MODE_CM_HOST_MASK 0x00000003 +#define XUSBPS_MODE_ES_MASK 0x00000004 /**< USB Endian Select */ +#define XUSBPS_MODE_SLOM_MASK 0x00000008 /**< USB Setup Lockout Mode Disable */ +#define XUSBPS_MODE_SDIS_MASK 0x00000010 +#define XUSBPS_MODE_VALID_MASK 0x0000001F + +/* @} */ + + +/** @name USB Device Address Register (DEVICEADDR) bit positions. + * @{ + */ +#define XUSBPS_DEVICEADDR_DEVICEAADV_MASK 0x01000000 + /**< Device Addr Auto Advance */ +#define XUSBPS_DEVICEADDR_ADDR_MASK 0xFE000000 + /**< Device Address */ +#define XUSBPS_DEVICEADDR_ADDR_SHIFT 25 + /**< Address shift */ +#define XUSBPS_DEVICEADDR_MAX 127 + /**< Biggest allowed address */ +/* @} */ + +/** @name USB TT Control Register (TTCTRL) bit positions. + * @{ + */ +#define XUSBPS_TTCTRL_HUBADDR_MASK 0x7F000000 /**< TT Hub Address */ +/* @} */ + + +/** @name USB Burst Size Register (BURSTSIZE) bit posisions. + * @{ + */ +#define XUSBPS_BURSTSIZE_RX_MASK 0x000000FF /**< RX Burst Length */ +#define XUSBPS_BURSTSIZE_TX_MASK 0x0000FF00 /**< TX Burst Length */ +/* @} */ + + +/** @name USB Tx Fill Tuning Register (TXFILL) bit positions. + * @{ + */ +#define XUSBPS_TXFILL_OVERHEAD_MASK 0x000000FF + /**< Scheduler Overhead */ +#define XUSBPS_TXFILL_HEALTH_MASK 0x00001F00 + /**< Scheduler Health Cntr */ +#define XUSBPS_TXFILL_BURST_MASK 0x003F0000 + /**< FIFO Burst Threshold */ +/* @} */ + + +/** @name USB ULPI Viewport Register (ULPIVIEW) bit positions. + * @{ + */ +#define XUSBPS_ULPIVIEW_DATWR_MASK 0x000000FF /**< ULPI Data Write */ +#define XUSBPS_ULPIVIEW_DATRD_MASK 0x0000FF00 /**< ULPI Data Read */ +#define XUSBPS_ULPIVIEW_ADDR_MASK 0x00FF0000 /**< ULPI Data Address */ +#define XUSBPS_ULPIVIEW_PORT_MASK 0x07000000 /**< ULPI Port Number */ +#define XUSBPS_ULPIVIEW_SS_MASK 0x08000000 /**< ULPI Synchronous State */ +#define XUSBPS_ULPIVIEW_RW_MASK 0x20000000 /**< ULPI Read/Write Control */ +#define XUSBPS_ULPIVIEW_RUN_MASK 0x40000000 /**< ULPI Run */ +#define XUSBPS_ULPIVIEW_WU_MASK 0x80000000 /**< ULPI Wakeup */ +/* @} */ + + +/** @name Port Status Control Register bit positions. + * @{ + */ +#define XUSBPS_PORTSCR_CCS_MASK 0x00000001 /**< Current Connect Status */ +#define XUSBPS_PORTSCR_CSC_MASK 0x00000002 /**< Connect Status Change */ +#define XUSBPS_PORTSCR_PE_MASK 0x00000004 /**< Port Enable/Disable */ +#define XUSBPS_PORTSCR_PEC_MASK 0x00000008 /**< Port Enable/Disable Change */ +#define XUSBPS_PORTSCR_OCA_MASK 0x00000010 /**< Over-current Active */ +#define XUSBPS_PORTSCR_OCC_MASK 0x00000020 /**< Over-current Change */ +#define XUSBPS_PORTSCR_FPR_MASK 0x00000040 /**< Force Port Resume */ +#define XUSBPS_PORTSCR_SUSP_MASK 0x00000080 /**< Suspend */ +#define XUSBPS_PORTSCR_PR_MASK 0x00000100 /**< Port Reset */ +#define XUSBPS_PORTSCR_HSP_MASK 0x00000200 /**< High Speed Port */ +#define XUSBPS_PORTSCR_LS_MASK 0x00000C00 /**< Line Status */ +#define XUSBPS_PORTSCR_PP_MASK 0x00001000 /**< Port Power */ +#define XUSBPS_PORTSCR_PO_MASK 0x00002000 /**< Port Owner */ +#define XUSBPS_PORTSCR_PIC_MASK 0x0000C000 /**< Port Indicator Control */ +#define XUSBPS_PORTSCR_PTC_MASK 0x000F0000 /**< Port Test Control */ +#define XUSBPS_PORTSCR_WKCN_MASK 0x00100000 /**< Wake on Connect Enable */ +#define XUSBPS_PORTSCR_WKDS_MASK 0x00200000 /**< Wake on Disconnect Enable */ +#define XUSBPS_PORTSCR_WKOC_MASK 0x00400000 /**< Wake on Over-current Enable */ +#define XUSBPS_PORTSCR_PHCD_MASK 0x00800000 /**< PHY Low Power Suspend - + * Clock Disable */ +#define XUSBPS_PORTSCR_PFSC_MASK 0x01000000 /**< Port Force Full Speed + * Connect */ +#define XUSBPS_PORTSCR_PSPD_MASK 0x0C000000 /**< Port Speed */ +/* @} */ + + +/** @name On-The-Go Status Control Register (OTGCSR) bit positions. + * @{ + */ +#define XUSBPS_OTGSC_VD_MASK 0x00000001 /**< VBus Discharge Bit */ +#define XUSBPS_OTGSC_VC_MASK 0x00000002 /**< VBus Charge Bit */ +#define XUSBPS_OTGSC_HAAR_MASK 0x00000004 /**< HW Assist Auto Reset + * Enable Bit */ +#define XUSBPS_OTGSC_OT_MASK 0x00000008 /**< OTG Termination Bit */ +#define XUSBPS_OTGSC_DP_MASK 0x00000010 /**< Data Pulsing Pull-up + * Enable Bit */ +#define XUSBPS_OTGSC_IDPU_MASK 0x00000020 /**< ID Pull-up Enable Bit */ +#define XUSBPS_OTGSC_HADP_MASK 0x00000040 /**< HW Assist Data Pulse + * Enable Bit */ +#define XUSBPS_OTGSC_HABA_MASK 0x00000080 /**< USB Hardware Assist + * B Disconnect to A + * Connect Enable Bit */ +#define XUSBPS_OTGSC_ID_MASK 0x00000100 /**< ID Status Flag */ +#define XUSBPS_OTGSC_AVV_MASK 0x00000200 /**< USB A VBus Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_ASV_MASK 0x00000400 /**< USB A Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSV_MASK 0x00000800 /**< USB B Session Valid Status Flag */ +#define XUSBPS_OTGSC_BSE_MASK 0x00001000 /**< USB B Session End Status Flag */ +#define XUSBPS_OTGSC_1MST_MASK 0x00002000 /**< USB 1 Millisecond Timer Status Flag */ +#define XUSBPS_OTGSC_DPS_MASK 0x00004000 /**< Data Pulse Status Flag */ +#define XUSBPS_OTGSC_IDIS_MASK 0x00010000 /**< USB ID Interrupt Status Flag */ +#define XUSBPS_OTGSC_AVVIS_MASK 0x00020000 /**< USB A VBus Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_ASVIS_MASK 0x00040000 /**< USB A Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSVIS_MASK 0x00080000 /**< USB B Session Valid Interrupt Status Flag */ +#define XUSBPS_OTGSC_BSEIS_MASK 0x00100000 /**< USB B Session End Interrupt Status Flag */ +#define XUSBPS_OTGSC_1MSS_MASK 0x00200000 /**< 1 Millisecond Timer Interrupt Status Flag */ +#define XUSBPS_OTGSC_DPIS_MASK 0x00400000 /**< Data Pulse Interrupt Status Flag */ +#define XUSBPS_OTGSC_IDIE_MASK 0x01000000 /**< ID Interrupt Enable Bit */ +#define XUSBPS_OTGSC_AVVIE_MASK 0x02000000 /**< USB A VBus Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_ASVIE_MASK 0x04000000 /**< USB A Session Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_BSVIE_MASK 0x08000000 /**< USB B Session Valid Interrupt Enable Bit */ +#define XUSBPS_OTGSC_BSEE_MASK 0x10000000 /**< USB B Session End Interrupt Enable Bit */ +#define XUSBPS_OTGSC_1MSE_MASK 0x20000000 /**< 1 Millisecond Timer + * Interrupt Enable Bit */ +#define XUSBPS_OTGSC_DPIE_MASK 0x40000000 /**< Data Pulse Interrupt + * Enable Bit */ + +#define XUSBPS_OTG_ISB_ALL (XUSBPS_OTGSC_IDIS_MASK |\ + XUSBPS_OTGSC_AVVIS_MASK | \ + XUSBPS_OTGSC_ASVIS_MASK | \ + XUSBPS_OTGSC_BSVIS_MASK | \ + XUSBPS_OTGSC_BSEIS_MASK | \ + XUSBPS_OTGSC_1MSS_MASK | \ + XUSBPS_OTGSC_DPIS_MASK) + /** Mask for All IRQ status masks */ + +#define XUSBPS_OTG_IEB_ALL (XUSBPS_OTGSC_IDIE_MASK |\ + XUSBPS_OTGSC_AVVIE_MASK | \ + XUSBPS_OTGSC_ASVIE_MASK | \ + XUSBPS_OTGSC_BSVIE_MASK | \ + XUSBPS_OTGSC_BSEE_IEB_MASK | \ + XUSBPS_OTGSC_1MSE_MASK | \ + XUSBPS_OTGSC_DPIE_MASK) + /** Mask for All IRQ Enable masks */ +/* @} */ + + +/**< Alignment of the Device Queue Head List BASE. */ +#define XUSBPS_dQH_BASE_ALIGN 2048 + +/**< Alignment of a Device Queue Head structure. */ +#define XUSBPS_dQH_ALIGN 64 + +/**< Alignment of a Device Transfer Descriptor structure. */ +#define XUSBPS_dTD_ALIGN 32 + +/**< Size of one RX buffer for a OUT Transfer Descriptor. */ +#define XUSBPS_dTD_BUF_SIZE 4096 + +/**< Maximum size of one RX/TX buffer. */ +#define XUSBPS_dTD_BUF_MAX_SIZE 16*1024 + +/**< Alignment requirement for Transfer Descriptor buffers. */ +#define XUSBPS_dTD_BUF_ALIGN 4096 + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/** +* +* This macro reads the given register. +* +* @param BaseAddress is the base address for the USB registers. +* @param RegOffset is the register offset to be read. +* +* @return The 32-bit value of the register. +* +* @note C-style signature: +* u32 XUsbPs_ReadReg(u32 BaseAddress, u32 RegOffset) +* +*****************************************************************************/ +#define XUsbPs_ReadReg(BaseAddress, RegOffset) \ + Xil_In32(BaseAddress + (RegOffset)) + + +/****************************************************************************/ +/** +* +* This macro writes the given register. +* +* @param BaseAddress is the the base address for the USB registers. +* @param RegOffset is the register offset to be written. +* @param Data is the the 32-bit value to write to the register. +* +* @return None. +* +* @note C-style signature: +* void XUsbPs_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* + *****************************************************************************/ +#define XUsbPs_WriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32(BaseAddress + (RegOffset), (Data)) + + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the USB PS interface + */ +void XUsbPs_ResetHw(u32 BaseAddress); +/************************** Variable Definitions ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XUSBPS_L_H */ diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_intr.c b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_intr.c new file mode 100755 index 00000000..8595646a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_intr.c @@ -0,0 +1,467 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/******************************************************************************/ +/** + * @file xusbps_intr.c + * + * This file contains the functions that are related to interrupt processing + * for the EPB USB driver. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- ----------------------------------------------------------
+ * 1.00a jz  10/10/10 First release
+ * 1.03a nm  09/21/12 Fixed CR#678977. Added proper sequence for setup packet
+ *                    handling.
+ * 
+ ******************************************************************************/ + +/***************************** Include Files **********************************/ + +#include "xusbps.h" +#include "xusbps_endpoint.h" + +/************************** Constant Definitions ******************************/ + +/**************************** Type Definitions ********************************/ + +/***************** Macros (Inline Functions) Definitions **********************/ + +/************************** Variable Definitions ******************************/ + +/************************** Function Prototypes *******************************/ + +static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl); +static void XUsbPs_IntrHandleRX(XUsbPs *InstancePtr, u32 EpCompl); +static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts); +static void XUsbPs_IntrHandleEp0Setup(XUsbPs *InstancePtr); + +/*****************************************************************************/ +/** +* This function is the first-level interrupt handler for the USB core. All USB +* interrupts will be handled here. Depending on the type of the interrupt, +* second level interrupt handler may be called. Second level interrupt +* handlers will be registered by the user using the: +* XUsbPs_IntrSetHandler() +* and/or +* XUsbPs_EpSetHandler() +* functions. +* +* +* @param HandlerRef is a Reference passed to the interrupt register +* function. In our case this will be a pointer to the XUsbPs +* instance. +* +* @return None +* +* @note None +* +******************************************************************************/ +void XUsbPs_IntrHandler(void *HandlerRef) +{ + XUsbPs *InstancePtr; + + u32 IrqSts; + + Xil_AssertVoid(HandlerRef != NULL); + + InstancePtr = (XUsbPs *) HandlerRef; + + /* Handle controller (non-endpoint) related interrupts. */ + IrqSts = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_ISR_OFFSET); + + /* Clear the interrupt status register. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_ISR_OFFSET, IrqSts); + + /* Nak interrupt, used to respond to host's IN request */ + if(IrqSts & XUSBPS_IXR_NAK_MASK) { + /* Ack the hardware */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPNAKISR_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPNAKISR_OFFSET)); + } + + + /*************************************************************** + * + * Handle general interrupts. Endpoint interrupts will be handler + * later. + * + */ + + /* RESET interrupt.*/ + if (IrqSts & XUSBPS_IXR_UR_MASK) { + XUsbPs_IntrHandleReset(InstancePtr, IrqSts); + return; + } + + /* Check if we have a user handler that needs to be called. Note that + * this is the handler for general interrupts. Endpoint interrupts will + * be handled below. + */ + if ((IrqSts & InstancePtr->HandlerMask) && InstancePtr->HandlerFunc) { + (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); + } + + + /*************************************************************** + * + * Handle Endpoint interrupts. + * + */ + if (IrqSts & XUSBPS_IXR_UI_MASK) { + u32 EpStat; + u32 EpCompl; + + /* ENDPOINT 0 SETUP PACKET HANDLING + * + * Check if we got a setup packet on endpoint 0. Currently we + * only check for setup packets on endpoint 0 as we would not + * expect setup packets on any other endpoint (even though it + * is possible to send setup packets on other endpoints). + */ + EpStat = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET); + if (EpStat & 0x0001) { + /* Handle the setup packet */ + XUsbPs_IntrHandleEp0Setup(InstancePtr); + + /* Re-Prime the endpoint. + * Endpoint is de-primed if a setup packet comes in. + */ + XUsbPs_EpPrime(InstancePtr, 0, XUSBPS_EP_DIRECTION_OUT); + } + + /* Check for RX and TX complete interrupts. */ + EpCompl = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET); + + + /* ACK the complete interrupts. */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET, EpCompl); + + /* Check OUT (RX) endpoints. */ + if (EpCompl & XUSBPS_EP_OUT_MASK) { + XUsbPs_IntrHandleRX(InstancePtr, EpCompl); + } + + /* Check IN (TX) endpoints. */ + if (EpCompl & XUSBPS_EP_IN_MASK) { + XUsbPs_IntrHandleTX(InstancePtr, EpCompl); + } + } +} + + +/*****************************************************************************/ +/** +* This function registers the user callback handler for controller +* (non-endpoint) interrupts. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param CallBackFunc is the Callback function to register. +* CallBackFunc may be NULL to clear the entry. +* @param CallBackRef is the user data reference passed to the +* callback function. CallBackRef may be NULL. +* @param Mask is the User interrupt mask. Defines which interrupts +* will cause the callback to be called. +* +* @return +* - XST_SUCCESS: Callback registered successfully. +* - XST_FAILURE: Callback could not be registered. +* +* @note None. +* +******************************************************************************/ +int XUsbPs_IntrSetHandler(XUsbPs *InstancePtr, + XUsbPs_IntrHandlerFunc CallBackFunc, + void *CallBackRef, u32 Mask) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + + InstancePtr->HandlerFunc = CallBackFunc; + InstancePtr->HandlerRef = CallBackRef; + InstancePtr->HandlerMask = Mask; + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* This function handles TX buffer interrupts. It is called by the interrupt +* when a transmit complete interrupt occurs. It returns buffers of completed +* descriptors to the caller. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* @param EpCompl is the Bit mask of endpoints that caused a transmit +* complete interrupt. +* +* @return None +* +* @note None. +* +******************************************************************************/ +static void XUsbPs_IntrHandleTX(XUsbPs *InstancePtr, u32 EpCompl) +{ + int Index; + u32 Mask; + int NumEp; + + /* Check all endpoints for TX complete bits. + */ + Mask = 0x00010000; + NumEp = InstancePtr->DeviceConfig.NumEndpoints; + + /* Check for every endpoint if its TX complete bit is + * set. + */ + for (Index = 0; Index < NumEp; Index++, Mask <<= 1) { + XUsbPs_EpIn *Ep; + + if (!(EpCompl & Mask)) { + continue; + } + /* The TX complete bit for this endpoint is + * set. Walk the list of descriptors to see + * which ones are completed. + */ + Ep = &InstancePtr->DeviceConfig.Ep[Index].In; + while (Ep->dTDTail != Ep->dTDHead) { + + XUsbPs_dTDInvalidateCache(Ep->dTDTail); + + /* If the descriptor is not active then the buffer has + * not been sent yet. + */ + if (XUsbPs_dTDIsActive(Ep->dTDTail)) { + break; + } + + if (Ep->HandlerFunc) { + void *BufPtr; + + BufPtr = (void *) XUsbPs_ReaddTD(Ep->dTDTail, + XUSBPS_dTDUSERDATA); + + Ep->HandlerFunc(Ep->HandlerRef, Index, + XUSBPS_EP_EVENT_DATA_TX, + BufPtr); + } + + Ep->dTDTail = XUsbPs_dTDGetNLP(Ep->dTDTail); + } + } +} + + +/*****************************************************************************/ +/** + * This function handles RX buffer interrupts. It is called by the interrupt + * when a receive complete interrupt occurs. It notifies the callback functions + * that have been registered with the individual endpoints that data has been + * received. + * + * @param InstancePtr + * Pointer to the XUsbPs instance of the controller. + * + * @param EpCompl + * Bit mask of endpoints that caused a receive complete interrupt. + * @return + * none + * + ******************************************************************************/ +static void XUsbPs_IntrHandleRX(XUsbPs *InstancePtr, u32 EpCompl) +{ + XUsbPs_EpOut *Ep; + int Index; + u32 Mask; + int NumEp; + + /* Check all endpoints for RX complete bits. */ + Mask = 0x00000001; + NumEp = InstancePtr->DeviceConfig.NumEndpoints; + + + /* Check for every endpoint if its RX complete bit is set.*/ + for (Index = 0; Index < NumEp; Index++, Mask <<= 1) { + int numP = 0; + + if (!(EpCompl & Mask)) { + continue; + } + Ep = &InstancePtr->DeviceConfig.Ep[Index].Out; + + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + + /* Handle all finished dTDs */ + while (!XUsbPs_dTDIsActive(Ep->dTDCurr)) { + numP += 1; + if (Ep->HandlerFunc) { + Ep->HandlerFunc(Ep->HandlerRef, Index, + XUSBPS_EP_EVENT_DATA_RX, NULL); + } + + Ep->dTDCurr = XUsbPs_dTDGetNLP(Ep->dTDCurr); + XUsbPs_dTDInvalidateCache(Ep->dTDCurr); + } + /* Re-Prime the endpoint.*/ + XUsbPs_EpPrime(InstancePtr, Index, XUSBPS_EP_DIRECTION_OUT); + } +} + + +/*****************************************************************************/ +/** +* This function handles a RESET interrupt. It will notify the interrupt +* handler callback of the RESET condition. +* +* @param InstancePtr is pointer to the XUsbPs instance of the controller +* @param IrqSts is the Interrupt status register content. +* To be passed on to the user. +* +* @return None +* +* @Note None. +* +******************************************************************************/ +static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts) +{ + int Timeout; + + /* Clear all setup token semaphores by reading the + * XUSBPS_EPSTAT_OFFSET register and writing its value back to + * itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPSTAT_OFFSET)); + + /* Clear all the endpoint complete status bits by reading the + * XUSBPS_EPCOMPL_OFFSET register and writings its value back + * to itself. + */ + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET, + XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPCOMPL_OFFSET)); + + /* Cancel all endpoint prime status by waiting until all bits + * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF + * to XUSBPS_EPFLUSH_OFFSET. + * + * Avoid hanging here by using a Timeout counter... + */ + Timeout = XUSBPS_TIMEOUT_COUNTER; + while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPPRIME_OFFSET) & + XUSBPS_EP_ALL_MASK) && --Timeout) { + /* NOP */ + } + XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, + XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); + + /* Make sure that the reset bit in XUSBPS_PORTSCR1_OFFSET is + * still set at this point. If the code gets to this point and + * the reset bit has already been cleared we are in trouble and + * hardware reset is necessary. + */ + if (!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, + XUSBPS_PORTSCR1_OFFSET) & + XUSBPS_PORTSCR_PR_MASK)) { + /* Send a notification to the user that a hardware + * RESET is required. At this point we can only hope + * that the user registered an interrupt handler and + * will issue a hardware RESET. + */ + if (InstancePtr->HandlerFunc) { + (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, + IrqSts); + } + else { + for (;;); + } + + /* If we get here there is nothing more to do. The user + * should have reset the core. + */ + return; + } + + /* Check if we have a user handler that needs to be called. + */ + if (InstancePtr->HandlerFunc) { + (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); + } + + /* We are done. After RESET we don't proceed in the interrupt + * handler. + */ +} + + +/*****************************************************************************/ +/** +* This function handles a Setup Packet interrupt. It will notify the interrupt +* handler callback of the RESET condition. +* +* @param InstancePtr is a pointer to the XUsbPs instance of the +* controller. +* +* @return None +* +* @Note None +* +******************************************************************************/ +static void XUsbPs_IntrHandleEp0Setup(XUsbPs *InstancePtr) +{ + + XUsbPs_EpOut *Ep; + + /* Notifiy the user. */ + Ep = &InstancePtr->DeviceConfig.Ep[0].Out; + + if (Ep->HandlerFunc) { + Ep->HandlerFunc(Ep->HandlerRef, 0, + XUSBPS_EP_EVENT_SETUP_DATA_RECEIVED, NULL); + } +} + + diff --git a/XilinxProcessorIPLib/drivers/usbps/src/xusbps_sinit.c b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_sinit.c new file mode 100755 index 00000000..3a728d7a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/usbps/src/xusbps_sinit.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* +* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/****************************************************************************/ +/** + * + * @file xusbps_sinit.c + * + * The implementation of the XUsbPs driver's static initialzation + * functionality. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.00a wgr  10/10/10 First release
+ * 
+ * + *****************************************************************************/ + +/***************************** Include Files ********************************/ + +#include "xstatus.h" +#include "xusbps.h" +#include "xparameters.h" + +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ + +extern XUsbPs_Config XUsbPs_ConfigTable[]; + +/************************** Function Prototypes *****************************/ + +/****************************************************************************/ +/** +* +* Looks up the controller configuration based on the unique controller ID. A +* table contains the configuration info for each controller in the system. +* +* @param DeviceID is the ID of the controller to look up the +* configuration for. +* +* @return +* A pointer to the configuration found or NULL if the specified +* controller ID was not found. +* +******************************************************************************/ +XUsbPs_Config *XUsbPs_LookupConfig(u16 DeviceID) +{ + XUsbPs_Config *CfgPtr = NULL; + + int Index; + + for (Index = 0; Index < XPAR_XUSBPS_NUM_INSTANCES; Index++) { + if (XUsbPs_ConfigTable[Index].DeviceID == DeviceID) { + CfgPtr = &XUsbPs_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +}