/*************************************************************************** * Physical Endpoint structure. USB core operates at logical endpoint level. * once host selects a configuration and an interface the associated logical endpoint objects * of the currently active interface will be binded with the physical endpoint objects. * The bind holds good until host again sets or resets the configuration and interface */ typedef struct PhysicalEndpointObject { ENDPOINT_OBJECT *pLogicalEndpointObj; /* logical endpoint object */ int eEndpointStat; /* endpoint state */ int PhysicalEndpointID; /* Physical endpoint ID */ }PHYSICAL_ENDPOINT_OBJECT; /* Endpoint Descriptor -Size 7 bytes - 6 fields */ typedef struct EndPointDescriptor { u8_t bLength; /* Descriptor size in bytes */ u8_t bDescriptorType; /* Descriptor type ENDPOINT 05h */ u8_t bEndpointAddress; /* Endpoint Address */ u8_t bAttributes; /* Transfer type supported */ u16_t wMaxPacketSize; /* Maximum packet size supported */ u8_t bInternal; /* Maximum latency/polling/NACK rate */ }ENDPOINT_DESCRIPTOR, *PENDPOINT_DESCRIPTOR; /* Endpoint Object */ typedef struct EndpointObject { ENDPOINT_DESCRIPTOR *pEndpointDesc; /*Endpoint Descriptor */ ENDPOINT_SPECIFIC_OBJECT *pEndpointSpecificObj; /* EP-Specific Config Obj */ struct EndponitObject *pNext; /* Next Endpoint object */ /* pNextActiveEp is used by the peripheral driver to get the currently active endpoint list */ struct EndponitObject *pNextActiveEpObj; /* Pointers to the next peer endpoint object */ int ID; /* Endpoint ID */ USB_EP_INFO EPInfo; }ENDPOINT_OBJECT, *PENDPOINT_OBJECT; /* Endpoint Specific Configuration Object */ typedef struct EndpointSpecificObject { int length; /* total length of ep specific config */ void *pEpSpecificData; /* Endpoint specific data */ struct EndpointSpecificObject *pNext; /* Next object */ }ENDPOINT_SPECIFIC_OBJECT, *PENDPOINT_SPECIFIC_OBJECT; typedef enum { /* Data direction */ ADI_DEV_DIRECTION_UNDEFINED, /* undefined */ ADI_DEV_DIRECTION_INBOUND, /* inbound (read) */ ADI_DEV_DIRECTION_OUTBOUND, /* outbound (write) */ ADI_DEV_DIRECTION_BIDIRECTIONAL,/* both (read and write) */ } ADI_DEV_DIRECTION; typedef enum DeviceState { DEV_STATE_RESET=0, DEV_STATE_OPEN_IN_PROCESS, DEV_STATE_OPENED, DEV_STATE_CLOSED, DEV_STATE_STARTED, }DEVICE_STATE; typedef enum { // Stream IDs for memory DMA ADI_DMA_MDMA_0, // memory DMA stream 0 ADI_DMA_MDMA_1, // memory DMA stream 1 ADI_DMA_MEMORY_STREAM_COUNT, // number of memory DMA streams } ADI_DMA_STREAM_ID; /* USB bus speeds */ typedef enum UsbDeviceSpeed { ADI_USB_DEVICE_SPEED_UNKNOWN, ADI_USB_DEVICE_SPEED_HIGH, ADI_USB_DEVICE_SPEED_FULL, ADI_USB_DEVICE_SPEED_LOW, }ADI_USB_DEVICE_SPEED; /* NET2272 Core Device Structure */ typedef struct Net2272DeviceData { ADI_DEV_DEVICE_HANDLE DeviceHandle; /* 设备控制 */ ADI_DMA_MANAGER_HANDLE DMAHandle; /* DMA控制 */ ADI_DCB_HANDLE DCBHandle; /* 数据控制块(DCB) */ ADI_DCB_CALLBACK_FN DMCallback; /* 回调函数 */ ADI_DEV_DIRECTION Direction; /* 设备方向 */ void *pCriticalRegionArg; /* 关键区参数指针 */ bool Started; /* 开始标志 */ DEVICE_STATE State; /* 设备状态 */ PHYSICAL_ENDPOINT_OBJECT PhysicalEndpointObjects[NUM_PHYSICAL_ENDPOINTS]; /* 物理终点对象*/ int NumPhysicalEndpoints; /* 物理中点数量 */ ADI_DMA_STREAM_ID DmaStreamID; /* DMA流的ID */ void* DmaChannelHandle; /* DMA通道句柄 */ ADI_INT_PERIPHERAL_ID PeripheralID; /* 外围设备ID *、 u32 PeripheralIVG; /* 外围设备中断向量优先级*/ int PF_Reset; /* PF(Programmable Flag)角复位 */ int PF_Int; /* PF角中断 */ int PF_Clear; /* PF角清空 */ int PF_Set; /* PF角设置 */ int DeviceID; /* 设备ID */ DEVICE_OBJECT *pDeviceObj; /* 设备对象指针 */ NET2272_STATS Stats; /* NET2272的状态 */ bool Cache; /* Cache */ void *ConfigMemoryArea; /* 配置内存区指针 */ int ConfigMemorySize; /* 配置内存区大小 */ int BufferPrefix; /* 缓冲区前缀 */ ADI_USB_DEVICE_SPEED Speed; /* USB 设备速度 */ }ADI_NET2272_DEVICE; /* We bind each logical Endpoint object with the physical Endpoint objects. The Endpoint Object * that is passed in is the logical endpoint object present in the currently active configuration */ section("L1_code") int BindPhysicalEndpoints(ENDPOINT_OBJECT *pLogicalEp) { int i = 1; PHYSICAL_ENDPOINT_OBJECT *pPhyEpO; ENDPOINT_OBJECT pLogEp = pLogicalEp; ENDPOINT_DESCRIPTOR *pEpD; ADI_NET2272_DEVICE *pDev = &Net2272Device; volatile unsigned char EpCfg = 0x00, e; for (i = 1; ((i <= NUM_PHYSICAL_ENDPOINTS) && (pLogEp != NULL)); i++) { _outpb_d(PAGESEL_ADDR, (unsigned char)i & 0xff); e = _inpb_d(PAGESEL_ADDR); /* Set the logical endpoint object associated for this point */ pDev->PhysicalEndpointObject[i].pLogicalEndpointObj = pLogEp; /* Get the endpoint descriptor */ pEpD = pLogEp->pEndpointDesc; /* Set endpoint ID */ pDev->PhysicalEndpointObjects[i].PhysicalEndpointID = pEpD->bEndpointAddress & 0x0F; /* configure the Max packet size */ _outpb_ind(EP_MAXPKT0, LOW_BYTE_LW(pEpD->wMaxPacketSize)); _outpb_ind(EP_MAXPKT1, HIGH_BYTE_LW(pEpD->wMaxPacketSize)); /* EP_CFG register settings */ EpCfg = ((pEpD->bEndpointAddress & 0x0F) | /* Endpoint Number */ (((pEpD->bEndpointAddress >> 7) & 0x1) << 4) | /* Endpoint Direction. Host in from device */ (pEpD->bAttributes << 5) | /* Endpoint type */ 1 << 7); /* Endpoint Enable */ _outpb_ind(EP_CFG, EpCfg); e = _inpb_d(PAGESEL_ADDR); /* disable all interrupts */ _outpb_d(EP_IRQENB_ADDR, 0x00); /* reset all status registers */ /* write 1 set and write 1 clear */ _outpb_d(EP_STAT0_ADDR, _inpb_d(EP_STAT0_ADDR)); _outpb_d(EP_STAT1_ADDR, _inpb_d(EP_STAT1_ADDR)); /* Check the direction if its 0x1 means IN endpoint (host perspective) * i.e you are going to send data on it, since endpoints are uni-directional * we really care about only one handler at a time */ if ((pEpD->bEndpointAddress >> 7) & 0x1) { _outpb_d(EP_IRQENB_ADDR, EP_DATA_XMTD_INT); } else /* OUT endpoint, you receive data on it */ { _outpb_d(EP_IRQENB_ADDR, EP_DATA_RCVD_INT | EP_DATA_OUT_TOKEN_INT); /* initially clear NAK_OUT_PACKETS */ _outpb_d(EP_RSPCLR_ADDR, (_inpb_d(EP_RSPCLR_ADDR) | EP_NAK_OUT_PACKETS_MODE)); } DUMP_REGISTER(); /* get the next logical endpoint */ pLogEp = pLogEp->pNextActiveEpObj; } /* If the number of logical endpoint objects if larger than physical ones, then it's an error */ /* enable interrupt */ _outpb_ind(IRQENB0, (_inpb_ind(IRQENB0) | (EP_A_INTERRUPT | EP_B_INTERRUPT | EP_C_INTERRUPT | EP_0_INTERRUPT))); DUMP_REGISTER(); return 1; }