From 514387711f2d7c5e3476ca80354d989797d088f4 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 9 Jun 2010 10:05:04 +0300 Subject: i2c: add driver for the MC34704 PMIC Signed-off-by: Baruch Siach Signed-off-by: Sascha Hauer --- include/i2c/mc34704.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 include/i2c/mc34704.h (limited to 'include') diff --git a/include/i2c/mc34704.h b/include/i2c/mc34704.h new file mode 100644 index 0000000000..a3723d72a9 --- /dev/null +++ b/include/i2c/mc34704.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 Marc Kleine-Budde + * Copyright (C) 2010 Baruch Siach + * + * This file is released under the GPLv2 + * + * Derived from: + * - arch-mxc/pmic_external.h -- contains interface of the PMIC protocol driver + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * + */ + +#ifndef __I2C_MC34704_H +#define __I2C_MC34704_H + +struct mc34704 { + struct cdev cdev; + struct i2c_client *client; +}; + +extern struct mc34704 *mc34704_get(void); + +extern int mc34704_reg_read(struct mc34704 *mc34704, u8 reg, u8 *val); +extern int mc34704_reg_write(struct mc34704 *mc34704, u8 reg, u8 val); + +#endif /* __I2C_MC34704_H */ -- cgit v1.2.3 From 994f95c073caf4df62d1271aef4112ce8aaa8add Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 27 May 2010 11:37:46 +0200 Subject: net: remove need for eth_halt/eth_open We used to eth_open/eth_halt the network devices during NetLoopInit which is called whenever the user enters a network command. Change this behaviour so that the current network device gets opened when making it the current one. With this change it's always possible to send packages and we are able to implement a new network stack in the next step. Signed-off-by: Sascha Hauer --- commands/net.c | 20 ++++++++++++-------- include/net.h | 1 + net/eth.c | 56 ++++++++++++++++++++++++++++++++++++-------------------- net/net.c | 21 +++++++++++++-------- net/ping.c | 1 - 5 files changed, 62 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/commands/net.c b/commands/net.c index 815a566a2b..949963ffdc 100644 --- a/commands/net.c +++ b/commands/net.c @@ -39,12 +39,16 @@ void netboot_update_env(void) { struct eth_device *eth_current = eth_get_current(); char tmp[22]; + IPaddr_t net_gateway_ip = NetOurGatewayIP; + IPaddr_t net_ip = NetOurIP; + IPaddr_t net_server_ip = NetServerIP; + IPaddr_t netmask = NetOurSubnetMask; - if (NetOurGatewayIP) - dev_set_param_ip(ð_current->dev, "gateway", NetOurGatewayIP); + if (net_gateway_ip) + dev_set_param_ip(ð_current->dev, "gateway", net_gateway_ip); - if (NetOurSubnetMask) - dev_set_param_ip(ð_current->dev, "netmask", NetOurSubnetMask); + if (netmask) + dev_set_param_ip(ð_current->dev, "netmask", netmask); if (NetOurHostName[0]) @@ -53,11 +57,11 @@ void netboot_update_env(void) if (NetOurRootPath[0]) setenv ("rootpath", NetOurRootPath); - if (NetOurIP) - dev_set_param_ip(ð_current->dev, "ipaddr", NetOurIP); + if (net_ip) + dev_set_param_ip(ð_current->dev, "ipaddr", net_ip); - if (NetServerIP) - dev_set_param_ip(ð_current->dev, "serverip", NetServerIP); + if (net_server_ip) + dev_set_param_ip(ð_current->dev, "serverip", net_server_ip); if (NetOurDNSIP) { ip_to_string (NetOurDNSIP, tmp); diff --git a/include/net.h b/include/net.h index 7353c8f501..de78293840 100644 --- a/include/net.h +++ b/include/net.h @@ -57,6 +57,7 @@ struct device_d; struct eth_device { int iobase; int state; + int active; int (*init) (struct eth_device*); diff --git a/net/eth.c b/net/eth.c index 7570198a17..fc16233be3 100644 --- a/net/eth.c +++ b/net/eth.c @@ -36,7 +36,13 @@ static LIST_HEAD(netdev_list); void eth_set_current(struct eth_device *eth) { + if (eth_current && eth_current->active) { + eth_current->halt(eth_current); + eth_current->active = 0; + } + eth_current = eth; + net_update_env(); } struct eth_device * eth_get_current(void) @@ -57,37 +63,37 @@ struct eth_device *eth_get_byname(char *ethname) return NULL; } -int eth_open(void) -{ - if (!eth_current) - return -ENODEV; - - return eth_current->open(eth_current); -} - -void eth_halt(void) -{ - if (!eth_current) - return; - - eth_current->halt(eth_current); - - eth_current->state = ETH_STATE_PASSIVE; -} - int eth_send(void *packet, int length) { + int ret; + if (!eth_current) return -ENODEV; + if (!eth_current->active) { + ret = eth_current->open(eth_current); + if (ret) + return ret; + eth_current->active = 1; + } + return eth_current->send(eth_current, packet, length); } int eth_rx(void) { + int ret; + if (!eth_current) return -ENODEV; + if (!eth_current->active) { + ret = eth_current->open(eth_current); + if (ret) + return ret; + eth_current->active = 1; + } + return eth_current->recv(eth_current); } @@ -104,11 +110,15 @@ static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const ch edev->set_ethaddr(edev, ethaddr); + if (edev == eth_current) + net_update_env(); + return 0; } static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const char *val) { + struct eth_device *edev = dev->type_data; IPaddr_t ip; if (string_to_ip(val, &ip)) @@ -117,6 +127,9 @@ static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const cha free(param->value); param->value = strdup(val); + if (edev == eth_current) + net_update_env(); + return 0; } @@ -157,7 +170,7 @@ int eth_register(struct eth_device *edev) if (edev->get_ethaddr(edev, ethaddr) == 0) { ethaddr_to_string(ethaddr, ethaddr_str); - printf("got MAC address from EEPROM: %s\n",ethaddr_str); + printf("got MAC address from EEPROM: %s\n",ðaddr_str); dev_set_param(dev, "ethaddr", ethaddr_str); } @@ -180,9 +193,12 @@ void eth_unregister(struct eth_device *edev) if (edev->param_serverip.value) free(edev->param_serverip.value); - if (eth_current == edev) + if (eth_current == edev) { + eth_current->halt(eth_current); eth_current = NULL; + } list_del(&edev->list); } + diff --git a/net/net.c b/net/net.c index 4554d49e36..28943a039e 100644 --- a/net/net.c +++ b/net/net.c @@ -228,9 +228,6 @@ int NetLoopInit(proto_t protocol) NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; NetArpWaitTxPacketSize = 0; - if (eth_open() < 0) - return -1; - string_to_ethaddr(dev_get_param(ð_get_current()->dev, "ethaddr"), NetOurEther); @@ -243,8 +240,6 @@ int NetLoopInit(proto_t protocol) NetServerIP = dev_get_param_ip(ð_current->dev, "serverip"); ret = net_check_prereq(protocol); - if (ret) - eth_halt(); return ret; } @@ -281,7 +276,6 @@ int NetLoop(void) * Abort if ctrl-c was pressed. */ if (ctrlc()) { - eth_halt(); puts ("\nAbort\n"); return -1; } @@ -315,11 +309,9 @@ int NetLoop(void) sprintf(buf, "0x%lx", NetBootFileXferSize); setenv("filesize", buf); } - eth_halt(); return NetBootFileXferSize; case NETLOOP_FAIL: - eth_halt(); return -1; } } @@ -959,3 +951,16 @@ void ethaddr_to_string(const unsigned char *enetaddr, char *str) enetaddr[4], enetaddr[5]); } +void net_update_env(void) +{ + struct eth_device *edev = eth_get_current(); + + NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr"); + NetServerIP = dev_get_param_ip(&edev->dev, "serverip"); + NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway"); + NetOurSubnetMask = dev_get_param_ip(&edev->dev, "netmask"); + + string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"), + NetOurEther); +} + diff --git a/net/ping.c b/net/ping.c index 1bc481af44..7e21fe4ccf 100644 --- a/net/ping.c +++ b/net/ping.c @@ -62,7 +62,6 @@ static int PingSend(void) static void PingTimeout (void) { - eth_halt(); NetState = NETLOOP_FAIL; /* we did not get the reply */ } -- cgit v1.2.3 From 97070487fa67d0a8b04c4e109966bb4c1b40212e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 2 Jun 2010 15:22:26 +0200 Subject: net: Implement a new network stack The old network stack has some bad limitations: - network commands are required to call NetLoop() which only returns when the network layer wants to. Instead we now use a net_poll() function which returns after handling one packet (or immediately if no packet is available). - There can be only one packet handler which makes it impossible to handle multiple connections - CamelCaseMakesItHardToRead The new network stack is implemented as a parallel universe. Currently all commands still use the old stack. They are converted in subsequent patches. Signed-off-by: Sascha Hauer --- include/net.h | 341 +++++++++++++++++++++++++++++++++++- net/net.c | 540 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 874 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/net.h b/include/net.h index de78293840..0ee7ecb8a6 100644 --- a/include/net.h +++ b/include/net.h @@ -15,6 +15,7 @@ #include #include #include +#include #include /* for nton* / ntoh* stuff */ @@ -186,8 +187,6 @@ typedef struct uchar ar_data[0]; } ARP_t; -#define ARP_HDR_SIZE (8+20) /* Size assuming ethernet */ - /* * ICMP stuff (just enough to handle (host) redirect messages) */ @@ -199,7 +198,7 @@ typedef struct #define ICMP_REDIR_NET 0 /* Redirect Net */ #define ICMP_REDIR_HOST 1 /* Redirect Host */ -typedef struct icmphdr { +typedef struct { uchar type; uchar code; ushort checksum; @@ -415,4 +414,340 @@ void eth_set_current(struct eth_device *eth); struct eth_device *eth_get_current(void); struct eth_device *eth_get_byname(char *name); +/* + * Ethernet header + */ +struct ethernet { + uint8_t et_dest[6]; /* Destination node */ + uint8_t et_src[6]; /* Source node */ + uint16_t et_protlen; /* Protocol or length */ +} __attribute__ ((packed)); + +#define ETHER_HDR_SIZE 14 /* Ethernet header size */ + +#define PROT_IP 0x0800 /* IP protocol */ +#define PROT_ARP 0x0806 /* IP ARP protocol */ +#define PROT_RARP 0x8035 /* IP ARP protocol */ +#define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */ + +#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ +#define IPPROTO_UDP 17 /* User Datagram Protocol */ + +/* + * Internet Protocol (IP) header. + */ +struct iphdr { + uint8_t hl_v; + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_t daddr; + /* The options start here. */ +} __attribute__ ((packed)); + +struct udphdr { + uint16_t uh_sport; /* source port */ + uint16_t uh_dport; /* destination port */ + uint16_t uh_ulen; /* udp length */ + uint16_t uh_sum; /* udp checksum */ +} __attribute__ ((packed)); + +/* + * Address Resolution Protocol (ARP) header. + */ +struct arprequest +{ + uint16_t ar_hrd; /* Format of hardware address */ +#define ARP_ETHER 1 /* Ethernet hardware address */ + uint16_t ar_pro; /* Format of protocol address */ + uint8_t ar_hln; /* Length of hardware address */ + uint8_t ar_pln; /* Length of protocol address */ + uint16_t ar_op; /* Operation */ +#define ARPOP_REQUEST 1 /* Request to resolve address */ +#define ARPOP_REPLY 2 /* Response to previous request */ + +#define RARPOP_REQUEST 3 /* Request to resolve address */ +#define RARPOP_REPLY 4 /* Response to previous request */ + + /* + * The remaining fields are variable in size, according to + * the sizes above, and are defined as appropriate for + * specific hardware/protocol combinations. + */ + uint8_t ar_data[0]; +} __attribute__ ((packed)); + +#define ARP_HDR_SIZE (8 + 20) /* Size assuming ethernet */ + +/* + * ICMP stuff (just enough to handle (host) redirect messages) + */ +#define ICMP_ECHO_REPLY 0 /* Echo reply */ +#define ICMP_REDIRECT 5 /* Redirect (change route) */ +#define ICMP_ECHO_REQUEST 8 /* Echo request */ + +/* Codes for REDIRECT. */ +#define ICMP_REDIR_NET 0 /* Redirect Net */ +#define ICMP_REDIR_HOST 1 /* Redirect Host */ + +struct icmphdr { + uint8_t type; + uint8_t code; + uint16_t checksum; + union { + struct { + uint16_t id; + uint16_t sequence; + } echo; + uint32_t gateway; + struct { + uint16_t __unused; + uint16_t mtu; + } frag; + } un; +} __attribute__ ((packed)); + + +/* + * Maximum packet size; used to allocate packet storage. + * TFTP packets can be 524 bytes + IP header + ethernet header. + * Lets be conservative, and go for 38 * 16. (Must also be + * a multiple of 32 bytes). + */ +#define PKTSIZE 1518 + +/**********************************************************************/ +/* + * Globals. + * + * Note: + * + * All variables of type IPaddr_t are stored in NETWORK byte order + * (big endian). + */ + +extern unsigned char *NetRxPackets[PKTBUFSRX];/* Receive packets */ + +void net_set_ip(IPaddr_t ip); +void net_set_serverip(IPaddr_t ip); +void net_set_netmask(IPaddr_t ip); +void net_set_gateway(IPaddr_t ip); +IPaddr_t net_get_ip(void); +IPaddr_t net_get_serverip(void); + +/* Do the work */ +void net_poll(void); + +static inline struct iphdr *net_eth_to_iphdr(char *pkt) +{ + return (struct iphdr *)(pkt + ETHER_HDR_SIZE); +} + +static inline struct udphdr *net_eth_to_udphdr(char *pkt) +{ + return (struct udphdr *)(net_eth_to_iphdr(pkt) + 1); +} + +static inline struct icmphdr *net_eth_to_icmphdr(char *pkt) +{ + return (struct icmphdr *)(net_eth_to_iphdr(pkt) + 1); +} + +static inline char *net_eth_to_icmp_payload(char *pkt) +{ + return (char *)(net_eth_to_icmphdr(pkt) + 1); +} + +static inline char *net_eth_to_udp_payload(char *pkt) +{ + return (char *)(net_eth_to_udphdr(pkt) + 1); +} + +static inline int net_eth_to_udplen(char *pkt) +{ + struct udphdr *udp = net_eth_to_udphdr(pkt); + return ntohs(udp->uh_ulen) - 8; +} + +int net_checksum_ok(unsigned char *, int); /* Return true if cksum OK */ +uint16_t net_checksum(unsigned char *, int); /* Calculate the checksum */ + +void NetReceive(unsigned char *, int); + +/* Print an IP address on the console */ +void print_IPaddr (IPaddr_t); + +/* + * The following functions are a bit ugly, but necessary to deal with + * alignment restrictions on ARM. + * + * We're using inline functions, which had the smallest memory + * footprint in our tests. + */ +/* return IP *in network byteorder* */ +static inline IPaddr_t net_read_ip(void *from) +{ + IPaddr_t ip; + memcpy((void*)&ip, from, sizeof(ip)); + return ip; +} + +/* return uint32 *in network byteorder* */ +static inline uint32_t net_read_uint32(uint32_t *from) +{ + ulong l; + memcpy((void*)&l, (void*)from, sizeof(l)); + return l; +} + +/* write IP *in network byteorder* */ +static inline void net_write_ip(void *to, IPaddr_t ip) +{ + memcpy(to, (void*)&ip, sizeof(ip)); +} + +/* copy IP */ +static inline void net_copy_ip(void *to, void *from) +{ + memcpy(to, from, sizeof(IPaddr_t)); +} + +/* copy ulong */ +static inline void net_copy_uint32(uint32_t *to, uint32_t *from) +{ + memcpy(to, from, sizeof(uint32_t)); +} + +/* Convert an IP address to a string */ +char *ip_to_string (IPaddr_t x, char *s); + +/* Convert a string to ip address */ +int string_to_ip(const char *s, IPaddr_t *ip); + +IPaddr_t getenv_ip(const char *name); +int setenv_ip(const char *name, IPaddr_t ip); + +int string_to_ethaddr(const char *str, char *enetaddr); +void ethaddr_to_string(const unsigned char *enetaddr, char *str); + +/** + * is_zero_ether_addr - Determine if give Ethernet address is all zeros. + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is all zeroes. + */ +static inline int is_zero_ether_addr(const u8 *addr) +{ + return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); +} + +/** + * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is a multicast address. + * By definition the broadcast address is also a multicast address. + */ +static inline int is_multicast_ether_addr(const u8 *addr) +{ + return (0x01 & addr[0]); +} + +/** + * is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802). + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is a local address. + */ +static inline int is_local_ether_addr(const u8 *addr) +{ + return (0x02 & addr[0]); +} + +/** + * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is the broadcast address. + */ +static inline int is_broadcast_ether_addr(const u8 *addr) +{ + return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; +} + +/** + * is_valid_ether_addr - Determine if the given Ethernet address is valid + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not + * a multicast address, and is not FF:FF:FF:FF:FF:FF. + * + * Return true if the address is valid. + */ +static inline int is_valid_ether_addr(const u8 *addr) +{ + /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to + * explicitly check for it here. */ + return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); +} + +typedef void rx_handler_f(char *packet, unsigned int len); + +void eth_set_current(struct eth_device *eth); +struct eth_device *eth_get_current(void); +struct eth_device *eth_get_byname(char *name); +void net_update_env(void); + +/** + * net_receive - Pass a received packet from an ethernet driver to the protocol stack + * @pkt: Pointer to the packet + * @len: length of the packet + * + * Return 0 if the packet is successfully handled. Can be ignored + */ +int net_receive(unsigned char *pkt, int len); + +struct net_connection { + struct ethernet *et; + struct iphdr *ip; + struct udphdr *udp; + struct icmphdr *icmp; + unsigned char *packet; + struct list_head list; + rx_handler_f *handler; + int proto; +}; + +static inline char *net_alloc_packet(void) +{ + return memalign(32, PKTSIZE); +} + +struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport, + rx_handler_f *handler); + +struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler); + +void net_unregister(struct net_connection *con); + +static inline int net_udp_bind(struct net_connection *con, int sport) +{ + con->udp->uh_sport = ntohs(sport); + return 0; +} + +static inline unsigned char *net_udp_get_payload(struct net_connection *con) +{ + return con->packet + sizeof(struct ethernet) + sizeof(struct iphdr) + + sizeof(struct udphdr); +} + +int net_udp_send(struct net_connection *con, int len); +int net_icmp_send(struct net_connection *con, int len); + #endif /* __NET_H__ */ diff --git a/net/net.c b/net/net.c index 28943a039e..2b1641e8e9 100644 --- a/net/net.c +++ b/net/net.c @@ -77,7 +77,9 @@ #include #include #include +#include #include +#include #include "tftp.h" #include "rarp.h" #include "nfs.h" @@ -89,7 +91,6 @@ # define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) #endif - /** BOOTP EXTENTIONS **/ IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */ @@ -407,6 +408,9 @@ NetReceive(uchar * inpkt, int len) pr_debug("packet received\n"); + if (!net_receive(inpkt, len)) + return; + NetRxPkt = inpkt; NetRxPktLen = len; et = (Ethernet_t *)inpkt; @@ -582,7 +586,8 @@ NetReceive(uchar * inpkt, int len) NetCopyIP(&NetServerIP, &arp->ar_data[ 6]); memcpy (NetServerEther, &arp->ar_data[ 0], 6); - (*packetHandler)(0,0,0,0); + if (packetHandler) + (*packetHandler)(0,0,0,0); } break; @@ -649,7 +654,8 @@ NetReceive(uchar * inpkt, int len) * IP header OK. Pass the packet to the current handler. */ /* XXX point to ip packet */ - (*packetHandler)((uchar *)ip, 0, 0, 0); + if (packetHandler) + (*packetHandler)((uchar *)ip, 0, 0, 0); return; #endif default: @@ -701,7 +707,8 @@ NetReceive(uchar * inpkt, int len) /* * IP header OK. Pass the packet to the current handler. */ - (*packetHandler)((uchar *)ip +IP_HDR_SIZE, + if (packetHandler) + (*packetHandler)((uchar *)ip +IP_HDR_SIZE, ntohs(ip->udp_dst), ntohs(ip->udp_src), ntohs(ip->udp_len) - 8); @@ -882,6 +889,30 @@ int string_to_ip(const char *s, IPaddr_t *ip) return 0; } +IPaddr_t getenv_ip(const char *name) +{ + IPaddr_t ip; + const char *var = getenv(name); + + if (!var) + return 0; + + string_to_ip(var, &ip); + + return ip; +} + +int setenv_ip(const char *name, IPaddr_t ip) +{ + char str[sizeof("xxx.xxx.xxx.xxx")]; + + ip_to_string(ip, str); + + setenv(name, str); + + return 0; +} + void VLAN_to_string(ushort x, char *s) { x = ntohs(x); @@ -951,10 +982,28 @@ void ethaddr_to_string(const unsigned char *enetaddr, char *str) enetaddr[4], enetaddr[5]); } +static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */ +static IPaddr_t net_gateway; /* Our gateways IP address */ + +static unsigned char net_ether[6]; /* Our ethernet address */ +static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */ +static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */ + +unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */ +static unsigned int net_ip_id; + void net_update_env(void) { struct eth_device *edev = eth_get_current(); + net_ip = dev_get_param_ip(&edev->dev, "ipaddr"); + net_serverip = dev_get_param_ip(&edev->dev, "serverip"); + net_gateway = dev_get_param_ip(&edev->dev, "gateway"); + net_netmask = dev_get_param_ip(&edev->dev, "netmask"); + + string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"), + net_ether); + NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr"); NetServerIP = dev_get_param_ip(&edev->dev, "serverip"); NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway"); @@ -964,3 +1013,486 @@ void net_update_env(void) NetOurEther); } +int net_checksum_ok(unsigned char *ptr, int len) +{ + return net_checksum(ptr, len) + 1; +} + +uint16_t net_checksum(unsigned char *ptr, int len) +{ + uint32_t xsum = 0; + uint16_t *p = (uint16_t *)ptr; + + if (len & 1) + ptr[len] = 0; + + len = (len + 1) >> 1; + + while (len-- > 0) + xsum += *p++; + + xsum = (xsum & 0xffff) + (xsum >> 16); + xsum = (xsum & 0xffff) + (xsum >> 16); + return xsum & 0xffff; +} + +static unsigned char *arp_ether; +static IPaddr_t arp_wait_ip; + +static void arp_handler(struct arprequest *arp) +{ + IPaddr_t tmp; + + /* are we waiting for a reply */ + if (!arp_wait_ip) + return; + + tmp = net_read_ip(&arp->ar_data[6]); + + /* matched waiting packet's address */ + if (tmp == arp_wait_ip) { + /* save address for later use */ + memcpy(arp_ether, &arp->ar_data[0], 6); + + /* no arp request pending now */ + arp_wait_ip = 0; + } +} + +int arp_request(IPaddr_t dest, unsigned char *ether) +{ + char *pkt; + struct arprequest *arp; + uint64_t arp_start; + static char *arp_packet; + struct ethernet *et; + + if (!arp_packet) { + arp_packet = net_alloc_packet(); + if (!arp_packet) + return -ENOMEM; + } + + pkt = arp_packet; + et = (struct ethernet *)arp_packet; + + arp_wait_ip = dest; + + pr_debug("ARP broadcast\n"); + + memset(et->et_dest, 0xff, 6); + memcpy(et->et_src, net_ether, 6); + et->et_protlen = htons(PROT_ARP); + + arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE); + + arp->ar_hrd = htons(ARP_ETHER); + arp->ar_pro = htons(PROT_IP); + arp->ar_hln = 6; + arp->ar_pln = 4; + arp->ar_op = htons(ARPOP_REQUEST); + + memcpy(arp->ar_data, net_ether, 6); /* source ET addr */ + net_write_ip(arp->ar_data + 6, net_ip); /* source IP addr */ + memset(arp->ar_data + 10, 0, 6); /* dest ET addr = 0 */ + + if ((dest & net_netmask) != (net_ip & net_netmask)) { + if (!net_gateway) + arp_wait_ip = dest; + else + arp_wait_ip = net_gateway; + } else { + arp_wait_ip = dest; + } + + net_write_ip(arp->ar_data + 16, arp_wait_ip); + + arp_ether = ether; + + eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); + arp_start = get_time_ns(); + + while (arp_wait_ip) { + if (ctrlc()) + return -EINTR; + + if (is_timeout(arp_start, 3 * SECOND)) { + printf("T "); + arp_start = get_time_ns(); + eth_send(arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); + } + + net_poll(); + } + + pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", + ether[0], ether[1], + ether[2], ether[3], + ether[4], ether[5]); + return 0; +} + +void net_poll(void) +{ + eth_rx(); +} + +static uint16_t net_udp_new_localport(void) +{ + static uint16_t localport; + + localport++; + + if (localport < 1024) + localport = 1024; + + return localport; +} + +IPaddr_t net_get_serverip(void) +{ + return net_serverip; +} + +void net_set_serverip(IPaddr_t ip) +{ + struct eth_device *edev = eth_get_current(); + + net_serverip = ip; + dev_set_param_ip(&edev->dev, "serverip", net_serverip); +} + +void net_set_ip(IPaddr_t ip) +{ + struct eth_device *edev = eth_get_current(); + + net_ip = ip; + dev_set_param_ip(&edev->dev, "ipaddr", net_ip); +} + +IPaddr_t net_get_ip(void) +{ + return net_ip; +} + +void net_set_netmask(IPaddr_t nm) +{ + struct eth_device *edev = eth_get_current(); + + net_netmask = nm; + dev_set_param_ip(&edev->dev, "netmask", net_netmask); +} + +void net_set_gateway(IPaddr_t gw) +{ + struct eth_device *edev = eth_get_current(); + + net_gateway = gw; + dev_set_param_ip(&edev->dev, "gateway", net_gateway); +} + +static LIST_HEAD(connection_list); + +static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler) +{ + struct net_connection *con; + int ret; + + if (!is_valid_ether_addr(net_ether)) + return ERR_PTR(-ENETDOWN); + + /* If we don't have an ip only broadcast is allowed */ + if (!net_ip && dest != 0xffffffff) + return ERR_PTR(-ENETDOWN); + + con = xzalloc(sizeof(*con)); + con->packet = memalign(32, PKTSIZE); + memset(con->packet, 0, PKTSIZE); + + con->et = (struct ethernet *)con->packet; + con->ip = (struct iphdr *)(con->packet + ETHER_HDR_SIZE); + con->udp = (struct udphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr)); + con->icmp = (struct icmphdr *)(con->packet + ETHER_HDR_SIZE + sizeof(struct iphdr)); + con->handler = handler; + + if (dest == 0xffffffff) { + memset(con->et->et_dest, 0xff, 6); + } else { + ret = arp_request(dest, con->et->et_dest); + if (ret) + goto out; + } + + con->et->et_protlen = htons(PROT_IP); + memcpy(con->et->et_src, net_ether, 6); + + con->ip->hl_v = 0x45; + con->ip->tos = 0; + con->ip->frag_off = htons(0x4000); /* No fragmentation */; + con->ip->ttl = 255; + net_copy_ip(&con->ip->daddr, &dest); + net_copy_ip(&con->ip->saddr, &net_ip); + + list_add_tail(&con->list, &connection_list); + + return con; +out: + free(con->packet); + free(con); + return ERR_PTR(ret); +} + +struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport, + rx_handler_f *handler) +{ + struct net_connection *con = net_new(dest, handler); + + if (IS_ERR(con)) + return con; + + con->proto = IPPROTO_UDP; + con->udp->uh_dport = htons(dport); + con->udp->uh_sport = htons(net_udp_new_localport()); + con->ip->protocol = IPPROTO_UDP; + + return con; +} + +struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler) +{ + struct net_connection *con = net_new(dest, handler); + + if (IS_ERR(con)) + return con; + + con->proto = IPPROTO_ICMP; + con->ip->protocol = IPPROTO_ICMP; + + return con; +} + +void net_unregister(struct net_connection *con) +{ + list_del(&con->list); + free(con->packet); + free(con); +} + +int net_ip_send(struct net_connection *con, int len) +{ + con->ip->tot_len = htons(sizeof(struct iphdr) + len); + con->ip->id = htons(net_ip_id++);; + con->ip->check = 0; + con->ip->check = ~net_checksum((unsigned char *)con->ip, sizeof(struct iphdr)); + + eth_send(con->packet, ETHER_HDR_SIZE + sizeof(struct iphdr) + len); + + return 0; +} + +int net_udp_send(struct net_connection *con, int len) +{ + con->udp->uh_ulen = htons(len + 8); + con->udp->uh_sum = 0; + + return net_ip_send(con, sizeof(struct udphdr) + len); +} + +int net_icmp_send(struct net_connection *con, int len) +{ + con->icmp->checksum = ~net_checksum((unsigned char *)con->icmp, + sizeof(struct icmphdr) + len); + + return net_ip_send(con, sizeof(struct icmphdr) + len); +} + +static int net_answer_arp(unsigned char *pkt, int len) +{ + struct arprequest *arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE); + struct ethernet *et = (struct ethernet *)pkt; + unsigned char *packet; + + debug("%s\n", __func__); + + memcpy (et->et_dest, et->et_src, 6); + memcpy (et->et_src, net_ether, 6); + + et->et_protlen = htons(PROT_ARP); + arp->ar_op = htons(ARPOP_REPLY); + memcpy(&arp->ar_data[10], &arp->ar_data[0], 6); + net_copy_ip(&arp->ar_data[16], &arp->ar_data[6]); + memcpy(&arp->ar_data[0], net_ether, 6); + net_copy_ip(&arp->ar_data[6], &net_ip); + + packet = net_alloc_packet(); + if (!packet) + return 0; + memcpy(packet, pkt, ETHER_HDR_SIZE + ARP_HDR_SIZE); + eth_send(packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); + free(packet); + + return 0; +} + +static void net_bad_packet(unsigned char *pkt, int len) +{ +#ifdef DEBUG + /* + * We received a bad packet. for now just dump it. + * We could add more sophisticated debugging here + */ + memory_display(pkt, 0, len, 1); +#endif +} + +static int net_handle_arp(unsigned char *pkt, int len) +{ + struct arprequest *arp; + + debug("%s: got arp\n", __func__); + + /* + * We have to deal with two types of ARP packets: + * - REQUEST packets will be answered by sending our + * IP address - if we know it. + * - REPLY packets are expected only after we asked + * for the TFTP server's or the gateway's ethernet + * address; so if we receive such a packet, we set + * the server ethernet address + */ + arp = (struct arprequest *)(pkt + ETHER_HDR_SIZE); + if (len < ARP_HDR_SIZE) + goto bad; + if (ntohs(arp->ar_hrd) != ARP_ETHER) + goto bad; + if (ntohs(arp->ar_pro) != PROT_IP) + goto bad; + if (arp->ar_hln != 6) + goto bad; + if (arp->ar_pln != 4) + goto bad; + if (net_ip == 0) + return 0; + if (net_read_ip(&arp->ar_data[16]) != net_ip) + return 0; + + switch (ntohs(arp->ar_op)) { + case ARPOP_REQUEST: + return net_answer_arp(pkt, len); + case ARPOP_REPLY: + arp_handler(arp); + return 1; + default: + pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op)); + return -EINVAL; + } + + return 0; + +bad: + net_bad_packet(pkt, len); + return -EINVAL; +} + +static int net_handle_udp(unsigned char *pkt, int len) +{ + struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE); + struct net_connection *con; + struct udphdr *udp; + int port; + + udp = (struct udphdr *)(ip + 1); + port = ntohs(udp->uh_dport); + list_for_each_entry(con, &connection_list, list) { + if (con->proto == IPPROTO_UDP && port == ntohs(con->udp->uh_sport)) { + con->handler(pkt, len); + return 0; + } + } + return -EINVAL; +} + +static int net_handle_icmp(unsigned char *pkt, int len) +{ + struct net_connection *con; + + debug("%s\n", __func__); + + list_for_each_entry(con, &connection_list, list) { + if (con->proto == IPPROTO_ICMP) { + con->handler(pkt, len); + return 0; + } + } + return 0; +} + +static int net_handle_ip(unsigned char *pkt, int len) +{ + struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE); + IPaddr_t tmp; + + debug("%s\n", __func__); + + if (len < sizeof(struct ethernet) + sizeof(struct iphdr) || + len < ETHER_HDR_SIZE + ntohs(ip->tot_len)) { + debug("%s: bad len\n", __func__); + goto bad; + } + + if ((ip->hl_v & 0xf0) != 0x40) + goto bad; + + if (ip->frag_off & htons(0x1fff)) /* Can't deal w/ fragments */ + goto bad; + if (!net_checksum_ok((unsigned char *)ip, sizeof(struct iphdr))) + goto bad; + + tmp = net_read_ip(&ip->daddr); + if (net_ip && tmp != net_ip && tmp != 0xffffffff) + return 0; + + switch (ip->protocol) { + case IPPROTO_ICMP: + return net_handle_icmp(pkt, len); + case IPPROTO_UDP: + return net_handle_udp(pkt, len); + } + + return 0; +bad: + net_bad_packet(pkt, len); + return 0; +} + +int net_receive(unsigned char *pkt, int len) +{ + struct ethernet *et = (struct ethernet *)pkt; + int et_protlen = ntohs(et->et_protlen); + + if (len < ETHER_HDR_SIZE) + return 0; + + switch (et_protlen) { + case PROT_ARP: + return net_handle_arp(pkt, len); + case PROT_IP: + return net_handle_ip(pkt, len); + default: + debug("%s: got unknown protocol type: %d\n", __func__, et_protlen); + return 1; + } +} + +static int net_init(void) +{ + int i; + + for (i = 0; i < PKTBUFSRX; i++) + NetRxPackets[i] = memalign(32, PKTSIZE); + + return 0; +} + +postcore_initcall(net_init); + -- cgit v1.2.3 From 57e1fc33bda4f4f215bdaa7ebb2a79cc5aac3799 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 2 Jun 2010 16:04:52 +0200 Subject: net: remove old network stack All network commands now use the new stack, so remove the old one. Signed-off-by: Sascha Hauer --- commands/net.c | 42 --- include/net.h | 359 +--------------------- net/net.c | 944 +++------------------------------------------------------ 3 files changed, 49 insertions(+), 1296 deletions(-) (limited to 'include') diff --git a/commands/net.c b/commands/net.c index 949963ffdc..938463c7c4 100644 --- a/commands/net.c +++ b/commands/net.c @@ -35,48 +35,6 @@ #include #include -void netboot_update_env(void) -{ - struct eth_device *eth_current = eth_get_current(); - char tmp[22]; - IPaddr_t net_gateway_ip = NetOurGatewayIP; - IPaddr_t net_ip = NetOurIP; - IPaddr_t net_server_ip = NetServerIP; - IPaddr_t netmask = NetOurSubnetMask; - - if (net_gateway_ip) - dev_set_param_ip(ð_current->dev, "gateway", net_gateway_ip); - - if (netmask) - dev_set_param_ip(ð_current->dev, "netmask", netmask); - - - if (NetOurHostName[0]) - setenv ("hostname", NetOurHostName); - - if (NetOurRootPath[0]) - setenv ("rootpath", NetOurRootPath); - - if (net_ip) - dev_set_param_ip(ð_current->dev, "ipaddr", net_ip); - - if (net_server_ip) - dev_set_param_ip(ð_current->dev, "serverip", net_server_ip); - - if (NetOurDNSIP) { - ip_to_string (NetOurDNSIP, tmp); - setenv ("dnsip", tmp); - } -#ifdef CONFIG_BOOTP_DNS2 - if (NetOurDNS2IP) { - ip_to_string (NetOurDNS2IP, tmp); - setenv ("dnsip2", tmp); - } -#endif - if (NetOurNISDomain[0]) - setenv ("domain", NetOurNISDomain); -} - #ifdef CONFIG_NET_RARP extern void RarpRequest(void); diff --git a/include/net.h b/include/net.h index 0ee7ecb8a6..a2863d0829 100644 --- a/include/net.h +++ b/include/net.h @@ -19,39 +19,8 @@ #include /* for nton* / ntoh* stuff */ -/* - * The number of receive packet buffers, and the required packet buffer - * alignment in memory. - * - */ - -#ifdef CFG_RX_ETH_BUFFER -# define PKTBUFSRX CFG_RX_ETH_BUFFER -#else -# define PKTBUFSRX 4 -#endif - -#define PKTALIGN 32 - -/* - * The current receive packet handler. Called with a pointer to the - * application packet, and a protocol type (PORT_BOOTPC or PORT_TFTP). - * All other packets are dealt with without calling the handler. - */ -typedef void rxhand_f(uchar *, unsigned, unsigned, unsigned); - -/* - * A timeout handler. Called after time interval has expired. - */ -typedef void thand_f(void); - -#define NAMESIZE 16 - -enum eth_state_t { - ETH_STATE_INIT, - ETH_STATE_PASSIVE, - ETH_STATE_ACTIVE -}; +/* The number of receive packet buffers */ +#define PKTBUFSRX 4 struct device_d; @@ -92,328 +61,6 @@ int eth_rx(void); /* Check for received packets */ void eth_halt(void); /* stop SCC */ char *eth_get_name(void); /* get name of current device */ - -/**********************************************************************/ -/* - * Protocol headers. - */ - -/* - * Ethernet header - */ -typedef struct { - uchar et_dest[6]; /* Destination node */ - uchar et_src[6]; /* Source node */ - ushort et_protlen; /* Protocol or length */ - uchar et_dsap; /* 802 DSAP */ - uchar et_ssap; /* 802 SSAP */ - uchar et_ctl; /* 802 control */ - uchar et_snap1; /* SNAP */ - uchar et_snap2; - uchar et_snap3; - ushort et_prot; /* 802 protocol */ -} Ethernet_t; - -#define ETHER_HDR_SIZE 14 /* Ethernet header size */ -#define E802_HDR_SIZE 22 /* 802 ethernet header size */ - -/* - * Ethernet header - */ -typedef struct { - uchar vet_dest[6]; /* Destination node */ - uchar vet_src[6]; /* Source node */ - ushort vet_vlan_type; /* PROT_VLAN */ - ushort vet_tag; /* TAG of VLAN */ - ushort vet_type; /* protocol type */ -} VLAN_Ethernet_t; - -#define VLAN_ETHER_HDR_SIZE 18 /* VLAN Ethernet header size */ - -#define PROT_IP 0x0800 /* IP protocol */ -#define PROT_ARP 0x0806 /* IP ARP protocol */ -#define PROT_RARP 0x8035 /* IP ARP protocol */ -#define PROT_VLAN 0x8100 /* IEEE 802.1q protocol */ - -#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ -#define IPPROTO_UDP 17 /* User Datagram Protocol */ - -/* - * Internet Protocol (IP) header. - */ -typedef struct { - uchar ip_hl_v; /* header length and version */ - uchar ip_tos; /* type of service */ - ushort ip_len; /* total length */ - ushort ip_id; /* identification */ - ushort ip_off; /* fragment offset field */ - uchar ip_ttl; /* time to live */ - uchar ip_p; /* protocol */ - ushort ip_sum; /* checksum */ - IPaddr_t ip_src; /* Source IP address */ - IPaddr_t ip_dst; /* Destination IP address */ - ushort udp_src; /* UDP source port */ - ushort udp_dst; /* UDP destination port */ - ushort udp_len; /* Length of UDP packet */ - ushort udp_xsum; /* Checksum */ -} IP_t; - -#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8) -#define IP_HDR_SIZE (sizeof (IP_t)) - - -/* - * Address Resolution Protocol (ARP) header. - */ -typedef struct -{ - ushort ar_hrd; /* Format of hardware address */ -# define ARP_ETHER 1 /* Ethernet hardware address */ - ushort ar_pro; /* Format of protocol address */ - uchar ar_hln; /* Length of hardware address */ - uchar ar_pln; /* Length of protocol address */ - ushort ar_op; /* Operation */ -# define ARPOP_REQUEST 1 /* Request to resolve address */ -# define ARPOP_REPLY 2 /* Response to previous request */ - -# define RARPOP_REQUEST 3 /* Request to resolve address */ -# define RARPOP_REPLY 4 /* Response to previous request */ - - /* - * The remaining fields are variable in size, according to - * the sizes above, and are defined as appropriate for - * specific hardware/protocol combinations. - */ - uchar ar_data[0]; -} ARP_t; - -/* - * ICMP stuff (just enough to handle (host) redirect messages) - */ -#define ICMP_ECHO_REPLY 0 /* Echo reply */ -#define ICMP_REDIRECT 5 /* Redirect (change route) */ -#define ICMP_ECHO_REQUEST 8 /* Echo request */ - -/* Codes for REDIRECT. */ -#define ICMP_REDIR_NET 0 /* Redirect Net */ -#define ICMP_REDIR_HOST 1 /* Redirect Host */ - -typedef struct { - uchar type; - uchar code; - ushort checksum; - union { - struct { - ushort id; - ushort sequence; - } echo; - ulong gateway; - struct { - ushort __unused; - ushort mtu; - } frag; - } un; -} ICMP_t; - - -/* - * Maximum packet size; used to allocate packet storage. - * TFTP packets can be 524 bytes + IP header + ethernet header. - * Lets be conservative, and go for 38 * 16. (Must also be - * a multiple of 32 bytes). - */ -/* - * AS.HARNOIS : Better to set PKTSIZE to maximum size because - * traffic type is not always controlled - * maximum packet size = 1518 - * maximum packet size and multiple of 32 bytes = 1536 - */ -#define PKTSIZE 1518 -#define PKTSIZE_ALIGN 1536 -/*#define PKTSIZE 608*/ - -/* - * Maximum receive ring size; that is, the number of packets - * we can buffer before overflow happens. Basically, this just - * needs to be enough to prevent a packet being discarded while - * we are processing the previous one. - */ -#define RINGSZ 4 -#define RINGSZ_LOG2 2 - -/**********************************************************************/ -/* - * Globals. - * - * Note: - * - * All variables of type IPaddr_t are stored in NETWORK byte order - * (big endian). - */ - -/* net.c */ -/** BOOTP EXTENTIONS **/ -extern IPaddr_t NetOurGatewayIP; /* Our gateway IP addresse */ -extern IPaddr_t NetOurSubnetMask; /* Our subnet mask (0 = unknown)*/ -extern IPaddr_t NetOurDNSIP; /* Our Domain Name Server (0 = unknown)*/ -extern IPaddr_t NetOurDNS2IP; /* Our 2nd Domain Name Server (0 = unknown)*/ -extern char NetOurNISDomain[32]; /* Our NIS domain */ -extern char NetOurHostName[32]; /* Our hostname */ -extern char NetOurRootPath[64]; /* Our root path */ -/** END OF BOOTP EXTENTIONS **/ -extern ulong NetBootFileXferSize; /* size of bootfile in bytes */ -extern uchar NetOurEther[6]; /* Our ethernet address */ -extern uchar NetServerEther[6]; /* Boot server enet address */ -extern IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ -extern IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */ -extern uchar * NetTxPacket; /* THE transmit packet */ -extern uchar * NetRxPackets[PKTBUFSRX];/* Receive packets */ -extern uchar * NetRxPkt; /* Current receive packet */ -extern int NetRxPktLen; /* Current rx packet length */ -extern unsigned NetIPID; /* IP ID (counting) */ -extern uchar NetBcastAddr[6]; /* Ethernet boardcast address */ -extern uchar NetEtherNullAddr[6]; - -#define VLAN_NONE 4095 /* untagged */ -#define VLAN_IDMASK 0x0fff /* mask of valid vlan id */ -extern ushort NetOurVLAN; /* Our VLAN */ -extern ushort NetOurNativeVLAN; /* Our Native VLAN */ - -extern int NetState; /* Network loop state */ - -/* ---------- Added by sha ------------ */ -extern IPaddr_t NetArpWaitPacketIP; -extern uchar *NetArpWaitPacketMAC; -extern uchar *NetArpWaitTxPacket; /* THE transmit packet */ -extern int NetArpWaitTxPacketSize; -extern int NetArpWaitTry; -extern uint64_t NetArpWaitTimerStart; -extern void ArpRequest (void); -/* ------------------------------------ */ - -#define NETLOOP_CONTINUE 1 -#define NETLOOP_SUCCESS 2 -#define NETLOOP_FAIL 3 - -typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t; - -/* Initialize the network adapter */ -int NetLoopInit(proto_t); - -/* Do the work */ -int NetLoop(void); - -/* Shutdown adapters and cleanup */ -void NetStop(void); - -/* Load failed. Start again. */ -void NetStartAgain(void); - -/* Get size of the ethernet header when we send */ -int NetEthHdrSize(void); - -/* Set ethernet header; returns the size of the header */ -int NetSetEther(uchar *, uchar *, uint); - -/* Set IP header */ -void NetSetIP(uchar *, IPaddr_t, int, int, int); - -/* Checksum */ -int NetCksumOk(uchar *, int); /* Return true if cksum OK */ -uint NetCksum(uchar *, int); /* Calculate the checksum */ - -/* Set callbacks */ -void NetSetHandler(rxhand_f *); /* Set RX packet handler */ -void NetSetTimeout(uint64_t, thand_f *);/* Set timeout handler */ - -/* Transmit "NetTxPacket" */ -void NetSendPacket(uchar *, int); - -/* Transmit UDP packet, performing ARP request if needed */ -int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len); - -/* Processes a received packet */ -void NetReceive(uchar *, int); - -/* Print an IP address on the console */ -#ifdef CONFIG_NET -void print_IPaddr (IPaddr_t); -#else -#define print_IPaddr(IPaddr_t); -#endif - -void netboot_update_env(void); - -/* - * The following functions are a bit ugly, but necessary to deal with - * alignment restrictions on ARM. - * - * We're using inline functions, which had the smallest memory - * footprint in our tests. - */ -/* return IP *in network byteorder* */ -static inline IPaddr_t NetReadIP(void *from) -{ - IPaddr_t ip; - memcpy((void*)&ip, from, sizeof(ip)); - return ip; -} - -/* return ulong *in network byteorder* */ -static inline ulong NetReadLong(ulong *from) -{ - ulong l; - memcpy((void*)&l, (void*)from, sizeof(l)); - return l; -} - -/* write IP *in network byteorder* */ -static inline void NetWriteIP(void *to, IPaddr_t ip) -{ - memcpy(to, (void*)&ip, sizeof(ip)); -} - -/* copy IP */ -static inline void NetCopyIP(void *to, void *from) -{ - memcpy(to, from, sizeof(IPaddr_t)); -} - -/* copy ulong */ -static inline void NetCopyLong(ulong *to, ulong *from) -{ - memcpy((void*)to, (void*)from, sizeof(ulong)); -} - -/* Convert an IP address to a string */ -char * ip_to_string (IPaddr_t x, char *s); - -/* Convert a string to ip address */ -int string_to_ip(const char *s, IPaddr_t *ip); - -/* Convert a VLAN id to a string */ -void VLAN_to_string (ushort x, char *s); - -/* Convert a string to a vlan id */ -ushort string_to_VLAN(const char *s); - -/* read an IP address from a environment variable */ -IPaddr_t getenv_IPaddr (char *); - -/* read a VLAN id from an environment variable */ -ushort getenv_VLAN(char *); - -int string_to_ethaddr(const char *str, char *enetaddr); -void ethaddr_to_string(const unsigned char *enetaddr, char *str); - -/**********************************************************************/ -/* Network devices */ -/**********************************************************************/ - -void eth_set_current(struct eth_device *eth); -struct eth_device *eth_get_current(void); -struct eth_device *eth_get_byname(char *name); - /* * Ethernet header */ @@ -577,8 +224,6 @@ static inline int net_eth_to_udplen(char *pkt) int net_checksum_ok(unsigned char *, int); /* Return true if cksum OK */ uint16_t net_checksum(unsigned char *, int); /* Calculate the checksum */ -void NetReceive(unsigned char *, int); - /* Print an IP address on the console */ void print_IPaddr (IPaddr_t); diff --git a/net/net.c b/net/net.c index 2b1641e8e9..4305c727f4 100644 --- a/net/net.c +++ b/net/net.c @@ -1,73 +1,31 @@ /* - * Copied from Linux Monitor (LiMon) - Networking. + * net.c - barebox networking support * - * Copyright 1994 - 2000 Neil Russell. - * (See License) - * Copyright 2000 Roland Borde - * Copyright 2000 Paolo Scaffardi - * Copyright 2000-2002 Wolfgang Denk, wd@denx.de - */ - -/* - * General Desription: - * - * The user interface supports commands for BOOTP, RARP, and TFTP. - * Also, we support ARP internally. Depending on available data, - * these interact as follows: - * - * BOOTP: - * - * Prerequisites: - own ethernet address - * We want: - own IP address - * - TFTP server IP address - * - name of bootfile - * Next step: ARP - * - * RARP: - * - * Prerequisites: - own ethernet address - * We want: - own IP address - * - TFTP server IP address - * Next step: ARP - * - * ARP: + * Copyright (c) 2010 Sascha Hauer , Pengutronix * - * Prerequisites: - own ethernet address - * - own IP address - * - TFTP server IP address - * We want: - TFTP server ethernet address - * Next step: TFTP + * based on U-Boot (LiMon) code * - * DHCP: + * Copyright 1994 - 2000 Neil Russell. + * Copyright 2000 Roland Borde + * Copyright 2000 Paolo Scaffardi + * Copyright 2000-2002 Wolfgang Denk, wd@denx.de * - * Prerequisites: - own ethernet address - * We want: - IP, Netmask, ServerIP, Gateway IP - * - bootfilename, lease time - * Next step: - TFTP + * See file CREDITS for list of people who contributed to this + * project. * - * TFTP: + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. * - * Prerequisites: - own ethernet address - * - own IP address - * - TFTP server IP address - * - TFTP server ethernet address - * - name of bootfile (if unknown, we use a default name - * derived from our own IP address) - * We want: - load the boot file - * Next step: none - * - * NFS: - * - * Prerequisites: - own ethernet address - * - own IP address - * - name of bootfile (if unknown, we use a default name - * derived from our own IP address) - * We want: - load the boot file - * Next step: none + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - #include #include #include @@ -77,778 +35,57 @@ #include #include #include +#include #include #include #include -#include "tftp.h" -#include "rarp.h" -#include "nfs.h" - -#define ARP_TIMEOUT (5 * SECOND) /* Seconds before trying ARP again */ -#ifndef CONFIG_NET_RETRY_COUNT -# define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ -#else -# define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) -#endif - -/** BOOTP EXTENTIONS **/ - -IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */ -IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */ -IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */ -#ifdef CONFIG_BOOTP_DNS2 -IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */ -#endif -char NetOurNISDomain[32]={0,}; /* Our NIS domain */ -char NetOurHostName[32]={0,}; /* Our hostname */ -char NetOurRootPath[64]={0,}; /* Our bootpath */ - -/** END OF BOOTP EXTENTIONS **/ - -ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */ -uchar NetOurEther[6]; /* Our ethernet address */ -uchar NetServerEther[6] = /* Boot server enet address */ - { 0, 0, 0, 0, 0, 0 }; -IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ -IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */ -uchar *NetRxPkt; /* Current receive packet */ -int NetRxPktLen; /* Current rx packet length */ -unsigned NetIPID; /* IP packet ID */ -uchar NetBcastAddr[6] = /* Ethernet bcast address */ - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -uchar NetEtherNullAddr[6] = - { 0, 0, 0, 0, 0, 0 }; -int NetState; /* Network loop state */ - -/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */ -ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */ -ushort NetOurNativeVLAN = 0xFFFF; /* ditto */ - -char BootFile[128]; /* Boot File name */ - -uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; - -uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ - -static rxhand_f *packetHandler; /* Current RX packet handler */ -static thand_f *timeHandler; /* Current timeout handler */ -static uint64_t timeStart; /* Time base value */ -static uint64_t timeDelta; /* Current timeout value */ -uchar *NetTxPacket = 0; /* THE transmit packet */ - -static int net_check_prereq (proto_t protocol); - -/**********************************************************************/ - -IPaddr_t NetArpWaitPacketIP; -IPaddr_t NetArpWaitReplyIP; -uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */ -uchar *NetArpWaitTxPacket; /* THE transmit packet */ -int NetArpWaitTxPacketSize; -uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; -uint64_t NetArpWaitTimerStart; - -void ArpRequest (void) -{ - int i; - uchar *pkt; - ARP_t *arp; - - pr_debug("ARP broadcast\n"); - - pkt = NetTxPacket; - - pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP); - - arp = (ARP_t *) pkt; - - arp->ar_hrd = htons (ARP_ETHER); - arp->ar_pro = htons (PROT_IP); - arp->ar_hln = 6; - arp->ar_pln = 4; - arp->ar_op = htons (ARPOP_REQUEST); - - memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */ - NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP); /* source IP addr */ - for (i = 10; i < 16; ++i) { - arp->ar_data[i] = 0; /* dest ET addr = 0 */ - } - - if ((NetArpWaitPacketIP & NetOurSubnetMask) != - (NetOurIP & NetOurSubnetMask)) { - if (NetOurGatewayIP == 0) { - puts ("## Warning: gatewayip needed but not set\n"); - NetArpWaitReplyIP = NetArpWaitPacketIP; - } else { - NetArpWaitReplyIP = NetOurGatewayIP; - } - } else { - NetArpWaitReplyIP = NetArpWaitPacketIP; - } - - NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP); - (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE); -} - -/**********************************************************************/ -/* - * Main network processing loop. - */ - -int NetLoopInit(proto_t protocol) -{ - struct eth_device *eth_current = eth_get_current(); - IPaddr_t ip; - int ret; - int i; - - if (!eth_current) { - printf("Current ethernet device not set!\n"); - return -1; - } - - ip = dev_get_param_ip(ð_current->dev, "ipaddr"); - NetCopyIP(&NetOurIP, &ip); - - /* XXX problem with bss workaround */ - NetArpWaitPacketMAC = NULL; - NetArpWaitTxPacket = NULL; - NetArpWaitPacketIP = 0; - NetArpWaitReplyIP = 0; - - /* - * Setup packet buffers, aligned correctly. - */ - NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); - NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; - for (i = 0; i < PKTBUFSRX; i++) { - NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; - } - - NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); - NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; - NetArpWaitTxPacketSize = 0; - - string_to_ethaddr(dev_get_param(ð_get_current()->dev, "ethaddr"), - NetOurEther); - - NetState = NETLOOP_CONTINUE; - - NetOurGatewayIP = dev_get_param_ip(ð_current->dev, "gateway"); - NetOurSubnetMask = dev_get_param_ip(ð_current->dev, "netmask"); - NetOurVLAN = getenv_VLAN("vlan"); - NetOurNativeVLAN = getenv_VLAN("nvlan"); - NetServerIP = dev_get_param_ip(ð_current->dev, "serverip"); - - ret = net_check_prereq(protocol); - - return ret; -} - -int NetLoop(void) -{ - /* - * Start the ball rolling with the given start function. From - * here on, this code is a state machine driven by received - * packets and timer events. - */ - - NetBootFileXferSize = 0; - - /* - * Main packet reception loop. Loop receiving packets until - * someone sets `NetState' to a state that terminates. - */ - for (;;) { - WATCHDOG_RESET(); -#ifdef CONFIG_SHOW_ACTIVITY - { - extern void show_activity(int arg); - show_activity(1); - } -#endif - /* - * Check the ethernet for a new packet. The ethernet - * receive routine will process it. - */ - eth_rx(); - - /* - * Abort if ctrl-c was pressed. - */ - if (ctrlc()) { - puts ("\nAbort\n"); - return -1; - } - - /* check for arp timeout */ - if (NetArpWaitPacketIP && - is_timeout(NetArpWaitTimerStart, ARP_TIMEOUT)) { - NetArpWaitTimerStart = get_time_ns(); - ArpRequest(); - } - - /* - * Check for a timeout, and run the timeout handler - * if we have one. - */ - if (timeHandler && is_timeout(timeStart, timeDelta)) { - thand_f *x; - x = timeHandler; - timeHandler = (thand_f *)0; - (*x)(); - } +static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */ +static IPaddr_t net_gateway; /* Our gateways IP address */ - switch (NetState) { - case NETLOOP_SUCCESS: - if (NetBootFileXferSize > 0) { - char buf[10]; - printf("Bytes transferred = %ld (%lx hex)\n", - NetBootFileXferSize, - NetBootFileXferSize); - sprintf(buf, "0x%lx", NetBootFileXferSize); - setenv("filesize", buf); - } - return NetBootFileXferSize; - - case NETLOOP_FAIL: - return -1; - } - } -} - -/**********************************************************************/ -/* - * Miscelaneous bits. - */ - -void -NetSetHandler(rxhand_f * f) -{ - packetHandler = f; -} - - -void -NetSetTimeout(uint64_t iv, thand_f * f) -{ - if (iv == 0) { - timeHandler = (thand_f *)0; - } else { - timeHandler = f; - timeStart = get_time_ns(); - timeDelta = iv; - } -} - - -void -NetSendPacket(uchar * pkt, int len) -{ - (void) eth_send(pkt, len); -} - -int -NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) -{ - uchar *pkt; - - /* convert to new style broadcast */ - if (dest == 0) - dest = 0xFFFFFFFF; - - /* if broadcast, make the ether address a broadcast and don't do ARP */ - if (dest == 0xFFFFFFFF) - ether = NetBcastAddr; - - /* if MAC address was not discovered yet, save the packet and do an ARP request */ - if (memcmp(ether, NetEtherNullAddr, 6) == 0) { - pr_debug("sending ARP for %08lx\n", dest); - - NetArpWaitPacketIP = dest; - NetArpWaitPacketMAC = ether; - - pkt = NetArpWaitTxPacket; - pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP); - - NetSetIP (pkt, dest, dport, sport, len); - memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len); - - /* size of the waiting packet */ - NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len; - - /* and do the ARP request */ - NetArpWaitTimerStart = get_time_ns(); - ArpRequest(); - return 1; /* waiting */ - } - - pr_debug("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n", - dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); - - pkt = (uchar *)NetTxPacket; - pkt += NetSetEther (pkt, ether, PROT_IP); - NetSetIP (pkt, dest, dport, sport, len); - (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len); +static unsigned char net_ether[6]; /* Our ethernet address */ +static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */ +static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */ - return 0; /* transmitted */ -} +unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */ +static unsigned int net_ip_id; -void -NetReceive(uchar * inpkt, int len) +void net_update_env(void) { - Ethernet_t *et; - IP_t *ip; - ARP_t *arp; - IPaddr_t tmp; - int x; - uchar *pkt; - ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid; - - pr_debug("packet received\n"); - - if (!net_receive(inpkt, len)) - return; - - NetRxPkt = inpkt; - NetRxPktLen = len; - et = (Ethernet_t *)inpkt; - - /* too small packet? */ - if (len < ETHER_HDR_SIZE) - return; - - myvlanid = ntohs(NetOurVLAN); - if (myvlanid == (ushort)-1) - myvlanid = VLAN_NONE; - mynvlanid = ntohs(NetOurNativeVLAN); - if (mynvlanid == (ushort)-1) - mynvlanid = VLAN_NONE; - - x = ntohs(et->et_protlen); - - pr_debug("packet received\n"); - - if (x < 1514) { - /* - * Got a 802 packet. Check the other protocol field. - */ - x = ntohs(et->et_prot); - - ip = (IP_t *)(inpkt + E802_HDR_SIZE); - len -= E802_HDR_SIZE; - - } else if (x != PROT_VLAN) { /* normal packet */ - ip = (IP_t *)(inpkt + ETHER_HDR_SIZE); - len -= ETHER_HDR_SIZE; - - } else { /* VLAN packet */ - VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et; - - pr_debug("VLAN packet received\n"); - - /* too small packet? */ - if (len < VLAN_ETHER_HDR_SIZE) - return; - - /* if no VLAN active */ - if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE - ) - return; - - cti = ntohs(vet->vet_tag); - vlanid = cti & VLAN_IDMASK; - x = ntohs(vet->vet_type); - - ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE); - len -= VLAN_ETHER_HDR_SIZE; - } - - pr_debug("Receive from protocol 0x%x\n", x); - - if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) { - if (vlanid == VLAN_NONE) - vlanid = (mynvlanid & VLAN_IDMASK); - /* not matched? */ - if (vlanid != (myvlanid & VLAN_IDMASK)) - return; - } - - switch (x) { - - case PROT_ARP: - /* - * We have to deal with two types of ARP packets: - * - REQUEST packets will be answered by sending our - * IP address - if we know it. - * - REPLY packets are expected only after we asked - * for the TFTP server's or the gateway's ethernet - * address; so if we receive such a packet, we set - * the server ethernet address - */ - pr_debug("Got ARP\n"); - - arp = (ARP_t *)ip; - if (len < ARP_HDR_SIZE) { - printf("bad length %d < %d\n", len, ARP_HDR_SIZE); - return; - } - if (ntohs(arp->ar_hrd) != ARP_ETHER) { - return; - } - if (ntohs(arp->ar_pro) != PROT_IP) { - return; - } - if (arp->ar_hln != 6) { - return; - } - if (arp->ar_pln != 4) { - return; - } - - if (NetOurIP == 0) { - return; - } - - if (NetReadIP(&arp->ar_data[16]) != NetOurIP) { - return; - } - - switch (ntohs(arp->ar_op)) { - case ARPOP_REQUEST: /* reply with our IP address */ - pr_debug("Got ARP REQUEST, return our IP\n"); - - pkt = (uchar *)et; - pkt += NetSetEther(pkt, et->et_src, PROT_ARP); - arp->ar_op = htons(ARPOP_REPLY); - memcpy (&arp->ar_data[10], &arp->ar_data[0], 6); - NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); - memcpy (&arp->ar_data[ 0], NetOurEther, 6); - NetCopyIP(&arp->ar_data[ 6], &NetOurIP); - memcpy(NetTxPacket, et, (pkt - (uchar *)et) + ARP_HDR_SIZE); - eth_send((uchar *)NetTxPacket, (pkt - (uchar *)et) + ARP_HDR_SIZE); - return; - - case ARPOP_REPLY: /* arp reply */ - /* are we waiting for a reply */ - if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC) - break; - pr_debug("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", - arp->ar_data[0], arp->ar_data[1], - arp->ar_data[2], arp->ar_data[3], - arp->ar_data[4], arp->ar_data[5]); - - tmp = NetReadIP(&arp->ar_data[6]); - - /* matched waiting packet's address */ - if (tmp == NetArpWaitReplyIP) { - pr_debug("Got it\n"); - - /* save address for later use */ - memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6); - - /* modify header, and transmit it */ - memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6); - (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize); - - /* no arp request pending now */ - NetArpWaitPacketIP = 0; - NetArpWaitTxPacketSize = 0; - NetArpWaitPacketMAC = NULL; - - } - return; - default: - pr_debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op)); - return; - } - break; - - case PROT_RARP: - pr_debug("Got RARP\n"); - - arp = (ARP_t *)ip; - if (len < ARP_HDR_SIZE) { - printf("bad length %d < %d\n", len, ARP_HDR_SIZE); - return; - } - - if ((ntohs(arp->ar_op) != RARPOP_REPLY) || - (ntohs(arp->ar_hrd) != ARP_ETHER) || - (ntohs(arp->ar_pro) != PROT_IP) || - (arp->ar_hln != 6) || (arp->ar_pln != 4)) { - - puts ("invalid RARP header\n"); - } else { - NetCopyIP(&NetOurIP, &arp->ar_data[16]); - if (NetServerIP == 0) - NetCopyIP(&NetServerIP, &arp->ar_data[ 6]); - memcpy (NetServerEther, &arp->ar_data[ 0], 6); - - if (packetHandler) - (*packetHandler)(0,0,0,0); - } - break; - - case PROT_IP: - pr_debug("Got IP\n"); - - if (len < IP_HDR_SIZE) { - debug ("len bad %d < %d\n", len, IP_HDR_SIZE); - return; - } - if (len < ntohs(ip->ip_len)) { - printf("len bad %d < %d\n", len, ntohs(ip->ip_len)); - return; - } - len = ntohs(ip->ip_len); - - pr_debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff); + struct eth_device *edev = eth_get_current(); - if ((ip->ip_hl_v & 0xf0) != 0x40) { - return; - } - if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */ - return; - } - if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) { - puts ("checksum bad\n"); - return; - } - tmp = NetReadIP(&ip->ip_dst); - if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) { - return; - } - /* - * watch for ICMP host redirects - * - * There is no real handler code (yet). We just watch - * for ICMP host redirect messages. In case anybody - * sees these messages: please contact me - * (wd@denx.de), or - even better - send me the - * necessary fixes :-) - * - * Note: in all cases where I have seen this so far - * it was a problem with the router configuration, - * for instance when a router was configured in the - * BOOTP reply, but the TFTP server was on the same - * subnet. So this is probably a warning that your - * configuration might be wrong. But I'm not really - * sure if there aren't any other situations. - */ - if (ip->ip_p == IPPROTO_ICMP) { - ICMP_t *icmph = (ICMP_t *)&(ip->udp_src); - - switch (icmph->type) { - case ICMP_REDIRECT: - if (icmph->code != ICMP_REDIR_HOST) - return; - puts (" ICMP Host Redirect to "); - print_IPaddr(icmph->un.gateway); - putchar(' '); - return; -#ifdef CONFIG_NET_PING - case ICMP_ECHO_REPLY: - /* - * IP header OK. Pass the packet to the current handler. - */ - /* XXX point to ip packet */ - if (packetHandler) - (*packetHandler)((uchar *)ip, 0, 0, 0); - return; -#endif - default: - return; - } - } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */ - return; - } + net_ip = dev_get_param_ip(&edev->dev, "ipaddr"); + net_serverip = dev_get_param_ip(&edev->dev, "serverip"); + net_gateway = dev_get_param_ip(&edev->dev, "gateway"); + net_netmask = dev_get_param_ip(&edev->dev, "netmask"); -#ifdef CONFIG_UDP_CHECKSUM - if (ip->udp_xsum != 0) { - ulong xsum; - ushort *sumptr; - ushort sumlen; - - xsum = ip->ip_p; - xsum += (ntohs(ip->udp_len)); - xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff; - xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff; - xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff; - xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff; - - sumlen = ntohs(ip->udp_len); - sumptr = (ushort *) &(ip->udp_src); - - while (sumlen > 1) { - ushort sumdata; - - sumdata = *sumptr++; - xsum += ntohs(sumdata); - sumlen -= 2; - } - if (sumlen > 0) { - ushort sumdata; - - sumdata = *(unsigned char *) sumptr; - sumdata = (sumdata << 8) & 0xff00; - xsum += sumdata; - } - while ((xsum >> 16) != 0) { - xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff); - } - if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) { - printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum)); - return; - } - } -#endif - /* - * IP header OK. Pass the packet to the current handler. - */ - if (packetHandler) - (*packetHandler)((uchar *)ip +IP_HDR_SIZE, - ntohs(ip->udp_dst), - ntohs(ip->udp_src), - ntohs(ip->udp_len) - 8); - break; - } + string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"), + net_ether); } - -/**********************************************************************/ - -static int net_check_prereq (proto_t protocol) +int net_checksum_ok(unsigned char *ptr, int len) { - struct eth_device *edev = eth_get_current(); - - switch (protocol) { - /* Fall through */ -#ifdef CONFIG_NET_NFS - case NFS: -#endif - case NETCONS: - case TFTP: - if (NetServerIP == 0) { - printf("*** ERROR: `%s.serverip' not set\n", dev_id(&edev->dev)); - return -1; - } - - if (NetOurIP == 0) { - printf("*** ERROR: `%s.ipaddr' not set\n", dev_id(&edev->dev)); - return -1; - } - /* Fall through */ - - case DHCP: - case RARP: - case BOOTP: - if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) { - printf("*** ERROR: `%s.ethaddr' not set\n", dev_id(&edev->dev)); - return -1; - } - /* Fall through */ - default: - return 0; - } - - return -1; /* not reached */ + return net_checksum(ptr, len) + 1; } -/**********************************************************************/ -int -NetCksumOk(uchar * ptr, int len) +uint16_t net_checksum(unsigned char *ptr, int len) { - return !((NetCksum(ptr, len) + 1) & 0xfffe); -} + uint32_t xsum = 0; + uint16_t *p = (uint16_t *)ptr; + if (len & 1) + ptr[len] = 0; -unsigned -NetCksum(uchar * ptr, int len) -{ - ulong xsum; - ushort *p = (ushort *)ptr; + len = (len + 1) >> 1; - xsum = 0; while (len-- > 0) xsum += *p++; + xsum = (xsum & 0xffff) + (xsum >> 16); xsum = (xsum & 0xffff) + (xsum >> 16); return xsum & 0xffff; } -int -NetEthHdrSize(void) -{ - ushort myvlanid; - - myvlanid = ntohs(NetOurVLAN); - if (myvlanid == (ushort)-1) - myvlanid = VLAN_NONE; - - return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE; -} - -int -NetSetEther(uchar * xet, uchar * addr, uint prot) -{ - Ethernet_t *et = (Ethernet_t *)xet; - ushort myvlanid; - - myvlanid = ntohs(NetOurVLAN); - if (myvlanid == (ushort)-1) - myvlanid = VLAN_NONE; - - memcpy (et->et_dest, addr, 6); - memcpy (et->et_src, NetOurEther, 6); - if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { - et->et_protlen = htons(prot); - return ETHER_HDR_SIZE; - } else { - VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet; - - vet->vet_vlan_type = htons(PROT_VLAN); - vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK)); - vet->vet_type = htons(prot); - return VLAN_ETHER_HDR_SIZE; - } -} - -void -NetSetIP(uchar * xip, IPaddr_t dest, int dport, int sport, int len) -{ - IP_t *ip = (IP_t *)xip; - - /* - * If the data is an odd number of bytes, zero the - * byte after the last byte so that the checksum - * will work. - */ - if (len & 1) - xip[IP_HDR_SIZE + len] = 0; - - /* - * Construct an IP and UDP header. - * (need to set no fragment bit - XXX) - */ - ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */ - ip->ip_tos = 0; - ip->ip_len = htons(IP_HDR_SIZE + len); - ip->ip_id = htons(NetIPID++); - ip->ip_off = htons(0x4000); /* No fragmentation */ - ip->ip_ttl = 255; - ip->ip_p = 17; /* UDP */ - ip->ip_sum = 0; - NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */ - NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */ - ip->udp_src = htons(sport); - ip->udp_dst = htons(dport); - ip->udp_len = htons(8 + len); - ip->udp_xsum = 0; - ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); -} - char *ip_to_string (IPaddr_t x, char *s) { x = ntohl (x); @@ -870,7 +107,7 @@ int string_to_ip(const char *s, IPaddr_t *ip) return -EINVAL; for (i = 0; i < 4; i++) { - ulong val; + unsigned long val; if (!isdigit(*s)) return -EINVAL; @@ -913,34 +150,6 @@ int setenv_ip(const char *name, IPaddr_t ip) return 0; } -void VLAN_to_string(ushort x, char *s) -{ - x = ntohs(x); - - if (x == (ushort)-1) - x = VLAN_NONE; - - if (x == VLAN_NONE) - strcpy(s, "none"); - else - sprintf(s, "%d", x & VLAN_IDMASK); -} - -ushort string_to_VLAN(const char *s) -{ - ushort id; - - if (s == NULL) - return htons(VLAN_NONE); - - if (*s < '0' || *s > '9') - id = VLAN_NONE; - else - id = (ushort)simple_strtoul(s, NULL, 10); - - return htons(id); -} - void print_IPaddr (IPaddr_t x) { char tmp[16]; @@ -950,14 +159,9 @@ void print_IPaddr (IPaddr_t x) puts (tmp); } -ushort getenv_VLAN(char *var) -{ - return string_to_VLAN(getenv(var)); -} - int string_to_ethaddr(const char *str, char *enetaddr) { - ulong reg; + int reg; char *e; if (!str || strlen(str) != 17) @@ -977,65 +181,11 @@ int string_to_ethaddr(const char *str, char *enetaddr) void ethaddr_to_string(const unsigned char *enetaddr, char *str) { - sprintf (str, "%02X:%02X:%02X:%02X:%02X:%02X", + sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3], enetaddr[4], enetaddr[5]); } -static IPaddr_t net_netmask; /* Our subnet mask (0=unknown) */ -static IPaddr_t net_gateway; /* Our gateways IP address */ - -static unsigned char net_ether[6]; /* Our ethernet address */ -static IPaddr_t net_ip; /* Our IP addr (0 = unknown) */ -static IPaddr_t net_serverip; /* Our IP addr (0 = unknown) */ - -unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */ -static unsigned int net_ip_id; - -void net_update_env(void) -{ - struct eth_device *edev = eth_get_current(); - - net_ip = dev_get_param_ip(&edev->dev, "ipaddr"); - net_serverip = dev_get_param_ip(&edev->dev, "serverip"); - net_gateway = dev_get_param_ip(&edev->dev, "gateway"); - net_netmask = dev_get_param_ip(&edev->dev, "netmask"); - - string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"), - net_ether); - - NetOurIP = dev_get_param_ip(&edev->dev, "ipaddr"); - NetServerIP = dev_get_param_ip(&edev->dev, "serverip"); - NetOurGatewayIP = dev_get_param_ip(&edev->dev, "gateway"); - NetOurSubnetMask = dev_get_param_ip(&edev->dev, "netmask"); - - string_to_ethaddr(dev_get_param(&edev->dev, "ethaddr"), - NetOurEther); -} - -int net_checksum_ok(unsigned char *ptr, int len) -{ - return net_checksum(ptr, len) + 1; -} - -uint16_t net_checksum(unsigned char *ptr, int len) -{ - uint32_t xsum = 0; - uint16_t *p = (uint16_t *)ptr; - - if (len & 1) - ptr[len] = 0; - - len = (len + 1) >> 1; - - while (len-- > 0) - xsum += *p++; - - xsum = (xsum & 0xffff) + (xsum >> 16); - xsum = (xsum & 0xffff) + (xsum >> 16); - return xsum & 0xffff; -} - static unsigned char *arp_ether; static IPaddr_t arp_wait_ip; -- cgit v1.2.3 From c3789cd49b43ec1c414ba1b0e9f48e8ccc19f8e1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 3 Jun 2010 10:13:29 +0200 Subject: rework device parameters Change device parameters so that the memory management is in generic code. This also removes the need of storing statically initialized parameters as they are stored in a struct list_head for each device. Signed-off-by: Sascha Hauer --- common/console.c | 40 ++++++----- drivers/nand/nand.c | 7 +- drivers/video/fb.c | 21 +++--- drivers/video/imx.c | 17 ++--- include/console.h | 6 -- include/driver.h | 2 +- include/fb.h | 2 - include/net.h | 6 -- include/param.h | 15 +++- lib/driver.c | 12 ++-- lib/parameter.c | 195 +++++++++++++++++++++++++++++++++------------------- net/eth.c | 48 ++++--------- 12 files changed, 202 insertions(+), 169 deletions(-) (limited to 'include') diff --git a/common/console.c b/common/console.c index d3d31f7898..7199d9afb8 100644 --- a/common/console.c +++ b/common/console.c @@ -57,26 +57,32 @@ static int console_std_set(struct device_d *dev, struct param_d *param, const char *val) { struct console_device *cdev = dev->type_data; + char active[4]; unsigned int flag = 0, i = 0; + if (!val) + dev_param_set_generic(dev, param, NULL); + if (strchr(val, 'i') && cdev->f_caps & CONSOLE_STDIN) { - cdev->active[i++] = 'i'; + active[i++] = 'i'; flag |= CONSOLE_STDIN; } if (strchr(val, 'o') && cdev->f_caps & CONSOLE_STDOUT) { - cdev->active[i++] = 'o'; + active[i++] = 'o'; flag |= CONSOLE_STDOUT; } if (strchr(val, 'e') && cdev->f_caps & CONSOLE_STDERR) { - cdev->active[i++] = 'e'; + active[i++] = 'e'; flag |= CONSOLE_STDERR; } - cdev->active[i] = 0; + active[i] = 0; cdev->f_active = flag; + dev_param_set_generic(dev, param, active); + return 0; } @@ -85,8 +91,12 @@ static int console_baudrate_set(struct device_d *dev, struct param_d *param, { struct console_device *cdev = dev->type_data; int baudrate; + char baudstr[16]; unsigned char c; + if (!val) + dev_param_set_generic(dev, param, NULL); + baudrate = simple_strtoul(val, NULL, 10); if (cdev->f_active) { @@ -101,7 +111,8 @@ static int console_baudrate_set(struct device_d *dev, struct param_d *param, } else cdev->setbrg(cdev, baudrate); - sprintf(cdev->baudrate_string, "%d", baudrate); + sprintf(baudstr, "%d", baudrate); + dev_param_set_generic(dev, param, baudstr); return 0; } @@ -129,29 +140,20 @@ int console_register(struct console_device *newcdev) register_device(dev); if (newcdev->setbrg) { - newcdev->baudrate_param.set = console_baudrate_set; - newcdev->baudrate_param.name = "baudrate"; - sprintf(newcdev->baudrate_string, "%d", - CONFIG_BAUDRATE); - console_baudrate_set(dev, &newcdev->baudrate_param, - newcdev->baudrate_string); - newcdev->baudrate_param.value = newcdev->baudrate_string; - dev_add_param(dev, &newcdev->baudrate_param); + dev_add_param(dev, "baudrate", console_baudrate_set, NULL, 0); + dev_set_param(dev, "baudrate", "115200"); } - newcdev->active_param.set = console_std_set; - newcdev->active_param.name = "active"; - newcdev->active_param.value = newcdev->active; - dev_add_param(dev, &newcdev->active_param); + dev_add_param(dev, "active", console_std_set, NULL, 0); initialized = CONSOLE_INIT_FULL; #ifdef CONFIG_CONSOLE_ACTIVATE_ALL - console_std_set(dev, &newcdev->active_param, "ioe"); + dev_set_param(dev, "active", "ioe"); #endif #ifdef CONFIG_CONSOLE_ACTIVATE_FIRST if (list_empty(&console_list)) { first = 1; - console_std_set(dev, &newcdev->active_param, "ioe"); + dev_set_param(dev, "active", "ioe"); } #endif diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c index bcf52bd940..4927231c17 100644 --- a/drivers/nand/nand.c +++ b/drivers/nand/nand.c @@ -210,6 +210,7 @@ static struct file_operations nand_ops_oob = { int add_mtd_device(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; + char str[16]; strcpy(mtd->class_dev.name, "nand"); register_device(&mtd->class_dev); @@ -220,10 +221,8 @@ int add_mtd_device(struct mtd_info *mtd) mtd->cdev.priv = mtd; mtd->cdev.dev = &mtd->class_dev; - mtd->param_size.flags = PARAM_FLAG_RO; - mtd->param_size.name = "size"; - mtd->param_size.value = asprintf("%u", mtd->size); - dev_add_param(&mtd->class_dev, &mtd->param_size); + sprintf(str, "%u", mtd->size); + dev_add_param_fixed(&mtd->class_dev, "size", str); devfs_create(&mtd->cdev); diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 00a0f6a177..841c3afe9e 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -32,15 +32,22 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param, { struct fb_info *info = dev->priv; int enable; + char *new; + + if (!val) + return dev_param_set_generic(dev, param, NULL); enable = simple_strtoul(val, NULL, 0); - if (enable) + if (enable) { info->fbops->fb_enable(info); - else + new = "1"; + } else { info->fbops->fb_disable(info); + new = "0"; + } - sprintf(info->enable_string, "%d", !!enable); + dev_param_set_generic(dev, param, new); return 0; } @@ -71,13 +78,9 @@ int register_framebuffer(struct fb_info *info) sprintf(dev->name, "fb"); - info->param_enable.set = fb_enable_set; - info->param_enable.name = "enable"; - sprintf(info->enable_string, "%d", 0); - info->param_enable.value = info->enable_string; - dev_add_param(dev, &info->param_enable); - register_device(&info->dev); + dev_add_param(dev, "enable", fb_enable_set, NULL, 0); + dev_set_param(dev, "enable", "0"); devfs_create(&info->cdev); diff --git a/drivers/video/imx.c b/drivers/video/imx.c index 67cae349e5..d9ba643acb 100644 --- a/drivers/video/imx.c +++ b/drivers/video/imx.c @@ -154,8 +154,6 @@ struct imxfb_info { struct fb_info overlay; - struct param_d param_alpha; - char alpha_string[4]; }; #define IMX_NAME "IMX" @@ -427,8 +425,12 @@ static int imxfb_alpha_set(struct device_d *dev, struct param_d *param, struct fb_info *overlay = dev->priv; struct imxfb_info *fbi = overlay->priv; int alpha; + char alphastr[16]; unsigned int tmp; + if (!val) + return dev_param_set_generic(dev, param, NULL); + alpha = simple_strtoul(val, NULL, 0); alpha &= 0xff; @@ -437,7 +439,9 @@ static int imxfb_alpha_set(struct device_d *dev, struct param_d *param, tmp |= LGWCR_GWAV(alpha); writel(tmp , fbi->regs + LCDC_LGWCR); - sprintf(fbi->alpha_string, "%d", alpha); + sprintf(alphastr, "%d", alpha); + + dev_param_set_generic(dev, param, alphastr); return 0; } @@ -502,11 +506,8 @@ static int imxfb_register_overlay(struct imxfb_info *fbi, void *fb) return ret; } - fbi->param_alpha.set = imxfb_alpha_set; - fbi->param_alpha.name = "alpha"; - sprintf(fbi->alpha_string, "%d", 0); - fbi->param_alpha.value = fbi->alpha_string; - dev_add_param(&overlay->dev, &fbi->param_alpha); + dev_add_param(&overlay->dev, "alpha", imxfb_alpha_set, NULL, 0); + dev_set_param(&overlay->dev, "alpha", "0"); return 0; } diff --git a/include/console.h b/include/console.h index 3568c562a8..3bcc5dbbc0 100644 --- a/include/console.h +++ b/include/console.h @@ -46,12 +46,6 @@ struct console_device { unsigned char f_caps; unsigned char f_active; - - struct param_d baudrate_param; - char baudrate_string[8]; - - struct param_d active_param; - char active[4]; }; int console_register(struct console_device *cdev); diff --git a/include/driver.h b/include/driver.h index 1dde38e021..6950c02047 100644 --- a/include/driver.h +++ b/include/driver.h @@ -98,7 +98,7 @@ struct device_d { /*! The parameters for this device. This is used to carry information * of board specific data from the board code to the device driver. */ - struct param_d *param; + struct list_head parameters; struct list_head cdevs; }; diff --git a/include/fb.h b/include/fb.h index f213c420d4..218500b985 100644 --- a/include/fb.h +++ b/include/fb.h @@ -80,8 +80,6 @@ struct fb_info { struct fb_ops *fbops; struct device_d dev; /* This is this fb device */ - struct param_d param_enable; - char enable_string[1]; void *screen_base; diff --git a/include/net.h b/include/net.h index a2863d0829..15106a7826 100644 --- a/include/net.h +++ b/include/net.h @@ -41,12 +41,6 @@ struct eth_device { struct eth_device *next; void *priv; - struct param_d param_ip; - struct param_d param_netmask; - struct param_d param_gateway; - struct param_d param_serverip; - struct param_d param_ethaddr; - struct device_d dev; struct list_head list; diff --git a/include/param.h b/include/param.h index fe4468ed2c..207ad5016a 100644 --- a/include/param.h +++ b/include/param.h @@ -2,6 +2,7 @@ #define PARAM_H #include +#include #define PARAM_FLAG_RO (1 << 0) @@ -15,12 +16,24 @@ struct param_d { char *name; struct param_d *next; char *value; + struct list_head list; }; const char *dev_get_param(struct device_d *dev, const char *name); int dev_set_param(struct device_d *dev, const char *name, const char *val); struct param_d *get_param_by_name(struct device_d *dev, const char *name); -int dev_add_param(struct device_d *dev, struct param_d *par); + +int dev_add_param(struct device_d *dev, char *name, + int (*set)(struct device_d *dev, struct param_d *p, const char *val), + char *(*get)(struct device_d *, struct param_d *p), + unsigned long flags); + +int dev_add_param_fixed(struct device_d *dev, char *name, char *value); + +void dev_remove_parameters(struct device_d *dev); + +int dev_param_set_generic(struct device_d *dev, struct param_d *p, + const char *val); /* Convenience functions to handle a parameter as an ip address */ int dev_set_param_ip(struct device_d *dev, char *name, IPaddr_t ip); diff --git a/lib/driver.c b/lib/driver.c index f433c3e9bf..b60074511f 100644 --- a/lib/driver.c +++ b/lib/driver.c @@ -107,6 +107,7 @@ int register_device(struct device_d *new_device) list_add_tail(&new_device->list, &device_list); INIT_LIST_HEAD(&new_device->children); INIT_LIST_HEAD(&new_device->cdevs); + INIT_LIST_HEAD(&new_device->parameters); for_each_driver(drv) { if (!match(drv, new_device)) @@ -313,16 +314,11 @@ static int do_devinfo(struct command *cmdtp, int argc, char *argv[]) if (dev->driver) dev->driver->info(dev); - param = dev->param; + printf("%s\n", list_empty(&dev->parameters) ? + "no parameters available" : "Parameters:"); - printf("%s\n", param ? - "Parameters:" : "no parameters available"); - - while (param) { + list_for_each_entry(param, &dev->parameters, list) printf("%16s = %s\n", param->name, param->value); - param = param->next; - } - } return 0; diff --git a/lib/parameter.c b/lib/parameter.c index 6b32207cd5..0aa4193431 100644 --- a/lib/parameter.c +++ b/lib/parameter.c @@ -33,17 +33,22 @@ struct param_d *get_param_by_name(struct device_d *dev, const char *name) { - struct param_d *param = dev->param; + struct param_d *p; - while (param) { - if (!strcmp(param->name, name)) - return param; - param = param->next; + list_for_each_entry(p, &dev->parameters, list) { + if (!strcmp(p->name, name)) + return p; } return NULL; } +/** + * dev_get_param - get the value of a parameter + * @param dev The device + * @param name The name of the parameter + * @return The value + */ const char *dev_get_param(struct device_d *dev, const char *name) { struct param_d *param = get_param_by_name(dev, name); @@ -53,10 +58,7 @@ const char *dev_get_param(struct device_d *dev, const char *name) return NULL; } - if (param->get) - return param->get(dev, param); - - return param->value; + return param->get(dev, param); } #ifdef CONFIG_NET @@ -80,6 +82,12 @@ int dev_set_param_ip(struct device_d *dev, char *name, IPaddr_t ip) } #endif +/** + * dev_set_param - set a parameter of a device to a new value + * @param dev The device + * @param name The name of the parameter + * @param value The new value of the parameter + */ int dev_set_param(struct device_d *dev, const char *name, const char *val) { struct param_d *param; @@ -101,35 +109,124 @@ int dev_set_param(struct device_d *dev, const char *name, const char *val) return -EACCES; } - if (param->set) { - errno = param->set(dev, param, val); - return errno; + errno = param->set(dev, param, val); + return errno; +} + +/** + * dev_param_set_generic - generic setter function for a parameter + * @param dev The device + * @param p the parameter + * @param val The new value + * + * If used the value of a parameter is a string allocated with + * malloc and freed with free. If val is NULL the value is freed. This is + * used during deregistration of the parameter to free the alloctated + * memory. + */ +int dev_param_set_generic(struct device_d *dev, struct param_d *p, + const char *val) +{ + if (p->value) + free(p->value); + if (!val) { + p->value = NULL; + return 0; } + p->value = strdup(val); + return 0; +} - if (param->value) - free(param->value); +static char *param_get_generic(struct device_d *dev, struct param_d *p) +{ + return p->value; +} - param->value = strdup(val); - return 0; +static struct param_d *__dev_add_param(struct device_d *dev, char *name, + int (*set)(struct device_d *dev, struct param_d *p, const char *val), + char *(*get)(struct device_d *dev, struct param_d *p), + unsigned long flags) +{ + struct param_d *param; + + param = xzalloc(sizeof(*param)); + + if (set) + param->set = set; + else + param->set = dev_param_set_generic; + if (get) + param->get = get; + else + param->get = param_get_generic; + + param->name = strdup(name); + param->flags = flags; + list_add_tail(¶m->list, &dev->parameters); + + return param; } -int dev_add_param(struct device_d *dev, struct param_d *newparam) +/** + * dev_add_param - add a parameter to a device + * @param dev The device + * @param name The name of the parameter + * @param set setter function for the parameter + * @param get getter function for the parameter + * @param flags + * + * This function adds a new parameter to a device. The get/set functions can + * be zero in which case the generic functions are used. The generic functions + * expect the parameter value to be a string which can be freed with free(). Do + * not use static arrays when using the generic functions. + */ +int dev_add_param(struct device_d *dev, char *name, + int (*set)(struct device_d *dev, struct param_d *p, const char *val), + char *(*get)(struct device_d *dev, struct param_d *param), + unsigned long flags) { - struct param_d *param = dev->param; + struct param_d *param; - newparam->next = NULL; + param = __dev_add_param(dev, name, set, get, flags); - if (param) { - while (param->next) - param = param->next; - param->next = newparam; - } else { - dev->param = newparam; - } + return param ? 0 : -EINVAL; +} + +/** + * dev_add_param_fixed - add a readonly parameter to a device + * @param dev The device + * @param name The name of the parameter + * @param value The value of the parameter + */ +int dev_add_param_fixed(struct device_d *dev, char *name, char *value) +{ + struct param_d *param; + + param = __dev_add_param(dev, name, NULL, NULL, PARAM_FLAG_RO); + if (!param) + return -EINVAL; + + param->value = strdup(value); return 0; } +/** + * dev_remove_parameters - remove all parameters from a device and free their + * memory + * @param dev The device + */ +void dev_remove_parameters(struct device_d *dev) +{ + struct param_d *p, *n; + + list_for_each_entry_safe(p, n, &dev->parameters, list) { + p->set(dev, p, NULL); + list_del(&p->list); + free(p); + } +} + /** @page dev_params Device parameters @section params_devices Devices can have several parameters. @@ -145,50 +242,6 @@ IP address of the first ethernet device is a matter of typing devices currently present. If called with a device id as parameter it shows the parameters available for a device. -@section params_programming Device parameters programming API - -@code -struct param_d { - char* (*get)(struct device_d *, struct param_d *param); - int (*set)(struct device_d *, struct param_d *param, const char *val); - ulong flags; - char *name; - struct param_d *next; - char *value; -}; -@endcode - -@code -int dev_add_param(struct device_d *dev, struct param_d *newparam); -@endcode - -This function adds a new parameter to a device. At least the name field in -the new parameter struct has to be initialized. The 'get' and 'set' fields -can be set to NULL in which case the framework handles them. It is also -allowed to implement only one of the get/set functions. Care must be taken -with the initial value of the parameter. If the framework handles the set -function it will try to free the value of the parameter. If this is a -static array bad things will happen. A parameter can have the flag -PARAM_FLAG_RO which means that the parameter is readonly. It is perfectly ok -then to point the value to a static array. - -@code -const char *dev_get_param(struct device_d *dev, const char *name); -@endcode - -This function returns a pointer to the value of the parameter specified -with dev and name. -If the framework handles the get/set functions the parameter value strings -are alloceted with malloc and freed with free when another value is set for -this parameter. Drivers implementing set/get themselves are allowed to -return values in static arrays. This means that the pointers returned from -dev_get_param() are only valid until the next call to dev_get_param. If this -is not long enough strdup() or similar must be used. - -@code -int dev_set_param(struct device_d *dev, const char *name, const char *val); -@endcode - -Set the value of a parameter. +See the individual functions for parameter programming. */ diff --git a/net/eth.c b/net/eth.c index fc16233be3..4d58191214 100644 --- a/net/eth.c +++ b/net/eth.c @@ -102,11 +102,13 @@ static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const ch struct eth_device *edev = dev->type_data; char ethaddr[sizeof("xx:xx:xx:xx:xx:xx")]; + if (!val) + return dev_param_set_generic(dev, param, NULL); + if (string_to_ethaddr(val, ethaddr) < 0) return -EINVAL; - free(param->value); - param->value = strdup(val); + dev_param_set_generic(dev, param, val); edev->set_ethaddr(edev, ethaddr); @@ -121,11 +123,13 @@ static int eth_set_ipaddr(struct device_d *dev, struct param_d *param, const cha struct eth_device *edev = dev->type_data; IPaddr_t ip; + if (!val) + return dev_param_set_generic(dev, param, NULL); + if (string_to_ip(val, &ip)) return -EINVAL; - free(param->value); - param->value = strdup(val); + dev_param_set_generic(dev, param, val); if (edev == eth_current) net_update_env(); @@ -148,21 +152,11 @@ int eth_register(struct eth_device *edev) register_device(&edev->dev); dev->type_data = edev; - edev->param_ip.name = "ipaddr"; - edev->param_ip.set = ð_set_ipaddr; - edev->param_ethaddr.name = "ethaddr"; - edev->param_ethaddr.set = ð_set_ethaddr; - edev->param_gateway.name = "gateway"; - edev->param_gateway.set = ð_set_ipaddr; - edev->param_netmask.name = "netmask"; - edev->param_netmask.set = ð_set_ipaddr; - edev->param_serverip.name = "serverip"; - edev->param_serverip.set = ð_set_ipaddr; - dev_add_param(dev, &edev->param_ip); - dev_add_param(dev, &edev->param_ethaddr); - dev_add_param(dev, &edev->param_gateway); - dev_add_param(dev, &edev->param_netmask); - dev_add_param(dev, &edev->param_serverip); + dev_add_param(dev, "ipaddr", eth_set_ipaddr, NULL, 0); + dev_add_param(dev, "ethaddr", eth_set_ethaddr, NULL, 0); + dev_add_param(dev, "gateway", eth_set_ipaddr, NULL, 0); + dev_add_param(dev, "netmask", eth_set_ipaddr, NULL, 0); + dev_add_param(dev, "serverip", eth_set_ipaddr, NULL, 0); edev->init(edev); @@ -182,21 +176,7 @@ int eth_register(struct eth_device *edev) void eth_unregister(struct eth_device *edev) { - if (edev->param_ip.value) - free(edev->param_ip.value); - if (edev->param_ethaddr.value) - free(edev->param_ethaddr.value); - if (edev->param_gateway.value) - free(edev->param_gateway.value); - if (edev->param_netmask.value) - free(edev->param_netmask.value); - if (edev->param_serverip.value) - free(edev->param_serverip.value); - - if (eth_current == edev) { - eth_current->halt(eth_current); - eth_current = NULL; - } + dev_remove_parameters(&edev->dev); list_del(&edev->list); } -- cgit v1.2.3 From cd81aa6e3b9181ffdbd8d91770407fa5f9e47aee Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 8 Jun 2010 13:11:40 +0200 Subject: net: add dns support Signed-off-by: Sascha Hauer --- include/net.h | 11 +++ net/Kconfig | 4 + net/Makefile | 1 + net/dns.c | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 net/dns.c (limited to 'include') diff --git a/include/net.h b/include/net.h index 15106a7826..8db83d8309 100644 --- a/include/net.h +++ b/include/net.h @@ -274,6 +274,17 @@ int setenv_ip(const char *name, IPaddr_t ip); int string_to_ethaddr(const char *str, char *enetaddr); void ethaddr_to_string(const unsigned char *enetaddr, char *str); +#ifdef CONFIG_NET_RESOLV +IPaddr_t resolv(char *host); +#else +static inline IPaddr_t resolv(char *host) +{ + IPaddr_t ip = 0; + string_to_ip(host, &ip); + return ip; +} +#endif + /** * is_zero_ether_addr - Determine if give Ethernet address is all zeros. * @addr: Pointer to a six-byte array containing the Ethernet address diff --git a/net/Kconfig b/net/Kconfig index faf2c286c6..ff6e45523d 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -25,4 +25,8 @@ config NET_NETCONSOLE help This option adds support for a simple udp based network console. +config NET_RESOLV + bool + prompt "dns support" + endif diff --git a/net/Makefile b/net/Makefile index e42a484f2e..66dc564dac 100644 --- a/net/Makefile +++ b/net/Makefile @@ -4,4 +4,5 @@ obj-$(CONFIG_NET) += net.o obj-$(CONFIG_NET_NFS) += nfs.o obj-$(CONFIG_NET_TFTP) += tftp.o obj-$(CONFIG_NET_PING) += ping.o +obj-$(CONFIG_NET_RESOLV)+= dns.o obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o diff --git a/net/dns.c b/net/dns.c new file mode 100644 index 0000000000..1ee270b678 --- /dev/null +++ b/net/dns.c @@ -0,0 +1,264 @@ +/* + * DNS support driver + * + * Copyright (c) 2008 Pieter Voorthuijsen + * Copyright (c) 2009 Robin Getz + * + * This is a simple DNS implementation for U-Boot. It will use the first IP + * in the DNS response as NetServerIP. This can then be used for any other + * network related activities. + * + * The packet handling is partly based on TADNS, original copyrights + * follow below. + * + */ + +/* + * Copyright (c) 2004-2005 Sergey Lyubka + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Sergey Lyubka wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. + */ +//#define DEBUG +#include +#include +#include +#include +#include +#include + +#define DNS_PORT 53 + +/* http://en.wikipedia.org/wiki/List_of_DNS_record_types */ +enum dns_query_type { + DNS_A_RECORD = 0x01, + DNS_CNAME_RECORD = 0x05, + DNS_MX_RECORD = 0x0f, +}; + +/* + * DNS network packet + */ +struct header { + uint16_t tid; /* Transaction ID */ + uint16_t flags; /* Flags */ + uint16_t nqueries; /* Questions */ + uint16_t nanswers; /* Answers */ + uint16_t nauth; /* Authority PRs */ + uint16_t nother; /* Other PRs */ + unsigned char data[1]; /* Data, variable length */ +}; + +#define STATE_INIT 0 +#define STATE_DONE 1 + +static struct net_connection *dns_con; +static uint64_t dns_timer_start; +static int dns_state; +static IPaddr_t dns_ip; + +static int dns_send(char *name) +{ + int ret; + struct header *header; + enum dns_query_type qtype = DNS_A_RECORD; + unsigned char *packet = net_udp_get_payload(dns_con); + unsigned char *p, *s, *fullname, *dotptr; + const unsigned char *domain; + + /* Prepare DNS packet header */ + header = (struct header *)packet; + header->tid = 1; + header->flags = htons(0x100); /* standard query */ + header->nqueries = htons(1); /* Just one query */ + header->nanswers = 0; + header->nauth = 0; + header->nother = 0; + + domain = getenv("domainname"); + + if (!strchr(name, '.') && domain && *domain) + fullname = asprintf(".%s.%s.", name, domain); + else + fullname = asprintf(".%s.", name); + + /* replace dots in fullname with chunk len */ + dotptr = fullname; + do { + int len; + + s = strchr(dotptr + 1, '.'); + + len = s - dotptr - 1; + + *dotptr = len; + dotptr = s; + } while (*(dotptr + 1)); + *dotptr = 0; +//memory_display(fullname, 0, strlen(fullname), 1); + strcpy(header->data, fullname); + + p = header->data + strlen(fullname); + + *p++ = 0; /* Mark end of host name */ + *p++ = 0; /* Some servers require double null */ + *p++ = (unsigned char)qtype; /* Query Type */ + + *p++ = 0; + *p++ = 1; /* Class: inet, 0x0001 */ + + ret = net_udp_send(dns_con, p - packet); + + free(fullname); + + return ret; +} + +static void dns_handler(char *packet, unsigned len) +{ + struct header *header; + unsigned char *p, *e, *s; + u16 type; + int found, stop, dlen; + short tmp; + + debug("%s\n", __func__); + + /* We sent 1 query. We want to see more that 1 answer. */ + header = (struct header *)net_eth_to_udp_payload(packet);; + if (ntohs(header->nqueries) != 1) + return; + + /* Received 0 answers */ + if (header->nanswers == 0) { + dns_state = STATE_DONE; + debug("DNS server returned no answers\n"); + return; + } + + /* Skip host name */ + s = &header->data[0]; + e = packet + len; + for (p = s; p < e && *p != '\0'; p++) + continue; + + /* We sent query class 1, query type 1 */ + tmp = p[1] | (p[2] << 8); + if (&p[5] > e || ntohs(tmp) != DNS_A_RECORD) { + debug("DNS response was not A record\n"); + return; + } + + /* Go to the first answer section */ + p += 5; + + /* Loop through the answers, we want A type answer */ + for (found = stop = 0; !stop && &p[12] < e; ) { + + /* Skip possible name in CNAME answer */ + if (*p != 0xc0) { + while (*p && &p[12] < e) + p++; + p--; + } + debug("Name (Offset in header): %d\n", p[1]); + + tmp = p[2] | (p[3] << 8); + type = ntohs(tmp); + debug("type = %d\n", type); + if (type == DNS_CNAME_RECORD) { + /* CNAME answer. shift to the next section */ + debug("Found canonical name\n"); + tmp = p[10] | (p[11] << 8); + dlen = ntohs(tmp); + debug("dlen = %d\n", dlen); + p += 12 + dlen; + } else if (type == DNS_A_RECORD) { + debug("Found A-record\n"); + found = stop = 1; + } else { + debug("Unknown type\n"); + stop = 1; + } + } + + if (found && &p[12] < e) { + + tmp = p[10] | (p[11] << 8); + dlen = ntohs(tmp); + p += 12; + dns_ip = net_read_ip(p); + dns_state = STATE_DONE; + } +} + +IPaddr_t resolv(char *host) +{ + IPaddr_t ip; + + if (!string_to_ip(host, &ip)) + return ip; + + dns_ip = 0; + + dns_state = STATE_INIT; + + ip = getenv_ip("nameserver"); + if (!ip) + return 0; + + debug("resolving host %s via nameserver %s\n", host, getenv("nameserver")); + + dns_con = net_udp_new(ip, DNS_PORT, dns_handler); + if (IS_ERR(dns_con)) + return PTR_ERR(dns_con); + dns_timer_start = get_time_ns(); + dns_send(host); + + while (dns_state != STATE_DONE) { + if (ctrlc()) { + break; + } + net_poll(); + if (is_timeout(dns_timer_start, SECOND)) { + dns_timer_start = get_time_ns(); + printf("T "); + dns_send(host); + } + } + + net_unregister(dns_con); + + return dns_ip; +} + +static int do_host(struct command *cmdtp, int argc, char *argv[]) +{ + IPaddr_t ip; + + if (argc != 2) + return COMMAND_ERROR_USAGE; + + ip = resolv(argv[1]); + if (!ip) + printf("unknown host %s\n", argv[1]); + else { + printf("%s is at ", argv[1]); + print_IPaddr(ip); + printf("\n"); + } + + return 0; +} + +static const __maybe_unused char cmd_host_help[] = +"Usage: host \n"; + +BAREBOX_CMD_START(host) + .cmd = do_host, + .usage = "resolve a hostname", + BAREBOX_CMD_HELP(cmd_host_help) +BAREBOX_CMD_END + -- cgit v1.2.3 From 738d70e430b0f4cb9ac71d2811b3f6a4c74abbf6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 11 Jun 2010 14:10:36 +0200 Subject: include support for a simple pseudo number generator Signed-off-by: Sascha Hauer --- include/net.h | 1 + include/stdlib.h | 16 ++++++++++++++++ lib/Makefile | 1 + lib/random.c | 26 ++++++++++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 include/stdlib.h create mode 100644 lib/random.c (limited to 'include') diff --git a/include/net.h b/include/net.h index 8db83d8309..709e76c895 100644 --- a/include/net.h +++ b/include/net.h @@ -16,6 +16,7 @@ #include #include #include +#include #include /* for nton* / ntoh* stuff */ diff --git a/include/stdlib.h b/include/stdlib.h new file mode 100644 index 0000000000..dc720132e8 --- /dev/null +++ b/include/stdlib.h @@ -0,0 +1,16 @@ +#ifndef __STDLIB_H +#define __STDLIB_H + +#define RAND_MAX 32767 + +/* return a pseudo-random integer in the range [0, RAND_MAX] */ +unsigned int rand(void); + +/* set the seed for rand () */ +void srand(unsigned int seed); + +/* fill a buffer with pseudo-random data */ +void get_random_bytes(char *buf, int len); + + +#endif /* __STDLIB_H */ diff --git a/lib/Makefile b/lib/Makefile index b072fb6bea..4a33aaa3c0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o obj-y += glob.o obj-y += notifier.o obj-y += copy_file.o +obj-y += random.o obj-y += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o diff --git a/lib/random.c b/lib/random.c new file mode 100644 index 0000000000..352d6bf3f7 --- /dev/null +++ b/lib/random.c @@ -0,0 +1,26 @@ +#include +#include + +static unsigned int random_seed; + +#if RAND_MAX > 32767 +#error this rand implementation is for RAND_MAX < 32678 only. +#endif + +unsigned int rand(void) +{ + random_seed = random_seed * 1103515245 + 12345; + return (random_seed / 65536) % (RAND_MAX + 1); +} + +void srand(unsigned int seed) +{ + random_seed = seed; +} + +void get_random_bytes(char *buf, int len) +{ + while (len--) + *buf++ = rand() % 256; +} + -- cgit v1.2.3 From 7867ceb8dc5c4d2c64d337aa130c57a05d9b556a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 11 Jun 2010 14:11:12 +0200 Subject: net: implement random_ether_addr Signed-off-by: Sascha Hauer --- include/net.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include') diff --git a/include/net.h b/include/net.h index 709e76c895..c695e5f72a 100644 --- a/include/net.h +++ b/include/net.h @@ -17,6 +17,7 @@ #include #include #include +#include #include /* for nton* / ntoh* stuff */ @@ -331,6 +332,21 @@ static inline int is_broadcast_ether_addr(const u8 *addr) return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; } +/** + * random_ether_addr - Generate software assigned random Ethernet address + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Generate a random Ethernet address (MAC) that is not multicast + * and has the local assigned bit set. + */ +static inline void random_ether_addr(u8 *addr) +{ + srand(get_time_ns()); + get_random_bytes(addr, 6); + addr [0] &= 0xfe; /* clear multicast bit */ + addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ +} + /** * is_valid_ether_addr - Determine if the given Ethernet address is valid * @addr: Pointer to a six-byte array containing the Ethernet address -- cgit v1.2.3 From 322bace5fb422fb4f8f22a119856877a3ad6c78e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 21 Jun 2010 12:11:23 +0200 Subject: usbnet: remove unused dev member in struct usbnet Signed-off-by: Sascha Hauer --- drivers/net/usb/asix.c | 12 ++++++------ drivers/net/usb/usbnet.c | 9 +++++---- include/usb/usbnet.h | 2 -- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index fc4146fdbc..ca71b34e12 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -415,13 +415,13 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len) while (len > 0) { if ((short)(header & 0x0000ffff) != ~((short)((header & 0xffff0000) >> 16))) - dev_err(&dev->dev, "asix_rx_fixup() Bad Header Length"); - + dev_err(&dev->edev.dev, "asix_rx_fixup() Bad Header Length"); + /* get the packet length */ size = (unsigned short) (header & 0x0000ffff); if (size > 1514) { - dev_err(&dev->dev, "asix_rx_fixup() Bad RX Length %d", size); + dev_err(&dev->edev.dev, "asix_rx_fixup() Bad RX Length %d", size); return 0; } @@ -440,7 +440,7 @@ static int asix_rx_fixup(struct usbnet *dev, void *buf, int len) } if (len < 0) { - dev_err(&dev->dev,"asix_rx_fixup() Bad SKB Length %d", len); + dev_err(&dev->edev.dev,"asix_rx_fixup() Bad SKB Length %d", len); return -1; } return 0; @@ -503,13 +503,13 @@ static int ax88172_bind(struct usbnet *dev) unsigned long gpio_bits = dev->driver_info->data; struct asix_data *data = (struct asix_data *)&dev->data; - dev_dbg(&dev->dev, "%s\n", __func__); + dev_dbg(&dev->edev.dev, "%s\n", __func__); data->eeprom_len = AX88172_EEPROM_LEN; ret = usbnet_get_endpoints(dev); if (ret) { - dev_err(&dev->dev, "can not get EPs\n"); + dev_err(&dev->edev.dev, "can not get EPs\n"); return ret; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index b0e309096a..cc170f6611 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -74,7 +74,7 @@ int usbnet_get_endpoints(struct usbnet *dev) in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); dev->out = usb_sndbulkpipe (dev->udev, out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - dev_dbg(&dev->dev, "found endpoints: IN=%d OUT=%d\n", + dev_dbg(&dev->edev.dev, "found endpoints: IN=%d OUT=%d\n", in->bEndpointAddress, out->bEndpointAddress); return 0; @@ -89,14 +89,14 @@ static int usbnet_send(struct eth_device *edev, void *eth_data, int data_length) struct driver_info *info = dev->driver_info; int len, alen, ret; - dev_dbg(&dev->dev, "%s\n",__func__); + dev_dbg(&edev->dev, "%s\n",__func__); /* some devices want funky USB-level framing, for * win32 driver (usually) and/or hardware quirks */ if(info->tx_fixup) { if(info->tx_fixup(dev, eth_data, data_length, tx_buffer, &len)) { - dev_dbg(&dev->dev, "can't tx_fixup packet"); + dev_dbg(&edev->dev, "can't tx_fixup packet"); return 0; } } else { @@ -191,7 +191,7 @@ int usbnet_probe(struct usb_device *usbdev, const struct usb_device_id *prod) struct driver_info *info; int status; - dev_dbg(&edev->dev, "%s\n", __func__); + dev_dbg(&usbdev->dev, "%s\n", __func__); undev = xzalloc(sizeof (*undev)); @@ -206,6 +206,7 @@ int usbnet_probe(struct usb_device *usbdev, const struct usb_device_id *prod) edev->recv = usbnet_recv, edev->halt = usbnet_halt, edev->priv = undev; + edev->dev = usbdev->dev; /* will be overwritten by eth_register */ info = (struct driver_info *)prod->driver_info; undev->driver_info = info; diff --git a/include/usb/usbnet.h b/include/usb/usbnet.h index 77f19603c2..e3ea373d95 100644 --- a/include/usb/usbnet.h +++ b/include/usb/usbnet.h @@ -54,8 +54,6 @@ struct usbnet { # define EVENT_RX_MEMORY 2 # define EVENT_STS_SPLIT 3 # define EVENT_LINK_RESET 4 - /* FIXME: Our eth_device should have this, not us! */ - struct device_d dev; }; #if 0 -- cgit v1.2.3 From 112d65d3d2bde37529e61d6ad3011c39a1f65589 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 22 Jun 2010 16:26:35 +0200 Subject: fb: add a usage counter to prevent double enable/disable Signed-off-by: Sascha Hauer --- drivers/video/fb.c | 5 +++++ include/fb.h | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 841c3afe9e..f9a425efac 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -39,6 +39,9 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param, enable = simple_strtoul(val, NULL, 0); + if (info->enabled == !!enable) + return 0; + if (enable) { info->fbops->fb_enable(info); new = "1"; @@ -49,6 +52,8 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param, dev_param_set_generic(dev, param, new); + info->enabled = !!enable; + return 0; } diff --git a/include/fb.h b/include/fb.h index 218500b985..379f931e9c 100644 --- a/include/fb.h +++ b/include/fb.h @@ -96,7 +96,9 @@ struct fb_info { struct fb_bitfield red; /* bitfield in fb mem if true color, */ struct fb_bitfield green; /* else only length is significant */ struct fb_bitfield blue; - struct fb_bitfield transp; /* transparency */ + struct fb_bitfield transp; /* transparency */ + + int enabled; }; int register_framebuffer(struct fb_info *info); -- cgit v1.2.3 From 57b56a989fb0071382832c9e7263e48057314e6c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 23 Jun 2010 15:29:44 +0200 Subject: ehci: Make has_tt configurable via platform data Signed-off-by: Sascha Hauer --- drivers/usb/usb_ehci_core.c | 18 ++++++++++++------ include/usb/ehci.h | 10 ++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 include/usb/ehci.h (limited to 'include') diff --git a/drivers/usb/usb_ehci_core.c b/drivers/usb/usb_ehci_core.c index d7efaadb8c..f3611cda2f 100644 --- a/drivers/usb/usb_ehci_core.c +++ b/drivers/usb/usb_ehci_core.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "usb_ehci.h" @@ -43,6 +44,7 @@ struct ehci_priv { struct QH *qh_list; void *qhp; int portreset; + unsigned long flags; }; #define to_ehci(ptr) container_of(ptr, struct ehci_priv, host) @@ -112,13 +114,8 @@ static struct descriptor { 255 /* bInterval */ }, }; -#define CONFIG_EHCI_IS_TDI // FIXME -#if defined(CONFIG_EHCI_IS_TDI) -#define ehci_is_TDI() (1) -#else -#define ehci_is_TDI() (0) -#endif +#define ehci_is_TDI() (ehci->flags & EHCI_HAS_TT) #ifdef CONFIG_MMU /* @@ -861,10 +858,19 @@ static int ehci_probe(struct device_d *dev) struct usb_host *host; struct ehci_priv *ehci; uint32_t reg; + struct ehci_platform_data *pdata = dev->platform_data; ehci = xmalloc(sizeof(struct ehci_priv)); host = &ehci->host; + if (pdata) + ehci->flags = pdata->flags; + else + /* default to EHCI_HAS_TT to not change behaviour of boards + * with platform_data + */ + ehci->flags = EHCI_HAS_TT; + host->init = ehci_init; host->submit_int_msg = submit_int_msg; host->submit_control_msg = submit_control_msg; diff --git a/include/usb/ehci.h b/include/usb/ehci.h new file mode 100644 index 0000000000..3304b60279 --- /dev/null +++ b/include/usb/ehci.h @@ -0,0 +1,10 @@ +#ifndef __USB_EHCI_H +#define __USB_EHCI_H + +#define EHCI_HAS_TT (1 << 0) + +struct ehci_platform_data { + unsigned long flags; +}; + +#endif /* __USB_EHCI_H */ -- cgit v1.2.3 From 257da5cac07854c89861de5925475b339e8ff71b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 14 Jun 2010 22:31:04 +0200 Subject: add progression bar function Signed-off-by: Sascha Hauer --- include/progress.h | 15 +++++++++++++ lib/Makefile | 1 + lib/show_progress.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 include/progress.h create mode 100644 lib/show_progress.c (limited to 'include') diff --git a/include/progress.h b/include/progress.h new file mode 100644 index 0000000000..5c4dd1e775 --- /dev/null +++ b/include/progress.h @@ -0,0 +1,15 @@ +#ifndef __PROGRSS_H +#define __PROGRSS_H + +/* Initialize a progress bar. If max > 0 a one line progress + * bar is printed where 'max' corresponds to 100%. If max == 0 + * a multi line progress bar is printed. + */ +void init_progression_bar(int max); + +/* update a progress bar to a new value. If now < 0 then a + * spinner is printed. + */ +void show_progress(int now); + +#endif /* __PROGRSS_H */ diff --git a/lib/Makefile b/lib/Makefile index 4a33aaa3c0..5afbf132aa 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -30,5 +30,6 @@ obj-y += notifier.o obj-y += copy_file.o obj-y += random.o obj-y += lzo/ +obj-y += show_progress.o obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o diff --git a/lib/show_progress.c b/lib/show_progress.c new file mode 100644 index 0000000000..333f49868a --- /dev/null +++ b/lib/show_progress.c @@ -0,0 +1,62 @@ +/* + * show_progress.c - simple progress bar functions + * + * Copyright (c) 2010 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define HASHES_PER_LINE 65 + +static int printed; +static int progress_max; +static int spin; + +void show_progress(int now) +{ + char spinchr[] = "\\|/-"; + + if (now < 0) { + printf("%c\b", spinchr[spin++ % (sizeof(spinchr) - 1)]); + return; + } + + if (progress_max) + now = now * HASHES_PER_LINE / progress_max; + + while (printed < now) { + if (!(printed % HASHES_PER_LINE) && printed) + printf("\n\t"); + printf("#"); + printed++; + } +} + +void init_progression_bar(int max) +{ + printed = 0; + progress_max = max; + spin = 0; + if (progress_max) + printf("\t[%65s]\r\t[", ""); + else + printf("\t"); +} + -- cgit v1.2.3