X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/f85e57578d144358f4d1e387455fc70ba9d52078..3a065a453ff58430b6915b58cf542e81d143ae3e:/target/linux/rdc-2.6/files/drivers/net/r6040.c diff --git a/target/linux/rdc-2.6/files/drivers/net/r6040.c b/target/linux/rdc-2.6/files/drivers/net/r6040.c index 81648ac13..376b6ecfe 100644 --- a/target/linux/rdc-2.6/files/drivers/net/r6040.c +++ b/target/linux/rdc-2.6/files/drivers/net/r6040.c @@ -139,6 +139,7 @@ struct r6040_private { u16 mcr0, mcr1; dma_addr_t desc_dma; char *desc_pool; + u16 switch_sig; }; struct r6040_chip_info { @@ -164,10 +165,15 @@ static struct r6040_chip_info r6040_chip_info[] __devinitdata = { { "RDC R6040 Knight", R6040_PCI_CMD, R6040_IO_SIZE, 0} }; +static char *parent = NULL; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) static int NUM_MAC_TABLE = 2 ; +module_param(parent, charp, 0444); +#else +MODULE_PARM(parent, "s"); #endif +MODULE_PARM_DESC(parent, "Parent network device name"); static int phy_table[] = { 0x1, 0x2}; static u8 adr_table[2][8] = {{0x00, 0x00, 0x60, 0x00, 0x00, 0x01}, {0x00, 0x00, 0x60, 0x00, 0x00, 0x02}}; @@ -264,6 +270,7 @@ static int __devinit r6040_init_one (struct pci_dev *pdev, /* Init RDC private data */ lp->mcr0 = 0x1002; lp->phy_addr = phy_table[card_idx]; + lp->switch_sig = 0; /* The RDC-specific entries in the device structure. */ dev->open = &r6040_open; @@ -330,13 +337,15 @@ r6040_open(struct net_device *dev) netif_start_queue(dev); + if (lp->switch_sig != 0x0243) + { /* set and active a timer process */ init_timer(&lp->timer); lp->timer.expires = TIMER_WUT; lp->timer.data = (unsigned long)dev; lp->timer.function = &r6040_timer; add_timer(&lp->timer); - + } return 0; } @@ -608,12 +617,29 @@ r6040_close(struct net_device *dev) return 0; } -/** - */ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { + struct r6040_private *lp = dev->priv; + RDC_DBUG("netdev_ioctl()", 0); - return 0; + if (lp->switch_sig == 0x0243 && cmd == SIOCDEVPRIVATE) + { + unsigned long *data = (unsigned long *)rq->ifr_data, args[4]; + int ioaddr = dev->base_addr; + unsigned int val; + + data = (unsigned long *)rq->ifr_data; + if (copy_from_user(args, data, 4*sizeof(unsigned long))) + return -EFAULT; + + /* port priority */ + if(args[0]&(1<<31))phy_write(ioaddr,29,19,(phy_read(ioaddr,29,19)|0x2000)); /* port 0 */ + if(args[0]&(1<<29))phy_write(ioaddr,29,19,(phy_read(ioaddr,29,19)|0x0020)); /* port 1 */ + if(args[0]&(1<<27))phy_write(ioaddr,29,20,(phy_read(ioaddr,29,20)|0x2000)); /* port 2 */ + if(args[0]&(1<<25))phy_write(ioaddr,29,20,(phy_read(ioaddr,29,20)|0x0020)); /* port 3 */ + + } + return -EOPNOTSUPP; } /** @@ -812,14 +838,20 @@ for (i = 0; i < RX_DCNT; i++) { /* Buffer Size Register */ outw(MAX_BUF_SIZE, ioaddr+0x18); - /* PHY Mode Check */ - phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP); - phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE); - - if (PHY_MODE == 0x3100) - lp->phy_mode = phy_mode_chk(dev); - else lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; - + if ((lp->switch_sig = phy_read(ioaddr, 0, 2)) == 0x0243) // ICPlus IP175C Signature + { + phy_write(ioaddr, 29,31, 0x175C); //Enable registers + lp->phy_mode = 0x8000; + } else { + /* PHY Mode Check */ + phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP); + phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE); + + if (PHY_MODE == 0x3100) + lp->phy_mode = phy_mode_chk(dev); + else + lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; + } /* MAC Bus Control Register */ outw(MBCR_DEFAULT, ioaddr+0x8); @@ -827,6 +859,16 @@ for (i = 0; i < RX_DCNT; i++) { lp->mcr0 |= lp->phy_mode; outw(lp->mcr0, ioaddr); + /* set interrupt waiting time and packet numbers */ + outw(0x0802, ioaddr + 0x0C); + outw(0x0802, ioaddr + 0x10); + + /* upgrade performance (by RDC guys) */ + phy_write(ioaddr,30,17,(phy_read(ioaddr,30,17)|0x4000)); //bit 14=1 + phy_write(ioaddr,30,17,~((~phy_read(ioaddr,30,17))|0x2000)); //bit 13=0 + phy_write(ioaddr,0,19,0x0000); + phy_write(ioaddr,0,30,0x01F0); + /* Interrupt Mask Register */ outw(R6040_INT_MASK, ioaddr + 0x40); } @@ -962,7 +1004,20 @@ static int __init r6040_init (void) printk(version); printed_version = 1; - return pci_module_init (&r6040_driver); + if (parent != NULL) + { + struct net_device *the_parent = dev_get_by_name(parent); + + if (the_parent == NULL) + { + printk (KERN_ERR DRV_NAME ": Unknown device \"%s\" specified.\n", parent); + return -EINVAL; + } + memcpy((u8 *)&adr_table[0][0], the_parent->dev_addr, 6); + memcpy((u8 *)&adr_table[1][0], the_parent->dev_addr, 6); + ++*(u8 *)&adr_table[0][5]; + } + return pci_register_driver (&r6040_driver); }