转 :::uboot1.2.0移植 AX88796驱动移植

      移植U-Boot.1.2.0到博创2410-S(S3C2410A)

      文章出处:: http://blog.chinaunix.net/u1/34474/showart_391051.html

引言:
     一个Bootloader没有tftp的支持,那么移植内核实在是痛苦的事。因为你要不断的用串口烧写内核到SDRAM里,时间少则2分多钟,多则4分多钟,错了还要重烧!在实现这个驱动前,我用U-Boot就是这么痛苦。
    在移植完Linux2.6.22.2的AX88796的驱动之后,我决心一定要把AX88796移植到U-Boot上,一劳永逸。借助移植Linux下的AX88796的经验,我首先看懂了/drivers下的ne2000.c的驱动,再参考了一些RTL8019的移植记录(都是NE2000兼容网卡),在痛苦了三四天后,驱动成功,ping和tftp成功,高兴得差点跳起来!以下介绍驱动的移植和U-Boot下网卡驱动移植、编写的一般方法。



本次驱动移植的参考资料:
1、AX88796L Datasheet
2、《NE2000 网卡芯片驱动程序》巨龙公司系统集成开发部 杨屹 2002/10/20
3、《REALTEK8019as 芯片资料翻译》也就是RTL8019网卡的中文资料
4、
zcx3000的关于网卡驱动的一系列文章,特别对于网卡初始化的顺序讲解的很细,必看。URL:http://blog.csdn.net/zcx3000/category/237774.aspx
5、
《嵌入式系统接口设计与Linux驱动程序开发》(刘淼 编著)第十五章:以太网接口与Linux网络驱动程序设计
6、《ARM嵌入式常用模块与综合系统设计实例精讲》 张绮文 谢建雄 谢劲心 编著 电子工业出版社  第16章 以太网控制器模块设计



 U-Boot下网卡驱动框架:
   U-Boot的
/drivers文件夹包含了许多U-Boot可能用到的驱动,其中包括:nand flash和网卡。(如果你有修改过nand flash驱动,你一定来过这。)这些驱动基本上都是最底层的硬件驱动。网卡驱动也不例外,它并不包含协议层,只实现网卡初始化、读写、停止等等功能,所以移植起来比较容易。
U-Boot网卡驱动的接口函数由以下四个函数组成:

int eth_init(bd_t *bd):完成网卡初始化的过程:热复位、相应寄存器的赋值、设置MAC地址等等
void eth_halt() :停止网卡运行
int eth_rx() :接收网络数据
int eth_send(volatile void *packet, int length) :发送数据

U-Boot在进行网络操作时,调用的就是这四个函数。所以移植时,只要集中精力在这四个函数,使它们对网卡的操作是正确的,移植就成功了。知道以上的知识,再学习一些网卡和网络的知识,看看成功的网卡驱动,要是以后出现U-boot不支持的网卡,也可以自己写驱动了!


U-Boot下AX88796网卡移植过程
    U-Boot下的AX88796网卡(NE2000寄存器兼容)驱动是使用NE2000的驱动,用到的文件是在/drivers文件夹下的8390.hne2000.cne2000.h

    首先说明一个关键问题,U-Boot的NE2000驱动是为8位总线写的,而博创的2410-S实验箱的AX88796的硬件连接适合16位总线的网卡驱动。所以必须将NE2000驱动该写成16位总线的驱动。(也许你会想:我也可以把2410的总线宽度改成8位,来使用8位的驱动。但是请你注意看看AX88796的数据手册的第51页和实验箱原理图的网卡部分,你就会知道:即使你用8位的驱动,你也必须使用16位 的总线,而且数据会处理更加麻烦。)还有就是没有修改过的驱动有BUG,没有修正是无法正常使用的。

 (1)修改
ne2000.c
......
#define DEBUG 0


#if DEBUG & 1
#define DEBUG_FUNCTION() do { printf("%s/n", __FUNCTION__); } while (0)
#define DEBUG_LINE() do { printf("%d/n", __LINE__); } while (0)
#else
#define DEBUG_FUNCTION() do {} while(0)
#define DEBUG_LINE() do {} while(0)
#endif

#include "ne2000.h"
//将8390的头文件上移到此,因为前面就要用到
#include "8390.h"

#if DEBUG & 1
#define PRINTK(args...) printf(args)
#else
#define PRINTK(args...)
#endif

static dp83902a_priv_data_t nic; /* just one instance of the card supported */

//添加从U-Boot的参数区读取MAC地址的函数
static int
ne2000_read_mac_addr(unsigned char * enaddr)
{
    int ii;
    char *s, *e;

    s = getenv ("ethaddr");
    if (s == NULL){
        return -1;
    }
    else{
        for(ii = 0; ii < 12; ii+=2) {
            enaddr[ii] =enaddr[ii+1]= s ? simple_strtoul (s, &e, 16) : 0;
            if (s){
                s = (*e) ? e + 1 : e;
            }
        }
    }
    return 0;
}
......

static void
dp83902a_start(unsigned char * enaddr)
{
    dp83902a_priv_data_t *dp = &nic;
    cyg_uint8 *base = dp->base;
    int i;

    DEBUG_FUNCTION();

    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */
    DP_OUT(base, DP_DCR, 0x49); //将网卡的总线宽度改为16位
    DP_OUT(base, DP_RBCH, 0);        /* Remote byte count */


 

......

DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);
    DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */
    DP_OUT(base, DP_RCR, DP_RCR_AB);  /* Accept broadcast, no errors, no multicast */
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
    dp->running = true;
}

......

static void
dp83902a_send(unsigned short *data, int total_len, unsigned long key)
{
......

    DP_OUT(base, DP_ISR, DP_ISR_RDC);  /* Clear end of DMA */
    {
        /* Dummy read. The manual sez something slightly different, */
        /* but the code is extended a bit to do what Hitachi's monitor */
        /* does (i.e., also read data). */
/*    //屏蔽无用的语句
        cyg_uint16 tmp;
        int len = 1;

        DP_OUT(base, DP_RSAL, 0x100-len);
        DP_OUT(base, DP_RSAH, (start_page-1) & 0xff);
        DP_OUT(base, DP_RBCL, len);
        DP_OUT(base, DP_RBCH, 0);
        DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
        DP_IN_DATA(dp->data, tmp);
*/    }

......

#if DEBUG & 4
    printf(" sg buf %08lx len %08x/n ", (unsigned long) data, len);
    dx = 0;
#endif
    while (len > 1) {
#if DEBUG & 4
        printf(" %04x", *data);
        if (0 == (++dx % 16)) printf("/n ");
#endif
        DP_OUT_DATA(dp->data, *data++);
        len-=2;
    }
#if DEBUG & 4
   
    if (len==1)     printf(" %04x", (*data)&0xff);
    printf("/n");
#endif
   
    if (len==1)     {DP_OUT_DATA(dp->data, (*data++)&0xff);    total_len++;    }

    if (total_len < pkt_len) {
#if DEBUG & 4
        printf("  + %d bytes of padding/n", pkt_len - total_len);
#endif
        /* Padding to 802.3 length was required */
        for (i = total_len;  i < pkt_len;) {
           
i+=2;
            DP_OUT_DATA(dp->data, 0);
        }
    }

......
}

/*
  This function is called when a packet has been received.  It's job is
  to prepare to unload the packet from the hardware.  Once the length of
  the packet is known, the upper layer of the driver can be told.  When
  the upper layer is ready to unload the packet, the internal function
  'dp83902a_recv' will be called to actually fetch it from the hardware.
*/
static void
dp83902a_RxEvent(void)
{
    struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
    cyg_uint8 *base = dp->base;
    unsigned char rsr;
    unsigned short rcv_hdr[2];
    int i, len, pkt, cur;
......
        DP_OUT(base, DP_RBCL, 4);
        DP_OUT(base, DP_RBCH, 0);
        DP_OUT(base, DP_RSAL, 0);
        DP_OUT(base, DP_RSAH, pkt);
        if (dp->rx_next == pkt) {
            if (cur == dp->rx_buf_start)
                DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
            else
                DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */
            return;
        }
        dp->rx_next = pkt;
        DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
        DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
        CYGACC_CALL_IF_DELAY_US(10);
#endif

        for (i = 0;  i < sizeof(rcv_hdr);) {
            DP_IN_DATA(dp->data, rcv_hdr[i++]);
        }

#if DEBUG & 5
        printf("rx hdr %04x %04x /n",
               rcv_hdr[0], rcv_hdr[1]);
#endif
        len = rcv_hdr[1] - 4;
        uboot_push_packet_len(len);
        if (((rcv_hdr[0] >>8)&0xff) == dp->rx_buf_start)
            DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
        else
            DP_OUT(base, DP_BNDRY, ((rcv_hdr[0] >>8)&0xff)-1); /* Update pointer */
    }
}

/*
  This function is called as a result of the "eth_drv_recv()" call above.
  It's job is to actually fetch data for a packet from the hardware once
  memory buffers have been allocated for the packet.  Note that the buffers
  may come in pieces, using a scatter-gather list.  This allows for more
  efficient processing in the upper layers of the stack.
*/
static void
dp83902a_recv(unsigned short *data, int len)
{
    ......

    /* Read incoming packet data */
    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
    DP_OUT(base, DP_RBCL, len & 0xFF);
    DP_OUT(base, DP_RBCH, (len >> 8)& 0xFF);
    DP_OUT(base, DP_RSAL, 4);        /* Past header */
    DP_OUT(base, DP_RSAH, dp->rx_next);
    DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
    DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
    CYGACC_CALL_IF_DELAY_US(10);
#endif

    saved = false;
    for (i = 0;  i < 1;  i++) {
        if (data) {
            mlen = len;
#if DEBUG & 4
            printf(" sg buf %08lx len %08x /n", (unsigned long) data, mlen);
            dx = 0;
#endif
            while (0 < mlen) {
                /* Saved byte from previous loop? */
                if (saved) {
                    *data++ = saved_char;
                    mlen--;
                    saved = false;
                    continue;
                }

                {
                    cyg_uint16 tmp;
                    DP_IN_DATA(dp->data, tmp);
#if DEBUG & 4
                    printf(" %04x", tmp);
                    if (0 == (++dx % 16)) printf("/n ");
#endif
                    *data++ = tmp;
                    mlen-=2;
                    if (mlen==1) {
                            DP_IN_DATA(dp->data, tmp);
                            tmp = tmp & 0xff;
#if DEBUG & 4
                            printf(" %04x", tmp);
#endif
                            *data++ = tmp;
                            mlen--;
                            }
                }
            }
#if DEBUG & 4
            printf("/n");
#endif
        }
    }
}

......
//添加自定义的AX88796硬件信息,在这里定义了如果网卡的MAC地址的前三个为

//0x08, 0x08, 0x08,那就是AX88796。如果你要修改MAC地址 ,
//最好前三个要和这三个一样,不然驱动会认不到网卡。

static hw_info_t hw_info[] = {
 ......
    { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
    { /* AX88796 */ 0x0ff0, 0x08, 0x08, 0x08, 0 },
    { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
......
};

......

static void pcnet_reset_8390(void)
{
    int i, r;

    PRINTK("nic base is %lx/n", nic_base);

#if 1
    n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
    PRINTK("cmd (at %lx) is %x/n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
    n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);
    PRINTK("cmd (at %lx) is %x/n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
    n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);
    PRINTK("cmd (at %lx) is %x/n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD));
#endif
    n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);

    n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET);  
//低级错误,严重的BUG,没有修改无法实现网卡的热复位,晕死。


    for (i = 0; i < 100; i++) {
        if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)
            break;
        PRINTK("got %x in reset/n", r);
        my_udelay(100);
    }
    n2k_outb(0xff, EN0_ISR); /* Ack intr. */

    if (i == 100)
        printf("pcnet_reset_8390() did not complete./n");
} /* pcnet_reset_8390 */

static hw_info_t * get_prom(void ) {
    unsigned char prom[32];
    char ethaddr[20];    //tekkaman
    int i, j, tekkaman;    //tekkaman
    unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman

    ......

    pcnet_reset_8390();

    mdelay(10);

    for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
        n2k_outb(program_seq[i].value, program_seq[i].offset);

    tekkaman=ne2000_read_mac_addr(prom);
    if (tekkaman)    {
        printf("ethaddr in nand is not found ,loading ne_defethaddr:");
        for (i = 0; i < 12; i++) {
            prom[i] = ne_defethaddr[i/2];
            printf(" %02x", prom[i]);
        }
    }
    prom[28] = prom[30] = 0x57;

    PRINTK("/n");
    for (i = 0; i < NR_INFO; i++) {
        if ((prom[0] == hw_info[i].a0) &&
            (prom[2] == hw_info[i].a1) &&
            (prom[4] == hw_info[i].a2)) {
            PRINTK("matched board %d/n", i);
            break;
        }
    }
    if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
        for (j = 0; j < 6; j++)
            dev_addr[j] = prom[j<<1];
        PRINTK("on exit i is %d/%ld/n", i, NR_INFO);
        PRINTK("MAC address is %02x:%02x:%02x:%02x:%02x:%02x/n",
               dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]);
        return (i < NR_INFO) ? hw_info+i : &default_info;
   
        if (tekkaman) {
        sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
         dev_addr[0], dev_addr[1],
         dev_addr[2], dev_addr[3],
         dev_addr[4], dev_addr[5]) ;
        printf("Set environment from HW MAC addr = /"%s/"/n", ethaddr);
        setenv ("ethaddr", ethaddr);
        }
    }
    return NULL;
}

/* U-boot specific routines */

#define NB 5

static unsigned short *pbuf = NULL;
static int plen[NB];
static int nrx = 0;

static int pkey = -1;

void uboot_push_packet_len(int len) {
    PRINTK("pushed len = %d, nrx = %d/n", len, nrx);
    if (len>=2000) {
        printf("NE2000: packet too big/n");
        return;
    }
    if (nrx >= NB) {
        printf("losing packets in rx/n");
        return;
    }
    plen[nrx] = len;
    dp83902a_recv(&pbuf[nrx*1000], len);
    nrx++;
}

void uboot_push_tx_done(int key, int val) {
    PRINTK("pushed key = %d/n", key);
    pkey = key;
}

int eth_init(bd_t *bd) {
    static hw_info_t * r;
//    char ethaddr[20];

    PRINTK("### eth_init/n");

    if (!pbuf) {
        pbuf = malloc(NB*1000);
        if (!pbuf) {
            printf("Cannot allocate rx buffers/n");
            return -1;
        }
    }

#ifdef CONFIG_DRIVER_NE2000_CCR
    {
        volatile unsigned char *p =  (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR;

        PRINTK("CCR before is %x/n", *p);
        *p = CONFIG_DRIVER_NE2000_VAL;
        PRINTK("CCR after is %x/n", *p);
    }
#endif

    nic_base = CONFIG_DRIVER_NE2000_BASE;
    nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE;

    r = get_prom();
    if (!r)
        return -1;
/*//屏蔽无用的语句
    sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
         dev_addr[0], dev_addr[1],
         dev_addr[2], dev_addr[3],
         dev_addr[4], dev_addr[5]) ;
   PRINTK("Set environment from HW MAC addr = /"%s/"/n", ethaddr);
    setenv ("ethaddr", ethaddr);
*/

#define DP_DATA        0x10
    nic.data = (unsigned short *) (nic.base + DP_DATA);
    nic.tx_buf1 = 0x40;
    nic.tx_buf2 = 0x46;
    nic.rx_buf_start = 0x4C;
    nic.rx_buf_end = 0x80;
   
    dp83902a_start(dev_addr);
    if (dp83902a_init() == false)
        return -1;
    return 0;
}

void eth_halt() {

    PRINTK("### eth_halt/n");

    dp83902a_stop();
}

int eth_rx() {
    int j, tmo;
    volatile uchar * inpkt
    PRINTK("### eth_rx/n");

    tmo = get_timer (0) + TOUT * CFG_HZ;
   
    while(1) {
        dp83902a_poll();
        if (nrx > 0) {
            for(j=0; j<nrx; j++) {
                inpkt = (uchar *) &pbuf[j*1000];


                NetReceive(inpkt, plen[j]);//这句的作用就是将接收到的数据

                                           //送到MAC层以上的协议层
            }
            nrx = 0;
            return 1;
        }
        if (get_timer (0) >= tmo) {
            printf("timeout during rx/n");
            return 0;
        }
    }
    return 0;
}

int eth_send(volatile void *packet, int length) {
    int tmo;

    PRINTK("### eth_send/n");

    pkey = -1;

    dp83902a_send((unsigned short *) packet, length, 666);
    tmo = get_timer (0) + TOUT * CFG_HZ;
    while(1) {
        dp83902a_poll();
        if (pkey != -1) {
            PRINTK("Packet sucesfully sent/n");
            return 0;
        }
        if (get_timer (0) >= tmo) {
            printf("transmission error (timoeut)/n");
            return 0;
        }

    }
    return 0;
}

#endif

ne2000.c修改完毕  (2)修改ne2000.h
NE2000驱动的低级错误
第45行:
 at http://sources.redhat.com/ecos/ecos-license/ */

改为:
 at http://sources.redhat.com/ecos/ecos-license/

就是去掉“*/”   ,   真是TNND汗死!!!!


......

#define DP_IN(_b_, _o_, _d_)  (_d_) = *( (volatile unsigned char *) ((_b_)+(_o_)))
#define DP_OUT(_b_, _o_, _d_) *( (volatile unsigned char *) ((_b_)+(_o_))) = ((unsigned char) (_d_))

#define DP_IN_DATA(_b_, _d_)  (_d_) = *( (volatile unsigned short *) ((_b_)))
#define DP_OUT_DATA(_b_, _d_) *( (volatile unsigned short *) ((_b_))) = ((unsigned short) (_d_))


/* here is all the data */

#define cyg_uint8 unsigned char
#define cyg_uint16 unsigned short
#define bool int

#define false 0
#define true 1

#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 1
#define CYGACC_CALL_IF_DELAY_US(X) my_udelay(X)

typedef struct dp83902a_priv_data {
    cyg_uint8* base;
    cyg_uint16* data;
    cyg_uint8* reset;
    int tx_next;           /* First free Tx page */
    int tx_int;            /* Expecting interrupt from this buffer */
    int rx_next;           /* First free Rx page */
    int tx1, tx2;          /* Page numbers for Tx buffers */
    unsigned long tx1_key, tx2_key;   /* Used to ack when packet sent */
    int tx1_len, tx2_len;
    bool tx_started, running, hardwired_esa;
    cyg_uint8 esa[6];
    void* plf_priv;

    /* Buffer allocation */
    int tx_buf1, tx_buf2;
    int rx_buf_start, rx_buf_end;
} dp83902a_priv_data_t;

......
(3)修改8390.h

......
/*
 *    Only generate indirect loads given a machine that needs them.
 *      - removed AMIGA_PCMCIA from this list, handled as ISA io now
 */

#define n2k_inb(port)   (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)))
#define n2k_outb(val,port)  (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)) = ((unsigned char) val))

#define EI_SHIFT(x)    (x)
......

 


 


U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)

U-Boot code: 33F80000 -> 33F98BC0  BSS: -> 33F9D3C0
DRAM:  64 MB
NAND:    64 MB
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0
[Tekkaman2410]# printenv
bootdelay=3
baudrate=115200
ethaddr=08:08:08:08:12:27
netmask=255.255.255.0
bootfile=zImage.img
loadaddr=0x30008000
bootargs=root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs bootcmd=tftp;bootm
ipaddr=192.168.1.2
serverip=192.168.1.22
stdin=serial
stdout=serial
stderr=serial

Environment size: 382/65532 bytes

serverip  服务器IP   ipaddr  为板子IP   设置完要保存

下载保存:::

nand erase 0x100000 20000          ;格式化要操作区域    0x100000:地址    20000:大小

nand write 0x30008000 0x100000 0x20000          ;写入     0x30008000:内存地址  

启动::: 

1、针对方法一:
sbc2410=>setenv bootcmd nand read 0x31000000 0x30000 0x1d0000/;bootm 0x31000000
sbc2410=>saveenv

2、针对方法二:
sbc2410=>setenv bootcmd nand read 0x30008000 0x30000 0x1d0000/;bootm 0x30008000
sbc2410=>saveenv

启动内核时候会出现些错误    Error: unrecognized/unsupported machine ID (r1 = 0x33f60264).

Linux内核启动时出现:bad machine ID,原因大致是u-boot传递给内核的machine ID错误,可以手动在内核源代码中添加machine ID.

解决方法:
在u-boot命令行中输入bdinfo
查看板卡信息,我的输出如下:
[ ~ljh@GDLC ]# bdinfo
arch_number =
0x000000C1
env_t       = 0x00000000
boot_params = 0x30000100
DRAM bank   = 0x00000000
-> start    = 0x30000000
-> size     = 0x04000000
ethaddr     = 08:00:3E:26:0A:5B
ip_addr     = 10.1.8.245
baudrate    = 115200 bps


修改内核的arch/arm/kernel/head.S,直接将s3c2410的参数赋给内核
# cd linux-2.6.19
# vi arch/arm/kernel/head.S +72
----------------------------------------------    
70     __INIT
71     .type       stext, %function
72 ENTRY(stext)
   /********* add here *********/
   mov    r0, #0
   mov    r1, #0xc1
   ldr    r2, =0x30000100
   /********* end add *********/

73     msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
74     @ and irqs disabled















解决方法二
========================================================
修改u-boot,填写ID;


# vi common/cmd_boot.c
----------------------------------------------
31 #if defined(CONFIG_I386)
32 DECLARE_GLOBAL_DATA_PTR;
33 #endif
====>
31 //#if defined(CONFIG_I386)
32 DECLARE_GLOBAL_DATA_PTR;
33 //#endif
   ...
60 #if !defined(CONFIG_NIOS)
        /************** add here ******************/
        if(argc==2)
            rc = ((ulong (*)(int, char *[]))addr) (0, gd->bd->bi_arch_number);
        else

        /*************** add end *****************/

61         rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);
62 #else
63     /*
64      * Nios function pointers are address >> 1
65      */
66     rc = ((ulong (*)(int, char *[]))(addr>>1)) (--argc, &argv[1]);
67 #endif

 

 


 



 


 


 


 



网卡驱动程序的修改到此结束,以下是总线参数的修改:

修改/board/tekkaman/tekkaman2410/lowlevel_init.S文件(参数都是参考 刘淼 的书):

#define B1_BWSCON    (DW16) /*@tekkaman*/
#define B2_BWSCON    (DW16 + UBLB)
#define B3_BWSCON    (DW16) 
/*@tekkaman*/

......

#define B2_Tacs    0x3 /*  4clk tekkaman*/
#define B2_Tcos    0x3 /*  4clk tekkaman*/

#define B2_Tacc    0x7 /*  14clk */
#define B2_Tcoh    0x3 /*  4clk tekkaman*/
#define B2_Tah    0x3 /*  4clk tekkaman*/
#define B2_Tacp    0x3 /*  6clk tekkaman*/

#define B2_PMC    0x0 /* normal */

......

/*
 * Hardware drivers
 */
//#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
//#define CS8900_BASE  0x19000300
//#define CS8900_BUS16  1 /* the Linux driver does accesses as shorts */
#define CONFIG_DRIVER_NE2000  1
#define CONFIG_DRIVER_NE2000_BASE (0x10000000+0x200)


在/include/configs/tekkaman2410.h文件中加上AX88796网卡驱动的信息:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值