1 /* 2 * (C) Copyright 2004 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <command.h> 26 #include <stdio_dev.h> 27 #include <net.h> 28 29 DECLARE_GLOBAL_DATA_PTR; 30 31 static char input_buffer[512]; 32 static int input_size = 0; /* char count in input buffer */ 33 static int input_offset = 0; /* offset to valid chars in input buffer */ 34 static int input_recursion = 0; 35 static int output_recursion = 0; 36 static int net_timeout; 37 static uchar nc_ether[6]; /* server enet address */ 38 static IPaddr_t nc_ip; /* server ip */ 39 static short nc_port; /* source/target port */ 40 static const char *output_packet; /* used by first send udp */ 41 static int output_packet_len = 0; 42 43 static void nc_wait_arp_handler(uchar *pkt, unsigned dest, 44 IPaddr_t sip, unsigned src, 45 unsigned len) 46 { 47 NetState = NETLOOP_SUCCESS; /* got arp reply - quit net loop */ 48 } 49 50 static void nc_handler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, 51 unsigned len) 52 { 53 if (input_size) 54 NetState = NETLOOP_SUCCESS; /* got input - quit net loop */ 55 } 56 57 static void nc_timeout (void) 58 { 59 NetState = NETLOOP_SUCCESS; 60 } 61 62 void NcStart (void) 63 { 64 if (!output_packet_len || memcmp (nc_ether, NetEtherNullAddr, 6)) { 65 /* going to check for input packet */ 66 NetSetHandler (nc_handler); 67 NetSetTimeout (net_timeout, nc_timeout); 68 } else { 69 /* send arp request */ 70 uchar *pkt; 71 NetSetHandler (nc_wait_arp_handler); 72 pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE; 73 memcpy (pkt, output_packet, output_packet_len); 74 NetSendUDPPacket (nc_ether, nc_ip, nc_port, nc_port, output_packet_len); 75 } 76 } 77 78 int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len) 79 { 80 int end, chunk; 81 82 if (dest != nc_port || !len) 83 return 0; /* not for us */ 84 85 if (input_size == sizeof input_buffer) 86 return 1; /* no space */ 87 if (len > sizeof input_buffer - input_size) 88 len = sizeof input_buffer - input_size; 89 90 end = input_offset + input_size; 91 if (end > sizeof input_buffer) 92 end -= sizeof input_buffer; 93 94 chunk = len; 95 if (end + len > sizeof input_buffer) { 96 chunk = sizeof input_buffer - end; 97 memcpy(input_buffer, pkt + chunk, len - chunk); 98 } 99 memcpy (input_buffer + end, pkt, chunk); 100 101 input_size += len; 102 103 return 1; 104 } 105 106 static void nc_send_packet (const char *buf, int len) 107 { 108 struct eth_device *eth; 109 int inited = 0; 110 uchar *pkt; 111 uchar *ether; 112 IPaddr_t ip; 113 114 if ((eth = eth_get_dev ()) == NULL) { 115 return; 116 } 117 118 if (!memcmp (nc_ether, NetEtherNullAddr, 6)) { 119 if (eth->state == ETH_STATE_ACTIVE) 120 return; /* inside net loop */ 121 output_packet = buf; 122 output_packet_len = len; 123 NetLoop (NETCONS); /* wait for arp reply and send packet */ 124 output_packet_len = 0; 125 return; 126 } 127 128 if (eth->state != ETH_STATE_ACTIVE) { 129 if (eth_init (gd->bd) < 0) 130 return; 131 inited = 1; 132 } 133 pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE; 134 memcpy (pkt, buf, len); 135 ether = nc_ether; 136 ip = nc_ip; 137 NetSendUDPPacket (ether, ip, nc_port, nc_port, len); 138 139 if (inited) 140 eth_halt (); 141 } 142 143 static int nc_start(void) 144 { 145 int netmask, our_ip; 146 147 nc_port = 6666; /* default port */ 148 149 if (getenv ("ncip")) { 150 char *p; 151 152 nc_ip = getenv_IPaddr ("ncip"); 153 if (!nc_ip) 154 return -1; /* ncip is 0.0.0.0 */ 155 if ((p = strchr (getenv ("ncip"), ':')) != NULL) 156 nc_port = simple_strtoul (p + 1, NULL, 10); 157 } else 158 nc_ip = ~0; /* ncip is not set */ 159 160 our_ip = getenv_IPaddr ("ipaddr"); 161 netmask = getenv_IPaddr ("netmask"); 162 163 if (nc_ip == ~0 || /* 255.255.255.255 */ 164 ((netmask & our_ip) == (netmask & nc_ip) && /* on the same net */ 165 (netmask | nc_ip) == ~0)) /* broadcast to our net */ 166 memset (nc_ether, 0xff, sizeof nc_ether); 167 else 168 memset (nc_ether, 0, sizeof nc_ether); /* force arp request */ 169 170 return 0; 171 } 172 173 static void nc_putc(char c) 174 { 175 if (output_recursion) 176 return; 177 output_recursion = 1; 178 179 nc_send_packet (&c, 1); 180 181 output_recursion = 0; 182 } 183 184 static void nc_puts(const char *s) 185 { 186 int len; 187 188 if (output_recursion) 189 return; 190 output_recursion = 1; 191 192 if ((len = strlen (s)) > 512) 193 len = 512; 194 195 nc_send_packet (s, len); 196 197 output_recursion = 0; 198 } 199 200 static int nc_getc(void) 201 { 202 uchar c; 203 204 input_recursion = 1; 205 206 net_timeout = 0; /* no timeout */ 207 while (!input_size) 208 NetLoop (NETCONS); 209 210 input_recursion = 0; 211 212 c = input_buffer[input_offset++]; 213 214 if (input_offset >= sizeof input_buffer) 215 input_offset -= sizeof input_buffer; 216 input_size--; 217 218 return c; 219 } 220 221 static int nc_tstc(void) 222 { 223 struct eth_device *eth; 224 225 if (input_recursion) 226 return 0; 227 228 if (input_size) 229 return 1; 230 231 eth = eth_get_dev (); 232 if (eth && eth->state == ETH_STATE_ACTIVE) 233 return 0; /* inside net loop */ 234 235 input_recursion = 1; 236 237 net_timeout = 1; 238 NetLoop (NETCONS); /* kind of poll */ 239 240 input_recursion = 0; 241 242 return input_size != 0; 243 } 244 245 int drv_nc_init (void) 246 { 247 struct stdio_dev dev; 248 int rc; 249 250 memset (&dev, 0, sizeof (dev)); 251 252 strcpy (dev.name, "nc"); 253 dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; 254 dev.start = nc_start; 255 dev.putc = nc_putc; 256 dev.puts = nc_puts; 257 dev.getc = nc_getc; 258 dev.tstc = nc_tstc; 259 260 rc = stdio_register (&dev); 261 262 return (rc == 0) ? 1 : rc; 263 } 264