第二週報告 姓名:張嘉巖 汪俊宏 學號:M9830205

第二週報告
姓名:張嘉巖
汪俊宏
學號: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);
}