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

发布时间:2024-07-12  

一、S3C2410和CS8900的硬件连接

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

二、移植过程

a) 配置内核支持S3C2410

wps_clip_image-18745

wps_clip_image-18807

wps_clip_image-18876

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

wps_clip_image-19042

wps_clip_image-19170

b) 配置内核支持CS89x0网卡

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

wps_clip_image-19326


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

186 #include

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 SETUPn");

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 %xn",

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) failedn", 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 median", 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博客


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>