2 * Copyright (c) 2015 National Instruments
5 * Joe Hershberger <joe.hershberger@ni.com>
7 * SPDX-License-Identifier: GPL-2.0
10 #include <asm/eth-raw-os.h>
16 DECLARE_GLOBAL_DATA_PTR
;
19 static struct in_addr arp_ip
;
21 static int sb_eth_raw_start(struct udevice
*dev
)
23 struct eth_sandbox_raw_priv
*priv
= dev_get_priv(dev
);
24 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
25 const char *interface
;
27 debug("eth_sandbox_raw: Start\n");
29 interface
= fdt_getprop(gd
->fdt_blob
, dev_of_offset(dev
),
30 "host-raw-interface", NULL
);
31 if (interface
== NULL
)
34 if (strcmp(interface
, "lo") == 0) {
36 env_set("ipaddr", "127.0.0.1");
37 env_set("serverip", "127.0.0.1");
39 return sandbox_eth_raw_os_start(interface
, pdata
->enetaddr
, priv
);
42 static int sb_eth_raw_send(struct udevice
*dev
, void *packet
, int length
)
44 struct eth_sandbox_raw_priv
*priv
= dev_get_priv(dev
);
46 debug("eth_sandbox_raw: Send packet %d\n", length
);
49 struct ethernet_hdr
*eth
= packet
;
51 if (ntohs(eth
->et_protlen
) == PROT_ARP
) {
52 struct arp_hdr
*arp
= packet
+ ETHER_HDR_SIZE
;
55 * localhost works on a higher-level API in Linux than
56 * ARP packets, so fake it
58 arp_ip
= net_read_ip(&arp
->ar_tpa
);
62 packet
+= ETHER_HDR_SIZE
;
63 length
-= ETHER_HDR_SIZE
;
65 return sandbox_eth_raw_os_send(packet
, length
, priv
);
68 static int sb_eth_raw_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
70 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
71 struct eth_sandbox_raw_priv
*priv
= dev_get_priv(dev
);
76 struct arp_hdr
*arp
= (void *)net_rx_packets
[0] +
80 * Fake an ARP response. The u-boot network stack is sending an
81 * ARP request (to find the MAC address to address the actual
82 * packet to) and requires an ARP response to continue. Since
83 * this is the localhost interface, there is no Etherent level
84 * traffic at all, so there is no way to send an ARP request or
85 * to get a response. For this reason we fake the response to
86 * make the u-boot network stack happy.
88 arp
->ar_hrd
= htons(ARP_ETHER
);
89 arp
->ar_pro
= htons(PROT_IP
);
90 arp
->ar_hln
= ARP_HLEN
;
91 arp
->ar_pln
= ARP_PLEN
;
92 arp
->ar_op
= htons(ARPOP_REPLY
);
93 /* Any non-zero MAC address will work */
94 memset(&arp
->ar_sha
, 0x01, ARP_HLEN
);
95 /* Use whatever IP we were looking for (always 127.0.0.1?) */
96 net_write_ip(&arp
->ar_spa
, arp_ip
);
97 memcpy(&arp
->ar_tha
, pdata
->enetaddr
, ARP_HLEN
);
98 net_write_ip(&arp
->ar_tpa
, net_ip
);
99 length
= ARP_HDR_SIZE
;
101 /* If local, the Ethernet header won't be included; skip it */
102 uchar
*pktptr
= priv
->local
?
103 net_rx_packets
[0] + ETHER_HDR_SIZE
: net_rx_packets
[0];
105 retval
= sandbox_eth_raw_os_recv(pktptr
, &length
, priv
);
108 if (!retval
&& length
) {
110 struct ethernet_hdr
*eth
= (void *)net_rx_packets
[0];
112 /* Fill in enough of the missing Ethernet header */
113 memcpy(eth
->et_dest
, pdata
->enetaddr
, ARP_HLEN
);
114 memset(eth
->et_src
, 0x01, ARP_HLEN
);
115 eth
->et_protlen
= htons(reply_arp
? PROT_ARP
: PROT_IP
);
117 length
+= ETHER_HDR_SIZE
;
120 debug("eth_sandbox_raw: received packet %d\n",
122 *packetp
= net_rx_packets
[0];
128 static void sb_eth_raw_stop(struct udevice
*dev
)
130 struct eth_sandbox_raw_priv
*priv
= dev_get_priv(dev
);
132 debug("eth_sandbox_raw: Stop\n");
134 sandbox_eth_raw_os_stop(priv
);
137 static const struct eth_ops sb_eth_raw_ops
= {
138 .start
= sb_eth_raw_start
,
139 .send
= sb_eth_raw_send
,
140 .recv
= sb_eth_raw_recv
,
141 .stop
= sb_eth_raw_stop
,
144 static int sb_eth_raw_ofdata_to_platdata(struct udevice
*dev
)
146 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
148 pdata
->iobase
= devfdt_get_addr(dev
);
152 static const struct udevice_id sb_eth_raw_ids
[] = {
153 { .compatible
= "sandbox,eth-raw" },
157 U_BOOT_DRIVER(eth_sandbox_raw
) = {
158 .name
= "eth_sandbox_raw",
160 .of_match
= sb_eth_raw_ids
,
161 .ofdata_to_platdata
= sb_eth_raw_ofdata_to_platdata
,
162 .ops
= &sb_eth_raw_ops
,
163 .priv_auto_alloc_size
= sizeof(struct eth_sandbox_raw_priv
),
164 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),