aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/net/pegasus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/net/pegasus.c')
-rw-r--r--drivers/usb/net/pegasus.c144
1 files changed, 89 insertions, 55 deletions
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 683e3df5d607..156a2f1cb39a 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -45,7 +45,7 @@
45/* 45/*
46 * Version Information 46 * Version Information
47 */ 47 */
48#define DRIVER_VERSION "v0.6.12 (2005/01/13)" 48#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
49#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" 49#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
50#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" 50#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
51 51
@@ -57,12 +57,14 @@ static const char driver_name[] = "pegasus";
57 57
58static int loopback = 0; 58static int loopback = 0;
59static int mii_mode = 0; 59static int mii_mode = 0;
60static char *devid=NULL;
60 61
61static struct usb_eth_dev usb_dev_id[] = { 62static struct usb_eth_dev usb_dev_id[] = {
62#define PEGASUS_DEV(pn, vid, pid, flags) \ 63#define PEGASUS_DEV(pn, vid, pid, flags) \
63 {.name = pn, .vendor = vid, .device = pid, .private = flags}, 64 {.name = pn, .vendor = vid, .device = pid, .private = flags},
64#include "pegasus.h" 65#include "pegasus.h"
65#undef PEGASUS_DEV 66#undef PEGASUS_DEV
67 {NULL, 0, 0, 0},
66 {NULL, 0, 0, 0} 68 {NULL, 0, 0, 0}
67}; 69};
68 70
@@ -71,6 +73,7 @@ static struct usb_device_id pegasus_ids[] = {
71 {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid}, 73 {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
72#include "pegasus.h" 74#include "pegasus.h"
73#undef PEGASUS_DEV 75#undef PEGASUS_DEV
76 {},
74 {} 77 {}
75}; 78};
76 79
@@ -79,8 +82,10 @@ MODULE_DESCRIPTION(DRIVER_DESC);
79MODULE_LICENSE("GPL"); 82MODULE_LICENSE("GPL");
80module_param(loopback, bool, 0); 83module_param(loopback, bool, 0);
81module_param(mii_mode, bool, 0); 84module_param(mii_mode, bool, 0);
85module_param(devid, charp, 0);
82MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); 86MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
83MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0"); 87MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
88MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'");
84 89
85/* use ethtool to change the level for any given device */ 90/* use ethtool to change the level for any given device */
86static int msg_level = -1; 91static int msg_level = -1;
@@ -113,7 +118,7 @@ static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
113 break; 118 break;
114 default: 119 default:
115 if (netif_msg_drv(pegasus)) 120 if (netif_msg_drv(pegasus))
116 dev_err(&pegasus->intf->dev, "%s, status %d\n", 121 dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
117 __FUNCTION__, urb->status); 122 __FUNCTION__, urb->status);
118 } 123 }
119 pegasus->flags &= ~ETH_REGS_CHANGED; 124 pegasus->flags &= ~ETH_REGS_CHANGED;
@@ -308,9 +313,9 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
308 __le16 regdi; 313 __le16 regdi;
309 int ret; 314 int ret;
310 315
311 ret = set_register(pegasus, PhyCtrl, 0); 316 set_register(pegasus, PhyCtrl, 0);
312 ret = set_registers(pegasus, PhyAddr, sizeof (data), data); 317 set_registers(pegasus, PhyAddr, sizeof (data), data);
313 ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ)); 318 set_register(pegasus, PhyCtrl, (indx | PHY_READ));
314 for (i = 0; i < REG_TIMEOUT; i++) { 319 for (i = 0; i < REG_TIMEOUT; i++) {
315 ret = get_registers(pegasus, PhyCtrl, 1, data); 320 ret = get_registers(pegasus, PhyCtrl, 1, data);
316 if (data[0] & PHY_DONE) 321 if (data[0] & PHY_DONE)
@@ -319,12 +324,12 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
319 if (i < REG_TIMEOUT) { 324 if (i < REG_TIMEOUT) {
320 ret = get_registers(pegasus, PhyData, 2, &regdi); 325 ret = get_registers(pegasus, PhyData, 2, &regdi);
321 *regd = le16_to_cpu(regdi); 326 *regd = le16_to_cpu(regdi);
322 return 1; 327 return ret;
323 } 328 }
324 if (netif_msg_drv(pegasus)) 329 if (netif_msg_drv(pegasus))
325 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); 330 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
326 331
327 return 0; 332 return ret;
328} 333}
329 334
330static int mdio_read(struct net_device *dev, int phy_id, int loc) 335static int mdio_read(struct net_device *dev, int phy_id, int loc)
@@ -344,20 +349,20 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
344 349
345 data[1] = (u8) regd; 350 data[1] = (u8) regd;
346 data[2] = (u8) (regd >> 8); 351 data[2] = (u8) (regd >> 8);
347 ret = set_register(pegasus, PhyCtrl, 0); 352 set_register(pegasus, PhyCtrl, 0);
348 ret = set_registers(pegasus, PhyAddr, sizeof(data), data); 353 set_registers(pegasus, PhyAddr, sizeof(data), data);
349 ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); 354 set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
350 for (i = 0; i < REG_TIMEOUT; i++) { 355 for (i = 0; i < REG_TIMEOUT; i++) {
351 ret = get_registers(pegasus, PhyCtrl, 1, data); 356 ret = get_registers(pegasus, PhyCtrl, 1, data);
352 if (data[0] & PHY_DONE) 357 if (data[0] & PHY_DONE)
353 break; 358 break;
354 } 359 }
355 if (i < REG_TIMEOUT) 360 if (i < REG_TIMEOUT)
356 return 0; 361 return ret;
357 362
358 if (netif_msg_drv(pegasus)) 363 if (netif_msg_drv(pegasus))
359 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); 364 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
360 return 1; 365 return -ETIMEDOUT;
361} 366}
362 367
363static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) 368static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
@@ -374,9 +379,9 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
374 __le16 retdatai; 379 __le16 retdatai;
375 int ret; 380 int ret;
376 381
377 ret = set_register(pegasus, EpromCtrl, 0); 382 set_register(pegasus, EpromCtrl, 0);
378 ret = set_register(pegasus, EpromOffset, index); 383 set_register(pegasus, EpromOffset, index);
379 ret = set_register(pegasus, EpromCtrl, EPROM_READ); 384 set_register(pegasus, EpromCtrl, EPROM_READ);
380 385
381 for (i = 0; i < REG_TIMEOUT; i++) { 386 for (i = 0; i < REG_TIMEOUT; i++) {
382 ret = get_registers(pegasus, EpromCtrl, 1, &tmp); 387 ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -386,12 +391,12 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
386 if (i < REG_TIMEOUT) { 391 if (i < REG_TIMEOUT) {
387 ret = get_registers(pegasus, EpromData, 2, &retdatai); 392 ret = get_registers(pegasus, EpromData, 2, &retdatai);
388 *retdata = le16_to_cpu(retdatai); 393 *retdata = le16_to_cpu(retdatai);
389 return 0; 394 return ret;
390 } 395 }
391 396
392 if (netif_msg_drv(pegasus)) 397 if (netif_msg_drv(pegasus))
393 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); 398 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
394 return -1; 399 return -ETIMEDOUT;
395} 400}
396 401
397#ifdef PEGASUS_WRITE_EEPROM 402#ifdef PEGASUS_WRITE_EEPROM
@@ -400,8 +405,8 @@ static inline void enable_eprom_write(pegasus_t * pegasus)
400 __u8 tmp; 405 __u8 tmp;
401 int ret; 406 int ret;
402 407
403 ret = get_registers(pegasus, EthCtrl2, 1, &tmp); 408 get_registers(pegasus, EthCtrl2, 1, &tmp);
404 ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); 409 set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
405} 410}
406 411
407static inline void disable_eprom_write(pegasus_t * pegasus) 412static inline void disable_eprom_write(pegasus_t * pegasus)
@@ -409,9 +414,9 @@ static inline void disable_eprom_write(pegasus_t * pegasus)
409 __u8 tmp; 414 __u8 tmp;
410 int ret; 415 int ret;
411 416
412 ret = get_registers(pegasus, EthCtrl2, 1, &tmp); 417 get_registers(pegasus, EthCtrl2, 1, &tmp);
413 ret = set_register(pegasus, EpromCtrl, 0); 418 set_register(pegasus, EpromCtrl, 0);
414 ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); 419 set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
415} 420}
416 421
417static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) 422static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
@@ -420,11 +425,11 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
420 __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; 425 __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
421 int ret; 426 int ret;
422 427
423 ret = set_registers(pegasus, EpromOffset, 4, d); 428 set_registers(pegasus, EpromOffset, 4, d);
424 enable_eprom_write(pegasus); 429 enable_eprom_write(pegasus);
425 ret = set_register(pegasus, EpromOffset, index); 430 set_register(pegasus, EpromOffset, index);
426 ret = set_registers(pegasus, EpromData, 2, &data); 431 set_registers(pegasus, EpromData, 2, &data);
427 ret = set_register(pegasus, EpromCtrl, EPROM_WRITE); 432 set_register(pegasus, EpromCtrl, EPROM_WRITE);
428 433
429 for (i = 0; i < REG_TIMEOUT; i++) { 434 for (i = 0; i < REG_TIMEOUT; i++) {
430 ret = get_registers(pegasus, EpromCtrl, 1, &tmp); 435 ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -433,10 +438,10 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
433 } 438 }
434 disable_eprom_write(pegasus); 439 disable_eprom_write(pegasus);
435 if (i < REG_TIMEOUT) 440 if (i < REG_TIMEOUT)
436 return 0; 441 return ret;
437 if (netif_msg_drv(pegasus)) 442 if (netif_msg_drv(pegasus))
438 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); 443 dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
439 return -1; 444 return -ETIMEDOUT;
440} 445}
441#endif /* PEGASUS_WRITE_EEPROM */ 446#endif /* PEGASUS_WRITE_EEPROM */
442 447
@@ -454,10 +459,9 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
454static void set_ethernet_addr(pegasus_t * pegasus) 459static void set_ethernet_addr(pegasus_t * pegasus)
455{ 460{
456 __u8 node_id[6]; 461 __u8 node_id[6];
457 int ret;
458 462
459 get_node_id(pegasus, node_id); 463 get_node_id(pegasus, node_id);
460 ret = set_registers(pegasus, EthID, sizeof (node_id), node_id); 464 set_registers(pegasus, EthID, sizeof (node_id), node_id);
461 memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); 465 memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
462} 466}
463 467
@@ -465,30 +469,29 @@ static inline int reset_mac(pegasus_t * pegasus)
465{ 469{
466 __u8 data = 0x8; 470 __u8 data = 0x8;
467 int i; 471 int i;
468 int ret;
469 472
470 ret = set_register(pegasus, EthCtrl1, data); 473 set_register(pegasus, EthCtrl1, data);
471 for (i = 0; i < REG_TIMEOUT; i++) { 474 for (i = 0; i < REG_TIMEOUT; i++) {
472 ret = get_registers(pegasus, EthCtrl1, 1, &data); 475 get_registers(pegasus, EthCtrl1, 1, &data);
473 if (~data & 0x08) { 476 if (~data & 0x08) {
474 if (loopback & 1) 477 if (loopback & 1)
475 break; 478 break;
476 if (mii_mode && (pegasus->features & HAS_HOME_PNA)) 479 if (mii_mode && (pegasus->features & HAS_HOME_PNA))
477 ret = set_register(pegasus, Gpio1, 0x34); 480 set_register(pegasus, Gpio1, 0x34);
478 else 481 else
479 ret = set_register(pegasus, Gpio1, 0x26); 482 set_register(pegasus, Gpio1, 0x26);
480 ret = set_register(pegasus, Gpio0, pegasus->features); 483 set_register(pegasus, Gpio0, pegasus->features);
481 ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET); 484 set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
482 break; 485 break;
483 } 486 }
484 } 487 }
485 if (i == REG_TIMEOUT) 488 if (i == REG_TIMEOUT)
486 return 1; 489 return -ETIMEDOUT;
487 490
488 if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || 491 if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
489 usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { 492 usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
490 ret = set_register(pegasus, Gpio0, 0x24); 493 set_register(pegasus, Gpio0, 0x24);
491 ret = set_register(pegasus, Gpio0, 0x26); 494 set_register(pegasus, Gpio0, 0x26);
492 } 495 }
493 if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) { 496 if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
494 __u16 auxmode; 497 __u16 auxmode;
@@ -527,7 +530,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
527 write_mii_word(pegasus, 0, 0x1b, auxmode | 4); 530 write_mii_word(pegasus, 0, 0x1b, auxmode | 4);
528 } 531 }
529 532
530 return 0; 533 return ret;
531} 534}
532 535
533static void fill_skb_pool(pegasus_t * pegasus) 536static void fill_skb_pool(pegasus_t * pegasus)
@@ -881,9 +884,8 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
881static inline void disable_net_traffic(pegasus_t * pegasus) 884static inline void disable_net_traffic(pegasus_t * pegasus)
882{ 885{
883 int tmp = 0; 886 int tmp = 0;
884 int ret;
885 887
886 ret = set_registers(pegasus, EthCtrl0, 2, &tmp); 888 set_registers(pegasus, EthCtrl0, 2, &tmp);
887} 889}
888 890
889static inline void get_interrupt_interval(pegasus_t * pegasus) 891static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -1206,18 +1208,17 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
1206static inline void setup_pegasus_II(pegasus_t * pegasus) 1208static inline void setup_pegasus_II(pegasus_t * pegasus)
1207{ 1209{
1208 __u8 data = 0xa5; 1210 __u8 data = 0xa5;
1209 int ret;
1210 1211
1211 ret = set_register(pegasus, Reg1d, 0); 1212 set_register(pegasus, Reg1d, 0);
1212 ret = set_register(pegasus, Reg7b, 1); 1213 set_register(pegasus, Reg7b, 1);
1213 mdelay(100); 1214 mdelay(100);
1214 if ((pegasus->features & HAS_HOME_PNA) && mii_mode) 1215 if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
1215 ret = set_register(pegasus, Reg7b, 0); 1216 set_register(pegasus, Reg7b, 0);
1216 else 1217 else
1217 ret = set_register(pegasus, Reg7b, 2); 1218 set_register(pegasus, Reg7b, 2);
1218 1219
1219 ret = set_register(pegasus, 0x83, data); 1220 set_register(pegasus, 0x83, data);
1220 ret = get_registers(pegasus, 0x83, 1, &data); 1221 get_registers(pegasus, 0x83, 1, &data);
1221 1222
1222 if (data == 0xa5) { 1223 if (data == 0xa5) {
1223 pegasus->chip = 0x8513; 1224 pegasus->chip = 0x8513;
@@ -1225,14 +1226,14 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
1225 pegasus->chip = 0; 1226 pegasus->chip = 0;
1226 } 1227 }
1227 1228
1228 ret = set_register(pegasus, 0x80, 0xc0); 1229 set_register(pegasus, 0x80, 0xc0);
1229 ret = set_register(pegasus, 0x83, 0xff); 1230 set_register(pegasus, 0x83, 0xff);
1230 ret = set_register(pegasus, 0x84, 0x01); 1231 set_register(pegasus, 0x84, 0x01);
1231 1232
1232 if (pegasus->features & HAS_HOME_PNA && mii_mode) 1233 if (pegasus->features & HAS_HOME_PNA && mii_mode)
1233 ret = set_register(pegasus, Reg81, 6); 1234 set_register(pegasus, Reg81, 6);
1234 else 1235 else
1235 ret = set_register(pegasus, Reg81, 2); 1236 set_register(pegasus, Reg81, 2);
1236} 1237}
1237 1238
1238 1239
@@ -1414,9 +1415,42 @@ static struct usb_driver pegasus_driver = {
1414 .resume = pegasus_resume, 1415 .resume = pegasus_resume,
1415}; 1416};
1416 1417
1418static void parse_id(char *id)
1419{
1420 unsigned int vendor_id=0, device_id=0, flags=0, i=0;
1421 char *token, *name=NULL;
1422
1423 if ((token = strsep(&id, ":")) != NULL)
1424 name = token;
1425 /* name now points to a null terminated string*/
1426 if ((token = strsep(&id, ":")) != NULL)
1427 vendor_id = simple_strtoul(token, NULL, 16);
1428 if ((token = strsep(&id, ":")) != NULL)
1429 device_id = simple_strtoul(token, NULL, 16);
1430 flags = simple_strtoul(id, NULL, 16);
1431 pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n",
1432 driver_name, name, vendor_id, device_id, flags);
1433
1434 if (vendor_id > 0x10000 || vendor_id == 0)
1435 return;
1436 if (device_id > 0x10000 || device_id == 0)
1437 return;
1438
1439 for (i=0; usb_dev_id[i].name; i++);
1440 usb_dev_id[i].name = name;
1441 usb_dev_id[i].vendor = vendor_id;
1442 usb_dev_id[i].device = device_id;
1443 usb_dev_id[i].private = flags;
1444 pegasus_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
1445 pegasus_ids[i].idVendor = vendor_id;
1446 pegasus_ids[i].idProduct = device_id;
1447}
1448
1417static int __init pegasus_init(void) 1449static int __init pegasus_init(void)
1418{ 1450{
1419 pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION); 1451 pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
1452 if (devid)
1453 parse_id(devid);
1420 pegasus_workqueue = create_singlethread_workqueue("pegasus"); 1454 pegasus_workqueue = create_singlethread_workqueue("pegasus");
1421 if (!pegasus_workqueue) 1455 if (!pegasus_workqueue)
1422 return -ENOMEM; 1456 return -ENOMEM;