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