fp@2589: /** fp@2589: Network Driver for Beckhoff CCAT communication controller fp@2589: Copyright (C) 2014 Beckhoff Automation GmbH fp@2589: Author: Patrick Bruenn fp@2589: fp@2589: This program is free software; you can redistribute it and/or modify fp@2589: it under the terms of the GNU General Public License as published by fp@2589: the Free Software Foundation; either version 2 of the License, or fp@2589: (at your option) any later version. fp@2589: fp@2589: This program is distributed in the hope that it will be useful, fp@2589: but WITHOUT ANY WARRANTY; without even the implied warranty of fp@2589: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@2589: GNU General Public License for more details. fp@2589: fp@2589: You should have received a copy of the GNU General Public License along fp@2589: with this program; if not, write to the Free Software Foundation, Inc., fp@2589: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. fp@2589: */ fp@2589: fp@2589: #ifndef _CCAT_H_ fp@2589: #define _CCAT_H_ fp@2589: fp@2589: #include fp@2589: #include fp@2589: #include fp@2589: #include fp@2589: #include "../ecdev.h" fp@2589: fp@2589: #define DRV_EXTRAVERSION "-ec" fp@2589: #define DRV_VERSION "0.10" DRV_EXTRAVERSION fp@2589: #define DRV_DESCRIPTION "Beckhoff CCAT Ethernet/EtherCAT Network Driver" fp@2589: fp@2589: #undef pr_fmt fp@2589: #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt fp@2589: fp@2589: /** fp@2589: * CCAT function type identifiers (u16) fp@2589: */ fp@2589: enum ccat_info_t { fp@2589: CCATINFO_NOTUSED = 0, fp@2589: CCATINFO_EPCS_PROM = 0xf, fp@2589: CCATINFO_ETHERCAT_MASTER_DMA = 0x14, fp@2589: CCATINFO_COPY_BLOCK = 0x17, fp@2589: CCATINFO_MAX fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_bar - CCAT PCI Base Address Register(BAR) configuration fp@2589: * @start: start address of this BAR fp@2589: * @end: end address of this BAR fp@2589: * @len: length of this BAR fp@2589: * @flags: flags set on this BAR fp@2589: * @ioaddr: ioremapped address of this bar fp@2589: */ fp@2589: struct ccat_bar { fp@2589: unsigned long start; fp@2589: unsigned long end; fp@2589: unsigned long len; fp@2589: unsigned long flags; fp@2589: void __iomem *ioaddr; fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_dma - CCAT DMA channel configuration fp@2589: * @phys: device-viewed address(physical) of the associated DMA memory fp@2589: * @virt: CPU-viewed address(virtual) of the associated DMA memory fp@2589: * @size: number of bytes in the associated DMA memory fp@2589: * @channel: CCAT DMA channel number fp@2589: * @dev: valid struct device pointer fp@2589: */ fp@2589: struct ccat_dma { fp@2589: dma_addr_t phys; fp@2589: void *virt; fp@2589: size_t size; fp@2589: size_t channel; fp@2589: struct device *dev; fp@2589: }; fp@2589: fp@2589: extern void ccat_dma_free(struct ccat_dma *const dma); fp@2589: extern int ccat_dma_init(struct ccat_dma *const dma, size_t channel, fp@2589: void __iomem * const ioaddr, struct device *const dev); fp@2589: fp@2589: /** fp@2589: * struct ccat_eth_frame - Ethernet frame with DMA descriptor header in front fp@2589: * @reservedn: is not used and should always be set to 0 fp@2589: * @received: used for reception, is set to 1 by the CCAT when data was written fp@2589: * @length: number of bytes in the frame including the DMA header fp@2589: * @sent: is set to 1 by the CCAT when data was transmitted fp@2589: * @timestamp: a 64 bit EtherCAT timestamp fp@2589: * @data: the bytes of the ethernet frame fp@2589: */ fp@2589: struct ccat_eth_frame { fp@2589: __le32 reserved1; fp@2589: __le32 rx_flags; fp@2589: #define CCAT_FRAME_RECEIVED 0x1 fp@2589: __le16 length; fp@2589: __le16 reserved3; fp@2589: __le32 tx_flags; fp@2589: #define CCAT_FRAME_SENT 0x1 fp@2589: __le64 timestamp; fp@2589: u8 data[0x800 - 3 * sizeof(u64)]; fp@2589: #define CCAT_ETH_FRAME_HEAD_LEN offsetof(struct ccat_eth_frame, data) fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_eth_register - CCAT register addresses in the PCI BAR fp@2589: * @mii: address of the CCAT management interface register fp@2589: * @tx_fifo: address of the CCAT TX DMA fifo register fp@2589: * @rx_fifo: address of the CCAT RX DMA fifo register fp@2589: * @mac: address of the CCAT media access control register fp@2589: * @rx_mem: address of the CCAT register holding the RX DMA address fp@2589: * @tx_mem: address of the CCAT register holding the TX DMA address fp@2589: * @misc: address of a CCAT register holding miscellaneous information fp@2589: */ fp@2589: struct ccat_eth_register { fp@2589: void __iomem *mii; fp@2589: void __iomem *tx_fifo; fp@2589: void __iomem *rx_fifo; fp@2589: void __iomem *mac; fp@2589: void __iomem *rx_mem; fp@2589: void __iomem *tx_mem; fp@2589: void __iomem *misc; fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_eth_dma_fifo - CCAT RX or TX DMA fifo fp@2589: * @add: callback used to add a frame to this fifo fp@2589: * @reg: PCI register address of this DMA fifo fp@2589: * @dma: information about the associated DMA memory fp@2589: */ fp@2589: struct ccat_eth_dma_fifo { fp@2589: void (*add) (struct ccat_eth_dma_fifo *, struct ccat_eth_frame *); fp@2589: void __iomem *reg; fp@2589: const struct ccat_eth_frame *end; fp@2589: struct ccat_eth_frame *next; fp@2589: struct ccat_dma dma; fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_device - CCAT device representation fp@2589: * @pdev: pointer to the pci object allocated by the kernel fp@2589: * @ethdev: CCAT Ethernet/EtherCAT Master (with DMA) function, NULL if function is not available or failed to initialize fp@2589: * @update: CCAT Update function, NULL if function is not available or failed to initialize fp@2589: * @bar [0] and [2] holding information about PCI BARs 0 and 2. fp@2589: * fp@2589: * One instance of a ccat_device should represent a physical CCAT. Since fp@2589: * a CCAT is implemented as FPGA the available functions can vary so fp@2589: * the function object pointers can be NULL. fp@2589: * Extra note: you will recognize that PCI BAR1 is not used and is a fp@2589: * waste of memory, thats true but right now, its very easy to use it fp@2589: * this way. So we might optimize it later. fp@2589: */ fp@2589: struct ccat_device { fp@2589: struct pci_dev *pdev; fp@2589: struct ccat_eth_priv *ethdev; fp@2589: struct ccat_update *update; fp@2589: struct ccat_bar bar[3]; //TODO optimize this fp@2589: }; fp@2589: fp@2589: struct ccat_info_block { fp@2589: u16 type; fp@2589: u16 rev; fp@2589: union { fp@2589: u32 config; fp@2589: struct { fp@2589: u8 tx_dma_chan; fp@2589: u8 rx_dma_chan; fp@2589: }; fp@2589: }; fp@2589: u32 addr; fp@2589: u32 size; fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_eth_priv - CCAT Ethernet/EtherCAT Master function (netdev) fp@2589: * @ccatdev: pointer to the parent struct ccat_device fp@2589: * @netdev: the net_device structure used by the kernel networking stack fp@2589: * @info: holds a copy of the CCAT Ethernet/EtherCAT Master function information block (read from PCI config space) fp@2589: * @reg: register addresses in PCI config space of the Ethernet/EtherCAT Master function fp@2589: * @rx_fifo: DMA fifo used for RX DMA descriptors fp@2589: * @tx_fifo: DMA fifo used for TX DMA descriptors fp@2589: * @poll_timer: interval timer used to poll CCAT for events like link changed, rx done, tx done fp@2589: * @rx_bytes: number of bytes received -> reported with ndo_get_stats64() fp@2589: * @rx_dropped: number of received frames, which were dropped -> reported with ndo_get_stats64() fp@2589: * @tx_bytes: number of bytes send -> reported with ndo_get_stats64() fp@2589: * @tx_dropped: number of frames requested to send, which were dropped -> reported with ndo_get_stats64() fp@2589: */ fp@2589: struct ccat_eth_priv { fp@2589: const struct ccat_device *ccatdev; fp@2589: struct net_device *netdev; fp@2589: struct ccat_info_block info; fp@2589: struct ccat_eth_register reg; fp@2589: struct ccat_eth_dma_fifo rx_fifo; fp@2589: struct ccat_eth_dma_fifo tx_fifo; fp@2589: struct hrtimer poll_timer; fp@2589: atomic64_t rx_bytes; fp@2589: atomic64_t rx_dropped; fp@2589: atomic64_t tx_bytes; fp@2589: atomic64_t tx_dropped; fp@2589: ec_device_t *ecdev; fp@2589: void (*carrier_off) (struct net_device * netdev); fp@2589: bool (*carrier_ok) (const struct net_device * netdev); fp@2589: void (*carrier_on) (struct net_device * netdev); fp@2589: void (*kfree_skb_any) (struct sk_buff * skb); fp@2589: void (*start_queue) (struct net_device * netdev); fp@2589: void (*stop_queue) (struct net_device * netdev); fp@2589: void (*unregister) (struct net_device * netdev); fp@2589: }; fp@2589: fp@2589: /** fp@2589: * same as: typedef struct _CCatInfoBlockOffs from CCatDefinitions.h fp@2589: * TODO add some checking facility outside of the linux tree fp@2589: */ fp@2589: struct ccat_mac_infoblock { fp@2589: u32 reserved; fp@2589: u32 mii; fp@2589: u32 tx_fifo; fp@2589: u32 mac; fp@2589: u32 rx_mem; fp@2589: u32 tx_mem; fp@2589: u32 misc; fp@2589: }; fp@2589: fp@2589: struct ccat_mac_register { fp@2589: /** MAC error register @+0x0 */ fp@2589: u8 frame_len_err; fp@2589: u8 rx_err; fp@2589: u8 crc_err; fp@2589: u8 link_lost_err; fp@2589: u32 reserved1; fp@2589: /** Buffer overflow errors @+0x8 */ fp@2589: u8 rx_mem_full; fp@2589: u8 reserved2[7]; fp@2589: /** MAC frame counter @+0x10 */ fp@2589: u32 tx_frames; fp@2589: u32 rx_frames; fp@2589: u64 reserved3; fp@2589: /** MAC fifo level @+0x20 */ fp@2589: u8 tx_fifo_level:7; fp@2589: u8 reserved4:1; fp@2589: u8 reserved5[7]; fp@2589: /** TX memory full error @+0x28 */ fp@2589: u8 tx_mem_full; fp@2589: u8 reserved6[7]; fp@2589: u64 reserved8[9]; fp@2589: /** Connection @+0x78 */ fp@2589: u8 mii_connected; fp@2589: }; fp@2589: fp@2589: /** fp@2589: * struct ccat_update - CCAT Update function (update) fp@2589: * @ccatdev: pointer to the parent struct ccat_device fp@2589: * @ioaddr: PCI base address of the CCAT Update function fp@2589: * dev: device number for this update function fp@2589: * cdev: character device used for the CCAT Update function fp@2589: * class: pointer to a device class used when registering the CCAT Update device fp@2589: * @info: holds a copy of the CCAT Update function information block (read from PCI config space) fp@2589: */ fp@2589: struct ccat_update { fp@2589: struct kref refcount; fp@2589: void __iomem *ioaddr; fp@2589: dev_t dev; fp@2589: struct cdev cdev; fp@2589: struct class *class; fp@2589: struct ccat_info_block info; fp@2589: }; fp@2589: #endif /* #ifndef _CCAT_H_ */