u16 mcr0, mcr1;
dma_addr_t desc_dma;
char *desc_pool;
+ u16 switch_sig;
};
struct r6040_chip_info {
{
{ "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}};
static int r6040_close(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops;
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static void r6040_down(struct net_device *dev);
static void r6040_up(struct net_device *dev);
static void r6040_tx_timeout (struct net_device *dev);
/* 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;
dev->stop = &r6040_close;
dev->get_stats = &r6040_get_stats;
dev->set_multicast_list = &set_multicast_list;
+ dev->do_ioctl = &netdev_ioctl;
dev->ethtool_ops = &netdev_ethtool_ops;
dev->tx_timeout = &r6040_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
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;
}
return 0;
}
+#define DMZ_GPIO 1
+#define RDC3210_CFGREG_ADDR 0x0CF8
+#define RDC3210_CFGREG_DATA 0x0CFC
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct r6040_private *lp = dev->priv;
+
+ RDC_DBUG("netdev_ioctl()", 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 */
+
+ /* DMZ LED */
+ val = 0x80000000 | (7 << 11) | ((0x48));
+ outl(val, RDC3210_CFGREG_ADDR);
+ udelay(10);
+ val = inl(RDC3210_CFGREG_DATA);
+
+ val |= (0x1 << DMZ_GPIO);
+ outl(val, RDC3210_CFGREG_DATA);
+ udelay(10);
+
+ val = 0x80000000 | (7 << 11) | ((0x4C));
+ outl(val, RDC3210_CFGREG_ADDR);
+ udelay(10);
+ val = inl(RDC3210_CFGREG_DATA);
+ if(args[0]&(1<<23)) /* DMZ enabled */
+ val &= ~(0x1 << DMZ_GPIO); /* low activated */
+ else val |= (0x1 << DMZ_GPIO);
+ outl(val, RDC3210_CFGREG_DATA);
+ udelay(10);
+ }
+ return 0;
+}
+
/**
Stop RDC MAC and Free the allocated resource
*/
/* Buffer Size Register */
outw(MAX_BUF_SIZE, ioaddr+0x18);
+ 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);
- /* Port priority */
- phy_write(ioaddr,29,19,(phy_read(ioaddr,29,19)|0x0020)); /* port 0 */
- phy_write(ioaddr,29,19,(phy_read(ioaddr,29,19)|0x0020)); /* port 1 */
- phy_write(ioaddr,29,20,(phy_read(ioaddr,29,20)|0x2000)); /* port 2 */
- phy_write(ioaddr,29,20,(phy_read(ioaddr,29,20)|0x0020)); /* port 3 */
-
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);
printk(version);
printed_version = 1;
+ 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);
}