📄 rtems_glue.c
字号:
t->arg = arg; /* * Start the task */ sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t); if (sc != RTEMS_SUCCESSFUL) rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc)); /* * Let our caller know the i.d. of the new task */ return tid;}rtems_status_code rtems_bsdnet_event_receive ( rtems_event_set event_in, rtems_option option_set, rtems_interval ticks, rtems_event_set *event_out){ rtems_status_code sc; rtems_bsdnet_semaphore_release (); sc = rtems_event_receive (event_in, option_set, ticks, event_out); rtems_bsdnet_semaphore_obtain (); return sc;}/* * Return time since startup */voidmicrotime (struct timeval *t){ rtems_interval now; rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); t->tv_sec = now / rtems_bsdnet_ticks_per_second; t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;}unsigned longrtems_bsdnet_seconds_since_boot (void){ rtems_interval now; rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); return now / rtems_bsdnet_ticks_per_second;}/* * Fake random number generator */unsigned longrtems_bsdnet_random (void){ rtems_interval now; rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); return (now * 99991);}/* * Callout list processing */voidtimeout(void (*ftn)(void *), void *arg, int ticks){ register struct callout *new, *p, *t; if (ticks <= 0) ticks = 1; /* Fill in the next free callout structure. */ if (callfree == NULL) { callfree = malloc (sizeof *callfree); if (callfree == NULL) rtems_panic ("No memory for timeout table entry"); callfree->c_next = NULL; } new = callfree; callfree = new->c_next; new->c_arg = arg; new->c_func = ftn; /* * The time for each event is stored as a difference from the time * of the previous event on the queue. Walk the queue, correcting * the ticks argument for queue entries passed. Correct the ticks * value for the queue entry immediately after the insertion point * as well. Watch out for negative c_time values; these represent * overdue events. */ for (p = &calltodo; (t = p->c_next) != NULL && ticks > t->c_time; p = t) if (t->c_time > 0) ticks -= t->c_time; new->c_time = ticks; if (t != NULL) t->c_time -= ticks; /* Insert the new entry into the queue. */ p->c_next = new; new->c_next = t;}/* * Ticks till specified time * XXX: This version worries only about seconds, but that's good * enough for the way the network code uses this routine. */inthzto(struct timeval *tv){ long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot(); if (diff <= 0) return 1; return diff * rtems_bsdnet_ticks_per_second;}/* * Kernel debugging */int rtems_bsdnet_log_priority;voidrtems_bsdnet_log (int priority, const char *fmt, ...){ va_list args; if (priority & rtems_bsdnet_log_priority) { va_start (args, fmt); vprintf (fmt, args); va_end (args); }}/* * IP header checksum routine for processors which don't have an inline version */u_intin_cksum_hdr (const void *ip){ rtems_unsigned32 sum; const rtems_unsigned16 *sp; int i; sum = 0; sp = (rtems_unsigned16 *)ip; for (i = 0 ; i < 10 ; i++) sum += *sp++; while (sum > 0xFFFF) sum = (sum & 0xffff) + (sum >> 16); return ~sum & 0xFFFF;}/* * Manipulate routing tables */int rtems_bsdnet_rtrequest ( int req, struct sockaddr *dst, struct sockaddr *gateway, struct sockaddr *netmask, int flags, struct rtentry **net_nrt){ int error; rtems_bsdnet_semaphore_obtain (); error = rtrequest (req, dst, gateway, netmask, flags, net_nrt); rtems_bsdnet_semaphore_release (); if (error) { errno = error; return -1; } return 0;}static intrtems_bsdnet_setup (void){ struct rtems_bsdnet_ifconfig *ifp; short flags; struct sockaddr_in address; struct sockaddr_in netmask; struct sockaddr_in broadcast; struct sockaddr_in gateway; int i; extern char *strdup (const char *cp); /* * Set local parameters */ if (rtems_bsdnet_config.hostname) sethostname (rtems_bsdnet_config.hostname, strlen (rtems_bsdnet_config.hostname)); if (rtems_bsdnet_config.domainname) rtems_bsdnet_domain_name = strdup (rtems_bsdnet_config.domainname); if (rtems_bsdnet_config.log_host) rtems_bsdnet_log_host_address.s_addr = inet_addr (rtems_bsdnet_config.log_host); for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server / sizeof rtems_bsdnet_config.name_server[0] ; i++) { if (!rtems_bsdnet_config.name_server[i]) break; rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr = inet_addr (rtems_bsdnet_config.name_server[i]); } for (i = 0 ; i < sizeof rtems_bsdnet_config.ntp_server / sizeof rtems_bsdnet_config.ntp_server[0] ; i++) { if (!rtems_bsdnet_config.ntp_server[i]) break; rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count++].s_addr = inet_addr (rtems_bsdnet_config.ntp_server[i]); } /* * Configure interfaces */ for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) { if (ifp->ip_address == NULL) continue; /* * Bring interface up */ flags = IFF_UP; if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFFLAGS, &flags) < 0) { printf ("Can't bring %s up: %s\n", ifp->name, strerror (errno)); continue; } /* * Set interface netmask */ memset (&netmask, '\0', sizeof netmask); netmask.sin_len = sizeof netmask; netmask.sin_family = AF_INET; netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask); if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFNETMASK, &netmask) < 0) { printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno)); continue; } /* * Set interface address */ memset (&address, '\0', sizeof address); address.sin_len = sizeof address; address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr (ifp->ip_address); if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFADDR, &address) < 0) { printf ("Can't set %s address: %s\n", ifp->name, strerror (errno)); continue; } /* * Set interface broadcast address if the interface has the * broadcast flag set. */ if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &flags) < 0) { printf ("Can't read %s flags: %s\n", ifp->name, strerror (errno)); continue; } if (flags & IFF_BROADCAST) { memset (&broadcast, '\0', sizeof broadcast); broadcast.sin_len = sizeof broadcast; broadcast.sin_family = AF_INET; broadcast.sin_addr.s_addr = address.sin_addr.s_addr | ~netmask.sin_addr.s_addr; if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFBRDADDR, &broadcast) < 0) { struct in_addr in_addr; char buf[20]; in_addr.s_addr = broadcast.sin_addr.s_addr; if (!inet_ntop(AF_INET, &in_addr, buf, sizeof(buf))) strcpy(buf,"?.?.?.?"); printf ("Can't set %s broadcast address %s: %s\n", ifp->name, buf, strerror (errno)); } } } /* * Set default route */ if (rtems_bsdnet_config.gateway) { address.sin_addr.s_addr = INADDR_ANY; netmask.sin_addr.s_addr = INADDR_ANY; memset (&gateway, '\0', sizeof gateway); gateway.sin_len = sizeof gateway; gateway.sin_family = AF_INET; gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway); if (rtems_bsdnet_rtrequest ( RTM_ADD, (struct sockaddr *)&address, (struct sockaddr *)&gateway, (struct sockaddr *)&netmask, (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) { printf ("Can't set default route: %s\n", strerror (errno)); return -1; } } return 0;}/* * Initialize the network */intrtems_bsdnet_initialize_network (void){ struct rtems_bsdnet_ifconfig *ifp; /* * Start network tasks. * Initialize BSD network data structures. */ if (rtems_bsdnet_initialize () < 0) return -1; /* * Attach interfaces */ for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) { rtems_bsdnet_attach (ifp); } /* * Bring up the network */ if (rtems_bsdnet_setup () < 0) return -1; if (rtems_bsdnet_config.bootp) (*rtems_bsdnet_config.bootp)(); return 0;}/* * Attach a network interface. */void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifp){ if (ifp) { rtems_bsdnet_semaphore_obtain (); (ifp->attach)(ifp, 1); rtems_bsdnet_semaphore_release (); }}/* * Detach a network interface. */void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifp){ if (ifp) { rtems_bsdnet_semaphore_obtain (); (ifp->attach)(ifp, 0); rtems_bsdnet_semaphore_release (); }}/* * Interface Configuration. */int rtems_bsdnet_ifconfig (const char *ifname, unsigned32 cmd, void *param){ int s, r = 0; struct ifreq ifreq; /* * Configure interfaces */ s = socket (AF_INET, SOCK_DGRAM, 0); if (s < 0) return -1; strncpy (ifreq.ifr_name, ifname, IFNAMSIZ); rtems_bsdnet_semaphore_obtain (); switch (cmd) { case SIOCSIFADDR: case SIOCSIFNETMASK: memcpy (&ifreq.ifr_addr, param, sizeof (struct sockaddr)); r = ioctl (s, cmd, &ifreq); break; case OSIOCGIFADDR: case SIOCGIFADDR: case OSIOCGIFNETMASK: case SIOCGIFNETMASK: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; memcpy (param, &ifreq.ifr_addr, sizeof (struct sockaddr)); break; case SIOCGIFFLAGS: case SIOCSIFFLAGS: if ((r = ioctl (s, SIOCGIFFLAGS, &ifreq)) < 0) break; if (cmd == SIOCGIFFLAGS) { *((short*) param) = ifreq.ifr_flags; break; } ifreq.ifr_flags |= *((short*) param); if ( (*((short*) param) & IFF_UP ) == 0 ) { /* set the interface down */ ifreq.ifr_flags &= ~(IFF_UP); } r = ioctl (s, SIOCSIFFLAGS, &ifreq); break; case SIOCSIFDSTADDR: memcpy (&ifreq.ifr_dstaddr, param, sizeof (struct sockaddr)); r = ioctl (s, cmd, &ifreq); break; case OSIOCGIFDSTADDR: case SIOCGIFDSTADDR: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; memcpy (param, &ifreq.ifr_dstaddr, sizeof (struct sockaddr)); break; case SIOCSIFBRDADDR: memcpy (&ifreq.ifr_broadaddr, param, sizeof (struct sockaddr)); r = ioctl (s, cmd, &ifreq); break; case OSIOCGIFBRDADDR: case SIOCGIFBRDADDR: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; memcpy (param, &ifreq.ifr_broadaddr, sizeof (struct sockaddr)); break; case SIOCSIFMETRIC: ifreq.ifr_metric = *((int*) param); r = ioctl (s, cmd, &ifreq); break; case SIOCGIFMETRIC: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; *((int*) param) = ifreq.ifr_metric; break; case SIOCSIFMTU: ifreq.ifr_mtu = *((int*) param); r = ioctl (s, cmd, &ifreq); break; case SIOCGIFMTU: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; *((int*) param) = ifreq.ifr_mtu; break; case SIOCSIFPHYS: ifreq.ifr_phys = *((int*) param); r = ioctl (s, cmd, &ifreq); break; case SIOCGIFPHYS: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; *((int*) param) = ifreq.ifr_phys; break; case SIOCSIFMEDIA: ifreq.ifr_media = *((int*) param); r = ioctl (s, cmd, &ifreq); break; case SIOCGIFMEDIA: if ((r = ioctl (s, cmd, &ifreq)) < 0) break; *((int*) param) = ifreq.ifr_media; break; case SIOCAIFADDR: case SIOCDIFADDR: r = ioctl(s, cmd, (struct freq *) param); break; default: errno = EOPNOTSUPP; r = -1; break; } rtems_bsdnet_semaphore_release (); close (s); return r;}/* * Parse a network driver name into a name and a unit number */intrtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep){ const char *cp = config->name; char c; int unitNumber = 0; if (cp == NULL) { printf ("No network driver name.\n"); return -1; } while ((c = *cp++) != '\0') { if ((c >= '0') && (c <= '9')) { int len = cp - config->name; if ((len < 2) || (len > 50)) break; for (;;) { unitNumber = (unitNumber * 10) + (c - '0'); c = *cp++; if (c == '\0') { char *unitName = malloc (len); if (unitName == NULL) { printf ("No memory.\n"); return -1; } strncpy (unitName, config->name, len - 1); unitName[len-1] = '\0'; *namep = unitName; return unitNumber; } if ((c < '0') || (c > '9')) break; } break; } } printf ("Bad network driver name `%s'.\n", config->name); return -1;}/* * Handle requests for more network memory * XXX: Another possibility would be to use a semaphore here with * a release in the mbuf free macro. I have chosen this `polling' * approach because: * 1) It is simpler. * 2) It adds no complexity to the free macro. * 3) Running out of mbufs should be a rare * condition -- predeployment testing of * an application should indicate the * required mbuf pool size. * XXX: Should there be a panic if a task is stuck in the loop for * more than a minute or so? */intm_mballoc (int nmb, int nowait){ if (nowait) return 0; m_reclaim (); if (mmbfree == NULL) { int try = 0; int print_limit = 30 * rtems_bsdnet_ticks_per_second; mbstat.m_wait++; for (;;) { rtems_bsdnet_semaphore_release (); rtems_task_wake_after (1); rtems_bsdnet_semaphore_obtain (); if (mmbfree) break; if (++try >= print_limit) { printf ("Still waiting for mbuf.\n"); try = 0; } } } else { mbstat.m_drops++; } return 1;}intm_clalloc(ncl, nowait){ if (nowait) return 0; m_reclaim (); if (mclfree == NULL) { int try = 0; int print_limit = 30 * rtems_bsdnet_ticks_per_second; mbstat.m_wait++; for (;;) { rtems_bsdnet_semaphore_release (); rtems_task_wake_after (1); rtems_bsdnet_semaphore_obtain (); if (mclfree) break; if (++try >= print_limit) { printf ("Still waiting for mbuf cluster.\n"); try = 0; } } } else { mbstat.m_drops++; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -