Chinaunix首页 | 论坛 | 博客
  • 博客访问: 27615
  • 博文数量: 10
  • 博客积分: 1653
  • 博客等级: 民兵
  • 技术积分: 60
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-08 12:04
文章分类
文章存档

2012年(3)

2011年(7)

最近访客

分类:

2011-09-12 09:39:41

移植Linux2.6.22.2到友善之臂SBC2440V4(s3c2440AL)(双网卡)

   昨天成功移植了U-Boot到SBC2440V4,今天把Linux2.6.22.2也移植上去。其实有了前面2410-S的移植经验以后,移植到SBC2440V4是一件很简单的事(虽然也碰到了点麻烦)。在移植时我基本都是按照【置顶】移植Linux2.6.22.2到博创2410-S(s3c2410A)(1)【置顶】移植Linux2.6.22.2到博创2410-S(s3c2410A)(3) 来移植的,只是稍加改动就好。在这里我就不在具体的讲了,我只详述一下与移植到2410-S不同的地方。

这次移植除了使用我以前的移植纪录外,还重点参考了:
(0)S3C2440英文数据手册
(1)《linux内核中设置CPU工作频率》URL:
(2)DM9000英文数据手册
(3)cs8900a驱动移植笔记  URL:
(4)WeiBing博客中的文章 cs8900 移植 Linux-2.6.19.2
(5)友善之臂SBC2440V4原理图 

首先,Linux2.6.22.2本身就支持s3c2440处理器,由于2410和2440基本兼容,所以在linux源码里2440的很多文件是和2410共用的。所以在按照我移植2410记录的基础上,主要修改如下:
 
一、开发板选项的选择。
System Type  --->      
   S3C2440 Machines  --->  
    [*] SMDK2440
    [*] SMDK2440 with S3C2440 CPU module
留下这两项就够了,S3C2400 Machines  ---> 、S3C2410 Machines  --->、S3C2412 Machines  --->、S3C2442 Machines  --->、S3C2443 Machines  --->里的项目全部“N”掉。
 
这两个选项是区分你的目标芯片是2410还是2440的关键选项!!
二、系统初始化时的芯片晶振频率的修改,修改arch/arm/mach-s3c2440/mach-smdk2440.c
 ......
    static void __init smdk2440_map_io(void)
{
    s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
    s3c24xx_init_clocks(12000000);
    s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}
 ......
如果没有改这个参数,系统启动时到了"done, booting the kernel."之后就会出现乱码现象或是没有输出。我一开始就碰到了这个麻烦。出现此类乱码或没有输出现象的另一个原因可能是你的bootloader对CPU的主频和分频的设置不正确。SBC2440V4的设置最好是时钟频率405MHz,分频比为1:4:8,不然有可能出现上述现象。请看参考资料(1)。
三、开发板四个LED指示灯的驱动修改
   SBC2440V4和SMDK2440一样有四个LED指示灯。指示用的GPIO口不一样。参考SBC2440V4的硬件说明书,修改/arch/arm/plat-s3c24xx/common-smdk.c如下:

......
static struct s3c24xx_led_platdata smdk_pdata_led4 = {
    .gpio        = S3C2410_GPB5,
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "led4",
    .def_trigger    = "timer",
};

static struct s3c24xx_led_platdata smdk_pdata_led5 = {
    .gpio        = S3C2410_GPB6,
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "led5",
    .def_trigger    = "nand-disk",
};

static struct s3c24xx_led_platdata smdk_pdata_led6 = {
    .gpio        = S3C2410_GPB7,
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "dm9000",
};

static struct s3c24xx_led_platdata smdk_pdata_led7 = {
    .gpio        = S3C2410_GPB8,
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "cs89x0",
};
 ......
void __init smdk_machine_init(void)
{
    /* Configure the LEDs (even if we have no LED support)*/

    s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPB5_OUTP);
    s3c2410_gpio_cfgpin(S3C2410_GPB6, S3C2410_GPB6_OUTP);
    s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPB7_OUTP);
    s3c2410_gpio_cfgpin(S3C2410_GPB8, S3C2410_GPB8_OUTP);

    s3c2410_gpio_setpin(S3C2410_GPB5, 1);
    s3c2410_gpio_setpin(S3C2410_GPB6, 1);
    s3c2410_gpio_setpin(S3C2410_GPB7, 0);
    s3c2410_gpio_setpin(S3C2410_GPB8, 0);

    if (machine_is_smdk2443())
        smdk_nand_info.twrph0 = 50;

    s3c_device_nand.dev.platform_data = &smdk_nand_info;

    platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));

    s3c2410_pm_init();
}
......

修改成功的现象,启动时LED1和LED2会亮一下;nand flash 读写时LED2会闪动;dm9000有网络活动时,LED3会亮;cs8900有网络活动时,LED4会亮。由于dm9000是作为NFS挂载的网卡,所以LED3亮的时间比较多。
 

四、修改/driver/net/Kconfig文件,使其在配置时出现cs89x0的选项。
......
config CS89x0
 tristate "CS89x0 support"
 ---help---
 depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
   Support for CS89x0 chipset based Ethernet cards. If you have a
   network (Ethernet) card of this type, say Y and read the
   Ethernet-HOWTO, available from
   <> as well as
   .
   To compile this driver as a module, choose M here and read
   .  The module will be
   called cs89x0.
就是使 depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)那一句失效。我是把它放到了 ---help---下面,你也可以把它删了。
以下是双网卡的移植,首先要说明的是如果都编译进内核中,双网卡在启动时会无法挂载NFS,会出现IP配置失败的提示。单独编译时都不会出现这种情况。原因我不知道。(那位大侠如果解决了记得通知一声) 经过多次试验发现:要实现双网卡,又要挂载NFS根文件系统最好的配置是将DM9000编译进内核(速度快),将
CS8900作为模块在启动后挂载。以下的移植就是针对这种情况修改的。

五、修改/driver/net/cs89x0.c文件,使其匹配SBC2440V4和cs8900
的硬件配置。
(并添加LED4在有网络操作时点亮的功能)
......
#include
#include
#include
#include
#if ALLOW_DMA
#include
#endif
#include "cs89x0.h"
//**********************tekkaman*************************
#include
#include
#include
#include
#include
#include
#define CS8900_BASE   (S3C2440_VA_ISA_CS8900)
#define CS8900_IRQ    IRQ_EINT9
//**********************tekkaman*****************************
static char version[] __initdata =
"cs89x0.c: v2.4.3-pre1 Russell Nelson <
>, Andrew Morton <";
DEFINE_LED_TRIGGER(cs89x0_led_trigger);
#define DRV_NAME "cs89x0"
......
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
#else
static unsigned int netcard_portlist[] __initdata = {CS8900_BASE, 0};
static unsigned int cs8900_irq_map[] = {CS8900_IRQ,0};

#endif
/* Index to functions, as function prototypes. */
static int cs89x0_probe1(struct net_device *dev,unsigned int ioaddr, int modular);
......
//static int get_eeprom_cksum(int off, int len, int *buffer);
......
struct net_device * __init cs89x0_probe(int unit)
{
 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
 unsigned int *port;
 int err = 0;
 unsigned int irq;
 unsigned int io;
//tekkaman
 static int once=0;
 unsigned int value;
//tekkaman

 if (!dev)
  return ERR_PTR(-ENODEV);
 sprintf(dev->name, "eth%d", unit);
 netdev_boot_setup_check(dev);
//******************************tekkaman********************************
     if (once) {
      return -ENXIO;
}
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_32);
value |= (S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_16);
__raw_writel(value, S3C2410_BWSCON);
value=0;
value = (S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
__raw_writel(value,S3C2410_BANKCON3);
set_irq_type(CS8900_IRQ,IRQ_TYPE_EDGE_RISING );
s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
s3c2410_gpio_pullup(S3C2410_GPG1, 0);
if(dev->base_addr==0){
 dev->base_addr = CS8900_BASE ;
 dev->irq = CS8900_IRQ;
 once++;
 }
 led_trigger_register_simple("cs89x0", &cs89x0_led_trigger);
//***********************************tekkaman************************************
 io = dev->base_addr;
 irq = dev->irq;
......
}
......
#else
static u16
readword(unsigned long base_addr, int portno)
{
 return __raw_readw(base_addr + portno);
}
static void
writeword(unsigned long base_addr, int portno, u16 value)
{
 __raw_writew(value, base_addr + portno);
}
#endif
......
#if 0
static int  __init
get_eeprom_cksum(int off, int len, int *buffer)
{
 int i, cksum;
 cksum = 0;
 for (i = 0; i < len; i++)
  cksum += buffer[i];
 cksum &= 0xffff;
 if (cksum == 0)
  return 0;
 return -1;
}
#endif
......
static int __init
cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular)
{
 struct net_local *lp = netdev_priv(dev);
 static unsigned version_printed;
 int i;
 int tmp;
 unsigned rev_type = 0;
// int eeprom_buff[CHKSUM_LEN];
 int retval;
 unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x27,0x12,0};//tekkaman
 SET_MODULE_OWNER(dev);
 /* Initialize the device structure. */
 if (!modular) {
  memset(lp, 0, sizeof(*lp));
  spin_lock_init(&lp->lock);
#ifndef MODULE
#if ALLOW_DMA
  if (g_cs89x0_dma) {
   lp->use_dma = 1;
   lp->dma = g_cs89x0_dma;
   lp->dmasize = 16; /* Could make this an option... */
  }
#endif
 // lp->force = g_cs89x0_media__force;
  lp->force = (FORCE_RJ45 | FORCE_FULL);
  lp->auto_neg_cnf=IMM_BIT;

......
#if 0
        if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
       (EEPROM_OK|EEPROM_PRESENT)) {
         /* Load the MAC. */
  for (i=0; i < ETH_ALEN/2; i++) {
                 unsigned int Addr;
   Addr = readreg(dev, PP_IA+i*2);
          dev->dev_addr[i*2] = Addr & 0xFF;
          dev->dev_addr[i*2+1] = Addr >> 8;
  }
......
  if (net_debug > 1)
   printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
    dev->name, lp->adapter_cnf);
        }
#endif
  for (i = 0; i < ETH_ALEN; i++) {
                        dev->dev_addr[i] = ne_defethaddr[i];
                        }
  
        /* allow them to force multiple transceivers.  If they force multiple, autosense */
        {
  int count = 0;
  if (lp->force & FORCE_RJ45) {lp->adapter_cnf |= A_CNF_10B_T; count++; }
  if (lp->force & FORCE_AUI)  {lp->adapter_cnf |= A_CNF_AUI; count++; }
  if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_10B_2; count++; }
  if (count > 1)   {lp->adapter_cnf |= A_CNF_MEDIA_AUTO; }
  else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; }
  else if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_MEDIA_AUI; }
  else if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_MEDIA_10B_2; }
        }
......
static int
detect_tp(struct net_device *dev)
{
......
 if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
  return DETECTED_NONE;
  lp->force = (FORCE_RJ45 | FORCE_FULL);
  lp->auto_neg_cnf=IMM_BIT;
 if (lp->chip_type == CS8900) {
                switch (lp->force & 0xf0) {
......
}
......
static int
net_open(struct net_device *dev)
{
......
  if (i >= CS8920_NO_INTS) {
   writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
   printk(KERN_ERR "cs89x0: can't get an interrupt\n");
   ret = -EAGAIN;
   goto bad_out;
  }
 }
 else
#endif
 {
#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410)
  if (((1 << dev->irq) & lp->irq_map) == 0) {
   printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                               dev->name, dev->irq, lp->irq_map);
   ret = -EAGAIN;
   goto bad_out;
  }
#endif
......
 /* set the Ethernet address */
 for (i=0; i < ETH_ALEN/2; i++)
  writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
 /* while we're testing the interface, leave interrupts disabled */
 writereg(dev, PP_BusCTL, MEMORY_ON);
 /* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
 if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
                lp->linectl = LOW_RX_SQUELCH;
 else
                lp->linectl = 0;
 lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T ;
        /* check to make sure that they have the "right" hardware available */
 switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
 case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
 case A_CNF_MEDIA_AUI:   result = lp->adapter_cnf & A_CNF_AUI; break;
 case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
        default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
        }
......
}
......
static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
 struct net_local *lp = netdev_priv(dev);
 led_trigger_event(cs89x0_led_trigger, LED_FULL);
......
 led_trigger_event(cs89x0_led_trigger, LED_OFF);
 return 0;
}
/* The typical workload of the driver:
   Handle the network interface interrupts. */
static irqreturn_t net_interrupt(int irq, void *dev_id)
{
 struct net_device *dev = dev_id;
 struct net_local *lp;
 unsigned int ioaddr, status;
  int handled = 0;
......
}
......
static void
net_rx(struct net_device *dev)
{
 struct net_local *lp = netdev_priv(dev);
 struct sk_buff *skb;
 int status, length;
 led_trigger_event(cs89x0_led_trigger, LED_FULL);
 unsigned int ioaddr = dev->base_addr;
 status = readword(ioaddr, RX_FRAME_PORT);
 length = readword(ioaddr, RX_FRAME_PORT);
......

 led_trigger_event(cs89x0_led_trigger, LED_OFF);
}
......
#ifdef MODULE
static struct net_device *dev_cs89x0;
/*
 * Support the 'debug' module parm even if we're compiled for non-debug to
 * avoid breaking someone's startup scripts
 */
static unsigned int io=CS8900_BASE;
static unsigned int irq=CS8900_IRQ;

static int debug;
static char media[8]="rj45";
static int duplex=-1;
static int use_dma;   /* These generate unused var warnings if ALLOW_DMA = 0 */
static int dma;
static int dmasize=16;   /* or 64 */
module_param(io, uint, 0);
module_param(irq,  uint, 0);
module_param(debug, int, 0);
......
int __init init_module(void)
{
 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
 struct net_local *lp;
 int ret = 0;
#if DEBUGGING
 net_debug = debug;
#else
 debug = 0;
#endif
//tekkaman 
 unsigned int value;
 value = __raw_readl(S3C2410_BWSCON);
 value &= ~(S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_32);
 value |= (S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_16);
 __raw_writel(value, S3C2410_BWSCON);
 value=0;
 value = (S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
 __raw_writel(value,S3C2410_BANKCON3);
 set_irq_type(CS8900_IRQ,IRQ_TYPE_EDGE_RISING );
 s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
 s3c2410_gpio_pullup(S3C2410_GPG1, 0);
 led_trigger_register_simple("cs89x0", &cs89x0_led_trigger);
//tekkaman
 if (!dev)
  return -ENOMEM;
......
}
......
特别说明:除了总线配置语句一定要加,否则网卡运行时会出现“time out”的错误之外,还有一个十分重要的地方:在驱动中存储 基地址 和中断 的变量一点要统一定义为unsigned int 否则会出错。
 

六、修改/driver/net/dm9000.c文件,使其匹配SBC2440V4和DM9000的硬件配置(并添加LED3在有网络操作时点亮的功能)
 
......
#include    //LED驱动头文件
......
//**********************tekkaman*************************
#include
#include
#include
#include
#include
#include
#define DM9000_IRQ    IRQ_EINT7
//**********************tekkaman*****************************

/*
 * Transmit timeout, default 5 seconds.
 */
static int watchdog = 5000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
DEFINE_LED_TRIGGER(dm9000_led_trigger);
......
static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
      int value);
//static u16 read_srom_word(board_info_t *, int);
static void dm9000_rx(struct net_device *);
static void dm9000_hash_table(struct net_device *);
//tekkaman
#undef DM9000_PROGRAM_EEPROM
//tekkaman
#ifdef DM9000_PROGRAM_EEPROM
static void program_eeprom(board_info_t * db);
#endif
......
#if  0
//def CONFIG_NET_POLL_CONTROLLER

/*
 *Used by netconsole
 */
static void dm9000_poll_controller(struct net_device *dev)
{
 disable_irq(dev->irq);
 dm9000_interrupt(dev->irq,dev);
 enable_irq(dev->irq);
}
#endif
......
static int
dm9000_probe(struct platform_device *pdev)
{
 struct dm9000_plat_data *pdata = pdev->dev.platform_data;
 struct board_info *db; /* Point a board information structure */
 struct net_device *ndev;
 unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman
 unsigned long base;
 int ret = 0;
 int iosize;
 int i;
 u32 id_val;
//******************************tekkaman********************************
 unsigned int value;
static int once=0;
     if (once) {
      return -ENXIO;
}
//tekkaman
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_32);
value |= (S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_16);
__raw_writel(value, S3C2410_BWSCON);
value=0;
value = (S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
__raw_writel(value,S3C2410_BANKCON4);
set_irq_type(DM9000_IRQ,IRQ_TYPE_LEVEL_HIGH );
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_EINT7);
s3c2410_gpio_pullup(S3C2410_GPF7, 0);
//******************************tekkaman********************************

 /* Init network device */
 ndev = alloc_etherdev(sizeof (struct board_info));
 if (!ndev) {
  printk("%s: could not allocate device.\n", CARDNAME);
  return -ENOMEM;
 }
......
#if  0
def CONFIG_NET_POLL_CONTROLLER
 ndev->poll_controller  = &dm9000_poll_controller;
#endif
#ifdef DM9000_PROGRAM_EEPROM
 program_eeprom(db);
#endif
 db->msg_enable       = NETIF_MSG_LINK;
 db->mii.phy_id_mask  = 0x1f;
 db->mii.reg_num_mask = 0x1f;
 db->mii.force_media  = 0;
 db->mii.full_duplex  = 0;
 db->mii.dev      = ndev;
 db->mii.mdio_read    = dm9000_phy_read;
 db->mii.mdio_write   = dm9000_phy_write;
 /* Read SROM content */
//tekkaman
/* for (i = 0; i < 64; i++)
  ((u16 *) db->srom)[i] = read_srom_word(db, i);
*/
 /* Set Node Address */
  for (i = 0; i < 6; i++)
   ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
 
//tekkaman
 if (!is_valid_ether_addr(ndev->dev_addr)) {
  /* try reading from mac */
  printk("%s: Invalid ethernet MAC address."
   " Load ne_defethaddr !! \n ", ndev->name);
  for (i = 0; i < 6; i++)
  ndev->dev_addr[i] = ne_defethaddr[i];
 }
 if (!is_valid_ether_addr(ndev->dev_addr))
  printk("%s: Invalid ethernet MAC address.  Please "
         "set using ifconfig\n", ndev->name);
......

/*
 * Initilize dm9000 board
 */
static void
dm9000_init_dm9000(struct net_device *dev)
{
 board_info_t *db = (board_info_t *) dev->priv;
 PRINTK1("entering %s\n",__FUNCTION__);
......
 /* Init Driver variable */
 db->tx_pkt_cnt = 0;
 db->queue_pkt_len = 0;
 dev->trans_start = 0;
 spin_lock_init(&db->lock);
}
 
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
 
 board_info_t *db = (board_info_t *) dev->priv;
 PRINTK3("dm9000_start_xmit\n");
 led_trigger_event(dm9000_led_trigger, LED_FULL);
 if (db->tx_pkt_cnt > 1)
  return 1;
......

 led_trigger_event(dm9000_led_trigger, LED_OFF);
 return 0;
}
......
static void
dm9000_rx(struct net_device *dev)
{
 board_info_t *db = (board_info_t *) dev->priv;
 struct dm9000_rxhdr rxhdr;
 struct sk_buff *skb;
 u8 rxbyte, *rdptr;
 bool GoodPacket;
 int RxLen;
 
 /* Check packet ready or not */
 do {
  led_trigger_event(dm9000_led_trigger, LED_FULL);
  ior(db, DM9000_MRCMDX); /* Dummy read */
......

 led_trigger_event(dm9000_led_trigger, LED_OFF);
 } while (rxbyte == DM9000_PKT_RDY);

}
/*
 *  Read a word data from SROM
 */
#if 0
static u16
read_srom_word(board_info_t * db, int offset)
{
 iow(db, DM9000_EPAR, offset);
 iow(db, DM9000_EPCR, EPCR_ERPRR);
 mdelay(8);  /* according to the datasheet 200us should be enough,
       but it doesn't work */
 iow(db, DM9000_EPCR, 0x0);
 return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8));
}
#endif
......
static int __init
dm9000_init(void)
{
 printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
 
 led_trigger_register_simple("dm9000", &dm9000_led_trigger);
 return platform_driver_register(&dm9000_driver); /* search board and register */
}
......
 
特别说明:static int dm9000_probe(struct platform_device *pdev)函数中的总线配置语句一定要加,否则网卡运行时会出现“time out”的错误。

七、修改文件/arch/arm/mach-s3c2440/mach-smdk2440.c,增加对DM9000和CS8900的配置信息。

......
#include
#define DM9000_BASE   (vDM9000_BASE)
#define DM9000_IRQ    IRQ_EINT7
#define pDM9000_BASE    S3C2440_PA_ISA_DM9000
#define vDM9000_BASE    S3C2440_VA_ISA_DM9000
#define CS8900_BASE   (vCS8900_BASE)
#define CS8900_IRQ    IRQ_EINT9
#define pCS8900_BASE    S3C2440_PA_ISA_CS8900
#define vCS8900_BASE    S3C2440_VA_ISA_CS8900


static struct map_desc smdk2440_iodesc[] __initdata = {
    /* ISA IO Space map (memory space selected by A24) */

    {
        .virtual    = (u32)S3C24XX_VA_ISA_WORD,
        .pfn        = __phys_to_pfn(S3C2410_CS1),
        .length        = 0x10000,
        .type        = MT_DEVICE,
    }, {
        .virtual    = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
        .pfn        = __phys_to_pfn(S3C2410_CS1 + (1<<24)),
        .length        = SZ_4M,
        .type        = MT_DEVICE,
    }, {
        .virtual    = (u32)S3C24XX_VA_ISA_BYTE,
        .pfn        = __phys_to_pfn(S3C2410_CS1),
        .length        = 0x10000,
        .type        = MT_DEVICE,
    }, {
        .virtual    = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
        .pfn        = __phys_to_pfn(S3C2410_CS1 + (1<<24)),
        .length        = SZ_4M,
        .type        = MT_DEVICE,
    }, {
        .virtual        = S3C2440_VA_ISA_DM9000,
                .pfn          = S3C2440_PA_ISA_DM9000,
                .length        = S3C2440_SZ_ISA_DM9000,
                .type          = MT_DEVICE,

        }, {
        .virtual        = S3C2440_VA_ISA_CS8900,
                .pfn          = S3C2440_PA_ISA_CS8900,
                .length        = S3C2440_SZ_ISA_CS8900,
                .type          = MT_DEVICE,

        }

};
......
struct dm9000_plat_data tekkaman2440_dm9000 = {
        .flags= DM9000_PLATF_16BITONLY
};

static struct resource s3c2440_dm9000_resource[] = {
    [0] = {
        .start = DM9000_BASE,
        .end   = DM9000_BASE + 0xff,
        .flags = IORESOURCE_MEM,
    },
    [1] = {
        .start = DM9000_IRQ,
        .end   = DM9000_IRQ,
        .flags = IORESOURCE_IRQ,
    }
};


struct platform_device s3c_device_dm9000 = {
    .name          = "dm9000",
    .id          = -1,
    .num_resources      = ARRAY_SIZE(s3c2440_dm9000_resource),
    .resource      = s3c2440_dm9000_resource,
    .dev              = {
        .platform_data = &tekkaman2440_dm9000,
    }
};

static struct platform_device *smdk2440_devices[] __initdata = {
    &s3c_device_usb,
    &s3c_device_lcd,
    &s3c_device_wdt,
    &s3c_device_i2c,
    &s3c_device_iis,
    &s3c_device_dm9000

};
......
 

八、修改文件/include/asm-arm/arch-s3c2410/map.h,增加DM9000和CS8900的配置信息。
......
/* ISA style IO, for each machine to sort out mappings for, if it
 * implements it. We reserve two 16M regions for ISA.
 */

#define S3C24XX_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
#define S3C24XX_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)

    /***************tekkaman****************************/
#define S3C2440_VA_ISA_DM9000   S3C2410_ADDR(0x02100300)
#define S3C2440_PA_ISA_DM9000   __phys_to_pfn(0x20000300)
#define S3C2440_SZ_ISA_DM9000   SZ_1M
#define S3C2440_VA_ISA_CS8900   S3C2410_ADDR(0x02200300)
#define S3C2440_PA_ISA_CS8900   __phys_to_pfn(0x19000300)
#define S3C2440_SZ_ISA_CS8900   SZ_1M

    /**********************tekkaman********************/
......

特别说明:至于CS8900的物理地址的配置
#define S3C2440_PA_ISA_CS8900   __phys_to_pfn(0x19000300),不一定非得0x19000300,也可以是0x1B000300、0x1D0003000x1F000300,这是由于SBC2440V4的CS8900连接基本和SDMK2410的是一样的,使用了ADDR24脚作为类似使能的管脚。这样的设计是为了系统扩展的方便。

九、配置内核
  Networking  --->
    Networking options  --->
       [*]   IP: kernel level autoconfiguration
        [ ]     IP: DHCP support
        [ ]     IP: BOOTP support
        [ ]     IP: RARP support  
   
 如果你的cs8900是编译进内核,这三项最好要去掉。如果你和我一样是编译成模块,“Y”、“M”和“N”都无所谓。
Device Drivers  --->   
  Network device support  --->
     Ethernet (10 or 100Mbit)  --->    
         [*] Ethernet (10 or 100Mbit)
         ---   Generic Media Independent Interface device support
         < >   SMC 91C9x/91C1xxx support
         <*> DM9000 support
         CS89x0 support 
如果双网卡都编译进内核中,在启动时会无法挂载NFS,会出现IP配置失败的提示。单独编译时都不会出现这种情况。


    最后就是make zImagemake modules。将/drivers/net/cs89x0.ko复制到根文件系统中,启动后挂载。以下是我系统的一些信息:
[Tekkaman2440@SBC2410]#cd /lib/modules/
[
Tekkaman2440@SBC2410]#insmod cs89x0.ko
eth%d: cs8900 rev K found at 0xf2200300 <6>cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 08:08:08:08:27:12
[
Tekkaman2440@SBC2410]#ifconfig eth1 192.168.0.22
eth1: using full-duplex 10Base-T (RJ-45)
[
Tekkaman2440@SBC2410]#ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: seq=0 ttl=64 time=4.977 ms
64 bytes from 192.168.0.1: seq=1 ttl=64 time=0.633 ms
64 bytes from 192.168.0.1: seq=2 ttl=64 time=0.617 ms
64 bytes from 192.168.0.1: seq=3 ttl=64 time=0.601 ms
64 bytes from 192.168.0.1: seq=4 ttl=64 time=0.640 ms
64 bytes from 192.168.0.1: seq=5 ttl=64 time=0.621 ms
64 bytes from 192.168.0.1: seq=6 ttl=64 time=0.723 ms
64 bytes from 192.168.0.1: seq=7 ttl=64 time=0.623 ms

--- 192.168.0.1 ping statistics ---
8 packets transmitted, 8 packets received, 0% packet loss
round-trip min/avg/max = 0.601/1.179/4.977 ms
[
Tekkaman2440@SBC2410]#ifconfig
eth0      Link encap:Ethernet  HWaddr 08:08:08:08:12:27
          inet addr:192.168.1.2  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3485 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2382 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2704784 (2.5 MiB)  TX bytes:422360 (412.4 KiB)
          Interrupt:51 Base address:0x300

eth1      Link encap:Ethernet  HWaddr 08:08:08:08:27:12
          inet addr:192.168.0.22  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:36 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:4513 (4.4 KiB)  TX bytes:826 (826.0 B)
          Interrupt:53 Base address:0x300

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)




    整个移植工作到这里就结束了,我没时间复查,如果按上面的配置会出错。请通知一声,我会及时更正。
阅读(1263) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~