Linux下利用DM9000C构造双网口
时间:2010-09-05 来源:kjq_smile
linux kernel:2.6.13
gcc:arm-linux-gcc-3.4.1
platform:s3c2440
DM9000CEP是一款完全集成的和符合成本效益单芯片快速以太网MAC控制器与一般处理接口,一个10/100M自适应的PHY和4K DWORD值的SRAM 。它的目的是在低功耗和高性能进程的3.3V与5V的支持宽容。DM9000CEP还提供了介质无关的接口,来连接所有提供支持介质无关接口功能的家用电话线网络设备或其他收发器。该DM9000CEP支持8位, 16位和32 -位接口访问内部存储器,以支持不同的处理器。DM9000cep物理协议层接口完全支持使用10MBps下3类、4类、5类非屏蔽双绞线和100MBps下5类非屏蔽双绞线。这是完全符合IEEE 802.3u规格。它的自动协调功能将自动完成配置以最大限度地适合其线路带宽。还支持IEEE 802.3x全双工流量控制。这个工作里面DM9000CEP是非常简单的,所以用户可以容易的移植任何系统下的端口驱动程序。
本文实现两个网口。
1、修改makefile文件,obj-$(CONFIG_DM9000) += dm9000.o,有的内核为dm9000x.o;
2、在内核编译配置选项中,driver-->net-->10/100M net-->DM9000 support;
3、修改mach-sbc2440.c,添加
.flags = DM9000_PLATF_16BITONLY
};
static struct platform_device s3c_device_eth0 = {
.name = "dm9000",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_dm9k_resource0),
.resource = s3c_dm9k_resource0,
.dev = {
.platform_data = &s3c_device_dm9k_pdata0,
},
}; static struct resource s3c_dm9k_resource1[] = {
[0] = {
.start = S3C2410_CS3,
.end = S3C2410_CS3+ 3,
.flags = IORESOURCE_MEM
},
[1] = {
.start = S3C2410_CS3+ 4,
.end = S3C2410_CS3+ 7,
.flags = IORESOURCE_MEM
},
[2] = {
.start = IRQ_EINT8,
.end = IRQ_EINT8,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
}
}; static struct dm9000_plat_data s3c_device_dm9k_pdata1 = {
.flags = DM9000_PLATF_16BITONLY
};
static struct platform_device s3c_device_eth1 = {
.name = "dm9000",
.id = 1,
.num_resources = ARRAY_SIZE(s3c_dm9k_resource1),
.resource = s3c_dm9k_resource1,
.dev = {
.platform_data = &s3c_device_dm9k_pdata1,
},
};
static void s3c_dm9k_bus_init(void)
{
unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;
*((volatile unsigned int *)S3C2410_BWSCON) =
(oldval_bwscon & ~(0x33<<12)) | S3C2410_BWSCON_DW3_16|S3C2410_BWSCON_DW4_16;
}
void __init sbc2440_init(void)
{
...... s3c_dm9k_bus_init();//koujinqiao ...... } 4、更改dm9000.c中dm9000_open(struct net_device *dev) if (request_irq(dev->irq, &dm9000_interrupt, SA_INTERRUPT, dev->name, dev))
return -EAGAIN; set_irq_type(dev->irq, IRQT_FALLING); //if (request_irq(dev->irq, &dm9000_interrupt, SA_SHIRQ, dev->name, dev))
// return -EAGAIN; 设置中断为单独中断 编译通过后,启动系统。
eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
eth1: link up, 100Mbps, full-duplex, lpa 0xCDE1 则需要重新启动系统。启动信息显示为 Try to bring eth0 interface up......eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
Done
Try to bring eth1 interface up......eth1: link up, 100Mbps, full-duplex, lpa 0xCDE1
Done 才能可以正常ping通。 ping通后若使用ifconfig ethX down 则ethX不能再ping 通。 问题怀疑为启动初始化不对 添加函数
static void
dm9000_reinit_dm9000(board_info_t * db)
{
PRINTK1("entering %s\n",__FUNCTION__); /* I/O mode */
db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ /* GPIO0 on pre-activate PHY */
iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
iow(db, DM9000_GPR, 0); /* Enable PHY */ /* Program operating register */
iow(db, DM9000_TCR, 0); /* TX Polling clear */
iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
iow(db, DM9000_FCR, 0xff); /* Flow Control */
iow(db, DM9000_SMCR, 0); /* Special Mode */
/* clear TX status */
iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ /* Activate DM9000 */
iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); /* Init Driver variable */
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
}
在
static void
dm9000_reset(board_info_t * db)
{
PRINTK1("dm9000: resetting\n");
/* RESET device */
writeb(DM9000_NCR, db->io_addr);
udelay(200);
writeb(NCR_RST, db->io_data);
udelay(200); dm9000_reinit_dm9000(db);
} 添加了dm9000_reinit_dm9000(db);
解决了重新启动系统才能ping通网络的问题。 网络最终解决:
1、修改makefile文件,编译dm9000.c
2、修改mach-sbc2440.c
3、修改dm9000.c.
static struct resource s3c_dm9k_resource0[] = {
[0] = {
.start = S3C2410_CS4,
.end = S3C2410_CS4 + 3,
.flags = IORESOURCE_MEM
},
[1] = {
.start = S3C2410_CS4 + 4,
.end = S3C2410_CS4 + 7,
.flags = IORESOURCE_MEM
},
[2] = {
.start = IRQ_EINT7,
.end = IRQ_EINT7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
}
};
.flags = DM9000_PLATF_16BITONLY
};
static struct platform_device s3c_device_eth0 = {
.name = "dm9000",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_dm9k_resource0),
.resource = s3c_dm9k_resource0,
.dev = {
.platform_data = &s3c_device_dm9k_pdata0,
},
}; static struct resource s3c_dm9k_resource1[] = {
[0] = {
.start = S3C2410_CS3,
.end = S3C2410_CS3+ 3,
.flags = IORESOURCE_MEM
},
[1] = {
.start = S3C2410_CS3+ 4,
.end = S3C2410_CS3+ 7,
.flags = IORESOURCE_MEM
},
[2] = {
.start = IRQ_EINT8,
.end = IRQ_EINT8,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
}
}; static struct dm9000_plat_data s3c_device_dm9k_pdata1 = {
.flags = DM9000_PLATF_16BITONLY
};
static struct platform_device s3c_device_eth1 = {
.name = "dm9000",
.id = 1,
.num_resources = ARRAY_SIZE(s3c_dm9k_resource1),
.resource = s3c_dm9k_resource1,
.dev = {
.platform_data = &s3c_device_dm9k_pdata1,
},
};
static void s3c_dm9k_bus_init(void)
{
unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;
*((volatile unsigned int *)S3C2410_BWSCON) =
(oldval_bwscon & ~(0x33<<12)) | S3C2410_BWSCON_DW3_16|S3C2410_BWSCON_DW4_16;
}
void __init sbc2440_init(void)
{
...... s3c_dm9k_bus_init();//koujinqiao ...... } 4、更改dm9000.c中dm9000_open(struct net_device *dev) if (request_irq(dev->irq, &dm9000_interrupt, SA_INTERRUPT, dev->name, dev))
return -EAGAIN; set_irq_type(dev->irq, IRQT_FALLING); //if (request_irq(dev->irq, &dm9000_interrupt, SA_SHIRQ, dev->name, dev))
// return -EAGAIN; 设置中断为单独中断 编译通过后,启动系统。
eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
eth1: link up, 100Mbps, full-duplex, lpa 0xCDE1 则需要重新启动系统。启动信息显示为 Try to bring eth0 interface up......eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
Done
Try to bring eth1 interface up......eth1: link up, 100Mbps, full-duplex, lpa 0xCDE1
Done 才能可以正常ping通。 ping通后若使用ifconfig ethX down 则ethX不能再ping 通。 问题怀疑为启动初始化不对 添加函数
static void
dm9000_reinit_dm9000(board_info_t * db)
{
PRINTK1("entering %s\n",__FUNCTION__); /* I/O mode */
db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ /* GPIO0 on pre-activate PHY */
iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
iow(db, DM9000_GPR, 0); /* Enable PHY */ /* Program operating register */
iow(db, DM9000_TCR, 0); /* TX Polling clear */
iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
iow(db, DM9000_FCR, 0xff); /* Flow Control */
iow(db, DM9000_SMCR, 0); /* Special Mode */
/* clear TX status */
iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ /* Activate DM9000 */
iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); /* Init Driver variable */
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
}
在
static void
dm9000_reset(board_info_t * db)
{
PRINTK1("dm9000: resetting\n");
/* RESET device */
writeb(DM9000_NCR, db->io_addr);
udelay(200);
writeb(NCR_RST, db->io_data);
udelay(200); dm9000_reinit_dm9000(db);
} 添加了dm9000_reinit_dm9000(db);
解决了重新启动系统才能ping通网络的问题。 网络最终解决:
1、修改makefile文件,编译dm9000.c
2、修改mach-sbc2440.c
3、修改dm9000.c.
相关阅读 更多 +