devices/ccat/netdev.c
branchstable-1.5
changeset 2569 720172a7563f
parent 2568 2f3078ec9ffb
child 2570 144e11d93e99
equal deleted inserted replaced
2568:2f3078ec9ffb 2569:720172a7563f
    26 #include <linux/spinlock.h>
    26 #include <linux/spinlock.h>
    27 
    27 
    28 #include "compat.h"
    28 #include "compat.h"
    29 #include "module.h"
    29 #include "module.h"
    30 #include "netdev.h"
    30 #include "netdev.h"
    31 #include "print.h"
       
    32 
    31 
    33 /**
    32 /**
    34  * EtherCAT frame to enable forwarding on EtherCAT Terminals
    33  * EtherCAT frame to enable forwarding on EtherCAT Terminals
    35  */
    34  */
    36 static const u8 frameForwardEthernetFrames[] = {
    35 static const u8 frameForwardEthernetFrames[] = {
   192  */
   191  */
   193 static int ccat_eth_priv_init_dma(struct ccat_eth_priv *priv)
   192 static int ccat_eth_priv_init_dma(struct ccat_eth_priv *priv)
   194 {
   193 {
   195 	if (ccat_eth_dma_fifo_init
   194 	if (ccat_eth_dma_fifo_init
   196 	    (&priv->rx_fifo, priv->reg.rx_fifo, ccat_eth_rx_fifo_add,
   195 	    (&priv->rx_fifo, priv->reg.rx_fifo, ccat_eth_rx_fifo_add,
   197 	     priv->info.rxDmaChn, priv)) {
   196 	     priv->info.rx_dma_chan, priv)) {
   198 		pr_warn("init Rx DMA fifo failed.\n");
   197 		pr_warn("init Rx DMA fifo failed.\n");
   199 		return -1;
   198 		return -1;
   200 	}
   199 	}
   201 
   200 
   202 	if (ccat_eth_dma_fifo_init
   201 	if (ccat_eth_dma_fifo_init
   203 	    (&priv->tx_fifo, priv->reg.tx_fifo, ccat_eth_tx_fifo_add_free,
   202 	    (&priv->tx_fifo, priv->reg.tx_fifo, ccat_eth_tx_fifo_add_free,
   204 	     priv->info.txDmaChn, priv)) {
   203 	     priv->info.tx_dma_chan, priv)) {
   205 		pr_warn("init Tx DMA fifo failed.\n");
   204 		pr_warn("init Tx DMA fifo failed.\n");
   206 		ccat_dma_free(&priv->rx_fifo.dma);
   205 		ccat_dma_free(&priv->rx_fifo.dma);
   207 		return -1;
   206 		return -1;
   208 	}
   207 	}
   209 
   208 
   217  * Initializes the CCat... members of the ccat_eth_priv structure.
   216  * Initializes the CCat... members of the ccat_eth_priv structure.
   218  * Call this function only if info and ioaddr are already initialized!
   217  * Call this function only if info and ioaddr are already initialized!
   219  */
   218  */
   220 static void ccat_eth_priv_init_mappings(struct ccat_eth_priv *priv)
   219 static void ccat_eth_priv_init_mappings(struct ccat_eth_priv *priv)
   221 {
   220 {
   222 	CCatInfoBlockOffs offsets;
   221 	struct ccat_mac_infoblock offsets;
   223 	void __iomem *const func_base =
   222 	void __iomem *const func_base =
   224 	    priv->ccatdev->bar[0].ioaddr + priv->info.nAddr;
   223 	    priv->ccatdev->bar[0].ioaddr + priv->info.addr;
   225 
   224 
   226 	memcpy_fromio(&offsets, func_base, sizeof(offsets));
   225 	memcpy_fromio(&offsets, func_base, sizeof(offsets));
   227 	priv->reg.mii = func_base + offsets.nMMIOffs;
   226 	priv->reg.mii = func_base + offsets.mii;
   228 	priv->reg.tx_fifo = func_base + offsets.nTxFifoOffs;
   227 	priv->reg.tx_fifo = func_base + offsets.tx_fifo;
   229 	priv->reg.rx_fifo = func_base + offsets.nTxFifoOffs + 0x10;
   228 	priv->reg.rx_fifo = func_base + offsets.tx_fifo + 0x10;
   230 	priv->reg.mac = func_base + offsets.nMacRegOffs;
   229 	priv->reg.mac = func_base + offsets.mac;
   231 	priv->reg.rx_mem = func_base + offsets.nRxMemOffs;
   230 	priv->reg.rx_mem = func_base + offsets.rx_mem;
   232 	priv->reg.tx_mem = func_base + offsets.nTxMemOffs;
   231 	priv->reg.tx_mem = func_base + offsets.tx_mem;
   233 	priv->reg.misc = func_base + offsets.nMiscOffs;
   232 	priv->reg.misc = func_base + offsets.misc;
   234 }
   233 }
   235 
   234 
   236 /**
   235 /**
   237  * Read link state from CCAT hardware
   236  * Read link state from CCAT hardware
   238  * @return 1 if link is up, 0 if not
   237  * @return 1 if link is up, 0 if not
   246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
   245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
   247 static struct rtnl_link_stats64 *ccat_eth_get_stats64(struct net_device *dev, struct rtnl_link_stats64
   246 static struct rtnl_link_stats64 *ccat_eth_get_stats64(struct net_device *dev, struct rtnl_link_stats64
   248 						      *storage)
   247 						      *storage)
   249 {
   248 {
   250 	struct ccat_eth_priv *const priv = netdev_priv(dev);
   249 	struct ccat_eth_priv *const priv = netdev_priv(dev);
   251 	CCatMacRegs mac;
   250 	struct ccat_mac_register mac;
   252 
   251 
   253 	memcpy_fromio(&mac, priv->reg.mac, sizeof(mac));
   252 	memcpy_fromio(&mac, priv->reg.mac, sizeof(mac));
   254 	storage->rx_packets = mac.rxFrameCnt;	/* total packets received       */
   253 	storage->rx_packets = mac.rx_frames;	/* total packets received       */
   255 	storage->tx_packets = mac.txFrameCnt;	/* total packets transmitted    */
   254 	storage->tx_packets = mac.tx_frames;	/* total packets transmitted    */
   256 	storage->rx_bytes = atomic64_read(&priv->rx_bytes);	/* total bytes received         */
   255 	storage->rx_bytes = atomic64_read(&priv->rx_bytes);	/* total bytes received         */
   257 	storage->tx_bytes = atomic64_read(&priv->tx_bytes);	/* total bytes transmitted      */
   256 	storage->tx_bytes = atomic64_read(&priv->tx_bytes);	/* total bytes transmitted      */
   258 	storage->rx_errors = mac.frameLenErrCnt + mac.dropFrameErrCnt + mac.crcErrCnt + mac.rxErrCnt;	/* bad packets received         */
   257 	storage->rx_errors = mac.frame_len_err + mac.rx_mem_full + mac.crc_err + mac.rx_err;	/* bad packets received         */
   259 	//TODO __u64    tx_errors;              /* packet transmit problems     */
   258 	storage->tx_errors = mac.tx_mem_full; /* packet transmit problems     */
   260 	storage->rx_dropped = atomic64_read(&priv->rx_dropped);	/* no space in linux buffers    */
   259 	storage->rx_dropped = atomic64_read(&priv->rx_dropped);	/* no space in linux buffers    */
   261 	storage->tx_dropped = atomic64_read(&priv->tx_dropped);	/* no space available in linux  */
   260 	storage->tx_dropped = atomic64_read(&priv->tx_dropped);	/* no space available in linux  */
   262 	//TODO __u64    multicast;              /* multicast packets received   */
   261 	//TODO __u64    multicast;              /* multicast packets received   */
   263 	//TODO __u64    collisions;
   262 	//TODO __u64    collisions;
   264 
   263 
   265 	/* detailed rx_errors: */
   264 	/* detailed rx_errors: */
   266 	storage->rx_length_errors = mac.frameLenErrCnt;
   265 	storage->rx_length_errors = mac.frame_len_err;
   267 	storage->rx_over_errors = mac.dropFrameErrCnt;	/* receiver ring buff overflow  */
   266 	storage->rx_over_errors = mac.rx_mem_full;	/* receiver ring buff overflow  */
   268 	storage->rx_crc_errors = mac.crcErrCnt;	/* recved pkt with crc error    */
   267 	storage->rx_crc_errors = mac.crc_err;	/* recved pkt with crc error    */
   269 	storage->rx_frame_errors = mac.rxErrCnt;	/* recv'd frame alignment error */
   268 	storage->rx_frame_errors = mac.rx_err;	/* recv'd frame alignment error */
   270 	storage->rx_fifo_errors = mac.dropFrameErrCnt;	/* recv'r fifo overrun          */
   269 	storage->rx_fifo_errors = mac.rx_mem_full;	/* recv'r fifo overrun          */
   271 	//TODO __u64    rx_missed_errors;       /* receiver missed packet       */
   270 	//TODO __u64    rx_missed_errors;       /* receiver missed packet       */
   272 
   271 
   273 	/* detailed tx_errors */
   272 	/* detailed tx_errors */
   274 	//TODO __u64    tx_aborted_errors;
   273 	//TODO __u64    tx_aborted_errors;
   275 	//TODO __u64    tx_carrier_errors;
   274 	//TODO __u64    tx_carrier_errors;
   295 	priv->ccatdev = ccatdev;
   294 	priv->ccatdev = ccatdev;
   296 
   295 
   297 	/* ccat register mappings */
   296 	/* ccat register mappings */
   298 	memcpy_fromio(&priv->info, addr, sizeof(priv->info));
   297 	memcpy_fromio(&priv->info, addr, sizeof(priv->info));
   299 	ccat_eth_priv_init_mappings(priv);
   298 	ccat_eth_priv_init_mappings(priv);
   300 	ccat_print_function_info(priv);
   299 	/* XXX disabled in release
       
   300 	 * ccat_print_function_info(priv);
       
   301 	 */
   301 
   302 
   302 	if (ccat_eth_priv_init_dma(priv)) {
   303 	if (ccat_eth_priv_init_dma(priv)) {
   303 		pr_warn("%s(): DMA initialization failed.\n", __FUNCTION__);
   304 		pr_warn("%s(): DMA initialization failed.\n", __FUNCTION__);
   304 		free_netdev(netdev);
   305 		free_netdev(netdev);
   305 		return NULL;
   306 		return NULL;
   306 	}
   307 	}
   307 
   308 
   308 	/* init netdev with MAC and stack callbacks */
   309 	/* init netdev with MAC and stack callbacks */
   309 	memcpy_fromio(netdev->dev_addr, priv->reg.mii + 8, 6);
   310 	memcpy_fromio(netdev->dev_addr, priv->reg.mii + 8, netdev->addr_len);
   310 	netdev->netdev_ops = &ccat_eth_netdev_ops;
   311 	netdev->netdev_ops = &ccat_eth_netdev_ops;
   311 
   312 
   312 	/* use as EtherCAT device? */
   313 	/* use as EtherCAT device? */
   313 	priv->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
   314 	priv->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
   314 	if (priv->ecdev) {
   315 	if (priv->ecdev) {
   453 
   454 
   454 	priv->kfree_skb_any(skb);
   455 	priv->kfree_skb_any(skb);
   455 
   456 
   456 	addr_and_length = 8 + (next * sizeof(*frame));
   457 	addr_and_length = 8 + (next * sizeof(*frame));
   457 	addr_and_length +=
   458 	addr_and_length +=
   458 	    ((frame[next].length + CCAT_DMA_FRAME_HEADER_LENGTH) / 8) << 24;
   459 	    ((frame[next].length + CCAT_ETH_FRAME_HEAD_LEN) / 8) << 24;
   459 	iowrite32(addr_and_length, priv->reg.tx_fifo);	/* add to DMA fifo */
   460 	iowrite32(addr_and_length, priv->reg.tx_fifo);	/* add to DMA fifo */
   460 	atomic64_add(frame[next].length, &priv->tx_bytes);	/* update stats */
   461 	atomic64_add(frame[next].length, &priv->tx_bytes);	/* update stats */
   461 
   462 
   462 	next = (next + 1) % FIFO_LENGTH;
   463 	next = (next + 1) % FIFO_LENGTH;
   463 	/* stop queue if tx ring is full */
   464 	/* stop queue if tx ring is full */
   495 	   speed == SPEED_100 ? 100 : 10,
   496 	   speed == SPEED_100 ? 100 : 10,
   496 	   cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); */
   497 	   cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); */
   497 
   498 
   498 	ccat_eth_dma_fifo_reset(&priv->rx_fifo);
   499 	ccat_eth_dma_fifo_reset(&priv->rx_fifo);
   499 	ccat_eth_dma_fifo_reset(&priv->tx_fifo);
   500 	ccat_eth_dma_fifo_reset(&priv->tx_fifo);
       
   501 
       
   502 	/* TODO reset CCAT MAC register */
       
   503 
   500 	ccat_eth_xmit_raw(dev, frameForwardEthernetFrames,
   504 	ccat_eth_xmit_raw(dev, frameForwardEthernetFrames,
   501 			  sizeof(frameForwardEthernetFrames));
   505 			  sizeof(frameForwardEthernetFrames));
   502 	priv->carrier_on(dev);
   506 	priv->carrier_on(dev);
   503 	priv->start_queue(dev);
   507 	priv->start_queue(dev);
   504 }
   508 }