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 } |