A, S3C2410 hardware connections and CS8900
FS2410 development board schematics I did not find, but you can see References 2, which is written in great detail
Second, the migration process
a) configure the kernel to support S3C2410
After selecting Samsung S3C24XX SoCs, it will automatically return to the previous menu (i.e. a front view), then choose:
b) configure the kernel to support CS89x0 card
Device Drivers-->Network device support-->Ethernet driver support—>
c) modify the drivers / net / ethenet / cirrus / cs89x0.c:
(1) In the beginning of the file, add the following lines, which play a role in the macro is defined CONFIG_ARCH_S3C24XX, acting represents FS2410 development board
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, in-depth study of the connection method S3C2410 memory