?? usb.c
字號:
/** * @file usb.c * * @author Intel Corporation * @date 30-OCT-2001 * @brief This file contains the implementation of the IXP400 USB Driver * * Design Notes: * - DMA handling logic (not actual code) is embedded but #ifdef-ed * on IX_USB_DMA in the code; remove before releasing * - don't use the start-of-frame event as this puts the device into * a non-functioning state * * * @par * IXP400 SW Release version 2.1 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * @par * -- End of Copyright Notice -- *//** * @addtogroup API * @{ */#include "IxOsal.h"#include "IxFeatureCtrl.h"#ifdef __HWEMU__#define PRIVATE#endif /* __HWEMU__ */#include "usb.h"#include "usbdeviceparam.h"#include "usbprivate.h"#include "usbprivatedata.h"#include "usbmacros.h"static USBDeviceContext *ixUSBGlobalContext;static BOOL ixUSBBulkNakThrottling = FALSE;#include "usb_util.c"#ifndef IX_USB_HAS_DUMMY_MBLK/* Pool definitions */#define NUM_MBLKS (2000)#define BLK_SIZE (2048)UINT32 ixUSBPoolCounter = NUM_MBLKS;/* Treshold under which the pool is considered depleted * The treshold number represents the number of packets still available * for CONTROL transactions; BULK OUT transactions will be replied with * NAK packets until more buffers become available * * NOTE: this is used only if the device is initialized * with the ENABLE_BULK_NAK_THROTTLE flag; ignored otherwise, in which case * pool depletion will result in an ASSERT(0) fatal error */#define POOL_THRESHOLD (10) static IX_OSAL_MBUF_POOL *pNetPool;#endif /* IX_USB_HAS_DUMMY_MBLK *//** Endpoint interrupt sources on UISR0 and UISR1 */static int UDCEPInterrupt[] ={/* UISR0 */ /* EP_0 */ (0x1 << 0), /* EP_1 */ (0x1 << 1), /* EP_2 */ (0x1 << 2), /* EP_3 */ (0x1 << 3), /* EP_4 */ (0x1 << 4), /* EP_5 */ (0x1 << 5), /* EP_6 */ (0x1 << 6), /* EP_7 */ (0x1 << 7),/* UISR1 */ /* EP_8 */ (0x1 << 0), /* EP_9 */ (0x1 << 1), /* EP_10 */ (0x1 << 2), /* EP_11 */ (0x1 << 3), /* EP_12 */ (0x1 << 4), /* EP_13 */ (0x1 << 5), /* EP_14 */ (0x1 << 6), /* EP_15 */ (0x1 << 7)};static EPInterruptHandler EPInterruptHandlerTable[] ={ /* EP_0 */ ixUSBEP0InterruptHandler, /* EP_1 */ ixUSBINInterruptHandler, /* EP_2 */ ixUSBOUTInterruptHandler, /* EP_3 */ ixUSBINInterruptHandler, /* EP_4 */ ixUSBOUTInterruptHandler, /* EP_5 */ ixUSBINInterruptHandler, /* EP_6 */ ixUSBINInterruptHandler, /* EP_7 */ ixUSBOUTInterruptHandler, /* EP_8 */ ixUSBINInterruptHandler, /* EP_9 */ ixUSBOUTInterruptHandler, /* EP_10 */ ixUSBINInterruptHandler, /* EP_11 */ ixUSBINInterruptHandler, /* EP_12 */ ixUSBOUTInterruptHandler, /* EP_13 */ ixUSBINInterruptHandler, /* EP_14 */ ixUSBOUTInterruptHandler, /* EP_15 */ ixUSBINInterruptHandler,};static int epPriority[]= {0, 5, 10, 15, 1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14};static IxOsalMutex usbBufferSubmitMutex[16];static UINT32 dataSendAllowed = TRUE;static UINT32 cwInitiated = 0, cwCompleted = 0, cwFailed = 0;static UINT32 crInitiated = 0, crCompleted = 0, crFailed = 0;static UINT32 cnInitiated = 0, cnFailed = 0;/** * Interrupt control registers' virtual addresses */static UINT32 ixUSBIrqCtrlRegVirtAddr = 0;PUBLIC IX_STATUSixUSBDriverInit(USBDevice *device){ USBDeviceContext *context; UDCRegisters *registers; UINT32 epIndex; static UINT32 lastDeviceIndex = 0; if (device == NULL) { return IX_FAIL; } /* If not IXP42X A0 stepping, proceed to check for existence of usb component */ if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 != (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK)) || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ())) { /* Check for USB device being present before proceeding*/ if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_USB)== IX_FEATURE_CTRL_COMPONENT_DISABLED) { IX_USB_TRACE("Warning: the USB component you specified " "does not exist\n", 0, 0, 0, 0, 0, 0); } } context = CONTEXT(device); ixUSBGlobalContext = context; ixUSBBulkNakThrottling = ((device->flags & ENABLE_BULK_NAK_THROTTLE) != 0); /* check redundant init */ if (context->checkPattern == USB_DEVICE_CONTEXT_CHECK_PATTERN) { RETURN_REDUNDANT(device); } /* Compile-time assert size of context */ /* This will give a "duplicate case" error if not satisfied */ /* If so, change your USBDevice::deviceContext size to what */ /* sizeof(USBDeviceContext) reports - or more */ IX_USB_CT_ASSERT(sizeof(device->deviceContext) >= sizeof(USBDeviceContext)); /* I/O map UDC base address */ device->baseIOAddress = (UINT32) IX_OSAL_MEM_MAP(IX_OSAL_IXP400_USB_PHYS_BASE, IX_OSAL_IXP400_USB_MAP_SIZE); if (device->baseIOAddress == 0) { ixOsalLog (IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDERR, "USB: cannot map controller I/O address 0x%08X", IX_OSAL_IXP400_USB_PHYS_BASE, 0, 0, 0, 0, 0); return IX_FAIL; } /* I/O map Interrupt Control Register base address */ ixUSBIrqCtrlRegVirtAddr = (UINT32) IX_OSAL_MEM_MAP(IX_OSAL_IXP400_INTC_PHYS_BASE, 4); if (ixUSBIrqCtrlRegVirtAddr == 0) { ixOsalLog (IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDERR, "USB: cannot map interrupt controller I/O address 0x%08X", IX_OSAL_IXP400_INTC_PHYS_BASE, 0, 0, 0, 0, 0); return IX_FAIL; } /* init USBDeviceContext structure */ ixOsalMemSet(context, 0, sizeof(USBDeviceContext)); /* add a check pattern to verify the context later */ context->checkPattern = USB_DEVICE_CONTEXT_CHECK_PATTERN; /* device is initially disabled */ context->enabled = FALSE; /* set UDC registers to base I/O address */ registers = (UDCRegisters *)(device->baseIOAddress); context->registers = registers; /* init EP0ControlData structure */ context->ep0ControlData.currentToken = UNKNOWN_TOKEN; context->ep0ControlData.transferType = UNKNOWN_TRANSFER; context->ep0ControlData.state = IDLE; /* init event processing */ context->eventProcessor.eventCallback = ixUSBNullEventCallback; context->eventProcessor.eventMap = USB_DEVICE_EVENTS; context->eventProcessor.setupCallback = ixUSBNullSetupCallback; context->eventProcessor.receiveCallback = ixUSBNullReceiveCallback; /* init per-endpoint EPStatusData structures */ ixOsalMemSet(context->epStatusData, 0, sizeof(context->epStatusData)); /* Populate EPStatusData structures */ for (epIndex = ENDPOINT_0 ; epIndex < NUM_ENDPOINTS ; epIndex++) { EPStatusData *epData = &context->epStatusData[epIndex]; /* link parent USBDevice */ epData->device = device; /* set endpoint properties */ epData->endpointNumber = epIndex; epData->direction = EP_DIRECTION(EPDescriptorTable[epIndex]); epData->type = EP_TYPE(EPDescriptorTable[epIndex]); epData->transferAllowed = TRUE;#ifdef IX_USB_DMA epData->dmaEnabled = EPDMAEnabledTable[epIndex];#endif /* IX_USB_DMA */ /* setup buffer queue */ ixUSBQueueInit(epData); if (epData->type == USB_CONTROL) { epData->fifoSize = CONTROL_FIFO_SIZE; } else if (epData->type == USB_BULK) { epData->fifoSize = BULK_FIFO_SIZE;#ifdef IX_USB_DMA epData->dmaSize = BULK_DMA_SIZE;#endif /* IX_USB_DMA */ } else if (epData->type == USB_ISOCHRONOUS) { epData->fifoSize = ISOCHRONOUS_FIFO_SIZE;#ifdef IX_USB_DMA epData->dmaSize = ISOCHRONOUS_DMA_SIZE;#endif /* IX_USB_DMA */ } else if (epData->type == USB_INTERRUPT) { epData->fifoSize = INTERRUPT_FIFO_SIZE; } /* * Warning: this switch block applies * only to the standard IXP4XX UDC * endpoint configuration. * Changes in EPDescriptorTable[] should * be reflected here. */ switch (epIndex) { case ENDPOINT_0: IX_USB_ASSERT((epData->direction | epData->type) == (USB_CONTROL | USB_IN_OUT)); epData->UDCCS = ®isters->UDCCS0; epData->UDDR = ®isters->UDDR0; epData->UBCR = NULL; break; case ENDPOINT_1: IX_USB_ASSERT((epData->direction | epData->type) == (USB_BULK | USB_IN)); epData->UDCCS = ®isters->UDCCS1; epData->UDDR = ®isters->UDDR1; epData->UBCR = NULL; break; case ENDPOINT_2: IX_USB_ASSERT((epData->direction | epData->type) == (USB_BULK | USB_OUT)); epData->UDCCS = ®isters->UDCCS2; epData->UDDR = ®isters->UDDR2; epData->UBCR = ®isters->UBCR2; break; case ENDPOINT_3: IX_USB_ASSERT((epData->direction | epData->type) == (USB_ISOCHRONOUS | USB_IN)); epData->UDCCS = ®isters->UDCCS3; epData->UDDR = ®isters->UDDR3; epData->UBCR = NULL; break; case ENDPOINT_4: IX_USB_ASSERT((epData->direction | epData->type) == (USB_ISOCHRONOUS | USB_OUT)); epData->UDCCS = ®isters->UDCCS4; epData->UDDR = ®isters->UDDR4; epData->UBCR = ®isters->UBCR4; break; case ENDPOINT_5: IX_USB_ASSERT((epData->direction | epData->type) == (USB_INTERRUPT | USB_IN)); epData->UDCCS = ®isters->UDCCS5; epData->UDDR = ®isters->UDDR5; epData->UBCR = NULL; break; case ENDPOINT_6: IX_USB_ASSERT((epData->direction | epData->type) == (USB_BULK | USB_IN)); epData->UDCCS = ®isters->UDCCS6; epData->UDDR = ®isters->UDDR6; epData->UBCR = NULL; break; case ENDPOINT_7: IX_USB_ASSERT((epData->direction | epData->type) == (USB_BULK | USB_OUT)); epData->UDCCS = ®isters->UDCCS7; epData->UDDR = ®isters->UDDR7; epData->UBCR = ®isters->UBCR7; break; case ENDPOINT_8: IX_USB_ASSERT((epData->direction | epData->type) == (USB_ISOCHRONOUS | USB_IN)); epData->UDCCS = ®isters->UDCCS8; epData->UDDR = ®isters->UDDR8; epData->UBCR = NULL; break; case ENDPOINT_9: IX_USB_ASSERT((epData->direction | epData->type) == (USB_ISOCHRONOUS | USB_OUT)); epData->UDCCS = ®isters->UDCCS9; epData->UDDR = ®isters->UDDR9; epData->UBCR = ®isters->UBCR9; break; case ENDPOINT_10: IX_USB_ASSERT((epData->direction | epData->type) == (USB_INTERRUPT | USB_IN)); epData->UDCCS = ®isters->UDCCS10; epData->UDDR = ®isters->UDDR10; epData->UBCR = NULL; break; case ENDPOINT_11: IX_USB_ASSERT((epData->direction | epData->type) == (USB_BULK | USB_IN)); epData->UDCCS = ®isters->UDCCS11; epData->UDDR = ®isters->UDDR11; epData->UBCR = NULL; break; case ENDPOINT_12: IX_USB_ASSERT((epData->direction | epData->type) == (USB_BULK | USB_OUT)); epData->UDCCS = ®isters->UDCCS12; epData->UDDR = ®isters->UDDR12; epData->UBCR = ®isters->UBCR12; break; case ENDPOINT_13: IX_USB_ASSERT((epData->direction | epData->type) == (USB_ISOCHRONOUS | USB_IN)); epData->UDCCS = ®isters->UDCCS13; epData->UDDR = ®isters->UDDR13; epData->UBCR = NULL; break; case ENDPOINT_14: IX_USB_ASSERT((epData->direction | epData->type) == (USB_ISOCHRONOUS | USB_OUT)); epData->UDCCS = ®isters->UDCCS14; epData->UDDR = ®isters->UDDR14; epData->UBCR = ®isters->UBCR14; break; case ENDPOINT_15: IX_USB_ASSERT((epData->direction | epData->type) == (USB_INTERRUPT | USB_IN)); epData->UDCCS = ®isters->UDCCS15; epData->UDDR = ®isters->UDDR15; epData->UBCR = NULL; break; default: /* it shouldn't get here */ IX_USB_ASSERT(FALSE); } IX_USB_VERBOSE_INIT_TRACE("epData[%p:%d]: %d\t%d\t%d\n",(UINT32)epData, epIndex, epData->type, epData->direction, epData->fifoSize, 0); } /* clear UDC interrupts */ /* clear endpoints 0..7 */ REG_SET(®isters->USIR0, UDC_CLEAR_ALL_INT); /* clear endpoint 8..15 */ REG_SET(®isters->USIR1, UDC_CLEAR_ALL_INT); /* clear RESET, RESUME, SUSPEND */ REG_SET(®isters->UDCCR, (UDC_UDCCR_RESIR | UDC_UDCCR_SUSIR | UDC_UDCCR_RSTIR)); /* clear Start-Of-Frame */ REG_SET(®isters->UFNHR, UDC_UFNHR_SIR); /* set UDC interrupt masks (all the events but SOF are enabled) */ /* enable suspend/resume interrupt by zeroing the mask bit */ REG_SET(®isters->UDCCR, ((REG_GET(®isters->UDCCR)) & ~UDC_UDCCR_SRM));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -