struct ccat_eth_priv *ccat_eth_init(const struct ccat_device *const ccatdev, const void __iomem * const addr) { struct ccat_eth_priv *priv; struct net_device *const netdev = alloc_etherdev(sizeof(*priv)); priv = netdev_priv(netdev); priv->netdev = netdev; priv->ccatdev = ccatdev; /* ccat register mappings */ memcpy_fromio(&priv->info, addr, sizeof(priv->info)); ccat_eth_priv_init_mappings(priv); if (ccat_eth_priv_init_dma(priv)) { pr_warn("%s(): DMA initialization failed.\n", __FUNCTION__); free_netdev(netdev); return NULL; } /* init netdev with MAC and stack callbacks */ memcpy_fromio(netdev->dev_addr, priv->reg.mii + 8, netdev->addr_len); netdev->netdev_ops = &ccat_eth_netdev_ops; /* use as EtherCAT device? */ priv->ecdev = ecdev_offer(netdev, ec_poll_rx, THIS_MODULE); if (priv->ecdev) { priv->carrier_off = ecdev_carrier_off; priv->carrier_ok = ecdev_carrier_ok; priv->carrier_on = ecdev_carrier_on; priv->kfree_skb_any = ecdev_kfree_skb_any; priv->start_queue = ecdev_nop; priv->stop_queue = ecdev_nop; priv->unregister = unregister_ecdev; priv->carrier_off(netdev); if (ecdev_open(priv->ecdev)) { pr_info("unable to register network device.\n"); ecdev_withdraw(priv->ecdev); ccat_eth_priv_free_dma(priv); free_netdev(netdev); return NULL; } return priv; } /* EtherCAT disabled -> prepare normal ethernet mode */ priv->carrier_off = netif_carrier_off; priv->carrier_ok = netif_carrier_ok; priv->carrier_on = netif_carrier_on; priv->kfree_skb_any = dev_kfree_skb_any; priv->start_queue = netif_start_queue; priv->stop_queue = netif_stop_queue; priv->unregister = unregister_netdev; priv->carrier_off(netdev); if (register_netdev(netdev)) { pr_info("unable to register network device.\n"); ccat_eth_priv_free_dma(priv); free_netdev(netdev); return NULL; } pr_info("registered %s as network device.\n", netdev->name); return priv; }
static int ccat_eth_init_netdev(struct ccat_eth_priv *priv) { int status; /* init netdev with MAC and stack callbacks */ memcpy_fromio(priv->netdev->dev_addr, priv->reg.mii + 8, priv->netdev->addr_len); priv->netdev->netdev_ops = &ccat_eth_netdev_ops; /* use as EtherCAT device? */ priv->carrier_off = ecdev_carrier_off; priv->carrier_ok = ecdev_carrier_ok; priv->carrier_on = ecdev_carrier_on; priv->kfree_skb_any = ecdev_kfree_skb_any; /* It would be more intuitive to check for: * if (priv->func->drv->type == CCATINFO_ETHERCAT_MASTER_DMA) { * unfortunately priv->func->drv is not initialized until probe() returns. * So we check if there is a rx dma fifo registered to determine dma/io mode */ if (&dma_rx_fifo_ops == priv->rx_fifo.ops) { priv->receive = ecdev_receive_dma; } else { priv->receive = ecdev_receive_eim; } priv->start_queue = ecdev_nop; priv->stop_queue = ecdev_nop; priv->unregister = unregister_ecdev; priv->ecdev = ecdev_offer(priv->netdev, ec_poll, THIS_MODULE); if (priv->ecdev) { priv->carrier_off(priv->netdev); if (ecdev_open(priv->ecdev)) { pr_info("unable to register network device.\n"); ecdev_withdraw(priv->ecdev); ccat_eth_priv_free(priv); free_netdev(priv->netdev); return -1; // TODO return better error code } priv->func->private_data = priv; return 0; } /* EtherCAT disabled -> prepare normal ethernet mode */ priv->carrier_off = netif_carrier_off; priv->carrier_ok = netif_carrier_ok; priv->carrier_on = netif_carrier_on; priv->kfree_skb_any = dev_kfree_skb_any; priv->receive = ccat_eth_receive; priv->start_queue = netif_start_queue; priv->stop_queue = netif_stop_queue; priv->unregister = unregister_netdev; priv->carrier_off(priv->netdev); status = register_netdev(priv->netdev); if (status) { pr_info("unable to register network device.\n"); ccat_eth_priv_free(priv); free_netdev(priv->netdev); return status; } pr_info("registered %s as network device.\n", priv->netdev->name); priv->func->private_data = priv; return 0; }