📄 net.c
字号:
/***************************************** Copyright (c) 2001-2002 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * net.c * * network layer * * first revision by Ho Lee 11/06/2002 */#include "config.h"#include "util.h"#include "uart.h"#include "specific.h"#include "timer.h"#include "bootconfig.h"#include "net.h"#include "net_ipv4.h"#if 0#define DPRINTF(x...) PrintFormat(x)#else#define DPRINTF(x...)#endif// from dm9000.cextern int dmfe_probe(struct net_device *dev);//// ethernet buffer manipulation//// allocation chunk of memory for ethernet buffer// and assign part of this memory whenever requested// implemented as circular buffer// allocated memory must be continuous (need boundary check)// allocated memory must be aligned // #define ETHER_BUF_MAX (1024 * 16) // 0x4000#define ETHER_BUF_ALIGN 8static unsigned char g_ether_buf[ETHER_BUF_MAX];static int g_ether_buf_start = 0, g_ether_buf_end = 0;static int ether_buf_empty(void);static int ether_buf_full(int len);static unsigned char *ether_buf_alloc(int len);static void ether_buf_free(unsigned char *buf, int len);static void ether_buf_dealloc(unsigned char *buf, int len);int ether_buf_empty(void){ return (g_ether_buf_start == g_ether_buf_end) ? 1 : 0;}int ether_buf_full(int len){ int start = g_ether_buf_start; int end = g_ether_buf_end; int avail; len += ETHER_BUF_ALIGN - 1; len &= ~(ETHER_BUF_ALIGN - 1); if (end + len > ETHER_BUF_MAX) { if (start == 0 || start > end) return 1; end = 0; } if (start <= end) start += ETHER_BUF_MAX; avail = start - end - 1; return (avail < len) ? 1 : 0;}unsigned char *ether_buf_alloc(int len){ int end; unsigned char *buf; if (ether_buf_full(len)) return NULL; end = g_ether_buf_end; len += ETHER_BUF_ALIGN - 1; len &= ~(ETHER_BUF_ALIGN - 1); if (end + len > ETHER_BUF_MAX) end = 0; buf = g_ether_buf + end; g_ether_buf_end = end + len; return buf;}void ether_buf_free(unsigned char *buf, int len){ len += ETHER_BUF_ALIGN - 1; len &= ~(ETHER_BUF_ALIGN - 1); g_ether_buf_start = (buf - g_ether_buf) + len; if (g_ether_buf_start >= ETHER_BUF_MAX) g_ether_buf_start = 0;}void ether_buf_dealloc(unsigned char *buf, int len){ g_ether_buf_end = (buf - g_ether_buf);}#if 0int ether_buf_test_main(void){ unsigned char *ptr; do { printf("%08x %08x : ", g_ether_buf_start, g_ether_buf_end); ptr = ether_buf_alloc(0x1c9); printf("%p\n", ptr); if (g_ether_buf_start < 0x400) ether_buf_free(ptr, 0x1c9); } while (ptr); return 0;}#endif//// socket buffer manipulation//#define SOCKET_BUF_MAX 128static struct sk_buff g_skb[SOCKET_BUF_MAX];static int g_skb_start = 0, g_skb_end = 0, g_skb_cur = 0;static int skb_empty(void);static int skb_empty_new(void);static int skb_full(void);struct sk_buff *skb_alloc(int len);void skb_free(struct sk_buff *skb);void skb_dealloc(struct sk_buff *skb);void skb_put(struct sk_buff *skb);struct sk_buff *skb_get(void);int skb_empty(void){ return (g_skb_start == g_skb_end) ? 1 : 0;}int skb_empty_new(void){ return (g_skb_cur == g_skb_end || !g_skb[g_skb_cur].valid) ? 1 : 0;}int skb_full(void){ int end = g_skb_end + 1; if (end == SOCKET_BUF_MAX) end = 0; return (g_skb_start == end) ? 1 : 0;}struct sk_buff *skb_alloc(int len){ struct sk_buff *skb; if (skb_full()) { DPRINTF("SKB Full : start = %04x, end = %04x\n", g_skb_start, g_skb_end); return NULL; } skb = g_skb + g_skb_end; if ((skb->data = ether_buf_alloc(len)) == NULL) { DPRINTF("ETH Full : start = %04x, end = %04x, len = %d\n", g_ether_buf_start, g_ether_buf_end, len); return NULL; } if (++g_skb_end == SOCKET_BUF_MAX) g_skb_end = 0; skb->len = len; skb->buflen = len; skb->valid = 0; return skb;}// assume that the skb is the first on the queuevoid skb_free(struct sk_buff *skb){ if (skb == NULL) return; ether_buf_free(skb->data, skb->buflen); if (++g_skb_start == SOCKET_BUF_MAX) g_skb_start = 0;}// assume that the skb is the last on the queuevoid skb_dealloc(struct sk_buff *skb){ if (skb == NULL || skb_empty()) return; ether_buf_dealloc(skb->data, skb->buflen); if (g_skb_end == 0) g_skb_end = SOCKET_BUF_MAX - 1; else --g_skb_end;}void skb_put(struct sk_buff *skb){ if (skb == NULL) return; if (ipv4_check_for_me(skb)) skb->valid = 1; else skb_dealloc(skb);}struct sk_buff *skb_get(void){ struct sk_buff *skb; if (skb_empty_new()) return NULL; skb = g_skb + g_skb_cur; if(++g_skb_cur == SOCKET_BUF_MAX) g_skb_cur = 0; if (!skb->valid) return NULL; return skb;}//// network device manipulation// struct net_device g_netdev;int net_init(void){ memset(&g_netdev, 0, sizeof g_netdev); ipv4_init(); if (dmfe_probe(&g_netdev)) return 0; return 1;}int net_found(void){ return (g_netdev.state);}int net_arp_setup(void){ ipv4_setup_arptable(g_bootconfig.ipaddr, g_bootconfig.netmask, g_bootconfig.macaddr, g_bootconfig.gateway, g_bootconfig.dns); return 0;}int net_dev_up(void){ if (g_netdev.state) { // setup network before enable device memcpy(g_netdev.dev_addr, g_bootconfig.macaddr, MACADDR_LEN); g_netdev.open(&g_netdev); DELAY(200000); // wait until network device is stable switch (g_bootconfig.protocol) { case BOOTNET_STATIC : if (!ipv4_ipaddr_valid(g_bootconfig.ipaddr)) { PrintUart("Invalid static IP address.\r\n", -1); } else { net_arp_setup(); } break; case BOOTNET_BOOTP : case BOOTNET_DHCP : arp_setaddr_index(ARP_CLIENT, INADDR_ANY, INADDR_ANY, g_bootconfig.macaddr); return ipv4_bootp(g_bootconfig.protocol == BOOTNET_BOOTP ? 1 : 0); } // setup after enable device return 0; } else return 1;}int net_dev_down(void){ if (g_netdev.state) { g_netdev.close(&g_netdev); return 0; } else return 1;}//// Network packet manipulation//int net_rx_ready(void){ if (g_netdev.state) { if (g_netdev.irq_pending(&g_netdev) & ETHIRQ_RX) { g_netdev.receive_packet(&g_netdev); return 1; } } return 0;}// timeout : // 0 : no wait// > 0 : wait until timeout// < 0 : wait until get any packetstruct sk_buff *net_getpacket(int timeout){ unsigned int startticks = timer_getticks(); if (!g_netdev.state) return NULL; // if there is a packet already in the buffer, return it if (!skb_empty_new()) return skb_get(); // if there is no packet in the buffer, check the device if any packet is ready do { //if ((g_netdev.irq_pending(&g_netdev) & ETHIRQ_RX) != 0) g_netdev.receive_packet(&g_netdev); if (!skb_empty_new()) return skb_get(); } while (!timer_timeout(startticks, timeout)); return NULL;}int net_sendpacket(struct sk_buff *skb){ if (!g_netdev.state || !skb->valid) return 1; g_netdev.send_packet(skb, &g_netdev); return 0;}void net_device_status(void){ if (g_netdev.print_status) g_netdev.print_status(&g_netdev);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -