参考自http://bbs.witech.com.cn/forum.php?mod=viewthread&tid=16373
1.修改include/configs/smdk6410.h
//注释掉下面几行
//#ifdef CONFIG_DRIVER_SMC911X
//#undef CONFIG_DRIVER_CS8900 u//#define CONFIG_DRIVER_SMC911X_BASE 0x18800300 / Z' i2 L( P5 h8 m# H0 F
//#else
//#define CONFIG_DRIVER_CS8900 0 /* we have a CS8900 on-board */
//#define CS8900_BASE 0x18800300
//#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
//增加下面4行 ) h6 _! A- v9 u+ E
#define CONFIG_DRIVER_DM9000 1 8 W9 a4 G2 F/ d& w3 {- w
#define CONFIG_DM9000_BASE 0x18000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4)
#define CONFIG_DM9000_USE_16BIT 1
//#define CONFIG_DM9000_DEBUG 3 F* L4 d" n- Y+ B9 g( s( V . X$ S# s- X3 S
3 W7 D) P# j6 S- m, I
2.修改drivers/dm9000x.c
a.在dm9000x.c中注释以下内容:(从环境变量中读取MAC地址) 4 |' ?7 x* I# C9 u+ o4 D! b& o* R
/* Set Node address */
/* for (i = 0; i < 6; i++)
((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
*/ 5 s& D1 v( m- o
添加以下内容,代替以上注释内容: * P1 K" U/ \- M3 ~
char *s, *e;
s = getenv ("ethaddr");
for (i = 0; i < 6; ++i) $ o$ c5 w N# @
{
bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
if (s) 6 M# M7 a3 S4 }' A. F: \
s = (*e) ? e + 1 : e;
}
b.参考Linux内核中代码,发现Linux的dm9000在rx函数中添加do while循环,于是按照Linux内核源码在u-boot中也添加do while循环。红色部分为添加代码。 / z1 P3 z% O; [2 h. e1 y2 P
g; } T& o+ s6 S3 H; `
DM9000_ior(DM9000_MRRH); # J$ }* h9 K. N& N; S. N( `
DM9000_ior(DM9000_MRRL);
do{
/* Check packet ready or not */ ) W: B+ e9 H" y* h
DM9000_ior(DM9000_MRCMDX); /* Dummy read */
rxbyte = DM9000_inb(DM9000_DATA); /* Got most updated data */
if (rxbyte == 0)
return 0; + q9 V9 E3 m h, H( V6 Z4 l) N
/* Status check: this byte must be 0 or 1 */
if (rxbyte > 1) {
DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */ ( _' t7 w3 K; M+ w. H* L3 F: j
DM9000_DBG("rx status check: %d\n", rxbyte); ; K# ?. R, X( B
}
DM9000_DBG("receiving packet\n"); % j# G" P( a9 ~; ?
/* A packet ready now & Get status/length */ & j2 V1 n5 K. }- i$ ^
DM9000_outb(DM9000_MRCMD, DM9000_IO);
/* */
RxStatus = DM9000_inw(DM9000_DATA); ( K3 x. u) r* c. x; v2 @3 u; l$ U
RxLen = DM9000_inw(DM9000_DATA);
/* */ ' Z. Q( ?! S$ M
DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
/* Move data from DM9000 */ 5 i5 X' @4 u1 u$ x9 k3 i- v
/* Read received packet from RX SRAM */ * l( o$ y4 U/ H* z7 ^$ W% Q
tmplen = (RxLen + 1) / 2;
for (i = 0; i < tmplen; i++)
{
((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA); 5 K6 r# ]2 l" O+ T! C
//printf("%d ",((u16 *) rdptr)[i]); - h7 S+ l. D$ m0 [) E `+ }, n
}
/* */ 6 }7 G, x- B W* X% B! p; b" S5 E
if ((RxStatus & 0xbf00) || (RxLen < 0x40) 9 p# H& K( W. X
|| (RxLen > DM9000_PKT_MAX)) {
if (RxStatus & 0x100) {
printf("rx fifo error\n"); . C' ~" R. q2 \
} 2 B, j+ q& X/ G$ l4 j0 S& d
if (RxStatus & 0x200) { 1 I0 Y; p! Y% Y' {9 U
printf("rx crc error\n");
}
if (RxStatus & 0x8000) {
printf("rx length error\n");
} : @" d6 Q1 o9 K0 \: K
if (RxLen > DM9000_PKT_MAX) { 3 s* k) E3 y2 ~
printf("rx length too big\n");
dm9000_reset();
}
} else {
/* Pass to upper layer */ / X! E A' P9 O, J
DM9000_DBG("passing packet to upper layer\n");
NetReceive(NetRxPackets[0], RxLen); 8 L! O. m, }6 m) M, b
//return RxLen;
} * I/ F( i( V6 Z" p6 B4 T
} 3 Y3 Q2 K# @/ r
while (rxbyte == DM9000_PKT_RDY);
//return 0;
return RxLen;
# m* _2 F( z: ^) t6 v8 X" d1 J
c. 注释掉下面2行,修正一直无法收到数据的错误,不要每次调用halt的时候都对PHY进行复位操作,否则会引起无法接受到数据的情况 .
void eth_halt(void)
{
DM9000_DBG("eth_halt dummy by kyon\n");
/* RESET devie */
//phy_write(0, 0x8000); /* PHY RESET */
//DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */ 5 F, o& g
}
4、至此,修改已完成。若ping不通linux主机,可能是环境变量没设好,同时注意有时要将无线关掉,切记:网线要插上
5、精简uboot
smdk6410.h中去掉了有关I2C、USB、RTC、KGDB、等的包涵定义,编译时出错,在/common目录下修改Makefile文件,去掉有关usb的.o文件和cmd_date.o,编译通过。u-boot.bin原来为192k,现在为160k。