source: rtems/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c @ f97536d

5
Last change on this file since f97536d was f97536d, checked in by Sebastian Huber <sebastian.huber@…>, on 10/16/15 at 06:21:48

basdefs.h: Add and use RTEMS_UNUSED

  • Property mode set to 100644
File size: 46.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc_eth
5 *
6 * @brief Ethernet driver.
7 */
8
9/*
10 * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1
24#define __BSD_VISIBLE 1
25
26#include <errno.h>
27#include <inttypes.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include <assert.h>
32
33#include <rtems.h>
34#include <rtems/rtems_bsdnet.h>
35#include <rtems/rtems_mii_ioctl.h>
36
37#include <sys/param.h>
38#include <sys/socket.h>
39#include <sys/sockio.h>
40#include <sys/mbuf.h>
41
42#include <net/if.h>
43#include <net/if_arp.h>
44#include <netinet/in.h>
45#include <netinet/if_ether.h>
46#include <netinet/in_systm.h>
47#include <netinet/ip.h>
48
49#include <bsp.h>
50#include <bsp/irq.h>
51#include <bsp/lpc-ethernet-config.h>
52#include <bsp/utility.h>
53
54#if MCLBYTES > (2 * 1024)
55  #error "MCLBYTES to large"
56#endif
57
58#ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
59  #define LPC_ETH_CONFIG_TX_BUF_SIZE sizeof(struct mbuf *)
60#else
61  #define LPC_ETH_CONFIG_TX_BUF_SIZE 1518U
62#endif
63
64#define DEFAULT_PHY 0
65#define WATCHDOG_TIMEOUT 5
66
67typedef struct {
68  uint32_t start;
69  uint32_t control;
70} lpc_eth_transfer_descriptor;
71
72typedef struct {
73  uint32_t info;
74  uint32_t hash_crc;
75} lpc_eth_receive_status;
76
77typedef struct {
78  uint32_t mac1;
79  uint32_t mac2;
80  uint32_t ipgt;
81  uint32_t ipgr;
82  uint32_t clrt;
83  uint32_t maxf;
84  uint32_t supp;
85  uint32_t test;
86  uint32_t mcfg;
87  uint32_t mcmd;
88  uint32_t madr;
89  uint32_t mwtd;
90  uint32_t mrdd;
91  uint32_t mind;
92  uint32_t reserved_0 [2];
93  uint32_t sa0;
94  uint32_t sa1;
95  uint32_t sa2;
96  uint32_t reserved_1 [45];
97  uint32_t command;
98  uint32_t status;
99  uint32_t rxdescriptor;
100  uint32_t rxstatus;
101  uint32_t rxdescriptornum;
102  uint32_t rxproduceindex;
103  uint32_t rxconsumeindex;
104  uint32_t txdescriptor;
105  uint32_t txstatus;
106  uint32_t txdescriptornum;
107  uint32_t txproduceindex;
108  uint32_t txconsumeindex;
109  uint32_t reserved_2 [10];
110  uint32_t tsv0;
111  uint32_t tsv1;
112  uint32_t rsv;
113  uint32_t reserved_3 [3];
114  uint32_t flowcontrolcnt;
115  uint32_t flowcontrolsts;
116  uint32_t reserved_4 [34];
117  uint32_t rxfilterctrl;
118  uint32_t rxfilterwolsts;
119  uint32_t rxfilterwolclr;
120  uint32_t reserved_5 [1];
121  uint32_t hashfilterl;
122  uint32_t hashfilterh;
123  uint32_t reserved_6 [882];
124  uint32_t intstatus;
125  uint32_t intenable;
126  uint32_t intclear;
127  uint32_t intset;
128  uint32_t reserved_7 [1];
129  uint32_t powerdown;
130} lpc_eth_controller;
131
132static volatile lpc_eth_controller *const lpc_eth =
133  (volatile lpc_eth_controller *) LPC_ETH_CONFIG_REG_BASE;
134
135/* ETH_RX_CTRL */
136
137#define ETH_RX_CTRL_SIZE_MASK 0x000007ffU
138#define ETH_RX_CTRL_INTERRUPT 0x80000000U
139
140/* ETH_RX_STAT */
141
142#define ETH_RX_STAT_RXSIZE_MASK 0x000007ffU
143#define ETH_RX_STAT_BYTES 0x00000100U
144#define ETH_RX_STAT_CONTROL_FRAME 0x00040000U
145#define ETH_RX_STAT_VLAN 0x00080000U
146#define ETH_RX_STAT_FAIL_FILTER 0x00100000U
147#define ETH_RX_STAT_MULTICAST 0x00200000U
148#define ETH_RX_STAT_BROADCAST 0x00400000U
149#define ETH_RX_STAT_CRC_ERROR 0x00800000U
150#define ETH_RX_STAT_SYMBOL_ERROR 0x01000000U
151#define ETH_RX_STAT_LENGTH_ERROR 0x02000000U
152#define ETH_RX_STAT_RANGE_ERROR 0x04000000U
153#define ETH_RX_STAT_ALIGNMENT_ERROR 0x08000000U
154#define ETH_RX_STAT_OVERRUN 0x10000000U
155#define ETH_RX_STAT_NO_DESCRIPTOR 0x20000000U
156#define ETH_RX_STAT_LAST_FLAG 0x40000000U
157#define ETH_RX_STAT_ERROR 0x80000000U
158
159/* ETH_TX_CTRL */
160
161#define ETH_TX_CTRL_SIZE_MASK 0x7ffU
162#define ETH_TX_CTRL_SIZE_SHIFT 0
163#define ETH_TX_CTRL_OVERRIDE 0x04000000U
164#define ETH_TX_CTRL_HUGE 0x08000000U
165#define ETH_TX_CTRL_PAD 0x10000000U
166#define ETH_TX_CTRL_CRC 0x20000000U
167#define ETH_TX_CTRL_LAST 0x40000000U
168#define ETH_TX_CTRL_INTERRUPT 0x80000000U
169
170/* ETH_TX_STAT */
171
172#define ETH_TX_STAT_COLLISION_COUNT_MASK 0x01e00000U
173#define ETH_TX_STAT_DEFER 0x02000000U
174#define ETH_TX_STAT_EXCESSIVE_DEFER 0x04000000U
175#define ETH_TX_STAT_EXCESSIVE_COLLISION 0x08000000U
176#define ETH_TX_STAT_LATE_COLLISION 0x10000000U
177#define ETH_TX_STAT_UNDERRUN 0x20000000U
178#define ETH_TX_STAT_NO_DESCRIPTOR 0x40000000U
179#define ETH_TX_STAT_ERROR 0x80000000U
180
181/* ETH_INT */
182
183#define ETH_INT_RX_OVERRUN 0x00000001U
184#define ETH_INT_RX_ERROR 0x00000002U
185#define ETH_INT_RX_FINISHED 0x00000004U
186#define ETH_INT_RX_DONE 0x00000008U
187#define ETH_INT_TX_UNDERRUN 0x00000010U
188#define ETH_INT_TX_ERROR 0x00000020U
189#define ETH_INT_TX_FINISHED 0x00000040U
190#define ETH_INT_TX_DONE 0x00000080U
191#define ETH_INT_SOFT 0x00001000U
192#define ETH_INT_WAKEUP 0x00002000U
193
194/* ETH_RX_FIL_CTRL */
195
196#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST 0x00000001U
197#define ETH_RX_FIL_CTRL_ACCEPT_BROADCAST 0x00000002U
198#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST 0x00000004U
199#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST_HASH 0x00000008U
200#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST_HASH 0x00000010U
201#define ETH_RX_FIL_CTRL_ACCEPT_PERFECT 0x00000020U
202#define ETH_RX_FIL_CTRL_MAGIC_PACKET_WOL 0x00001000U
203#define ETH_RX_FIL_CTRL_RX_FILTER_WOL 0x00002000U
204
205/* ETH_CMD */
206
207#define ETH_CMD_RX_ENABLE 0x00000001U
208#define ETH_CMD_TX_ENABLE 0x00000002U
209#define ETH_CMD_REG_RESET 0x00000008U
210#define ETH_CMD_TX_RESET 0x00000010U
211#define ETH_CMD_RX_RESET 0x00000020U
212#define ETH_CMD_PASS_RUNT_FRAME 0x00000040U
213#define ETH_CMD_PASS_RX_FILTER 0X00000080U
214#define ETH_CMD_TX_FLOW_CONTROL 0x00000100U
215#define ETH_CMD_RMII 0x00000200U
216#define ETH_CMD_FULL_DUPLEX 0x00000400U
217
218/* ETH_STAT */
219
220#define ETH_STAT_RX_ACTIVE 0x00000001U
221#define ETH_STAT_TX_ACTIVE 0x00000002U
222
223/* ETH_MAC2 */
224
225#define ETH_MAC2_FULL_DUPLEX BSP_BIT32(8)
226
227/* ETH_SUPP */
228
229#define ETH_SUPP_SPEED BSP_BIT32(8)
230
231/* ETH_MCFG */
232
233#define ETH_MCFG_CLOCK_SELECT(val) BSP_FLD32(val, 2, 4)
234
235#define ETH_MCFG_RESETMIIMGMT BSP_BIT32(15)
236
237/* ETH_MCMD */
238
239#define ETH_MCMD_READ BSP_BIT32(0)
240#define ETH_MCMD_SCAN BSP_BIT32(1)
241
242/* ETH_MADR */
243
244#define ETH_MADR_REG(val) BSP_FLD32(val, 0, 4)
245#define ETH_MADR_PHY(val) BSP_FLD32(val, 8, 12)
246
247/* ETH_MIND */
248
249#define ETH_MIND_BUSY BSP_BIT32(0)
250#define ETH_MIND_SCANNING BSP_BIT32(1)
251#define ETH_MIND_NOT_VALID BSP_BIT32(2)
252#define ETH_MIND_MII_LINK_FAIL BSP_BIT32(3)
253
254/* Events */
255
256#define LPC_ETH_EVENT_INITIALIZE RTEMS_EVENT_1
257
258#define LPC_ETH_EVENT_TXSTART RTEMS_EVENT_2
259
260#define LPC_ETH_EVENT_INTERRUPT RTEMS_EVENT_3
261
262#define LPC_ETH_EVENT_STOP RTEMS_EVENT_4
263
264/* Status */
265
266#define LPC_ETH_INTERRUPT_RECEIVE \
267  (ETH_INT_RX_ERROR | ETH_INT_RX_FINISHED | ETH_INT_RX_DONE)
268
269#define LPC_ETH_INTERRUPT_TRANSMIT \
270  (ETH_INT_TX_DONE | ETH_INT_TX_FINISHED | ETH_INT_TX_ERROR)
271
272#define LPC_ETH_RX_STAT_ERRORS \
273  (ETH_RX_STAT_CRC_ERROR \
274    | ETH_RX_STAT_SYMBOL_ERROR \
275    | ETH_RX_STAT_LENGTH_ERROR \
276    | ETH_RX_STAT_ALIGNMENT_ERROR \
277    | ETH_RX_STAT_OVERRUN \
278    | ETH_RX_STAT_NO_DESCRIPTOR)
279
280#define LPC_ETH_LAST_FRAGMENT_FLAGS \
281  (ETH_TX_CTRL_OVERRIDE \
282    | ETH_TX_CTRL_PAD \
283    | ETH_TX_CTRL_CRC \
284    | ETH_TX_CTRL_INTERRUPT \
285    | ETH_TX_CTRL_LAST)
286
287/* Debug */
288
289#ifdef DEBUG
290  #define LPC_ETH_PRINTF(...) printf(__VA_ARGS__)
291  #define LPC_ETH_PRINTK(...) printk(__VA_ARGS__)
292#else
293  #define LPC_ETH_PRINTF(...)
294  #define LPC_ETH_PRINTK(...)
295#endif
296
297typedef enum {
298  LPC_ETH_STATE_NOT_INITIALIZED = 0,
299  LPC_ETH_STATE_DOWN,
300  LPC_ETH_STATE_UP
301} lpc_eth_state;
302
303typedef struct {
304  struct arpcom arpcom;
305  lpc_eth_state state;
306  struct rtems_mdio_info mdio;
307  uint32_t anlpar;
308  rtems_id receive_task;
309  rtems_id transmit_task;
310  unsigned rx_unit_count;
311  unsigned tx_unit_count;
312  volatile lpc_eth_transfer_descriptor *rx_desc_table;
313  volatile lpc_eth_receive_status *rx_status_table;
314  struct mbuf **rx_mbuf_table;
315  volatile lpc_eth_transfer_descriptor *tx_desc_table;
316  volatile uint32_t *tx_status_table;
317  void *tx_buf_table;
318  unsigned received_frames;
319  unsigned receive_interrupts;
320  unsigned transmitted_frames;
321  unsigned transmit_interrupts;
322  unsigned receive_drop_errors;
323  unsigned receive_overrun_errors;
324  unsigned receive_fragment_errors;
325  unsigned receive_crc_errors;
326  unsigned receive_symbol_errors;
327  unsigned receive_length_errors;
328  unsigned receive_alignment_errors;
329  unsigned receive_no_descriptor_errors;
330  unsigned receive_fatal_errors;
331  unsigned transmit_underrun_errors;
332  unsigned transmit_late_collision_errors;
333  unsigned transmit_excessive_collision_errors;
334  unsigned transmit_excessive_defer_errors;
335  unsigned transmit_no_descriptor_errors;
336  unsigned transmit_overflow_errors;
337  unsigned transmit_fatal_errors;
338  uint32_t phy_id;
339  int phy;
340  rtems_vector_number interrupt_number;
341  rtems_id control_task;
342} lpc_eth_driver_entry;
343
344static lpc_eth_driver_entry lpc_eth_driver_data;
345
346static void lpc_eth_control_request_complete(const lpc_eth_driver_entry *e)
347{
348  rtems_status_code sc = rtems_event_transient_send(e->control_task);
349  assert(sc == RTEMS_SUCCESSFUL);
350}
351
352static void lpc_eth_control_request(
353  lpc_eth_driver_entry *e,
354  rtems_id task,
355  rtems_event_set event
356)
357{
358  rtems_status_code sc = RTEMS_SUCCESSFUL;
359  uint32_t nest_count = 0;
360
361  e->control_task = rtems_task_self();
362
363  sc = rtems_bsdnet_event_send(task, event);
364  assert(sc == RTEMS_SUCCESSFUL);
365
366  nest_count = rtems_bsdnet_semaphore_release_recursive();
367  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
368  assert(sc == RTEMS_SUCCESSFUL);
369  rtems_bsdnet_semaphore_obtain_recursive(nest_count);
370
371  e->control_task = 0;
372}
373
374static inline uint32_t lpc_eth_increment(
375  uint32_t value,
376  uint32_t cycle
377)
378{
379  if (value < cycle) {
380    return ++value;
381  } else {
382    return 0;
383  }
384}
385
386static void lpc_eth_enable_promiscous_mode(bool enable)
387{
388  if (enable) {
389    lpc_eth->rxfilterctrl = ETH_RX_FIL_CTRL_ACCEPT_UNICAST
390      | ETH_RX_FIL_CTRL_ACCEPT_MULTICAST
391      | ETH_RX_FIL_CTRL_ACCEPT_BROADCAST;
392  } else {
393    lpc_eth->rxfilterctrl = ETH_RX_FIL_CTRL_ACCEPT_PERFECT
394      | ETH_RX_FIL_CTRL_ACCEPT_MULTICAST_HASH
395      | ETH_RX_FIL_CTRL_ACCEPT_BROADCAST;
396  }
397}
398
399static void lpc_eth_interrupt_handler(void *arg)
400{
401  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
402  rtems_event_set re = 0;
403  rtems_event_set te = 0;
404  uint32_t ie = 0;
405
406  /* Get interrupt status */
407  uint32_t im = lpc_eth->intenable;
408  uint32_t is = lpc_eth->intstatus & im;
409
410  /* Check receive interrupts */
411  if ((is & ETH_INT_RX_OVERRUN) != 0) {
412    re = LPC_ETH_EVENT_INITIALIZE;
413    ++e->receive_fatal_errors;
414  } else if ((is & LPC_ETH_INTERRUPT_RECEIVE) != 0) {
415    re = LPC_ETH_EVENT_INTERRUPT;
416    ie |= LPC_ETH_INTERRUPT_RECEIVE;
417  }
418
419  /* Send events to receive task */
420  if (re != 0) {
421    ++e->receive_interrupts;
422    (void) rtems_bsdnet_event_send(e->receive_task, re);
423  }
424
425  /* Check transmit interrupts */
426  if ((is & ETH_INT_TX_UNDERRUN) != 0) {
427    te = LPC_ETH_EVENT_INITIALIZE;
428    ++e->transmit_fatal_errors;
429  } else if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
430    te = LPC_ETH_EVENT_INTERRUPT;
431    ie |= LPC_ETH_INTERRUPT_TRANSMIT;
432  }
433
434  /* Send events to transmit task */
435  if (te != 0) {
436    ++e->transmit_interrupts;
437    (void) rtems_bsdnet_event_send(e->transmit_task, te);
438  }
439
440  LPC_ETH_PRINTK("interrupt: rx = 0x%08x, tx = 0x%08x\n", re, te);
441
442  /* Update interrupt mask */
443  lpc_eth->intenable = im & ~ie;
444
445  /* Clear interrupts */
446  lpc_eth->intclear = is;
447}
448
449static void lpc_eth_enable_receive_interrupts(void)
450{
451  rtems_interrupt_level level;
452
453  rtems_interrupt_disable(level);
454  lpc_eth->intenable |= LPC_ETH_INTERRUPT_RECEIVE;
455  rtems_interrupt_enable(level);
456}
457
458static void lpc_eth_disable_receive_interrupts(void)
459{
460  rtems_interrupt_level level;
461
462  rtems_interrupt_disable(level);
463  lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_RECEIVE;
464  rtems_interrupt_enable(level);
465}
466
467static void lpc_eth_enable_transmit_interrupts(void)
468{
469  rtems_interrupt_level level;
470
471  rtems_interrupt_disable(level);
472  lpc_eth->intenable |= LPC_ETH_INTERRUPT_TRANSMIT;
473  rtems_interrupt_enable(level);
474}
475
476static void lpc_eth_disable_transmit_interrupts(void)
477{
478  rtems_interrupt_level level;
479
480  rtems_interrupt_disable(level);
481  lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_TRANSMIT;
482  rtems_interrupt_enable(level);
483}
484
485#define LPC_ETH_RX_DATA_OFFSET 2
486
487static struct mbuf *lpc_eth_new_mbuf(struct ifnet *ifp, bool wait)
488{
489  struct mbuf *m = NULL;
490  int mw = wait ? M_WAIT : M_DONTWAIT;
491
492  MGETHDR(m, mw, MT_DATA);
493  if (m != NULL) {
494    MCLGET(m, mw);
495    if ((m->m_flags & M_EXT) != 0) {
496      /* Set receive interface */
497      m->m_pkthdr.rcvif = ifp;
498
499      /* Adjust by two bytes for proper IP header alignment */
500      m->m_data = mtod(m, char *) + LPC_ETH_RX_DATA_OFFSET;
501
502      return m;
503    } else {
504      m_free(m);
505    }
506  }
507
508  return NULL;
509}
510
511static bool lpc_eth_add_new_mbuf(
512  struct ifnet *ifp,
513  volatile lpc_eth_transfer_descriptor *desc,
514  struct mbuf **mbufs,
515  uint32_t i,
516  bool wait
517)
518{
519  /* New mbuf */
520  struct mbuf *m = lpc_eth_new_mbuf(ifp, wait);
521
522  /* Check mbuf */
523  if (m != NULL) {
524    /* Cache invalidate */
525    rtems_cache_invalidate_multiple_data_lines(
526      mtod(m, void *),
527      MCLBYTES - LPC_ETH_RX_DATA_OFFSET
528    );
529
530    /* Add mbuf to queue */
531    desc [i].start = mtod(m, uint32_t);
532    desc [i].control = (MCLBYTES - LPC_ETH_RX_DATA_OFFSET - 1)
533      | ETH_RX_CTRL_INTERRUPT;
534
535    /* Cache flush of descriptor  */
536    rtems_cache_flush_multiple_data_lines(
537      (void *) &desc [i],
538      sizeof(desc [0])
539    );
540
541    /* Add mbuf to table */
542    mbufs [i] = m;
543
544    return true;
545  } else {
546    return false;
547  }
548}
549
550static void lpc_eth_receive_task(void *arg)
551{
552  rtems_status_code sc = RTEMS_SUCCESSFUL;
553  rtems_event_set events = 0;
554  lpc_eth_driver_entry *const e = (lpc_eth_driver_entry *) arg;
555  struct ifnet *const ifp = &e->arpcom.ac_if;
556  volatile lpc_eth_transfer_descriptor *const desc = e->rx_desc_table;
557  volatile lpc_eth_receive_status *const status = e->rx_status_table;
558  struct mbuf **const mbufs = e->rx_mbuf_table;
559  uint32_t const index_max = e->rx_unit_count - 1;
560  uint32_t produce_index = 0;
561  uint32_t consume_index = 0;
562
563  LPC_ETH_PRINTF("%s\n", __func__);
564
565  /* Main event loop */
566  while (true) {
567    /* Wait for events */
568    sc = rtems_bsdnet_event_receive(
569      LPC_ETH_EVENT_INITIALIZE
570        | LPC_ETH_EVENT_STOP
571        | LPC_ETH_EVENT_INTERRUPT,
572      RTEMS_EVENT_ANY | RTEMS_WAIT,
573      RTEMS_NO_TIMEOUT,
574      &events
575    );
576    assert(sc == RTEMS_SUCCESSFUL);
577
578    LPC_ETH_PRINTF("rx: wake up: 0x%08" PRIx32 "\n", events);
579
580    /* Stop receiver? */
581    if ((events & LPC_ETH_EVENT_STOP) != 0) {
582      lpc_eth_control_request_complete(e);
583
584      /* Wait for events */
585      continue;
586    }
587
588    /* Initialize receiver? */
589    if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
590      /* Disable receive interrupts */
591      lpc_eth_disable_receive_interrupts();
592
593      /* Disable receiver */
594      lpc_eth->command &= ~ETH_CMD_RX_ENABLE;
595
596      /* Wait for inactive status */
597      while ((lpc_eth->status & ETH_STAT_RX_ACTIVE) != 0) {
598        /* Wait */
599      }
600
601      /* Reset */
602      lpc_eth->command |= ETH_CMD_RX_RESET;
603
604      /* Clear receive interrupts */
605      lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE;
606
607      /* Move existing mbufs to the front */
608      consume_index = 0;
609      for (produce_index = 0; produce_index <= index_max; ++produce_index) {
610        if (mbufs [produce_index] != NULL) {
611          mbufs [consume_index] = mbufs [produce_index];
612          ++consume_index;
613        }
614      }
615
616      /* Fill receive queue */
617      for (
618        produce_index = consume_index;
619        produce_index <= index_max;
620        ++produce_index
621      ) {
622        lpc_eth_add_new_mbuf(ifp, desc, mbufs, produce_index, true);
623      }
624
625      /* Receive descriptor table */
626      lpc_eth->rxdescriptornum = index_max;
627      lpc_eth->rxdescriptor = (uint32_t) desc;
628      lpc_eth->rxstatus = (uint32_t) status;
629
630      /* Initialize indices */
631      produce_index = lpc_eth->rxproduceindex;
632      consume_index = lpc_eth->rxconsumeindex;
633
634      /* Enable receiver */
635      lpc_eth->command |= ETH_CMD_RX_ENABLE;
636
637      /* Enable receive interrupts */
638      lpc_eth_enable_receive_interrupts();
639
640      lpc_eth_control_request_complete(e);
641
642      /* Wait for events */
643      continue;
644    }
645
646    while (true) {
647      /* Clear receive interrupt status */
648      lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE;
649
650      /* Get current produce index */
651      produce_index = lpc_eth->rxproduceindex;
652
653      if (consume_index != produce_index) {
654        uint32_t stat = 0;
655
656        /* Fragment status */
657        rtems_cache_invalidate_multiple_data_lines(
658          (void *) &status [consume_index],
659          sizeof(status [0])
660        );
661        stat = status [consume_index].info;
662
663        if (
664          (stat & ETH_RX_STAT_LAST_FLAG) != 0
665            && (stat & LPC_ETH_RX_STAT_ERRORS) == 0
666        ) {
667          /* Received mbuf */
668          struct mbuf *m = mbufs [consume_index];
669
670          if (lpc_eth_add_new_mbuf(ifp, desc, mbufs, consume_index, false)) {
671            /* Ethernet header */
672            struct ether_header *eh = mtod(m, struct ether_header *);
673
674            /* Discard Ethernet header and CRC */
675            int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1
676              - ETHER_HDR_LEN - ETHER_CRC_LEN;
677
678            /* Update mbuf */
679            m->m_len = sz;
680            m->m_pkthdr.len = sz;
681            m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
682
683            LPC_ETH_PRINTF("rx: %02" PRIu32 ": %u\n", consume_index, sz);
684
685            /* Hand over */
686            ether_input(ifp, eh, m);
687
688            /* Increment received frames counter */
689            ++e->received_frames;
690          } else {
691            ++e->receive_drop_errors;
692          }
693        } else {
694          /* Update error counters */
695          if ((stat & ETH_RX_STAT_OVERRUN) != 0) {
696            ++e->receive_overrun_errors;
697          }
698          if ((stat & ETH_RX_STAT_LAST_FLAG) == 0) {
699            ++e->receive_fragment_errors;
700          }
701          if ((stat & ETH_RX_STAT_CRC_ERROR) != 0) {
702            ++e->receive_crc_errors;
703          }
704          if ((stat & ETH_RX_STAT_SYMBOL_ERROR) != 0) {
705            ++e->receive_symbol_errors;
706          }
707          if ((stat & ETH_RX_STAT_LENGTH_ERROR) != 0) {
708            ++e->receive_length_errors;
709          }
710          if ((stat & ETH_RX_STAT_ALIGNMENT_ERROR) != 0) {
711            ++e->receive_alignment_errors;
712          }
713          if ((stat & ETH_RX_STAT_NO_DESCRIPTOR) != 0) {
714            ++e->receive_no_descriptor_errors;
715          }
716        }
717
718        /* Increment and update consume index */
719        consume_index = lpc_eth_increment(consume_index, index_max);
720        lpc_eth->rxconsumeindex = consume_index;
721      } else {
722        /* Nothing to do, enable receive interrupts */
723        lpc_eth_enable_receive_interrupts();
724        break;
725      }
726    }
727  }
728}
729
730static struct mbuf *lpc_eth_next_fragment(
731  struct ifnet *ifp,
732  struct mbuf *m,
733  uint32_t *ctrl
734)
735{
736  struct mbuf *n = NULL;
737  int size = 0;
738
739  while (true) {
740    if (m == NULL) {
741      /* Dequeue first fragment of the next frame */
742      IF_DEQUEUE(&ifp->if_snd, m);
743
744      /* Empty queue? */
745      if (m == NULL) {
746        return m;
747      }
748    }
749
750    /* Get fragment size */
751    size = m->m_len;
752
753    if (size > 0) {
754      /* Now we have a not empty fragment */
755      break;
756    } else {
757      /* Discard empty fragments */
758      m = m_free(m);
759    }
760  }
761
762  /* Set fragment size */
763  *ctrl = (uint32_t) (size - 1);
764
765  /* Discard empty successive fragments */
766  n = m->m_next;
767  while (n != NULL && n->m_len <= 0) {
768    n = m_free(n);
769  }
770  m->m_next = n;
771
772  /* Is our fragment the last in the frame? */
773  if (n == NULL) {
774    *ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS;
775  }
776
777  return m;
778}
779
780static void lpc_eth_transmit_task(void *arg)
781{
782  rtems_status_code sc = RTEMS_SUCCESSFUL;
783  rtems_event_set events = 0;
784  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
785  struct ifnet *ifp = &e->arpcom.ac_if;
786  volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
787  volatile uint32_t *const status = e->tx_status_table;
788  #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
789    struct mbuf **const mbufs = e->tx_buf_table;
790  #else
791    char *const buf = e->tx_buf_table;
792  #endif
793  struct mbuf *m = NULL;
794  uint32_t const index_max = e->tx_unit_count - 1;
795  uint32_t produce_index = 0;
796  uint32_t consume_index = 0;
797  uint32_t ctrl = 0;
798  #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
799    uint32_t frame_length = 0;
800    char *frame_buffer = NULL;
801  #endif
802
803  LPC_ETH_PRINTF("%s\n", __func__);
804
805  #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
806    /* Initialize descriptor table */
807    for (produce_index = 0; produce_index <= index_max; ++produce_index) {
808      desc [produce_index].start =
809        (uint32_t) (buf + produce_index * LPC_ETH_CONFIG_TX_BUF_SIZE);
810    }
811  #endif
812
813  /* Main event loop */
814  while (true) {
815    /* Wait for events */
816    sc = rtems_bsdnet_event_receive(
817      LPC_ETH_EVENT_INITIALIZE
818        | LPC_ETH_EVENT_STOP
819        | LPC_ETH_EVENT_TXSTART
820        | LPC_ETH_EVENT_INTERRUPT,
821      RTEMS_EVENT_ANY | RTEMS_WAIT,
822      RTEMS_NO_TIMEOUT,
823      &events
824    );
825    assert(sc == RTEMS_SUCCESSFUL);
826
827    LPC_ETH_PRINTF("tx: wake up: 0x%08" PRIx32 "\n", events);
828
829    /* Stop transmitter? */
830    if ((events & LPC_ETH_EVENT_STOP) != 0) {
831      lpc_eth_control_request_complete(e);
832
833      /* Wait for events */
834      continue;
835    }
836
837    /* Initialize transmitter? */
838    if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
839      /* Disable transmit interrupts */
840      lpc_eth_disable_transmit_interrupts();
841
842      /* Disable transmitter */
843      lpc_eth->command &= ~ETH_CMD_TX_ENABLE;
844
845      /* Wait for inactive status */
846      while ((lpc_eth->status & ETH_STAT_TX_ACTIVE) != 0) {
847        /* Wait */
848      }
849
850      /* Reset */
851      lpc_eth->command |= ETH_CMD_TX_RESET;
852
853      /* Clear transmit interrupts */
854      lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
855
856      /* Transmit descriptors */
857      lpc_eth->txdescriptornum = index_max;
858      lpc_eth->txdescriptor = (uint32_t) desc;
859      lpc_eth->txstatus = (uint32_t) status;
860
861      #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
862        /* Discard outstanding fragments (= data loss) */
863        for (produce_index = 0; produce_index <= index_max; ++produce_index) {
864          struct mbuf *victim = mbufs [produce_index];
865
866          if (victim != NULL) {
867            m_free(victim);
868            mbufs [produce_index] = NULL;
869          }
870        }
871      #endif
872
873      /* Initialize indices */
874      produce_index = lpc_eth->txproduceindex;
875      consume_index = lpc_eth->txconsumeindex;
876
877      #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
878        /* Fresh frame length and buffer start */
879        frame_length = 0;
880        frame_buffer = (char *) desc [produce_index].start;
881      #endif
882
883      /* Enable transmitter */
884      lpc_eth->command |= ETH_CMD_TX_ENABLE;
885
886      lpc_eth_control_request_complete(e);
887    }
888
889    /* Free consumed fragments */
890    while (true) {
891      /* Save last known consume index */
892      uint32_t c = consume_index;
893
894      /* Clear transmit interrupt status */
895      lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
896
897      /* Get new consume index */
898      consume_index = lpc_eth->txconsumeindex;
899
900      /* Nothing consumed in the meantime? */
901      if (c == consume_index) {
902        break;
903      }
904
905      while (c != consume_index) {
906        uint32_t s = status [c];
907
908        /* Update error counters */
909        if ((s & (ETH_TX_STAT_ERROR | ETH_TX_STAT_NO_DESCRIPTOR)) != 0) {
910          if ((s & ETH_TX_STAT_UNDERRUN) != 0) {
911            ++e->transmit_underrun_errors;
912          }
913          if ((s & ETH_TX_STAT_LATE_COLLISION) != 0) {
914            ++e->transmit_late_collision_errors;
915          }
916          if ((s & ETH_TX_STAT_EXCESSIVE_COLLISION) != 0) {
917            ++e->transmit_excessive_collision_errors;
918          }
919          if ((s & ETH_TX_STAT_EXCESSIVE_DEFER) != 0) {
920            ++e->transmit_excessive_defer_errors;
921          }
922          if ((s & ETH_TX_STAT_NO_DESCRIPTOR) != 0) {
923            ++e->transmit_no_descriptor_errors;
924          }
925        }
926
927        #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
928          /* Release mbuf */
929          m_free(mbufs [c]);
930          mbufs [c] = NULL;
931        #endif
932
933        /* Next consume index */
934        c = lpc_eth_increment(c, index_max);
935      }
936    }
937
938    /* Transmit new fragments */
939    while (true) {
940      /* Compute next produce index */
941      uint32_t p = lpc_eth_increment(produce_index, index_max);
942
943      /* Get next fragment and control value */
944      m = lpc_eth_next_fragment(ifp, m, &ctrl);
945
946      /* Queue full? */
947      if (p == consume_index) {
948        LPC_ETH_PRINTF("tx: full queue: 0x%08x\n", m);
949
950        /* The queue is full, wait for transmit interrupt */
951        break;
952      }
953
954      /* New fragment? */
955      if (m != NULL) {
956        #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
957          /* Set the transfer data */
958          rtems_cache_flush_multiple_data_lines(
959            mtod(m, const void *),
960            (size_t) m->m_len
961          );
962          desc [produce_index].start = mtod(m, uint32_t);
963          desc [produce_index].control = ctrl;
964          rtems_cache_flush_multiple_data_lines(
965            (void *) &desc [produce_index],
966            sizeof(desc [0])
967           );
968          mbufs [produce_index] = m;
969
970          LPC_ETH_PRINTF(
971            "tx: %02" PRIu32 ": %u %s\n",
972            produce_index, m->m_len,
973            (ctrl & ETH_TX_CTRL_LAST) != 0 ? "L" : ""
974          );
975
976          /* Next produce index */
977          produce_index = p;
978
979          /* Last fragment of a frame? */
980          if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
981            /* Update the produce index */
982            lpc_eth->txproduceindex = produce_index;
983
984            /* Increment transmitted frames counter */
985            ++e->transmitted_frames;
986          }
987
988          /* Next fragment of the frame */
989          m = m->m_next;
990        #else
991          size_t fragment_length = (size_t) m->m_len;
992          void *fragment_start = mtod(m, void *);
993          uint32_t new_frame_length = frame_length + fragment_length;
994
995          /* Check buffer size */
996          if (new_frame_length > LPC_ETH_CONFIG_TX_BUF_SIZE) {
997            LPC_ETH_PRINTF("tx: overflow\n");
998
999            /* Discard overflow data */
1000            new_frame_length = LPC_ETH_CONFIG_TX_BUF_SIZE;
1001            fragment_length = new_frame_length - frame_length;
1002
1003            /* Finalize frame */
1004            ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS;
1005
1006            /* Update error counter */
1007            ++e->transmit_overflow_errors;
1008          }
1009
1010          LPC_ETH_PRINTF(
1011            "tx: copy: %" PRIu32 "%s%s\n",
1012            fragment_length,
1013            (m->m_flags & M_EXT) != 0 ? ", E" : "",
1014            (m->m_flags & M_PKTHDR) != 0 ? ", H" : ""
1015          );
1016
1017          /* Copy fragment to buffer in Ethernet RAM */
1018          memcpy(frame_buffer, fragment_start, fragment_length);
1019
1020          if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
1021            /* Finalize descriptor */
1022            desc [produce_index].control = (ctrl & ~ETH_TX_CTRL_SIZE_MASK)
1023              | (new_frame_length - 1);
1024
1025            LPC_ETH_PRINTF(
1026              "tx: %02" PRIu32 ": %" PRIu32 "\n",
1027              produce_index,
1028              new_frame_length
1029            );
1030
1031            /* Cache flush of data */
1032            rtems_cache_flush_multiple_data_lines(
1033              (const void *) desc [produce_index].start,
1034              new_frame_length
1035            );
1036
1037            /* Cache flush of descriptor  */
1038            rtems_cache_flush_multiple_data_lines(
1039              (void *) &desc [produce_index],
1040              sizeof(desc [0])
1041            );
1042
1043            /* Next produce index */
1044            produce_index = p;
1045
1046            /* Update the produce index */
1047            lpc_eth->txproduceindex = produce_index;
1048
1049            /* Fresh frame length and buffer start */
1050            frame_length = 0;
1051            frame_buffer = (char *) desc [produce_index].start;
1052
1053            /* Increment transmitted frames counter */
1054            ++e->transmitted_frames;
1055          } else {
1056            /* New frame length */
1057            frame_length = new_frame_length;
1058
1059            /* Update current frame buffer start */
1060            frame_buffer += fragment_length;
1061          }
1062
1063          /* Free mbuf and get next */
1064          m = m_free(m);
1065        #endif
1066      } else {
1067        /* Nothing to transmit */
1068        break;
1069      }
1070    }
1071
1072    /* No more fragments? */
1073    if (m == NULL) {
1074      /* Interface is now inactive */
1075      ifp->if_flags &= ~IFF_OACTIVE;
1076    } else {
1077      LPC_ETH_PRINTF("tx: enable interrupts\n");
1078
1079      /* Enable transmit interrupts */
1080      lpc_eth_enable_transmit_interrupts();
1081    }
1082  }
1083}
1084
1085static int lpc_eth_mdio_wait_for_not_busy(void)
1086{
1087  rtems_interval one_second = rtems_clock_get_ticks_per_second();
1088  rtems_interval i = 0;
1089
1090  while ((lpc_eth->mind & ETH_MIND_BUSY) != 0 && i < one_second) {
1091    rtems_task_wake_after(1);
1092    ++i;
1093  }
1094
1095  LPC_ETH_PRINTK("tx: lpc_eth_mdio_wait %s after %d\n",
1096                 i != one_second? "succeed": "timeout", i);
1097
1098  return i != one_second ? 0 : ETIMEDOUT;
1099}
1100
1101static uint32_t lpc_eth_mdio_read_anlpar(int phy)
1102{
1103  uint32_t madr = ETH_MADR_REG(MII_ANLPAR) | ETH_MADR_PHY(phy);
1104  uint32_t anlpar = 0;
1105  int eno = 0;
1106
1107  if (lpc_eth->madr != madr) {
1108    lpc_eth->madr = madr;
1109  }
1110
1111  if (lpc_eth->mcmd != ETH_MCMD_READ) {
1112    lpc_eth->mcmd = 0;
1113    lpc_eth->mcmd = ETH_MCMD_READ;
1114  }
1115
1116  eno = lpc_eth_mdio_wait_for_not_busy();
1117  if (eno == 0) {
1118    anlpar = lpc_eth->mrdd;
1119  }
1120
1121  /* Start next read */
1122  lpc_eth->mcmd = 0;
1123  lpc_eth->mcmd = ETH_MCMD_READ;
1124
1125  return anlpar;
1126}
1127
1128static int lpc_eth_mdio_read(
1129  int phy,
1130  void *arg RTEMS_UNUSED,
1131  unsigned reg,
1132  uint32_t *val
1133)
1134{
1135  int eno = 0;
1136
1137  if (0 <= phy && phy <= 31) {
1138    lpc_eth->madr = ETH_MADR_REG(reg) | ETH_MADR_PHY(phy);
1139    lpc_eth->mcmd = 0;
1140    lpc_eth->mcmd = ETH_MCMD_READ;
1141    eno = lpc_eth_mdio_wait_for_not_busy();
1142
1143    if (eno == 0) {
1144      *val = lpc_eth->mrdd;
1145    }
1146  } else {
1147    eno = EINVAL;
1148  }
1149
1150  return eno;
1151}
1152
1153static int lpc_eth_mdio_write(
1154  int phy,
1155  void *arg RTEMS_UNUSED,
1156  unsigned reg,
1157  uint32_t val
1158)
1159{
1160  int eno = 0;
1161
1162  if (0 <= phy && phy <= 31) {
1163    lpc_eth->madr = ETH_MADR_REG(reg) | ETH_MADR_PHY(phy);
1164    lpc_eth->mwtd = val;
1165    eno = lpc_eth_mdio_wait_for_not_busy();
1166  } else {
1167    eno = EINVAL;
1168  }
1169
1170  return eno;
1171}
1172
1173static int lpc_eth_phy_get_id(int phy, uint32_t *id)
1174{
1175  uint32_t id1 = 0;
1176  int eno = lpc_eth_mdio_read(phy, NULL, MII_PHYIDR1, &id1);
1177
1178  if (eno == 0) {
1179    uint32_t id2 = 0;
1180
1181    eno = lpc_eth_mdio_read(phy, NULL, MII_PHYIDR2, &id2);
1182    if (eno == 0) {
1183      *id = (id1 << 16) | (id2 & 0xfff0);
1184    }
1185  }
1186
1187  return eno;
1188}
1189
1190#define PHY_KSZ80X1RNL 0x221550
1191#define PHY_DP83848    0x20005c90
1192
1193typedef struct {
1194  unsigned reg;
1195  uint32_t set;
1196  uint32_t clear;
1197} lpc_eth_phy_action;
1198
1199static int lpc_eth_phy_set_and_clear(
1200  lpc_eth_driver_entry *e,
1201  const lpc_eth_phy_action *actions,
1202  size_t n
1203)
1204{
1205  int eno = 0;
1206  size_t i;
1207
1208  for (i = 0; eno == 0 && i < n; ++i) {
1209    const lpc_eth_phy_action *action = &actions [i];
1210    uint32_t val;
1211
1212    eno = lpc_eth_mdio_read(e->phy, NULL, action->reg, &val);
1213    if (eno == 0) {
1214      val |= action->set;
1215      val &= ~action->clear;
1216      eno = lpc_eth_mdio_write(e->phy, NULL, action->reg, val);
1217    }
1218  }
1219
1220  return eno;
1221}
1222
1223static const lpc_eth_phy_action lpc_eth_phy_up_action_default [] = {
1224  { MII_BMCR, 0, BMCR_PDOWN },
1225  { MII_BMCR, BMCR_RESET, 0 },
1226  { MII_BMCR, BMCR_AUTOEN, 0 }
1227};
1228
1229static const lpc_eth_phy_action lpc_eth_phy_up_pre_action_KSZ80X1RNL [] = {
1230  /* Disable slow oscillator mode */
1231  { 0x11, 0, 0x10 }
1232};
1233
1234static const lpc_eth_phy_action lpc_eth_phy_up_post_action_KSZ80X1RNL [] = {
1235  /* Enable energy detect power down (EDPD) mode */
1236  { 0x18, 0x0800, 0 },
1237  /* Turn PLL of automatically in EDPD mode */
1238  { 0x10, 0x10, 0 }
1239};
1240
1241static int lpc_eth_phy_up(lpc_eth_driver_entry *e)
1242{
1243  int eno;
1244  int retries = 64;
1245  uint32_t val;
1246
1247  e->phy = DEFAULT_PHY - 1;
1248  while (true) {
1249    e->phy = (e->phy + 1) % 32;
1250
1251    --retries;
1252    eno = lpc_eth_phy_get_id(e->phy, &e->phy_id);
1253    if (
1254      (eno == 0 && e->phy_id != 0xfffffff0 && e->phy_id != 0)
1255        || retries <= 0
1256    ) {
1257      break;
1258    }
1259
1260    rtems_task_wake_after(1);
1261  }
1262
1263  LPC_ETH_PRINTF("lpc_eth_phy_get_id: 0x%08" PRIx32 " from phy %d retries %d\n",
1264                 e->phy_id, e->phy, retries);
1265
1266  if (eno == 0) {
1267    switch (e->phy_id) {
1268      case PHY_KSZ80X1RNL:
1269        eno = lpc_eth_phy_set_and_clear(
1270          e,
1271          &lpc_eth_phy_up_pre_action_KSZ80X1RNL [0],
1272          RTEMS_ARRAY_SIZE(lpc_eth_phy_up_pre_action_KSZ80X1RNL)
1273        );
1274        break;
1275      case PHY_DP83848:
1276        eno = lpc_eth_mdio_read(e->phy, NULL, 0x17, &val);
1277        LPC_ETH_PRINTF("phy PHY_DP83848 RBR 0x%08" PRIx32 "\n", val);
1278        /* val = 0x21; */
1279        val = 0x32 ;
1280        eno = lpc_eth_mdio_write(e->phy, NULL, 0x17, val);
1281        break;
1282      case 0:
1283      case 0xfffffff0:
1284        eno = EIO;
1285        e->phy = DEFAULT_PHY;
1286        break;
1287      default:
1288        break;
1289    }
1290
1291    if (eno == 0) {
1292      eno = lpc_eth_phy_set_and_clear(
1293        e,
1294        &lpc_eth_phy_up_action_default [0],
1295        RTEMS_ARRAY_SIZE(lpc_eth_phy_up_action_default)
1296      );
1297    }
1298
1299    if (eno == 0) {
1300      switch (e->phy_id) {
1301        case PHY_KSZ80X1RNL:
1302          eno = lpc_eth_phy_set_and_clear(
1303            e,
1304            &lpc_eth_phy_up_post_action_KSZ80X1RNL [0],
1305            RTEMS_ARRAY_SIZE(lpc_eth_phy_up_post_action_KSZ80X1RNL)
1306          );
1307          break;
1308        default:
1309          break;
1310      }
1311    }
1312  } else {
1313    e->phy_id = 0;
1314  }
1315
1316  return eno;
1317}
1318
1319static const lpc_eth_phy_action lpc_eth_phy_down_action_default [] = {
1320  { MII_BMCR, BMCR_PDOWN, 0 }
1321};
1322
1323static const lpc_eth_phy_action lpc_eth_phy_down_post_action_KSZ80X1RNL [] = {
1324  /* Enable slow oscillator mode */
1325  { 0x11, 0x10, 0 }
1326};
1327
1328static void lpc_eth_phy_down(lpc_eth_driver_entry *e)
1329{
1330  int eno = lpc_eth_phy_set_and_clear(
1331    e,
1332    &lpc_eth_phy_down_action_default [0],
1333    RTEMS_ARRAY_SIZE(lpc_eth_phy_down_action_default)
1334  );
1335
1336  if (eno == 0) {
1337    switch (e->phy_id) {
1338      case PHY_KSZ80X1RNL:
1339        eno = lpc_eth_phy_set_and_clear(
1340          e,
1341          &lpc_eth_phy_down_post_action_KSZ80X1RNL [0],
1342          RTEMS_ARRAY_SIZE(lpc_eth_phy_down_post_action_KSZ80X1RNL)
1343        );
1344        break;
1345      default:
1346        break;
1347    }
1348  }
1349}
1350
1351static void lpc_eth_soft_reset(void)
1352{
1353  lpc_eth->command = 0x38;
1354  lpc_eth->mac1 = 0xcf00;
1355  lpc_eth->mac1 = 0x0;
1356}
1357
1358static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
1359{
1360  int eno = 0;
1361  rtems_status_code sc = RTEMS_SUCCESSFUL;
1362  struct ifnet *ifp = &e->arpcom.ac_if;
1363
1364  if (up && e->state == LPC_ETH_STATE_DOWN) {
1365
1366    lpc_eth_config_module_enable();
1367
1368    /* Enable RX/TX reset and disable soft reset */
1369    lpc_eth->mac1 = 0xf00;
1370
1371    /* Initialize PHY */
1372    /* Clock value 10 (divide by 44 ) is safe on LPC178x up to 100 MHz AHB clock */
1373    lpc_eth->mcfg = ETH_MCFG_CLOCK_SELECT(10) | ETH_MCFG_RESETMIIMGMT;
1374    rtems_task_wake_after(1);
1375    lpc_eth->mcfg = ETH_MCFG_CLOCK_SELECT(10);
1376    rtems_task_wake_after(1);
1377    eno = lpc_eth_phy_up(e);
1378
1379    if (eno == 0) {
1380      /*
1381       * We must have a valid external clock from the PHY at this point,
1382       * otherwise the system bus hangs and only a watchdog reset helps.
1383       */
1384      lpc_eth_soft_reset();
1385
1386      /* Reinitialize registers */
1387      lpc_eth->mac2 = 0x31;
1388      lpc_eth->ipgt = 0x15;
1389      lpc_eth->ipgr = 0x12;
1390      lpc_eth->clrt = 0x370f;
1391      lpc_eth->maxf = 0x0600;
1392      lpc_eth->supp = ETH_SUPP_SPEED;
1393      lpc_eth->test = 0;
1394      #ifdef LPC_ETH_CONFIG_RMII
1395        lpc_eth->command = 0x0600;
1396      #else
1397        lpc_eth->command = 0x0400;
1398      #endif
1399      lpc_eth->intenable = ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN;
1400      lpc_eth->intclear = 0x30ff;
1401      lpc_eth->powerdown = 0;
1402
1403      /* MAC address */
1404      lpc_eth->sa0 = ((uint32_t) e->arpcom.ac_enaddr [5] << 8)
1405        | (uint32_t) e->arpcom.ac_enaddr [4];
1406      lpc_eth->sa1 = ((uint32_t) e->arpcom.ac_enaddr [3] << 8)
1407        | (uint32_t) e->arpcom.ac_enaddr [2];
1408      lpc_eth->sa2 = ((uint32_t) e->arpcom.ac_enaddr [1] << 8)
1409        | (uint32_t) e->arpcom.ac_enaddr [0];
1410
1411      /* Enable receiver */
1412      lpc_eth->mac1 = 0x03;
1413
1414      /* Initialize tasks */
1415      lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INITIALIZE);
1416      lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_INITIALIZE);
1417
1418      /* Install interrupt handler */
1419      sc = rtems_interrupt_handler_install(
1420        e->interrupt_number,
1421        "Ethernet",
1422        RTEMS_INTERRUPT_UNIQUE,
1423        lpc_eth_interrupt_handler,
1424        e
1425      );
1426      assert(sc == RTEMS_SUCCESSFUL);
1427
1428      /* Start watchdog timer */
1429      ifp->if_timer = 1;
1430
1431      /* Change state */
1432      e->state = LPC_ETH_STATE_UP;
1433    }
1434
1435    if (eno != 0) {
1436      ifp->if_flags &= ~IFF_UP;
1437    }
1438  } else if (!up && e->state == LPC_ETH_STATE_UP) {
1439    /* Remove interrupt handler */
1440    sc = rtems_interrupt_handler_remove(
1441      e->interrupt_number,
1442      lpc_eth_interrupt_handler,
1443      e
1444    );
1445    assert(sc == RTEMS_SUCCESSFUL);
1446
1447    /* Stop tasks */
1448    lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_STOP);
1449    lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_STOP);
1450
1451    lpc_eth_soft_reset();
1452    lpc_eth_phy_down(e);
1453    lpc_eth_config_module_disable();
1454
1455    /* Stop watchdog timer */
1456    ifp->if_timer = 0;
1457
1458    /* Change state */
1459    e->state = LPC_ETH_STATE_DOWN;
1460  }
1461
1462  return eno;
1463}
1464
1465static void lpc_eth_interface_init(void *arg)
1466{
1467  /* Nothing to do */
1468}
1469
1470static void lpc_eth_interface_stats(lpc_eth_driver_entry *e)
1471{
1472  int eno = EIO;
1473  int media = 0;
1474
1475  if (e->state == LPC_ETH_STATE_UP) {
1476    media = IFM_MAKEWORD(0, 0, 0, 0);
1477    eno = rtems_mii_ioctl(&e->mdio, e, SIOCGIFMEDIA, &media);
1478  }
1479
1480  rtems_bsdnet_semaphore_release();
1481
1482  if (eno == 0) {
1483    rtems_ifmedia2str(media, NULL, 0);
1484    printf("\n");
1485  }
1486
1487  printf("received frames:                     %u\n", e->received_frames);
1488  printf("receive interrupts:                  %u\n", e->receive_interrupts);
1489  printf("transmitted frames:                  %u\n", e->transmitted_frames);
1490  printf("transmit interrupts:                 %u\n", e->transmit_interrupts);
1491  printf("receive drop errors:                 %u\n", e->receive_drop_errors);
1492  printf("receive overrun errors:              %u\n", e->receive_overrun_errors);
1493  printf("receive fragment errors:             %u\n", e->receive_fragment_errors);
1494  printf("receive CRC errors:                  %u\n", e->receive_crc_errors);
1495  printf("receive symbol errors:               %u\n", e->receive_symbol_errors);
1496  printf("receive length errors:               %u\n", e->receive_length_errors);
1497  printf("receive alignment errors:            %u\n", e->receive_alignment_errors);
1498  printf("receive no descriptor errors:        %u\n", e->receive_no_descriptor_errors);
1499  printf("receive fatal errors:                %u\n", e->receive_fatal_errors);
1500  printf("transmit underrun errors:            %u\n", e->transmit_underrun_errors);
1501  printf("transmit late collision errors:      %u\n", e->transmit_late_collision_errors);
1502  printf("transmit excessive collision errors: %u\n", e->transmit_excessive_collision_errors);
1503  printf("transmit excessive defer errors:     %u\n", e->transmit_excessive_defer_errors);
1504  printf("transmit no descriptor errors:       %u\n", e->transmit_no_descriptor_errors);
1505  printf("transmit overflow errors:            %u\n", e->transmit_overflow_errors);
1506  printf("transmit fatal errors:               %u\n", e->transmit_fatal_errors);
1507
1508  rtems_bsdnet_semaphore_obtain();
1509}
1510
1511static int lpc_eth_multicast_control(
1512  bool add,
1513  struct ifreq *ifr,
1514  struct arpcom *ac
1515)
1516{
1517  int eno = 0;
1518
1519  if (add) {
1520    eno = ether_addmulti(ifr, ac);
1521  } else {
1522    eno = ether_delmulti(ifr, ac);
1523  }
1524
1525  if (eno == ENETRESET) {
1526    struct ether_multistep step;
1527    struct ether_multi *enm;
1528
1529    eno = 0;
1530
1531    lpc_eth->hashfilterl = 0;
1532    lpc_eth->hashfilterh = 0;
1533
1534    ETHER_FIRST_MULTI(step, ac, enm);
1535    while (enm != NULL) {
1536      uint64_t addrlo = 0;
1537      uint64_t addrhi = 0;
1538
1539      memcpy(&addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
1540      memcpy(&addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
1541      while (addrlo <= addrhi) {
1542        /* XXX: ether_crc32_le() does not work, why? */
1543        uint32_t crc = ether_crc32_be((uint8_t *) &addrlo, ETHER_ADDR_LEN);
1544        uint32_t index = (crc >> 23) & 0x3f;
1545
1546        if (index < 32) {
1547          lpc_eth->hashfilterl |= 1U << index;
1548        } else {
1549          lpc_eth->hashfilterh |= 1U << (index - 32);
1550        }
1551        ++addrlo;
1552      }
1553      ETHER_NEXT_MULTI(step, enm);
1554    }
1555  }
1556
1557  return eno;
1558}
1559
1560static int lpc_eth_interface_ioctl(
1561  struct ifnet *ifp,
1562  ioctl_command_t cmd,
1563  caddr_t data
1564)
1565{
1566  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
1567  struct ifreq *ifr = (struct ifreq *) data;
1568  int eno = 0;
1569
1570  LPC_ETH_PRINTF("%s\n", __func__);
1571
1572  switch (cmd)  {
1573    case SIOCGIFMEDIA:
1574    case SIOCSIFMEDIA:
1575      rtems_mii_ioctl(&e->mdio, e, cmd, &ifr->ifr_media);
1576      break;
1577    case SIOCGIFADDR:
1578    case SIOCSIFADDR:
1579      ether_ioctl(ifp, cmd, data);
1580      break;
1581    case SIOCSIFFLAGS:
1582      eno = lpc_eth_up_or_down(e, (ifp->if_flags & IFF_UP) != 0);
1583      if (eno == 0 && (ifp->if_flags & IFF_UP) != 0) {
1584        lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0);
1585      }
1586      break;
1587    case SIOCADDMULTI:
1588    case SIOCDELMULTI:
1589      eno = lpc_eth_multicast_control(cmd == SIOCADDMULTI, ifr, &e->arpcom);
1590      break;
1591    case SIO_RTEMS_SHOW_STATS:
1592      lpc_eth_interface_stats(e);
1593      break;
1594    default:
1595      eno = EINVAL;
1596      break;
1597  }
1598
1599  return eno;
1600}
1601
1602static void lpc_eth_interface_start(struct ifnet *ifp)
1603{
1604  rtems_status_code sc = RTEMS_SUCCESSFUL;
1605  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
1606
1607  ifp->if_flags |= IFF_OACTIVE;
1608
1609  if (e->state == LPC_ETH_STATE_UP) {
1610    sc = rtems_bsdnet_event_send(e->transmit_task, LPC_ETH_EVENT_TXSTART);
1611    assert(sc == RTEMS_SUCCESSFUL);
1612  }
1613}
1614
1615static void lpc_eth_interface_watchdog(struct ifnet *ifp)
1616{
1617  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
1618
1619  if (e->state == LPC_ETH_STATE_UP) {
1620    uint32_t anlpar = lpc_eth_mdio_read_anlpar(e->phy);
1621
1622    if (e->anlpar != anlpar) {
1623      bool full_duplex = false;
1624      bool speed = false;
1625
1626      e->anlpar = anlpar;
1627
1628      if ((anlpar & ANLPAR_TX_FD) != 0) {
1629        full_duplex = true;
1630        speed = true;
1631      } else if ((anlpar & ANLPAR_T4) != 0) {
1632        speed = true;
1633      } else if ((anlpar & ANLPAR_TX) != 0) {
1634        speed = true;
1635      } else if ((anlpar & ANLPAR_10_FD) != 0) {
1636        full_duplex = true;
1637      }
1638
1639      if (full_duplex) {
1640        lpc_eth->mac2 |= ETH_MAC2_FULL_DUPLEX;
1641      } else {
1642        lpc_eth->mac2 &= ~ETH_MAC2_FULL_DUPLEX;
1643      }
1644
1645      if (speed) {
1646        lpc_eth->supp |= ETH_SUPP_SPEED;
1647      } else {
1648        lpc_eth->supp &= ~ETH_SUPP_SPEED;
1649      }
1650    }
1651
1652    ifp->if_timer = WATCHDOG_TIMEOUT;
1653  }
1654}
1655
1656static unsigned lpc_eth_fixup_unit_count(int count, int default_value, int max)
1657{
1658  if (count <= 0) {
1659    count = default_value;
1660  } else if (count > max) {
1661    count = max;
1662  }
1663
1664  return LPC_ETH_CONFIG_UNIT_MULTIPLE
1665    + (((unsigned) count - 1U) & ~(LPC_ETH_CONFIG_UNIT_MULTIPLE - 1U));
1666}
1667
1668static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config)
1669{
1670  lpc_eth_driver_entry *e = &lpc_eth_driver_data;
1671  struct ifnet *ifp = &e->arpcom.ac_if;
1672  char *unit_name = NULL;
1673  int unit_index = rtems_bsdnet_parse_driver_name(config, &unit_name);
1674  size_t table_area_size = 0;
1675  char *table_area = NULL;
1676  char *table_location = NULL;
1677
1678  /* Check parameter */
1679  if (unit_index < 0) {
1680    return 0;
1681  }
1682  if (unit_index != 0) {
1683    goto cleanup;
1684  }
1685  if (config->hardware_address == NULL) {
1686    goto cleanup;
1687  }
1688  if (e->state != LPC_ETH_STATE_NOT_INITIALIZED) {
1689    goto cleanup;
1690  }
1691
1692  /* MDIO */
1693  e->mdio.mdio_r = lpc_eth_mdio_read;
1694  e->mdio.mdio_w = lpc_eth_mdio_write;
1695  e->mdio.has_gmii = 0;
1696  e->anlpar = 0;
1697
1698  /* Interrupt number */
1699  config->irno = LPC_ETH_CONFIG_INTERRUPT;
1700
1701  /* Device control */
1702  config->drv_ctrl = e;
1703
1704  /* Receive unit count */
1705  e->rx_unit_count = lpc_eth_fixup_unit_count(
1706    config->rbuf_count,
1707    LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT,
1708    LPC_ETH_CONFIG_RX_UNIT_COUNT_MAX
1709  );
1710  config->rbuf_count = (int) e->rx_unit_count;
1711
1712  /* Transmit unit count */
1713  e->tx_unit_count = lpc_eth_fixup_unit_count(
1714    config->xbuf_count,
1715    LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT,
1716    LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX
1717  );
1718  config->xbuf_count = (int) e->tx_unit_count;
1719
1720  /* Remember interrupt number */
1721  e->interrupt_number = config->irno;
1722
1723  /* Copy MAC address */
1724  memcpy(e->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
1725
1726  /* Allocate and clear table area */
1727  table_area_size =
1728    e->rx_unit_count
1729      * (sizeof(lpc_eth_transfer_descriptor)
1730        + sizeof(lpc_eth_receive_status)
1731        + sizeof(struct mbuf *))
1732    + e->tx_unit_count
1733      * (sizeof(lpc_eth_transfer_descriptor)
1734        + sizeof(uint32_t)
1735        + LPC_ETH_CONFIG_TX_BUF_SIZE);
1736  table_area = lpc_eth_config_alloc_table_area(table_area_size);
1737  if (table_area == NULL) {
1738    goto cleanup;
1739  }
1740  memset(table_area, 0, table_area_size);
1741
1742  table_location = table_area;
1743
1744  /*
1745   * The receive status table must be the first one since it has the strictest
1746   * alignment requirements.
1747   */
1748  e->rx_status_table = (volatile lpc_eth_receive_status *) table_location;
1749  table_location += e->rx_unit_count * sizeof(e->rx_status_table [0]);
1750
1751  e->rx_desc_table = (volatile lpc_eth_transfer_descriptor *) table_location;
1752  table_location += e->rx_unit_count * sizeof(e->rx_desc_table [0]);
1753
1754  e->rx_mbuf_table = (struct mbuf **) table_location;
1755  table_location += e->rx_unit_count * sizeof(e->rx_mbuf_table [0]);
1756
1757  e->tx_desc_table = (volatile lpc_eth_transfer_descriptor *) table_location;
1758  table_location += e->tx_unit_count * sizeof(e->tx_desc_table [0]);
1759
1760  e->tx_status_table = (volatile uint32_t *) table_location;
1761  table_location += e->tx_unit_count * sizeof(e->tx_status_table [0]);
1762
1763  e->tx_buf_table = table_location;
1764
1765  /* Set interface data */
1766  ifp->if_softc = e;
1767  ifp->if_unit = (short) unit_index;
1768  ifp->if_name = unit_name;
1769  ifp->if_mtu = (config->mtu > 0) ? (u_long) config->mtu : ETHERMTU;
1770  ifp->if_init = lpc_eth_interface_init;
1771  ifp->if_ioctl = lpc_eth_interface_ioctl;
1772  ifp->if_start = lpc_eth_interface_start;
1773  ifp->if_output = ether_output;
1774  ifp->if_watchdog = lpc_eth_interface_watchdog;
1775  ifp->if_flags = IFF_MULTICAST | IFF_BROADCAST | IFF_SIMPLEX;
1776  ifp->if_snd.ifq_maxlen = ifqmaxlen;
1777  ifp->if_timer = 0;
1778
1779  /* Create tasks */
1780  e->receive_task = rtems_bsdnet_newproc(
1781    "ntrx",
1782    4096,
1783    lpc_eth_receive_task,
1784    e
1785  );
1786  e->transmit_task = rtems_bsdnet_newproc(
1787    "nttx",
1788    4096,
1789    lpc_eth_transmit_task,
1790    e
1791  );
1792
1793  /* Change status */
1794  ifp->if_flags |= IFF_RUNNING;
1795  e->state = LPC_ETH_STATE_DOWN;
1796
1797  /* Attach the interface */
1798  if_attach(ifp);
1799  ether_ifattach(ifp);
1800
1801  return 1;
1802
1803cleanup:
1804
1805  lpc_eth_config_free_table_area(table_area);
1806
1807  /* FIXME: Type */
1808  free(unit_name, (int) 0xdeadbeef);
1809
1810  return 0;
1811}
1812
1813static int lpc_eth_detach(
1814  struct rtems_bsdnet_ifconfig *config RTEMS_UNUSED
1815)
1816{
1817  /* FIXME: Detach the interface from the upper layers? */
1818
1819  /* Module soft reset */
1820  lpc_eth->command = 0x38;
1821  lpc_eth->mac1 = 0xcf00;
1822
1823  /* FIXME: More cleanup */
1824
1825  return 0;
1826}
1827
1828int lpc_eth_attach_detach(
1829  struct rtems_bsdnet_ifconfig *config,
1830  int attaching
1831)
1832{
1833  /* FIXME: Return value */
1834
1835  if (attaching) {
1836    return lpc_eth_attach(config);
1837  } else {
1838    return lpc_eth_detach(config);
1839  }
1840}
Note: See TracBrowser for help on using the repository browser.