📄 enc28j60.c
字号:
/* enc28j60.c: EDTP FrameThrower style enc28j60 driver for Linux 2.4
*
* (c) Copyright 2006 American Microsystems Limited
* Written by David Anders.
*
* Based on the Procyon AVRlib enc28j60.c written by Pascal Stang
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include <linux/module.h>
#include <linux/config.h>
#include <linux/netdevice.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/in.h>
#include <linux/etherdevice.h> /* eth_type_trans */
#include <linux/ip.h> /* struct iphdr */
#include <linux/tcp.h> /* struct tcphdr */
#include <linux/skbuff.h>
#include <linux/types.h> /* size_t */
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include "enc28j60.h"
#include <asm/arch-s3c2410/S3C2410.h>
u8 Enc28j60Bank=-1;
u16 NextPacketPtr;
int ResetCounter=100;
void enc28j60ChipSelect(int cs_stat)
{
unsigned long tmpval;
if ( cs_stat == 1 ) {
GPBDAT &= ~(1<<6); // set GPB6=0,low, active the enc28j60
}
else {
GPBDAT |= (1<<6);
}
}
void enc28j60ReadBuffer(u16 len, u8* data)
{
u8 tmpval;
int counter=1;
// assert CS
enc28j60ChipSelect(1);
// issue read command
SPTDAT0 = ENC28J60_READ_BUF_MEM;
udelay(4);
while(len--)
{
// read data
SPTDAT0 = 0xff; //0x00
udelay(4);
*data++ = SPRDAT0;
udelay(4);
}
// release CS
enc28j60ChipSelect(0);
}
void enc28j60WriteBuffer(u16 len, u8* data)
{
u8 tmpval;
// assert CS
enc28j60ChipSelect(1);
// issue write command
SPTDAT0 = ENC28J60_WRITE_BUF_MEM;
udelay(4);
while(len--)
{
// write data
SPTDAT0 = *data++;
udelay(4);
}
// release CS
enc28j60ChipSelect(0);
}
u8 enc28j60ReadOp(u8 op, u8 address)
{
u8 data;
u8 tmpval;
// assert CS
enc28j60ChipSelect(1);
// issue read command
SPTDAT0 = op | (address & ADDR_MASK);
data = SPRDAT0;
udelay(4);
SPTDAT0 = 0xff;
data = SPRDAT0;
udelay(4);
// do dummy read if needed
if(address & 0x80)
{
SPTDAT0 = 0xff;
data = SPRDAT0;
udelay(4);
}
data = SPRDAT0;
// release CS
enc28j60ChipSelect(0);
return data;
}
void enc28j60WriteOp(u8 op, u8 address, u8 data)
{
u8 tmpval;
// assert CS
enc28j60ChipSelect(1);
// issue write command
SPTDAT0 = op | (address & ADDR_MASK);
udelay(5);
SPTDAT0 = data;
udelay(5);
// release CS
enc28j60ChipSelect(0);
}
void enc28j60SetBank(u8 address)
{
// set the bank (if needed)
if((address & BANK_MASK) != Enc28j60Bank)
{
// set the bank
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
Enc28j60Bank = (address & BANK_MASK);
}
}
u8 enc28j60Read(u8 address)
{
// set the bank
enc28j60SetBank(address);
// do the read
return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
}
void enc28j60Write(u8 address, u8 data)
{
// set the bank
enc28j60SetBank(address);
// do the write
enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
}
u16 enc28j60PhyRead(u8 address)
{
u16 data;
// Set the right address and start the register read operation
enc28j60Write(MIREGADR, address);
enc28j60Write(MICMD, MICMD_MIIRD);
// wait until the PHY read completes
while(enc28j60Read(MISTAT) & MISTAT_BUSY);
// quit reading
enc28j60Write(MICMD, 0x00);
// get data value
data = enc28j60Read(MIRDL);
//data |= enc28j60Read(MIRDH);
data = enc28j60Read(MIRDH)<<8 | data;
// return the data
return data;
}
void enc28j60PhyWrite(u8 address, u16 data)
{
// set the PHY register address
enc28j60Write(MIREGADR, address);
// write the PHY data
enc28j60Write(MIWRL, data);
enc28j60Write(MIWRH, data>>8);
// wait until the PHY write completes
while(enc28j60Read(MISTAT) & MISTAT_BUSY){
printk("MISTAT:0x%02x\n",enc28j60Read(MISTAT));
udelay(100);
}
}
void nicGetMacAddress(u8* macaddr)
{
// read MAC address registers
// NOTE: MAC address in ENC28J60 is byte-backward
*macaddr++ = enc28j60Read(MAADR5);
*macaddr++ = enc28j60Read(MAADR4);
*macaddr++ = enc28j60Read(MAADR3);
*macaddr++ = enc28j60Read(MAADR2);
*macaddr++ = enc28j60Read(MAADR1);
*macaddr++ = enc28j60Read(MAADR0);
}
void nicSetMacAddress(u8* macaddr)
{
// write MAC address
// NOTE: MAC address in ENC28J60 is byte-backward
enc28j60Write(MAADR5, *macaddr++);
enc28j60Write(MAADR4, *macaddr++);
enc28j60Write(MAADR3, *macaddr++);
enc28j60Write(MAADR2, *macaddr++);
enc28j60Write(MAADR1, *macaddr++);
enc28j60Write(MAADR0, *macaddr++);
}
void enc28j60_RegDump(void)
{
printk("RevID: 0x%02x\r\n", enc28j60Read(EREVID));
printk("Cntrl: ECON1 ECON2 ESTAT EIR EIE\r\n");
printk(" 0x%02x ",enc28j60Read(ECON1));
printk("0x%02x ",enc28j60Read(ECON2));
printk("0x%02x ",enc28j60Read(ESTAT));
printk("0x%02x ",enc28j60Read(EIR));
printk("0x%02x\n\n",enc28j60Read(EIE));
printk("MAC : MACON1 MACON2 MACON3 MACON4 MAC-Address\r\n");
printk(" 0x%02x ",enc28j60Read(MACON1));
printk("0x%02x ",enc28j60Read(MACON2));
printk("0x%02x ",enc28j60Read(MACON3));
printk("0x%02x ",enc28j60Read(MACON4));
printk("%02x:",enc28j60Read(MAADR5));
printk("%02x:",enc28j60Read(MAADR4));
printk("%02x:",enc28j60Read(MAADR3));
printk("%02x:",enc28j60Read(MAADR2));
printk("%02x:",enc28j60Read(MAADR1));
printk("%02x\n\n",enc28j60Read(MAADR0));
printk("Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL\r\n");
printk(" 0x%02x:",enc28j60Read(ERXSTH));
printk("0x%02x ",enc28j60Read(ERXSTL));
printk("0x%02x:",enc28j60Read(ERXNDH));
printk("0x%02x ",enc28j60Read(ERXNDL));
printk("0x%02x:",enc28j60Read(ERXWRPTH));
printk("0x%02x ",enc28j60Read(ERXWRPTL));
printk("0x%02x:",enc28j60Read(ERXRDPTH));
printk("0x%02x ",enc28j60Read(ERXRDPTL));
printk("0x%02x ",enc28j60Read(ERXFCON));
printk("0x%02x ",enc28j60Read(EPKTCNT));
printk("0x%02x:",enc28j60Read(MAMXFLH));
printk("0x%02x\n",enc28j60Read(MAMXFLL));
printk("Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP\r\n");
printk("0x%02x:",enc28j60Read(ETXSTH));
printk("0x%02x ",enc28j60Read(ETXSTL));
printk("0x%02x:",enc28j60Read(ETXNDH));
printk("0x%02x ",enc28j60Read(ETXNDL));
printk("0x%02x ",enc28j60Read(MACLCON1));
printk("0x%02x ",enc28j60Read(MACLCON2));
printk("0x%02x\n",enc28j60Read(MAPHSUP));
udelay(1000);
}
static struct net_device_stats *
get_stats(struct net_device *dev)
{
return (struct net_device_stats *)(dev->priv);
}
int enc28j60_open (struct net_device *dev)
{
printk("enc28j60_open called\n");
netif_start_queue (dev);
return 0;
}
int enc28j60_release (struct net_device *dev)
{
printk ("enc28j60_release called\n");
netif_stop_queue(dev);
return 0;
}
static int enc28j60_xmit (struct sk_buff *skb,
struct net_device *dev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -