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

Posted normalmanzhao2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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博客

以上是关于Linux3.4.2移植CS8900网卡驱动到优龙FS2410开发板的主要内容,如果未能解决你的问题,请参考以下文章

移植触摸屏驱动到linux3.4.2

Linux 下 cs8900a 的移植说明

u-boot-2016.03在mini2440移植 之DM9000

u-boot-2014.10移植识别dm9000

为linux3.4.2内核编写LED驱动

输入子系统(input)框架解析(基于Linux3.4.2)