net: sun8i_emac: Retrieve GMAC clock via 'syscon' phandle
[oweals/u-boot.git] / drivers / net / sandbox.c
index 9c0e0d009ea25c232f66904fb6a2cf70b683762a..decce2fa59c4c5c670b6db9c2bbecd761bbbb5ca 100644 (file)
@@ -160,6 +160,98 @@ int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet,
        return 0;
 }
 
+/*
+ * sandbox_eth_recv_arp_req()
+ *
+ * Inject an ARP request for this target
+ *
+ * returns 0 if injected, -EOVERFLOW if not
+ */
+int sandbox_eth_recv_arp_req(struct udevice *dev)
+{
+       struct eth_sandbox_priv *priv = dev_get_priv(dev);
+       struct ethernet_hdr *eth_recv;
+       struct arp_hdr *arp_recv;
+
+       /* Don't allow the buffer to overrun */
+       if (priv->recv_packets >= PKTBUFSRX)
+               return -EOVERFLOW;
+
+       /* Formulate a fake request */
+       eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+       memcpy(eth_recv->et_dest, net_bcast_ethaddr, ARP_HLEN);
+       memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+       eth_recv->et_protlen = htons(PROT_ARP);
+
+       arp_recv = (void *)eth_recv + ETHER_HDR_SIZE;
+       arp_recv->ar_hrd = htons(ARP_ETHER);
+       arp_recv->ar_pro = htons(PROT_IP);
+       arp_recv->ar_hln = ARP_HLEN;
+       arp_recv->ar_pln = ARP_PLEN;
+       arp_recv->ar_op = htons(ARPOP_REQUEST);
+       memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN);
+       net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+       memcpy(&arp_recv->ar_tha, net_null_ethaddr, ARP_HLEN);
+       net_write_ip(&arp_recv->ar_tpa, net_ip);
+
+       priv->recv_packet_length[priv->recv_packets] =
+               ETHER_HDR_SIZE + ARP_HDR_SIZE;
+       ++priv->recv_packets;
+
+       return 0;
+}
+
+/*
+ * sandbox_eth_recv_ping_req()
+ *
+ * Inject a ping request for this target
+ *
+ * returns 0 if injected, -EOVERFLOW if not
+ */
+int sandbox_eth_recv_ping_req(struct udevice *dev)
+{
+       struct eth_sandbox_priv *priv = dev_get_priv(dev);
+       struct ethernet_hdr *eth_recv;
+       struct ip_udp_hdr *ipr;
+       struct icmp_hdr *icmpr;
+
+       /* Don't allow the buffer to overrun */
+       if (priv->recv_packets >= PKTBUFSRX)
+               return -EOVERFLOW;
+
+       /* Formulate a fake ping */
+       eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+
+       memcpy(eth_recv->et_dest, net_ethaddr, ARP_HLEN);
+       memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+       eth_recv->et_protlen = htons(PROT_IP);
+
+       ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+       ipr->ip_hl_v = 0x45;
+       ipr->ip_len = htons(IP_ICMP_HDR_SIZE);
+       ipr->ip_off = htons(IP_FLAGS_DFRAG);
+       ipr->ip_p = IPPROTO_ICMP;
+       ipr->ip_sum = 0;
+       net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr);
+       net_write_ip(&ipr->ip_dst, net_ip);
+       ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+
+       icmpr = (struct icmp_hdr *)&ipr->udp_src;
+
+       icmpr->type = ICMP_ECHO_REQUEST;
+       icmpr->code = 0;
+       icmpr->checksum = 0;
+       icmpr->un.echo.id = 0;
+       icmpr->un.echo.sequence = htons(1);
+       icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE);
+
+       priv->recv_packet_length[priv->recv_packets] =
+               ETHER_HDR_SIZE + IP_ICMP_HDR_SIZE;
+       ++priv->recv_packets;
+
+       return 0;
+}
+
 /*
  * sb_default_handler()
  *
@@ -206,6 +298,26 @@ void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler)
                priv->tx_handler = sb_default_handler;
 }
 
+/*
+ * Set priv ptr
+ *
+ * priv - priv void ptr to store in the device
+ */
+void sandbox_eth_set_priv(int index, void *priv)
+{
+       struct udevice *dev;
+       struct eth_sandbox_priv *dev_priv;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_ETH, index, &dev);
+       if (ret)
+               return;
+
+       dev_priv = dev_get_priv(dev);
+
+       dev_priv->priv = priv;
+}
+
 static int sb_eth_start(struct udevice *dev)
 {
        struct eth_sandbox_priv *priv = dev_get_priv(dev);