Changeset 5b03188 in rtems-libbsd


Ignore:
Timestamp:
06/09/22 08:10:06 (6 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
192e8d3
Parents:
d6b8db2
git-author:
Sebastian Huber <sebastian.huber@…> (06/09/22 08:10:06)
git-committer:
Sebastian Huber <sebastian.huber@…> (09/06/22 11:26:06)
Message:

if_lpe.c: Import legacy LPC Ethernet driver

The standard FreeBSD MII support causes severe problems on the LPC3200
chip family. If an Ethernet module register is accessed while there is
no clock from the PHY, the chip completely locks up and only an external
watchdog can recover from this state. The legacy driver had a custom
PHY management code which helped to avoid such issues. The if_lpe.c
driver is no longer maintained by FreeBSD.

Files:
1 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • libbsd.py

    rd6b8db2 r5b03188  
    222222                'rtems/rtems-legacy-newproc.c',
    223223                'rtems/rtems-legacy-mii.c',
    224                 'sys/arm/lpc/if_lpe.c',
    225224                'sys/arm/lpc/lpc_pwr.c',
    226225                'sys/dev/atsam/if_atsam.c',
  • rtemsbsd/sys/arm/lpc/if_lpe.c

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