/* Create and initialize a NAT entry. */ static __EASY_NAT_ENTRY* CreateNatEntry(__NAT_MANAGER* pMgr) { __EASY_NAT_ENTRY* pEntry = NULL; BUG_ON(NULL == pMgr); /* * If too many NAT entries exist. Should in critical section,but * now it's OK,since the routine will be called by tcp_ip thread only. */ if (MAX_NAT_ENTRY_NUM < pMgr->stat.entry_num) { _hx_printf("[NAT]: too many NAT entries.\r\n"); goto __TERMINAL; } pMgr->stat.entry_num++; /* Create and initialize it. */ pEntry = (__EASY_NAT_ENTRY*)_hx_malloc(sizeof(__EASY_NAT_ENTRY)); if (NULL == pEntry) { goto __TERMINAL; } memset(pEntry, 0, sizeof(__EASY_NAT_ENTRY)); __TERMINAL: return pEntry; }
/* Set a network timer object. */ void _hx_sys_timeout(HANDLE hTarget, unsigned long msecs, sys_timeout_handler handler, void* arg) { HANDLE hTimer = NULL; __network_timer_object* pTimerObject = NULL; pTimerObject = (__network_timer_object*)_hx_malloc(sizeof(__network_timer_object)); if (NULL == pTimerObject) { goto __TERMINAL; } /* * Initialize the network timer object and * insert it into global list. */ pTimerObject->dwObjectSignature = KERNEL_OBJECT_SIGNATURE; pTimerObject->handler = handler; pTimerObject->handler_param = arg; pTimerObject->msecs = msecs; pTimerObject->pNext = timer_list.pNext; pTimerObject->pPrev = &timer_list; timer_list.pNext->pPrev = pTimerObject; timer_list.pNext = pTimerObject; /* Set a HelloX timer object. */ //hTimer = SetTimer((DWORD)pTimerObject, msecs, NULL, NULL, // TIMER_FLAGS_ONCE); hTimer = System.SetTimer( (__COMMON_OBJECT*)&System, (__KERNEL_THREAD_OBJECT*)hTarget, (DWORD)pTimerObject, msecs, NULL, NULL, TIMER_FLAGS_ONCE); if (NULL == hTimer) { _hx_printf("%s:failed to set timer.\r\n", __func__); goto __TERMINAL; } pTimerObject->hTimer = hTimer; __TERMINAL: if (NULL == hTimer) /* Failed to set timer. */ { _hx_release_network_tmo(pTimerObject); } return; }
char* itoa(int value, char* string, int radix) { char tmp[33]; char* tp = tmp; int i; unsigned v; int sign; char* sp; if (radix > 36 || radix <= 1) { //__set_errno(EDOM); return 0; } sign = (radix == 10 && value < 0); if (sign) v = -value; else v = (unsigned)value; while (v || tp == tmp) { i = v % radix; v = v / radix; if (i < 10) *tp++ = i+'0'; else *tp++ = i + 'a' - 10; } if (string == 0) string = (char*)_hx_malloc((tp-tmp)+sign+1); sp = string; if (sign) *sp++ = '-'; while (tp > tmp) *sp++ = *--tp; *sp = 0; return string; }
//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; }
/* 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; }
/* * 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; }
//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; }