static void hieth_net_isr_proc(struct hieth_netdev_local *ld, int ints) { if ((ints & UD_BIT_NAME(HIETH_INT_MULTI_RXRDY)) && (hieth_hw_recv_tryup(ld) > 0)) { tasklet_schedule(&ld->bf_recv); } if (ints & UD_BIT_NAME(HIETH_INT_TXQUE_RDY)) { hieth_irq_disable(ld, UD_BIT_NAME(HIETH_INT_TXQUE_RDY)); netif_wake_queue(hieth_devs_save[ld->port]); } }
int hieth_glb_preinit_dummy(struct hieth_netdev_local *ld) { local_lock_init(ld); //FIXME: hieth_glb_preinit_dummy //HW MAX DEFAULT RX-PKT-LEN [42,1518] //HW MAC FILTER TABLE DISABLE /*soft reset */ hieth_writel_bits(ld, 1, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET); udelay(1000); hieth_writel_bits(ld, 0, GLB_SOFT_RESET, BITS_ETH_SOFT_RESET); hieth_set_endian_mode(ld, HIETH_LITTLE_ENDIAN); hieth_set_linkstat(ld, 0); hieth_set_negmode(ld, HIETH_NEGMODE_CPUSET); /* RMII mode */ hieth_set_mii_mode(ld, UD_BIT_NAME(HIETH_MII_RMII_MODE)); hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS)); hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS_ENA)); hieth_writel_bits(ld, ~0, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT); hieth_irq_disable(ld, ~0); /* init */ hieth_writel(ld, 0, GLB_FWCTRL); hieth_writel(ld, 0, GLB_MACTCTRL); /*disable vlan func */ hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_VLAN_ENABLE); /*enable UpEther<->CPU */ hieth_writel_bits(ld, 1, GLB_FWCTRL, BITS_FW2CPU_ENA_UP); hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_FWALL2CPU_UP); hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_UP); hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_MACT_ENA_UP); /*enable DownEther<->CPU and UpEther<->CPU */ hieth_writel_bits(ld, 1, GLB_FWCTRL, BITS_FW2CPU_ENA_DOWN); hieth_writel_bits(ld, 0, GLB_FWCTRL, BITS_FWALL2CPU_DOWN); hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_DOWN); hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_MACT_ENA_DOWN); hieth_set_mac_leadcode_cnt_limit(ld, 0); return 0; }
static int hieth_net_hard_start_xmit( struct sk_buff *skb, struct net_device *dev) { int ret; struct hieth_netdev_local *ld = netdev_priv(dev); int tx_lpi_assert = 0x2; unsigned int data; data = readl(ld->iobase + 0x488); data &= ~tx_lpi_assert; writel(data, ld->iobase + 0x488); hieth_xmit_release_skb(ld); dma_map_single(ld->dev, skb->data, skb->len, DMA_TO_DEVICE); ret = hieth_xmit_real_send(ld, skb); if (ret < 0) { ld->stats.tx_dropped++; hieth_error("tx bug, drop packet"); BUG(); return NETDEV_TX_BUSY; } dev->trans_start = jiffies; ld->stats.tx_packets++; ld->stats.tx_bytes += skb->len; hieth_clear_irqstatus(ld, UD_BIT_NAME(HIETH_INT_TXQUE_RDY)); if (!hieth_hw_xmitq_ready(ld)) { netif_stop_queue(dev); hieth_irq_enable(ld, UD_BIT_NAME(HIETH_INT_TXQUE_RDY)); } return NETDEV_TX_OK; }
static void hieth_adjust_link(struct net_device *dev) { int stat = 0; struct hieth_netdev_local *ld = netdev_priv(dev); stat |= (ld->phy->link) ? HIETH_LINKED : 0; stat |= (ld->phy->duplex == DUPLEX_FULL) ? HIETH_DUP_FULL : 0; stat |= (ld->phy->speed == SPEED_100) ? HIETH_SPD_100M : 0; if (stat != ld->link_stat) { if (ld->phy->link == 0) { printk(KERN_INFO "***link down status changed***.\n"); writel(0x0, ld->iobase + 0x490); writel(0x0, ld->iobase + 0x484); } else { writel(0x1, ld->iobase + 0x490); #ifdef CONFIG_EEE_SUPPORT if (eee_available > NO_EEE) { int data = ld->driver->eee_enable(); if (DEBUG) printk(KERN_INFO "adjust_link " "data:(=2?): %d\n", data); if (eee_available == MAC_EEE) { writel(0x10, ld->iobase + 0x484); /* enable intr */ writel(0x1f, ld->iobase + 0x480); } else writel(0x0, ld->iobase + 0x484); } #endif } hieth_set_linkstat(ld, stat); phy_print_status(ld->phy); ld->link_stat = stat; hieth_set_mii_mode(ld, UD_BIT_NAME(CONFIG_HIETH_MII_RMII_MODE)); } }
static int hieth_net_close(struct net_device *dev) { struct hieth_netdev_local *ld = netdev_priv(dev); hieth_irq_disable(ld, UD_BIT_NAME(HIETH_INT_MULTI_RXRDY)); phy_stop(ld->phy); del_timer_sync(&ld->monitor); /* reset and init port */ hieth_port_reset(ld, ld->port); hieth_port_init(ld, ld->port); skb_queue_purge(&ld->rx_head); skb_queue_purge(&ld->rx_hw); skb_queue_purge(&ld->tx_hw); ld->tx_hw_cnt = 0; module_put(THIS_MODULE); return 0; }
static int hieth_platdev_probe_port(struct platform_device *pdev, int port) { int ret = -1; struct net_device *netdev = NULL; struct hieth_netdev_local *ld; if ((UP_PORT != port) && (DOWN_PORT != port)) { hieth_error("port error!"); ret = -ENODEV; goto _error_exit; } netdev = alloc_etherdev(sizeof(*ld)); if (netdev == NULL) { hieth_error("alloc_etherdev fail!"); ret = -ENOMEM; goto _error_alloc_etherdev; } SET_NETDEV_DEV(netdev, &pdev->dev); netdev->irq = CONFIG_HIETH_IRQNUM; netdev->watchdog_timeo = 3*HZ; netdev->netdev_ops = &hieth_netdev_ops; netdev->ethtool_ops = &hieth_ethtools_ops; /* init hieth_global somethings... */ hieth_devs_save[port] = netdev; /* init hieth_local_driver */ ld = netdev_priv(netdev); memset(ld, 0, sizeof(*ld)); local_lock_init(ld); ld->iobase = (unsigned long)ioremap_nocache(CONFIG_HIETH_IOBASE, \ CONFIG_HIETH_IOSIZE); if (!ld->iobase) { hieth_error("ioremap_nocache err, base=0x%.8x, size=0x%.8x\n", CONFIG_HIETH_IOBASE, CONFIG_HIETH_IOSIZE); ret = -EFAULT; goto _error_ioremap_nocache; } ld->iobase_phys = CONFIG_HIETH_IOBASE; ld->port = port; ld->dev = &(pdev->dev); /* reset and init port */ hieth_port_reset(ld, ld->port); hieth_port_init(ld, ld->port); ld->depth.hw_xmitq = CONFIG_HIETH_HWQ_XMIT_DEPTH; memset(ld->phy_name, 0, sizeof(ld->phy_name)); snprintf(ld->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, \ HIETH_MIIBUS_NAME, UD_PHY_NAME(CONFIG_HIETH_PHYID)); ld->phy = phy_connect(netdev, ld->phy_name, hieth_adjust_link, 0, \ UD_BIT_NAME(CONFIG_HIETH_MII_RMII_MODE) ? \ PHY_INTERFACE_MODE_MII : PHY_INTERFACE_MODE_MII); if (IS_ERR(ld->phy)) { hieth_error("connect to phy_device %s failed!", ld->phy_name); ld->phy = NULL; goto _error_phy_connect; } skb_queue_head_init(&ld->rx_head); skb_queue_head_init(&ld->rx_hw); skb_queue_head_init(&ld->tx_hw); ld->tx_hw_cnt = 0; ret = hieth_init_skb_buffers(ld); if (ret) { hieth_error("hieth_init_skb_buffers failed!"); goto _error_init_skb_buffers; } ret = register_netdev(netdev); if (ret) { hieth_error("register_netdev %s failed!", netdev->name); goto _error_register_netdev; } return ret; _error_register_netdev: hieth_destroy_skb_buffers(ld); _error_init_skb_buffers: phy_disconnect(ld->phy); ld->phy = NULL; _error_phy_connect: iounmap((void *)ld->iobase); _error_ioremap_nocache: local_lock_exit(); hieth_devs_save[port] = NULL; free_netdev(netdev); _error_alloc_etherdev: _error_exit: return ret; }
static int hieth_net_open(struct net_device *dev) { struct hieth_netdev_local *ld = netdev_priv(dev); unsigned int data; unsigned long phy_id; try_module_get(THIS_MODULE); /* init tasklet */ ld->bf_recv.next = NULL; ld->bf_recv.state = 0; ld->bf_recv.func = hieth_bfproc_recv; ld->bf_recv.data = (unsigned long)dev; atomic_set(&ld->bf_recv.count, 0); /* setup hardware */ hieth_set_hwq_depth(ld); hieth_clear_irqstatus(ld, UD_BIT_NAME(BITS_IRQS_MASK)); netif_carrier_off(dev); hieth_feed_hw(ld); netif_start_queue(dev); ld->link_stat = 0; phy_start(ld->phy); hieth_irq_enable(ld, UD_BIT_NAME(HIETH_INT_MULTI_RXRDY)); hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, UD_BIT_NAME(BITS_IRQS_ENA)); hieth_writel_bits(ld, 1, GLB_RW_IRQ_ENA, BITS_IRQS_ENA_ALLPORT); init_timer(&ld->monitor); ld->monitor.function = hieth_monitor_func; ld->monitor.data = (unsigned long)dev; ld->monitor.expires = jiffies + msecs_to_jiffies(CONFIG_HIETH_MONITOR_TIMER); add_timer(&ld->monitor); data = readl(ld->iobase + 0x210); data |= 0x40000000; /* do CRC check in mac*/ writel(data, ld->iobase + 0x210); phy_id = phy_id_read(); #ifdef CONFIG_EEE_SUPPORT hiphyinfo = phy_search_ids(phy_id); if (hiphyinfo) { eee_available = hiphyinfo->with_eee; if (DEBUG) printk(KERN_INFO "fit_phy_id : %x, phy_name: %s," "eee :%x\n", (unsigned int)hiphyinfo->phy_id, hiphyinfo->name, (unsigned int)eee_available); ld->driver = hiphyinfo->driver; if (eee_available > NO_EEE) { data = 0x0; data_tmp = ld->driver->eee_enable(); if (eee_available == MAC_EEE) { /* init EEE timer */ /* 0x35 only for FPGA(54M)*/ writel(0x35, ld->iobase + 0x494); writel(0x1e03e8, ld->iobase + 0x48c); writel(0xf42400, ld->iobase + 0x488); data = readl(ld->iobase + 0x490); data |= 0x2; writel(data, ld->iobase + 0x490); /* enable EEE */ writel(0x10, ld->iobase + 0x484); if (DEBUG) printk(KERN_INFO "mac eee mode start " "to enable, eee :%x\n", eee_available); data = readl(ld->iobase + 0x488); data |= 0x1; /* mac-eee_enable */ writel(data, ld->iobase + 0x488); } } } else { printk(KERN_INFO "non-EEE mode\n"); eee_available = NO_EEE; } #endif return 0; }