📄 ethemu.c
字号:
/* dm9000.c: Version 1.2 12/15/2003 A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. Copyright (C) 1997 Sten Wang This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match 06/22/2001 Support DM9801 progrmming E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 R17 = (R17 & 0xfff0) | NF + 3 E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 R17 = (R17 & 0xfff0) | NFv1.00 modify by simon 2001.9.5 change for kernel 2.4.xv1.1 11/09/2001 fix force mode bugv1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>: Fixed phy reset. Added tx/rx 32 bit mode. Cleaned up for kernel merge.-------------------------------------- 12/15/2003 Initial port to u-boot by Sascha Hauer <saschahauer@web.de>TODO: Homerun NIC and longrun NIC are not functional, only internal at the moment.*///#include <common.h>#include "config.h"#include <types.h>#include <command.h>#include "net.h"#include <time.h>#include <printk.h>//#include <asm/io.h>#ifdef CONFIG_DRIVER_DM9000/* Board/System/Debug information/definition ---------------- *//* #define CONFIG_DM9000_DEBUG *///#define DM9000_DBG_T(fmt,args...) printk(__FUNCTION__"(): " fmt ,##args)//#define DM9000_DBG_D(fmt,args...) printk(fmt ,##args)#define DM9000_DBG_T(fmt,args...)#define DM9000_DBG_D(fmt,args...)#ifdef CONFIG_DM9000_DEBUG#define DM9000_DBG(fmt,args...) printk(__FUNCTION__"(): " fmt ,##args)#else /* */#define DM9000_DBG(fmt,args...)#endif /* *//* Structure/enum declaration ------------------------------- */typedef struct board_info { u32 runt_length_counter; /* counter: RX length < 64byte */ u32 long_length_counter; /* counter: RX length > 1514byte */ u32 reset_counter; /* counter: RESET */ u32 reset_tx_timeout; /* RESET caused by TX Timeout */ u32 reset_rx_status; /* RESET caused by RX Statsus wrong */ u16 tx_pkt_cnt; u16 queue_start_addr; u16 dbug_cnt; u8 phy_addr; u8 device_wait_reset; /* device state */ u8 nic_type; /* NIC type */ unsigned char srom[128];} board_info_t;board_info_t dmfe_info;int eeth_send(volatile void *packet, int length);/*************************************************************************************///// newwork emulator///*************************************************************************************/net_config default_net_config={ {0x00,0x01,0x5d,0x68,0x7a,0x0f}, 0x0101a8c0, 0x00ffffff, 0xde01a8c0, 0xFFFF,0xFFFF};IPaddr_t NetArpWaitReplyIP;//extern IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) *///extern IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */static rxhand_f *packetHandler; /* Current RX packet handler */static const uchar NetBcastAddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};static const uchar eNetOurEther[6] = {0x00,0x0c,0x76,0xab,0xcd,0xef};static const IPaddr_t eNetOurIP = 0x0501a8c0UL;static const IPaddr_t eNetOurSubnetMask = 0x00ffffffUL;static const IPaddr_t eNetOurGatewayIP = 0x0101a8c0UL;static IPaddr_t eNetArpWaitPacketIP,eNetArpWaitPacketMAC;static uchar NetTargetEther[6];static IPaddr_t NetTargetIP;#define NETBUFFSIZE (64*1024)static uchar txrxbuff[NETBUFFSIZE+16];static int tx,rx;void putc(uchar);/*static ushort ntohs(ushort ){ return ((>>8)|(<<8));}static ushort hston(ushort ){ return ((>>8)|(<<8));}*//*void ArpReply (void){ int i; volatile uchar *pkt; ARP_t *arp;#ifdef ET_DEBUG printk ("ARP broadcast %d\n", NetArpWaitTry);#endif pkt = NetTxPacket; pkt += eNetSetEther (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_REPLY); memcpy (&arp->ar_sha, eNetOurEther, 6); / * source ET addr * / NetWriteIP ((uchar *) & arp->ar_spa, eNetOurIP); / * source IP addr * / for (i = 0; i < 6; ++i) { arp->ar_tha[i] = 0; / * dest ET addr = 0 * / } if ((eNetArpWaitPacketIP & eNetOurSubnetMask) != (eNetOurIP & eNetOurSubnetMask)) { if (eNetOurGatewayIP == 0) { printk ("## Warning: gatewayip needed but not set\n"); } NetArpWaitReplyIP = eNetOurGatewayIP; } else { NetArpWaitReplyIP = eNetArpWaitPacketIP; } NetWriteIP ((uchar *) arp->ar_tpa, NetArpWaitReplyIP); (void) eeth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE);}*/inteNetSetEther(volatile uchar * xet, const uchar * addr, uint prot){ Ethernet_t *et = (Ethernet_t *)xet; memcpy (et->et_dest, addr, 6); memcpy (et->et_src, eNetOurEther, 6); et->et_protlen = htons(prot); return ETHER_HDR_SIZE;}static voidIcmp_Echo_Reply (volatile uchar * inpkt, int len){ uchar *pkt = (uchar *)inpkt; IP_t *ip; Ethernet_t *et; volatile ushort *s; ushort ip_id,sn; printk(__FUNCTION__"()\n"); et = (Ethernet_t *)inpkt; memcpy(NetTargetEther, et->et_src, 6); ip = (IP_t *)(inpkt + ETHER_HDR_SIZE); len -= ETHER_HDR_SIZE; NetTargetIP = NetReadIP(&ip->ip_src); ip_id = ip->ip_id; s = &ip->udp_src; /* XXX ICMP starts here */ sn = s[3]; /* sequence number */ pkt += eNetSetEther(pkt, NetTargetEther, PROT_IP); ip = (IP_t *)pkt; /* * Construct an IP and ICMP 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_NO_UDP + 8); ip->ip_id = ip_id; ip->ip_off = htons(0x4000); /* No fragmentation */ ip->ip_ttl = 255; ip->ip_p = 0x01; /* ICMP */ ip->ip_sum = 0; NetCopyIP((uchar *)&ip->ip_src, (uchar *)&eNetOurIP); /* - "" - */ NetCopyIP((uchar *)&ip->ip_dst, (uchar *)&NetTargetIP); /* already in network byte order */ ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); s = &ip->udp_src; /* XXX ICMP starts here */ s[0] = ICMP_ECHO_REPLY; //htons(0x0800); /* echo-request, code */ s[1] = 0; /* checksum */ s[2] = 0; /* identifier */ s[3] = sn; /* sequence number */ s[1] = ~NetCksum((uchar *)s, 8/2); eeth_send((uchar *)et, (pkt - (uchar *)et) + IP_HDR_SIZE_NO_UDP + 8);}voideNetReceive(volatile uchar * inpkt, int len){ Ethernet_t *et; IP_t *ip; ARP_t *arp; IPaddr_t tmp; int x; uchar *pkt;#ifdef ET_DEBUG printk("packet received\n");#endif et = (Ethernet_t *)inpkt; /* too small packet? */ if (len < ETHER_HDR_SIZE) return; x = ntohs(et->et_protlen);#ifdef ET_DEBUG printk("packet received\n");#endif 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 */ return; }#ifdef ET_DEBUG printk("Receive from protocol 0x%x\n", x);#endif 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 packates 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 */#ifdef ET_DEBUG putstr ("Got ARP\n");#endif arp = (ARP_t *)ip; if (len < ARP_HDR_SIZE) { printk("bad length %d < %d\n", len, ARP_HDR_SIZE); return; } if ((ntohs(arp->ar_hrd) != ARP_ETHER)||(ntohs(arp->ar_pro) != PROT_IP)) { return; } if ((arp->ar_hln != 6)||(arp->ar_pln != 4)) { return; } if (eNetOurIP == 0) { return; } if (NetReadIP(arp->ar_tpa) != eNetOurIP) { return; } switch (ntohs(arp->ar_op)) { case ARPOP_REQUEST: /* reply with our IP address */#ifdef ET_DEBUG putstr ("Got ARP REQUEST, return our IP\n");#endif pkt = (uchar *)et; pkt += eNetSetEther(pkt, et->et_src, PROT_ARP); arp->ar_op = htons(ARPOP_REPLY); memcpy (arp->ar_tha, arp->ar_sha, 6); memcpy (arp->ar_tpa, arp->ar_spa, 4); memcpy (arp->ar_sha, &eNetOurEther, 6);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -