aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/declance.c164
1 files changed, 117 insertions, 47 deletions
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 4ae0fed7122e..9f7e1db8ce62 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * adopted from sunlance.c by Richard van den Berg 6 * adopted from sunlance.c by Richard van den Berg
7 * 7 *
8 * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki 8 * Copyright (C) 2002, 2003, 2005, 2006 Maciej W. Rozycki
9 * 9 *
10 * additional sources: 10 * additional sources:
11 * - PMAD-AA TURBOchannel Ethernet Module Functional Specification, 11 * - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
@@ -44,6 +44,8 @@
44 * v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the 44 * v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the
45 * PMAX requirement to only use halfword accesses to the 45 * PMAX requirement to only use halfword accesses to the
46 * buffer. macro 46 * buffer. macro
47 *
48 * v0.011: Converted the PMAD to the driver model. macro
47 */ 49 */
48 50
49#include <linux/crc32.h> 51#include <linux/crc32.h>
@@ -58,6 +60,7 @@
58#include <linux/spinlock.h> 60#include <linux/spinlock.h>
59#include <linux/stddef.h> 61#include <linux/stddef.h>
60#include <linux/string.h> 62#include <linux/string.h>
63#include <linux/tc.h>
61#include <linux/types.h> 64#include <linux/types.h>
62 65
63#include <asm/addrspace.h> 66#include <asm/addrspace.h>
@@ -69,15 +72,16 @@
69#include <asm/dec/kn01.h> 72#include <asm/dec/kn01.h>
70#include <asm/dec/machtype.h> 73#include <asm/dec/machtype.h>
71#include <asm/dec/system.h> 74#include <asm/dec/system.h>
72#include <asm/dec/tc.h>
73 75
74static char version[] __devinitdata = 76static char version[] __devinitdata =
75"declance.c: v0.010 by Linux MIPS DECstation task force\n"; 77"declance.c: v0.011 by Linux MIPS DECstation task force\n";
76 78
77MODULE_AUTHOR("Linux MIPS DECstation task force"); 79MODULE_AUTHOR("Linux MIPS DECstation task force");
78MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver"); 80MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
79MODULE_LICENSE("GPL"); 81MODULE_LICENSE("GPL");
80 82
83#define __unused __attribute__ ((unused))
84
81/* 85/*
82 * card types 86 * card types
83 */ 87 */
@@ -246,7 +250,6 @@ struct lance_init_block {
246struct lance_private { 250struct lance_private {
247 struct net_device *next; 251 struct net_device *next;
248 int type; 252 int type;
249 int slot;
250 int dma_irq; 253 int dma_irq;
251 volatile struct lance_regs *ll; 254 volatile struct lance_regs *ll;
252 255
@@ -288,6 +291,7 @@ struct lance_regs {
288 291
289int dec_lance_debug = 2; 292int dec_lance_debug = 2;
290 293
294static struct tc_driver dec_lance_tc_driver;
291static struct net_device *root_lance_dev; 295static struct net_device *root_lance_dev;
292 296
293static inline void writereg(volatile unsigned short *regptr, short value) 297static inline void writereg(volatile unsigned short *regptr, short value)
@@ -1023,7 +1027,7 @@ static void lance_set_multicast_retry(unsigned long _opaque)
1023 lance_set_multicast(dev); 1027 lance_set_multicast(dev);
1024} 1028}
1025 1029
1026static int __init dec_lance_init(const int type, const int slot) 1030static int __init dec_lance_probe(struct device *bdev, const int type)
1027{ 1031{
1028 static unsigned version_printed; 1032 static unsigned version_printed;
1029 static const char fmt[] = "declance%d"; 1033 static const char fmt[] = "declance%d";
@@ -1031,6 +1035,7 @@ static int __init dec_lance_init(const int type, const int slot)
1031 struct net_device *dev; 1035 struct net_device *dev;
1032 struct lance_private *lp; 1036 struct lance_private *lp;
1033 volatile struct lance_regs *ll; 1037 volatile struct lance_regs *ll;
1038 resource_size_t start = 0, len = 0;
1034 int i, ret; 1039 int i, ret;
1035 unsigned long esar_base; 1040 unsigned long esar_base;
1036 unsigned char *esar; 1041 unsigned char *esar;
@@ -1038,14 +1043,18 @@ static int __init dec_lance_init(const int type, const int slot)
1038 if (dec_lance_debug && version_printed++ == 0) 1043 if (dec_lance_debug && version_printed++ == 0)
1039 printk(version); 1044 printk(version);
1040 1045
1041 i = 0; 1046 if (bdev)
1042 dev = root_lance_dev; 1047 snprintf(name, sizeof(name), "%s", bdev->bus_id);
1043 while (dev) { 1048 else {
1044 i++; 1049 i = 0;
1045 lp = (struct lance_private *)dev->priv; 1050 dev = root_lance_dev;
1046 dev = lp->next; 1051 while (dev) {
1052 i++;
1053 lp = (struct lance_private *)dev->priv;
1054 dev = lp->next;
1055 }
1056 snprintf(name, sizeof(name), fmt, i);
1047 } 1057 }
1048 snprintf(name, sizeof(name), fmt, i);
1049 1058
1050 dev = alloc_etherdev(sizeof(struct lance_private)); 1059 dev = alloc_etherdev(sizeof(struct lance_private));
1051 if (!dev) { 1060 if (!dev) {
@@ -1063,7 +1072,6 @@ static int __init dec_lance_init(const int type, const int slot)
1063 spin_lock_init(&lp->lock); 1072 spin_lock_init(&lp->lock);
1064 1073
1065 lp->type = type; 1074 lp->type = type;
1066 lp->slot = slot;
1067 switch (type) { 1075 switch (type) {
1068 case ASIC_LANCE: 1076 case ASIC_LANCE:
1069 dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE); 1077 dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
@@ -1110,12 +1118,22 @@ static int __init dec_lance_init(const int type, const int slot)
1110 break; 1118 break;
1111#ifdef CONFIG_TC 1119#ifdef CONFIG_TC
1112 case PMAD_LANCE: 1120 case PMAD_LANCE:
1113 claim_tc_card(slot); 1121 dev_set_drvdata(bdev, dev);
1122
1123 start = to_tc_dev(bdev)->resource.start;
1124 len = to_tc_dev(bdev)->resource.end - start + 1;
1125 if (!request_mem_region(start, len, bdev->bus_id)) {
1126 printk(KERN_ERR
1127 "%s: Unable to reserve MMIO resource\n",
1128 bdev->bus_id);
1129 ret = -EBUSY;
1130 goto err_out_dev;
1131 }
1114 1132
1115 dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot)); 1133 dev->mem_start = CKSEG1ADDR(start);
1116 dev->mem_end = dev->mem_start + 0x100000; 1134 dev->mem_end = dev->mem_start + 0x100000;
1117 dev->base_addr = dev->mem_start + 0x100000; 1135 dev->base_addr = dev->mem_start + 0x100000;
1118 dev->irq = get_tc_irq_nr(slot); 1136 dev->irq = to_tc_dev(bdev)->interrupt;
1119 esar_base = dev->mem_start + 0x1c0002; 1137 esar_base = dev->mem_start + 0x1c0002;
1120 lp->dma_irq = -1; 1138 lp->dma_irq = -1;
1121 1139
@@ -1174,7 +1192,7 @@ static int __init dec_lance_init(const int type, const int slot)
1174 printk(KERN_ERR "%s: declance_init called with unknown type\n", 1192 printk(KERN_ERR "%s: declance_init called with unknown type\n",
1175 name); 1193 name);
1176 ret = -ENODEV; 1194 ret = -ENODEV;
1177 goto err_out_free_dev; 1195 goto err_out_dev;
1178 } 1196 }
1179 1197
1180 ll = (struct lance_regs *) dev->base_addr; 1198 ll = (struct lance_regs *) dev->base_addr;
@@ -1188,7 +1206,7 @@ static int __init dec_lance_init(const int type, const int slot)
1188 "%s: Ethernet station address prom not found!\n", 1206 "%s: Ethernet station address prom not found!\n",
1189 name); 1207 name);
1190 ret = -ENODEV; 1208 ret = -ENODEV;
1191 goto err_out_free_dev; 1209 goto err_out_resource;
1192 } 1210 }
1193 /* Check the prom contents */ 1211 /* Check the prom contents */
1194 for (i = 0; i < 8; i++) { 1212 for (i = 0; i < 8; i++) {
@@ -1198,7 +1216,7 @@ static int __init dec_lance_init(const int type, const int slot)
1198 printk(KERN_ERR "%s: Something is wrong with the " 1216 printk(KERN_ERR "%s: Something is wrong with the "
1199 "ethernet station address prom!\n", name); 1217 "ethernet station address prom!\n", name);
1200 ret = -ENODEV; 1218 ret = -ENODEV;
1201 goto err_out_free_dev; 1219 goto err_out_resource;
1202 } 1220 }
1203 } 1221 }
1204 1222
@@ -1255,48 +1273,51 @@ static int __init dec_lance_init(const int type, const int slot)
1255 if (ret) { 1273 if (ret) {
1256 printk(KERN_ERR 1274 printk(KERN_ERR
1257 "%s: Unable to register netdev, aborting.\n", name); 1275 "%s: Unable to register netdev, aborting.\n", name);
1258 goto err_out_free_dev; 1276 goto err_out_resource;
1259 } 1277 }
1260 1278
1261 lp->next = root_lance_dev; 1279 if (!bdev) {
1262 root_lance_dev = dev; 1280 lp->next = root_lance_dev;
1281 root_lance_dev = dev;
1282 }
1263 1283
1264 printk("%s: registered as %s.\n", name, dev->name); 1284 printk("%s: registered as %s.\n", name, dev->name);
1265 return 0; 1285 return 0;
1266 1286
1267err_out_free_dev: 1287err_out_resource:
1288 if (bdev)
1289 release_mem_region(start, len);
1290
1291err_out_dev:
1268 free_netdev(dev); 1292 free_netdev(dev);
1269 1293
1270err_out: 1294err_out:
1271 return ret; 1295 return ret;
1272} 1296}
1273 1297
1298static void __exit dec_lance_remove(struct device *bdev)
1299{
1300 struct net_device *dev = dev_get_drvdata(bdev);
1301 resource_size_t start, len;
1302
1303 unregister_netdev(dev);
1304 start = to_tc_dev(bdev)->resource.start;
1305 len = to_tc_dev(bdev)->resource.end - start + 1;
1306 release_mem_region(start, len);
1307 free_netdev(dev);
1308}
1274 1309
1275/* Find all the lance cards on the system and initialize them */ 1310/* Find all the lance cards on the system and initialize them */
1276static int __init dec_lance_probe(void) 1311static int __init dec_lance_platform_probe(void)
1277{ 1312{
1278 int count = 0; 1313 int count = 0;
1279 1314
1280 /* Scan slots for PMAD-AA cards first. */
1281#ifdef CONFIG_TC
1282 if (TURBOCHANNEL) {
1283 int slot;
1284
1285 while ((slot = search_tc_card("PMAD-AA")) >= 0) {
1286 if (dec_lance_init(PMAD_LANCE, slot) < 0)
1287 break;
1288 count++;
1289 }
1290 }
1291#endif
1292
1293 /* Then handle onboard devices. */
1294 if (dec_interrupt[DEC_IRQ_LANCE] >= 0) { 1315 if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
1295 if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) { 1316 if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
1296 if (dec_lance_init(ASIC_LANCE, -1) >= 0) 1317 if (dec_lance_probe(NULL, ASIC_LANCE) >= 0)
1297 count++; 1318 count++;
1298 } else if (!TURBOCHANNEL) { 1319 } else if (!TURBOCHANNEL) {
1299 if (dec_lance_init(PMAX_LANCE, -1) >= 0) 1320 if (dec_lance_probe(NULL, PMAX_LANCE) >= 0)
1300 count++; 1321 count++;
1301 } 1322 }
1302 } 1323 }
@@ -1304,21 +1325,70 @@ static int __init dec_lance_probe(void)
1304 return (count > 0) ? 0 : -ENODEV; 1325 return (count > 0) ? 0 : -ENODEV;
1305} 1326}
1306 1327
1307static void __exit dec_lance_cleanup(void) 1328static void __exit dec_lance_platform_remove(void)
1308{ 1329{
1309 while (root_lance_dev) { 1330 while (root_lance_dev) {
1310 struct net_device *dev = root_lance_dev; 1331 struct net_device *dev = root_lance_dev;
1311 struct lance_private *lp = netdev_priv(dev); 1332 struct lance_private *lp = netdev_priv(dev);
1312 1333
1313 unregister_netdev(dev); 1334 unregister_netdev(dev);
1314#ifdef CONFIG_TC
1315 if (lp->slot >= 0)
1316 release_tc_card(lp->slot);
1317#endif
1318 root_lance_dev = lp->next; 1335 root_lance_dev = lp->next;
1319 free_netdev(dev); 1336 free_netdev(dev);
1320 } 1337 }
1321} 1338}
1322 1339
1323module_init(dec_lance_probe); 1340#ifdef CONFIG_TC
1324module_exit(dec_lance_cleanup); 1341static int __init dec_lance_tc_probe(struct device *dev);
1342static int __exit dec_lance_tc_remove(struct device *dev);
1343
1344static const struct tc_device_id dec_lance_tc_table[] = {
1345 { "DEC ", "PMAD-AA " },
1346 { }
1347};
1348MODULE_DEVICE_TABLE(tc, dec_lance_tc_table);
1349
1350static struct tc_driver dec_lance_tc_driver = {
1351 .id_table = dec_lance_tc_table,
1352 .driver = {
1353 .name = "declance",
1354 .bus = &tc_bus_type,
1355 .probe = dec_lance_tc_probe,
1356 .remove = __exit_p(dec_lance_tc_remove),
1357 },
1358};
1359
1360static int __init dec_lance_tc_probe(struct device *dev)
1361{
1362 int status = dec_lance_probe(dev, PMAD_LANCE);
1363 if (!status)
1364 get_device(dev);
1365 return status;
1366}
1367
1368static int __exit dec_lance_tc_remove(struct device *dev)
1369{
1370 put_device(dev);
1371 dec_lance_remove(dev);
1372 return 0;
1373}
1374#endif
1375
1376static int __init dec_lance_init(void)
1377{
1378 int status;
1379
1380 status = tc_register_driver(&dec_lance_tc_driver);
1381 if (!status)
1382 dec_lance_platform_probe();
1383 return status;
1384}
1385
1386static void __exit dec_lance_exit(void)
1387{
1388 dec_lance_platform_remove();
1389 tc_unregister_driver(&dec_lance_tc_driver);
1390}
1391
1392
1393module_init(dec_lance_init);
1394module_exit(dec_lance_exit);