Linux3.4.2移植CS8900网卡驱动到优龙FS2410开发板

一、S3C2410和CS8900的硬件连接

FS2410开发板的原理图我没有找到,但可看参考资料2,里面写的非常详细

二、移植过程

a) 配置内核支持S3C2410

选好Samsung S3C24XX SoCs后,会自动返回到上一级菜单(即前一张图),然后选择:

b) 配置内核支持CS89x0网卡

Device Drivers-->Network device support-->Ethernet driver support—>

c) 修改drivers/net/ethenet/cirrus/cs89x0.c:

(1)在文件开头增加以下几行,它们在宏CONFIG_ARCH_S3C24XX被定义时起作用,表示作用于FS2410开发板

183 	static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
184 	#elif defined(CONFIG_ARCH_S3C24XX)
185 	#include <asm/irq.h>
186 	#include <mach/regs-mem.h>
187 	#define S3C24XX_PA_CS8900   0x19000000  /* 物理基地址 */
188 	static unsigned int netcard_portlist[] __initdata = {0, 0};     /* 在下面进行设置 */
189 	static unsigned int cs8900_irq_map[] = {IRQ_EINT9, 0, 0, 0};    /* 中断号*/
190 	#else
191 	#ifndef CONFIG_CS89x0_PLATFORM
192 	static unsigned int netcard_portlist[] __used __initdata =

(2)修改入口函数cs89x0_probe

以下使用宏CONFIG_ARCH_S3C24XX包裹起来的代码是新加的

311 	struct net_device * __init cs89x0_probe(int unit)
312 	{
313 		struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
314 		unsigned *port;
315 		int err = 0;
316 		int irq;
317 		int io;
318 	#if defined(CONFIG_ARCH_S3C24XX)
319 			unsigned int oldval_bwscon; 	/* 用来保存BWSCON寄存器的值 */
320 			unsigned int oldval_bankcon3;	/* 用来保存S3C2410_BANKCON3寄存器的值 */
321 	#endif
322 		if (!dev)
323 			return ERR_PTR(-ENODEV);
324
325 		sprintf(dev->name, "eth%d", unit);
326 		netdev_boot_setup_check(dev);
327 		io = dev->base_addr;
328 		irq = dev->irq;
329 	#if defined(CONFIG_ARCH_S3C24XX)
330 			// cs89x0_probe会被调用多次,我们只需要1次,根据netcard_portlist[0]的值忽略后面的调用
331 			if (netcard_portlist[0])
332 				return -ENODEV;
333 			// 将CS8900A的物理地址转换为虚拟地址,0x300是CS8900A内部的IO空间的偏移地址
334 			netcard_portlist[0] = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;
335 			/* 设置默认MAC地址,
336 			 * MAC地址可以由CS8900A外接的EEPROM设定(有些单板没接EEPROM),
337 			 * 或者启动系统后使用ifconfig修改
338 			 */
339 			dev->dev_addr[0] = 0x08;
340 			dev->dev_addr[1] = 0x89;
341 			dev->dev_addr[2] = 0x89;
342 			dev->dev_addr[3] = 0x89;
343 			dev->dev_addr[4] = 0x89;
344 			dev->dev_addr[5] = 0x89;
345 			/* 设置Bank3: 总线宽度为16, 使能nWAIT, 使能UB/LB。by www.100ask.net */
346 			oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);
347 			*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12)) 348 				| S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;
349 			/* 设置BANK3的时间参数, by www.100ask.net */
350 			oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);
351 			*((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;
352 	#endif
353 		if (net_debug)
354 			printk("cs89x0:cs89x0_probe(0x%x)\n", io);
355
356 		if (io > 0x1ff)	{	/* Check a single specified location. */
357 			err = cs89x0_probe1(dev, io, 0);
358 		} else if (io != 0) {	/* Don‘t probe at all. */
359 			err = -ENXIO;
360 		} else {
361 			for (port = netcard_portlist; *port; port++) {
362 				if (cs89x0_probe1(dev, *port, 0) == 0)
363 					break;
364 				dev->irq = irq;
365 			}
366 			if (!*port)
367 				err = -ENODEV;
368 		}
369 		if (err)
370 			goto out;
371 		return dev;
372 	out:
373 	#if defined(CONFIG_ARCH_S3C24XX)
374 			iounmap(netcard_portlist[0]);
375 			netcard_portlist[0] = 0;
376
377 			/* 恢复寄存器原来的值 */
378 			*((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
379 			*((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;
380 	#endif
381 		free_netdev(dev);
382 		printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");
383 		return ERR_PTR(err);
384 	}
385 	//#endif   多了一个
386 	#endif

(3)修改模块入口函数init_module

以下使用宏CONFIG_ARCH_S3C24XX包裹起来的代码是新加的

1879	int __init init_module(void)
1880	{
1881		struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
1882		struct net_local *lp;
1883		int ret = 0;
1884	#if defined(CONFIG_ARCH_S3C24XX)
1885			unsigned int oldval_bwscon; 	/* 用来保存BWSCON寄存器的值 */
1886			unsigned int oldval_bankcon3;	/* 用来保存S3C2410_BANKCON3寄存器的值 */
1887	#endif
1888	#if DEBUGGING
1889		net_debug = debug;
1890	#else
1891		debug = 0;
1892	#endif
1893		if (!dev)
1894			return -ENOMEM;
1895
1896	#if defined(CONFIG_ARCH_S3C24XX)
1897			// 将CS8900A的物理地址转换为虚拟地址,0x300是CS8900A内部的IO空间的偏移地址
1898			dev->base_addr = io = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;
1899			dev->irq = irq = cs8900_irq_map[0]; /* 中断号 */
1900
1901			/* 设置默认MAC地址,
1902			 * MAC地址可以由CS8900A外接的EEPROM设定(有些单板没接EEPROM),
1903			 * 或者启动系统后使用ifconfig修改
1904			 */
1905			dev->dev_addr[0] = 0x08;
1906			dev->dev_addr[1] = 0x89;
1907			dev->dev_addr[2] = 0x89;
1908			dev->dev_addr[3] = 0x89;
1909			dev->dev_addr[4] = 0x89;
1910			dev->dev_addr[5] = 0x89;
1911
1912			/* 设置Bank3: 总线宽度为16, 使能nWAIT, 使能UB/LB。by www.100ask.net */
1913			oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);
1914			*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12)) 1915				| S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;
1916
1917			/* 设置BANK3的时间参数, by www.100ask.net */
1918			oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);
1919			*((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;
1920	#else
1921			dev->irq = irq;
1922			dev->base_addr = io;
1923	#endif
 …       …
1971	out:
1972	#if defined(CONFIG_ARCH_S3C24XX)
1973			iounmap(dev->base_addr);
1974
1975			/* 恢复寄存器原来的值 */
1976			*((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
1977			*((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;
1978	#endif
1979		free_netdev(dev);
1980		return ret;
1981	}

(4)修改模块退出函数cleanup_module

以下使用宏CONFIG_ARCH_S3C24XX包裹起来的代码是新加的

1983	void __exit
1984	cleanup_module(void)
1985	{
1986		unregister_netdev(dev_cs89x0);
1987		writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
1988		release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
1989	#if defined(CONFIG_ARCH_S3C24XX)
1990			iounmap(dev_cs89x0->base_addr);
1991	#endif
1992		free_netdev(dev_cs89x0);
1993	}
1994	#endif /* MODULE && !CONFIG_CS89x0_PLATFORM */
1995

(5)修改net_open

1240	net_open(struct net_device *dev)
1241	{
1242		struct net_local *lp = netdev_priv(dev);
1243		int result = 0;
1244		int i;
1245		int ret;
1246	#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C24XX) /* uses irq#1, so this won‘t work */
1247		if (dev->irq < 2) {
1248			/* Allow interrupts to be generated by the chip */
1249	/* Cirrus‘ release had this: */
1250	#if 0
1251			writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
1252	#endif
1253	/* And 2.3.47 had this: */
1254			writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
 ...    ...
1273		}
1274		else
1275	#endif
1276		{
1277	#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)&& !defined(CONFIG_ARCH_S3C24XX)
1278			if (((1 << dev->irq) & lp->irq_map) == 0) {
1279				printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
1280								   dev->name, dev->irq, lp->irq_map);
1281				ret = -EAGAIN;
1282				goto bad_out;
1283			}
1284	#endif
1285	/* FIXME: Cirrus‘ release had this: */
1286			writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
1287	/* And 2.3.47 had this: */
1288	#if 0
1289			writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
1290	#endif
1291			write_irq(dev, lp->chip_type, dev->irq);
1292	#if defined(CONFIG_ARCH_S3C24XX)
1293			ret = request_irq(dev->irq, &net_interrupt, IRQF_TRIGGER_RISING, dev->name, dev);
1294	#else
1295		ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);
1296	#endif
1297		if (ret) {
1298				printk(KERN_ERR "cs89x0: request_irq(%d) failed\n", dev->irq);
1299				goto bad_out;
1300			}
1301		}
 ...    ...
1358			/* check to make sure that they have the "right" hardware available */
1359		switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
1360		case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
1361		case A_CNF_MEDIA_AUI:   result = lp->adapter_cnf & A_CNF_AUI; break;
1362		case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
1363			default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
1364			}
1365	#if defined(CONFIG_ARCH_PNX010X) || defined(CONFIG_ARCH_S3C24XX)
1366		result = A_CNF_10B_T;
1367	#endif
1368		if (!result) {
1369					printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
1370	release_dma:
 ...	...
1478	}

(6)全局变量static int io 修改为static unsigned int io;

原因请看参考资料1

最后,编译内核,执行make uImage。

三、参考资料

1、《嵌入式linux应用开发完全手册》韦东山

2、《FS2410中CS8900A IO模式驱动分析》杨志平

3、S3C2410 内存连接方法的深入研究

4、(转)CS8900A 驱动程序分析(国嵌)

5、AUI与BNC - BaiShi 在路上 - CSDN博客

原文地址:https://www.cnblogs.com/normalmanzhao2003/p/11355691.html

时间: 2024-10-08 06:35:26

Linux3.4.2移植CS8900网卡驱动到优龙FS2410开发板的相关文章

【转】 linux内核移植和网卡驱动(二)

原文网址:http://blog.chinaunix.net/uid-29589379-id-4708911.html 一,内核移植步骤: 1, 修改顶层目录下的Makefile ARCH            ?= $(SUBARCH) CROSS_COMPILE   ?= $(CONFIG_CROSS_COMPILE:"%"=%) 修改为: ARCH :=arm CROSS_COMPILE :=/usr/local/arm/4.4.3/bin/arm-linux- 2, 拷贝配置文

基于tiny4412的Linux内核移植 -- DM9621NP网卡驱动移植(四)

作者信息 作者: 彭东林 邮箱:[email protected] QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 网卡芯片:DM9621NP 交叉编译工具链: arm-none-linux-gnueabi-gcc

LINUX 内核移植以及网卡驱动添加

我用的板子是sama5d3xek,原来板子内核是linux-at91-3.13,升级使用linux-at91-4.10 首先去官网下载一个linux—at91-4.10压缩包,然后在ubuntu里解压,进入源文件目录,我这里用的是arm板子所以更改Makefile 如下 vi Makefile 使的 ARCH ?= $(SUBARCH)  CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) 改为 ARCH ?= arm CROSS_COMPIL

移植tslib和Qt5.6到三星s5pv210开发板

tslib1.4移植 下载tslib1.4后 1.cp tslib-1.4.tar.bz2 /home/gec 2.tar jxvf tslib-1.4.tar.bz2 3.sudo -s 4.cd tslib-1.4/ 5../configure --host=arm-linux --prefix=/usr/local/arm ac_cv_func_malloc_0_nonnull=yes 6.make 7.make install 修改tslib安装目录下的/etc/ts.conf文件去掉#

Gt9xx芯片,在规格书+Linux驱动的基础上,移植为USB裸机经验。直接用开发板,不去碰硬件的坑。

1,用内核代码和规格书来印证数据格式: //命令3字节,IC地址 u8 end_cmd[3] = {GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0}; //总长度 前 3个字节.最大点数*8.加1 u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1]={GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF}; 2,读数据:调

linux网卡驱动移植

这里重要的是物理层PHY receiver,MAC(media access control)层,这里与软件中的协议栈不同,在硬件上MAC是PHY的下一层.DM9000A将MAC和PHY做到一起,也可以像IIS设备那样,SOC内有IIS的控制器,而声卡UDA1341放在片外.网卡当然也有这种设计,它是把PHY的下层MAC放入SOC内,片外的是PHY,当然我暂时还没见过这种的.DM9000A的输入是并行的总线,可以和CPU直接IO.而IIS那种需要通过:CPU CORE BUS->I2S控制器->

AM335x(TQ335x)学习笔记——Nand&amp;&amp;网卡驱动移植

移植完成声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前先感慨一下:TI的维护的内核真的很健壮,DTS真的很强大. 1. Nand驱动移植 阅读TQ335x的原理图可知,TQ335x的Nand连接到了GPMC上,且都是使用的相应引脚的MODE0复用功能,AM335x上上电复位后这些引脚的默认状态就处于MODE0模式,故无需进行pinmux设置,原始的DT

AM335x(TQ335x)学习笔记——Nand&amp;amp;&amp;amp;网卡驱动移植

移植完毕声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前先感慨一下:TI的维护的内核真的非常健壮,DTS真的非常强大. 1. Nand驱动移植 阅读TQ335x的原理图可知,TQ335x的Nand连接到了GPMC上,且与DTS中默认的配置吻合,此处不做不论什么改动,详情例如以下: nandflash_pins_s0: nandflash_pins_s0

linux-2.6.32在mini2440开发板上移植之DM9000网卡移植

   移植DM9000 网卡驱动1 设备资源初始化      Linux-2..6.32.2 已经自带了完善的DM9000 网卡驱动驱动(源代码位置:linux-2.6.32.2/drivers/net/dm9000.c),它也是一个平台设备,因此在目标平台初始化代码中,只要填写好相应的结构表即可,具体步骤如下: 首先添加驱动所需的头文件dm9000.h:#include <linux/dm9000.h> 再定义DM9000 网卡设备的物理基地址,以便后面用到:/* DM9000AEP 10/