您的位置:首页 > 运维架构 > Linux

cs8900移植到linux2.6.32.2(注意make clean后可能会被清除所做的修改)

2012-09-11 15:56 447 查看
1.将准备好的cs8900.c/cs8900.h两个文件复制到drivers/net/arm目录下2.在include/net/目录下创建文件smdk2410.h,并添加如下代码:  #define pSMDK2410_ETH_IO
__phys_to_pfn(0x19000000)  #define vSMDK2410_ETH_IO 0xE0000000  #define SMDK2410_EHT_IRQ IRQ_EINT93.在arch/arm/mach-s3c2440/mach-smdk2410.c中加入"include <net/smdk2410.h>"在struct map_desc smdk2440_iodesc[]中添加cs8900相应的io空间映射:   {vSMDK2410_ETH_IO, pSMDK2410_ETH_IO, SZ_1M, MT_DEVICE}4.在drivers/net/arm/目录下的Makefile中加入cs8900相关项:    obj-$(CONFIG_ARM_CS8900) +=
cs8900.o 在drivers/net/arm/目录下的Kconfig中加入cs8900相关项:config ARM_CS8900tristate
"CS8900 support"depends
on NET_ETHERNET && ARM && (ARCH_SMDK2410 || ARCH_ZL2440 || MACH_MINI2440)helpSupport
for CS8900A chipset based Ethernet cards. If you have anetwork
(Ethernet) card of this type, say Y and read theEthernet-HOWTO,
available from<http://www.tldp.org/docs.html#howto>
as well as <file:Documentation/networking/cs89x0.txt>.5.make menuconfig选中cs8900选项,去掉dm9000选项。6.make 之后可以启动了。下面说一下内核中网卡和cs8900驱动相关的话题:由于内核更新后,struct net_device结构体及相关宏定义有变化,或造成在2.6.16/2.6.22/2.6.24内核工作的cs8900驱动在2.6.36上不能编译通过。主要修改如下:1>"IRQT_RISING"改成"IRQ_TYPE_EDGE_RISING"2>2.6.36内核的net_device中没有“priv“和"mc_list"项”。代码都要作相应修改。3>以前内核(2.6.16/2.6.22/2.6.24)struct
net_device中的函数指针域在2.6.36中都放在struct net_device_ops类型的指针netdev_ops指向的结构体中。也要作相应修改。附件是修改后的cs8900.c和cs8900.h文件。文件传不上来。贴上吧。下面是cs8900.c文件:
#define VERSION_STRING "Cirrus Logic CS8900A driver for Linux (Modified for ZL2440)"

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/types.h>

#include <linux/version.h>

#include <linux/errno.h>

#include <linux/init.h>

#include <linux/delay.h>

#include <linux/ioport.h>

#include <linux/pm.h>

#include <linux/irq.h>

//#include <asm/hardware.h>

#include <asm/io.h>

#include <asm/uaccess.h>

#include <linux/netdevice.h>

#include <linux/etherdevice.h>

#include <linux/skbuff.h>

// Added BSt

#include <asm/mach-types.h>

//#ifdef CONFIG_ARCH_SMDK2410

#if 1

//#include "asm/arch-s3c2410/regs-irq.h"

#include "mach/regs-mem.h"

//#include "asm/arch/smdk2410.h"

#include "net/smdk2410.h"

#endif

#include "cs8900.h"

//#define FULL_DUPLEX

//#define DEBUG

typedef struct {

struct net_device_stats stats;

u16 txlen;

int char_devnum;

spinlock_t lock;

} cs8900_t;

int cs8900_probe (struct net_device *dev);

static struct net_device *cs8900_dev ;

#define MAX_EEPROM_SIZE        256

static inline u16 cs8900_read (struct net_device *dev,u16 reg)

{

outw (reg,dev->base_addr + PP_Address);

return (inw (dev->base_addr + PP_Data));

}

static inline void cs8900_write (struct net_device *dev,u16
reg,u16 value)

{

outw (reg,dev->base_addr + PP_Address);

outw (value,dev->base_addr + PP_Data);

}

static inline void cs8900_set (struct net_device *dev,u16
reg,u16 value)

{

cs8900_write (dev,reg,cs8900_read (dev,reg) | value);

}

static inline void cs8900_clear (struct net_device *dev,u16
reg,u16 value)

{

cs8900_write (dev,reg,cs8900_read (dev,reg) & ~value);

}

static inline void cs8900_frame_read (struct net_device *dev,struct sk_buff *skb,u16
length)

{

insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2);

}

static inline void cs8900_frame_write (struct net_device *dev,struct sk_buff *skb)

{

outsw (dev->base_addr,skb->data,(skb->len + 1) / 2);

}

#ifdef DEBUG

static inline int printable (int c)

{

return ((c >= 32 && c <= 126) ||

(c >= 174 && c <= 223) ||

(c >= 242 && c <= 243) ||

(c >= 252 && c <= 253));

}

static void dump16 (struct net_device *dev,const u8 *s,size_t len)

{

int i;

char str[128];

if (!len) return;

*str = '\0';

for (i = 0; i < len; i++) {

if (i && !(i % 4)) strcat (str,"
");

sprintf (str,"%s%.2x ",str,s[i]);

}

for ( ; i < 16; i++) {

if (i && !(i % 4)) strcat (str,"
");

strcat (str," ");

}

strcat (str," ");

for (i = 0; i < len; i++) sprintf (str,"%s%c",str,printable (s[i]) ? s[i] : '.');

printk (KERN_DEBUG "%s: %s\n",dev->name,str);

}

static void hexdump (struct net_device *dev,const void *ptr,size_t size)

{

const u8 *s = (u8 *) ptr;

int i;

for (i = 0; i < size / 16; i++, s += 16) dump16 (dev,s,16);

dump16 (dev,s,size % 16);

}

static void dump_packet (struct net_device *dev,struct sk_buff *skb,const char *type)

{

printk (KERN_INFO "%s: %s %d byte frame %.2x:%.2x:%.2x:%.2x:%.2x:%.2x to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x type %.4x\n",

dev->name,

type,

skb->len,

skb->data[0],skb->data[1],skb->data[2],skb->data[3],skb->data[4],skb->data[5],

skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11],

(skb->data[12] << 8) | skb->data[13]);

if (skb->len < 0x100) hexdump (dev,skb->data,skb->len);

}

#endif

static void cs8900_receive (struct net_device *dev)

{

//cs8900_t *priv = (cs8900_t *) dev->priv;

cs8900_t *priv = (cs8900_t *)netdev_priv(dev);

struct sk_buff *skb;

u16 status,length;

status = cs8900_read (dev,PP_RxStatus);

length = cs8900_read (dev,PP_RxLength);

if (!(status & RxOK)) {

priv->stats.rx_errors++;

if ((status & (Runt | Extradata))) priv->stats.rx_length_errors++;

if ((status & CRCerror)) priv->stats.rx_crc_errors++;

return;

}

if ((skb = dev_alloc_skb (length + 4)) == NULL) {

priv->stats.rx_dropped++;

return;

}

skb->dev = dev;

skb_reserve (skb,2);

cs8900_frame_read (dev,skb,length);

#ifdef FULL_DUPLEX

dump_packet (dev,skb,"recv");

#endif

skb->protocol = eth_type_trans (skb,dev);

netif_rx (skb);

dev->last_rx = jiffies;

priv->stats.rx_packets++;

priv->stats.rx_bytes += length;

}

static int cs8900_send_start (struct sk_buff *skb,struct net_device *dev)

{

//cs8900_t *priv = (cs8900_t *) dev->priv;

cs8900_t *priv = (cs8900_t *)netdev_priv(dev);

u16 status;

spin_lock_irq(&priv->lock);

netif_stop_queue (dev);

cs8900_write (dev,PP_TxCMD,TxStart (After5));

cs8900_write (dev,PP_TxLength,skb->len);

status = cs8900_read (dev,PP_BusST);

if ((status & TxBidErr)) {

spin_unlock_irq(&priv->lock);

printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);

priv->stats.tx_errors++;

priv->stats.tx_aborted_errors++;

priv->txlen = 0;

return (1);

}

if (!(status & Rdy4TxNOW)) {

spin_unlock_irq(&priv->lock);

printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);

priv->stats.tx_errors++;

priv->txlen = 0;

return (1);

}

cs8900_frame_write (dev,skb);

spin_unlock_irq(&priv->lock);

#ifdef DEBUG

dump_packet (dev,skb,"send");

#endif

dev->trans_start = jiffies;

dev_kfree_skb (skb);

priv->txlen = skb->len;

return (0);

}

static irqreturn_t cs8900_interrupt (int irq,void *id)

{

struct net_device *dev = (struct net_device *) id;

cs8900_t *priv;

volatile u16 status;

irqreturn_t handled = 0;

#if 0

if (dev->priv == NULL) {

printk (KERN_WARNING "%s: irq %d for unknown device.\n",dev->name,irq);

return 0;

}

#endif

//priv = (cs8900_t *) dev->priv;

priv = (cs8900_t *)netdev_priv(dev);

while ((status = cs8900_read (dev, PP_ISQ))) {

handled = 1;

switch (RegNum (status)) {

case RxEvent:

cs8900_receive (dev);

break;

case TxEvent:

priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));

if (!(RegContent (status) & TxOK)) {

priv->stats.tx_errors++;

if ((RegContent (status) & Out_of_window)) priv->stats.tx_window_errors++;

if ((RegContent (status) & Jabber)) priv->stats.tx_aborted_errors++;

break;

} else if (priv->txlen) {

priv->stats.tx_packets++;

priv->stats.tx_bytes += priv->txlen;

}

priv->txlen = 0;

netif_wake_queue (dev);

break;

case BufEvent:

if ((RegContent (status) & RxMiss)) {

u16 missed = MissCount (cs8900_read (dev,PP_RxMISS));

priv->stats.rx_errors += missed;

priv->stats.rx_missed_errors += missed;

}

if ((RegContent (status) & TxUnderrun)) {

priv->stats.tx_errors++;

priv->stats.tx_fifo_errors++;

priv->txlen = 0;

netif_wake_queue (dev);

}

break;

case TxCOL:

priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));

break;

case RxMISS:

status = MissCount (cs8900_read (dev,PP_RxMISS));

priv->stats.rx_errors += status;

priv->stats.rx_missed_errors += status;

break;

}

}

return IRQ_RETVAL(handled);

}

static void cs8900_transmit_timeout (struct net_device *dev)

{

//cs8900_t *priv = (cs8900_t *) dev->priv;

cs8900_t *priv = (cs8900_t *)netdev_priv(dev);

priv->stats.tx_errors++;

priv->stats.tx_heartbeat_errors++;

priv->txlen = 0;

netif_wake_queue (dev);

}

static int cs8900_start (struct net_device *dev)

{

int result;

//set_irq_type(dev->irq, IRQT_RISING);

set_irq_type(dev->irq, IRQ_TYPE_EDGE_RISING);

cs8900_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE);

cs8900_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA);

cs8900_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE);

cs8900_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE);

cs8900_set (dev,PP_LineCTL,SerRxON | SerTxON);

cs8900_set (dev,PP_BusCTL,EnableRQ);

#ifdef FULL_DUPLEX

cs8900_set (dev,PP_TestCTL,FDX);

#endif

udelay(200);

if ((result = request_irq (dev->irq, &cs8900_interrupt, 0, dev->name, dev)) <0) {

printk (KERN_ERR "%s: could not register interrupt %d\n",dev->name, dev->irq);

return (result);

}

netif_start_queue (dev);

return (0);

}

static int cs8900_stop (struct net_device *dev)

{

cs8900_write (dev,PP_BusCTL,0);

cs8900_write (dev,PP_TestCTL,0);

cs8900_write (dev,PP_SelfCTL,0);

cs8900_write (dev,PP_LineCTL,0);

cs8900_write (dev,PP_BufCFG,0);

cs8900_write (dev,PP_TxCFG,0);

cs8900_write (dev,PP_RxCTL,0);

cs8900_write (dev,PP_RxCFG,0);

free_irq (dev->irq,dev);

netif_stop_queue (dev);

return (0);

}

static struct net_device_stats *cs8900_get_stats (struct net_device *dev)

{

//cs8900_t *priv = (cs8900_t *) dev->priv;

cs8900_t *priv = (cs8900_t *)netdev_priv(dev);

return (&priv->stats);

}

static void cs8900_set_receive_mode (struct net_device *dev)

{

if ((dev->flags & IFF_PROMISC))

cs8900_set (dev,PP_RxCTL,PromiscuousA);

else

cs8900_clear (dev,PP_RxCTL,PromiscuousA);

//if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)

if ((dev->flags & IFF_ALLMULTI) && !netdev_mc_empty(dev))

cs8900_set (dev,PP_RxCTL,MulticastA);

else

cs8900_clear (dev,PP_RxCTL,MulticastA);

}

int __init cs8900_probe (struct net_device *dev)

{

static cs8900_t *priv;

int i,result;

u16 value;

printk (VERSION_STRING"\n");

memset (&priv,0,sizeof (cs8900_t));

//+kevin

__raw_writel(0x2211d110,S3C2410_BWSCON);

__raw_writel(0x1f7c,S3C2410_BANKCON3);

//#if defined(CONFIG_ARCH_SMDK2410)

#if 1

dev->dev_addr[0] = 0x00;

dev->dev_addr[1] = 0x00;

dev->dev_addr[2] = 0x3e;

dev->dev_addr[3] = 0x26;

dev->dev_addr[4] = 0x0a;

dev->dev_addr[5] = 0x00;

#endif

dev->if_port = IF_PORT_10BASET;

//dev->priv = (void *) &priv;

priv = (cs8900_t *)netdev_priv(dev);

spin_lock_init(&priv->lock);

//hejiasheng SET_MODULE_OWNER (dev);

//#if defined(CONFIG_ARCH_SMDK2410)

#if 1

dev->base_addr = vSMDK2410_ETH_IO + 0x300;

dev->irq = IRQ_EINT9;

printk("debug:[%s-%d]\n", __func__, __LINE__);

#endif

if ((result = check_mem_region (dev->base_addr, 16))) {

printk (KERN_ERR "%s: can't get I/O port address 0x%lx\n",dev->name,dev->base_addr);

return (result);

}

request_mem_region (dev->base_addr, 16, dev->name);

printk("debug:[%s-%d]\n", __func__, __LINE__);

if ((value = cs8900_read (dev,PP_ProductID)) != EISA_REG_CODE) {

printk (KERN_ERR "%s: incorrect signature 0x%.4x\n",dev->name,value);

return (-ENXIO);

}

printk("debug:[%s-%d]\n", __func__, __LINE__);

value = cs8900_read (dev,PP_ProductID + 2);

if (VERSION (value) != CS8900A) {

printk (KERN_ERR "%s: unknown chip version 0x%.8x\n",dev->name,VERSION (value));

return (-ENXIO);

}

cs8900_write (dev,PP_IntNum,0);

printk (KERN_INFO "%s: CS8900A rev %c at %#lx irq=%d",

dev->name,'B' + REVISION (value) - REV_B, dev->base_addr, dev->irq);

for (i = 0; i < ETH_ALEN; i += 2)

cs8900_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8));

printk (", addr:");

for (i = 0; i < ETH_ALEN; i += 2)

{

u16 mac = cs8900_read (dev,PP_IA + i);

printk ("%cX:%2X", (i==0)?'
':':', mac & 0xff, (mac >> 8));

}

printk ("\n");

return (0);

}

static const struct net_device_ops net_ops = {

.ndo_init = cs8900_probe,

.ndo_open        = cs8900_start,

.ndo_stop        = cs8900_stop,

.ndo_tx_timeout        = cs8900_transmit_timeout,

.ndo_start_xmit     = cs8900_send_start,

.ndo_get_stats        = cs8900_get_stats,

.ndo_set_multicast_list = cs8900_set_receive_mode,

#if 0

.ndo_set_mac_address     = set_mac_address,

.ndo_poll_controller    = net_poll_controller,

.ndo_change_mtu        = eth_change_mtu,

.ndo_validate_addr    = eth_validate_addr,

#endif

};

static int __init cs8900_init (void)

{

struct net_device *ndev;

ndev = alloc_etherdev(sizeof (cs8900_t));

if (!ndev) {

printk("%s: could not allocate device.\n", "cs8900");

return -ENOMEM;

}

printk("allocate cs8900 device ok.\n");

cs8900_dev = ndev;

//cs8900_dev->init = cs8900_probe;

ether_setup (ndev);

#if 0

ndev->open = cs8900_start;

ndev->stop = cs8900_stop;

ndev->hard_start_xmit = cs8900_send_start;

ndev->get_stats = cs8900_get_stats;

ndev->set_multicast_list = cs8900_set_receive_mode;

ndev->tx_timeout = cs8900_transmit_timeout;

#endif

ndev->netdev_ops = &net_ops;

ndev->watchdog_timeo = HZ;

return (register_netdev (cs8900_dev));

}

static void __exit cs8900_cleanup (void)

{

//    cs8900_t *priv = (cs8900_t *) cs8900_dev->priv;

cs8900_t *priv = (cs8900_t *)netdev_priv(cs8900_dev);

if( priv->char_devnum)

{

unregister_chrdev(priv->char_devnum,"cs8900_eeprom");

}

release_mem_region (cs8900_dev->base_addr,16);

unregister_netdev (cs8900_dev);

}

MODULE_AUTHOR ("Abraham van der Merwe <abraham at 2d3d.co.za>");

MODULE_DESCRIPTION (VERSION_STRING);

MODULE_LICENSE ("GPL");

module_init (cs8900_init);

module_exit (cs8900_cleanup);

下面是cs8900.h
#ifndef CS8900_H

#define CS8900_H

#define PP_Address        0x0a

#define PP_Data            0x0c

#define PP_ProductID        0x0000

#define PP_MemBase            0x002c

#define PP_IntNum            0x0022

#define PP_EEPROMCommand    0x0040

#define PP_EEPROMData        0x0042

#define PP_RxCFG            0x0102

#define PP_RxCTL            0x0104

#define PP_TxCFG            0x0106

#define PP_BufCFG            0x010a

#define PP_LineCTL            0x0112

#define PP_SelfCTL            0x0114

#define PP_BusCTL            0x0116

#define PP_TestCTL            0x0118

#define PP_ISQ                0x0120

#define PP_TxEvent            0x0128

#define PP_BufEvent            0x012c

#define PP_RxMISS            0x0130

#define PP_TxCOL            0x0132

#define PP_SelfST            0x0136

#define PP_BusST            0x0138

#define PP_TxCMD            0x0144

#define PP_TxLength            0x0146

#define PP_IA                0x0158

#define PP_RxStatus            0x0400

#define PP_RxLength            0x0402

#define PP_RxFrame            0x0404

#define PP_TxFrame            0x0a00

#define INTRQ0            0x0000

#define INTRQ1            0x0001

#define INTRQ2            0x0002

#define INTRQ3            0x0003

#define EISA_REG_CODE    0x630e

#define REVISION(x)        (((x) & 0x1f00) >> 8)

#define VERSION(x)        ((x) & ~0x1f00)

#define CS8900A            0x0000

#define REV_B            7

#define REV_C            8

#define REV_D            9

#define Skip_1            0x0040

#define StreamE            0x0080

#define RxOKiE            0x0100

#define RxDMAonly        0x0200

#define AutoRxDMAE        0x0400

#define BufferCRC        0x0800

#define CRCerroriE        0x1000

#define RuntiE            0x2000

#define ExtradataiE        0x4000

#define IAHashA            0x0040

#define PromiscuousA    0x0080

#define RxOKA            0x0100

#define MulticastA        0x0200

#define IndividualA        0x0400

#define BroadcastA        0x0800

#define CRCerrorA        0x1000

#define RuntA            0x2000

#define ExtradataA        0x4000

#define Loss_of_CRSiE    0x0040

#define SQErroriE        0x0080

#define TxOKiE            0x0100

#define Out_of_windowiE    0x0200

#define JabberiE        0x0400

#define AnycolliE        0x0800

#define T16colliE        0x8000

#define SWint_X            0x0040

#define RxDMAiE            0x0080

#define Rdy4TxiE        0x0100

#define TxUnderruniE    0x0200

#define RxMissiE        0x0400

#define Rx128iE            0x0800

#define TxColOvfiE        0x1000

#define MissOvfloiE        0x2000

#define RxDestiE        0x8000

#define SerRxON            0x0040

#define SerTxON            0x0080

#define AUIonly            0x0100

#define AutoAUI_10BT    0x0200

#define ModBackoffE        0x0800

#define PolarityDis        0x1000

#define L2_partDefDis    0x2000

#define LoRxSquelch        0x4000

#define RESET            0x0040

#define SWSuspend        0x0100

#define HWSleepE        0x0200

#define HWStandbyE        0x0400

#define HC0E            0x1000

#define HC1E            0x2000

#define HCB0            0x4000

#define HCB1            0x8000

#define ResetRxDMA        0x0040

#define DMAextend        0x0100

#define UseSA            0x0200

#define MemoryE            0x0400

#define DMABurst        0x0800

#define IOCHRDYE        0x1000

#define RxDMAsize        0x2000

#define EnableRQ        0x8000

#define DisableLT        0x0080

#define ENDECloop        0x0200

#define AUIloop            0x0400

#define DisableBackoff    0x0800

#define FDX                0x4000

#define RegNum(x) ((x) & 0x3f)

#define RegContent(x) ((x) & ~0x3d)

#define RxEvent            0x0004

#define TxEvent            0x0008

#define BufEvent        0x000c

#define RxMISS            0x0010

#define TxCOL            0x0012

#define IAHash            0x0040

#define Dribblebits        0x0080

#define RxOK            0x0100

#define Hashed            0x0200

#define IndividualAdr    0x0400

#define Broadcast        0x0800

#define CRCerror        0x1000

#define Runt            0x2000

#define Extradata        0x4000

#define HashTableIndex(x) ((x) >> 0xa)

#define After5            0

#define After381        1

#define After1021        2

#define AfterAll        3

#define TxStart(x) ((x) << 6)

#define Force            0x0100

#define Onecoll            0x0200

#define InhibitCRC        0x1000

#define TxPadDis        0x2000

#define TxBidErr        0x0080

#define Rdy4TxNOW        0x0100

#define Loss_of_CRS        0x0040

#define SQEerror        0x0080

#define TxOK            0x0100

#define Out_of_window    0x0200

#define Jabber            0x0400

#define T16coll            0x8000

#define TX_collisions(x) (((x) >> 0xb) & ~0x8000)

#define SWint            0x0040

#define RxDMAFrame        0x0080

#define Rdy4Tx            0x0100

#define TxUnderrun        0x0200

#define RxMiss            0x0400

#define Rx128            0x0800

#define RxDest            0x8000

#define MissCount(x) ((x) >> 6)

#define ColCount(x) ((x) >> 6)

#define T3VActive        0x0040

#define INITD            0x0080

#define SIBUSY            0x0100

#define EEPROMpresent    0x0200

#define EEPROMOK        0x0400

#define ELpresent        0x0800

#define EEsize            0x1000

#define EEWriteEnable 0x00F0

#define EEWriteDisable 0x0000

#define EEWriteRegister    0x0100

#define EEReadRegister    0x0200

#define EEEraseRegister    0x0300

#define ELSEL            0x0400

#endif


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: