int __gc_cleanup(void *ptr, unsigned int delay) { GCQueueItem *i = fwlib->malloc(sizeof *i); if(!i) return -1; i->next = 0; i->body = ptr; i->delay = delay; /* wait for cleanup thread will done */ while(gc_queue.busy) NU_Sleep(40); gc_queue.busy = 1; if(gc_queue.first) { gc_queue.last->next = i; gc_queue.last = i; } else { gc_queue.first = gc_queue.last = i; } gc_queue.busy = 0; /* Resume garbage collector thread */ NU_Resume_Task(&gc_tsk); return 0; }
VOS_UINT32 VOS_ResumeTask( VOS_UINT32 ulTaskID ) { if( ulTaskID >= vos_TaskCtrlBlkNumber ) { return(VOS_ERR); } if ( NU_SUCCESS != NU_Resume_Task( &(vos_TaskCtrlBlk[ulTaskID].NuTid) ) ) { Print("# Nucleus taskResume error.\r\n"); return(VOS_ERR); } return(VOS_OK); }
STATUS DEV_Init_Devices (DEV_DEVICE *devices, INT dev_count) { STATUS status; DV_DEVICE_ENTRY *dev_ptr; INT i; static INT next_index = 0; #if (INCLUDE_RIP2) static INT need_rip2 = 0; #endif for ( i = 0; i < dev_count; i++) { /* Allocate memory for this device entry. */ if ((status = NU_Allocate_Memory(&System_Memory, (VOID **)&dev_ptr, (UNSIGNED)(sizeof(struct _DV_DEVICE_ENTRY)), (UNSIGNED)NU_NO_SUSPEND)) != NU_SUCCESS) { return (status); } /* Clear out the structure. */ UTL_Zero(dev_ptr, sizeof(struct _DV_DEVICE_ENTRY)); /* Adde the new device entry to the list of devices. */ dll_enqueue((tqe_t *)&DEV_Table, (tqe_t *)dev_ptr); #if (INCLUDE_RIP2) /* Should RIP2 be used on this device. */ if( devices[i].dv_use_rip2 ) { if (!need_rip2) NU_Resume_Task(&rip2_task_ptr); need_rip2++; /* Set the routing metric for this device. */ if (devices[i].dv_ifmetric) dev_ptr->dev_metric = devices[i].dv_ifmetric; else dev_ptr->dev_metric = 1; dev_ptr->dev_rip2_recvmode = devices[i].dv_recvmode; dev_ptr->dev_rip2_sendmode = devices[i].dv_sendmode; } #endif /* INCLUDE_RIP2 */ /* Now initialize the fields that we can. The rest will be initialized by the driver. */ /* Set the unit number. This number will be unique for all devices. The first will be numbered at 0 each succeeding device will be numbered contiguously. */ dev_ptr->dev_index = next_index++; /* Initialize the device's name. */ dev_ptr->dev_net_if_name = devices[i].dv_name; /* Get the flags set by the application */ dev_ptr->dev_flags = devices[i].dv_flags; /* Is this a serial link? */ if (devices[i].dv_flags & DV_POINTTOPOINT) { /* Store the options that pertain only to a serial link. All of these may not be used. It depends on the UART. */ dev_ptr->dev_com_port = devices[i].dv_hw.uart.com_port; dev_ptr->dev_baud_rate = devices[i].dv_hw.uart.baud_rate; dev_ptr->dev_data_mode = devices[i].dv_hw.uart.data_mode; dev_ptr->dev_parity = devices[i].dv_hw.uart.parity; dev_ptr->dev_stop_bits = devices[i].dv_hw.uart.stop_bits; dev_ptr->dev_data_bits = devices[i].dv_hw.uart.data_bits; } else { /* Store the options that pertain only to an ethernet link */ dev_ptr->dev_irq = devices[i].dv_hw.ether.dv_irq; dev_ptr->dev_sm_addr = devices[i].dv_hw.ether.dv_shared_addr; dev_ptr->dev_io_addr = devices[i].dv_hw.ether.dv_io_addr; } if( (status = (devices[i].dv_init)(dev_ptr)) != NU_SUCCESS) return status; /* Indicate that the device is Running. */ dev_ptr->dev_flags |= DV_RUNNING; /* If an IP address was specified and this is not a PPP device then go ahead and attach the IP address and the subnet mask. Otherwise it is assumed Bootp will be used to discover the IP address and attach it at a later time. */ if (( *(uint32 *)devices[i].dv_ip_addr != 0 ) && (!(devices[i].dv_flags & DV_POINTTOPOINT))) { if ((status = DEV_Attach_IP_To_Device(dev_ptr->dev_net_if_name, (uint8 *)devices[i].dv_ip_addr, (uint8 *)devices[i].dv_subnet_mask)) != NU_SUCCESS) { return (status); } } else /* Clear the devices IP address. */ memcpy(dev_ptr->dev_addr.dev_ip_addr, IP_Null, 4); } /* Everything is OK. */ return( NU_SUCCESS ); } /* DEV_Init_Devices. */
/*************************************************************************/ #ifdef PLUS VOID NU_EventsDispatcher(UNSIGNED argc, VOID *argv) #else /* !PLUS */ VOID NU_EventsDispatcher(VOID) #endif /* !PLUS */ { struct uport *uprt; struct port *prt; struct sock_struct *sock_ptr = NU_NULL; /* Socket pointer. */ #ifdef PLUS STATUS status; UNSIGNED waittime; #else /* !PLUS */ int16 status, waittime; #endif /* !PLUS */ int16 tmoflag; UNSIGNED event = 0, dat = 0; tqe_t *duptqe, *tqe_wait; /* Timer queue entry */ #ifdef NU_PPP DV_DEVICE_ENTRY *dev_ptr; #endif /******************************************************************* Receive_Message points to a single occurence in the event queue. The index 3 signals that the structure is 3 words (or 6 bytes) long and is formatted as follows: struct { 8 bits: the msg_class 8 bits: the event 16 bits: pointer to the next event on the queue 16 bits: the data field } *******************************************************************/ #ifdef PLUS UNSIGNED Receive_Message[3] = {0, 0, 0}; UNSIGNED actual_size; #else /* !PLUS */ unsigned int Receive_Message[3]; #endif /* !PLUS */ tqe_wait = (tqe_t *)0; #ifdef PLUS /* Remove compilation warnings for unused parameters. */ status = (STATUS) argc + (STATUS) argv; #endif while (1) { /* Retrieve a message from the event queue. Note that if the source queue is empty this task suspends until something becomes available. */ #ifdef PLUS NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND); #else /* !PLUS */ NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER); #endif /* !PLUS */ /* If someone is waiting on the timer list, then we need to calculate the next hit time for that timer. */ if (!tqe_wait) tqe_wait = tcp_timerlist.flink; if (tqe_wait) { #ifdef PLUS if (tqe_wait->duetime > NU_Retrieve_Clock()) waittime = ((UNSIGNED) tqe_wait->duetime - NU_Retrieve_Clock()); else waittime = NU_NO_SUSPEND; #else /* !PLUS */ waittime = (tqe_wait->duetime - NU_Read_Time()); if (waittime <= 0) waittime = (-1); #endif /* !PLUS */ } else { tqe_wait = (tqe_t *)0; #ifdef PLUS waittime = NU_SUSPEND; #else /* !PLUS */ waittime = NU_WAIT_FOREVER; #endif /* !PLUS */ } #ifdef PLUS /* If waittime is not NU_SUSPEND then there is a timeout value. */ if (waittime != NU_NO_SUSPEND) { NU_Release_Semaphore(&TCP_Resource); #else /* !PLUS */ if (waittime >= 0) { NU_Release_Resource(TCP_Resource); #endif /* !PLUS */ #ifdef PLUS status = NU_Receive_From_Queue(&eQueue, &Receive_Message[0], (UNSIGNED)3, &actual_size, waittime); NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND); #else /* !PLUS */ status = NU_Retrieve_Item(eQueue, Receive_Message, waittime); NU_Request_Resource(TCP_Resource, NU_WAIT_FOREVER); #endif /* !PLUS */ } else #ifdef PLUS status = NU_TIMEOUT; #else /* !PLUS */ status = NU_QUEUE_TIMEOUT; #endif /* !PLUS */ #ifndef INTERRUPT netsleep(0); #endif /* !INTERRUPT */ /* Determine if the message was received successfully. */ #ifdef PLUS if (status == NU_TIMEOUT) #else /* !PLUS */ if (status == NU_QUEUE_TIMEOUT) #endif /* !PLUS */ { if (tqe_wait == tcp_timerlist.flink) { /* Take off the head of the list. */ dll_dequeue((tqe_t *) &tcp_timerlist); /* Place any duplicate entries on to the timer list. */ duptqe = (tqe_t *)dll_dequeue(&tqe_wait->duplist); while (duptqe) { tqpost((tqe_t *) &tcp_timerlist, duptqe); duptqe = (tqe_t *)dll_dequeue(&tqe_wait->duplist); } /* Place the dequeued entry on the free list. */ dll_enqueue(&tcptimer_freelist, tqe_wait); tmoflag = 1; /* Take care of event TCPRETRANS here...other events are handled by the CASE statement below... */ if (tqe_wait->tqe_event == TCPRETRANS) { /* Get a pointer to the porlist entry. */ prt = portlist[tqe_wait->tqe_data]; /* If there is still data to be transmitted and we still have a connection, update the retransmission timeout value. */ if ((prt->out.num_packets > 0) || (prt->state > SEST)) { /* If a retransmission timeout occurs, exponential * back-off. This number returns toward the correct * value by the RTT measurement code in ackcheck. */ if (prt->rto < MAXRTO) prt->rto <<= 1; /* double it */ } tcp_retransmit (prt, tqe_wait->tqe_ext_data); tqe_wait = (tqe_t *)0; #ifdef PLUS NU_Release_Semaphore(&TCP_Resource); #else /* !PLUS */ NU_Release_Resource(TCP_Resource); #endif /* !PLUS */ continue; } else { event = tqe_wait->tqe_event; dat = tqe_wait->tqe_data; status = NU_SUCCESS; } } else { tqe_wait = (tqe_t *)0; #ifdef PLUS NU_Release_Semaphore(&TCP_Resource); #else /* !PLUS */ NU_Release_Resource(TCP_Resource); #endif /* !PLUS */ continue; } } else { tmoflag = 0; tqe_wait = (tqe_t *)NU_NULL; } /* Determine if the message was received successfully. */ if (status == NU_SUCCESS) { if (!tmoflag) { event = (int16)Receive_Message[0]; dat = (uint16)Receive_Message[2]; } /* switch on the msg_class/event combination */ switch (event) { default: break; case CONNULL: break; /*********** CONNECTION CLASS **********************/ case CONFAIL: /* connection attempt failed */ case CONOPEN: /* successful connect attempt */ /* Make sure the socket is not NULL, this is possible if a TCP connection is made and immediately RESET by the foreign host. */ if ((sock_ptr = socket_list[dat]) != NU_NULL) { /* return control to the waiting task */ #ifdef PLUS if (sock_ptr->s_TXTask != NU_NULL) NU_Resume_Task(sock_ptr->s_TXTask); #else /* !PLUS */ if (sock_ptr->s_TXTask != -1) NU_Start(sock_ptr->s_TXTask); #endif /* !PLUS */ } break; case TCPACK: /* An ack needs to be sent. */ /* Get a pointer to the port. */ prt = portlist[dat]; /* Clear the ACK timer flag in the port. */ prt->portFlags &= (~ACK_TIMER_SET); /* Send the ack. */ tcp_sendack (prt); break; case CONTX: /* get a pointer into the port list table at the entry pointed to by dat in the event queue */ prt = portlist[dat]; if ( (prt->xmitFlag == NU_SET) && (prt->out.nextPacket != NU_NULL) ) { prt->tcpout.flags |= TPUSH; tcp_xmit(prt, prt->out.nextPacket); prt->out.nextPacket = (NET_BUFFER *)prt->out.nextPacket->next; prt->xmitFlag = NU_CLEAR; } break; case WINPROBE: /* Get a pointer to the socket. */ if ((sock_ptr = socket_list[dat]) != NU_NULL) { /* restart the waiting task */ #ifdef PLUS if (sock_ptr->s_TXTask != NU_NULL) NU_Resume_Task(sock_ptr->s_TXTask); #else if (sock_ptr->s_TXTask != -1) NU_Start(sock_ptr->s_TXTask); #endif } break; case SELECT: NU_Resume_Task((NU_TASK *)dat); break; case ARPRESOLVE: case RARP_REQUEST: ARP_Event((uint16)dat); break; case CONRX: NET_Demux(); break; /********************** USER CLASS *************************/ case UDPDATA: /* get a pointer into the port list table at the entry pointed to by dat in the event queue */ uprt = uportlist[dat]; if (uprt != NU_NULL) { /* return control to the waiting task */ #ifdef PLUS if (uprt->RXTask != NU_NULL) NU_Resume_Task(uprt->RXTask); #else /* !PLUS */ if (uprt->RXTask != -1) NU_Start(uprt->RXTask); #endif /* !PLUS */ } break; #if INCLUDE_IP_MULTICASTING case EV_IGMP_REPORT : /* Send an IGMP multicast group membership report. */ IGMP_REPORT_EVENT(dat); break; #endif /* INCLUDE_IP_MULTICASTING */ case EV_IP_REASSEMBLY : /* Clear the fragment list. The whole datagram has not yet been received. */ IP_Reassembly_Event((IP_QUEUE_ELEMENT *)dat); break; /*********************** PPP CLASS ************************/ #ifdef NU_PPP case LCP_RESEND: /* Remove the PPP header that was added the first time this packet was sent. */ lcp_state.negotiation_pkt->data_ptr += sizeof (PPP_HEADER); lcp_state.negotiation_pkt->data_len -= sizeof (PPP_HEADER); lcp_state.negotiation_pkt->mem_total_data_len -= sizeof (PPP_HEADER); /* Send the packet again. */ PPP_TX_Packet (lcp_state.negotiation_pkt->mem_buf_device, lcp_state.negotiation_pkt); break; case LCP_SEND_CONFIG: /* Send a new configure request packet */ LCP_Send_Config_Req (); break; case HANGUP_MDM: MDM_Hangup(); break; case LCP_ECHO_REQ: /* Send a echo request packet */ LCP_Send_Echo_Req ((DV_DEVICE_ENTRY *) dat); break; case NCP_RESEND: /* Remove the PPP header that was added the first time this packet was sent. */ ncp_state.negotiation_pkt->data_ptr += sizeof (PPP_HEADER); ncp_state.negotiation_pkt->data_len -= sizeof (PPP_HEADER); ncp_state.negotiation_pkt->mem_total_data_len -= sizeof (PPP_HEADER); /* Send the packet again. */ PPP_TX_Packet (ncp_state.negotiation_pkt->mem_buf_device, ncp_state.negotiation_pkt); break; case NCP_SEND_CONFIG: /* Get a pointer to the device structure for this device so that the IP address of this device can be found. */ dev_ptr = (DV_DEVICE_ENTRY *)dat; /* Send it to the host */ NCP_IP_Send_Config_Req (dev_ptr->dev_addr.dev_ip_addr); break; case LCP_CLOSE_LINK: /* Get a pointer to the device structure for this device so that the IP address of this device can be found. */ dev_ptr = (DV_DEVICE_ENTRY *)dat; /* Close the network down. */ PPP_Kill_All_Open_Sockets(dev_ptr); /* Detach the IP address from this device. */ DEV_Detach_IP_From_Device (dev_ptr->dev_net_if_name); /* Send a terminate request */ LCP_Send_Terminate_Req(); /* Start the timer */ NU_Reset_Timer (&LCP_Restart_Timer, LCP_Timer_Expire, LCP_TIMEOUT_VALUE, LCP_TIMEOUT_VALUE, NU_ENABLE_TIMER); break; case PAP_SEND_AUTH: /* Retransmit the authentication pkt */ PAP_Send_Authentication(); break; case CHAP_RESEND: /* Remove the PPP header that was added the first time this packet was sent. */ lcp_state.negotiation_pkt->data_ptr += sizeof (PPP_HEADER); lcp_state.negotiation_pkt->data_len -= sizeof (PPP_HEADER); lcp_state.negotiation_pkt->mem_total_data_len -= sizeof (PPP_HEADER); /* Resend the last sent chap packet */ PPP_TX_Packet (lcp_state.negotiation_pkt->mem_buf_device, lcp_state.negotiation_pkt); break; case CHAP_CHALL: /* Send the CHAP challenge */ CHAP_Send_Challenge(); break; #endif /* NU_PPP */ } /* end switch on msg_class/event combination */ } /* end if status is NU_SUCCESS */ /* added 11/3/92 - during ATI mods */ #ifdef PLUS NU_Release_Semaphore(&TCP_Resource); #else /* !PLUS */ NU_Release_Resource(TCP_Resource); #endif /* !PLUS */ } /* end while */ } /* end NU_EventDispatcher */