p@2550: /** p@2550: Network Driver for Beckhoff CCAT communication controller p@2550: Copyright (C) 2014 Beckhoff Automation GmbH p@2550: Author: Patrick Bruenn p@2550: p@2550: This program is free software; you can redistribute it and/or modify p@2550: it under the terms of the GNU General Public License as published by p@2550: the Free Software Foundation; either version 2 of the License, or p@2550: (at your option) any later version. p@2550: p@2550: This program is distributed in the hope that it will be useful, p@2550: but WITHOUT ANY WARRANTY; without even the implied warranty of p@2550: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the p@2550: GNU General Public License for more details. p@2550: p@2550: You should have received a copy of the GNU General Public License along p@2550: with this program; if not, write to the Free Software Foundation, Inc., p@2550: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. p@2550: */ p@2550: p@2550: #ifndef _CCAT_H_ p@2550: #define _CCAT_H_ p@2550: p@2550: #include p@2550: #include p@2550: #include p@2550: #include "CCatDefinitions.h" p@2550: #include "../ecdev.h" p@2550: p@2550: #define DRV_NAME "ec_ccat" p@2550: #define DRV_EXTRAVERSION "-ec" p@2550: #define DRV_VERSION "0.7" DRV_EXTRAVERSION p@2550: #define DRV_DESCRIPTION "Beckhoff CCAT Ethernet/EtherCAT Network Driver" p@2550: p@2551: #undef pr_fmt p@2551: #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt p@2551: p@2550: /** p@2550: * struct ccat_bar - CCAT PCI Base Address Register(BAR) configuration p@2550: * @start: start address of this BAR p@2550: * @end: end address of this BAR p@2550: * @len: length of this BAR p@2550: * @flags: flags set on this BAR p@2550: * @ioaddr: ioremapped address of this bar p@2550: */ p@2550: struct ccat_bar { p@2550: unsigned long start; p@2550: unsigned long end; p@2550: unsigned long len; p@2550: unsigned long flags; p@2550: void __iomem *ioaddr; p@2550: }; p@2550: p@2550: /** p@2550: * struct ccat_dma - CCAT DMA channel configuration p@2550: * @phys: device-viewed address(physical) of the associated DMA memory p@2550: * @virt: CPU-viewed address(virtual) of the associated DMA memory p@2550: * @size: number of bytes in the associated DMA memory p@2550: * @channel: CCAT DMA channel number p@2550: * @dev: valid struct device pointer p@2550: */ p@2550: struct ccat_dma { p@2550: dma_addr_t phys; p@2550: void *virt; p@2550: size_t size; p@2550: size_t channel; p@2550: struct device *dev; p@2550: }; p@2550: p@2550: extern void ccat_dma_free(struct ccat_dma *const dma); p@2550: extern int ccat_dma_init(struct ccat_dma *const dma, size_t channel, p@2550: void __iomem * const ioaddr, struct device *const dev); p@2550: p@2550: /** p@2550: * struct ccat_eth_frame - Ethernet frame with DMA descriptor header in front p@2550: * @reservedn: is not used and should always be set to 0 p@2550: * @received: used for reception, is set to 1 by the CCAT when data was written p@2550: * @length: number of bytes in the frame including the DMA header p@2550: * @sent: is set to 1 by the CCAT when data was transmitted p@2550: * @timestamp: a 64 bit EtherCAT timestamp p@2550: * @data: the bytes of the ethernet frame p@2550: */ p@2550: struct ccat_eth_frame { p@2550: uint32_t reserved1; p@2550: uint32_t received:1; p@2550: uint32_t reserved2:31; p@2550: uint16_t length; p@2550: uint16_t reserved3; p@2550: uint32_t sent:1; p@2550: uint32_t reserved4:31; p@2550: uint64_t timestamp; p@2550: uint8_t data[0x800 - 3 * sizeof(uint64_t)]; p@2550: }; p@2550: p@2550: /** p@2550: * struct ccat_eth_register - CCAT register addresses in the PCI BAR p@2550: * @mii: address of the CCAT management interface register p@2550: * @tx_fifo: address of the CCAT TX DMA fifo register p@2550: * @rx_fifo: address of the CCAT RX DMA fifo register p@2550: * @mac: address of the CCAT media access control register p@2550: * @rx_mem: address of the CCAT register holding the RX DMA address p@2550: * @tx_mem: address of the CCAT register holding the TX DMA address p@2550: * @misc: address of a CCAT register holding miscellaneous information p@2550: */ p@2550: struct ccat_eth_register { p@2550: void __iomem *mii; p@2550: void __iomem *tx_fifo; p@2550: void __iomem *rx_fifo; p@2550: void __iomem *mac; p@2550: void __iomem *rx_mem; p@2550: void __iomem *tx_mem; p@2550: void __iomem *misc; p@2550: }; p@2550: p@2550: /** p@2550: * struct ccat_eth_dma_fifo - CCAT RX or TX DMA fifo p@2550: * @add: callback used to add a frame to this fifo p@2550: * @reg: PCI register address of this DMA fifo p@2550: * @dma: information about the associated DMA memory p@2550: */ p@2550: struct ccat_eth_dma_fifo { p@2550: void (*add) (struct ccat_eth_frame *, struct ccat_eth_dma_fifo *); p@2550: void __iomem *reg; p@2550: struct ccat_dma dma; p@2550: }; p@2550: p@2550: /** p@2550: * struct ccat_device - CCAT device representation p@2550: * @pdev: pointer to the pci object allocated by the kernel p@2550: * @ethdev: CCAT Ethernet/EtherCAT Master (with DMA) function, NULL if function is not available or failed to initialize p@2550: * @update: CCAT Update function, NULL if function is not available or failed to initialize p@2550: * @bar [0] and [2] holding information about PCI BARs 0 and 2. p@2550: * p@2550: * One instance of a ccat_device should represent a physical CCAT. Since p@2550: * a CCAT is implemented as FPGA the available functions can vary so p@2550: * the function object pointers can be NULL. p@2550: * Extra note: you will recognize that PCI BAR1 is not used and is a p@2550: * waste of memory, thats true but right now, its very easy to use it p@2550: * this way. So we might optimize it later. p@2550: */ p@2550: struct ccat_device { p@2550: struct pci_dev *pdev; p@2550: struct ccat_eth_priv *ethdev; p@2550: struct ccat_update *update; p@2550: struct ccat_bar bar[3]; //TODO optimize this p@2550: }; p@2550: p@2550: /** p@2550: * struct ccat_eth_priv - CCAT Ethernet/EtherCAT Master function (netdev) p@2550: * @ccatdev: pointer to the parent struct ccat_device p@2550: * @netdev: the net_device structure used by the kernel networking stack p@2550: * @poll_thread: is used to poll status registers like link state p@2550: * @rx_thread: thread which does housekeeping of RX DMA descriptors p@2550: * @tx_thread: thread which does housekeeping of TX DMA descriptors p@2550: * @next_tx_frame: pointer to the next TX DMA descriptor, which the tx_thread should check for availablity p@2550: * @info: holds a copy of the CCAT Ethernet/EtherCAT Master function information block (read from PCI config space) p@2550: * @reg: register addresses in PCI config space of the Ethernet/EtherCAT Master function p@2550: * @rx_fifo: DMA fifo used for RX DMA descriptors p@2550: * @tx_fifo: DMA fifo used for TX DMA descriptors p@2550: * @rx_bytes: number of bytes received -> reported with ndo_get_stats64() p@2550: * @rx_dropped: number of received frames, which were dropped -> reported with ndo_get_stats64() p@2550: * @tx_bytes: number of bytes send -> reported with ndo_get_stats64() p@2550: * @tx_dropped: number of frames requested to send, which were dropped -> reported with ndo_get_stats64() p@2550: */ p@2550: struct ccat_eth_priv { p@2550: const struct ccat_device *ccatdev; p@2550: struct net_device *netdev; p@2550: struct task_struct *poll_thread; p@2550: struct task_struct *rx_thread; p@2550: struct task_struct *tx_thread; p@2550: const struct ccat_eth_frame *next_tx_frame; /* next frame the tx_thread should check for availability */ p@2550: CCatInfoBlock info; p@2550: struct ccat_eth_register reg; p@2550: struct ccat_eth_dma_fifo rx_fifo; p@2550: struct ccat_eth_dma_fifo tx_fifo; p@2550: atomic64_t rx_bytes; p@2550: atomic64_t rx_dropped; p@2550: atomic64_t tx_bytes; p@2550: atomic64_t tx_dropped; p@2550: ec_device_t *ecdev; p@2550: void (*carrier_off) (struct net_device * const netdev); p@2550: void (*carrier_on) (struct net_device * const netdev); p@2550: void (*kfree_skb_any) (struct sk_buff * skb); p@2550: void (*start_queue) (struct net_device * const netdev); p@2550: void (*stop_queue) (struct net_device * const netdev); p@2550: void (*tx_fifo_full) (struct net_device * const dev, p@2550: const struct ccat_eth_frame * const frame); p@2550: void (*unregister) (struct net_device * const netdev); p@2550: }; p@2550: p@2550: /** p@2550: * struct ccat_update - CCAT Update function (update) p@2550: * @ccatdev: pointer to the parent struct ccat_device p@2550: * @ioaddr: PCI base address of the CCAT Update function p@2550: * dev: device number for this update function p@2550: * cdev: character device used for the CCAT Update function p@2550: * class: pointer to a device class used when registering the CCAT Update device p@2550: * @info: holds a copy of the CCAT Update function information block (read from PCI config space) p@2550: */ p@2550: struct ccat_update { p@2550: struct kref refcount; p@2550: void __iomem *ioaddr; p@2550: dev_t dev; p@2550: struct cdev cdev; p@2550: struct class *class; p@2550: CCatInfoBlock info; p@2550: }; p@2550: #endif /* #ifndef _CCAT_H_ */