/* 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; }
/* * 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; }
/* * 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); }
/* * 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); }
/* 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); }
/* * 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; }
//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; }
//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; }
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 }
/* * 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; }
/* * 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; }
/* * 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; }
/* 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; }
/* * 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; }
/* * 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; }
/* 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); }
/* * 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; }