第二週報告 姓名:張嘉巖 汪俊宏 學號:M9830205 M9730249 班級:碩研電子一甲 練習一: 使用 C 建立一各網際網路功能 目的: 了解使用 unSPIDE2.0.0D 環境介面下,使用 C 語言來測 試網際網路功能 程式: /* * Copyright (c) 2001-2003 Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. * * Author: Adam Dunkels <adam@sics.se> * */ /* * This file is a skeleton for developing Ethernet network interface * drivers for lwIP. Add code to the low_level functions and do a * search-and-replace for the word "ethernetif" to replace it with * something that better describes your network interface. * * THIS CODE NEEDS TO BE FIXED - IT IS NOT In SYNC WITH CURRENT ETHARP API */ #include "cc.h" #include "Dm9000.h" #include "hardware.h" /* Define those to better describe your network interface. */ #define PIOBData #define PIOBDir ((volatile u16_t *)(P_IOB_Data)) ((volatile u16_t *)(P_IOB_Dir)) #define PIOAData ((volatile u16_t *)(P_IOA_Data)) #define PIOADir ((volatile u16_t *)(P_IOA_Dir)) #define PWatchdogClear ((volatile u16_t *)(P_Watchdog_Clear)) #define ERR_OK 0 #define ENODEV 1 enum DM9K_PHY_mode { DM9K_10MHD = 0, DM9K_100MHD = 1, //vvv DM9K_10MFD = 4, DM9K_100MFD = 5, DM9K_AUTO = 8, DM9K_DISCONN = 9 }; void delay(u16_t); u16_t getbyte(u16_t *data, u16_t offset); u16_t inb(int port)// 1各byte輸入 //vvv { int iData; *PIOBData=0x4070; //復歸預設值 *PIOADir=0x0000; *PIOBData=0x0070|port; //cs 拉低 *PIOBData=0x0020|port; //讀資料&位址 *PIOADir=0x0000; iData=*PIOAData; *PIOBData=0x0070|port; *PIOBData=0x4070|port; // //cs拉低 //復歸預設值 *PIOADir=0xffff; return(iData & 0x00ff); } void outb(int data,int port)// output one byte //vvv { *PIOADir=0xffff; *PIOAData=data; *PIOBData=0x4070|port; *PIOBData=0x0070|port; //復歸預設值 //cs 拉低 *PIOBData=0x0010|port; *PIOBData=0x4070; //寫資料 //復歸預設值 } u16_t inw(int port)// imputer 2 byte //vvv { int iData; *PIOBData=0x4070; //復歸預設值 *PIOADir=0x0000; *PIOBData=0x0070|port; //cs拉低 *PIOBData=0x0020|port; iData=*PIOAData; //讀資料 // *PIOBData=0x0070|port; //cs拉低 *PIOBData=0x4070|port; //復歸預設值 *PIOADir=0xffff; return(iData); } void outw(int data,int port)// output two byte { // ? // ? *PIOADir=0xffff; *PIOAData=data; *PIOBData=0x4070|port; *PIOBData=0x0070|port; *PIOBData=0x0010|port; *PIOBData=0x0070|port; *PIOBData=0x4070|port; //復歸預設值 //cs //寫資料 //cs //復歸預設值 } void r_pack(unsigned int len,unsigned int *payload) //連續接收資 料,接收緩衝區起始位址為payload,接收長度為len(以字為單 位)送封包資料且存資料 { //vvv unsigned int j=0; *PIOBData=0x4074; //復歸預設值 *PIOADir=0x0000; for(j=0;j<len;j++) { //*PIOBData=0x0070; *PIOBData=0x0024; //cs //讀資料 *(payload++)=*PIOAData; //*PIOBData=0x0074; *PIOBData=0x0034; //*PIOBData=0x4074; // //cs //wr pull high //復歸預設值 } *PIOADir=0xffff; } void drop(unsigned int len) //連續接收資料,接收緩衝區起始位址 為payload,接收長度為len(以字為單位)收資料但不存 { //vvv unsigned int j=0; *PIOBData=0x4070; //復歸預設值 *PIOADir=0x0000; for(j=0;j<len;j++) { //*PIOBData=0x0074; //cs *PIOBData=0x0024; *PIOBData=0x0034; //*PIOBData=0x4074; //讀資料 //cs //復歸預設值 } *PIOADir=0xffff; } void s_pack(unsigned int len,unsigned int *payload)//傳送一筆資料 {// ? unsigned int j=0; *PIOBData=0x4070; *PIOADir=0xffff; for(j=0;j<len;j++) { //復歸預設值 *PIOAData=*(payload++); *PIOBData=0x4074; //*PIOBData=0x0070; //*PIOBData=0x0074; *PIOBData=0x0014; //*PIOBData=0x0034; //*PIOBData=0x0074; *PIOBData=0x4074; } } void delay(u16_t delay_time) {//vvv u16_t i; for(i=0; i<delay_time; i++) { *PWatchdogClear = 1; } } u16_t getbyte(u16_t *data, u16_t offset) // //復歸預設值 //cs //cs //寫資料 //wr pull high //cs //復歸預設值 {//vvv u16_t tmp; if(offset < 2) { // 0 放入第一組位址 tmp = *data; } else if(offset < 4) { tmp = *(data+1); } else { tmp = *(data+2); } if(offset%2) { // 0%2 = 0 return (tmp & 0x00ff); } else { return (tmp >> 8); } } struct eth_addr { //vvv 與 00ff作and PACK_STRUCT_FIELD(u16_t addr[3]); }PACK_STRUCT_STRUCT; struct eth_hdr { //vvv struct eth_addr dest; struct eth_addr src; PACK_STRUCT_FIELD(u16_t type); }PACK_STRUCT_STRUCT; struct pbuf { //vvv u16_t payload[1520]; u16_t len; }; static const struct eth_addr ethbroadcast = {{0xffff,0xffff,0xffff}}; typedef struct EtherDev{//網卡管理 u16_t base_addr; struct eth_addr dev_addr; struct pbuf* q; u8_t op_mode; /* PHY operation mode */ u8_t io_mode; /* 0:word, 2:byte */ u16_t link_mode; //u16_t runt_length_counter; /* counter: RX length < 64byte */ //u16_t long_length_counter; /* counter: RX length > 1514byte */ //u16_t reset_counter; /* counter: RESET */ u16_t reset_rx_status; /* RESET caused by RX Statsus wrong */ //u16_t rx_fifo_errors; //u16_t rx_crc_errors; //u16_t rx_length_errors; u16_t rx_packets; u16_t tx_packets; //u16_t drop_packets; } DM9000_t; /* Global variable declaration ----------------------------- */ //static struct EtherDev * dmfe_dev = 0; static DM9000_t * dmfe_dev = 0; /* function declaration ------------------------------------- */ int dmfe_probe(struct EtherDev *); static int dmfe_stop(struct EtherDev *); static void dmfe_init_DM9K(struct EtherDev *); volatile static u8_t ior(int); static void iow(int, u8_t); volatile static u16_t phy_read( int); static void phy_write(int, u16_t); #if 0 static u16_t read_srom_word(int); u32_t CRC_32(u8_t *CRC_Data , u16_t Data_len); static void DM9K_hash_table(struct EtherDev *); static unsigned long cal_CRC(u8_t *, unsigned int, u8_t); struct dev_mc_list mc2 = {NULL,(0x01,0x02,0x03,0x04,0x05,0x05)}; struct dev_mc_list mc1 = {&mc2,(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)}; #endif /* from DM9K linux driver */ /* Search DM9K board, allocate space and register it */ int dmfe_probe(struct EtherDev *dev) {//vvv u32_t id_val; u16_t iobase = DM9K_MIN_IO; 0x000 //#define DM9K_MIN_IO in Dm9000.h u16_t i, DM9K_found = FALSE,oft; //#define FALSE 0 in Dm9000.h //DMFE_DBUG(0, "dmfe_probe()",0); /* Search All DM9K NIC */ outb(DM9K_VID_L, iobase); // iobase = 0x0000 #define DM9K_VID_L 0x28 in Dm9000.h id_val = inb(iobase + 4); // inb(0x0004) outb(DM9K_VID_H, iobase); //#define DM9K_VID_H 0x29 in Dm9000.h id_val |= inb(iobase + 4) << 8; // inb (0x0400) outb(DM9K_PID_L, iobase); //#define DM9K_PID_L 0x2A in Dm9000.h id_val |= (u32_t)inb(iobase + 4) << 16; // outb(DM9K_PID_H, iobase); //#define DM9K_PID_H 0x2B in Dm9000.h id_val |= (u32_t)inb(iobase + 4) << 24; if (id_val == DM9K_ID) { //#define DM9K_ID 0x90000A46 in Dm9000.h //DEBUGF(DM9K_DEBUG | DBG_TRACE , ("<DM9K> I/O: %x, VID: %x \n",iobase, id_val)); DM9K_found = TRUE; // #define TRUE 1 in Dm9000.h /* Init network device */ //dev = init_etherdev(dev, 0); /* Allocated board information structure */ dmfe_dev = dev; //****上面有定義 dmfe_dev dev->base_addr DM9K_MIN_IO 0x000 = iobase; // iobase = #if 0 dev->mc_list = &mc1; dev->mc_count = 2; #endif dev->dev_addr.addr[0]=0x0001; // addr[0] ~ addr[2] 是由eth_addr內部定義 dev->dev_addr.addr[1]=0x0203; //而eth_addr內部 定義#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) dev->dev_addr.addr[2]=0x0405; //是否定義 attribute? for (i = 0, oft = 0x10; i < 6; i++, oft++) iow(oft, GETMAC(dev->dev_addr, i)); //#define GETMAC(eaddr,i) getbyte(eaddr.addr,i) /* Set Node Address */ } return DM9K_found ? 0:-ENODEV; // ENODEV 1 定義在此 程式上 } /* Open the interface. The interface is opened whenever "ifconfig" actives it. */ void low_level_init(struct EtherDev *dev) {//vvv dmfe_init_DM9K(dev); //在下下面 } /* Set PHY operationg mode */ static void set_PHY_mode(u16_t op_mode) {//vvv u16_t phy_reg4 = 0x01e1, phy_reg0=0x1000; switch(op_mode) { case DM9K_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x0000; break; case DM9K_10MFD: phy_reg4 = 0x41; phy_reg0 = 0x1100; break; case DM9K_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x2000; break; case DM9K_100MFD: phy_reg4 = 0x101; phy_reg0 =0x3100; break; } phy_write(4, phy_reg4); /* Set PHY media mode */ phy_write(0, phy_reg0); /* Tmp */ iow( 0x1e, 0x01); iow( 0x1f, 0x00); } /* /* Let GPIO0 output */ /* Enable PHY */ Hardware start transmission. Send a packet to media from the upper layer. */ int low_level_output(struct EtherDev *dev, struct pbuf *q) {//vvv u16_t * data_ptr; int tmplen; /* Disable all interrupt */ /* Move data to DM9K TX RAM */ ior(0x05); outb(0xf8, DM9KADDR); if (dev->io_mode == DM9K_WORD_MODE) { /* Word mode */ data_ptr = q->payload; tmplen = (q->len + 1) / 2; s_pack(tmplen, data_ptr); dev->tx_packets++; /* Set TX length to DM9K */ iow( 0xfc, q->len & 0xff); iow( 0xfd, (q->len >> 8) & 0xff); iow( 0x02, 0x01); while (!( ior( 0x01) & (4 | 8))); return ERR_OK; } } /* Initilize DM9K board */ static void dmfe_init_DM9K(struct EtherDev *dev) { //vvv /* RESET device */ iow( 0, 3); delay(100); /* delay 100us */ iow( 0, 0); iow( 0, 3); delay(100); /* delay 100us */ iow( 0, 0); /* I/O mode */ dev->io_mode = ior( 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */ //DEBUGF(DM9K_DEBUG | DBG_TRACE, ("io_mode = %d\n", dev->io_mode)); delay(200); /* delay 100us */ /* Set PHY */ dev->op_mode = DM9K_10MFD; DM9K_10MFD // DM9k_10MFD = 4, set_PHY_mode(dev->op_mode); delay(500); if (!(ior(NSR) &1<<6)) dev->link_mode = DM9K_DISCONN; else dev->link_mode = dev->op_mode; //while(!(ior( NSR) & 1<<6)); /* Init needed register value */ /* Program operating register */ iow( 0x00, DM9K_REG00); iow( 0x02, 0); /* TX Polling clear */ iow( 0x08, 0x3f); /* Less 3Kb, 200us */ iow( 0x09, DM9K_REG09); /* Flow Control : High/Low Water */ iow( 0x0a, DM9K_REG0A); /* Flow Control */ iow( 0x2f, 0); /* Special Mode */ iow( 0x01, 0x2c); /* clear TX status */ iow( 0xfe, 0x0f); /* Clear interrupt status */ /* Set address filter table */ #if 0 DM9K_hash_table(dev); #endif /* Activate DM9K */ iow( 0x05, DM9K_REG05 | 1); iow( 0xff, DM9K_REGFF); /* RX enable */ /* Enable TX/RX interrupt mask */ /* Init Driver variable */ } /* Stop the interface. The interface is stopped when it is brought. */ static int dmfe_stop(struct EtherDev *dev) {//vvv //DMFE_DBUG(0, "dmfe_stop", 0); /* RESET devie */ phy_write( 0x00, 0x8000); /* PHY RESET */ delay(200); iow( 0x1f, 0x01); /* Power-Down PHY */ iow( 0xff, 0x80); /* Disable all interrupt */ iow( 0x05, 0x00); /* Disable RX */ delay(200); /* Dump Statistic counter */ #if DM9K_DEBUG Print("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors); Print("RX CRC %lx\n", db->stats.rx_crc_errors); Print("RX LEN Err %lx\n", dev->rx_length_errors); Print("RX LEN < 64byte %x\n", dev->runt_length_counter); Print("RX LEN > 1514byte %x\n", dev->long_length_counter); Print("RESET %x\n", dev->reset_counter); #endif return 0; } /* Received a packet and pass to upper layer */ void low_level_input(struct EtherDev *dev, struct pbuf *skb) {//vvv u16_t rxbyte, *rdptr; u16_t RxStatus, RxLen, GoodPacket, tmplen; /* Check packet ready or not */ ior(0xf0); /* Dummy read */ rxbyte = inb(DM9KDATA); // // #define DM9KDATA /* Got most updated data */ (DM9K_BaseAddr + 4) #define DM9K_BaseAddr 0x0 /* Status check: this byte must be 0 or 1 */ /* packet ready to receive check */ if (rxbyte == DM9K_PKT_RDY) { //#define DM9K_PKT_RDY /* A packet ready now 0x01 in Dm9000.h & Get status/length */ GoodPacket = TRUE; outb(0xf2, DM9KADDR); #if 0 if (dev->io_mode == DM9K_BYTE_MODE) { //#define DM9K_BYTE_MODE 2 /* Byte mode */ RxStatus = inb(DM9KDATA)+(inb(DM9KDATA) << 8); RxLen = inb(DM9KDATA)+(inb(DM9KDATA) << 8); } else #endif if (dev->io_mode == DM9K_WORD_MODE) { // #define DM9K_WORD_MODE 0 /* Word mode */ RxStatus = inw(DM9KDATA); RxLen } = inw(DM9KDATA); /* Packet Status check */ if (RxLen < 0x40) { GoodPacket = FALSE; //dev->runt_length_counter++; } if (RxLen > DM9K_PKT_MAX) { //#define DM9K_PKT_MAX 1536 /* Received packet max size */ //DEBUGF(DM9K_DEBUG | DBG_TRACE, ("<DM9K> RST: RX Len:%x\n", RxLen)); //dev->long_length_counter++; } if (RxStatus & 0xbf00) { GoodPacket = FALSE; if (RxStatus & 0x100) //dev->rx_fifo_errors++; ; if (RxStatus & 0x200) //dev->rx_crc_errors++; ; if (RxStatus & 0x8000) //dev->rx_length_errors++; ; } /* Move data from DM9K */ if ( GoodPacket ) { rdptr = skb->payload; /* Read received packet from RX SARM */ if (dev->io_mode == DM9K_WORD_MODE) { /* Word mode */ tmplen = (RxLen + 1) / 2; r_pack(tmplen, rdptr); } /* Pass to upper layer */ dev->rx_packets++; } else { tmplen = (RxLen + 1) / 2; drop(tmplen); //dev->drop_packets++; } } return; } /* Read a word data from SROM */ /* Set DM9K multicast address */ #if 0 static u16_t read_srom_word( int offset) {//? iow( 0xc, offset); iow( 0xb, 0x4); delay(200); iow( 0xb, 0x0); return (ior( 0xd) + (ior( 0xe) << 8) ); } void DM9K_hash_table(struct net_device *dev) {//VVV //EtherDev_t *db = (EtherDev_t *)dev->priv; struct dev_mc_list *mcptr = dev->mc_list; int mc_cnt = dev->mc_count; u16_t hash_val; u16_t i, oft, hash_table[4]; DMFE_DBUG(0, "DM9K_hash_table()", 0); /* Set Node address */ for (i = 0, oft = 0x10; i < 6; i++, oft++) // ? iow( oft, GETMAC(dev->dev_addr, i)); /* Clear Hash Table */ for (i = 0; i < 4; i++) hash_table[i] = 0x0; /* broadcast address */ hash_table[3] = 0x8000; /* the multicast address in Hash Table : 64 bits */ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { hash_val = cal_CRC((u8_t *)mcptr->dmi_addr, 6, 0) & 0x3f; hash_table[hash_val / 16] |=(u16_t) 1 << (hash_val % 16); } /* Write the hash table to MAC MD table */ for (i = 0, oft = 0x16; i < 4; i++) { iow( oft++, hash_table[i] & 0xff); iow( oft++, (hash_table[i] >> 8) & 0xff); } } /* Calculate the CRC valude of the Rx packet flag = 1 : return the reverse CRC (for the received packet CRC) 0 : return the normal CRC (for Hash Table index) */ static unsigned long cal_CRC(u8_t * Data, unsigned int Len, u8_t flag) {//vvv u32_t crc = CRC_32(Data,Len); if (flag) return ~crc; return crc; } /* CRC_32 堍呾 */ u32_t CRC_32(u8_t *CRC_Data , u16_t Data_len) {//vvv u32_t crc ,carry ; u16_t iTemp; u16_t iTemp1; /* crc-32 堍呾 */ crc = 0xffffffff; for(iTemp = 0 ; iTemp < Data_len ; iTemp++) { carry = (crc ^ *CRC_Data++) & 0xff; for(iTemp1 = 0 ; iTemp1 < 8 ; iTemp1++) { if(carry & 1) carry = (carry >> 1) ^ 0xedb88320; else carry >>= 1; } crc = ((crc >> 8) & 0x00ffffff) ^ carry; } return(crc); } #endif /* Read a byte from I/O port */ volatile static u8_t ior(int reg) {//vvv outb(reg, DM9KADDR); return inb(DM9KDATA); } /* Write a byte to I/O port */ static void iow(int reg, u8_t value) {//vvv outb(reg, DM9KADDR); outb(value, DM9KDATA); } /* Read a word from phyxcer */ volatile static u16_t phy_read(int reg) {//? /* Fill the phyxcer register into REG_0C */ iow(0xc, DM9K_PHY | reg); iow(0xb, 0xc); /* Issue phyxcer read command */ delay(100); /* Wait read complete */ while((ior(EPCR) & 0x01) == 0x01); iow( 0xb, 0x0); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ return ( ior(0xe) << 8 ) | ior(0xd); } /* Write a word to phyxcer */ static void phy_write(int reg, u16_t value) {//vvv /* Fill the phyxcer register into REG_0C */ iow(0xc, DM9K_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow(0xd, (value & 0xff)); iow(0xe, ( (value >> 8) & 0xff)); iow(0xb, 0xa); /* Issue phyxcer write command */ delay(200); /* Wait write complete */ while((ior(EPCR) & 0x01) == 0x01); iow(0xb, 0x0); /* Clear phyxcer write command */ } /*----------------------------------------------------------------------------------*/ /* * ethernetif_init(): * * Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. * */ /*----------------------------------------------------------------------------------*/ int ethernetif_init(struct EtherDev* dev) {//vvv //int i; if (dmfe_probe(dmfe_dev)!=0) { //DEBUGF(DM9K_DEBUG | DBG_TRACE, ("device not found!\n")); return -1; } low_level_init(dmfe_dev); return 0; } /*----------------------------------------------------------------------------------*/ /* 檢查 DM9K 接收記憶體是否還有新的封包 */ u8_t CheckNetPack(struct EtherDev *dev) {//vvv u16_t temp; ior(MRCMDX); switch(ior(MRCMDX))//DM9KREG_r(MRCMDX)) /* 檢查是否有新的封包進入 */ { case 0x00 : { return(0); /* 尚無 封包進入 */ } case 0x01 : return(1); default /* 有封包進入 */ : temp = ior(0xF4) + ior(0xF5)*256; //DEBUGF(DM9K_DEBUG | DBG_TRACE,("%02x",ior(MRCMDX))); dev->reset_rx_status++; dmfe_stop(dev); delay(200); dmfe_init_DM9K(dev); /* 記憶體出錯,重置 DM9K */ return(0); } } void Ethernet_poll(struct EtherDev *dev) {//vvv // DM9K_DISCONN = 9 if (dev->link_mode == DM9K_DISCONN) { //DEBUGF(DM9K_DEBUG | DBG_TRACE, // ("Hardware error!No Active network connected.\n \ // Please check your network interface.\n")); return; } if(CheckNetPack(dev)) { //ethernetif_input(dev); low_level_input(dev, dev->q); } } int main() { int i; struct EtherDev dev; struct pbuf pktBuf; ethernetif_init(&dev); pktBuf.payload[0]=0xffff; pktBuf.payload[1]=0xffff; pktBuf.payload[2]=0xffff; pktBuf.payload[3]=0xffff; pktBuf.payload[4]=0x0203; pktBuf.payload[5]=0x0405; pktBuf.payload[6]=0x1234; for(i=0;i<64;i++) { if(i % 2) { pktBuf.payload[7+(i >> 1)] += i; }else { pktBuf.payload[7+(i >> 1)] = i << 8; } } pktBuf.len = 142; low_level_output(dmfe_dev, &pktBuf); while(1) { Ethernet_poll(dmfe_dev); *PWatchdogClear = 1; } } 練習一: 使用 C 建立一各網際網路功能 目的: 了解使用 unSPIDE2.0.0D 環境介面下,使用 C 語言來測 試網際網路功能,測試 ARP 的 ARPRequest 和 ARPReply 程式: /* * Copyright (c) 2001-2003 Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. * * Author: Adam Dunkels <adam@sics.se> * */ /* * This file is a skeleton for developing Ethernet network interface * drivers for lwIP. Add code to the low_level functions and do a * search-and-replace for the word "ethernetif" to replace it with * something that better describes your network interface. * * THIS CODE NEEDS TO BE FIXED - IT IS NOT In SYNC WITH CURRENT ETHARP API */ #include "cc.h" #include "Dm9000.h" #include "hardware.h" /* Define those to better describe your network interface. */ #define PIOBData ((volatile u16_t *)(P_IOB_Data)) #define PIOBDir ((volatile u16_t *)(P_IOB_Dir)) #define PIOAData ((volatile u16_t *)(P_IOA_Data)) #define PIOADir ((volatile u16_t *)(P_IOA_Dir)) #define PWatchdogClear ((volatile u16_t *)(P_Watchdog_Clear)) #define ERR_OK 0 #define ENODEV 1 enum DM9K_PHY_mode { DM9K_10MHD = 0, DM9K_100MHD = 1, DM9K_10MFD = 4, DM9K_100MFD = 5, DM9K_AUTO = 8, DM9K_DISCONN = 9 }; void delay(u16_t); u16_t getbyte(u16_t *data, u16_t offset); u16_t inb(int port) { int iData; *PIOBData=0x4070; *PIOADir=0x0000; *PIOBData=0x0070|port; 腴 *PIOBData=0x0020|port; //离弇 //cs 嶺 //黍杅 擂&華硊 *PIOADir=0x0000; iData=*PIOAData; *PIOBData=0x0070|port; // //cs 嶺腴 *PIOBData=0x4070|port; //离 弇 *PIOADir=0xffff; return(iData & 0x00ff); } void outb(int data,int port) { *PIOADir=0xffff; *PIOAData=data; *PIOBData=0x4070|port; *PIOBData=0x0070|port; *PIOBData=0x0010|port; *PIOBData=0x4070; } u16_t inw(int port) { int iData; *PIOBData=0x4070; *PIOADir=0x0000; *PIOBData=0x0070|port; *PIOBData=0x0020|port; 擂 iData=*PIOAData; *PIOBData=0x0070|port; *PIOBData=0x4070|port; 弇 //离弇 //cs //迡杅擂 //离弇 //离弇 //cs //黍杅 // //cs //离 *PIOADir=0xffff; return(iData); } void outw(int data,int port) { *PIOADir=0xffff; *PIOAData=data; *PIOBData=0x4070|port; //离 弇 *PIOBData=0x0070|port; //cs *PIOBData=0x0010|port; //迡杅 擂 *PIOBData=0x0070|port; //cs *PIOBData=0x4070|port; //离 弇 } void r_pack(unsigned int len,unsigned int *payload) //蟀哿諉彶杅 擂ㄛ諉彶遣喳 宎華硊峈 payload ㄛ諉彶酗僅峈 len(眕趼峈等 弇ㄘ { unsigned int j=0; *PIOBData=0x4074; //离弇 *PIOADir=0x0000; for(j=0;j<len;j++) { //*PIOBData=0x0070; //cs *PIOBData=0x0024; //黍杅擂 *(payload++)=*PIOAData; // //*PIOBData=0x0074; //cs *PIOBData=0x0034; //wr pull high //*PIOBData=0x4074; //离弇 } *PIOADir=0xffff; } void drop(unsigned int len) //蟀哿諉彶杅擂ㄛ諉彶遣喳 宎華 硊峈 payload ㄛ諉彶酗僅峈 len(眕趼峈等弇ㄘ { unsigned int j=0; *PIOBData=0x4070; //离弇 *PIOADir=0x0000; for(j=0;j<len;j++) { //*PIOBData=0x0074; //cs *PIOBData=0x0024; //黍杅擂 *PIOBData=0x0034; //cs //*PIOBData=0x4074; //离弇 } *PIOADir=0xffff; } void s_pack(unsigned int len,unsigned int *payload) { unsigned int j=0; *PIOBData=0x4070; //离弇 *PIOADir=0xffff; for(j=0;j<len;j++) { *PIOAData=*(payload++); // *PIOBData=0x4074; //离弇 //*PIOBData=0x0070; //cs //*PIOBData=0x0074; //cs *PIOBData=0x0014; //迡杅擂 //*PIOBData=0x0034; //wr pull high //*PIOBData=0x0074; *PIOBData=0x4074; } } void delay(u16_t delay_time) { u16_t i; for(i=0; i<delay_time; i++) { *PWatchdogClear = 1; } } u16_t getbyte(u16_t *data, u16_t offset) { u16_t tmp; if(offset < 2) { tmp = *data; } else if(offset < 4) { tmp = *(data+1); } else { tmp = *(data+2); } if(offset%2) { return (tmp & 0x00ff); } else { return (tmp >> 8); } } struct eth_addr { PACK_STRUCT_FIELD(u16_t addr[3]); //cs //离弇 }PACK_STRUCT_STRUCT; struct ip_addr { PACK_STRUCT_FIELD(u16_t addr[2]); }PACK_STRUCT_STRUCT; struct eth_hdr { struct eth_addr dest; struct eth_addr src; PACK_STRUCT_FIELD(u16_t type); }PACK_STRUCT_STRUCT; struct pbuf { u16_t payload[1520]; u16_t len; }; static const struct eth_addr ethbroadcast = {{0xffff,0xffff,0xffff}}; typedef struct EtherDev{ u16_t base_addr; struct eth_addr dev_addr; struct pbuf* q; u8_t op_mode; /* PHY operation mode */ u8_t io_mode; /* 0:word, 2:byte */ u16_t link_mode; //u16_t runt_length_counter; /* counter: RX length < 64byte */ //u16_t long_length_counter; /* counter: RX length > 1514byte */ //u16_t reset_counter; /* counter: RESET */ u16_t reset_rx_status; /* RESET caused by RX Statsus wrong */ //u16_t rx_fifo_errors; //u16_t rx_crc_errors; //u16_t rx_length_errors; u16_t rx_packets; u16_t tx_packets; //u16_t drop_packets; } DM9000_t; /* Global variable declaration ----------------------------- */ //static struct EtherDev * dmfe_dev = 0; static DM9000_t * dmfe_dev = 0; /* function declaration ------------------------------------- */ int dmfe_probe(struct EtherDev *); static int dmfe_stop(struct EtherDev *); static void dmfe_init_DM9K(struct EtherDev *); volatile static u8_t ior(int); static void iow(int, u8_t); volatile static u16_t phy_read( int); static void phy_write(int, u16_t); u16_t swapByte(u16_t val); #if 0 static u16_t read_srom_word(int); u32_t CRC_32(u8_t *CRC_Data , u16_t Data_len); static void DM9K_hash_table(struct EtherDev *); static unsigned long cal_CRC(u8_t *, unsigned int, u8_t); struct dev_mc_list mc2 = {NULL,(0x01,0x02,0x03,0x04,0x05,0x05)}; struct dev_mc_list mc1 = {&mc2,(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)}; #endif /* from DM9K linux driver */ /* */ Search DM9K board, allocate space and register it int dmfe_probe(struct EtherDev *dev) { u32_t id_val; u16_t iobase = DM9K_MIN_IO; u16_t i, DM9K_found = FALSE,oft; //DMFE_DBUG(0, "dmfe_probe()",0); /* Search All DM9K NIC */ outb(DM9K_VID_L, iobase); id_val = inb(iobase + 4); outb(DM9K_VID_H, iobase); id_val |= inb(iobase + 4) << 8; outb(DM9K_PID_L, iobase); id_val |= (u32_t)inb(iobase + 4) << 16; outb(DM9K_PID_H, iobase); id_val |= (u32_t)inb(iobase + 4) << 24; if (id_val == DM9K_ID) { //DEBUGF(DM9K_DEBUG | DBG_TRACE , ("<DM9K> I/O: %x, VID: %x \n",iobase, id_val)); DM9K_found = TRUE; /* Init network device */ //dev = init_etherdev(dev, 0); /* Allocated board information structure */ dmfe_dev = dev; dev->base_addr = iobase; #if 0 dev->mc_list = &mc1; dev->mc_count = 2; #endif dev->dev_addr.addr[0]=0x0001; dev->dev_addr.addr[1]=0x0203; dev->dev_addr.addr[2]=0x0405; for (i = 0, oft = 0x10; i < 6; i++, oft++) iow(oft, GETMAC(dev->dev_addr, i)); /* Set Node Address */ } return DM9K_found ? 0:-ENODEV; } /* Open the interface. The interface is opened whenever "ifconfig" actives it. */ void low_level_init(struct EtherDev *dev) { dmfe_init_DM9K(dev); } /* Set PHY operationg mode */ static void set_PHY_mode(u16_t op_mode) { u16_t phy_reg4 = 0x01e1, phy_reg0=0x1000; switch(op_mode) { case DM9K_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x0000; break; case DM9K_10MFD: phy_reg4 = 0x41; phy_reg0 = 0x1100; break; case DM9K_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x2000; break; case DM9K_100MFD: phy_reg4 = 0x101; phy_reg0 =0x3100; break; } phy_write(4, phy_reg4); /* Set PHY media mode */ phy_write(0, phy_reg0); /* Tmp */ iow( 0x1e, 0x01); /* Let GPIO0 output */ iow( 0x1f, 0x00); /* Enable PHY */ } /* Hardware start transmission. Send a packet to media from the upper layer. */ int low_level_output(struct EtherDev *dev, struct pbuf *q) { u16_t * data_ptr; int tmplen; /* Disable all interrupt */ /* Move data to DM9K TX RAM */ ior(0x05); outb(0xf8, DM9KADDR); if (dev->io_mode == DM9K_WORD_MODE) { /* Word mode */ data_ptr = q->payload; tmplen = (q->len + 1) / 2; s_pack(tmplen, data_ptr); dev->tx_packets++; /* Set TX length to DM9K */ iow( 0xfc, q->len & 0xff); iow( 0xfd, (q->len >> 8) & 0xff); iow( 0x02, 0x01); while (!( ior( 0x01) & (4 | 8))); return ERR_OK; } return -1; } /* Initilize DM9K board */ static void dmfe_init_DM9K(struct EtherDev *dev) { /* RESET device */ iow( 0, 3); delay(100); /* delay 100us */ iow( 0, 0); iow( 0, 3); delay(100); /* delay 100us */ iow( 0, 0); /* I/O mode */ dev->io_mode = ior( 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */ //DEBUGF(DM9K_DEBUG | DBG_TRACE, ("io_mode = %d\n", dev->io_mode)); delay(200); /* delay 100us */ /* Set PHY */ dev->op_mode = DM9K_10MFD; set_PHY_mode(dev->op_mode); delay(500); if (!(ior(NSR) &1<<6)) dev->link_mode = DM9K_DISCONN; else dev->link_mode = dev->op_mode; //while(!(ior( NSR) & 1<<6)); /* Init needed register value */ /* Program operating register */ iow( 0x00, DM9K_REG00); iow( 0x02, 0); /* TX Polling clear */ iow( 0x08, 0x3f); /* Less 3Kb, 200us */ iow( 0x09, DM9K_REG09); /* Flow Control : High/Low Water */ iow( 0x0a, DM9K_REG0A); /* Flow Control */ iow( 0x2f, 0); /* Special Mode */ iow( 0x01, 0x2c); /* clear TX status */ iow( 0xfe, 0x0f); /* Clear interrupt status */ /* Set address filter table */ #if 0 DM9K_hash_table(dev); #endif /* Activate DM9K */ iow( 0x05, DM9K_REG05 | 1); /* RX enable */ iow( 0xff, DM9K_REGFF); /* Enable TX/RX interrupt mask */ /* Init Driver variable */ } /* Stop the interface. The interface is stopped when it is brought. */ static int dmfe_stop(struct EtherDev *dev) { //DMFE_DBUG(0, "dmfe_stop", 0); /* RESET devie */ phy_write( 0x00, 0x8000); /* PHY RESET */ delay(200); iow( 0x1f, 0x01); /* Power-Down PHY */ iow( 0xff, 0x80); /* Disable all interrupt */ iow( 0x05, 0x00); /* Disable RX */ delay(200); /* Dump Statistic counter */ #if DM9K_DEBUG Print("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors); Print("RX CRC %lx\n", db->stats.rx_crc_errors); Print("RX LEN Err %lx\n", dev->rx_length_errors); Print("RX LEN < 64byte %x\n", dev->runt_length_counter); Print("RX LEN > 1514byte %x\n", dev->long_length_counter); Print("RESET %x\n", dev->reset_counter); #endif return 0; } /* Received a packet and pass to upper layer */ int low_level_input(struct EtherDev *dev, struct pbuf *skb) { u16_t rxbyte, *rdptr; u16_t RxStatus, RxLen, GoodPacket, tmplen; /* Check packet ready or not */ ior(0xf0); /* Dummy read */ rxbyte = inb(DM9KDATA); /* Got most updated data */ /* Status check: this byte must be 0 or 1 */ /* packet ready to receive check */ if (rxbyte == DM9K_PKT_RDY) { /* A packet ready now & Get status/length */ GoodPacket = TRUE; outb(0xf2, DM9KADDR); if (dev->io_mode == DM9K_WORD_MODE) { /* Word mode */ RxStatus = inw(DM9KDATA); RxLen = inw(DM9KDATA); } /* Packet Status check */ if (RxLen < 0x40) { GoodPacket = FALSE; //dev->runt_length_counter++; } if (RxLen > DM9K_PKT_MAX) { //DEBUGF(DM9K_DEBUG | DBG_TRACE, ("<DM9K> RST: RX Len:%x\n", RxLen)); //dev->long_length_counter++; } if (RxStatus & 0xbf00) { GoodPacket = FALSE; if (RxStatus & 0x100) //dev->rx_fifo_errors++; ; if (RxStatus & 0x200) //dev->rx_crc_errors++; ; if (RxStatus & 0x8000) //dev->rx_length_errors++; ; } /* Move data from DM9K */ if ( GoodPacket ) { rdptr = skb->payload; skb->len = RxLen; /* Read received packet from RX SARM */ if (dev->io_mode == DM9K_WORD_MODE) { /* Word mode */ tmplen = (RxLen + 1) / 2; r_pack(tmplen, rdptr); } /* Pass to upper layer */ dev->rx_packets++; return 1; } else { tmplen = (RxLen + 1) / 2; drop(tmplen); //dev->drop_packets++; } } return -1; } /* Read a word data from SROM */ /* Set DM9K multicast address */ #if 0 static u16_t read_srom_word( int offset) { iow( 0xc, offset); iow( 0xb, 0x4); delay(200); iow( 0xb, 0x0); return (ior( 0xd) + (ior( 0xe) << 8) ); } void DM9K_hash_table(struct net_device *dev) { //EtherDev_t *db = (EtherDev_t *)dev->priv; struct dev_mc_list *mcptr = dev->mc_list; int mc_cnt = dev->mc_count; u16_t hash_val; u16_t i, oft, hash_table[4]; DMFE_DBUG(0, "DM9K_hash_table()", 0); /* Set Node address */ for (i = 0, oft = 0x10; i < 6; i++, oft++) iow( oft, GETMAC(dev->dev_addr, i)); /* Clear Hash Table */ for (i = 0; i < 4; i++) hash_table[i] = 0x0; /* broadcast address */ hash_table[3] = 0x8000; /* the multicast address in Hash Table : 64 bits */ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { hash_val = cal_CRC((u8_t *)mcptr->dmi_addr, 6, 0) & 0x3f; hash_table[hash_val / 16] |=(u16_t) 1 << (hash_val % 16); } /* Write the hash table to MAC MD table */ for (i = 0, oft = 0x16; i < 4; i++) { iow( oft++, hash_table[i] & 0xff); iow( oft++, (hash_table[i] >> 8) & 0xff); } } /* Calculate the CRC valude of the Rx packet flag = 1 : return the reverse CRC (for the received packet CRC) 0 : return the normal CRC (for Hash Table index) */ static unsigned long cal_CRC(u8_t * Data, unsigned int Len, u8_t flag) { u32_t crc = CRC_32(Data,Len); if (flag) return ~crc; return crc; } /* CRC_32 堍呾 */ u32_t CRC_32(u8_t *CRC_Data , u16_t Data_len) { u32_t crc ,carry ; u16_t iTemp; u16_t iTemp1; /* 蔚怀 crc-32 堍呾 */ crc = 0xffffffff; for(iTemp = 0 ; iTemp < Data_len ; iTemp++) { carry = (crc ^ *CRC_Data++) & 0xff; for(iTemp1 = 0 ; iTemp1 < 8 ; iTemp1++) { if(carry & 1) carry = (carry >> 1) ^ 0xedb88320; else carry >>= 1; } crc = ((crc >> 8) & 0x00ffffff) ^ carry; } return(crc); } #endif /* Read a byte from I/O port */ volatile static u8_t ior(int reg) { outb(reg, DM9KADDR); return inb(DM9KDATA); } /* Write a byte to I/O port */ static void iow(int reg, u8_t value) { outb(reg, DM9KADDR); outb(value, DM9KDATA); } /* Read a word from phyxcer */ volatile static u16_t phy_read(int reg) { /* Fill the phyxcer register into REG_0C */ iow(0xc, DM9K_PHY | reg); iow(0xb, 0xc); /* Issue phyxcer read command */ delay(100); /* Wait read complete */ while((ior(EPCR) & 0x01) == 0x01); iow( 0xb, 0x0); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ return ( ior(0xe) << 8 ) | ior(0xd); } /* Write a word to phyxcer */ static void phy_write(int reg, u16_t value) { /* Fill the phyxcer register into REG_0C */ iow(0xc, DM9K_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow(0xd, (value & 0xff)); iow(0xe, ( (value >> 8) & 0xff)); iow(0xb, 0xa); /* Issue phyxcer write command */ delay(200); /* Wait write complete */ while((ior(EPCR) & 0x01) == 0x01); iow(0xb, 0x0); /* Clear phyxcer write command */ } /*----------------------------------------------------------------------------------*/ /* * ethernetif_init(): * * Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. * */ /*----------------------------------------------------------------------------------*/ int ethernetif_init(struct EtherDev* dev) { //int i; if (dmfe_probe(dev)!=0) { //DEBUGF(DM9K_DEBUG | DBG_TRACE, ("device not found!\n")); return -1; } low_level_init(dmfe_dev); return 0; } /*----------------------------------------------------------------------------------*/ /* 潰脤 DM9K 諉彶囀湔岆瘁遜衄陔腔猾婦 */ u8_t CheckNetPack(struct EtherDev *dev) { u16_t temp; ior(MRCMDX); switch(ior(MRCMDX))//DM9KREG_r(MRCMDX)) /* 潰脤岆瘁衄陔腔猾婦輛 */ { case 0x00 : { return(0); /* 奾拸 猾婦輛 */ } case 0x01 : return(1); /* 衄猾婦輛 */ default : temp = ior(0xF4) + ior(0xF5)*256; //DEBUGF(DM9K_DEBUG | DBG_TRACE,("%02x",ior(MRCMDX))); dev->reset_rx_status++; dmfe_stop(dev); delay(200); dmfe_init_DM9K(dev); /* 囀湔堤渣 ㄛ笭离 DM9K */ return(0); } } int Ethernet_poll(struct EtherDev *dev) { if (dev->link_mode == DM9K_DISCONN) { //DEBUGF(DM9K_DEBUG | DBG_TRACE, // ("Hardware error!No Active network connected.\n \ Please check your network interface.\n")); return -1; } if(CheckNetPack(dev)) { //ethernetif_input(dev); return(low_level_input(dev, dev->q)); } } struct EtherDev myDev; struct pbuf pktBuf; //struct eth_addr arpReqMACSrc; //struct ip_addr arpReqIPSrc; void ARPReguest(struct eth_addr localMAC, struct ip_addr localIP, struct eth_addr remoteMAC, struct ip_addr remoteIP); void ARPReply(struct eth_addr localMAC, struct ip_addr localIP, struct eth_addr remoteMAC, struct ip_addr remoteIP); int main () { int i; struct eth_addr localMAC; struct ip_addr localIP; struct ip_addr remoteIP; struct eth_addr remoteMAC; System_Initial(); ethernetif_init(&myDev); dmfe_dev-> q = &pktBuf; // source MAC localMAC.addr[0] = 0x0001; localMAC.addr[1] = 0x0203; localMAC.addr[2] = 0x0405; // source IP localIP.addr[0] = 0xC0A8; localIP.addr[1] = 0x0105; // dst IP remoteIP.addr[0] = 0xC0A8; remoteIP.addr[1] = 0x010A; // dst MAC remoteMAC.addr[0] = 0xffff; remoteMAC.addr[1] = 0xffff; remoteMAC.addr[2] = 0xffff; ARPReguest(localMAC, localIP, remoteMAC, remoteIP); while(1) { if(Ethernet_poll(dmfe_dev)>0) { if(dmfe_dev->q->len>0) { if(swapByte(dmfe_dev->q->payload[6])==0x0806 && swapByte(dmfe_dev->q->payload[10])==0x0001) { //ARP Request Received if(swapByte(dmfe_dev->q->payload[19])==remot eIP.addr[0] && swapByte(dmfe_dev->q->payload[20])==remoteIP.addr[1]) { remoteMAC.addr[0] = dmfe_dev->q->payload[11]; remoteMAC.addr[1] = dmfe_dev->q->payload[12]; remoteMAC.addr[2] = dmfe_dev->q->payload[13]; remoteIP.addr[0] = dmfe_dev->q->payload[14]; remoteIP.addr[1] = dmfe_dev->q->payload[15]; ARPReply(localMAC, localIP, remoteMAC, remoteIP); } } } } *PWatchdogClear = 1; } //return; } u16_t swapByte(u16_t val) { return((val<<8) | (val>>8)); } void ARPReguest(struct eth_addr localMAC, struct ip_addr localIP, struct eth_addr remoteMAC, struct ip_addr remoteIP) { pktBuf.payload[0]=swapByte(remoteMAC.addr[0 ]); //change des MAC pktBuf.payload[1]=swapByte(remoteMAC.addr[1 ]); // change pktBuf.payload[2]=swapByte(remoteMAC.addr[2 ]); // change // change pktBuf.payload[3]=swapByte(localMAC.addr[0]); source MAC pktBuf.payload[4]=swapByte(localMAC.addr[1]); // change pktBuf.payload[5]=swapByte(localMAC.addr[2]); // change pktBuf.payload[6]=swapByte(0x0806); //ARP pktBuf.payload[7]=swapByte(0x0001); pktBuf.payload[8]=swapByte(0x0800); pktBuf.payload[9]=swapByte(0x0604); pktBuf.payload[10]=swapByte(0x0001); //ARP request pktBuf.payload[11]=swapByte(0x0001); //Sender MAC Addr. pktBuf.payload[12]=swapByte(0x0203); pktBuf.payload[13]=swapByte(0x0405); pktBuf.payload[14]=swapByte(localIP.addr[0]); //Sender IP Addr. 192.168.1.5 //change pktBuf.payload[15]=swapByte(localIP.addr[1]); /* pktBuf.payload[16]=swapByte(0xffff); //Target MAC Addr. => Don't care for ARP request pktBuf.payload[17]=swapByte(0xffff); pktBuf.payload[18]=swapByte(0xffff); */ //change 為此 pktBuf.payload[16]=swapByte(0x0000); //Target MAC Addr. => Don't care for ARP request pktBuf.payload[17]=swapByte(0x0000); pktBuf.payload[18]=swapByte(0x0000); pktBuf.payload[19]=swapByte(remoteIP.addr[0]); //Target IP Addr. 192.168.1.10 //change pktBuf.payload[20]=swapByte(remoteIP.addr[1]); pktBuf.len = 42; low_level_output(dmfe_dev, dmfe_dev->q); } void ARPReply(struct eth_addr localMAC, struct ip_addr localIP, struct eth_addr remoteMAC, struct ip_addr remoteIP) { //ARP reply pktBuf.payload[0]=swapByte(remoteMAC.addr[0 ]); //change des MAC pktBuf.payload[1]=swapByte(remoteMAC.addr[1 ]); // change pktBuf.payload[2]=swapByte(remoteMAC.addr[2 ]); // change // change pktBuf.payload[3]=swapByte(localMAC.addr[0]); source MAC pktBuf.payload[4]=swapByte(localMAC.addr[1]); // change pktBuf.payload[5]=swapByte(localMAC.addr[2]); // change pktBuf.payload[6]=swapByte(0x0806); //ARP pktBuf.payload[7]=swapByte(0x0001); //Type pktBuf.payload[8]=swapByte(0x0800); pktBuf.payload[9]=swapByte(0x0604); pktBuf.payload[10]=swapByte(0x0002); //ARP reply pktBuf.payload[11]=swapByte(0x0001); //Sender MAC Addr. pktBuf.payload[12]=swapByte(0x0203); pktBuf.payload[13]=swapByte(0x0405); pktBuf.payload[14]=swapByte(localIP.addr[0]); //Sender IP Addr. 192.168.1.5 //change pktBuf.payload[15]=swapByte(localIP.addr[1]); 0]); pktBuf.payload[16]=swapByte(remoteMAC.addr[ //Target MAC Addr. => Don't care for ARP request pktBuf.payload[17]=swapByte(remoteMAC.addr[ 1]); pktBuf.payload[18]=swapByte(remoteMAC.addr[ 2]); pktBuf.payload[19]=swapByte(remoteIP.addr[0]); //Target IP Addr. 192.168.1.10 pktBuf.payload[20]=swapByte(remoteIP.addr[1]); pktBuf.len = 42; low_level_output(dmfe_dev, dmfe_dev->q); }