⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethernetif.c

📁 凌阳单片机之以太网通讯模组模组
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "netif/etharp.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))

enum DM9K_PHY_mode {
	DM9K_10MHD   = 0, 
	DM9K_100MHD  = 1, 
	DM9K_10MFD   = 4,
	DM9K_100MFD  = 5, 
	DM9K_AUTO    = 8,
    DM9K_DISCONN = 9
};

extern void delay(u16_t);


u16_t inb(int port)
{
	 int iData,i;
	 *PIOBData=0x4070;               //置位
	 *PIOADir=0x0000;
	 *PIOBData=0x0070|port;            //cs 拉低
	 *PIOBData=0x0020|port;              //读数据&地址	 
	 *PIOADir=0x0000;
	 iData=*PIOAData;            //
	 *PIOBData=0x0070|port;            //cs拉低	 
	 *PIOBData=0x4070|port;               //置位
	 *PIOADir=0xffff;
     return(iData & 0x00ff);
}

void outb(int data,int port)
{
	int i;
	 *PIOADir=0xffff;	 
	 *PIOAData=data;   
	 *PIOBData=0x4070|port;               //置位
	 *PIOBData=0x0070|port;            //cs
    *PIOBData=0x0010|port;              //写数据	 
*PIOBData=0x4070;               //置位
}

u16_t inw(int port)
{
	 int iData,i;
	 *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)
{
	 int i;
	 *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 i,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 i,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 i,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;            //cs	 	 
	 *PIOBData=0x4074;               //置位
    }
}

void delay(u16_t delay_time);

static const struct eth_addr ethbroadcast = {{0xffff,0xffff,0xffff}};
/* Forward declarations. */
static void  ethernetif_input(struct netif *netif);
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,struct ip_addr *ipaddr);

typedef struct EtherDev{
    u16_t   base_addr;
    struct eth_addr dev_addr;
	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 = NULL;
/* 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);
static u16_t read_srom_word(int);
#if 0
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
*/
struct EtherDev *init_etherdev(struct EtherDev *dev, u16_t opt)
{
dev = mem_malloc(sizeof (struct EtherDev));
memset(dev,0,sizeof (struct EtherDev));
return(dev);
}




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]=0x6000;
            dev->dev_addr.addr[1]=0x006e;
            dev->dev_addr.addr[2]=0x0090;
            
            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 netif *netif)
{
	struct EtherDev * dev = netif->state;
	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.
*/

err_t
low_level_output(struct netif *netif, struct pbuf *skb)
{
    struct EtherDev *dev = netif->state;
	u16_t * data_ptr;
	int i, tmplen;
	struct pbuf *q;
	/* Disable all interrupt */	
	/* Move data to DM9K TX RAM */
	ior(0x05);
	outb(0xf8, DM9KADDR);
	#if 0
	if (db->io_mode == DM9K_BYTE_MODE) {
		/* Byte mode */
		for (i = 0; i < skb->len; i++)
			outb((data_ptr[i] & 0xff), DM9KADDR);
			while(1);
	} else 
	#endif 
	if (dev->io_mode == DM9K_WORD_MODE) {
		/* Word mode */
  for(q = skb ; q != NULL; q = q->next) {
    /* Send the data from the pbuf to the interface, one pbuf at a
       time. The size of the data in each pbuf is kept in the ->len
       variable. */
   if ((q->len % 2) && (q->next !=NULL))
   {
   DEBUGF(DM9K_DEBUG | DBG_TRACE, ("data error ! odd bytes. q->len\n",q->len));
   while(1);
   }
   data_ptr = q->payload;
   tmplen = (q->len + 1) / 2;
   s_pack(tmplen, data_ptr);
  }
       dev->tx_packets++;
		/* Set TX length to DM9K */
		iow( 0xfc, skb->tot_len & 0xff);
		iow( 0xfd, (skb->tot_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)
{ 	
	/* 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
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -