Beispiel #1
0
/* Uninitializer of NAT manager. */
static void nmUninitialize(__NAT_MANAGER* pMgr)
{
	__EASY_NAT_ENTRY* pEntry = NULL;

	BUG_ON(NULL == pMgr);
	BUG_ON(NULL == pMgr->pTree);
	BUG_ON(NULL == pMgr->lock);

	/* Destroy all NAT entries in system. */
	WaitForThisObject(pMgr->lock);
	pEntry = pMgr->entryList.pNext;
	while (pEntry != &pMgr->entryList)
	{
		/* Unlink it first. */
		pEntry->pNext->pPrev = pEntry->pPrev;
		pEntry->pPrev->pNext = pEntry->pNext;
		_hx_free(pEntry);
		pEntry = pMgr->entryList.pNext;
	}
	ReleaseMutex(pMgr->lock);

	/* Destroy lock. */
	DestroyMutex(pMgr->lock);

	/* Destroy the radix tree object. */
	DestroyRadixTree(pMgr->pTree);
	return;
}
Beispiel #2
0
/*
 * Commit USB sending request.
 */
static BOOL __Commit_Send(__ETHERNET_INTERFACE* pEthInt, char* pSendingBuff, int length, int buff_num)
{
	int actual_len = 0;
	struct ueth_data* ss = NULL;
	struct usb_device *udev = NULL;

	ss = (struct ueth_data*)pEthInt->pIntExtension;
	BUG_ON(NULL == ss);
	udev = ss->pusb_dev;
	BUG_ON(NULL == udev);

	char* msg = _hx_aligned_malloc(length, USB_DMA_MINALIGN);
	if (NULL == msg)
	{
		return FALSE;
	}
	memcpy(msg, pSendingBuff, length);

	int err = usb_bulk_msg(udev, usb_sndbulkpipe(udev, ss->ep_out),
		(void *)pSendingBuff, length,
		//(void*)msg,length,
		&actual_len, USB_BULK_SEND_TIMEOUT);

	/* debug */
	//_hx_printf("%s:len = %d,buff_num = %d,actual_len = %d.\r\n", 
	//	__func__, length, buff_num, actual_len);

	if (err < 0)
	{
		if (pEthInt->ifState.dwTxErrorNum < 6)
		{
			_hx_printf("%s: bulk msg fail[err = %d,buf_l = %d,buff_n = %d].\r\n",
				__func__,
				err,
				length,
				buff_num);
		}
		pEthInt->ifState.dwTxErrorNum += buff_num;
		_hx_free(msg);
		return FALSE;
	}
	/* Update interface level statistics counter. */
	pEthInt->ifState.dwFrameSendSuccess += buff_num;
	_hx_free(msg);
	return TRUE;
}
Beispiel #3
0
/* 
 * Handler of PPPOE_MSG_SENDPACKET message.
 * It gets parameter block objects from list,then
 * send the packet out by calling pppifOutput routine.
 * Parameter block object also be destroyed in
 * this routine.
 */
static void _SendPacketHandler(__PPP_SENDPACKET_BLOCK* pBlock)
{
	BUG_ON(NULL == pBlock);

	/* Send the packet out through PPP interface. */
	pppifOutput(pBlock->out_if, pBlock->pkt_buff, &pBlock->addr);

	/* Release pbuf object since we refered it. */
	pbuf_free(pBlock->pkt_buff);

	/* Destroy the parameter object. */
	_hx_free(pBlock);
}
Beispiel #4
0
/* 
 * Release a network timer object,and unlink it from global list.
 * This routine only release the network timer object,does not
 * check the status of hTimer,even if the HelloX timer object(hTimer)
 * is not destroyed.
 * So please call this routine after make sure the hTimer is 
 * destroyed.
 */
void _hx_release_network_tmo(__network_timer_object* pTimerObject)
{
	BUG_ON(NULL == pTimerObject);
	if (pTimerObject->dwObjectSignature != KERNEL_OBJECT_SIGNATURE)
	{
		return;
	}
	pTimerObject->pPrev->pNext = pTimerObject->pNext;
	pTimerObject->pNext->pPrev = pTimerObject->pPrev;
	/* Clear object signature. */
	pTimerObject->dwObjectSignature = 0;
	_hx_free(pTimerObject);
}
Beispiel #5
0
/* Release a PPPoE instance object. */
static void DestroyPPPoEInstance(__PPPOE_INSTANCE* pInstance)
{
	__PPPOE_ETHIF_BINDING* pBinding = NULL;
	int i = 0;
	__PPPOE_INSTANCE* pPrev = NULL;
	__PPPOE_INSTANCE* pNext = NULL;

	BUG_ON(NULL == pInstance);
	
	if (pInstance->status != SESSION_IDLE)
	{
		return;
	}
	/* Unbind from ethernet interface. */
	for (i = 0; i < PPPOE_MAX_INSTANCE_NUM; i++)
	{
		pBinding = &pppoeBinding[i];
		if (pBinding->pInstance == pInstance)
		{
			pBinding->pInstance = NULL;
			break;
		}
	}
	BUG_ON(PPPOE_MAX_INSTANCE_NUM == i);

	/* Remove from instance list. */
	pPrev = pNext = pppoeManager.pInstanceList;
	while (pNext != pInstance)
	{
		if (NULL == pNext)
		{
			BUG(); /* The instance must be in list. */
		}
		pPrev = pNext;
		pNext = pNext->pNext;
	}
	pPrev->pNext = pNext->pNext;
	if (pppoeManager.pInstanceList == pInstance)
	{
		pppoeManager.pInstanceList = NULL;
	}

	/* Just release the instance object. */
	_hx_free(pInstance);
}
Beispiel #6
0
/* 
 * Handler of PPPOE_MSG_POSTFRAME.It unlinks and deliverys a ethernet
 * frame object into pppoe_disc_input or pppoe_data_input routine,
 * according the frame type value.
 */
static BOOL pppoePostFrameHandler(__PPPOE_MANAGER* pMgr, __PPPOE_POSTFRAME_BLOCK* pParam)
{
	__PPPOE_INSTANCE* pInstance = NULL;
	__ETHERNET_INTERFACE* pEthInt = NULL;
	struct netif* netif = NULL;

	BUG_ON(NULL == pMgr);
	BUG_ON(NULL == pParam);

	pInstance = pParam->pInstance;
	pEthInt = pParam->pEthInt;
	BUG_ON(NULL == pParam->p);
	BUG_ON(NULL == pInstance);
	BUG_ON(NULL == pEthInt);

	/* Delivery the frame to PPPoE module. */
	netif = pEthInt->Proto_Interface[0].pL3Interface;

	/* Delivery to PPPoE module according frame type. */
	if (ETH_FRAME_TYPE_PPPOE_S == pParam->frame_type)
	{
		pppoe_disc_input(netif, pParam->p);
	}
	else if (ETH_FRAME_TYPE_PPPOE_D == pParam->frame_type)
	{
		pppoe_data_input(netif, pParam->p);
	}
	else
	{
		BUG();
	}

	/* Release the post frame parameter object. */
	_hx_free(pParam);
	return TRUE;
}
Beispiel #7
0
//Delivery a Ethernet Frame to this protocol,a dedicated L3 interface is also provided.
BOOL pppoeDeliveryFrame(__ETHERNET_BUFFER* pEthBuff, LPVOID pL3Interface)
{
	__PPPOE_ETHIF_BINDING* pBinding = (__PPPOE_ETHIF_BINDING*)pL3Interface;
	__PPPOE_POSTFRAME_BLOCK* pBlock = NULL;
	struct pbuf *p = NULL, *q = NULL;
	int i = 0;
	BOOL bResult = FALSE;

	BUG_ON(NULL == pEthBuff);
	BUG_ON(NULL == pBinding);
	
	/* Make sure the frame type is PPPoE discovery or session. */
	if ((pEthBuff->frame_type != ETH_FRAME_TYPE_PPPOE_S) &&
		(pEthBuff->frame_type != ETH_FRAME_TYPE_PPPOE_D))
	{
		LINK_STATS_INC(link.proterr);
		goto __TERMINAL;
	}

	if (NULL == pBinding->pInstance) /* No PPPoE instance yet. */
	{
		//_hx_printf("PPPoE frame received but no PPPoE session yet.\r\n");
		goto __TERMINAL;
	}
	/* Only started instance is available to receive frame. */
	if (pBinding->pInstance->status != SESSION_RUNNING)
	{
		goto __TERMINAL;
	}

	/* Allocate post frame block object. */
	pBlock = (__PPPOE_POSTFRAME_BLOCK*)_hx_malloc(sizeof(__PPPOE_POSTFRAME_BLOCK));
	if (NULL == pBlock)
	{
		goto __TERMINAL;
	}
	pBlock->pInstance = pBinding->pInstance;
	pBlock->pEthInt = pEthBuff->pInInterface;
	pBlock->frame_type = pEthBuff->frame_type;
	pBlock->p = NULL;
	pBlock->pNext = NULL;

	p = pbuf_alloc(PBUF_RAW, pEthBuff->act_length, PBUF_RAM);
	if (NULL == p)
	{
		_hx_printf("  %s:allocate pbuf object failed.\r\n", __func__);
		goto __TERMINAL;
	}
	i = 0;
	for (q = p; q != NULL; q = q->next)
	{
		memcpy((u8_t*)q->payload, &pEthBuff->Buffer[i], q->len);
		i = i + q->len;
	}
	pBlock->p = p;

	//Delivery the frame to PPPoE main thread.
	bResult = pppoeManager.PostFrame(pBlock);

__TERMINAL:
	/* 
	 * pBlock and pbuf object should be released if delivery failed.
	 * They will be released in upper module if delivery success.
	 */
	if (!bResult)
	{
		if (p)
		{
			pbuf_free(p);
		}
		if (pBlock)
		{
			_hx_free(pBlock);
			LINK_STATS_INC(link.drop);
		}
	}
	else
	{
		LINK_STATS_INC(link.recv);
	}
	return bResult;
}
Beispiel #8
0
//Create a USB isochronous transfer descriptor and install it into system.
__USB_ISO_DESCRIPTOR* usbCreateISODescriptor(__PHYSICAL_DEVICE* pPhyDev, int direction, int bandwidth,
	char* buffer, int bufflength, __U8 endpoint,__U16 maxPacketSize,__U8 multi)
{
	__USB_ISO_DESCRIPTOR* pIsoDesc = NULL;
	BOOL bResult = FALSE;
	struct usb_device* pUsbDev = NULL;
	struct iTD* pitd = NULL;
	__COMMON_USB_CONTROLLER* pCtrl = NULL;
	struct ehci_ctrl* pEhciCtrl = NULL;
	int maxXferSize = 0, transact_leng = 0;
	int slot_num = 0;     //How many slot the iTD should link to.
	int slot_space = 0;   //The slot number between 2 iTDs in periodic list.
	int i = 0;
	char* buff_ptr = buffer;
	DWORD dwFlags;

	//Parameters check.
	if ((NULL == pPhyDev) || (NULL == buffer) || (0 == bufflength) || (0 == endpoint))
	{
		goto __TERMINAL;
	}
	if ((bandwidth > EHCI_ISO_MAX_BANDWIDTH) || (0 == multi))
	{
		goto __TERMINAL;
	}
	if (maxPacketSize > 1024)  //EHCI spec.
	{
		goto __TERMINAL;
	}
	if ((direction != USB_TRANSFER_DIR_IN) && (direction != USB_TRANSFER_DIR_OUT))
	{
		goto __TERMINAL;
	}
	pUsbDev = (struct usb_device*)pPhyDev->lpPrivateInfo;
	if (NULL == pUsbDev)
	{
		BUG();
	}
	pCtrl = (__COMMON_USB_CONTROLLER*)pUsbDev->controller;
	pEhciCtrl = (struct ehci_ctrl*)pCtrl->pUsbCtrl;

	//8 transactions in one iTD descriptor.
	maxXferSize = maxPacketSize * multi * 8;
	if (bufflength > (int)maxXferSize)
	{
		goto __TERMINAL;
	}

	//Allocate a ISOxfer descriptor and initialize it accordingly.
	pIsoDesc = _hx_malloc(sizeof(__USB_ISO_DESCRIPTOR));
	if (NULL == pIsoDesc)
	{
		goto __TERMINAL;
	}
	memset(pIsoDesc, 0, sizeof(__USB_ISO_DESCRIPTOR));
	pIsoDesc->bandwidth = bandwidth;
	pIsoDesc->buffer = buffer;
	pIsoDesc->bufflength = bufflength;
	pIsoDesc->direction = direction;
	pIsoDesc->ISOXferIntHandler = ISOXferIntHandler;
	pIsoDesc->itdArray = NULL; //Will be initialized later.
	pIsoDesc->itdnumber = 0;   //Will be initialized later.
	pIsoDesc->pCtrl = (__COMMON_USB_CONTROLLER*)pUsbDev->controller;
	pIsoDesc->hEvent = NULL;
	pIsoDesc->endpoint = endpoint;
	pIsoDesc->maxPacketSize = maxPacketSize;
	pIsoDesc->multi = multi;
	pIsoDesc->pNext = NULL;
	pIsoDesc->pPhyDev = pPhyDev;
	pIsoDesc->status = USB_ISODESC_STATUS_INITIALIZED;

	pIsoDesc->hEvent = CreateEvent(FALSE);
	if (NULL == pIsoDesc)
	{
		goto __TERMINAL;
	}

	//Create iTD and initialize it.
	pitd = (struct iTD*)_hx_aligned_malloc(sizeof(struct iTD), 32);
	if (NULL == pitd)
	{
		goto __TERMINAL;
	}
	memset(pitd, 0, sizeof(struct iTD));
	pitd->lp_next |= ITD_NEXT_TERMINATE;  //Terminate bit.
	pitd->lp_next |= ITD_NEXT_TYPE_SET(ITD_NEXT_TYPE_ITD);  //Type as iTD.

	//pitd->transaction[0] |= ITD_TRANS_XLEN_SET(bufflength); //xlength.
	//pitd->transaction[0] |= ITD_TRANS_IOC_SET(1);           //Set IOC bit.
	//pitd->transaction[0] |= ITD_TRANS_PG_SET(0);            //Page 0.
	//pitd->transaction[0] |= ITD_TRANS_XOFFSET_SET(buffer);  //Buffer offset.
	//pitd->pg_pointer[0] |= ITD_PGPTR_SET(buffer);           //Buffer page pointer.

	pitd->pg_pointer[0] |= ITD_ENDPOINT_SET(endpoint);      //Endpoint.
	pitd->pg_pointer[0] |= pUsbDev->devnum;                 //Device address.
	//Set transfer direction.
	if (USB_TRANSFER_DIR_IN == direction)
	{
		pitd->pg_pointer[1] |= ITD_XFERDIR_SET(1);
	}
	else
	{
		pitd->pg_pointer[1] |= ITD_XFERDIR_SET(0);
	}
	pitd->pg_pointer[1] |= ITD_MAX_PKTSZ_SET(maxPacketSize);  //Max packet size.
	pitd->pg_pointer[2] |= ITD_MULTI_SET(multi);              //multiple per (micro)frame.

	//Fill iTD's transaction(s) accordingly.
	__Fill_iTD(pIsoDesc,pitd,direction,buffer,bufflength,endpoint,maxPacketSize,multi);

#if 0
	//Initializes data buffer offset and pointer one by one.
	i = 0;
	buff_ptr = buffer;
	maxXferSize = bufflength;
	transact_leng = (maxPacketSize * multi > maxXferSize) ?
	maxXferSize : (maxPacketSize * multi);
	while (maxXferSize)
	{
		pitd->transaction[i] |= ITD_TRANS_XLEN_SET(bufflength); //xlength.
		pitd->transaction[i] |= ITD_TRANS_PG_SET(i);            //Page 0.
		pitd->transaction[i] |= ITD_TRANS_XOFFSET_SET(buffer);  //Buffer offset.
		pitd->pg_pointer[i] |= ITD_PGPTR_SET(buffer);           //Buffer page pointer.
	}
#endif

#ifdef __DEBUG_USB_ISO
	_hx_printf("iso_iTD:lp_next = 0x%X,trans[0] = 0x%X,pg_ptr[0] = 0x%X,pg_ptr[1] = 0x%X,pg_ptr[2] = 0x%X.\r\n",
		pitd->lp_next, pitd->transaction[0], pitd->pg_pointer[0], pitd->pg_pointer[1],pitd->pg_pointer[2]);
#endif

	flush_dcache_range((unsigned long)pitd, ALIGN_END_ADDR(struct iTD, pitd, 1));

	//Link the iTD to isochronous transfer descriptor.
	pIsoDesc->itdArray = pitd;
	pIsoDesc->itdnumber = 1;

	//Calculate how many periodic list slot shall we use.
	slot_num = bandwidth / 8;
	if (slot_num < bufflength)
	{
		slot_num = 1;
	}
	else
	{
		slot_num = (0 == slot_num % bufflength) ? (slot_num / bufflength) :
			(slot_num / bufflength + 1);
	}
	if (slot_num > USB_PERIODIC_LIST_LENGTH) //Paameter checking makes sure this can not happen.
	{
		_hx_printf("%s:too many slot number[bw = %d,buff_len = %d,slot_num = %d.\r\n",
			__func__,
			bandwidth,
			bufflength,
			slot_num);
		goto __TERMINAL;
	}
	//Save the slot_num to descriptor,since it will be used in usbDestroyISODescriptor routine.
	pIsoDesc->slot_num = slot_num;
	slot_space = USB_PERIODIC_LIST_LENGTH / slot_num;
	if (0 == slot_space)
	{
		slot_space = 1;
	}
#ifdef __DEBUG_USB_ISO
	_hx_printf("slot_num:%d,slot_space:%d.\r\n", slot_num, slot_space);
#endif

	//Stop periodic schedule if enabled already.
	WaitForThisObject(pEhciCtrl->hMutex);
	if (pEhciCtrl->periodic_schedules > 0)
	{
		if (ehci_disable_periodic(pEhciCtrl) < 0) {
			ReleaseMutex(pEhciCtrl->hMutex);
			_hx_printf("FATAL %s: periodic should never fail, but did.\r\n", __func__);
			goto __TERMINAL;
		}
	}

	//Insert the iTD to periodic list,and insert the ISOXfer descriptor into EHCI controller's
	//list.
	i = 0;
	__ENTER_CRITICAL_SECTION(NULL, dwFlags);
	while (slot_num)
	{
		pitd->lp_next = pEhciCtrl->periodic_list[i];
		pEhciCtrl->periodic_list[i] = ((__U32)pitd | QH_LINK_TYPE_ITD);
		flush_dcache_range((unsigned long)&pEhciCtrl->periodic_list[i],
			ALIGN_END_ADDR(uint32_t, &pEhciCtrl->periodic_list[i], 1));
		i += slot_space;
		//Re-calculate the space between slot to make sure the iTD can be linked into
		//periodic list as scatterly as possible.
		slot_space = (USB_PERIODIC_LIST_LENGTH - i) / slot_num;
		if (0 == slot_space)
		{
			slot_space = 1;
		}
		slot_num--;
	}

	//Insert it into global list.
	if (NULL == pEhciCtrl->pIsoDescFirst)  //First element.
	{
		pEhciCtrl->pIsoDescFirst = pIsoDesc;
		pEhciCtrl->pIsoDescLast = pIsoDesc;
	}
	else  //Put it at last.
	{
		//We only support one isochronous xfer at the sametime for simpicity.
		BUG();
		if (NULL == pEhciCtrl->pIsoDescLast)
		{
			BUG();
		}
		pEhciCtrl->pIsoDescLast->pNext = pIsoDesc;
		pEhciCtrl->pIsoDescLast = pIsoDesc;
	}
	__LEAVE_CRITICAL_SECTION(NULL, dwFlags);

	//Restart the periodic schedule if already enabled.
	if (pEhciCtrl->periodic_schedules > 0)
	{
		ehci_enable_periodic(pEhciCtrl);
	}
	ReleaseMutex(pEhciCtrl->hMutex);
	
	bResult = TRUE;

__TERMINAL:
	if (!bResult)
	{
		if (pIsoDesc)  //Should release it.
		{
			if (pIsoDesc->hEvent)
			{
				DestroyEvent(pIsoDesc->hEvent);
			}
			_hx_free(pIsoDesc);
		}
		if (pitd)
		{
			_hx_free(pitd);
		}
		pIsoDesc = NULL;  //Mark as failed.
	}
	return pIsoDesc;
}
Beispiel #9
0
static DWORD copy(__CMD_PARA_OBJ* pCmdObj)
{
#ifdef __CFG_SYS_DDF
	HANDLE   hSourceFile = NULL;
	HANDLE   hDestinationFile = NULL;
	char*    pBuffer = NULL;
	DWORD    dwReadSize = 0;
	DWORD    dwWriteSize = 0;
	DWORD    dwTotalRead = 0;
	char     srcFullName[MAX_FILE_NAME_LEN];
	char     dstFullName[MAX_FILE_NAME_LEN];
	DWORD    dwFileSize = 0;
	DWORD    dwBatSize = 0;

	if (pCmdObj->byParameterNum < 3)
	{
		_hx_printf("Please specify the source and destination file name.\r\n");
		goto __TERMINAL;
	}
	/* Construct source file's full name. */
	if (IsRelative(pCmdObj->Parameter[1]))
	{
		/* Append current directory into the relative file name. */
		strcpy(srcFullName, FsGlobalData.CurrentDir);
		strcat(srcFullName, pCmdObj->Parameter[1]);
	}
	else
	{
		strcpy(srcFullName, pCmdObj->Parameter[1]);
	}
	ToCapital(srcFullName);

	/* Construct destination file's full name. */
	if (IsRelative(pCmdObj->Parameter[2]))
	{
		/* Append current directory into the relative file name. */
		strcpy(dstFullName, FsGlobalData.CurrentDir);
		strcat(dstFullName, pCmdObj->Parameter[2]);
	}
	else
	{
		strcpy(dstFullName, pCmdObj->Parameter[2]);
	}
	ToCapital(dstFullName);

	/* Can not copy one file to itself. */
	if (0 == strcmp(srcFullName, dstFullName))
	{
		_hx_printf("Can not copy a file to it's self.\r\n");
		goto __TERMINAL;
	}

	/* Try to open the source file. */
	hSourceFile = IOManager.CreateFile((__COMMON_OBJECT*)&IOManager,
		srcFullName,
		FILE_ACCESS_READ,
		0,
		NULL);
	if (NULL == hSourceFile)
	{
		_hx_printf("Can not open the source file[%s].\r\n",
			srcFullName);
		goto __TERMINAL;
	}

	/* Try to open or create the destination file name. */
	hDestinationFile = IOManager.CreateFile((__COMMON_OBJECT*)&IOManager,
		dstFullName,
		FILE_OPEN_ALWAYS,
		0,
		NULL);
	if (NULL == hDestinationFile)
	{
		_hx_printf("Can not open the target file[%s].\r\n",
			dstFullName);
		goto __TERMINAL;
	}

	/* Get the source file's size. */
	dwFileSize = GetFileSize(hSourceFile, NULL);
	dwBatSize = dwFileSize / 20;

	/* Allocate a buffer to hold the file's data. */
#define __TMP_FILE_BUFFSZ (64 * 1024)
	pBuffer = (char*)_hx_malloc(__TMP_FILE_BUFFSZ);
	if (NULL == pBuffer)
	{
		_hx_printf("Failed to allocate data buffer.\r\n");
		goto __TERMINAL;
	}

	/* Copy data now. */
	do {
		/* Read the source file. */
		if (!IOManager.ReadFile((__COMMON_OBJECT*)&IOManager,
			hSourceFile,
			__TMP_FILE_BUFFSZ,
			pBuffer,
			&dwReadSize))
		{
			_hx_printf("Can not read the source file.\r\n");
			goto __TERMINAL;
		}

		/* Write the data block into destination file. */
		if (!IOManager.WriteFile((__COMMON_OBJECT*)&IOManager,
			hDestinationFile,
			dwReadSize,
			pBuffer,
			&dwWriteSize))
		{
			_hx_printf("Failed to write data into target file.\r\n");
			goto __TERMINAL;
		}
		dwTotalRead += dwReadSize;

		/* Show out copying progress. */
		if (dwBatSize < dwReadSize)
		{
			_hx_printf(".");
			dwBatSize = dwFileSize / 20;
		}
		else
		{
			dwBatSize -= dwReadSize;
		}
	} while (dwReadSize == __TMP_FILE_BUFFSZ);
#undef __TMP_FILE_BUFFSZ

	_hx_printf("\r\n");
	_hx_printf("[copy]: %d byte(s) copied.\r\n", dwTotalRead);

__TERMINAL:
	if (NULL != hSourceFile)
	{
		IOManager.CloseFile((__COMMON_OBJECT*)&IOManager,
			hSourceFile);
	}
	if (NULL != hDestinationFile)
	{
		IOManager.CloseFile((__COMMON_OBJECT*)&IOManager,
			hDestinationFile);
	}
	if (NULL != pBuffer)
	{
		_hx_free(pBuffer);
	}
	return SHELL_CMD_PARSER_SUCCESS;;
#else
	return FS_CMD_FAILED;
#endif
}
Beispiel #10
0
/*
 * Check if there is a PCI device in system that matches
 * the given ID,and initialize it if found.
 */
static BOOL _Check_E1000_Nic(struct pci_device_id* id)
{
	__PHYSICAL_DEVICE*    pDev = NULL;
	__IDENTIFIER          devId;
	struct e1000_hw*      priv = NULL;
	__U16                 iobase_s = 0, iobase_e = 0;
	LPVOID                memAddr_s = NULL;
	LPVOID                memAddr_e = NULL;
	int                   intVector = 0;
	int                   index = 0;
	BOOL                  bResult = FALSE;
	int                   cardnum = 0;

	//Set device ID accordingly.
	devId.dwBusType = BUS_TYPE_PCI;
	devId.Bus_ID.PCI_Identifier.ucMask = PCI_IDENTIFIER_MASK_VENDOR | PCI_IDENTIFIER_MASK_DEVICE;
	devId.Bus_ID.PCI_Identifier.wVendor = id->vendor_id;
	devId.Bus_ID.PCI_Identifier.wDevice = id->device_id;

	//Try to fetch the physical device with the specified ID.
	pDev = DeviceManager.GetDevice(
		&DeviceManager,
		BUS_TYPE_PCI,
		&devId,
		NULL);
	if (NULL == pDev)  //PCNet may not exist.
	{
		//DEBUGOUT("%s:No device[v_id = 0x%X,d_id = 0x%X] found.\r\n",
		//	__func__,id->vendor_id,id->device_id);
		goto __TERMINAL;
	}

	//Got a valid device,retrieve it's hardware resource and save them into 
	//private structure.
	while (pDev)
	{
		for (index = 0; index < MAX_RESOURCE_NUM; index++)
		{
			if (pDev->Resource[index].dwResType == RESOURCE_TYPE_INTERRUPT)
			{
				intVector = pDev->Resource[index].Dev_Res.ucVector;
			}
			if (pDev->Resource[index].dwResType == RESOURCE_TYPE_IO)
			{
				iobase_s = pDev->Resource[index].Dev_Res.IOPort.wStartPort;
				iobase_e = pDev->Resource[index].Dev_Res.IOPort.wEndPort;
			}
			if (pDev->Resource[index].dwResType == RESOURCE_TYPE_MEMORY)
			{
				memAddr_s = pDev->Resource[index].Dev_Res.MemoryRegion.lpStartAddr;
				memAddr_e = pDev->Resource[index].Dev_Res.MemoryRegion.lpEndAddr;
			}
		}
		//Check if the device with valid resource.
		if ((0 == intVector) && (0 == iobase_s) && (NULL == memAddr_s))
		{
			DEBUGOUT("%s: Find a device without valid resource.\r\n", __func__);
			goto __TERMINAL;
		}

		//Now allocate a rtl8111_priv_t structure and fill the resource.
		priv = (struct e1000_hw*)_hx_malloc(sizeof(struct e1000_hw));
		if (NULL == priv)
		{
			DEBUGOUT("%s:allocate e1000 private structure failed.\r\n", __func__);
			goto __TERMINAL;
		}
		memset(priv, 0, sizeof(struct e1000_hw));

		/* Create tx/rx descriptors and packet buffer. */
		priv->tx_base = (struct e1000_tx_desc*)_hx_aligned_malloc(
			TX_DESC_NUM * sizeof(struct e1000_tx_desc), E1000_BUFFER_ALIGN);
		if (NULL == priv->tx_base)
		{
			goto __TERMINAL;
		}
		priv->rx_base = (struct e1000_rx_desc*)_hx_aligned_malloc(
			RX_DESC_NUM * sizeof(struct e1000_rx_desc), E1000_BUFFER_ALIGN);
		if (NULL == priv->rx_base)
		{
			goto __TERMINAL;
		}
		priv->packet = (unsigned char*)_hx_aligned_malloc(PACKET_BUFFER_SIZE,
			E1000_BUFFER_ALIGN);
		if (NULL == priv->packet)
		{
			goto __TERMINAL;
		}

		priv->pdev = pDev;
		priv->ioport_s = iobase_s;
		priv->ioport_e = iobase_e;
		priv->memaddr_s = memAddr_s;
		priv->memaddr_e = memAddr_e;
		priv->int_vector = intVector;
		priv->cardnum = cardnum++;
		/* Save PCI id. */
		priv->device_id = id->device_id;
		priv->vendor_id = id->vendor_id;

		if (_Init_E1000(priv))
		{
			//Link the private object into global list.
			priv->pNext = e1000_hw_list;
			e1000_hw_list = priv;
			bResult = TRUE;
		}
		else
		{
			goto __TERMINAL;
		}

		DEBUGOUT("%s: Get a E1000 NIC device[int = %d,iobase = 0x%X,mem = 0x%X].\r\n",
			__func__,
			intVector,
			iobase_s,
			memAddr_s);

		//Try to fetch another PCNet device.
		pDev = DeviceManager.GetDevice(
			&DeviceManager,
			BUS_TYPE_PCI,
			&devId,
			pDev);
	}

__TERMINAL:
	if (!bResult)
	{
		if (priv)
		{
			if (priv->tx_base)
			{
				_hx_free(priv->tx_base);
			}
			if (priv->rx_base)
			{
				_hx_free(priv->rx_base);
			}
			if (priv->packet)
			{
				_hx_free(priv->packet);
			}
			_hx_free(priv);
		}
	}
	return bResult;
}
Beispiel #11
0
/* 
 * Send out a packet through PPP/PPPoE main thread.
 * This routine is mainly used as sending routine of PPP interface,
 * which is called by IP layer.
 */
static BOOL pppSendPacket(struct netif* out_if, struct pbuf* pb, ip_addr_t* ipaddr)
{
	__PPP_SENDPACKET_BLOCK* pBlock = NULL;
	__KERNEL_THREAD_MESSAGE msg;
	DWORD dwFlags;
	BOOL bResult = FALSE;

	BUG_ON(NULL == out_if);
	BUG_ON(NULL == pb);

	/* Make sure the PPPoE main thread is in place. */
	if (NULL == pppoeManager.hMainThread)
	{
		goto __TERMINAL;
	}

	/* Allocate a parameter block object to hold all parameters. */
	pBlock = (__PPP_SENDPACKET_BLOCK*)_hx_malloc(sizeof(__PPP_SENDPACKET_BLOCK));
	if (NULL == pBlock)
	{
		goto __TERMINAL;
	}
	/* 
	 * Increase reference counter of pbuf,avoid to be deleted by 
	 * this routine's caller.
	 * The pbuf object will be released in the handler of SENDPACKET
	 * message.
	 */
	pbuf_ref(pb);

	pBlock->pNext = NULL;
	pBlock->out_if = out_if;
	pBlock->pkt_buff = pb; /* Should be confirmed if a new pbuf object should be allocated here. */
	pBlock->addr = *ipaddr;

	/*
	 * Hook the send packet block object into pppoeManager's out going list,
	 * and send a message to the PPPoE main thread if the list is empty,to
	 * trigger the sending process.
	 * Use critical section to protect the list operation since it maybe accessed
	 * in interrupt context.
	 */
	__ENTER_CRITICAL_SECTION_SMP(pppoeManager.spin_lock, dwFlags);
	if (0 == pppoeManager.nOutgSize) /* List is empty. */
	{
		BUG_ON(pppoeManager.pOutgFirst != NULL);
		BUG_ON(pppoeManager.pOutgLast != NULL);
		pppoeManager.pOutgFirst = pppoeManager.pOutgLast = pBlock;
		pBlock->pNext = NULL; /* Very important. */
		pppoeManager.nOutgSize++;
		/* 
		 * Send sending message to PPPoE main thread.
		 * Disable kernel thread's scheduling since in critical
		 * section.
		 */
		__LEAVE_CRITICAL_SECTION_SMP(pppoeManager.spin_lock, dwFlags);
		msg.wCommand = PPPOE_MSG_SENDPACKET;
		msg.wParam = 0;
		msg.dwParam = 0;
		bResult = SendMessage(pppoeManager.hMainThread, &msg);

		if (!bResult) /* Msg queue is full? */
		{
			__ENTER_CRITICAL_SECTION_SMP(pppoeManager.spin_lock, dwFlags);
			/* Unlink from list. */
			pppoeManager.pOutgFirst = pppoeManager.pOutgLast = NULL;
			pppoeManager.nOutgSize = 0;
			__LEAVE_CRITICAL_SECTION_SMP(pppoeManager.spin_lock, dwFlags);
			goto __TERMINAL;
		}
	}
	else /* The out going list is not empty. */
	{
		BUG_ON(NULL == pppoeManager.pOutgFirst);
		BUG_ON(NULL == pppoeManager.pOutgLast);
		if (pppoeManager.nOutgSize > PPPOE_MAX_PENDINGLIST_SIZE)
		{
			__LEAVE_CRITICAL_SECTION_SMP(pppoeManager.spin_lock, dwFlags);
			bResult = FALSE;
			goto __TERMINAL;
		}
		/* Link the block into lsit. */
		pBlock->pNext = NULL;
		pppoeManager.pOutgLast->pNext = pBlock;
		pppoeManager.pOutgLast = pBlock;
		pppoeManager.nOutgSize++;
		__LEAVE_CRITICAL_SECTION_SMP(pppoeManager.spin_lock, dwFlags);
		bResult = TRUE;
	}

#if 0 /* Obsoleted. */
	/* Send message to PPP/PPPoE main thread to trigger sending. */
	msg.wCommand = PPPOE_MSG_SENDPACKET;
	msg.wParam = 0;
	msg.dwParam = (DWORD)pBlock;
	bResult = SendMessage(pppoeManager.hMainThread, &msg);
#endif

__TERMINAL:
	if (!bResult)
	{
		/* Should release the parameter block object. */
		if (pBlock)
		{
			_hx_free(pBlock);
		}
		/* Free pbuf since we refered it. */
		pbuf_free(pb);
		LINK_STATS_INC(link.drop);
	}
	return bResult;
}
Beispiel #12
0
/*
* Kernel thread responses for USB ethernet frame transmition.
* It polls message queue in loop and delivery the received
* frame to Ethernet Manager object if has.
* A KERNEL_MESSAGE_TERMINAL message will cause the thread
* exit.
*/
static DWORD __R8152_Send(LPVOID pData)
{
	__KERNEL_THREAD_MESSAGE msg;
	__ETHERNET_BUFFER* pEthBuff = NULL;
	__ETHERNET_INTERFACE* pEthInt = NULL;
	struct ueth_data* pEthData = (struct ueth_data*)pData;
	DWORD dwFlags;
	static char* pSendingBuff = NULL; /* Dedicated send buffer. */
	int buff_num = 0, offset = 0;
	//struct tx_desc* pTxDesc = NULL;

	if (NULL == pEthData)
	{
		goto __TERMINAL;
	}
	if (NULL == pEthData->thisIf)  //Shoud not occur.
	{
		BUG();
	}
	pEthInt = pEthData->thisIf;
	
	BUG_ON(NULL == pEthData->tx_buff);
	BUG_ON(NULL == pEthData->pTxDesc);
	pSendingBuff = pEthData->tx_buff;

	/*
	 * Change the owner of tx xfer descriptor,it's default
	 * owner is USB_Core thread since it is created in process
	 * of initialization.
	 * Set to current thead to facilite debugging.
	 */
	pEthData->pTxDesc->hOwnerThread = (HANDLE)KernelThreadManager.lpCurrentKernelThread;

	//Check the message queue.
	while (KernelThreadManager.GetMessage(NULL, &msg))
	{
		if (msg.wCommand == KERNEL_MESSAGE_TERMINAL)
		{
			/*
			* If the thread exit without process the sending queue,memory
			* leaking may lead since there maybe ethernet buffer(s) pending
			* in queue.
			* We will curb this issue later.(:-)
			*/
			goto __TERMINAL;
		}
		if (msg.wCommand == R8152_SEND_FRAME)
		{
			while (TRUE)
			{
				__ENTER_CRITICAL_SECTION(NULL, dwFlags);
				/*
				* Fetch one ethernet frame from sending list.
				*/
				pEthBuff = pEthData->pSndList;
				if (NULL == pEthBuff) /* No pending frame. */
				{
					__LEAVE_CRITICAL_SECTION(NULL, dwFlags);
					break;
				}
				pEthData->pSndList = pEthBuff->pNext;
				/*
				* Decrease the general sending queue size of system.
				*/
				EthernetManager.nDrvSendingQueueSz--;
				/* Update the sending queue(list) size. */
				pEthInt->nSendingQueueSz--;
				__LEAVE_CRITICAL_SECTION(NULL, dwFlags);
				BUG_ON(pEthBuff->pEthernetInterface != pEthInt);
				buff_num++;
				/*
				 * Pack the ethernet buffer into sending buffer,
				 * send it out if the buffer full.
				 */
				if (!__R8152_Pack_Ethernet_Buffer(pSendingBuff, pEthBuff, offset, &offset))
				{
					//__Commit_Send(pEthInt, pSendingBuff, offset, buff_num);
					__Commit_Nostop_Send(pEthInt, pSendingBuff, offset, buff_num);
					/* Reset state info. */
					offset = 0;
					buff_num = 0;
				}
				else
				{
					if (NULL == pEthBuff->pNext) /* Last buffer */
					{
						//__Commit_Send(pEthInt, pSendingBuff, offset, buff_num);
						__Commit_Nostop_Send(pEthInt, pSendingBuff, offset, buff_num);
						offset = 0;
						buff_num = 0;
					}
				}
				EthernetManager.DestroyEthernetBuffer(pEthBuff);
			}
		}
	}

__TERMINAL:
	/*
	 * Destroy the tx descriptor and tx buffer,they are created in process
	 * of NIC initialization.
	 */
	if (pEthData->pTxDesc)
	{
		usbStopAsyncXfer(pEthData->pTxDesc);
		usbDestroyAsyncDescriptor(pEthData->pTxDesc);
		pEthData->pTxDesc = NULL;
	}
	if (NULL != pSendingBuff)
	{
		_hx_free(pSendingBuff);
	}
	_hx_printf("%s:exit tx thread of ethernet if[%s].\r\n",
		__func__, pEthInt->ethName);
	return 0;
}
Beispiel #13
0
/* Create a new PPPoE instance. */
static __PPPOE_INSTANCE* CreatePPPoEInstance(char* ethName, char* instName, char* user_name, 
	char* password,__PPPOE_AUTH_TYPE authType)
{
	__PPPOE_INSTANCE* pInstance = NULL;
	int i = 0;
	__ETHERNET_INTERFACE* pEthInt = NULL;
	__PPPOE_ETHIF_BINDING* pBinding = NULL;
	BOOL bResult = FALSE;

	BUG_ON(NULL == instName);
	BUG_ON(NULL == user_name);
	BUG_ON(NULL == ethName);

	/* 
	 * Can not create PPPoE instance without any ethernet interface
	 * that bound to PPPoE protocol.
	 */
	if (0 == current_bind_num)
	{
		goto __TERMINAL;
	}

	pInstance = _hx_malloc(sizeof(__PPPOE_INSTANCE));
	if (NULL == pInstance)
	{
		goto __TERMINAL;
	}
	/* Initialize it. */
	memset(pInstance, 0, sizeof(*pInstance));
	pInstance->authType = authType;
	pInstance->instance_id = session_id++;
	pInstance->ppp_session_id = -1;
	pInstance->status = SESSION_IDLE;
	pInstance->pEthInt = NULL;

	/* Set PPPoE user name. */
	if (strlen(user_name) > PPPOE_USER_NAME_LEN)
	{
		goto __TERMINAL;
	}
	strcpy(pInstance->user_name, user_name);

	/* Set PPPoE instance name. */
	if (strlen(instName) > PPPOE_SESSION_NAME_LEN)
	{
		goto __TERMINAL;
	}
	strcpy(pInstance->session_name, instName);

	/* Set password if specified. */
	if (strlen(password) > PPPOE_PASSWORD_LEN)
	{
		goto __TERMINAL;
	}
	strcpy(pInstance->password, password);

#if 0
	/* Set the ethernet interface this session based on. */
	pEthInt = EthernetManager.GetEthernetInterface(ethName);
	if (NULL == pEthInt)
	{
		goto __TERMINAL;
	}
	pInstance->pEthInt = pEthInt;
#endif

	/* Find the ethernet interface that this instance based on. */
	for (i = 0; i < PPPOE_MAX_INSTANCE_NUM; i++)
	{
		pBinding = &pppoeBinding[i];
		if (NULL == pBinding->pEthInt)
		{
			continue;
		}
		if (0 == strcmp(ethName, pBinding->pEthInt->ethName))
		{
			pInstance->pEthInt = pBinding->pEthInt;
			pBinding->pInstance = pInstance;
			break;
		}
	}
	if (NULL == pInstance->pEthInt) /* Can not match ethernet interface. */
	{
		goto __TERMINAL;
	}

	/* Link the instance to global list. */
	pInstance->pNext = pppoeManager.pInstanceList;
	pppoeManager.pInstanceList = pInstance;

	/* Set success indictor. */
	bResult = TRUE;

__TERMINAL:
	if (!bResult) /* Should release the instance. */
	{
		if (pInstance)
		{
			_hx_free(pInstance);
			pInstance = NULL;
		}
	}
	return pInstance;
}
Beispiel #14
0
/*
* Kernel thread responses for USB ethernet frame receiving.
* It polls USB ethernet device in loop and delivery the received
* frame to Ethernet Manager object if has.
* A KERNEL_MESSAGE_TERMINAL message will cause the thread
* exit.
*/
static DWORD __R8152_Recv(LPVOID pData)
{
	__KERNEL_THREAD_MESSAGE msg;
	__ETHERNET_BUFFER* pEthBuff = NULL;
	__ETHERNET_INTERFACE* pEthInt = NULL;
	struct ueth_data* pEthData = (struct ueth_data*)pData;
	struct usb_device* dev = NULL;
	char* rx_buff = NULL;

	if (NULL == pEthData)
	{
		goto __TERMINAL;
	}
	BUG_ON(NULL == pEthData->thisIf);
	pEthInt = pEthData->thisIf;
	dev = pEthData->pusb_dev;
	BUG_ON(NULL == dev);
	BUG_ON(NULL == pEthData->rx_buff);
	BUG_ON(NULL == pEthData->pRxDesc);
	rx_buff = pEthData->rx_buff;

	/*
	* Change the owner of tx xfer descriptor,it's default
	* owner is USB_Core thread since it is created in process
	* of initialization.
	* Set to current thead to facilite debugging.
	*/
	pEthData->pRxDesc->hOwnerThread = (HANDLE)KernelThreadManager.lpCurrentKernelThread;

	while (TRUE)
	{
		//Peek the message queue.
		while (KernelThreadManager.PeekMessage(NULL, &msg))
		{
			if (msg.wCommand == KERNEL_MESSAGE_TERMINAL)
			{
				/*
				* If the thread exit without process the sending queue,memory
				* leaking may lead since there maybe ethernet buffer(s) pending
				* in queue.
				* We will curb this issue later.(:-)
				*/
				goto __TERMINAL;
			}
		}
		//Poll the USB ethernet device to receive ethernet buffer.
		//__r8152_recv(pEthInt);
		__r8152_nostop_recv(pEthInt, pEthData->pRxDesc);
	}

__TERMINAL:
	/*
	 * Destroy the rx descriptor and rx buffer,
	 * they are created in process of NIC initialization.
	 */
	if (pEthData->pRxDesc)
	{
		usbStopAsyncXfer(pEthData->pRxDesc);
		usbDestroyAsyncDescriptor(pEthData->pRxDesc);
		/* Reset to NULL. */
		pEthData->pRxDesc = NULL;
	}
	if (rx_buff)
	{
		_hx_free(rx_buff);
	}
	_hx_printf("%s:exit rx thread of ethernet[%s].\r\n",
		__func__,
		pEthInt->ethName);
	return 0;
}
Beispiel #15
0
/* 
 * Add a new NAT entry in system,when out direction entry can not
 * be found.
 */
static __EASY_NAT_ENTRY* AddNewNatEntry(__NAT_MANAGER* pMgr, struct ip_hdr* pHdr, struct netif* pOutIf)
{
	__EASY_NAT_ENTRY* pEntry = NULL;
	__EASY_NAT_ENTRY* pHashList = NULL;
	int err_code = -1;
	unsigned long hash_key = 0;
	BOOL bResult = FALSE;

	BUG_ON(NULL == pMgr);
	BUG_ON(NULL == pHdr);
	BUG_ON(NULL == pOutIf);

	/* Try to create a new NAT entry. */
	pEntry = CreateNatEntry(pMgr);
	if (NULL == pEntry)
	{
		goto __TERMINAL;
	}
	/* Initialize it by using IP hdr. */
	InitNatEntry(pEntry, pHdr, pOutIf);

	/* 
	 * Calculate the corresponding hash key of the new NAT
	 * in radix tree.
	 */
	hash_key = enatGetHashKeyByHdr(pHdr,out);

	/* Add the new NAT entry into radix tree and global list. */
	WaitForThisObject(pMgr->lock);
	pHashList = pMgr->pTree->Lookup(pMgr->pTree, hash_key);
	if (NULL == pHashList) /* No entry with the same key. */
	{
		pEntry->pHashNext = NULL;
		err_code = pMgr->pTree->Insert(pMgr->pTree, hash_key, pEntry);
		if (ERR_OK != err_code)
		{
			ReleaseMutex(pMgr->lock);
			_hx_printf("Insert NAT entry into radix tree failed[code = %d]", err_code);
			goto __TERMINAL;
		}
	}
	else /* Hash collision,just link to hash list. */
	{
		pEntry->pHashNext = pHashList->pHashNext;
		pHashList->pHashNext = pEntry;
	}
	/* Add to global NAT entry list. */
	pEntry->pNext = pMgr->entryList.pNext;
	pEntry->pNext->pPrev = pEntry;
	pEntry->pPrev = &pMgr->entryList;
	pMgr->entryList.pNext = pEntry;
	ReleaseMutex(pMgr->lock);

	bResult = TRUE;

__TERMINAL:
	if (!bResult)
	{
		if (pEntry)
		{
			_hx_free(pEntry);
			pEntry = NULL;
		}
	}
	return pEntry;
}
Beispiel #16
0
/* Destroy an easy NAT entry. */
static void DestroyNatEntry(__NAT_MANAGER* pMgr, __EASY_NAT_ENTRY* pEntry)
{
	BUG_ON(NULL == pEntry);
	NatManager.stat.entry_num--;
	_hx_free(pEntry);
}
Beispiel #17
0
/*
* A helper routine to initialize and register a new found R8152
* device. It will be invoked when a new device is scaned in Driver Entry
* routine.
*/
static int Init_R8152(struct usb_device *dev, unsigned int ifnum)
{
	struct usb_interface *iface;
	struct usb_interface_descriptor *iface_desc;
	int ep_in_found = 0, ep_out_found = 0;
	struct ueth_data* ss = NULL;
	int i, ret = 0;
	struct r8152 *tp = NULL;
	char recv_name[64];
	static int ef_idx = 0;

	/* Construct a new management data struct of R8152. */
	ss = _hx_malloc(sizeof(struct ueth_data));
	if (NULL == ss)
	{
		goto __TERMINAL;
	}
	memset(ss, 0, sizeof(struct ueth_data));

	/* let's examine the device now */
	iface = &dev->config.if_desc[ifnum];
	iface_desc = &dev->config.if_desc[ifnum].desc;

	/* At this point, we know we've got a live one */
	debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n",
		dev->descriptor.idVendor, dev->descriptor.idProduct);

	/* Initialize the ueth_data structure with some useful info */
	ss->ifnum = ifnum;
	ss->pusb_dev = dev;
	ss->subclass = iface_desc->bInterfaceSubClass;
	ss->protocol = iface_desc->bInterfaceProtocol;

	/* alloc driver private */
	ss->dev_priv = calloc(1, sizeof(struct r8152));
	if (!ss->dev_priv)
	{
		goto __TERMINAL;
	}
	memzero(ss->dev_priv, sizeof(struct r8152));

	/*
	* We are expecting a minimum of 3 endpoints - in, out (bulk), and
	* int. We will ignore any others.
	*/
	for (i = 0; i < iface_desc->bNumEndpoints; i++) {
		/* is it an BULK endpoint? */
		if ((iface->ep_desc[i].bmAttributes &
			USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
			u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
			if ((ep_addr & USB_DIR_IN) && !ep_in_found) {
				ss->ep_in = ep_addr &
					USB_ENDPOINT_NUMBER_MASK;
				ep_in_found = 1;
			}
			else {
				if (!ep_out_found) {
					ss->ep_out = ep_addr &
						USB_ENDPOINT_NUMBER_MASK;
					ep_out_found = 1;
				}
			}
		}

		/* is it an interrupt endpoint? */
		if ((iface->ep_desc[i].bmAttributes &
			USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
			ss->ep_int = iface->ep_desc[i].bEndpointAddress &
				USB_ENDPOINT_NUMBER_MASK;
			ss->irqinterval = iface->ep_desc[i].bInterval;
		}
	}

	debug("Endpoints In %d Out %d Int %d\n", ss->ep_in, ss->ep_out, ss->ep_int);

	/* Do some basic sanity checks, and bail if we find a problem */
	if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
		!ss->ep_in || !ss->ep_out || !ss->ep_int) {
		debug("Problems with device\n");
		goto __TERMINAL;
	}

	/* Establish data structure's relationship. */
	dev->privptr = (void *)ss;
	tp = ss->dev_priv;
	tp->udev = dev;
	tp->intf = iface;

	r8152b_get_version(tp);

	if (rtl_ops_init(tp))
	{
		_hx_printf("%s: failed to init r8152 device.\r\n", __func__);
		goto __TERMINAL;
	}

	tp->rtl_ops.init(tp);
	tp->rtl_ops.up(tp);

	rtl8152_set_speed(tp, AUTONEG_ENABLE,
		tp->supports_gmii ? SPEED_1000 : SPEED_100,
		DUPLEX_FULL);

	/* Assign a index value to this USB ethernet interface. */
	ss->ef_idx = ef_idx++;

	/* Initialization seems OK,now register the R8152 device into
	* HelloX kernel.
	*/
	if (!Register_R8152(dev, ss))
	{
		_hx_printf("Failed to register R8152 into system.\r\n");
		goto __TERMINAL;
	}

	/*
	* Create the recv and send buffer.These 2 buffers
	* will be released when the corresponding rx/tx thread exit.
	*/
	ss->rx_buff = (char*)_hx_aligned_malloc(RTL8152_AGG_BUF_SZ, USB_DMA_MINALIGN);
	if (NULL == ss->rx_buff)
	{
		goto __TERMINAL;
	}
	ss->tx_buff = (char*)_hx_aligned_malloc(RTL8152_AGG_BUF_SZ, USB_DMA_MINALIGN);
	if (NULL == ss->tx_buff)
	{
		goto __TERMINAL;
	}

	/*
	* Create the rx and tx bulk transfer descriptor,which is used
	* by the corresponding rx/tx thread.
	* These 2 descriptors will be destroyed by the rx/tx thread before
	* exit.
	*/
	ss->pTxDesc = usbCreateAsyncDescriptor(
		ss->pusb_dev, usb_sndbulkpipe(ss->pusb_dev, ss->ep_out),
		ss->tx_buff, RTL8152_AGG_BUF_SZ, NULL);
	if (NULL == ss->pTxDesc)
	{
		goto __TERMINAL;
	}
	ss->pRxDesc = usbCreateAsyncDescriptor(
		ss->pusb_dev, usb_rcvbulkpipe(ss->pusb_dev, ss->ep_in),
		ss->rx_buff, RTL8152_AGG_BUF_SZ, NULL);
	if (NULL == ss->pRxDesc)
	{
		_hx_printf("%s: create rx desc failed.\r\n", __func__);
		goto __TERMINAL;
	}

	/*
	* Create the dedicated receiving kernel thread.
	*/
	_hx_sprintf(recv_name, "%s%d", R8152_RECV_NAME_BASE, ss->ef_idx);
	ss->pRxThread = KernelThreadManager.CreateKernelThread(
		(__COMMON_OBJECT*)&KernelThreadManager,
		0,
		KERNEL_THREAD_STATUS_SUSPENDED,
		PRIORITY_LEVEL_NORMAL,
		__R8152_Recv,
		(LPVOID)ss,
		NULL,
		recv_name);
	if (NULL == ss->pRxThread)
	{
		goto __TERMINAL;
	}

	/*
	* Create the dedicated sending kernel thread.
	*/
	_hx_sprintf(recv_name, "%s%d", R8152_SEND_NAME_BASE, ss->ef_idx);
	ss->pTxThread = KernelThreadManager.CreateKernelThread(
		(__COMMON_OBJECT*)&KernelThreadManager,
		0,
		KERNEL_THREAD_STATUS_SUSPENDED,
		PRIORITY_LEVEL_NORMAL,
		__R8152_Send,
		(LPVOID)ss,
		NULL,
		recv_name);
	if (NULL == ss->pTxThread)
	{
		goto __TERMINAL;
	}

	/* Link the management data structure into global list. */
	ss->pNext = global_list;
	global_list = ss;

	/* Resume the corresponding thread to run. */
	/*KernelThreadManager.ResumeKernelThread(
		(__COMMON_OBJECT*)&KernelThreadManager,
		(__COMMON_OBJECT*)ss->pRxThread);
	KernelThreadManager.ResumeKernelThread(
		(__COMMON_OBJECT*)&KernelThreadManager,
		(__COMMON_OBJECT*)ss->pTxThread);*/

	/* Mark all things in place. */
	ret = 1;

__TERMINAL:
	if (0 == ret)  /* Failed,should release all resources allocated. */
	{
		if (ss)
		{
			Unregister_R8152(dev, ss);
			if (ss->pRxThread)  //Shoud destroy it.
			{
				WaitForThisObject((HANDLE)ss->pRxThread);
				KernelThreadManager.DestroyKernelThread(
					(__COMMON_OBJECT*)&KernelThreadManager,
					(__COMMON_OBJECT*)ss->pRxThread);
			}
			if (ss->pTxThread)
			{
				WaitForThisObject((HANDLE)ss->pTxThread);
				KernelThreadManager.DestroyKernelThread(
					(__COMMON_OBJECT*)&KernelThreadManager,
					(__COMMON_OBJECT*)ss->pTxThread);
			}
			if (ss->dev_priv)
			{
				_hx_free(ss->dev_priv);
			}
			if (ss->rx_buff)
			{
				_hx_free(ss->rx_buff);
			}
			if (ss->tx_buff)
			{
				_hx_free(ss->tx_buff);
			}
			if (ss->pRxDesc)
			{
				usbStopAsyncXfer(ss->pRxDesc);
				usbDestroyAsyncDescriptor(ss->pRxDesc);
			}
			if (ss->pTxDesc)
			{
				usbStopAsyncXfer(ss->pTxDesc);
				usbDestroyAsyncDescriptor(ss->pTxDesc);
			}
			_hx_free(ss);
		}
		/* Reset USB device's private pointer since it maybe changed in
		* above process.
		*/
		dev->privptr = NULL;
	}
	return ret;
}