一个Bootloader没有tftp的支持,那么移植内核实在是痛苦的事。因为你要不断的用串口烧写内核到SDRAM里,时间少则2分多钟,多则4分多钟,错了还要重烧!在实现这个驱动前,我用U-Boot就是这么痛苦。<br /> 在移植完Linux2.6.22.2的AX88796的驱动之后,我决心一定要把AX88796移植到U-Boot上,一劳永逸。借助移植Linux下的AX88796的经验,我首先看懂了/drivers下的ne2000.c的驱动,再参考了一些RTL8019的移植记录(都是NE2000兼容网卡),在痛苦了三四天后,驱动成功,ping和tftp成功,高兴得差点跳起来!以下介绍驱动的移植和U-Boot下网卡驱动移植、编写的一般方法。<br />U-Boot下网卡驱动框架:<br /> U-Boot的/drivers文件夹包含了许多U-Boot可能用到的驱动,其中包括:nand flash和网卡。(如果你有修改过nand flash驱动,你一定来过这。)这些驱动基本上都是最底层的硬件驱动。网卡驱动也不例外,它并不包含协议层,只实现网卡初始化、读写、停止等等功能,所以移植起来比较容易。<br />U-Boot网卡驱动的接口函数由以下四个函数组成:<br /><br />int eth_init(bd_t *bd):完成网卡初始化的过程:热复位、相应寄存器的赋值、设置MAC地址等等<br />void eth_halt() :停止网卡运行<br />int eth_rx() :接收网络数据<br />int eth_send(volatile void *packet, int length) :发送数据<br /><br />U-Boot在进行网络操作时,调用的就是这四个函数。所以移植时,只要集中精力在这四个函数,使它们对网卡的操作是正确的,移植就成功了。知道以上的知识,再学习一些网卡和网络的知识,看看成功的网卡驱动,要是以后出现U-boot不支持的网卡,也可以自己写驱动了!<br /><br />--------------------------------------------------------------------------------<br />U-Boot下AX88796网卡移植过程<br /> U-Boot下的AX88796网卡(NE2000寄存器兼容)驱动是使用NE2000的驱动,用到的文件是在/drivers文件夹下的8390.h、ne2000.c和ne2000.h。<br /><br /> 首先说明一个关键问题,U-Boot的NE2000驱动是为8位总线写的,而博创的2410-S实验箱的AX88796的硬件连接适合16位总线的网卡驱动。所以必须将NE2000驱动该写成16位总线的驱动。(也许你会想:我也可以把2410的总线宽度改成8位,来使用8位的驱动。但是请你注意看看AX88796的数据手册的第51页和实验箱原理图的网卡部分,你就会知道:即使你用8位的驱动,你也必须使用16位 的总线,而且数据会处理更加麻烦。)还有就是没有修改过的驱动有BUG,没有修正是无法正常使用的。 <br />--------------------------------------------------------------------------------<br /><br /><br />(1)修改ne2000.c<br />......<br />#define DEBUG 0<br /><br />#if DEBUG & 1<br />#define DEBUG_FUNCTION() do { printf('%s<br />', __FUNCTION__); } while (0)<br />#define DEBUG_LINE() do { printf('%d<br />', __LINE__); } while (0)<br />#else<br />#define DEBUG_FUNCTION() do {} while(0)<br />#define DEBUG_LINE() do {} while(0)<br />#endif<br /><br />#include 'ne2000.h'<br />//将8390的头文件上移到此,因为前面就要用到<br />#include '8390.h'<br /><br />#if DEBUG & 1<br />#define PRINTK(args...) printf(args)<br />#else<br />#define PRINTK(args...)<br />#endif<br /><br />static dp83902a_priv_data_t nic; /* just one instance of the card supported */<br /><br />//添加从U-Boot的参数区读取MAC地址的函数<br />static int<br />ne2000_read_mac_addr(unsigned char * enaddr)<br />{<br /> int ii;<br /> char *s, *e;<br /><br /> s = getenv ('ethaddr');<br /> if (s == NULL){<br /> return -1;<br /> }<br /> else{<br /> for(ii = 0; ii < 12; ii+=2) {<br /> enaddr[ii] =enaddr[ii+1]= s ? simple_strtoul (s, &e, 16) : 0;<br /> if (s){<br /> s = (*e) ? e + 1 : e;<br /> }<br /> }<br /> }<br /> return 0;<br />}<br />......<br /><br />static void<br />dp83902a_start(unsigned char * enaddr)<br />{<br /> dp83902a_priv_data_t *dp = &nic;<br /> cyg_uint8 *base = dp->base;<br /> int i;<br /><br /> DEBUG_FUNCTION();<br /><br /> DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */<br /> DP_OUT(base, DP_DCR, 0x49); //将网卡的总线宽度改为16位<br /> DP_OUT(base, DP_RBCH, 0); /* Remote byte count */<br /><br /><br />......<br /><br />DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);<br /> DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */<br /> DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */<br /> DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);<br /> dp->running = true;<br />}<br /><br />......<br /><br />static void<br />dp83902a_send(unsigned short *data, int total_len, unsigned long key)<br />{<br />......<br /><br /> DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */<br /> {<br /> /* Dummy read. The manual sez something slightly different, */<br /> /* but the code is extended a bit to do what Hitachi's monitor */<br /> /* does (i.e., also read data). */<br />/* //屏蔽无用的语句<br /> cyg_uint16 tmp;<br /> int len = 1;<br /><br /> DP_OUT(base, DP_RSAL, 0x100-len);<br /> DP_OUT(base, DP_RSAH, (start_page-1) & 0xff);<br /> DP_OUT(base, DP_RBCL, len);<br /> DP_OUT(base, DP_RBCH, 0);<br /> DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);<br /> DP_IN_DATA(dp->data, tmp);<br />*/ }<br /><br />......<br /><br />#if DEBUG & 4<br /> printf(' sg buf %08lx len %08x<br />', (unsigned long) data, len);<br /> dx = 0;<br />#endif<br /> while (len > 1) {<br />#if DEBUG & 4<br /> printf(' %04x', *data);<br /> if (0 == (++dx % 16)) printf('<br />');<br />#endif<br /> DP_OUT_DATA(dp->data, *data++);<br /> len-=2;<br /> }<br />#if DEBUG & 4<br /> <br /> if (len==1) printf(' %04x', (*data)&0xff);<br /> printf('<br />');<br />#endif<br /> <br /> if (len==1) {DP_OUT_DATA(dp->data, (*data++)&0xff); total_len++; }<br /><br /> if (total_len < pkt_len) {<br />#if DEBUG & 4<br /> printf(' + %d bytes of padding<br />', pkt_len - total_len);<br />#endif<br /> /* Padding to 802.3 length was required */<br /> for (i = total_len; i < pkt_len;) {<br /> i+=2;<br /> DP_OUT_DATA(dp->data, 0);<br /> }<br /> }<br /><br />......<br />}<br /><br />/*<br /> This function is called when a packet has been received. It's job is<br /> to prepare to unload the packet from the hardware. Once the length of<br /> the packet is known, the upper layer of the driver can be told. When<br /> the upper layer is ready to unload the packet, the internal function<br /> 'dp83902a_recv' will be called to actually fetch it from the hardware.<br />*/<br />static void<br />dp83902a_RxEvent(void)<br />{<br /> struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;<br /> cyg_uint8 *base = dp->base;<br /> unsigned char rsr;<br /> unsigned short rcv_hdr[2];<br /> int i, len, pkt, cur;<br />......<br /> DP_OUT(base, DP_RBCL, 4);<br /> DP_OUT(base, DP_RBCH, 0);<br /> DP_OUT(base, DP_RSAL, 0);<br /> DP_OUT(base, DP_RSAH, pkt);<br /> if (dp->rx_next == pkt) {<br /> if (cur == dp->rx_buf_start)<br /> DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);<br /> else<br /> DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */<br /> return;<br /> }<br /> dp->rx_next = pkt;<br /> DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */<br /> DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);<br />#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA<br /> CYGACC_CALL_IF_DELAY_US(10);<br />#endif<br /><br /> for (i = 0; i < sizeof(rcv_hdr);) {<br /> DP_IN_DATA(dp->data, rcv_hdr[i++]);<br /> }<br /><br />#if DEBUG & 5<br /> printf('rx hdr %04x %04x <br />',<br /> rcv_hdr[0], rcv_hdr[1]);<br />#endif<br /> len = rcv_hdr[1] - 4;<br /> uboot_push_packet_len(len);<br /> if (((rcv_hdr[0] >>8)&0xff) == dp->rx_buf_start)<br /> DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);<br /> else<br /> DP_OUT(base, DP_BNDRY, ((rcv_hdr[0] >>8)&0xff)-1); /* Update pointer */<br /> }<br />}<br /><br />/*<br /> This function is called as a result of the 'eth_drv_recv()' call above.<br /> It's job is to actually fetch data for a packet from the hardware once<br /> memory buffers have been allocated for the packet. Note that the buffers<br /> may come in pieces, using a scatter-gather list. This allows for more<br /> efficient processing in the upper layers of the stack.<br />*/<br />static void<br />dp83902a_recv(unsigned short *data, int len)<br />{<br /> ......<br /><br /> /* Read incoming packet data */<br /> DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);<br /> DP_OUT(base, DP_RBCL, len & 0xFF);<br /> DP_OUT(base, DP_RBCH, (len >> 8)& 0xFF);<br /> DP_OUT(base, DP_RSAL, 4); /* Past header */<br /> DP_OUT(base, DP_RSAH, dp->rx_next);<br /> DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */<br /> DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);<br />#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA<br /> CYGACC_CALL_IF_DELAY_US(10);<br />#endif<br /><br /> saved = false;<br /> for (i = 0; i < 1; i++) {<br /> if (data) {<br /> mlen = len;<br />#if DEBUG & 4<br /> printf(' sg buf %08lx len %08x <br />', (unsigned long) data, mlen);<br /> dx = 0;<br />#endif<br /> while (0 < mlen) {<br /> /* Saved byte from previous loop? */<br /> if (saved) {<br /> *data++ = saved_char;<br /> mlen--;<br /> saved = false;<br /> continue;<br /> }<br /><br /> {<br /> cyg_uint16 tmp;<br /> DP_IN_DATA(dp->data, tmp);<br />#if DEBUG & 4<br /> printf(' %04x', tmp);<br /> if (0 == (++dx % 16)) printf('<br />');<br />#endif<br /> *data++ = tmp;<br /> mlen-=2;<br /> if (mlen==1) {<br /> DP_IN_DATA(dp->data, tmp);<br /> tmp = tmp & 0xff;<br />#if DEBUG & 4<br /> printf(' %04x', tmp);<br />#endif<br /> *data++ = tmp;<br /> mlen--;<br /> }<br /> }<br /> }<br />#if DEBUG & 4<br /> printf('<br />');<br />#endif<br /> }<br /> }<br />}<br /><br />......<br />//添加自定义的AX88796硬件信息,在这里定义了如果网卡的MAC地址的前三个为 <br />//0x08, 0x08, 0x08,那就是AX88796。如果你要修改MAC地址 ,<br />//最好前三个要和这三个一样,不然驱动会认不到网卡。<br />static hw_info_t hw_info[] = {<br />......<br /> { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },<br /> { /* AX88796 */ 0x0ff0, 0x08, 0x08, 0x08, 0 },<br /> { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,<br />......<br />};<br /><br />......<br /><br />static void pcnet_reset_8390(void)<br />{<br /> int i, r;<br /><br /> PRINTK('nic base is %lx<br />', nic_base);<br /><br />#if 1<br /> n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);<br /> PRINTK('cmd (at %lx) is %x<br />', nic_base+ E8390_CMD, n2k_inb(E8390_CMD));<br /> n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD);<br /> PRINTK('cmd (at %lx) is %x<br />', nic_base+ E8390_CMD, n2k_inb(E8390_CMD));<br /> n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);<br /> PRINTK('cmd (at %lx) is %x<br />', nic_base+ E8390_CMD, n2k_inb(E8390_CMD));<br />#endif<br /> n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD);<br /><br /> n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET); <br />//低级错误,严重的BUG,没有修改无法实现网卡的热复位,晕死。<br /><br /> for (i = 0; i < 100; i++) {<br /> if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0)<br /> break;<br /> PRINTK('got %x in reset<br />', r);<br /> my_udelay(100);<br /> }<br /> n2k_outb(0xff, EN0_ISR); /* Ack intr. */<br /><br /> if (i == 100)<br /> printf('pcnet_reset_8390() did not complete.<br />');<br />} /* pcnet_reset_8390 */<br /><br />static hw_info_t * get_prom(void ) {<br /> unsigned char prom[32];<br /> char ethaddr[20]; //tekkaman<br /> int i, j, tekkaman; //tekkaman<br /> unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman<br /><br /> ......<br /><br /> pcnet_reset_8390();<br /><br /> mdelay(10);<br /><br /> for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)<br /> n2k_outb(program_seq.value, program_seq.offset);<br /><br /> tekkaman=ne2000_read_mac_addr(prom);<br /> if (tekkaman) {<br /> printf('ethaddr in nand is not found ,loading ne_defethaddr:');<br /> for (i = 0; i < 12; i++) {<br /> prom = ne_defethaddr[i/2];<br /> printf(' %02x', prom);<br /> }<br /> }<br /> prom[28] = prom[30] = 0x57;<br /><br /> PRINTK('<br />');<br /> for (i = 0; i < NR_INFO; i++) {<br /> if ((prom[0] == hw_info.a0) &&<br /> (prom[2] == hw_info.a1) &&<br /> (prom[4] == hw_info.a2)) {<br /> PRINTK('matched board %d<br />', i);<br /> break;<br /> }<br /> }<br /> if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {<br /> for (j = 0; j < 6; j++)<br /> dev_addr[j] = prom[j<<1];<br /> PRINTK('on exit i is %d/%ld<br />', i, NR_INFO);<br /> PRINTK('MAC address is %02x:%02x:%02x:%02x:%02x:%02x<br />',<br /> dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]);<br /> return (i < NR_INFO) ? hw_info+i : &default_info;<br /> <br /> if (tekkaman) {<br /> sprintf (ethaddr, '%02X:%02X:%02X:%02X:%02X:%02X',<br /> dev_addr[0], dev_addr[1],<br /> dev_addr[2], dev_addr[3],<br /> dev_addr[4], dev_addr[5]) ;<br /> printf('Set environment from HW MAC addr = '%s'<br />', ethaddr);<br /> setenv ('ethaddr', ethaddr);<br /> }<br /> }<br /> return NULL;<br />}<br /><br />/* U-boot specific routines */<br /><br />#define NB 5<br /><br />static unsigned short *pbuf = NULL;<br />static int plen[NB];<br />static int nrx = 0;<br /><br />static int pkey = -1;<br /><br />void uboot_push_packet_len(int len) {<br /> PRINTK('pushed len = %d, nrx = %d<br />', len, nrx);<br /> if (len>=2000) {<br /> printf('NE2000: packet too big<br />');<br /> return;<br /> }<br /> if (nrx >= NB) {<br /> printf('losing packets in rx<br />');<br /> return;<br /> }<br /> plen[nrx] = len;<br /> dp83902a_recv(&pbuf[nrx*1000], len);<br /> nrx++;<br />}<br /><br />void uboot_push_tx_done(int key, int val) {<br /> PRINTK('pushed key = %d<br />', key);<br /> pkey = key;<br />}<br /><br />int eth_init(bd_t *bd) {<br /> static hw_info_t * r;<br />// char ethaddr[20];<br /><br /> PRINTK('### eth_init<br />');<br /><br /> if (!pbuf) {<br /> pbuf = malloc(NB*1000);<br /> if (!pbuf) {<br /> printf('Cannot allocate rx buffers<br />');<br /> return -1;<br /> }<br /> }<br /><br />#ifdef CONFIG_DRIVER_NE2000_CCR<br /> {<br /> volatile unsigned char *p = (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR;<br /><br /> PRINTK('CCR before is %x<br />', *p);<br /> *p = CONFIG_DRIVER_NE2000_VAL;<br /> PRINTK('CCR after is %x<br />', *p);<br /> }<br />#endif<br /><br /> nic_base = CONFIG_DRIVER_NE2000_BASE;<br /> nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE;<br /><br /> r = get_prom();<br /> if (!r)<br /> return -1;<br />/*//屏蔽无用的语句<br /> sprintf (ethaddr, '%02X:%02X:%02X:%02X:%02X:%02X',<br /> dev_addr[0], dev_addr[1],<br /> dev_addr[2], dev_addr[3],<br /> dev_addr[4], dev_addr[5]) ;<br /> PRINTK('Set environment from HW MAC addr = '%s'<br />', ethaddr);<br /> setenv ('ethaddr', ethaddr);<br />*/<br /><br />#define DP_DATA 0x10<br /> nic.data = (unsigned short *) (nic.base + DP_DATA);<br /> nic.tx_buf1 = 0x40;<br /> nic.tx_buf2 = 0x46;<br /> nic.rx_buf_start = 0x4C;<br /> nic.rx_buf_end = 0x80;<br /> <br /> dp83902a_start(dev_addr);<br /> if (dp83902a_init() == false)<br /> return -1;<br /> return 0;<br />}<br /><br />void eth_halt() {<br /><br /> PRINTK('### eth_halt<br />');<br /><br /> dp83902a_stop();<br />}<br /><br />int eth_rx() {<br /> int j, tmo;<br /> volatile uchar * inpkt<br /> PRINTK('### eth_rx<br />');<br /><br /> tmo = get_timer (0) + TOUT * CFG_HZ;<br /> <br /> while(1) {<br /> dp83902a_poll();<br /> if (nrx > 0) {<br /> for(j=0; j inpkt = (uchar *) &pbuf[j*1000];<br /><br /><br /> NetReceive(inpkt, plen[j]);//这句的作用就是将接收到的数据<br /><br /> //送到MAC层以上的协议层<br /> }<br /> nrx = 0;<br /> return 1;<br /> }<br /> if (get_timer (0) >= tmo) {<br /> printf('timeout during rx<br />');<br /> return 0;<br /> }<br /> }<br /> return 0;<br />}<br /><br />int eth_send(volatile void *packet, int length) {<br /> int tmo;<br /><br /> PRINTK('### eth_send<br />');<br /><br /> pkey = -1;<br /><br /> dp83902a_send((unsigned short *) packet, length, 666);<br /> tmo = get_timer (0) + TOUT * CFG_HZ;<br /> while(1) {<br /> dp83902a_poll();<br /> if (pkey != -1) {<br /> PRINTK('Packet sucesfully sent<br />');<br /> return 0;<br /> }<br /> if (get_timer (0) >= tmo) {<br /> printf('transmission error (timoeut)<br />');<br /> return 0;<br /> }<br /><br /> }<br /> return 0;<br />}<br /><br />#endif<br /><br />ne2000.c修改完毕 <br /><br /><br /><br />--------------------------------------------------------------------------------<br /><br /><br /><br /><br />(2)修改ne2000.h<br />NE2000驱动的低级错误<br />将第45行:<br />at http://sources.redhat.com/ecos/ecos-license/ */<br /><br />改为:<br />at http://sources.redhat.com/ecos/ecos-license/ <br /><br />就是去掉“*/” , 真是TNND汗死!!!!<br /><br />......<br /><br />#define DP_IN(_b_, _o_, _d_) (_d_) = *( (volatile unsigned char *) ((_b_)+(_o_)))<br />#define DP_OUT(_b_, _o_, _d_) *( (volatile unsigned char *) ((_b_)+(_o_))) = ((unsigned char) (_d_))<br /><br />#define DP_IN_DATA(_b_, _d_) (_d_) = *( (volatile unsigned short *) ((_b_)))<br />#define DP_OUT_DATA(_b_, _d_) *( (volatile unsigned short *) ((_b_))) = ((unsigned short) (_d_))<br /><br /><br />/* here is all the data */<br /><br />#define cyg_uint8 unsigned char<br />#define cyg_uint16 unsigned short<br />#define bool int<br /><br />#define false 0<br />#define true 1<br /><br />#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 1<br />#define CYGACC_CALL_IF_DELAY_US(X) my_udelay(X)<br /><br />typedef struct dp83902a_priv_data {<br /> cyg_uint8* base;<br /> cyg_uint16* data;<br /> cyg_uint8* reset;<br /> int tx_next; /* First free Tx page */<br /> int tx_int; /* Expecting interrupt from this buffer */<br /> int rx_next; /* First free Rx page */<br /> int tx1, tx2; /* Page numbers for Tx buffers */<br /> unsigned long tx1_key, tx2_key; /* Used to ack when packet sent */<br /> int tx1_len, tx2_len;<br /> bool tx_started, running, hardwired_esa;<br /> cyg_uint8 esa[6];<br /> void* plf_priv;<br /><br /> /* Buffer allocation */<br /> int tx_buf1, tx_buf2;<br /> int rx_buf_start, rx_buf_end;<br />} dp83902a_priv_data_t;<br /><br />......<br /><br /><br /><br /><br />--------------------------------------------------------------------------------<br /><br /><br /><br />(3)修改8390.h<br /><br />......<br />/*<br />* Only generate indirect loads given a machine that needs them.<br />* - removed AMIGA_PCMCIA from this list, handled as ISA io now<br />*/<br /><br />#define n2k_inb(port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)))<br />#define n2k_outb(val,port) (*((volatile unsigned char *)(port+CONFIG_DRIVER_NE2000_BASE)) = ((unsigned char) val))<br /><br />#define EI_SHIFT(x) (x)<br />...... <br /><br /><br /><br />--------------------------------------------------------------------------------<br /><br /><br /><br /><br />网卡驱动程序的修改到此结束,以下是总线参数的修改:<br /><br />修改/board/tekkaman/tekkaman2410/lowlevel_init.S文件(参数都是参考 刘淼 的书):<br /><br />#define B1_BWSCON (DW16) /*@tekkaman*/<br />#define B2_BWSCON (DW16 + UBLB)<br />#define B3_BWSCON (DW16) /*@tekkaman*/<br />......<br /><br />#define B2_Tacs 0x3 /* 4clk tekkaman*/<br />#define B2_Tcos 0x3 /* 4clk tekkaman*/<br />#define B2_Tacc 0x7 /* 14clk */<br />#define B2_Tcoh 0x3 /* 4clk tekkaman*/<br />#define B2_Tah 0x3 /* 4clk tekkaman*/<br />#define B2_Tacp 0x3 /* 6clk tekkaman*/<br />#define B2_PMC 0x0 /* normal */<br /><br />......<br /><br /><br /><br />--------------------------------------------------------------------------------<br />在/include/configs/tekkaman2410.h文件中加上AX88796网卡驱动的信息:<br />/*<br />* Hardware drivers<br />*/<br />//#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */<br />//#define CS8900_BASE 0x19000300<br />//#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */<br />#define CONFIG_DRIVER_NE2000 1<br />#define CONFIG_DRIVER_NE2000_BASE (0x10000000+0x200)<br /><br /><br /><br /><br /><br />--------------------------------------------------------------------------------<br /><br /><br /><br />U-Boot下的AX88796移植结束了,我有复查过,应该在编译网卡驱动的时候连警告都不会有,所以如果您遇到了问题,在检查是否按照上面步骤移植后,还不能解决,可以联系我,QQ:78027228。不过我建议:最好是在看过我介绍的资料后再来移植,出了问题你自己就可以解决了。下一步的目标是U-Boot和Linux下的LCD驱动。以下附上我启动时和运行的输出信息(请注意U-Boot环境变量的设定):<br /><br />U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)<br /><br />U-Boot code: 33F80000 -> 33F98BC0 BSS: -> 33F9D3C0<br />DRAM: 64 MB<br />NAND: 64 MB<br />In: serial<br />Out: serial<br />Err: serial<br />Hit any key to stop autoboot: 0<br />[Tekkaman2410]# printenv<br />bootdelay=3<br />baudrate=115200<br />ethaddr=08:08:08:08:12:27<br />netmask=255.255.255.0<br />bootfile=zImage.img<br />loadaddr=0x30008000<br />bootargs=root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs ip=192.168.1.2:192.168.1.22::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M<br />bootcmd=tftp;bootm<br />ipaddr=192.168.1.2<br />serverip=192.168.1.22<br />stdin=serial<br />stdout=serial<br />stderr=serial<br /><br />Environment size: 382/65532 bytes<br /><br /><br />U-Boot 1.2.0 (Sep 25 2007 - 14:59:27)<br /><br />U-Boot code: 33F80000 -> 33F98BC0 BSS: -> 33F9D3C0<br />DRAM: 64 MB<br />NAND: 64 MB<br />In: serial<br />Out: serial<br />Err: serial<br />Hit any key to stop autoboot: 0<br />### eth_init<br />matched board 31<br />AX88796 - tekkmana ESA: 08:08:08:08:12:27<br />TFTP from server 192.168.1.22; our IP address is 192.168.1.2<br />Filename 'zImage.img'.<br />Load address: 0x30008000<br />Loading: #################################################################<br /> #################################################################<br /> #################################################################<br /> #################################################################<br /> #################################################################<br /> #############<br />done<br />Bytes transferred = 1727136 (1a5aa0 hex)<br />## Booting image at 30008000 ...<br /> Image Name: tekkamanninja<br /> Created: 2007-09-25 9:28:11 UTC<br /> Image Type: ARM Linux Kernel Image (uncompressed)<br /> Data Size: 1727072 Bytes = 1.6 MB<br /> Load Address: 30008000<br /> Entry Point: 30008040<br /> Verifying Checksum ... OK<br /> XIP Kernel Image ... OK<br /><br />Starting kernel ...<br /><br />Uncompressing Linux................................................................................................................ done, booting the kernel.<br />Linux version 2.6.22.2 (root@Tekkaman-Ninja) (gcc version 4.1.0) #5 Tue Sep 25 15:43:11 CST 2007<br />CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177<br />Machine: Tekkaman2410<br />Memory policy: ECC disabled, Data cache writeback<br />CPU S3C2410A (id 0x32410002)<br />S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz<br />S3C24XX Clocks, (c) 2004 Simtec Electronics<br />CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on<br />CPU0: D VIVT write-back cache<br />CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets<br />CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets<br />Built 1 zonelists. Total pages: 16256<br />Kernel command line: root=/dev/nfs rw nfsroot=192.168.1.22:/home/tekkaman/working/rootfs ip=192.168.1.2:192.168.1.22::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M<br />irq: clearing pending ext status 00000100<br />irq: clearing subpending status 00000002<br /> |
|