source: rtems-libbsd/rtemsbsd/sys/arm/lpc/if_lpe.c @ 1056349

6-freebsd-12
Last change on this file since 1056349 was 1056349, checked in by Sebastian Huber <sebastian.huber@…>, on 06/22/22 at 12:41:38

if_lpe.c: Move transmit initialization

Move the transmit initialization out of the transmit task to be able to
remove the transmit task in the next patch.

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