diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2007-02-05 19:28:27 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-07 18:49:11 -0500 |
commit | 257b346d20cd309a4c5a13b8de5ad2b7c63b590a (patch) | |
tree | 7fc65b6f0338e6de9011ced2af027fcdd744b2be /drivers/net/declance.c | |
parent | d9a9720eab7437aa7f34dcbb92bb4bc8cc36bba9 (diff) |
mips: declance: Driver model for the PMAD-A
This is a set of changes that converts the PMAD-A support to the driver model.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/declance.c')
-rw-r--r-- | drivers/net/declance.c | 164 |
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 | ||
74 | static char version[] __devinitdata = | 76 | static 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 | ||
77 | MODULE_AUTHOR("Linux MIPS DECstation task force"); | 79 | MODULE_AUTHOR("Linux MIPS DECstation task force"); |
78 | MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver"); | 80 | MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver"); |
79 | MODULE_LICENSE("GPL"); | 81 | MODULE_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 { | |||
246 | struct lance_private { | 250 | struct 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 | ||
289 | int dec_lance_debug = 2; | 292 | int dec_lance_debug = 2; |
290 | 293 | ||
294 | static struct tc_driver dec_lance_tc_driver; | ||
291 | static struct net_device *root_lance_dev; | 295 | static struct net_device *root_lance_dev; |
292 | 296 | ||
293 | static inline void writereg(volatile unsigned short *regptr, short value) | 297 | static 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 | ||
1026 | static int __init dec_lance_init(const int type, const int slot) | 1030 | static 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 | ||
1267 | err_out_free_dev: | 1287 | err_out_resource: |
1288 | if (bdev) | ||
1289 | release_mem_region(start, len); | ||
1290 | |||
1291 | err_out_dev: | ||
1268 | free_netdev(dev); | 1292 | free_netdev(dev); |
1269 | 1293 | ||
1270 | err_out: | 1294 | err_out: |
1271 | return ret; | 1295 | return ret; |
1272 | } | 1296 | } |
1273 | 1297 | ||
1298 | static 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 */ |
1276 | static int __init dec_lance_probe(void) | 1311 | static 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 | ||
1307 | static void __exit dec_lance_cleanup(void) | 1328 | static 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 | ||
1323 | module_init(dec_lance_probe); | 1340 | #ifdef CONFIG_TC |
1324 | module_exit(dec_lance_cleanup); | 1341 | static int __init dec_lance_tc_probe(struct device *dev); |
1342 | static int __exit dec_lance_tc_remove(struct device *dev); | ||
1343 | |||
1344 | static const struct tc_device_id dec_lance_tc_table[] = { | ||
1345 | { "DEC ", "PMAD-AA " }, | ||
1346 | { } | ||
1347 | }; | ||
1348 | MODULE_DEVICE_TABLE(tc, dec_lance_tc_table); | ||
1349 | |||
1350 | static 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 | |||
1360 | static 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 | |||
1368 | static 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 | |||
1376 | static 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 | |||
1386 | static void __exit dec_lance_exit(void) | ||
1387 | { | ||
1388 | dec_lance_platform_remove(); | ||
1389 | tc_unregister_driver(&dec_lance_tc_driver); | ||
1390 | } | ||
1391 | |||
1392 | |||
1393 | module_init(dec_lance_init); | ||
1394 | module_exit(dec_lance_exit); | ||